=begin require 'spec_helper' describe TeacherPayment do let(:user) { FactoryGirl.create(:user) } let(:user2) { FactoryGirl.create(:user) } let(:teacher1_auth) { UserAuthorization.create(provider: 'stripe_connect', uid: stripe_account1_id, token: 'abc', refresh_token: 'abc', token_expiration: Date.today + 365, secret: 'secret') } let(:teacher2_auth) { UserAuthorization.create(provider: 'stripe_connect', uid: stripe_account2_id, token: 'abc', refresh_token: 'abc', token_expiration: Date.today + 365, secret: 'secret') } let(:teacher) { FactoryGirl.create(:user) } let(:teacher2) { FactoryGirl.create(:user) } let(:teacher_obj) { FactoryGirl.create(:teacher, user: teacher) } let(:teacher_obj2) { FactoryGirl.create(:teacher, user: teacher2) } let(:school_teacher) { FactoryGirl.create(:user) } let(:school_owner_teacher) { FactoryGirl.create(:teacher, user: school_teacher) } let(:test_drive_lesson) { testdrive_lesson(user, teacher) } let(:test_drive_lesson2) { testdrive_lesson(user2, teacher2) } let(:test_drive_distribution) { FactoryGirl.create(:teacher_distribution, lesson_session: test_drive_lesson, teacher: teacher, teacher_payment: nil, ready: false) } let(:test_drive_distribution2) { FactoryGirl.create(:teacher_distribution, lesson_session: test_drive_lesson2, teacher: teacher2, teacher_payment: nil, ready: false) } let(:normal_lesson_session) { normal_lesson(user, teacher) } let(:normal_distribution) { FactoryGirl.create(:teacher_distribution, lesson_session: normal_lesson_session, teacher: teacher, teacher_payment: nil, ready: false) } let(:school) { FactoryGirl.create(:school, user: school_teacher) } describe "pending_teacher_payments" do describe "normal teachers" do before(:each) do teacher_obj.touch teacher_obj2.touch teacher.teacher.stripe_account_id = stripe_account1_id teacher2.teacher.stripe_account_id = stripe_account2_id end it "empty" do TeacherPayment.pending_teacher_payments.count.should eql 0 end it "one distribution" do teacher.should eql teacher_obj.user test_drive_distribution.touch teacher.user_authorizations.count.should eql 1 user_auth = teacher.user_authorizations[0] user_auth.provider.should eql 'stripe_connect' payments = TeacherPayment.pending_teacher_payments payments.count.should eql 0 test_drive_distribution.ready = true test_drive_distribution.save! test_drive_distribution.distributed.should be_false payments = TeacherPayment.pending_teacher_payments payments.count.should eql 1 payments[0]['id'].should eql teacher.id end it "multiple teachers" do test_drive_distribution.touch test_drive_distribution2.touch payments = TeacherPayment.pending_teacher_payments payments.count.should eql 0 test_drive_distribution.ready = true test_drive_distribution.save! test_drive_distribution2.ready = true test_drive_distribution2.save! payments = TeacherPayment.pending_teacher_payments payments.count.should eql 2 payment_user_ids = payments.map(&:id) payment_user_ids.include? teacher.id payment_user_ids.include? teacher2.id end end describe "school teachers" do before(:each) do teacher_obj.touch teacher.teacher.stripe_account_id = stripe_account1_id end it "school distribution" do test_drive_distribution.school = school test_drive_distribution.save! payments = TeacherPayment.pending_teacher_payments payments.count.should eql 0 test_drive_distribution.ready = true test_drive_distribution.save! payments = TeacherPayment.pending_teacher_payments payments.count.should eql 1 payments[0]['id'].should eql teacher.id end end end describe "teacher_payments" do describe "normal teachers" do before(:each) do teacher_obj.touch teacher_obj2.touch teacher.teacher.stripe_account_id = stripe_account1_id teacher2.teacher.stripe_account_id = stripe_account2_id end it "empty" do TeacherPayment.teacher_payments end it "charges test drive" do test_drive_distribution.touch test_drive_distribution.ready = true test_drive_distribution.save! TeacherPayment.teacher_payments test_drive_distribution.reload test_drive_distribution.teacher_payment.should_not be_nil TeacherPayment.count.should eql 1 payment = test_drive_distribution.teacher_payment if payment.teacher_payment_charge.billing_error_reason puts payment.teacher_payment_charge.billing_error_reason puts payment.teacher_payment_charge.billing_error_detail end payment.teacher_payment_charge.billed.should eql true payment.teacher_payment_charge.amount_in_cents.should eql (1000 + 1000 * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.fee_in_cents.should eql 0 teacher_distribution = payment.teacher_payment_charge.distribution teacher_distribution.amount_in_cents.should eql 1000 charge = Stripe::Charge.retrieve(payment.teacher_payment_charge.stripe_charge_id) charge.amount.should eql (1000 + 1000 * APP_CONFIG.stripe[:ach_pct]).round charge.application_fee.should eql nil TeacherPayment.pending_teacher_payments.count.should eql 0 end it "charges normal" do normal_distribution.touch normal_distribution.ready = true normal_distribution.save! UserMailer.deliveries.clear TeacherPayment.teacher_payments normal_distribution.reload normal_distribution.teacher_payment.should_not be_nil TeacherPayment.count.should eql 1 payment = normal_distribution.teacher_payment if payment.teacher_payment_charge.billing_error_reason puts payment.teacher_payment_charge.billing_error_reason puts payment.teacher_payment_charge.billing_error_detail end # only one confirm email to teacher UserMailer.deliveries.length.should eql 1 payment.teacher_payment_charge.billed.should eql true payment.teacher_payment_charge.amount_in_cents.should eql ((1000 * 0.72) + (1000 * 0.72) * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.fee_in_cents.should eql 280 payment.teacher_payment_charge.teacher.should eql teacher teacher_distribution = payment.teacher_payment_charge.distribution teacher_distribution.amount_in_cents.should eql 1000 charge = Stripe::Charge.retrieve(payment.teacher_payment_charge.stripe_charge_id) charge.amount.should eql ((1000 * 0.72) + (1000 * 0.72) * APP_CONFIG.stripe[:ach_pct]).round charge.application_fee.should be_nil end it "charges multiple" do test_drive_distribution.touch test_drive_distribution.ready = true test_drive_distribution.save! normal_distribution.touch normal_distribution.ready = true normal_distribution.save! TeacherPayment.teacher_payments normal_distribution.reload normal_distribution.teacher_payment.should_not be_nil TeacherPayment.count.should eql 2 payment = normal_distribution.teacher_payment if payment.teacher_payment_charge.billing_error_reason puts payment.teacher_payment_charge.billing_error_reason puts payment.teacher_payment_charge.billing_error_detail end payment.teacher_payment_charge.billed.should eql true payment.teacher_payment_charge.amount_in_cents.should eql ((1000 * 0.72) + (1000 * 0.72) * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.fee_in_cents.should eql 280 teacher_distribution = payment.teacher_payment_charge.distribution teacher_distribution.amount_in_cents.should eql 1000 charge = Stripe::Charge.retrieve(payment.teacher_payment_charge.stripe_charge_id) charge.amount.should eql ((1000 * 0.72) + (1000 * 0.72) * APP_CONFIG.stripe[:ach_pct]).round charge.application_fee.should be_nil test_drive_distribution.reload payment = test_drive_distribution.teacher_payment if payment.teacher_payment_charge.billing_error_reason puts payment.teacher_payment_charge.billing_error_reason puts payment.teacher_payment_charge.billing_error_detail end payment.teacher_payment_charge.billed.should eql true payment.teacher_payment_charge.amount_in_cents.should eql (1000 + 1000 * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.fee_in_cents.should eql 0 teacher_distribution = payment.teacher_payment_charge.distribution teacher_distribution.amount_in_cents.should eql 1000 charge = Stripe::Charge.retrieve(payment.teacher_payment_charge.stripe_charge_id) charge.amount.should eql 1000 + (1000 * APP_CONFIG.stripe[:ach_pct]).round charge.application_fee.should be_nil end end describe "school teachers" do before(:each) do teacher_obj.touch teacher.teacher.stripe_account_id = stripe_account1_id school_owner_teacher.touch school_teacher.teacher.stripe_account_id = stripe_account2_id end it "charges school" do teacher.touch normal_distribution.school = school normal_distribution.ready = true normal_distribution.save! UserMailer.deliveries.clear TeacherPayment.teacher_payments normal_distribution.reload normal_distribution.teacher_payment.should_not be_nil normal_distribution.teacher_payment.school.should eql school TeacherPayment.count.should eql 1 payment = normal_distribution.teacher_payment if payment.teacher_payment_charge.billing_error_reason puts payment.teacher_payment_charge.billing_error_reason puts payment.teacher_payment_charge.billing_error_detail end # one to school owner, one to teacher UserMailer.deliveries.length.should eql 2 payment.teacher_payment_charge.billed.should eql true payment.teacher_payment_charge.amount_in_cents.should eql ((1000 * 0.67) + (1000 * 0.67) * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.fee_in_cents.should eql 330 payment.teacher_payment_charge.user.should eql school.owner teacher_distribution = payment.teacher_payment_charge.distribution teacher_distribution.amount_in_cents.should eql 1000 charge = Stripe::Charge.retrieve(payment.teacher_payment_charge.stripe_charge_id) charge.destination.should_not be_nil charge.amount.should eql 675 charge.application_fee.should be_nil end end describe "stripe mocked" do before { StripeMock.start } after { StripeMock.stop } describe "normal" do before { teacher_obj.touch teacher_obj2.touch teacher.teacher.stripe_account_id = stripe_account1_id teacher2.teacher.stripe_account_id = stripe_account2_id } it "failed payment, then success" do StripeMock.prepare_card_error(:card_declined) normal_distribution.touch normal_distribution.ready = true normal_distribution.save! TeacherPayment.teacher_payments normal_distribution.reload normal_distribution.teacher_payment.should_not be_nil TeacherPayment.count.should eql 1 payment = normal_distribution.teacher_payment payment.teacher_payment_charge.billing_error_reason.should eql("card_declined") payment.teacher_payment_charge.billing_error_detail.should include("declined") payment.teacher_payment_charge.billed.should eql false payment.teacher_payment_charge.amount_in_cents.should eql ((1000 * 0.72) + (1000 * 0.72) * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.fee_in_cents.should eql 280 teacher_distribution = payment.teacher_payment_charge.distribution teacher_distribution.amount_in_cents.should eql 1000 payment.teacher_payment_charge.stripe_charge_id.should be_nil StripeMock.clear_errors TeacherPayment.teacher_payments normal_distribution.reload normal_distribution.teacher_payment.should_not be_nil TeacherPayment.count.should eql 1 # make sure the teacher_payment is reused, and charge is reused normal_distribution.teacher_payment.should eql(payment) normal_distribution.teacher_payment.teacher_payment_charge.should eql(payment.teacher_payment_charge) # no attempt should be made because a day hasn't gone by payment = normal_distribution.teacher_payment payment.teacher_payment_charge.billed.should eql false payment.teacher_payment_charge.amount_in_cents.should eql ((1000 * 0.72) + (1000 * 0.72) * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.fee_in_cents.should eql 280 teacher_distribution = payment.teacher_payment_charge.distribution teacher_distribution.amount_in_cents.should eql 1000 # advance one day so that a charge is attempted again Timecop.freeze(Date.today + 2) TeacherPayment.teacher_payments normal_distribution.reload normal_distribution.teacher_payment.should_not be_nil TeacherPayment.count.should eql 1 # make sure the teacher_payment is reused, and charge is reused normal_distribution.teacher_payment.should eql(payment) normal_distribution.teacher_payment.teacher_payment_charge.should eql(payment.teacher_payment_charge) # no attempt should be made because a day hasn't gone by payment = normal_distribution.teacher_payment payment.reload payment.teacher_payment_charge.billed.should eql true payment.teacher_payment_charge.amount_in_cents.should eql ((1000 * 0.72) + (1000 * 0.72) * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.fee_in_cents.should eql 280 teacher_distribution = payment.teacher_payment_charge.distribution teacher_distribution.amount_in_cents.should eql 1000 charge = Stripe::Charge.retrieve(payment.teacher_payment_charge.stripe_charge_id) charge.amount.should eql 726 end it "charges multiple (with initial failure)" do StripeMock.prepare_card_error(:card_declined) test_drive_distribution.touch test_drive_distribution.ready = true test_drive_distribution.save! normal_distribution.touch normal_distribution.ready = true normal_distribution.save! TeacherPayment.teacher_payments TeacherPayment.count.should eql 1 payment = TeacherPayment.first payment.teacher_payment_charge.billed.should be_false # advance one day so that a charge is attempted again Timecop.freeze(Date.today + 2) StripeMock.clear_errors TeacherPayment.teacher_payments normal_distribution.reload normal_distribution.teacher_payment.should_not be_nil TeacherPayment.count.should eql 2 payment = normal_distribution.teacher_payment payment.teacher_payment_charge.billed.should eql true payment.teacher_payment_charge.amount_in_cents.should eql ((1000 * 0.72) + (1000 * 0.72) * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.fee_in_cents.should eql 280 teacher_distribution = payment.teacher_payment_charge.distribution teacher_distribution.amount_in_cents.should eql 1000 charge = Stripe::Charge.retrieve(payment.teacher_payment_charge.stripe_charge_id) charge.amount.should eql ((1000 * 0.72) + (1000 * 0.72) * APP_CONFIG.stripe[:ach_pct]).round test_drive_distribution.reload payment = test_drive_distribution.teacher_payment payment.teacher_payment_charge.billed.should eql true payment.teacher_payment_charge.amount_in_cents.should eql (1000 + 1000 * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.fee_in_cents.should eql 0 teacher_distribution = payment.teacher_payment_charge.distribution teacher_distribution.amount_in_cents.should eql 1000 charge = Stripe::Charge.retrieve(payment.teacher_payment_charge.stripe_charge_id) charge.amount.should eql 1000 + (1000 * APP_CONFIG.stripe[:ach_pct]).round end end describe "school" do before { teacher_obj.touch teacher.teacher.stripe_account_id = stripe_account1_id school_owner_teacher.touch school_teacher.teacher.stripe_account_id = stripe_account2_id } it "failed payment, then success (school)" do StripeMock.prepare_card_error(:card_declined) normal_distribution.school = school normal_distribution.ready = true normal_distribution.save! TeacherPayment.teacher_payments normal_distribution.reload normal_distribution.teacher_payment.should_not be_nil TeacherPayment.count.should eql 1 payment = normal_distribution.teacher_payment payment.teacher_payment_charge.billing_error_reason.should eql("card_declined") payment.teacher_payment_charge.billing_error_detail.should include("declined") payment.teacher_payment_charge.billed.should eql false payment.teacher_payment_charge.amount_in_cents.should eql ((1000 * 0.67) + (1000 * 0.67) * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.fee_in_cents.should eql 330 teacher_distribution = payment.teacher_payment_charge.distribution teacher_distribution.amount_in_cents.should eql 1000 payment.teacher_payment_charge.stripe_charge_id.should be_nil StripeMock.clear_errors TeacherPayment.teacher_payments normal_distribution.reload normal_distribution.teacher_payment.should_not be_nil TeacherPayment.count.should eql 1 # make sure the teacher_payment is reused, and charge is reused normal_distribution.teacher_payment.should eql(payment) normal_distribution.teacher_payment.teacher_payment_charge.should eql(payment.teacher_payment_charge) # no attempt should be made because a day hasn't gone by payment = normal_distribution.teacher_payment payment.teacher_payment_charge.billed.should eql false payment.teacher_payment_charge.amount_in_cents.should eql ((1000 * 0.67) + (1000 * 0.67) * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.fee_in_cents.should eql 330 teacher_distribution = payment.teacher_payment_charge.distribution teacher_distribution.amount_in_cents.should eql 1000 # advance one day so that a charge is attempted again Timecop.freeze(Date.today + 2) TeacherPayment.teacher_payments normal_distribution.reload normal_distribution.teacher_payment.should_not be_nil TeacherPayment.count.should eql 1 # make sure the teacher_payment is reused, and charge is reused normal_distribution.teacher_payment.should eql(payment) normal_distribution.teacher_payment.teacher_payment_charge.should eql(payment.teacher_payment_charge) # no attempt should be made because a day hasn't gone by payment = normal_distribution.teacher_payment payment.reload payment.teacher_payment_charge.billed.should eql true payment.teacher_payment_charge.amount_in_cents.should eql ((1000 * 0.67) + (1000 * 0.67) * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.fee_in_cents.should eql 330 teacher_distribution = payment.teacher_payment_charge.distribution teacher_distribution.amount_in_cents.should eql 1000 charge = Stripe::Charge.retrieve(payment.teacher_payment_charge.stripe_charge_id) charge.amount.should eql 675 end end end end end =end