ACH payment consideration in teacher payments
This commit is contained in:
parent
5d68fe322a
commit
ae9249532b
|
|
@ -1,6 +1,6 @@
|
|||
ActiveAdmin.register JamRuby::LessonBooking, :as => 'LessonBookings' do
|
||||
|
||||
menu :label => 'LessonBooking', :parent => 'JamClass'
|
||||
menu :label => 'Lesson Booking', :parent => 'JamClass'
|
||||
|
||||
config.sort_order = 'created_at desc'
|
||||
config.batch_actions = false
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
ActiveAdmin.register JamRuby::LessonSession, :as => 'LessonSessions' do
|
||||
|
||||
menu :label => 'LessonSession', :parent => 'JamClass'
|
||||
menu :label => 'Lesson Session', :parent => 'JamClass'
|
||||
|
||||
config.sort_order = 'created_at desc'
|
||||
config.batch_actions = false
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
ActiveAdmin.register JamRuby::LessonSession, :as => 'SlowResponses' do
|
||||
|
||||
menu :label => 'Slow Responses', :parent => 'JamClass'
|
||||
|
||||
config.sort_order = 'created_at desc'
|
||||
config.batch_actions = false
|
||||
config.per_page = 100
|
||||
config.paginate = true
|
||||
config.filters = false
|
||||
|
||||
scope("Slow Responses", default: true) { |scope| scope.unscoped.slow_responses }
|
||||
scope("Least Time Left") { |scope| scope.unscoped.least_time_left }
|
||||
|
||||
index do
|
||||
column "Teacher" do |lesson_session|
|
||||
teacher = lesson_session.teacher
|
||||
span do
|
||||
link_to "#{teacher.name} (#{teacher.email})", "#{Rails.application.config.external_root_url}/client#/profile/teacher/#{teacher.id}"
|
||||
end
|
||||
end
|
||||
column "Student" do |lesson_session|
|
||||
student = lesson_session.student
|
||||
span do
|
||||
link_to "#{student.name} (#{student.email})", "#{Rails.application.config.external_root_url}/client#/profile/#{student.id}"
|
||||
end
|
||||
end
|
||||
column "Type" do |lesson_session|
|
||||
link_to lesson_session.display_type
|
||||
end
|
||||
column "Start Time" do |lesson_session|
|
||||
span do
|
||||
if lesson_session.music_session.nil?
|
||||
raise "Lessonsesison with no id #{lesson_session.id}"
|
||||
else
|
||||
lesson_session.music_session.pretty_scheduled_start(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
column "Last student comms date" do |lesson_session|
|
||||
lesson_session.last_student_comm_date
|
||||
end
|
||||
column "Days with no response" do |lesson_session|
|
||||
"#{lesson_session.days_no_response} days"
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -354,4 +354,5 @@ lesson_booking_success.sql
|
|||
user_origin.sql
|
||||
remove_stripe_acct_id.sql
|
||||
track_user_on_lesson.sql
|
||||
audio_in_music_notations.sql
|
||||
audio_in_music_notations.sql
|
||||
lesson_time_tracking.sql
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
ALTER TABLE lesson_bookings ADD COLUMN sent_notices_at timestamp without time zone;
|
||||
ALTER TABLE lesson_bookings ADD COLUMN countered_at timestamp without time zone;
|
||||
ALTER TABLE lesson_sessions ADD COLUMN countered_at timestamp without time zone;
|
||||
ALTER TABLE lesson_bookings ADD COLUMN counterer_id VARCHAR(64) REFERENCES users(id);
|
||||
ALTER TABLE lesson_sessions ADD COLUMN counterer_id VARCHAR(64) REFERENCES users(id);
|
||||
ALTER TABLE lesson_bookings ADD COLUMN sent_counter_reminder BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
|
|
@ -1672,6 +1672,55 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
# please respond to outstanding counter!
|
||||
def student_counter_reminder(lesson_session)
|
||||
@student = lesson_session.student
|
||||
@teacher = lesson_session.teacher
|
||||
@session_url = lesson_session.web_url
|
||||
@lesson_session = lesson_session
|
||||
|
||||
email = @student.email
|
||||
@subject = "Instructor's time proposal is still awaiting your response"
|
||||
unique_args = {:type => "student_counter_reminder"}
|
||||
|
||||
sendgrid_category "Notification"
|
||||
sendgrid_unique_args :type => unique_args[:type]
|
||||
|
||||
sendgrid_recipients([email])
|
||||
sendgrid_substitute('@USERID', [@student.id])
|
||||
|
||||
mail(:to => email, :subject => @subject) do |format|
|
||||
format.text
|
||||
format.html { render :layout => "from_user_mailer" }
|
||||
end
|
||||
end
|
||||
|
||||
# please respond to outstanding counter!
|
||||
def teacher_counter_reminder(lesson_session)
|
||||
@student = lesson_session.student
|
||||
@teacher = lesson_session.teacher
|
||||
@session_name = lesson_session.music_session.name
|
||||
@session_description = lesson_session.music_session.description
|
||||
@session_date = lesson_session.slot.pretty_scheduled_start(true)
|
||||
@session_url = lesson_session.web_url
|
||||
@lesson_session = lesson_session
|
||||
email = lesson_session.teacher.email
|
||||
@subject = "Student #{@student.name}'s time proposal is still awaiting your response"
|
||||
unique_args = {:type => "teacher_counter_reminder"}
|
||||
|
||||
sendgrid_category "Notification"
|
||||
sendgrid_unique_args :type => unique_args[:type]
|
||||
|
||||
sendgrid_recipients([email])
|
||||
sendgrid_substitute('@USERID', [@teacher.id])
|
||||
|
||||
mail(:to => email, :subject => @subject) do |format|
|
||||
format.text
|
||||
format.html { render :layout => "from_user_mailer" }
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def lesson_starting_soon_teacher(lesson_session)
|
||||
@lesson_booking = lesson_booking = lesson_session.lesson_booking
|
||||
@student = lesson_booking.student
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
<% provide(:title, @subject) %>
|
||||
<% provide(:photo_url, @teacher.resolved_photo_url) %>
|
||||
|
||||
<% content_for :note do %>
|
||||
<p>
|
||||
<%= @teacher.name %> proposed a different time 24 hours ago.
|
||||
<br/>
|
||||
<br/>
|
||||
Please click the button below to respond.
|
||||
</p>
|
||||
<p>
|
||||
<a href="<%= @lesson_session.web_url %>" style="margin: 8px 0 0 0;background-color: #ed3618;border: solid 1px #F27861;padding: 3px 10px;font-size: 12px;font-weight: 300;cursor: pointer;color: #FC9;text-decoration: none;line-height: 12px;text-align: center;">VIEW
|
||||
LESSON DETAILS</a>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<%= @teacher.name %> has proposed a different time 24 hours ago. Please respond.
|
||||
|
||||
To see this lesson, click here: <%= @lesson_session.web_url %>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<% provide(:title, @subject) %>
|
||||
<% provide(:photo_url, @student.resolved_photo_url) %>
|
||||
|
||||
<% content_for :note do %>
|
||||
<p>
|
||||
<%= @student.name %> has proposed a different time 24 hours ago.
|
||||
<br/>
|
||||
<br/>
|
||||
Please click the button below to respond.
|
||||
</p>
|
||||
<p>
|
||||
<a href="<%= @lesson_session.web_url %>" style="margin: 8px 0 0 0;background-color: #ed3618;border: solid 1px #F27861;padding: 3px 10px;font-size: 12px;font-weight: 300;cursor: pointer;color: #FC9;text-decoration: none;line-height: 12px;text-align: center;">VIEW
|
||||
LESSON DETAILS</a>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<%= @student.name %> has proposed a different time 24 hours ago. Please respond.
|
||||
|
||||
To see this lesson, click here: <%= @lesson_session.web_url %>
|
||||
|
|
@ -9,7 +9,7 @@ module JamRuby
|
|||
|
||||
@@log = Logging.logger[LessonBooking]
|
||||
|
||||
attr_accessor :accepting, :countering, :canceling, :countered_slot, :countered_lesson, :current_purchase, :current_lesson
|
||||
attr_accessor :accepting, :countering, :canceling, :autocanceling, :countered_slot, :countered_lesson, :current_purchase, :current_lesson
|
||||
|
||||
STATUS_REQUESTED = 'requested'
|
||||
STATUS_CANCELED = 'canceled'
|
||||
|
|
@ -17,8 +17,9 @@ module JamRuby
|
|||
STATUS_SUSPENDED = 'suspended'
|
||||
STATUS_COUNTERED = 'countered'
|
||||
STATUS_COMPLETED = 'completed'
|
||||
STATUS_UNCONFIRMED = 'unconfirmed'
|
||||
|
||||
STATUS_TYPES = [STATUS_REQUESTED, STATUS_CANCELED, STATUS_APPROVED, STATUS_SUSPENDED, STATUS_COUNTERED, STATUS_COMPLETED]
|
||||
STATUS_TYPES = [STATUS_REQUESTED, STATUS_CANCELED, STATUS_APPROVED, STATUS_SUSPENDED, STATUS_COUNTERED, STATUS_COMPLETED, STATUS_UNCONFIRMED]
|
||||
|
||||
LESSON_TYPE_FREE = 'single-free'
|
||||
LESSON_TYPE_TEST_DRIVE = 'test-drive'
|
||||
|
|
@ -40,6 +41,7 @@ module JamRuby
|
|||
belongs_to :teacher, class_name: "JamRuby::User"
|
||||
belongs_to :accepter, class_name: "JamRuby::User"
|
||||
belongs_to :canceler, class_name: "JamRuby::User"
|
||||
belongs_to :counterer, class_name: "JamRuby::User", foreign_key: :counterer_id
|
||||
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"
|
||||
|
|
@ -188,6 +190,9 @@ module JamRuby
|
|||
self.countering = true
|
||||
self.lesson_booking_slots << slot
|
||||
self.counter_slot = slot
|
||||
self.counterer = proposer
|
||||
self.countered_at = Time.now
|
||||
self.sent_counter_reminder = false
|
||||
#self.status = STATUS_COUNTERED
|
||||
self.save
|
||||
end
|
||||
|
|
@ -432,6 +437,7 @@ module JamRuby
|
|||
UserMailer.teacher_lesson_request(self).deliver
|
||||
Notification.send_lesson_message('requested', lesson_sessions[0], false) # TODO: this isn't quite an 'accept'
|
||||
self.sent_notices = true
|
||||
self.sent_notices_at = Time.now
|
||||
self.save
|
||||
end
|
||||
|
||||
|
|
@ -566,6 +572,13 @@ module JamRuby
|
|||
!self.accepter_id.nil?
|
||||
end
|
||||
|
||||
def autocancel
|
||||
self.autocanceling = true
|
||||
self.active = false
|
||||
self.status = STATUS_UNCONFIRMED
|
||||
save
|
||||
self
|
||||
end
|
||||
def cancel(canceler, other, message)
|
||||
|
||||
self.canceling = true
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ module JamRuby
|
|||
include HtmlSanitize
|
||||
html_sanitize strict: [:cancel_message]
|
||||
|
||||
attr_accessor :accepting, :creating, :countering, :countered_slot, :countered_lesson, :canceling, :assigned_student
|
||||
attr_accessor :accepting, :creating, :countering, :autocanceling, :countered_slot, :countered_lesson, :canceling, :assigned_student
|
||||
|
||||
|
||||
@@log = Logging.logger[LessonSession]
|
||||
|
|
@ -22,27 +22,29 @@ module JamRuby
|
|||
STATUS_APPROVED = 'approved'
|
||||
STATUS_SUSPENDED = 'suspended'
|
||||
STATUS_COUNTERED = 'countered'
|
||||
STATUS_UNCONFIRMED = 'unconfirmed'
|
||||
|
||||
STATUS_TYPES = [STATUS_REQUESTED, STATUS_CANCELED, STATUS_MISSED, STATUS_COMPLETED, STATUS_APPROVED, STATUS_SUSPENDED, STATUS_COUNTERED]
|
||||
STATUS_TYPES = [STATUS_REQUESTED, STATUS_CANCELED, STATUS_MISSED, STATUS_COMPLETED, STATUS_APPROVED, STATUS_SUSPENDED, STATUS_COUNTERED, STATUS_UNCONFIRMED]
|
||||
|
||||
LESSON_TYPE_SINGLE = 'paid'
|
||||
LESSON_TYPE_SINGLE_FREE = 'single-free'
|
||||
LESSON_TYPE_TEST_DRIVE = 'test-drive'
|
||||
LESSON_TYPES = [LESSON_TYPE_SINGLE, LESSON_TYPE_SINGLE_FREE, LESSON_TYPE_TEST_DRIVE]
|
||||
|
||||
has_one :music_session, class_name: "JamRuby::MusicSession", :dependent => :destroy
|
||||
belongs_to :teacher, class_name: "JamRuby::User", foreign_key: :teacher_id, inverse_of: :taught_lessons
|
||||
belongs_to :canceler, class_name: "JamRuby::User", foreign_key: :canceler_id
|
||||
belongs_to :lesson_package_purchase, class_name: "JamRuby::LessonPackagePurchase"
|
||||
belongs_to :lesson_booking, class_name: "JamRuby::LessonBooking"
|
||||
belongs_to :user, class_name: "JamRuby::User"
|
||||
belongs_to :slot, class_name: "JamRuby::LessonBookingSlot", foreign_key: :slot_id, :dependent => :destroy
|
||||
belongs_to :lesson_payment_charge, class_name: "JamRuby::LessonPaymentCharge", foreign_key: :charge_id
|
||||
belongs_to :counter_slot, class_name: "JamRuby::LessonBookingSlot", foreign_key: :counter_slot_id, inverse_of: :countered_lesson, :dependent => :destroy
|
||||
has_one :teacher_distribution, class_name: "JamRuby::TeacherDistribution"
|
||||
has_many :lesson_booking_slots, class_name: "JamRuby::LessonBookingSlot"
|
||||
has_many :notifications, :class_name => "JamRuby::Notification", :foreign_key => "lesson_session_id"
|
||||
has_many :chat_messages, :class_name => "JamRuby::ChatMessage", :foreign_key => "lesson_session_id"
|
||||
has_one :music_session, class_name: "JamRuby::MusicSession", :dependent => :destroy
|
||||
belongs_to :teacher, class_name: "JamRuby::User", foreign_key: :teacher_id, inverse_of: :taught_lessons
|
||||
belongs_to :canceler, class_name: "JamRuby::User", foreign_key: :canceler_id
|
||||
belongs_to :counterer, class_name: "JamRuby::User", foreign_key: :counterer_id
|
||||
belongs_to :lesson_package_purchase, class_name: "JamRuby::LessonPackagePurchase"
|
||||
belongs_to :lesson_booking, class_name: "JamRuby::LessonBooking"
|
||||
belongs_to :user, class_name: "JamRuby::User"
|
||||
belongs_to :slot, class_name: "JamRuby::LessonBookingSlot", foreign_key: :slot_id, :dependent => :destroy
|
||||
belongs_to :lesson_payment_charge, class_name: "JamRuby::LessonPaymentCharge", foreign_key: :charge_id
|
||||
belongs_to :counter_slot, class_name: "JamRuby::LessonBookingSlot", foreign_key: :counter_slot_id, inverse_of: :countered_lesson, :dependent => :destroy
|
||||
has_one :teacher_distribution, class_name: "JamRuby::TeacherDistribution"
|
||||
has_many :lesson_booking_slots, class_name: "JamRuby::LessonBookingSlot"
|
||||
has_many :notifications, :class_name => "JamRuby::Notification", :foreign_key => "lesson_session_id"
|
||||
has_many :chat_messages, :class_name => "JamRuby::ChatMessage", :foreign_key => "lesson_session_id"
|
||||
|
||||
|
||||
validates :duration, presence: true, numericality: {only_integer: true}
|
||||
|
|
@ -61,6 +63,7 @@ module JamRuby
|
|||
validate :validate_creating, :if => :creating
|
||||
validate :validate_accepted, :if => :accepting
|
||||
validate :validate_canceled, :if => :canceling
|
||||
validate :validate_autocancel, :if => :autocanceling
|
||||
|
||||
after_save :after_counter, :if => :countering
|
||||
after_save :manage_slot_changes
|
||||
|
|
@ -74,7 +77,13 @@ module JamRuby
|
|||
scope :missed, -> { where(status: STATUS_MISSED) }
|
||||
scope :upcoming, -> { joins(:music_session).where('music_sessions.scheduled_start > ?', Time.now) }
|
||||
scope :past_cancel_window, -> { joins(:music_session).where('music_sessions.scheduled_start > ?', 24.hours.from_now) }
|
||||
|
||||
# show all requested/countered sessions where the student was the last to communicate
|
||||
scope :slow_responses, -> {joins(:lesson_booking).where('lesson_sessions.status = ? OR lesson_sessions.status = ?', LessonSession::STATUS_REQUESTED, LessonSession::STATUS_COUNTERED)
|
||||
.where('lesson_bookings.counterer_id IS NULL OR lesson_bookings.user_id = lesson_bookings.counterer_id')
|
||||
.order('(COALESCE(lesson_bookings.countered_at, lesson_bookings.sent_notices_at)) ASC')}
|
||||
scope :least_time_left, -> {joins(:lesson_booking, :music_session).where('lesson_sessions.status = ? OR lesson_sessions.status = ?', LessonSession::STATUS_REQUESTED, LessonSession::STATUS_COUNTERED)
|
||||
.where('lesson_bookings.counterer_id IS NULL OR lesson_bookings.user_id = lesson_bookings.counterer_id')
|
||||
.order('music_sessions.scheduled_start DESC')}
|
||||
def create_charge
|
||||
if !school_on_school? && !is_test_drive? && !is_monthly_payment?
|
||||
self.lesson_payment_charge = LessonPaymentCharge.new
|
||||
|
|
@ -107,30 +116,54 @@ module JamRuby
|
|||
end
|
||||
|
||||
def self.hourly_check
|
||||
auto_cancel
|
||||
analyse_sessions
|
||||
complete_sessions
|
||||
remind_counters
|
||||
end
|
||||
|
||||
def self.minutely_check
|
||||
upcoming_sessions_reminder
|
||||
end
|
||||
|
||||
def self.remind_counters
|
||||
MusicSession.joins(lesson_session: :lesson_booking)
|
||||
.where("lesson_bookings.sent_counter_reminder = false")
|
||||
.where('lesson_sessions.status = ? OR lesson_sessions.status = ?', LessonSession::STATUS_REQUESTED, LessonSession::STATUS_COUNTERED)
|
||||
.where("? > (COALESCE(lesson_bookings.countered_at, lesson_bookings.sent_notices_at)) + (INTERVAL '24 hours')", Time.now).each do |music_session|
|
||||
lesson_session = music_session.lesson_session
|
||||
if lesson_session.student_last_proposed?
|
||||
UserMailer.teacher_counter_reminder(lesson_session).deliver!
|
||||
else
|
||||
UserMailer.student_counter_reminder(lesson_session).deliver!
|
||||
end
|
||||
lesson_session.lesson_booking.sent_counter_reminder = true
|
||||
lesson_session.lesson_booking.save(validate: false)
|
||||
end
|
||||
end
|
||||
def self.auto_cancel
|
||||
MusicSession.joins(lesson_session: :lesson_booking).where('lesson_sessions.status = ?', LessonSession::STATUS_REQUESTED).where("? > scheduled_start + (INTERVAL '1 minutes' * (duration))", Time.now).each do |music_session|
|
||||
lesson_session = music_session.lesson_session
|
||||
lesson_session.autocancel
|
||||
end
|
||||
end
|
||||
|
||||
def self.analyse_sessions
|
||||
MusicSession.joins(lesson_session: :lesson_booking).where('lesson_sessions.status = ?', LessonSession::STATUS_APPROVED).where("NOW() > scheduled_start + (INTERVAL '1 minutes' * (duration))").where('analysed = false').each do |music_session|
|
||||
lession_session = music_session.lesson_session
|
||||
lession_session.analyse
|
||||
MusicSession.joins(lesson_session: :lesson_booking).where('lesson_sessions.status = ?', LessonSession::STATUS_APPROVED).where("? > scheduled_start + (INTERVAL '1 minutes' * (duration))", Time.now).where('analysed = false').each do |music_session|
|
||||
lesson_session = music_session.lesson_session
|
||||
lesson_session.analyse
|
||||
end
|
||||
end
|
||||
|
||||
def self.complete_sessions
|
||||
# this will find any paid session (recurring monthly paid, recurring single paid, single paid)
|
||||
MusicSession.joins(lesson_session: [:lesson_booking, :lesson_payment_charge]).where('lesson_sessions.status = ?', LessonSession::STATUS_COMPLETED).where("NOW() > scheduled_start + (INTERVAL '1 minutes' * (duration))").where('analysed = true').where('lesson_sessions.post_processed = false').where('billing_should_retry = true').each do |music_session|
|
||||
lession_session = music_session.lesson_session
|
||||
lession_session.session_completed
|
||||
MusicSession.joins(lesson_session: [:lesson_booking, :lesson_payment_charge]).where('lesson_sessions.status = ?', LessonSession::STATUS_COMPLETED).where("? > scheduled_start + (INTERVAL '1 minutes' * (duration))", Time.now).where('analysed = true').where('lesson_sessions.post_processed = false').where('billing_should_retry = true').each do |music_session|
|
||||
lesson_session = music_session.lesson_session
|
||||
lesson_session.session_completed
|
||||
end
|
||||
|
||||
# test drives don't have a lesson_payment_charge, so we don't join against them
|
||||
MusicSession.joins(lesson_session: [:lesson_booking]).where('lesson_sessions.status = ?', LessonSession::STATUS_COMPLETED).where('lesson_sessions.lesson_type = ?', LESSON_TYPE_TEST_DRIVE).where("session_removed_at IS NOT NULL OR NOW() > scheduled_start + (INTERVAL '1 minutes' * duration)").where('analysed = true').where('lesson_sessions.post_processed = false').each do |music_session|
|
||||
MusicSession.joins(lesson_session: [:lesson_booking]).where('lesson_sessions.status = ?', LessonSession::STATUS_COMPLETED).where('lesson_sessions.lesson_type = ?', LESSON_TYPE_TEST_DRIVE).where("session_removed_at IS NOT NULL OR ? > scheduled_start + (INTERVAL '1 minutes' * duration)", Time.now).where('analysed = true').where('lesson_sessions.post_processed = false').each do |music_session|
|
||||
lession_session = music_session.lesson_session
|
||||
lession_session.session_completed
|
||||
end
|
||||
|
|
@ -150,6 +183,10 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def student_last_proposed?
|
||||
counterer_id.nil? || counterer_id == student_id
|
||||
end
|
||||
|
||||
def analyse
|
||||
if self.analysed
|
||||
return
|
||||
|
|
@ -291,7 +328,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
else
|
||||
"because no error"
|
||||
"because no error"
|
||||
end
|
||||
else
|
||||
"not yet analysed"
|
||||
|
|
@ -468,7 +505,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
# if this is a single lesson (testdrive, paid), but the scheduled time is before now, then it's in the past, and we have to reject
|
||||
if !recurring && self.slot.scheduled_time(0) <= Time.now
|
||||
if !recurring && self.slot.scheduled_time(0) <= Time.now
|
||||
self.errors.add(:slot, "is in the past")
|
||||
end
|
||||
|
||||
|
|
@ -482,6 +519,18 @@ module JamRuby
|
|||
self.accepting = false
|
||||
end
|
||||
|
||||
def validate_autocancel
|
||||
|
||||
if scheduled_start + (duration * 60) > Time.now
|
||||
self.errors.add(:status, "This session is not in the past.")
|
||||
end
|
||||
|
||||
if self.status_was != STATUS_REQUESTED
|
||||
self.errors.add(:status, "This session is #{self.status_was} and can not be autocanceled")
|
||||
end
|
||||
|
||||
self.autocanceling = false
|
||||
end
|
||||
def validate_canceled
|
||||
if !is_canceled?
|
||||
self.errors.add(:status, "This session is already #{self.status}.")
|
||||
|
|
@ -714,6 +763,8 @@ module JamRuby
|
|||
slot.proposer = proposer
|
||||
slot.lesson_session = self
|
||||
slot.message = message
|
||||
self.counterer = proposer
|
||||
self.countered_at = Time.now
|
||||
self.lesson_booking_slots << slot
|
||||
self.countered_slot = slot
|
||||
self.countered_lesson = self
|
||||
|
|
@ -759,6 +810,28 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
# canceled by the system because it is requested, and the end time has gone by
|
||||
def autocancel
|
||||
response = self
|
||||
LessonSession.transaction do
|
||||
self.autocanceling = true
|
||||
self.status = LessonSession::STATUS_UNCONFIRMED
|
||||
if self.save
|
||||
if !lesson_booking.recurring
|
||||
response = lesson_booking.autocancel
|
||||
if response.errors.any?
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
end
|
||||
else
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
|
||||
msg = ChatMessage.create(teacher, nil, '', ChatMessage::CHANNEL_LESSON, nil, student, self, "Lesson Timeout")
|
||||
msg = ChatMessage.create(student, nil, '', ChatMessage::CHANNEL_LESSON, nil, teacher, self, "Lesson Timeout")
|
||||
end
|
||||
end
|
||||
|
||||
# teacher accepts the lesson
|
||||
def cancel(params)
|
||||
response = self
|
||||
|
|
@ -825,6 +898,30 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def display_type
|
||||
if is_test_drive?
|
||||
'TestDrive'
|
||||
elsif recurring
|
||||
'Recurring'
|
||||
else
|
||||
'Single'
|
||||
end
|
||||
end
|
||||
|
||||
def last_student_comm_date
|
||||
counterer_id == user_id ? countered_at : sent_notices_at
|
||||
end
|
||||
|
||||
def days_no_response
|
||||
date = last_student_comm_date
|
||||
if date.nil?
|
||||
'?'
|
||||
else
|
||||
(Time.now - last_student_comm_date) / (60 * 60 * 24)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
def stripe_description(lesson_booking)
|
||||
description(lesson_booking)
|
||||
|
|
|
|||
|
|
@ -396,7 +396,7 @@ module JamRuby
|
|||
}
|
||||
|
||||
authorization = user.user_authorizations.build(user_auth_hash)
|
||||
authorization.save
|
||||
authorization.save!
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -91,14 +91,14 @@ module JamRuby
|
|||
if payment.teacher_payment_charge.nil?
|
||||
charge = TeacherPaymentCharge.new
|
||||
charge.user = payment.payable_teacher
|
||||
charge.amount_in_cents = payment.amount_in_cents
|
||||
charge.amount_in_cents = (payment.amount_in_cents / (1 - APP_CONFIG.stripe[:ach_pct])).round
|
||||
charge.fee_in_cents = payment.fee_in_cents
|
||||
charge.teacher_payment = payment
|
||||
payment.teacher_payment_charge = charge
|
||||
# charge.save!
|
||||
else
|
||||
charge = payment.teacher_payment_charge
|
||||
charge.amount_in_cents = payment.amount_in_cents
|
||||
charge.amount_in_cents = (payment.amount_in_cents / (1 - APP_CONFIG.stripe[:ach_pct])).round
|
||||
charge.fee_in_cents = payment.fee_in_cents
|
||||
charge.save!
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,9 +10,130 @@ describe LessonSession do
|
|||
let(:lesson_booking) {b = LessonBooking.book_normal(user, teacher, [slot1, slot2], "Hey I've heard of you before.", false, LessonBooking::PAYMENT_STYLE_SINGLE, 60); b.card_presumed_ok = true; b.save!; b}
|
||||
let(:lesson_session) {lesson_booking.lesson_sessions[0]}
|
||||
|
||||
describe "accept" do
|
||||
it "can accept" do
|
||||
describe "autocancel" do
|
||||
it "can't autocancel in the past" do
|
||||
lesson_session.status.should eql LessonSession::STATUS_REQUESTED
|
||||
|
||||
lesson_session.autocancel
|
||||
lesson_session.reload
|
||||
lesson_session.status.should eql LessonSession::STATUS_REQUESTED
|
||||
lesson_session.lesson_booking.status.should eql LessonSession::STATUS_REQUESTED
|
||||
end
|
||||
|
||||
it "can't autocancel approved" do
|
||||
lesson_session = normal_lesson(user, teacher, {accept: true})
|
||||
lesson_session.status.should eql LessonSession::STATUS_APPROVED
|
||||
|
||||
lesson_session.autocancel
|
||||
lesson_session.reload
|
||||
lesson_session.status.should eql LessonSession::STATUS_APPROVED
|
||||
lesson_session.lesson_booking.status.should eql LessonSession::STATUS_APPROVED
|
||||
end
|
||||
|
||||
it "autocancel works" do
|
||||
lesson_session.status.should eql LessonSession::STATUS_REQUESTED
|
||||
|
||||
Timecop.travel(Date.today + 10)
|
||||
|
||||
lesson_session.autocancel
|
||||
lesson_session.reload
|
||||
lesson_session.status.should eql LessonSession::STATUS_UNCONFIRMED
|
||||
lesson_session.lesson_booking.status.should eql LessonSession::STATUS_UNCONFIRMED
|
||||
end
|
||||
|
||||
it "autocancel sweeper works" do
|
||||
lesson_session.status.should eql LessonSession::STATUS_REQUESTED
|
||||
|
||||
Timecop.travel(Date.today + 10)
|
||||
|
||||
LessonSession.auto_cancel
|
||||
lesson_session.reload
|
||||
lesson_session.lesson_booking.active.should be_false
|
||||
lesson_session.status.should eql LessonSession::STATUS_UNCONFIRMED
|
||||
lesson_session.lesson_booking.status.should eql LessonSession::STATUS_UNCONFIRMED
|
||||
end
|
||||
end
|
||||
|
||||
describe "slow_responses" do
|
||||
it "sorts correctly" do
|
||||
lesson_session1 = normal_lesson(user, teacher, {counter: true, counterer: user})
|
||||
lesson_session2 = normal_lesson(user, teacher, {counter: true, counterer: teacher}) # this shouldn't show up
|
||||
Timecop.travel(Date.today - 5)
|
||||
lesson_session3 = normal_lesson(user, teacher, {})
|
||||
|
||||
slow = LessonSession.unscoped.slow_responses
|
||||
slow.count.should eql 2
|
||||
slow[0].should eql lesson_session3
|
||||
slow[1].should eql lesson_session1
|
||||
end
|
||||
end
|
||||
describe "least_time_left" do
|
||||
it "sorts correctly" do
|
||||
lesson_session1 = normal_lesson(user, teacher, {counter: true, counterer: user})
|
||||
lesson_session2 = normal_lesson(user, teacher, {counter: true, counterer: teacher}) # this shouldn't show up
|
||||
Timecop.travel(Date.today - 5)
|
||||
lesson_session3 = normal_lesson(user, teacher, {})
|
||||
|
||||
slow = LessonSession.unscoped.least_time_left
|
||||
slow.count.should eql 2
|
||||
slow[0].should eql lesson_session1
|
||||
slow[1].should eql lesson_session3
|
||||
end
|
||||
end
|
||||
|
||||
describe "remind_counters" do
|
||||
it "finds old requested and pokes teacher" do
|
||||
lesson_session1 = normal_lesson(user, teacher, {})
|
||||
|
||||
mailer = mock
|
||||
mailer.should_receive(:deliver!)
|
||||
UserMailer.should_receive(:teacher_counter_reminder).and_return(mailer)
|
||||
|
||||
LessonSession.remind_counters
|
||||
lesson_session1.reload
|
||||
lesson_session1.lesson_booking.sent_counter_reminder.should be_false
|
||||
|
||||
Timecop.travel(Date.today + 10)
|
||||
|
||||
LessonSession.remind_counters
|
||||
lesson_session1.reload
|
||||
lesson_session1.lesson_booking.sent_counter_reminder.should be_true
|
||||
end
|
||||
|
||||
it "finds old counter and pokes teacher" do
|
||||
lesson_session1 = normal_lesson(user, teacher, {counter: true, counterer: user})
|
||||
|
||||
mailer = mock
|
||||
mailer.should_receive(:deliver!)
|
||||
UserMailer.should_receive(:teacher_counter_reminder).and_return(mailer)
|
||||
|
||||
LessonSession.remind_counters
|
||||
lesson_session1.reload
|
||||
lesson_session1.lesson_booking.sent_counter_reminder.should be_false
|
||||
|
||||
Timecop.travel(Date.today + 10)
|
||||
|
||||
LessonSession.remind_counters
|
||||
lesson_session1.reload
|
||||
lesson_session1.lesson_booking.sent_counter_reminder.should be_true
|
||||
end
|
||||
|
||||
it "finds old counter and pokes teacher" do
|
||||
lesson_session1 = normal_lesson(user, teacher, {counter: true, counterer: teacher})
|
||||
|
||||
mailer = mock
|
||||
mailer.should_receive(:deliver!)
|
||||
UserMailer.should_receive(:student_counter_reminder).and_return(mailer)
|
||||
|
||||
LessonSession.remind_counters
|
||||
lesson_session1.reload
|
||||
lesson_session1.lesson_booking.sent_counter_reminder.should be_false
|
||||
|
||||
Timecop.travel(Date.today + 10)
|
||||
|
||||
LessonSession.remind_counters
|
||||
lesson_session1.reload
|
||||
lesson_session1.lesson_booking.sent_counter_reminder.should be_true
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -4,235 +4,152 @@ 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)}
|
||||
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
|
||||
|
||||
it "empty" do
|
||||
TeacherPayment.pending_teacher_payments.count.should eql 0
|
||||
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
|
||||
|
||||
it "one distribution" do
|
||||
test_drive_distribution.touch
|
||||
describe "school teachers" do
|
||||
before(:each) do
|
||||
teacher_obj.touch
|
||||
teacher.teacher.stripe_account_id = stripe_account1_id
|
||||
end
|
||||
|
||||
payments = TeacherPayment.pending_teacher_payments
|
||||
payments.count.should eql 0
|
||||
it "school distribution" do
|
||||
|
||||
test_drive_distribution.ready = true
|
||||
test_drive_distribution.save!
|
||||
test_drive_distribution.school = school
|
||||
test_drive_distribution.save!
|
||||
|
||||
payments = TeacherPayment.pending_teacher_payments
|
||||
payments.count.should eql 1
|
||||
payments[0]['id'].should eql teacher.id
|
||||
end
|
||||
payments = TeacherPayment.pending_teacher_payments
|
||||
payments.count.should eql 0
|
||||
|
||||
it "school distribution" do
|
||||
test_drive_distribution.school = school
|
||||
test_drive_distribution.save!
|
||||
test_drive_distribution.ready = true
|
||||
test_drive_distribution.save!
|
||||
|
||||
payments = TeacherPayment.pending_teacher_payments
|
||||
payments.count.should eql 0
|
||||
payments = TeacherPayment.pending_teacher_payments
|
||||
payments.count.should eql 1
|
||||
payments[0]['id'].should eql teacher.id
|
||||
end
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
# 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
|
||||
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
|
||||
it "empty" do
|
||||
TeacherPayment.teacher_payments
|
||||
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!
|
||||
it "charges test drive" do
|
||||
test_drive_distribution.touch
|
||||
|
||||
TeacherPayment.teacher_payments
|
||||
test_drive_distribution.ready = true
|
||||
test_drive_distribution.save!
|
||||
|
||||
normal_distribution.reload
|
||||
normal_distribution.teacher_payment.should_not be_nil
|
||||
TeacherPayment.count.should eql 2
|
||||
TeacherPayment.teacher_payments
|
||||
|
||||
payment = normal_distribution.teacher_payment
|
||||
test_drive_distribution.reload
|
||||
test_drive_distribution.teacher_payment.should_not be_nil
|
||||
TeacherPayment.count.should eql 1
|
||||
|
||||
if payment.teacher_payment_charge.billing_error_reason
|
||||
puts payment.teacher_payment_charge.billing_error_reason
|
||||
puts payment.teacher_payment_charge.billing_error_detail
|
||||
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
|
||||
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)
|
||||
|
||||
it "charges normal" do
|
||||
normal_distribution.touch
|
||||
|
||||
normal_distribution.ready = true
|
||||
normal_distribution.save!
|
||||
UserMailer.deliveries.clear
|
||||
|
||||
TeacherPayment.teacher_payments
|
||||
|
||||
|
|
@ -242,134 +159,26 @@ describe TeacherPayment do
|
|||
|
||||
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")
|
||||
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 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
|
||||
# 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.amount_in_cents.should eql (1000 + 1000 * 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
|
||||
charge.amount.should eql (1000 + 1000 * APP_CONFIG.stripe[:ach_pct]).round
|
||||
charge.application_fee.should include("fee_")
|
||||
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)
|
||||
|
||||
it "charges multiple" do
|
||||
test_drive_distribution.touch
|
||||
test_drive_distribution.ready = true
|
||||
test_drive_distribution.save!
|
||||
|
|
@ -379,40 +188,302 @@ describe TeacherPayment do
|
|||
|
||||
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
|
||||
|
||||
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.amount_in_cents.should eql (1000 + 1000 * 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
|
||||
charge.amount.should eql (1000 + 1000 * APP_CONFIG.stripe[:ach_pct]).round
|
||||
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.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
|
||||
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 + 1000 * APP_CONFIG.stripe[:ach_pct]).round
|
||||
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 1008
|
||||
charge.application_fee.should include("fee_")
|
||||
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 + 1000 * 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 + 1000 * 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 + 1000 * 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 1008
|
||||
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 + 1000 * 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 + 1000 * 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 + 1000 * 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 + 1000 * 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 + 1000 * 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 1008
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,15 @@ describe "RenderMailers", :slow => true do
|
|||
UserMailer.teacher_welcome_message(teacher).deliver
|
||||
end
|
||||
|
||||
it "teacher_counter_reminder" do
|
||||
@filename = "teacher_counter_reminder"
|
||||
|
||||
lesson_session = testdrive_lesson(user, teacher)
|
||||
|
||||
UserMailer.deliveries.clear
|
||||
UserMailer.teacher_counter_reminder(lesson_session).deliver
|
||||
end
|
||||
|
||||
it "teacher_lesson_request" do
|
||||
@filename = "teacher_lesson_request"
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,17 @@ def book_lesson(user, teacher, options)
|
|||
end
|
||||
end
|
||||
|
||||
if options[:counter]
|
||||
if options[:monthly]
|
||||
counter_slot = FactoryGirl.build(:lesson_booking_slot_recurring)
|
||||
else
|
||||
counter_slot = FactoryGirl.build(:lesson_booking_slot_single)
|
||||
end
|
||||
|
||||
lesson.counter({proposer: options[:counterer] || user, message: "countered YEAH!", slot: counter_slot})
|
||||
lesson.reload
|
||||
lesson.status.should eql LessonSession::STATUS_COUNTERED
|
||||
end
|
||||
|
||||
if options[:accept]
|
||||
lesson.accept({message: 'Yeah I got this', slot: slots[0]})
|
||||
|
|
|
|||
|
|
@ -301,7 +301,8 @@ def app_config
|
|||
{
|
||||
:publishable_key => 'pk_test_HLTvioRAxN3hr5fNfrztZeoX',
|
||||
:secret_key => 'sk_test_OkjoIF7FmdjunyNsdVqJD02D',
|
||||
:source_customer => 'cus_88Vp44SLnBWMXq' # seth@jamkazam.com in JamKazam-test account
|
||||
:source_customer => 'cus_88Vp44SLnBWMXq', # seth@jamkazam.com in JamKazam-test account
|
||||
:ach_pct => 0.008
|
||||
}
|
||||
end
|
||||
private
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ ChatActions = @ChatActions
|
|||
when 'Notation File' then 'attached a notation file'
|
||||
when 'Audio File' then 'attached an audio file'
|
||||
when 'JamKazam Recording' then 'attached a recording'
|
||||
when 'Lesson Timeout' then 'canceled by system'
|
||||
else purpose
|
||||
|
||||
notationClicked: (music_notation, e) ->
|
||||
|
|
|
|||
|
|
@ -35,7 +35,9 @@ teacherActions = window.JK.Actions.Teacher
|
|||
lesson.displayStatus = 'Scheduled'
|
||||
|
||||
if !lesson.displayStatus?
|
||||
if lesson.status == 'canceled'
|
||||
if lesson.status == 'unconfirmed'
|
||||
lesson.displayStatus = 'Unconfirmed'
|
||||
else if lesson.status == 'canceled'
|
||||
lesson.displayStatus = 'Canceled'
|
||||
if lesson.student_canceled
|
||||
lesson.displayStatus = 'Canceled (Student)'
|
||||
|
|
|
|||
|
|
@ -426,7 +426,8 @@ if defined?(Bundler)
|
|||
config.stripe = {
|
||||
:publishable_key => 'pk_test_9vO8ZnxBpb9Udb0paruV3qLv',
|
||||
:secret_key => 'sk_test_cPVRbtr9xbMiqffV8jwibwLA',
|
||||
:client_id => 'ca_8CgkjoHvfRMVqoQkcKdPt5Riy3dSPIlg'
|
||||
:client_id => 'ca_8CgkjoHvfRMVqoQkcKdPt5Riy3dSPIlg',
|
||||
:ach_pct => 0.008
|
||||
}
|
||||
|
||||
config.test_drive_wait_period_year = 1
|
||||
|
|
|
|||
|
|
@ -139,7 +139,8 @@ def web_config
|
|||
{
|
||||
:publishable_key => 'pk_test_HLTvioRAxN3hr5fNfrztZeoX',
|
||||
:secret_key => 'sk_test_OkjoIF7FmdjunyNsdVqJD02D',
|
||||
:source_customer => 'cus_88Vp44SLnBWMXq' # seth@jamkazam.com in JamKazam-test account
|
||||
:source_customer => 'cus_88Vp44SLnBWMXq', # seth@jamkazam.com in JamKazam-test account
|
||||
:ach_pct => 0.008
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -146,6 +146,17 @@ def book_lesson(user, teacher, options)
|
|||
end
|
||||
end
|
||||
|
||||
if options[:counter]
|
||||
if options[:monthly]
|
||||
counter_slot = FactoryGirl.build(:lesson_booking_slot_recurring)
|
||||
else
|
||||
counter_slot = FactoryGirl.build(:lesson_booking_slot_single)
|
||||
end
|
||||
|
||||
lesson.counter({proposer: user, message: "countered YEAH!", slot: counter_slot})
|
||||
lesson.reload
|
||||
lesson.status.should eql LessonSession::STATUS_COUNTERED
|
||||
end
|
||||
|
||||
if options[:accept]
|
||||
lesson.accept({message: 'Yeah I got this', slot: slots[0]})
|
||||
|
|
|
|||
Loading…
Reference in New Issue