require 'spec_helper' describe TeacherPayment do let(:user) { FactoryGirl.create(:user) } let(:user2) { FactoryGirl.create(:user) } let(:teacher_obj) {FactoryGirl.create(:teacher, stripe_account_id: stripe_account1_id)} let(:teacher_obj2) {FactoryGirl.create(:teacher, stripe_account_id: stripe_account2_id)} let(:school_owner_teacher) {FactoryGirl.create(:teacher, stripe_account_id: stripe_account2_id)} let(:teacher) { FactoryGirl.create(:user, teacher: teacher_obj) } let(:teacher2) { FactoryGirl.create(:user, teacher: teacher_obj2) } let(:school_teacher) { FactoryGirl.create(:user, teacher: school_owner_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 it "empty" do TeacherPayment.pending_teacher_payments.count.should eql 0 end it "one distribution" do test_drive_distribution.touch 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 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 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 "teacher_payments" do 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 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 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 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 charge.application_fee.should include("fee_") end it "charges school" do 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 payment.teacher_payment_charge.fee_in_cents.should eql 280 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 eql school.owner.teacher.stripe_account_id charge.amount.should eql 1000 charge.application_fee.should include("fee_") 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 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 charge.application_fee.should include("fee_") 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 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 charge.application_fee.should be_nil end describe "stripe mocked" do before { StripeMock.start } after { StripeMock.stop; Timecop.return } 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 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 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 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 end 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 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 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 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 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 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 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 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 end end end end