diff --git a/db/manifest b/db/manifest index c17ed2029..68db33231 100755 --- a/db/manifest +++ b/db/manifest @@ -346,4 +346,5 @@ lessons_unread_messages.sql track_school_signups.sql add_test_drive_types.sql updated_subjects.sql -update_payment_history.sql \ No newline at end of file +update_payment_history.sql +lesson_booking_schools.sql \ No newline at end of file diff --git a/db/up/lesson_booking_schools.sql b/db/up/lesson_booking_schools.sql new file mode 100644 index 000000000..265e731b7 --- /dev/null +++ b/db/up/lesson_booking_schools.sql @@ -0,0 +1,3 @@ +ALTER TABLE lesson_bookings ADD COLUMN school_id INTEGER REFERENCES schools(id); +ALTER TABLE teacher_payments ADD COLUMN school_id INTEGER REFERENCES schools(id); +ALTER TABLE teacher_distributions ADD COLUMN school_id INTEGER REFERENCES schools(id); \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/mailers/user_mailer.rb b/ruby/lib/jam_ruby/app/mailers/user_mailer.rb index 1d539e16c..44410c3e8 100644 --- a/ruby/lib/jam_ruby/app/mailers/user_mailer.rb +++ b/ruby/lib/jam_ruby/app/mailers/user_mailer.rb @@ -1270,12 +1270,39 @@ module JamRuby end end + # always goes to the teacher def teacher_distribution_done(teacher_payment) + @school = teacher_payment.school @teacher_payment = teacher_payment + @distribution = teacher_payment.teacher_distribution @teacher = teacher_payment.teacher + @payable_teacher = teacher_payment.payable_teacher + @name = @teacher.first_name || 'Anonymous' + @student = @distribution.student email = @teacher.email - @subject = "You have received payment for your participation in JamClass" + if @school + if @distribution.is_test_drive? + @subject = "Your TestDrive lesson with #{@student.name}" + elsif @distribution.is_normal? + @subject = "Your lesson with #{@student.name}" + elsif @distribution.is_monthly? + @subject = "Your #{@distribution.month_name} lessons with #{@student.name}" + else + @subject = "Your lesson with #{@student.name}" + end + else + if @distribution.is_test_drive? + @subject = "You have earned #{@distribution.real_distribution_display} for your TestDrive lesson with #{@student.first_name}" + elsif @distribution.is_normal? + @subject = "You have earned #{@distribution.real_distribution_display} for your lesson with #{@student.first_name}" + elsif @distribution.is_monthly? + @subject = "You have earned #{@distribution.real_distribution_display} for your #{@distribution.month_name} lessons with #{@student.first_name}" + else + @subject = "You have earned #{@distribution.real_distribution_display} for your lesson with #{@student.first_name}" + end + end + unique_args = {:type => "teacher_distribution_done"} sendgrid_category "Notification" @@ -1290,24 +1317,51 @@ module JamRuby end end + # if school, goes to school owner; otherwise goes to teacher def teacher_distribution_fail(teacher_payment) + @school = teacher_payment.school @teacher_payment = teacher_payment + @distribution = teacher_payment.teacher_distribution @teacher = teacher_payment.teacher - email = @teacher.email + @payable_teacher = teacher_payment.payable_teacher + @student = @distribution.student + @name = @payable_teacher.first_name || 'Anonymous' + email = @payable_teacher.email @card_declined = teacher_payment.is_card_declined? @card_expired = teacher_payment.is_card_expired? @bill_date = teacher_payment.last_billed_at_date - @subject = "We were unable to pay you today" + if @school + if @distribution.is_test_drive? + @subject = "We had a problem paying #{@distribution.real_distribution_display} for #{@teacher.name}'s TestDrive lesson with #{@student.name}" + elsif @distribution.is_normal? + @subject = "We had a problem paying #{@distribution.real_distribution_display} for #{@teacher.name}'s lesson with #{@student.name}" + elsif @distribution.is_monthly? + @subject = "We had a problem paying #{@distribution.real_distribution_display} for #{@teacher.name}'s #{@distribution.month_name} lessons with #{@student.name}" + else + @subject = "We had a problem paying #{@distribution.real_distribution_display} for #{@teacher.name}'s lesson with #{@student.name}" + end + else + if @distribution.is_test_drive? + @subject = "We had a problem paying you #{@distribution.real_distribution_display} for your TestDrive lesson with #{@student.first_name}" + elsif @distribution.is_normal? + @subject = "We had a problem paying you #{@distribution.real_distribution_display} for your lesson with #{@student.first_name}" + elsif @distribution.is_monthly? + @subject = "We had a problem paying you #{@distribution.real_distribution_display} for your #{@distribution.month_name} lessons with #{@student.first_name}" + else + @subject = "We had a problem paying you #{@distribution.real_distribution_display} for your lesson with #{@student.first_name}" + end + end + unique_args = {:type => "teacher_distribution_fail"} sendgrid_category "Notification" sendgrid_unique_args :type => unique_args[:type] sendgrid_recipients([email]) - sendgrid_substitute('@USERID', [@teacher.id]) + sendgrid_substitute('@USERID', [@payable_teacher.id]) mail(:to => email, :subject => @subject) do |format| format.text @@ -1315,6 +1369,42 @@ module JamRuby end end + # always goes to the school owner + def school_distribution_done(teacher_payment) + @school = teacher_payment.school + @teacher_payment = teacher_payment + @distribution = teacher_payment.teacher_distribution + @teacher = teacher_payment.teacher + @payable_teacher = @school.owner + @name = @payable_teacher.first_name || 'Anonymous' + @student = @distribution.student + email = @payable_teacher.email + + if @distribution.is_test_drive? + @subject = "#{@teacher.name} has earned #{@distribution.real_distribution_display} for TestDrive lesson with #{@student.name}" + elsif @distribution.is_normal? + @subject = "#{@teacher.name} has earned #{@distribution.real_distribution_display} for a lesson with #{@student.name}" + elsif @distribution.is_monthly? + @subject = "#{@teacher.name} has earned #{@distribution.real_distribution_display} for #{@distribution.month_name} lessons with #{@student.name}" + else + @subject = "#{@teacher.name} has earned #{@distribution.real_distribution_display} for a lesson with #{@student.name}" + end + + unique_args = {:type => "school_distribution_done"} + + sendgrid_category "Notification" + sendgrid_unique_args :type => unique_args[:type] + + sendgrid_recipients([email]) + sendgrid_substitute('@USERID', [@payable_teacher.id]) + + mail(:to => email, :subject => @subject) do |format| + format.text + format.html + end + end + + def monthly_recurring_done(lesson_session) @student = lesson_session.student @teacher = lesson_session.teacher diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/monthly_recurring_done.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/monthly_recurring_done.html.erb index 96bf19889..bc205e230 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/monthly_recurring_done.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/monthly_recurring_done.html.erb @@ -7,7 +7,7 @@

- We hope you enjoyed your JamClass lesson today with <%= @teacher.name %>. As just a reminder, you already paid for this lesson in advance. + We hope you enjoyed your JamClass lesson today with <%= @teacher.name %>.

diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/school_distribution_done.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/school_distribution_done.html.erb new file mode 100644 index 000000000..37f9d2780 --- /dev/null +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/school_distribution_done.html.erb @@ -0,0 +1,20 @@ +<% provide(:title, @subject) %> + +

+ Hello <%= @name %>, +

+ + <% if @distribution.is_test_drive? %> +

We have processed a payment to you via your Stripe account for $<%= @distribution.real_distribution_display %> for this lesson.

+ <% elsif @distribution.is_normal? %> +

We have processed a payment to you via your Stripe account for $<%= @distribution.real_distribution_display %> for this lesson.

+ <% elsif @distribution.is_monthly? %> +

We have processed a payment to you via your Stripe account for $<%= @distribution.real_distribution_display %> for <%= @distribution.month_name %> lessons.

+ <% else %> + Unknown payment type. + <% end %> +
+
+ +Best Regards,
+JamKazam \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/school_distribution_done.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/school_distribution_done.text.erb new file mode 100644 index 000000000..fcf56ab98 --- /dev/null +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/school_distribution_done.text.erb @@ -0,0 +1,16 @@ +<% provide(:title, @subject) %> + +Hello <%= @name %>, + +<% if @distribution.is_test_drive? %> +We have processed a payment to you via your Stripe account for $<%= @distribution.real_distribution_display %> for this lesson. +<% elsif @distribution.is_normal? %> +We have processed a payment to you via your Stripe account for $<%= @distribution.real_distribution_display %> for this lesson. +<% elsif @distribution.is_monthly? %> +We have processed a payment to you via your Stripe account for $<%= @distribution.real_distribution_display %> for <%= @distribution.month_name %> lessons. +<% else %> +Unknown payment type. +<% end %> + +Best Regards, +JamKazam \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_lesson_normal_done.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_lesson_normal_done.html.erb index 1a3c7e42a..a6a2cddc7 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_lesson_normal_done.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_lesson_normal_done.html.erb @@ -7,8 +7,7 @@

- We hope you enjoyed your JamClass lesson today with <%= @teacher.name %>. You have been - billed $<%= @lesson_session.amount_charged %> for today's lesson. + We hope you enjoyed your JamClass lesson today with <%= @teacher.name %>. You have been billed $<%= @lesson_session.amount_charged %> for today's lesson.

diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/teacher_distribution_done.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/teacher_distribution_done.html.erb index af2681325..fc3c62e31 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/teacher_distribution_done.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/teacher_distribution_done.html.erb @@ -1,31 +1,42 @@ <% provide(:title, @subject) %> -

You were paid a total of $<%= @teacher_payment.amount %> for your participation in JamClass. Below are more details:

-
+

+ Hello <%= @name %>, +

-<% @teacher_payment.teacher_distributions.each do |distribution| %> - - <% if distribution.is_test_drive? %> -

You have earned $<%= distribution.amount %> for your TestDrive lesson with <%= distribution.student.name %>

+ <% if @distribution.is_test_drive? %> + <% if @school %> +

We hope you enjoyed your TestDrive lesson today with <%= @distribution.student.name %>.

+ <% else %> +

You have earned $<%= @distribution.real_distribution_display %> for your TestDrive lesson with <%= @distribution.student.name %>.

+ <% end %>

- <% if !@teacher_payment.teacher.has_rated_student(distribution.student) %> - If you haven't already done so, please rate your student now to help us monitor for any issues with students who may cause issues for our instructor community. + <% if !@teacher_payment.teacher.has_rated_student(@distribution.student) %> + If you haven't already done so, please rate your student now to help us monitor for any issues with students who may cause issues for our instructor community. <% end %> If you had technical problems during your lesson, or have questions, or would like to make suggestions on how to improve JamClass, please email us at support@jamkazam.com.

- <% elsif distribution.is_normal? %> -

You have earned $<%= distribution.amount %> for your lesson with <%= distribution.student.name %>

+ <% elsif @distribution.is_normal? %> + <% if @school %> +

we hope you enjoyed your lesson today with <%= @distribution.student.name %>.

+ <% else %> +

You have earned $<%= @distribution.real_distribution_display %> for your lesson with <%= @distribution.student.name %>.

+ <% end %>

- <% if !@teacher_payment.teacher.has_rated_student(distribution.student) %> - If you haven't already done so, please rate your student now to help us monitor for any issues with students who may cause issues for our instructor community. + <% if !@teacher_payment.teacher.has_rated_student(@distribution.student) %> + If you haven't already done so, please rate your student now to help us monitor for any issues with students who may cause issues for our instructor community. <% end %> If you had technical problems during your lesson, or have questions, or would like to make suggestions on how to improve JamClass, please email us at support@jamkazam.com.

- <% elsif distribution.is_monthly? %> -

You have earned $<%= distribution.amount %> for your <%= distribution.month_name%> lesson with <%= distribution.student.name %>

+ <% elsif @distribution.is_monthly? %> + <% if @school %> +

we hope you enjoyed your <%= @distribution.month_name %> lessons with <%= @distribution.student.name %>.

+ <% else %> +

You have earned $<%= @distribution.real_distribution_display %> for your <%= @distribution.month_name%> lessons with <%= @distribution.student.name %>.

+ <% end %>

- <% if !@teacher_payment.teacher.has_rated_student(distribution.student) %> - If you haven't already done so, please rate your student now to help us monitor for any issues with students who may cause issues for our instructor community. + <% if !@teacher_payment.teacher.has_rated_student(@distribution.student) %> + If you haven't already done so, please rate your student now to help us monitor for any issues with students who may cause issues for our instructor community. <% end %> If you had technical problems during your lesson, or have questions, or would like to make suggestions on how to improve JamClass, please email us at support@jamkazam.com.

@@ -35,7 +46,5 @@

-<% end %> - Best Regards,
JamKazam \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/teacher_distribution_done.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/teacher_distribution_done.text.erb index 2e18fa163..17ecc5c92 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/teacher_distribution_done.text.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/teacher_distribution_done.text.erb @@ -1,31 +1,40 @@ <% provide(:title, @subject) %> -You were paid a total of $<%= @teacher_payment.amount %> for your participation in JamClass. Below are more details: +Hello <%= @name %>, -<% @teacher_payment.teacher_distributions.each do |distribution| %> - -<% if distribution.is_test_drive? %> -You have earned $<%= distribution.amount %> for your TestDrive lesson with <%= distribution.student.name %>. -<% if !@teacher_payment.teacher.has_rated_student(distribution.student) %> -If you haven't already done so, please rate your student now to help us monitor for any issues with students who may cause issues for our instructor community. <%= distribution.student.student_ratings_url %> +<% if @distribution.is_test_drive? %> +<% if @school %> +We hope you enjoyed your TestDrive lesson today with <%= @distribution.student.name %>. +<% else %> +You have earned $<%= @distribution.amount %> for your TestDrive lesson with <%= @distribution.student.name %>. +<% end %> +<% if !@teacher_payment.teacher.has_rated_student(@distribution.student) %> +If you haven't already done so, please rate your student now to help us monitor for any issues with students who may cause issues for our instructor community. <%= @distribution.student.student_ratings_url %> <% end%> If you had technical problems during your lesson, or have questions, or would like to make suggestions on how to improve JamClass, please email us at support@jamkazam.com. -<% elsif distribution.is_normal? %> -You have earned $<%= distribution.amount %> for your lesson with <%= distribution.student.name %>. -<% if !@teacher_payment.teacher.has_rated_student(distribution.student) %> -If you haven't already done so, please rate your student now to help us monitor for any issues with students who may cause issues for our instructor community. <%= distribution.student.student_ratings_url %> +<% elsif @distribution.is_normal? %> +<% if @school %> +We hope you enjoyed your lesson today with <%= @distribution.student.name %>. +<% else %> +You have earned $<%= @distribution.amount %> for your lesson with <%= @distribution.student.name %>. +<% end %> +<% if !@teacher_payment.teacher.has_rated_student(@distribution.student) %> +If you haven't already done so, please rate your student now to help us monitor for any issues with students who may cause issues for our instructor community. <%= @distribution.student.student_ratings_url %> <% end%> If you had technical problems during your lesson, or have questions, or would like to make suggestions on how to improve JamClass, please email us at support@jamkazam.com. -<% elsif distribution.is_monthly? %> -You have earned $<%= distribution.amount %> for your <%= distribution.month_name%> lesson with <%= distribution.student.name %>. -<% if !@teacher_payment.teacher.has_rated_student(distribution.student) %> -If you haven't already done so, please rate your student now to help us monitor for any issues with students who may cause issues for our instructor community. <%= distribution.student.student_ratings_url %> +<% elsif @distribution.is_monthly? %> +<% if @school %> +We hope you enjoyed your <%= @distribution.month_name%> lessons with <%= @distribution.student.name %>. +<% else %> +You have earned $<%= @distribution.amount %> for your <%= @distribution.month_name%> lessons with <%= @distribution.student.name %>. +<% end %> +<% if !@teacher_payment.teacher.has_rated_student(@distribution.student) %> +If you haven't already done so, please rate your student now to help us monitor for any issues with students who may cause issues for our instructor community. <%= @distribution.student.student_ratings_url %> <% end%> If you had technical problems during your lesson, or have questions, or would like to make suggestions on how to improve JamClass, please email us at support@jamkazam.com. <% else %> Unknown payment type. <% end %> -<% end %> Best Regards, JamKazam \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/teacher_distribution_fail.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/teacher_distribution_fail.html.erb index bdd291b49..bcd797ffd 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/teacher_distribution_fail.html.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/teacher_distribution_fail.html.erb @@ -1,5 +1,12 @@ <% provide(:title, @subject) %> +

Hello <%= @name %>,

+ +<% if @school %> +

+ We attempted to process a payment via your Stripe account for <%= @distribution.real_distribution_display %> for this lesson, but the payment failed. Please sign into your Stripe account, and verify that everything there is working properly. We’ll try again to process this payment in about 24 hours. +

+<% else %>

<% if @card_declined %> When we tried to distribute a payment to you on <%= @bill_date %>, the charge was declined by stripe. Can you please check your stripe account status? Thank you! @@ -9,6 +16,7 @@ For some reason, when we tried to distribute a payment to you on <%= @bill_date %>, the charge failed. Can you please check your stripe account status? Thank you! <% end %>

+<% end %>
Best Regards,
diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/teacher_distribution_fail.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/teacher_distribution_fail.text.erb index 8cc72bce5..a0ce26b67 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/teacher_distribution_fail.text.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/teacher_distribution_fail.text.erb @@ -1,5 +1,9 @@ <% provide(:title, @subject) %> +Hello <%= @name %>, +<% if @school %> + We attempted to process a payment via your Stripe account for <%= @distribution.real_distribution_display %> for this lesson, but the payment failed. Please sign into your Stripe account, and verify that everything there is working properly. We’ll try again to process this payment in about 24 hours. +<% else %> <% if @card_declined %> When we tried to distribute a payment to you on <%= @bill_date %>, the charge was declined by stripe. Can you please check your stripe account status? Thank you! <% elsif @card_expired %> @@ -7,6 +11,7 @@ When we tried to distribute a payment to you on <%= @bill_date %>, the charge wa <% else %> For some reason, when we tried to distribute a payment to you on <%= @bill_date %>, the charge failed. Can you please check your stripe account status? Thank you! <% end %> +<% end %> Best Regards, JamKazam \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/affiliate_payment_charge.rb b/ruby/lib/jam_ruby/models/affiliate_payment_charge.rb index 7955fc3a1..376578b9d 100644 --- a/ruby/lib/jam_ruby/models/affiliate_payment_charge.rb +++ b/ruby/lib/jam_ruby/models/affiliate_payment_charge.rb @@ -1,7 +1,7 @@ module JamRuby class AffiliatePaymentCharge < Charge - has_one :teacher_payment, class_name: "JamRuby::TeacherPayment", foreign_key: :affiliate_charge_id + #has_one :teacher_payment, class_name: "JamRuby::TeacherPayment", foreign_key: :affiliate_charge_id def distribution @distribution ||= teacher_payment.teacher_distribution @@ -36,15 +36,15 @@ module JamRuby end def do_send_notices - UserMailer.teacher_distribution_done(teacher_payment) + #UserMailer.teacher_distribution_done(teacher_payment) end def do_send_unable_charge - UserMailer.teacher_distribution_fail(teacher_payment) + #UserMailer.teacher_distribution_fail(teacher_payment) end def construct_description - teacher_payment.teacher_distribution.description + #teacher_payment.teacher_distribution.description end end diff --git a/ruby/lib/jam_ruby/models/charge.rb b/ruby/lib/jam_ruby/models/charge.rb index 1f8a4d4c0..83d9400ce 100644 --- a/ruby/lib/jam_ruby/models/charge.rb +++ b/ruby/lib/jam_ruby/models/charge.rb @@ -98,6 +98,7 @@ module JamRuby else self.billing_error_detail = e.to_s + "\n" + e.backtrace.join("\n\t") if e.backtrace end + puts "Charge: unhandled exception #{billing_error_reason}, #{billing_error_detail}" self.save(validate: false) end diff --git a/ruby/lib/jam_ruby/models/lesson_booking.rb b/ruby/lib/jam_ruby/models/lesson_booking.rb index 3fc16b1ca..dd373790d 100644 --- a/ruby/lib/jam_ruby/models/lesson_booking.rb +++ b/ruby/lib/jam_ruby/models/lesson_booking.rb @@ -39,6 +39,7 @@ module JamRuby belongs_to :canceler, class_name: "JamRuby::User" belongs_to :default_slot, class_name: "JamRuby::LessonBookingSlot", foreign_key: :default_slot_id, inverse_of: :defaulted_booking, :dependent => :destroy belongs_to :counter_slot, class_name: "JamRuby::LessonBookingSlot", foreign_key: :counter_slot_id, inverse_of: :countered_booking, :dependent => :destroy + belongs_to :school, class_name: "JamRuby::School" has_many :lesson_booking_slots, class_name: "JamRuby::LessonBookingSlot", :dependent => :destroy has_many :lesson_sessions, class_name: "JamRuby::LessonSession", :dependent => :destroy has_many :lesson_package_purchases, class_name: "JamRuby::LessonPackagePurchase", :dependent => :destroy @@ -61,7 +62,7 @@ module JamRuby validate :validate_lesson_booking_slots validate :validate_lesson_length validate :validate_payment_style - validate :validate_uncollectables + validate :validate_uncollectables, on: :create validate :validate_accepted, :if => :accepting validate :validate_canceled, :if => :canceling @@ -657,6 +658,10 @@ module JamRuby end end + def school_owned? + !!school + end + def self.book_free(user, teacher, lesson_booking_slots, description) self.book(user, teacher, LessonBooking::LESSON_TYPE_FREE, lesson_booking_slots, false, 30, PAYMENT_STYLE_ELSEWHERE, description) end @@ -685,6 +690,9 @@ module JamRuby lesson_booking.payment_style = payment_style lesson_booking.description = description lesson_booking.status = STATUS_REQUESTED + if lesson_booking.teacher && lesson_booking.teacher.teacher.school + lesson_booking.school = school + end # two-way association slots, for before_validation loic in slot to work lesson_booking.lesson_booking_slots = lesson_booking_slots diff --git a/ruby/lib/jam_ruby/models/lesson_package_purchase.rb b/ruby/lib/jam_ruby/models/lesson_package_purchase.rb index cda42d86a..10405a9e9 100644 --- a/ruby/lib/jam_ruby/models/lesson_package_purchase.rb +++ b/ruby/lib/jam_ruby/models/lesson_package_purchase.rb @@ -33,7 +33,7 @@ module JamRuby end def create_charge - if self.lesson_booking.is_monthly_payment? + if lesson_booking && lesson_booking.is_monthly_payment? self.lesson_payment_charge = LessonPaymentCharge.new lesson_payment_charge.user = user lesson_payment_charge.amount_in_cents = 0 @@ -97,8 +97,8 @@ module JamRuby (price * 100).to_i end - def description(lesson_booking, time = false) - lesson_package_type.description(lesson_booking, time) + def description(lesson_booking) + lesson_package_type.description(lesson_booking) end def stripe_description(lesson_booking) @@ -121,12 +121,21 @@ module JamRuby user end + def school_on_school? + teacher.teacher.school && student.school && (teacher.teacher.school.id == student.school.id) + end def bill_monthly(force = false) - lesson_payment_charge.charge(force) - if lesson_payment_charge.billed + if school_on_school? + success = true + else + lesson_payment_charge.charge(force) + success = lesson_payment_charge.billed + end + + if success self.sent_notices = true self.sent_notices_at = Time.now self.post_processed = true diff --git a/ruby/lib/jam_ruby/models/lesson_session.rb b/ruby/lib/jam_ruby/models/lesson_session.rb index 53bb1462f..74574cb00 100644 --- a/ruby/lib/jam_ruby/models/lesson_session.rb +++ b/ruby/lib/jam_ruby/models/lesson_session.rb @@ -241,10 +241,14 @@ module JamRuby end def bill_lesson + if school_on_school? + success = true + else + lesson_payment_charge.charge + success = lesson_payment_charge.billed + end - lesson_payment_charge.charge - - if lesson_payment_charge.billed + if success self.sent_notices = true self.sent_notices_at = Time.now self.post_processed = true @@ -297,9 +301,12 @@ module JamRuby end else if lesson_booking.is_monthly_payment? - # bad session; just poke user if !sent_notices - UserMailer.monthly_recurring_no_bill(self).deliver + if !school_on_school? + # bad session; just poke user + UserMailer.monthly_recurring_no_bill(self).deliver + end + self.sent_notices = true self.sent_notices_at = Time.now self.post_processed = true @@ -309,8 +316,11 @@ module JamRuby else if !sent_notices - # bad session; just poke user - UserMailer.student_lesson_normal_no_bill(self).deliver + if !school_on_school? + # bad session; just poke user + UserMailer.student_lesson_normal_no_bill(self).deliver + end + self.sent_notices = true self.sent_notices_at = Time.now self.post_processed = true @@ -327,8 +337,11 @@ module JamRuby bill_lesson else if !sent_notices - UserMailer.student_lesson_normal_no_bill(self).deliver - UserMailer.teacher_lesson_normal_no_bill(self).deliver + if !school_on_school? + UserMailer.student_lesson_normal_no_bill(self).deliver + UserMailer.teacher_lesson_normal_no_bill(self).deliver + end + self.sent_notices = true self.sent_notices_at = Time.now self.post_processed = true @@ -385,6 +398,10 @@ module JamRuby @parsed_analysis || analysis ? JSON.parse(analysis) : nil end + def school_on_school? + teacher.teacher.school && student.school && (teacher.teacher.school.id == student.school.id) + end + def validate_creating if !is_requested? && !is_approved? self.errors.add(:status, "is not valid for a new lesson session.") diff --git a/ruby/lib/jam_ruby/models/lesson_session_analyser.rb b/ruby/lib/jam_ruby/models/lesson_session_analyser.rb index 74f23b5f3..57fb611e8 100644 --- a/ruby/lib/jam_ruby/models/lesson_session_analyser.rb +++ b/ruby/lib/jam_ruby/models/lesson_session_analyser.rb @@ -69,7 +69,7 @@ module JamRuby # spec: https://jamkazam.atlassian.net/wiki/display/PS/Product+Specification+-+JamClass#ProductSpecification-JamClass-TeacherReceives&RespondstoLessonBookingRequest - if !force && (!((music_session.scheduled_start + (lesson_session.duration * 60)) < Time.now)) + if !force && !((music_session.scheduled_start + (lesson_session.duration * 60)) < Time.now) reason = SESSION_ONGOING bill = false else diff --git a/ruby/lib/jam_ruby/models/school.rb b/ruby/lib/jam_ruby/models/school.rb index 1c573d778..dc659b2d9 100644 --- a/ruby/lib/jam_ruby/models/school.rb +++ b/ruby/lib/jam_ruby/models/school.rb @@ -18,6 +18,8 @@ module JamRuby has_many :students, class_name: ::JamRuby::User has_many :teachers, class_name: ::JamRuby::Teacher has_many :school_invitations, class_name: 'JamRuby::SchoolInvitation' + has_many :teacher_payments, class_name: 'JamRuby::TeacherPayment' + has_many :teacher_distributions, class_name: 'JamRuby::TeacherDistribution' validates :user, presence: true validates :enabled, inclusion: {in: [true, false]} diff --git a/ruby/lib/jam_ruby/models/teacher_distribution.rb b/ruby/lib/jam_ruby/models/teacher_distribution.rb index e7001ad65..552a5959c 100644 --- a/ruby/lib/jam_ruby/models/teacher_distribution.rb +++ b/ruby/lib/jam_ruby/models/teacher_distribution.rb @@ -5,6 +5,7 @@ module JamRuby belongs_to :teacher_payment, class_name: "JamRuby::TeacherPayment" belongs_to :lesson_session, class_name: "JamRuby::LessonSession" belongs_to :lesson_package_purchase, class_name: "JamRuby::LessonPackagePurchase" + belongs_to :school, class_name: "JamRuby::School" validates :teacher, presence: true validates :amount_in_cents, presence: true @@ -14,7 +15,7 @@ module JamRuby limit ||= 100 limit = limit.to_i - query = TeacherDistribution.where(teacher_id: current_user.id).order('created_at desc') + query = TeacherDistribution.where(teacher_id: current_user.id).where('school_id IS NULL').order('created_at desc') current_page = params[:page].nil? ? 1 : params[:page].to_i next_page = current_page + 1 @@ -59,6 +60,7 @@ module JamRuby distribution.ready = false distribution.distributed = false distribution.amount_in_cents = target.lesson_booking.distribution_price_in_cents(target) + distribution.school = target.lesson_booking.school distribution end @@ -70,11 +72,19 @@ module JamRuby amount_in_cents - calculate_teacher_fee end + def real_distribution + (real_distribution_in_cents / 100.0) + end + + def real_distribution_display + '$%.2f' % real_distribution + end + def calculate_teacher_fee if is_test_drive? 0 else - (amount_in_cents * teacher.teacher.jamkazam_rate + 0.03).round + (amount_in_cents * (teacher.teacher.jamkazam_rate + 0.03)).round end end diff --git a/ruby/lib/jam_ruby/models/teacher_payment.rb b/ruby/lib/jam_ruby/models/teacher_payment.rb index fe2b603c3..a0fa6deff 100644 --- a/ruby/lib/jam_ruby/models/teacher_payment.rb +++ b/ruby/lib/jam_ruby/models/teacher_payment.rb @@ -4,12 +4,22 @@ module JamRuby belongs_to :teacher, class_name: "JamRuby::User", foreign_key: :teacher_id belongs_to :teacher_payment_charge, class_name: "JamRuby::TeacherPaymentCharge", foreign_key: :charge_id has_one :teacher_distribution, class_name: "JamRuby::TeacherDistribution" + belongs_to :school, class_name: "JamRuby::School" def self.hourly_check teacher_payments end + # pay the school if the payment owns the school; otherwise default to the teacher + def payable_teacher + if school + school.owner + else + teacher + end + end + def teacher_distributions [teacher_distribution] end @@ -74,13 +84,13 @@ module JamRuby payment.teacher_distribution = teacher_distribution end - + payment.school = payment.teacher_distribution.school payment.amount_in_cents = payment.teacher_distribution.amount_in_cents payment.fee_in_cents = payment.teacher_distribution.calculate_teacher_fee if payment.teacher_payment_charge.nil? charge = TeacherPaymentCharge.new - charge.user = teacher + charge.user = payment.payable_teacher charge.amount_in_cents = payment.amount_in_cents charge.fee_in_cents = payment.fee_in_cents charge.teacher_payment = payment diff --git a/ruby/lib/jam_ruby/models/teacher_payment_charge.rb b/ruby/lib/jam_ruby/models/teacher_payment_charge.rb index e54bc5330..0f82e48e2 100644 --- a/ruby/lib/jam_ruby/models/teacher_payment_charge.rb +++ b/ruby/lib/jam_ruby/models/teacher_payment_charge.rb @@ -12,15 +12,13 @@ module JamRuby end def teacher - @teacher ||= teacher_payment.teacher + @teacher ||= teacher_payment.payable_teacher end def charged_user teacher end - - def do_charge(force) # source will let you supply a token. But... how to get a token in this case? @@ -38,11 +36,17 @@ module JamRuby end def do_send_notices - UserMailer.teacher_distribution_done(teacher_payment) + unless teacher_payment.school && distribution.is_monthly? + # we don't send monthly success notices to the teacher if they are in a school, otherwise they get an email + UserMailer.teacher_distribution_done(teacher_payment).deliver + end + if teacher_payment.school + UserMailer.school_distribution_done(teacher_payment).deliver + end end def do_send_unable_charge - UserMailer.teacher_distribution_fail(teacher_payment) + UserMailer.teacher_distribution_fail(teacher_payment).deliver end def construct_description diff --git a/ruby/spec/jam_ruby/flows/monthly_recurring_lesson_spec.rb b/ruby/spec/jam_ruby/flows/monthly_recurring_lesson_spec.rb index 2f3935b42..8b0292922 100644 --- a/ruby/spec/jam_ruby/flows/monthly_recurring_lesson_spec.rb +++ b/ruby/spec/jam_ruby/flows/monthly_recurring_lesson_spec.rb @@ -38,11 +38,11 @@ describe "Monthly Recurring Lesson Flow" do ########## Need validate their credit card token = create_stripe_token result = user.payment_update({token: token, zip: '78759', normal: true}) - booking = result[:lesson] - lesson = booking.lesson_sessions[0] + booking.card_presumed_ok.should be_true booking.errors.any?.should be_false lesson.errors.any?.should be_false - booking.card_presumed_ok.should be_true + booking = result[:lesson] + lesson = booking.lesson_sessions[0] booking.sent_notices.should be_true lesson.music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0) lesson.amount_charged.should be 0.0 diff --git a/ruby/spec/jam_ruby/flows/normal_lesson_spec.rb b/ruby/spec/jam_ruby/flows/normal_lesson_spec.rb index 9bb60d232..a81e686be 100644 --- a/ruby/spec/jam_ruby/flows/normal_lesson_spec.rb +++ b/ruby/spec/jam_ruby/flows/normal_lesson_spec.rb @@ -14,7 +14,9 @@ describe "Normal Lesson Flow" do let(:valid_recurring_slots) { [lesson_booking_slot_recurring1, lesson_booking_slot_recurring2] } describe "stripe mocked" do - before { StripeMock.start + before { + StripeMock.clear_errors + StripeMock.start teacher.stripe_account_id = stripe_account1_id teacher.save! } @@ -35,7 +37,7 @@ describe "Normal Lesson Flow" do ########## Need validate their credit card token = create_stripe_token - result = user.payment_update({token: token, zip: '78759', normal: true}) + result = user.payment_update({token: token, zip: '78759', normal: true, booking_id: booking.id}) booking = result[:lesson] lesson = booking.lesson_sessions[0] booking.errors.any?.should be_false @@ -92,6 +94,7 @@ describe "Normal Lesson Flow" do lesson_session.music_session.session_removed_at = end_time lesson_session.music_session.save! + Timecop.travel(end_time + 1) UserMailer.deliveries.clear # background code comes around and analyses the session @@ -178,12 +181,12 @@ describe "Normal Lesson Flow" do lesson_session.reload payment = lesson_session.lesson_payment_charge - payment.amount_in_cents.should eql 3248 payment.fee_in_cents.should eql 0 + lesson_session.billing_attempts.should eql 4 lesson_session.post_processed.should be_true - LessonPaymentCharge.count.should eql 2 + LessonPaymentCharge.count.should eql 1 lesson_session.reload lesson_session.analysed.should be_true @@ -267,7 +270,7 @@ describe "Normal Lesson Flow" do ########## Need validate their credit card token = create_stripe_token - result = user.payment_update({token: token, zip: '78759', normal: true}) + result = user.payment_update({token: token, zip: '78759', normal: true, booking_id: booking.id}) booking = result[:lesson] lesson = booking.lesson_sessions[0] booking.errors.any?.should be_false @@ -373,6 +376,7 @@ describe "Normal Lesson Flow" do lesson_session.music_session.session_removed_at = end_time lesson_session.music_session.save! + Timecop.travel(end_time + 1) UserMailer.deliveries.clear # background code comes around and analyses the session diff --git a/ruby/spec/jam_ruby/flows/recurring_lesson_spec.rb b/ruby/spec/jam_ruby/flows/recurring_lesson_spec.rb index f91871129..8eba1de70 100644 --- a/ruby/spec/jam_ruby/flows/recurring_lesson_spec.rb +++ b/ruby/spec/jam_ruby/flows/recurring_lesson_spec.rb @@ -13,6 +13,9 @@ describe "Recurring Lesson Flow" do let(:valid_single_slots) { [lesson_booking_slot_single1, lesson_booking_slot_single2] } let(:valid_recurring_slots) { [lesson_booking_slot_recurring1, lesson_booking_slot_recurring2] } + before(:each) do + Timecop.return + end it "works" do # user has no test drives, no credit card on file, but attempts to book a lesson @@ -27,7 +30,7 @@ describe "Recurring Lesson Flow" do ########## Need validate their credit card token = create_stripe_token - result = user.payment_update({token: token, zip: '78759', normal: true}) + result = user.payment_update({token: token, zip: '78759', normal: true, booking_id: booking.id}) booking = result[:lesson] lesson = booking.lesson_sessions[0] booking.errors.any?.should be_false @@ -139,6 +142,7 @@ describe "Recurring Lesson Flow" do lesson_session.music_session.session_removed_at = end_time lesson_session.music_session.save! + Timecop.travel(end_time + 1) UserMailer.deliveries.clear # background code comes around and analyses the session diff --git a/ruby/spec/jam_ruby/flows/testdrive_lesson_spec.rb b/ruby/spec/jam_ruby/flows/testdrive_lesson_spec.rb index 6bc88f745..6cd7c13b0 100644 --- a/ruby/spec/jam_ruby/flows/testdrive_lesson_spec.rb +++ b/ruby/spec/jam_ruby/flows/testdrive_lesson_spec.rb @@ -14,6 +14,7 @@ describe "TestDrive Lesson Flow" do let(:valid_recurring_slots) { [lesson_booking_slot_recurring1, lesson_booking_slot_recurring2] } before { + Timecop.return teacher.stripe_account_id = stripe_account1_id teacher.save! } @@ -163,6 +164,7 @@ describe "TestDrive Lesson Flow" do lesson_session.music_session.session_removed_at = end_time lesson_session.music_session.save! + Timecop.travel(end_time + 1) UserMailer.deliveries.clear diff --git a/ruby/spec/jam_ruby/models/lesson_booking_spec.rb b/ruby/spec/jam_ruby/models/lesson_booking_spec.rb index 0c2bab1dd..29a5f2cec 100644 --- a/ruby/spec/jam_ruby/models/lesson_booking_spec.rb +++ b/ruby/spec/jam_ruby/models/lesson_booking_spec.rb @@ -137,7 +137,7 @@ describe LessonBooking do end it "advances to next month" do - user.card_approved(create_stripe_token, '78759', booking.id) + user.card_approved(create_stripe_token, '78759', nil) user.save! day = Date.new(2016, 1, 20) @@ -386,38 +386,6 @@ describe LessonBooking do end describe "book_free" do - it "works" do - - pending "free not supported" - booking = LessonBooking.book_free(user, teacher_user, valid_single_slots, "Hey I've heard of you before.") - booking.errors.any?.should be false - booking.user.should eq user - booking.teacher.should eq teacher_user - booking.description.should eq ("Hey I've heard of you before.") - booking.payment_style.should eq LessonBooking::PAYMENT_STYLE_ELSEWHERE - booking.recurring.should eq false - booking.lesson_length.should eq 30 - booking.lesson_type.should eq LessonBooking::LESSON_TYPE_FREE - booking.lesson_booking_slots.length.should eq 2 - - chat_message = ChatMessage.where(lesson_booking_id: booking.id).first - chat_message.should_not be_nil - chat_message.message.should eq booking.description - - user.reload - user.remaining_free_lessons.should eq 0 - user.remaining_test_drives.should eq 1 - - booking.card_presumed_ok.should eq false - booking.sent_notices.should eq false - - user.card_approved(create_stripe_token, '78759') - user.save! - booking.reload - booking.sent_notices.should eq true - booking.card_presumed_ok.should eq true - - end it "allows long message to flow through chat" do @@ -446,16 +414,6 @@ describe LessonBooking do ChatMessage.count.should eq 1 end - it "prevents user without stored credit card" do - - pending "free not supported" - user.stored_credit_card = false - user.save! - - booking = LessonBooking.book_free(user, teacher_user, valid_single_slots, "Hey I've heard of you before.") - booking.errors.any?.should be false - end - it "must have 2 lesson booking slots" do booking = LessonBooking.book_test_drive(user, teacher_user, [], "Hey I've heard of you before.") @@ -520,7 +478,7 @@ describe LessonBooking do booking = LessonBooking.book_test_drive(user, teacher_user, valid_single_slots, "Hey I've heard of you before.") booking.errors.any?.should be true - booking.errors[:user].should eq ["has a requested TestDrive with this teacher"] + booking.errors[:user].should eq ["have a requested TestDrive with this teacher"] ChatMessage.count.should eq 1 end diff --git a/ruby/spec/jam_ruby/models/lesson_session_spec.rb b/ruby/spec/jam_ruby/models/lesson_session_spec.rb index bbf60d93a..938de25e7 100644 --- a/ruby/spec/jam_ruby/models/lesson_session_spec.rb +++ b/ruby/spec/jam_ruby/models/lesson_session_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe LessonSession do - let(:user) {FactoryGirl.create(:user, stored_credit_card: false, remaining_free_lessons: 1, remaining_test_drives: 1)} + let(:user) {FactoryGirl.create(:user, stored_credit_card: true, remaining_free_lessons: 1, remaining_test_drives: 1)} let(:teacher) {FactoryGirl.create(:teacher_user)} let(:slot1) { FactoryGirl.build(:lesson_booking_slot_single) } let(:slot2) { FactoryGirl.build(:lesson_booking_slot_single) } diff --git a/ruby/spec/jam_ruby/models/sale_spec.rb b/ruby/spec/jam_ruby/models/sale_spec.rb index c00c8f5f6..20291922f 100644 --- a/ruby/spec/jam_ruby/models/sale_spec.rb +++ b/ruby/spec/jam_ruby/models/sale_spec.rb @@ -9,6 +9,9 @@ describe Sale do let(:jam_track3) { FactoryGirl.create(:jam_track) } let(:gift_card) { GiftCardType.jam_track_5 } + before(:each) { + Timecop.return + } def assert_free_line_item(sale_line_item, jamtrack) sale_line_item.recurly_tax_in_cents.should be_nil sale_line_item.recurly_total_in_cents.should be_nil @@ -596,6 +599,8 @@ describe Sale do lesson_session.music_session.session_removed_at = end_time lesson_session.music_session.save! + Timecop.travel(end_time + 1) + # bill the user LessonSession.hourly_check @@ -649,6 +654,8 @@ describe Sale do lesson_session.music_session.session_removed_at = end_time lesson_session.music_session.save! + Timecop.travel(end_time + 1) + # bill the user LessonSession.hourly_check @@ -715,7 +722,7 @@ describe Sale do booking.should eql user.unprocessed_test_drive token = create_stripe_token - result = user.payment_update({token: token, zip: '72205', test_drive: true}) + result = user.payment_update({token: token, zip: '72205', test_drive: true, booking_id: booking.id}) booking.reload booking.card_presumed_ok.should be_true @@ -762,7 +769,7 @@ describe Sale do user.remaining_test_drives.should eql 0 token = create_stripe_token - result = user.payment_update({token: token, zip: '78759', test_drive: true}) + result = user.payment_update({token: token, zip: '78759', test_drive: true, booking_id: booking.id}) booking.reload booking.card_presumed_ok.should be_true diff --git a/ruby/spec/jam_ruby/models/teacher_payment_spec.rb b/ruby/spec/jam_ruby/models/teacher_payment_spec.rb index 58ac4d16f..bd85935dc 100644 --- a/ruby/spec/jam_ruby/models/teacher_payment_spec.rb +++ b/ruby/spec/jam_ruby/models/teacher_payment_spec.rb @@ -6,14 +6,17 @@ describe TeacherPayment do 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 @@ -35,6 +38,21 @@ describe TeacherPayment do 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 @@ -95,6 +113,7 @@ describe TeacherPayment do normal_distribution.ready = true normal_distribution.save! + UserMailer.deliveries.clear TeacherPayment.teacher_payments @@ -108,9 +127,13 @@ describe TeacherPayment do 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) @@ -118,6 +141,39 @@ describe TeacherPayment do 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 @@ -240,6 +296,76 @@ describe TeacherPayment do 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)