amazon readiness complete

This commit is contained in:
Seth Call 2017-07-16 19:38:40 -05:00
parent 7f18c6b056
commit 41e1ef7083
33 changed files with 740 additions and 256 deletions

View File

@ -16,7 +16,7 @@ ALTER TABLE posa_cards ADD COLUMN preactivate BOOLEAN NOT NULL DEFAULT FALSE;
ALTER TABLE posa_cards ADD COLUMN requires_purchase BOOLEAN NOT NULL DEFAULT FALSE;
ALTER TABLE posa_cards ADD COLUMN purchased BOOLEAN NOT NULL DEFAULT TRUE;
ALTER TABLE lesson_bookings ADD COLUMN posa_card_purchased BOOLEAN NOT NULL DEFAULT TRUE;
ALTER TABLE lesson_bookings ADD COLUMN posa_card_purchased BOOLEAN NOT NULL DEFAULT FALSE;
update posa_cards set credits = 5 where card_type = 'jam_tracks_5';
update posa_cards set credits = 10 where card_type = 'jam_tracks_10';
@ -36,3 +36,11 @@ ALTER TABLE lesson_bookings ADD COLUMN remaining_roll_forward_amount_in_cents IN
ALTER TABLE users ADD COLUMN lesson_package_needs_purchase_id VARCHAR(64) REFERENCES lesson_package_types(id) ON DELETE SET NULL;
ALTER TABLE lesson_sessions ADD COLUMN sent_counter_reminder BOOLEAN NOT NULL DEFAULT FALSE;
ALTER TABLE lesson_bookings ADD COLUMN student_canceled BOOLEAN DEFAULT FALSE NOT NULL;
ALTER TABLE lesson_bookings ADD COLUMN teacher_canceled BOOLEAN DEFAULT FALSE NOT NULL;
ALTER TABLE lesson_bookings ADD COLUMN student_canceled_at TIMESTAMP;
ALTER TABLE lesson_bookings ADD COLUMN teacher_canceled_at TIMESTAMP;
ALTER TABLE lesson_bookings ADD COLUMN teacher_canceled_reason VARCHAR;
ALTER TABLE lesson_bookings ADD COLUMN student_canceled_reason VARCHAR;

View File

@ -1011,6 +1011,48 @@ module JamRuby
end
end
def student_lesson_counter_recurring(lesson_booking, slot)
@user = lesson_booking.student
email = lesson_booking.student.email
subject = "Instructor has proposed a different time for all lessons"
unique_args = {:type => "student_lesson_counter_recurring"}
@student = lesson_booking.student
@teacher = lesson_booking.teacher
@lesson_booking = lesson_booking
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
def teacher_lesson_counter_recurring(lesson_booking, slot)
@user = lesson_booking.teacher
email = lesson_booking.school_over_teacher
subject = "Student has proposed a different time for all lessons"
unique_args = {:type => "teacher_lesson_counter"}
@student = lesson_booking.student
@teacher = lesson_booking.teacher
@lesson_booking = lesson_booking
sendgrid_category "Notification"
sendgrid_unique_args :type => unique_args[:type]
sendgrid_recipients(email)
sendgrid_substitute('@USERID', lesson_booking.school_over_teacher_ids)
mail(:to => email, :subject => subject) do |format|
format.text
format.html { render :layout => "from_user_mailer" }
end
end
def teacher_lesson_completed(lesson_session)
@student = lesson_session.student
@teacher = lesson_session.teacher

View File

@ -5,7 +5,7 @@
<p>
<% if @lesson_booking.recurring %>
All lessons that were scheduled for <%= @lesson_booking.dayWeekDesc %> with <%= @teacher.name %> have been canceled.
All lessons that were <%= @lesson_booking.ever_accepted? ? 'scheduled' : 'requested' %> for <%= @lesson_booking.dayWeekDesc %> with <%= @teacher.name %> have been canceled.
<% else %>
Your lesson with <%= @teacher.name %> has been canceled.<br/><br/>

View File

@ -0,0 +1,17 @@
<% provide(:title, "#{@teacher.name} has proposed a different time for your weekly lessons") %>
<% provide(:photo_url, @teacher.resolved_photo_url) %>
<% content_for :note do %>
<p>
<%= @teacher.name %> has proposed a different time for your weekly lessons.
<br/>
<br/>
Click the button below to get more information and respond.
</p>
<p>
<a href="<%= @lesson_booking.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 %>

View File

@ -0,0 +1,3 @@
<%= @teacher.name %> has proposed a different time for your weekly lessons.
To see this request, click here: <%= @lesson_booking.web_url %>

View File

@ -5,7 +5,7 @@
<p>
<% if @lesson_booking.recurring %>
All lessons that were scheduled for <%= @lesson_booking.dayWeekDesc %> with <%= @student.name %> have been canceled.
All lessons that were <%= @lesson_booking.ever_accepted? ? 'scheduled' : 'requested' %> for <%= @lesson_booking.dayWeekDesc %> with <%= @student.name %> have been canceled.
<% else %>
Your lesson with <%= @student.name %> has been canceled.<br/><br/>

View File

@ -0,0 +1,17 @@
<% provide(:title, "#{@student.name} has proposed a different time for their weekly lessons") %>
<% provide(:photo_url, @student.resolved_photo_url) %>
<% content_for :note do %>
<p>
<%= @student.name %> has proposed a different time for their weekly lessons.
<br/>
<br/>
Click the button below to get more information and respond.
</p>
<p>
<a href="<%= @lesson_booking.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 %>

View File

@ -0,0 +1,3 @@
<%= @student.name %> has proposed a different time for their weekly lessons.
To see this request, click here: <%= @lesson_booking.web_url %>

View File

@ -143,6 +143,18 @@ module JamRuby
booked_price
end
def is_countered?
has_recurring_counter?
end
def has_recurring_counter?
!!self.counter_slot && self.counter_slot.is_recurring?
end
def ever_accepted?
!!self.accepter
end
def no_slots
default_slot.from_package
end
@ -180,31 +192,53 @@ module JamRuby
end
self.active = true
self.status = STATUS_APPROVED
self.counter_slot = nil
self.default_slot = slot
self.accepter = accepter
if slot.is_recurring?
if self.recurring
self.counter_slot = nil
self.status = STATUS_APPROVED
self.default_slot = slot
self.accepter = accepter
else
# should never happen because u shouldn't be able to set a recurring slot on a single lesson
end
else
self.status = STATUS_APPROVED
self.default_slot = slot
self.accepter = accepter
end
success = self.save
if !success
#puts "unable to accept lesson booking #{errors.inspect}"
end
puts "unable to accept lesson booking #{errors.inspect}"
else
# ok, now we have to update the slots of our lesson_sessions
self.lesson_sessions.each do |lesson_session|
if !lesson_session.is_countered?
lesson_session.slot = slot
lesson_session.save
end
end
end
success
end
def counter(lesson_session, proposer, slot)
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
if slot.is_recurring?
self.lesson_booking_slots << slot
self.countering = true
self.counter_slot = slot
self.counterer = proposer
self.countered_at = Time.now
self.sent_counter_reminder = false
self.status = STATUS_COUNTERED
end
if self.default_slot.from_package
self.default_slot = slot
end
#self.status = STATUS_COUNTERED
self.save
end
@ -438,7 +472,7 @@ module JamRuby
def validate_accepted
# accept is multipe purpose; either accept the initial request, or a counter slot
if self.status_was != STATUS_REQUESTED && counter_slot.nil? # && self.status_was != STATUS_COUNTERED
if self.status_was != STATUS_REQUESTED && self.status_was != STATUS_COUNTERED
self.errors.add(:status, "This lesson is already #{self.status}.")
end
@ -679,10 +713,18 @@ module JamRuby
am_pm = 'am'
end
"#{day} at #{hour}:#{slot.minute}#{am_pm}"
"#{day} at #{hour}:#{slot.minute.to_s.rjust(2, "0")}#{am_pm}"
end
def status_as_verb
if is_requested?
'requested'
else
'scheduled'
end
end
def approved_before?
!self.accepter_id.nil?
end
@ -695,16 +737,32 @@ module JamRuby
self
end
def cancel(canceler, other, message)
self.canceling = true
self.active = false
def cancel_tracking(canceler, message)
canceled_by_student = canceler == student
self.status = STATUS_CANCELED
self.cancel_message = message
self.canceler = canceler
self.canceling = true
if canceled_by_student
self.student_canceled = true
self.student_canceled_at = Time.now
self.student_canceled_reason = message
else
self.teacher_canceled = true
self.teacher_canceled_at = Time.now
self.teacher_canceled_reason = message
end
end
def cancel(canceler, other, message)
cancel_tracking(canceler, message)
self.active = false
success = save
if success
lesson_sessions.past_cancel_window.each do |lesson_session|
lesson_sessions.upcoming.each do |lesson_session|
lesson_session = LessonSession.find(lesson_session.id) # because .upcoming creates ReadOnly records
lesson_session.cancel_lesson(canceler, message)
if !lesson_session.save

View File

@ -11,7 +11,7 @@ module JamRuby
@@log = Logging.logger[LessonSession]
delegate :sent_billing_notices, :last_billing_attempt_at, :billing_attempts, :billing_should_retry, :billed_at, :billing_error_detail, :billing_error_reason, :is_card_declined?, :is_card_expired?, :last_billed_at_date, :sent_billing_notices, to: :lesson_payment_charge, allow_nil: true
delegate :is_test_drive?, :is_single_free?, :is_normal?, :approved_before?, :is_active?, :recurring, :is_monthly_payment?, :school_on_school?, :school_on_school_payment?, :no_school_on_school_payment?, :payment_if_school_on_school?, :scheduling_email, :teacher_school_emails, :school_and_teacher, :school_over_teacher, :school_and_teacher_ids, :school_over_teacher_ids, :posa_card, :remaining_roll_forward_amount_in_cents, to: :lesson_booking
delegate :is_test_drive?, :is_single_free?, :is_normal?, :approved_before?, :is_active?, :recurring, :is_monthly_payment?, :school_on_school?, :school_on_school_payment?, :no_school_on_school_payment?, :payment_if_school_on_school?, :scheduling_email, :teacher_school_emails, :school_and_teacher, :school_over_teacher, :school_and_teacher_ids, :school_over_teacher_ids, :posa_card, :remaining_roll_forward_amount_in_cents, :has_recurring_counter?, :ever_accepted?, to: :lesson_booking
delegate :pretty_scheduled_start, to: :music_session
@ -79,10 +79,10 @@ module JamRuby
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') }
.where('lesson_sessions.counterer_id IS NULL OR lesson_sessions.user_id = lesson_sessions.counterer_id')
.order('(COALESCE(lesson_sessions.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')
.where('lesson_sessions.counterer_id IS NULL OR lesson_sessions.user_id = lesson_sessions.counterer_id')
.order('music_sessions.scheduled_start DESC') }
def create_charge
@ -133,6 +133,7 @@ module JamRuby
analyse_sessions
complete_sessions
remind_counters
remind_counters_recurring
end
def self.minutely_check
@ -141,9 +142,24 @@ module JamRuby
def self.remind_counters
MusicSession.joins(lesson_session: :lesson_booking)
.where("lesson_bookings.sent_counter_reminder = false")
.where('lesson_sessions.sent_counter_reminder = false AND lesson_bookings.recurring = 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|
.where("? > (COALESCE(lesson_sessions.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_now
else
UserMailer.student_counter_reminder(lesson_session).deliver_now
end
lesson_session.sent_counter_reminder = true
lesson_session.save(validate: false)
end
end
def self.remind_counters_recurring
MusicSession.joins(lesson_session: :lesson_booking)
.where("lesson_bookings.status = ? AND lesson_bookings.sent_counter_reminder = false AND lesson_bookings.recurring = TRUE",LessonBooking::STATUS_COUNTERED)
.where("? > (COALESCE(lesson_sessions.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_now
@ -156,14 +172,14 @@ module JamRuby
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|
MusicSession.joins(lesson_session: :lesson_booking).where('lesson_sessions.status = ? OR lesson_bookings.status = ?', LessonSession::STATUS_REQUESTED, LessonBooking::STATUS_COUNTERED).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("? > scheduled_start + (INTERVAL '1 minutes' * (duration))", Time.now).where('analysed = false').each do |music_session|
MusicSession.joins(lesson_session: :lesson_booking).where('lesson_sessions.status = ? AND lesson_bookings.status != ?', LessonSession::STATUS_APPROVED, LessonBooking::STATUS_COUNTERED).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
@ -497,7 +513,7 @@ module JamRuby
end
def send_counter(countered_lesson, countered_slot)
def send_counter_for_lesson(countered_lesson, countered_slot)
if !lesson_booking.errors.any?
if countered_slot.is_teacher_created?
UserMailer.student_lesson_counter(countered_lesson, countered_slot).deliver_now
@ -508,6 +524,17 @@ module JamRuby
self.countering = false
end
def send_counter_for_lesson_recurring(countered_booking, countered_slot)
if !countered_booking.errors.any?
if countered_slot.is_teacher_created?
UserMailer.student_lesson_counter_recurring(countered_booking, countered_slot).deliver_now
else
UserMailer.teacher_lesson_counter_recurring(countered_booking, countered_slot).deliver_now
end
end
self.countering = false
end
default_scope { order('lesson_sessions.created_at') }
def is_requested?
@ -571,7 +598,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 !slot.is_recurring? && self.slot.scheduled_time(0) <= duration.minutes.ago # let someone accept a very late meeting so that they can just hope in the session and do it
self.errors.add(:slot, "is in the past")
end
@ -591,8 +618,8 @@ module JamRuby
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")
if self.status_was != STATUS_REQUESTED && !self.lesson_booking.is_countered?
self.errors.add(:status, "This session is #{self.status_was}/booking=#{lesson_booking.status} and can not be autocanceled")
end
self.autocanceling = false
@ -604,7 +631,8 @@ module JamRuby
end
# check 24 hour window
if scheduled_start.to_i - Time.now.to_i < 24 * 60 * 60
if ever_accepted? && !student_short_canceled && !teacher_short_canceled && scheduled_start.to_i - Time.now.to_i < 24 * 60 * 60
self.errors.add(:base, "This session is due to start within 24 hours and can not be canceled.")
end
@ -776,11 +804,23 @@ module JamRuby
slot = params[:slot]
accepter = params[:accepter]
raise "LessonBookingSlot" if slot.is_a?(LessonBookingSlot)
self.slot = slot = LessonBookingSlot.find(slot)
slot = LessonBookingSlot.find(slot)
self.slot.accept_message = message
self.slot.save!
self.accepting = true
self.status = STATUS_APPROVED
self.slot.save
if !slot.is_recurring?
self.slot = slot
self.accepting = true
self.status = STATUS_APPROVED
end
if slot.is_recurring? && !approved_before?
# we need to approve the lessons, cuz the booking is going to be approved too with this.
#self.slot = slot
self.accepting = true
self.status = STATUS_APPROVED
end
if !approved_before?
# 1st time this has ever been approved; there are other things we need to do
@ -817,7 +857,7 @@ module JamRuby
# this implies a new slot has been countered, and now approved
if self.save
if slot.update_all
if slot.is_recurring?
if !lesson_booking.accept(self, slot, accepter)
response = lesson_booking
raise ActiveRecord::Rollback
@ -859,20 +899,24 @@ module JamRuby
slot = params[:slot]
message = params[:message]
update_all = slot.update_all || !lesson_booking.recurring
self.countering = true
self.countering_flag = true
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
self.status = STATUS_COUNTERED
#if !update_all
self.counter_slot = slot
if !slot.is_recurring?
self.countering = true
self.countering_flag = true
self.counterer = proposer
self.countered_at = Time.now
self.lesson_booking_slots << slot
self.countered_lesson = self
self.status = STATUS_COUNTERED
self.sent_counter_reminder = false
#if !update_all
self.counter_slot = slot
self.countered_slot = slot
end
#end
if self.save
#if update_all && !lesson_booking.counter(self, proposer, slot)
@ -885,10 +929,19 @@ module JamRuby
raise ActiveRecord::Rollback
end
send_counter(@countered_lesson, @countered_slot)
message = '' if message.nil?
msg = ChatMessage.create(slot.proposer, music_session, message, ChatMessage::CHANNEL_LESSON, nil, slot.recipient, self, "New Time Proposed")
Notification.send_lesson_message('counter', self, slot.is_teacher_created?)
if slot.is_recurring?
send_counter_for_lesson_recurring(lesson_booking, lesson_booking.counter_slot)
message = '' if message.nil?
msg = ChatMessage.create(slot.proposer, music_session, message, ChatMessage::CHANNEL_LESSON, nil, slot.recipient, self, "New Time Proposed")
Notification.send_lesson_message('counter', self, slot.is_teacher_created?)
else
send_counter_for_lesson(@countered_lesson, @countered_slot)
message = '' if message.nil?
msg = ChatMessage.create(slot.proposer, music_session, message, ChatMessage::CHANNEL_LESSON, nil, slot.recipient, self, "New Time Proposed")
Notification.send_lesson_message('counter', self, slot.is_teacher_created?)
end
end
response
@ -896,6 +949,7 @@ module JamRuby
def cancel_lesson(canceler, message)
canceled_by_student = canceler == student
self.status = STATUS_CANCELED
self.cancel_message = message
self.canceler = canceler
@ -905,15 +959,20 @@ module JamRuby
self.student_canceled = true
self.student_canceled_at = Time.now
self.student_canceled_reason = message
self.student_short_canceled = 24.hours.from_now > scheduled_start
self.student_short_canceled = in_no_cancel_window && ever_accepted?
else
self.teacher_canceled = true
self.teacher_canceled_at = Time.now
self.teacher_canceled_reason = message
self.teacher_short_canceled = 24.hours.from_now > scheduled_start
self.teacher_short_canceled = in_no_cancel_window && ever_accepted?
end
end
def in_no_cancel_window
Time.now > scheduled_start - 24.hours
end
# canceled by the system because it is requested, and the end time has gone by
def autocancel
response = self
@ -928,6 +987,7 @@ module JamRuby
end
end
else
@@log.error("unable to autocancel lesson #{self.id} #{self.errors.inspect}")
raise ActiveRecord::Rollback
end

View File

@ -100,7 +100,7 @@ describe "Monthly Recurring Lesson Flow" do
lesson_session.counter({proposer: user, slot: student_countered_slot, message: 'Does this work better?'})
lesson_session.errors.any?.should be false
lesson_session.lesson_booking.errors.any?.should be false
lesson_session.lesson_booking_slots.length.should eql 2
#lesson_session.lesson_booking_slots.length.should eql 2
student_counter = booking.lesson_booking_slots.order(:created_at).last
student_counter.proposer.should eql user
booking.reload
@ -373,7 +373,7 @@ describe "Monthly Recurring Lesson Flow" do
lesson_session.counter({proposer: user, slot: student_countered_slot, message: 'Does this work better?'})
lesson_session.errors.any?.should be false
lesson_session.lesson_booking.errors.any?.should be false
lesson_session.lesson_booking_slots.length.should eql 2
#lesson_session.lesson_booking_slots.length.should eql 2
student_counter = booking.lesson_booking_slots.order(:created_at).last
student_counter.proposer.should eql user
booking.reload
@ -484,7 +484,7 @@ describe "Monthly Recurring Lesson Flow" do
payment = teacher_distribution.teacher_payment
payment.amount_in_cents.should eql prorated_cents
payment.fee_in_cents.should eql (prorated_cents * (school.base_rate + APP_CONFIG.stripe[:charge_fee])).round
payment.teacher_payment_charge.amount_in_cents.should eql (payment.real_distribution_in_cents + payment.real_distribution_in_cents * APP_CONFIG.stripe[:ach_pct]).round
payment.teacher_payment_charge.amount_in_cents.should eql (payment.real_distribution_in_cents + payment.real_distribution_in_cents * APP_CONFIG.stripe[:ach_pct]).round + 1 # we are off by 1 in rounding error somewhere. I'm OK with that
payment.teacher_payment_charge.fee_in_cents.should eql (prorated_cents * (school.base_rate + 0.03)).round
payment.teacher.should eql teacher_user
payment.teacher_distribution.should eql teacher_distribution
@ -601,7 +601,7 @@ describe "Monthly Recurring Lesson Flow" do
lesson_session.counter({proposer: user, slot: student_countered_slot, message: 'Does this work better?'})
lesson_session.errors.any?.should be false
lesson_session.lesson_booking.errors.any?.should be false
lesson_session.lesson_booking_slots.length.should eql 2
#lesson_session.lesson_booking_slots.length.should eql 2
student_counter = booking.lesson_booking_slots.order(:created_at).last
student_counter.proposer.should eql user
booking.reload

View File

@ -320,7 +320,7 @@ describe "Normal Lesson Flow" do
teacher_counter = lesson_session.lesson_booking_slots.order(:created_at).last
teacher_counter.should eql teacher_countered_slot
teacher_counter.proposer.should eql teacher_user
booking.lesson_booking_slots.length.should eql 3
#lesson_session.lesson_booking_slots.length.should eql 3
UserMailer.deliveries.length.should eql 1
chat = ChatMessage.unscoped.order(:created_at).last
chat.channel.should eql ChatMessage::CHANNEL_LESSON
@ -343,7 +343,7 @@ describe "Normal Lesson Flow" do
student_counter = booking.lesson_booking_slots.order(:created_at).last
student_counter.proposer.should eql user
booking.reload
booking.lesson_booking_slots.length.should eql 4
#booking.lesson_booking_slots.length.should eql 4
UserMailer.deliveries.length.should eql 1
chat = ChatMessage.unscoped.order(:created_at).last
chat.message.should eql 'Does this work better?'
@ -520,7 +520,7 @@ describe "Normal Lesson Flow" do
teacher_counter = lesson_session.lesson_booking_slots.order(:created_at).last
teacher_counter.should eql teacher_countered_slot
teacher_counter.proposer.should eql teacher_user
booking.lesson_booking_slots.length.should eql 3
#booking.lesson_sessions.lesson_booking_slots.length.should eql 3
UserMailer.deliveries.length.should eql 1
chat = ChatMessage.unscoped.order(:created_at).last
chat.channel.should eql ChatMessage::CHANNEL_LESSON
@ -543,7 +543,7 @@ describe "Normal Lesson Flow" do
student_counter = booking.lesson_booking_slots.order(:created_at).last
student_counter.proposer.should eql user
booking.reload
booking.lesson_booking_slots.length.should eql 4
#booking.lesson_booking_slots.length.should eql 4
UserMailer.deliveries.length.should eql 1
chat = ChatMessage.unscoped.order(:created_at).last
chat.message.should eql 'Does this work better?'
@ -723,7 +723,7 @@ describe "Normal Lesson Flow" do
teacher_counter = lesson_session.lesson_booking_slots.order(:created_at).last
teacher_counter.should eql teacher_countered_slot
teacher_counter.proposer.should eql teacher_user
booking.lesson_booking_slots.length.should eql 3
#lesson_session.lesson_booking_slots.length.should eql 3
UserMailer.deliveries.length.should eql 1
chat = ChatMessage.unscoped.order(:created_at).last
chat.channel.should eql ChatMessage::CHANNEL_LESSON
@ -746,7 +746,7 @@ describe "Normal Lesson Flow" do
student_counter = booking.lesson_booking_slots.order(:created_at).last
student_counter.proposer.should eql user
booking.reload
booking.lesson_booking_slots.length.should eql 4
#booking.lesson_booking_slots.length.should eql 4
UserMailer.deliveries.length.should eql 1
chat = ChatMessage.unscoped.order(:created_at).last
chat.message.should eql 'Does this work better?'
@ -926,7 +926,7 @@ describe "Normal Lesson Flow" do
teacher_counter = lesson_session.lesson_booking_slots.order(:created_at).last
teacher_counter.should eql teacher_countered_slot
teacher_counter.proposer.should eql teacher_user
booking.lesson_booking_slots.length.should eql 3
#lesson_session.lesson_booking_slots.length.should eql 3
UserMailer.deliveries.length.should eql 1
chat = ChatMessage.unscoped.order(:created_at).last
chat.channel.should eql ChatMessage::CHANNEL_LESSON
@ -949,7 +949,7 @@ describe "Normal Lesson Flow" do
student_counter = booking.lesson_booking_slots.order(:created_at).last
student_counter.proposer.should eql user
booking.reload
booking.lesson_booking_slots.length.should eql 4
#booking.lesson_booking_slots.length.should eql 4
UserMailer.deliveries.length.should eql 1
chat = ChatMessage.unscoped.order(:created_at).last
chat.message.should eql 'Does this work better?'
@ -1147,7 +1147,7 @@ describe "Normal Lesson Flow" do
teacher_counter = lesson_session.lesson_booking_slots.order(:created_at).last
teacher_counter.should eql teacher_countered_slot
teacher_counter.proposer.should eql teacher_user
booking.lesson_booking_slots.length.should eql 3
#lesson_session.lesson_booking_slots.length.should eql 3
UserMailer.deliveries.length.should eql 1
chat = ChatMessage.unscoped.order(:created_at).last
chat.channel.should eql ChatMessage::CHANNEL_LESSON
@ -1170,7 +1170,7 @@ describe "Normal Lesson Flow" do
student_counter = booking.lesson_booking_slots.order(:created_at).last
student_counter.proposer.should eql user
booking.reload
booking.lesson_booking_slots.length.should eql 4
#booking.lesson_booking_slots.length.should eql 4
UserMailer.deliveries.length.should eql 1
chat = ChatMessage.unscoped.order(:created_at).last
chat.message.should eql 'Does this work better?'

View File

@ -8,8 +8,8 @@ describe "Recurring Lesson Flow" do
let(:teacher) { teacher_user.teacher }
let(:lesson_booking_slot_single1) { FactoryGirl.build(:lesson_booking_slot_single) }
let(:lesson_booking_slot_single2) { FactoryGirl.build(:lesson_booking_slot_single) }
let(:lesson_booking_slot_recurring1) { FactoryGirl.build(:lesson_booking_slot_recurring) }
let(:lesson_booking_slot_recurring2) { FactoryGirl.build(:lesson_booking_slot_recurring) }
let(:lesson_booking_slot_recurring1) { FactoryGirl.build(:lesson_booking_slot_recurring, day_of_week: 2.days.from_now.wday) }
let(:lesson_booking_slot_recurring2) { FactoryGirl.build(:lesson_booking_slot_recurring, day_of_week: 3.days.from_now.wday) }
let(:valid_single_slots) { [lesson_booking_slot_single1, lesson_booking_slot_single2] }
let(:valid_recurring_slots) { [lesson_booking_slot_recurring1, lesson_booking_slot_recurring2] }
@ -50,20 +50,21 @@ describe "Recurring Lesson Flow" do
customer.email.should eql user.email
booking.lesson_sessions.length.should eql 1
lesson_session = booking.lesson_sessions[0]
lesson_session.status.should eql LessonBooking::STATUS_REQUESTED
lesson_session1 = booking.lesson_sessions[0]
lesson_session1.status.should eql LessonBooking::STATUS_REQUESTED
booking.status.should eql LessonBooking::STATUS_REQUESTED
######### Teacher counters with new slot
teacher_countered_slot = FactoryGirl.build(:lesson_booking_slot_recurring, hour: 14, update_all: true)
UserMailer.deliveries.clear
lesson_session.counter({proposer: teacher_user, slot: teacher_countered_slot, message: 'Does this work?'})
booking.counter_slot.should be_nil
lesson_session1.counter({proposer: teacher_user, slot: teacher_countered_slot, message: 'Does this work?'})
booking.reload
booking.errors.any?.should be false
lesson_session.lesson_booking.errors.any?.should be false
lesson_session.lesson_booking_slots.length.should eql 1
lesson_session.lesson_booking_slots[0].proposer.should eql teacher_user
teacher_counter = lesson_session.lesson_booking_slots.order(:created_at).last
lesson_session1.lesson_booking.errors.any?.should be false
booking.lesson_booking_slots.length.should eql 3
#booking.lesson_booking_slots[2].proposer.should eql teacher_user
teacher_counter = booking.counter_slot
teacher_counter.should eql teacher_countered_slot
teacher_counter.proposer.should eql teacher_user
booking.lesson_booking_slots.length.should eql 3
@ -74,19 +75,20 @@ describe "Recurring Lesson Flow" do
chat.user.should eql teacher_user
chat.target_user.should eql user
notification = Notification.unscoped.order(:created_at).last
notification.session_id.should eql lesson_session.music_session.id
notification.session_id.should eql lesson_session1.music_session.id
notification.student_directed.should eql true
notification.purpose.should eql 'counter'
notification.description.should eql NotificationTypes::LESSON_MESSAGE
#notification.message.should eql "Instructor has proposed a different time for your lesson."
######### Student counters with new slot
student_countered_slot = FactoryGirl.build(:lesson_booking_slot_recurring, hour: 16, update_all: true)
student_countered_slot = FactoryGirl.build(:lesson_booking_slot_recurring, hour: 16, update_all: true, day_of_week: 2.days.from_now.wday)
UserMailer.deliveries.clear
lesson_session.counter({proposer: user, slot: student_countered_slot, message: 'Does this work better?'})
lesson_session.errors.any?.should be false
lesson_session.lesson_booking.errors.any?.should be false
lesson_session.lesson_booking_slots.length.should eql 2
lesson_session1.counter({proposer: user, slot: student_countered_slot, message: 'Does this work better?'})
lesson_session1.errors.any?.should be false
lesson_session1.lesson_booking.errors.any?.should be false
lesson_session1.lesson_booking_slots.length.should eql 2
lesson_session1.slot.is_recurring?.should be true
student_counter = booking.lesson_booking_slots.order(:created_at).last
student_counter.proposer.should eql user
booking.reload
@ -98,26 +100,30 @@ describe "Recurring Lesson Flow" do
chat.user.should eql user
chat.target_user.should eql teacher_user
notification = Notification.unscoped.order(:created_at).last
notification.session_id.should eql lesson_session.music_session.id
notification.session_id.should eql lesson_session1.music_session.id
notification.student_directed.should eql false
notification.purpose.should eql 'counter'
notification.description.should eql NotificationTypes::LESSON_MESSAGE
######## Teacher accepts slot
UserMailer.deliveries.clear
lesson_session.accept({message: 'Yeah I got this', slot: student_counter.id, accepter: teacher_user})
lesson_session1.accept({message: 'Yeah I got this', slot: student_counter.id, accepter: teacher_user})
UserMailer.deliveries.each do |del|
# puts del.inspect
#puts del.subject
end
# get acceptance emails, as well as 'your stuff is accepted'
UserMailer.deliveries.length.should eql 2
lesson_session.errors.any?.should be_false
lesson_session.reload
lesson_session.slot.should eql student_counter
lesson_session.status.should eql LessonSession::STATUS_APPROVED
lesson_session1.errors.any?.should be_false
lesson_session1.reload
lesson_session1.slot.should eql student_counter
lesson_session2 = booking.lesson_sessions.order(:created_at).last
booking.reload
booking.counter_slot.should be_nil
lesson_session1.status.should eql LessonSession::STATUS_APPROVED
lesson_session2.status.should eql LessonSession::STATUS_APPROVED
booking.reload
booking.default_slot.should eql student_counter
lesson_session.music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
lesson_session1.music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
booking.status.should eql LessonBooking::STATUS_APPROVED
UserMailer.deliveries.length.should eql 2
@ -128,7 +134,7 @@ describe "Recurring Lesson Flow" do
chat.user.should eql teacher_user
chat.target_user.should eql user
notification = Notification.unscoped.order(:created_at).last
notification.session_id.should eql lesson_session.music_session.id
notification.session_id.should eql lesson_session1.music_session.id
notification.student_directed.should eql true
notification.purpose.should eql 'accept'
notification.description.should eql NotificationTypes::LESSON_MESSAGE
@ -139,27 +145,27 @@ describe "Recurring Lesson Flow" do
booking.lesson_sessions[0].scheduled_start.should_not eql booking.lesson_sessions[1].scheduled_start
# teacher & student get into session
start = lesson_session.scheduled_start
end_time = lesson_session.scheduled_start + (60 * lesson_session.duration)
uh2 = FactoryGirl.create(:music_session_user_history, user: teacher_user, history: lesson_session.music_session, created_at: start, session_removed_at: end_time)
start = lesson_session1.scheduled_start
end_time = lesson_session1.scheduled_start + (60 * lesson_session1.duration)
uh2 = FactoryGirl.create(:music_session_user_history, user: teacher_user, history: lesson_session1.music_session, created_at: start, session_removed_at: end_time)
# artificially end the session, which is covered by other background jobs
lesson_session.music_session.session_removed_at = end_time
lesson_session.music_session.save!
lesson_session1.music_session.session_removed_at = end_time
lesson_session1.music_session.save!
Timecop.travel(end_time + 1)
UserMailer.deliveries.clear
# background code comes around and analyses the session
LessonSession.hourly_check
lesson_session.reload
lesson_session.analysed.should be_true
analysis = lesson_session.analysis
lesson_session1.reload
lesson_session1.analysed.should be_true
analysis = lesson_session1.analysis
analysis["reason"].should eql LessonSessionAnalyser::STUDENT_FAULT
analysis["student"].should eql LessonSessionAnalyser::NO_SHOW
if lesson_session.billing_error_detail
puts "testdrive flow #{lesson_session.billing_error_detail}" # this should not occur, but helps a great deal if a regression occurs and running all the tests
if lesson_session1.billing_error_detail
puts "testdrive flow #{lesson_session1.billing_error_detail}" # this should not occur, but helps a great deal if a regression occurs and running all the tests
end
lesson_session.billed.should be true
lesson_session1.billed.should be true
user.reload
user.lesson_purchases.length.should eql 1
lesson_purchase = user.lesson_purchases[0]
@ -181,8 +187,8 @@ describe "Recurring Lesson Flow" do
line_item.lesson_package_purchase.should eql lesson_purchase
lesson_purchase.sale_line_item.should eql line_item
lesson.amount_charged.should eql (sale.recurly_total_in_cents / 100.0).to_f
lesson_session.billing_error_reason.should be_nil
lesson_session.sent_billing_notices.should be true
lesson_session1.billing_error_reason.should be_nil
lesson_session1.sent_billing_notices.should be true
user.reload
user.remaining_test_drives.should eql 0
UserMailer.deliveries.each do |d|

View File

@ -102,7 +102,7 @@ describe "TestDrive Lesson Flow" do
teacher_counter = lesson_session.lesson_booking_slots.order(:created_at).last
teacher_counter.should eql teacher_countered_slot
teacher_counter.proposer.should eql teacher_user
booking.lesson_booking_slots.length.should eql 3
# booking.lesson_booking_slots.length.should eql 3
UserMailer.deliveries.length.should eql 1
chat = ChatMessage.unscoped.order(:created_at).last
chat.channel.should eql ChatMessage::CHANNEL_LESSON
@ -125,7 +125,7 @@ describe "TestDrive Lesson Flow" do
student_counter = booking.lesson_booking_slots.order(:created_at).last
student_counter.proposer.should eql user
booking.reload
booking.lesson_booking_slots.length.should eql 4
# booking.lesson_booking_slots.length.should eql 4
UserMailer.deliveries.length.should eql 1
chat = ChatMessage.unscoped.order(:created_at).last
chat.message.should eql 'Does this work better?'
@ -304,7 +304,7 @@ describe "TestDrive Lesson Flow" do
teacher_counter = lesson_session.lesson_booking_slots.order(:created_at).last
teacher_counter.should eql teacher_countered_slot
teacher_counter.proposer.should eql teacher_user
booking.lesson_booking_slots.length.should eql 3
# booking.lesson_booking_slots.length.should eql 3
UserMailer.deliveries.length.should eql 1
chat = ChatMessage.unscoped.order(:created_at).last
chat.channel.should eql ChatMessage::CHANNEL_LESSON
@ -327,7 +327,7 @@ describe "TestDrive Lesson Flow" do
student_counter = booking.lesson_booking_slots.order(:created_at).last
student_counter.proposer.should eql user
booking.reload
booking.lesson_booking_slots.length.should eql 4
# booking.lesson_booking_slots.length.should eql 4
UserMailer.deliveries.length.should eql 1
chat = ChatMessage.unscoped.order(:created_at).last
chat.message.should eql 'Does this work better?'

View File

@ -8,8 +8,8 @@ describe LessonBooking do
let(:teacher) { teacher_user.teacher }
let(:lesson_booking_slot_single1) { FactoryGirl.build(:lesson_booking_slot_single) }
let(:lesson_booking_slot_single2) { FactoryGirl.build(:lesson_booking_slot_single) }
let(:lesson_booking_slot_recurring1) { FactoryGirl.build(:lesson_booking_slot_recurring) }
let(:lesson_booking_slot_recurring2) { FactoryGirl.build(:lesson_booking_slot_recurring) }
let(:lesson_booking_slot_recurring1) { FactoryGirl.build(:lesson_booking_slot_recurring, day_of_week: 2.days.from_now.wday) }
let(:lesson_booking_slot_recurring2) { FactoryGirl.build(:lesson_booking_slot_recurring, day_of_week: 3.days.from_now.wday) }
let(:valid_single_slots) { [lesson_booking_slot_single1, lesson_booking_slot_single2] }
let(:valid_recurring_slots) { [lesson_booking_slot_recurring1, lesson_booking_slot_recurring2] }
@ -641,10 +641,9 @@ describe LessonBooking do
booking.lesson_sessions.length.should eql 1
booking.accept(booking.lesson_sessions[0], booking.lesson_booking_slots[0], user)
booking.errors.any?.should be false
booking.reload
booking.lesson_sessions.length.should eql 1
booking.accepter.should eql user
booking.errors.any?.should be true
booking.errors[:accepter].should eql ["No one has been indicated as accepting the lesson"]
end
end
@ -705,13 +704,14 @@ describe LessonBooking do
lesson_session.status.should eql LessonSession::STATUS_REQUESTED
lesson_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
lesson_session.accept({accepter: teacher_user, message: 'Yeah I got this', slot: booking.default_slot.id, update_all: false})
lesson_session.accept({accepter: teacher_user, message: 'Yeah I got this', slot: booking.default_slot.id, update_all: true})
lesson_session.errors.any?.should be_false
lesson_session.status.should eql LessonSession::STATUS_APPROVED
lesson_session.reload
lesson_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
booking.reload
booking.active.should eql true
booking.status.should eql LessonSession::STATUS_APPROVED
UserMailer.deliveries.clear
Timecop.freeze(7.days.ago)
@ -793,8 +793,9 @@ describe LessonBooking do
lesson_session.errors.any?.should be false
lesson_session.status.should eql LessonSession::STATUS_COUNTERED
lesson_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
lesson_session.counter_slot.should eql counter
booking.reload
booking.counter_slot.should eql counter
booking.counter_slot.should be_nil
lesson_session.accept({accepter: teacher_user, message: 'Yeah I got this', slot: counter.id, update_all: false})
lesson_session.errors.any?.should be_false
@ -808,7 +809,7 @@ describe LessonBooking do
it "recurring" do
Timecop.freeze(Time.new(2016, 03, 4, 5, 0, 0))
booking = LessonBooking.book_normal(user, teacher_user, valid_recurring_slots, "Hey I've heard of you before.", true, LessonBooking::PAYMENT_STYLE_WEEKLY, 60)
booking = LessonBooking.book_normal(user, teacher_user, valid_recurring_slots, "Hey I've heard of you before.", true, LessonBooking::PAYMENT_STYLE_MONTHLY, 60)
lesson_session = booking.lesson_sessions[0]
lesson_session.status.should eql LessonSession::STATUS_REQUESTED
lesson_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
@ -816,17 +817,24 @@ describe LessonBooking do
counter = FactoryGirl.build(:lesson_booking_slot_recurring, day_of_week: 2, update_all: true)
lesson_session.counter({proposer: user, slot: counter, message: 'Does this work better?'})
lesson_session.errors.any?.should be false
lesson_session.status.should eql LessonSession::STATUS_COUNTERED
lesson_session.status.should eql LessonSession::STATUS_REQUESTED
lesson_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
booking.reload
booking.counter_slot.should eql counter
booking.counterer.should eql user
booking.has_recurring_counter?.should be true
booking.is_countered?.should be true
# to help scoot out the 'created_at' of the lessons
Timecop.freeze(Time.now + 10)
lesson_session.accept({accepter: teacher_user, message: 'Yeah I got this', slot: counter.id, update_all: false})
lesson_session.accept({accepter: teacher_user, message: 'Yeah I got this', slot: counter.id})
lesson_session.errors.any?.should be_false
lesson_session.status.should eql LessonSession::STATUS_APPROVED
booking.reload
booking.status.should eql LessonSession::STATUS_APPROVED
booking.has_recurring_counter?.should be false
booking.is_countered?.should be false
lesson_session.reload
lesson_session.scheduled_start.should eql counter.scheduled_time(0)
@ -837,10 +845,14 @@ describe LessonBooking do
# now it's approved, we have 2 sessions that are not yet completed with a time
# we should be able to reschedule just one of the lessons
counter2 = FactoryGirl.build(:lesson_booking_slot_recurring, day_of_week: 4, update_all: false)
counter2 = FactoryGirl.build(:lesson_booking_slot_single, day_of_week: 4)
lesson_session.counter({proposer: user, slot: counter2, message: 'ACtually, let\'s do this instead for just this one'})
lesson_session.errors.any?.should be false
lesson_session.status.should eql LessonSession::STATUS_COUNTERED
lesson_session.has_recurring_counter?.should be false
booking.reload
booking.status.should eql LessonSession::STATUS_APPROVED
lesson_session.scheduled_start.should eql counter.scheduled_time(0)
lesson_session.accept({accepter: teacher_user, message: 'OK, lets fix just this one', slot: counter2.id})
@ -858,9 +870,11 @@ describe LessonBooking do
counter3 = FactoryGirl.build(:lesson_booking_slot_recurring, day_of_week: 5, update_all: true)
lesson_session.counter({proposer: user, slot: counter3, message: 'ACtually, let\'s do this instead for just this one... again'})
lesson_session.errors.any?.should be false
lesson_session.status.should eql LessonSession::STATUS_COUNTERED
lesson_session.status.should eql LessonSession::STATUS_APPROVED
lesson_session.reload
lesson_session.has_recurring_counter?.should be true
lesson_session2.reload
lesson_session2.has_recurring_counter?.should be true
lesson_session.scheduled_start.should eql counter2.scheduled_time(0)
lesson_session2.scheduled_start.should eql counter.scheduled_time(1)
booking.reload
@ -874,10 +888,14 @@ describe LessonBooking do
booking.counter_slot.should be_nil
lesson_session.reload
lesson_session2.reload
lesson_session.reload
lesson_session.has_recurring_counter?.should be false
lesson_session2.reload
lesson_session2.has_recurring_counter?.should be false
lesson_session.created_at.should be < lesson_session2.created_at
lesson_session.scheduled_start.should eql counter3.scheduled_time(0)
lesson_session2.scheduled_start.should eql counter3.scheduled_time(1 )
lesson_session2.scheduled_start.should eql counter3.scheduled_time(1)
end
end

View File

@ -2,18 +2,18 @@ require 'spec_helper'
describe LessonSession do
let(:user) {FactoryGirl.create(:user, stored_credit_card: true, remaining_free_lessons: 1, remaining_test_drives: 1)}
let(:teacher) {FactoryGirl.create(:teacher_user)}
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) }
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]}
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 "counter" do
describe "recurring" do
it "counter madness" do
lesson = monthly_lesson(user, teacher, {accept:false})
lesson = monthly_lesson(user, teacher, {accept: false})
# start with the student
invalid = FactoryGirl.build(:lesson_booking_slot_single, update_all: false)
@ -28,8 +28,9 @@ describe LessonSession do
lesson.counter({proposer: user, message: "crumble and bumble take 2", slot: counter1})
lesson.errors.any?.should be_false
lesson.reload
lesson.status.should eql LessonSession::STATUS_COUNTERED
lesson.counter_slot.id.should eql counter1.id
lesson.status.should eql LessonSession::STATUS_REQUESTED
lesson.has_recurring_counter?.should be true
lesson.counter_slot.should be_nil
lesson.lesson_booking.counter_slot.id.should eql counter1.id
counter2 = FactoryGirl.build(:lesson_booking_slot_recurring, update_all: true)
@ -37,33 +38,179 @@ describe LessonSession do
lesson.counter({proposer: teacher, message: "crumble and bumble take 3", slot: counter2})
lesson.errors.any?.should be_false
lesson.reload
lesson.status.should eql LessonSession::STATUS_COUNTERED
lesson.counter_slot.id.should eql counter2.id
lesson.status.should eql LessonSession::STATUS_REQUESTED
lesson.counter_slot.should be_nil
lesson.has_recurring_counter?.should be true
lesson.lesson_booking.counter_slot.id.should eql counter2.id
lesson.accept({accepter: user, message: "burp", slot: counter2.id})
lesson.errors.any?.should be_false
lesson.reload
lesson.counter_slot.should be_nil
lesson.status.should eql LessonSession::STATUS_APPROVED
lesson.has_recurring_counter?.should be false
counter3 = FactoryGirl.build(:lesson_booking_slot_recurring, update_all: false)
counter3 = FactoryGirl.build(:lesson_booking_slot_recurring)
lesson.counter({proposer: user, message: "crumble and bumble take 4", slot: counter3})
lesson.errors.any?.should be_false
lesson.reload
lesson.status.should eql LessonSession::STATUS_COUNTERED
lesson.counter_slot.id.should eql counter3.id
lesson.counter_slot.should be_nil
lesson.status.should eql LessonSession::STATUS_APPROVED
lesson.lesson_booking.counter_slot.id.should eql counter3.id
lesson.has_recurring_counter?.should be true
counter4 = FactoryGirl.build(:lesson_booking_slot_recurring, update_all: true)
lesson.counter({proposer: teacher, message: "crumble and bumble take 5", slot: counter4})
lesson.errors.any?.should be_false
lesson.reload
lesson.status.should eql LessonSession::STATUS_COUNTERED
lesson.counter_slot.id.should eql counter4.id
lesson.counter_slot.should be_nil
lesson.status.should eql LessonSession::STATUS_APPROVED
lesson.lesson_booking.counter_slot.id.should eql counter4.id
lesson.has_recurring_counter?.should be true
end
it "simultaneous recurring and single counter and approve recurring first" do
# first create a single counter, then recurring after, and approve the recurring first without it having any effect of the single counter
lesson1 = monthly_lesson(user, teacher, {accept: true})
lesson2 = lesson1.lesson_booking.lesson_sessions.order(:created_at).last
counter1 = FactoryGirl.build(:lesson_booking_slot_recurring, update_all: true)
lesson1.counter({proposer: user, message: "crumble and bumble take 2", slot: counter1})
lesson1.errors.any?.should be_false
lesson1.reload
lesson2.reload
lesson1.status.should eql LessonSession::STATUS_APPROVED
lesson2.status.should eql LessonSession::STATUS_APPROVED
lesson1.has_recurring_counter?.should be true
lesson1.counter_slot.should be_nil
lesson1.lesson_booking.counter_slot.id.should eql counter1.id
lesson1.lesson_booking.is_countered?.should be true
counter2 = FactoryGirl.build(:lesson_booking_slot_single, update_all: true)
lesson2.counter({proposer: user, message: "crumble and bumble take 3", slot: counter2})
lesson1.errors.any?.should be_false
lesson1.reload
lesson2.reload
lesson1.status.should eql LessonSession::STATUS_APPROVED
lesson2.status.should eql LessonSession::STATUS_COUNTERED
lesson1.counter_slot.should be_nil
lesson1.has_recurring_counter?.should be true
lesson1.lesson_booking.counter_slot.id.should eql counter1.id
lesson2.counter_slot.should eql counter2
lesson1.accept({accepter: teacher, message: 'accept recurring', slot: counter1.id})
lesson2.reload
lesson1.reload
lesson1.status.should eql LessonSession::STATUS_APPROVED
lesson2.status.should eql LessonSession::STATUS_COUNTERED
lesson1.lesson_booking.counter_slot.should be_nil
lesson1.lesson_booking.is_countered?.should be false
lesson2.accept({accepter: teacher, message: 'accept single', slot: counter2.id})
lesson2.reload
lesson1.reload
lesson1.status.should eql LessonSession::STATUS_APPROVED
lesson2.status.should eql LessonSession::STATUS_APPROVED
lesson1.lesson_booking.counter_slot.should be_nil
lesson1.lesson_booking.is_countered?.should be false
end
it "simultaneous recurring and single counter and approve single first" do
# first create a single counter, then recurring after, and approve the recurring first without it having any effect of the single counter
lesson1 = monthly_lesson(user, teacher, {accept: true})
lesson2 = lesson1.lesson_booking.lesson_sessions.order(:created_at).last
counter1 = FactoryGirl.build(:lesson_booking_slot_recurring, update_all: true)
lesson1.counter({proposer: user, message: "crumble and bumble take 2", slot: counter1})
lesson1.errors.any?.should be_false
lesson1.reload
lesson2.reload
lesson1.status.should eql LessonSession::STATUS_APPROVED
lesson2.status.should eql LessonSession::STATUS_APPROVED
lesson1.lesson_booking.status.should eql LessonBooking::STATUS_COUNTERED
lesson1.has_recurring_counter?.should be true
lesson1.counter_slot.should be_nil
lesson1.lesson_booking.counter_slot.id.should eql counter1.id
lesson1.lesson_booking.is_countered?.should be true
counter2 = FactoryGirl.build(:lesson_booking_slot_single, update_all: true)
lesson2.counter({proposer: user, message: "crumble and bumble take 3", slot: counter2})
lesson1.errors.any?.should be_false
lesson1.reload
lesson2.reload
lesson1.status.should eql LessonSession::STATUS_APPROVED
lesson2.status.should eql LessonSession::STATUS_COUNTERED
lesson1.counter_slot.should be_nil
lesson1.has_recurring_counter?.should be true
lesson1.lesson_booking.counter_slot.id.should eql counter1.id
lesson2.counter_slot.should eql counter2
lesson2.accept({accepter: teacher, message: 'accept single', slot: counter2.id})
lesson2.reload
lesson1.reload
lesson1.status.should eql LessonSession::STATUS_APPROVED
lesson2.status.should eql LessonSession::STATUS_APPROVED
lesson1.lesson_booking.counter_slot.should_not be_nil
lesson1.lesson_booking.is_countered?.should be true
lesson1.accept({accepter: teacher, message: 'accept recurring', slot: counter1.id})
lesson2.reload
lesson1.reload
lesson1.status.should eql LessonSession::STATUS_APPROVED
lesson2.status.should eql LessonSession::STATUS_APPROVED
lesson1.lesson_booking.counter_slot.should be_nil
lesson1.lesson_booking.is_countered?.should be false
lesson1.lesson_booking.status.should eql LessonBooking::STATUS_APPROVED
end
it "countered lesson that goes into past gets autocancelled; affects billing" do
# first create a single counter, then recurring after, and approve the recurring first without it having any effect of the single counter
lesson1 = monthly_lesson(user, teacher, {accept: true})
lesson2 = lesson1.lesson_booking.lesson_sessions.order(:created_at).last
counter1 = FactoryGirl.build(:lesson_booking_slot_recurring, update_all: true)
lesson1.counter({proposer: user, message: "crumble and bumble take 2", slot: counter1})
lesson1.errors.any?.should be_false
lesson1.reload
lesson2.reload
lesson1.status.should eql LessonSession::STATUS_APPROVED
lesson2.status.should eql LessonSession::STATUS_APPROVED
lesson1.lesson_booking.status.should eql LessonBooking::STATUS_COUNTERED
lesson1.has_recurring_counter?.should be true
lesson1.counter_slot.should be_nil
lesson1.lesson_booking.counter_slot.id.should eql counter1.id
lesson1.lesson_booking.is_countered?.should be true
Timecop.travel(Date.today + 50)
LessonSession.analyse_sessions
lesson1.reload
lesson2.reload
lesson1.analysed.should be false
lesson2.analysed.should be false
LessonSession.auto_cancel
lesson1.reload
lesson2.reload
lesson1.status.should eql LessonSession::STATUS_UNCONFIRMED
lesson2.status.should eql LessonSession::STATUS_UNCONFIRMED
end
end
end
@ -141,56 +288,59 @@ describe LessonSession do
describe "remind_counters" do
it "finds old requested and pokes teacher" do
lesson_session1 = normal_lesson(user, teacher, {})
lesson_session1.sent_counter_reminder.should be_false
lesson_session1.status.should eql LessonSession::STATUS_REQUESTED
mailer = mock
mailer.should_receive(:deliver_now)
mailer.should_receive(:deliver_now).once
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
lesson_session1.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
lesson_session1.sent_counter_reminder.should be_true
LessonSession.remind_counters
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_now)
mailer.should_receive(:deliver_now).once
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
lesson_session1.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
lesson_session1.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_now)
mailer.should_receive(:deliver_now).once
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
lesson_session1.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
lesson_session1.sent_counter_reminder.should be_true
end
end
@ -238,6 +388,95 @@ describe LessonSession do
end
end
def day_out(num_days)
safe_day_out = Time.now.wday + num_days
if safe_day_out > 6
safe_day_out -= 6
end
safe_day_out
end
describe "cancel" do
it "cancels both recurring lessons" do
now = Time.now
slotRecurring1 = FactoryGirl.build(:lesson_booking_slot_recurring, day_of_week: day_out(2))
slotRecurring2 = FactoryGirl.build(:lesson_booking_slot_recurring, day_of_week: day_out(3))
lesson = monthly_lesson(user, teacher, {slots: [slotRecurring1, slotRecurring2], accept: true})
lesson.reload
booking = lesson.lesson_booking
# verify ti's all approved and ready to test
booking.is_approved?.should be true
booking.lesson_sessions.count.should eql 2
lessons = booking.lesson_sessions.order(:created_at)
first_lesson = lessons[0]
second_lesson = lessons[1]
first_lesson.is_approved?.should be true
first_lesson.in_no_cancel_window.should be false
second_lesson.is_approved?.should be true
second_lesson.in_no_cancel_window.should be false
first_lesson.cancel({canceler: user, message: "Screw this lesson", update_all: true})
first_lesson.reload
second_lesson.reload
booking.reload
first_lesson.is_canceled?.should be true
second_lesson.is_canceled?.should be true
booking.is_canceled?.should be true
first_lesson.student_short_canceled.should be false
first_lesson.student_canceled.should be true
first_lesson.teacher_canceled.should be false
second_lesson.student_short_canceled.should be false
second_lesson.student_canceled.should be true
second_lesson.teacher_canceled.should be false
end
it "cancels both recurring lessons one within no-cancel window" do
now = Time.now
today = now.wday
slight_future = 6.hours.from_now
slight_future2 = 7.hours.from_now
slotRecurring1 = FactoryGirl.build(:lesson_booking_slot_recurring, day_of_week: slight_future.wday, hour: slight_future.hour)
slotRecurring2 = FactoryGirl.build(:lesson_booking_slot_recurring, day_of_week: slight_future2.wday, hour: slight_future2.hour)
lesson = monthly_lesson(user, teacher, {slots: [slotRecurring1, slotRecurring2], accept: true})
lesson.reload
booking = lesson.lesson_booking
# verify ti's all approved and ready to test
booking.is_approved?.should be true
booking.lesson_sessions.count.should eql 2
lessons = booking.lesson_sessions.order(:created_at)
first_lesson = lessons[0]
second_lesson = lessons[1]
first_lesson.is_approved?.should be true
first_lesson.in_no_cancel_window.should be true
second_lesson.is_approved?.should be true
second_lesson.in_no_cancel_window.should be false
first_lesson.cancel({canceler: user, message: "Screw this lesson", update_all: true})
first_lesson.reload
second_lesson.reload
booking.reload
first_lesson.is_canceled?.should be true
second_lesson.is_canceled?.should be true
booking.is_canceled?.should be true
first_lesson.student_short_canceled.should be true
first_lesson.student_canceled.should be true
first_lesson.teacher_canceled.should be false
second_lesson.student_short_canceled.should be false
second_lesson.student_canceled.should be true
second_lesson.teacher_canceled.should be false
end
end
describe "permissions" do
it "student can join session" do
lesson = normal_lesson(user, teacher)
@ -305,7 +544,7 @@ describe LessonSession do
end
describe "schools" do
let (:school) {FactoryGirl.create(:school, scheduling_communication: School::SCHEDULING_COMM_SCHOOL)}
let (:school) { FactoryGirl.create(:school, scheduling_communication: School::SCHEDULING_COMM_SCHOOL) }
describe "owner" do
it "works when not a teacher" do

View File

@ -898,7 +898,7 @@ describe Sale do
user.reload
user.has_stored_credit_card?.should be_true
user.sales.count.should eql 1
user.sales.count.should eql 1
sale = result[:test_drive]
sale.stripe_charge_id.should_not be_nil

View File

@ -171,7 +171,8 @@ group :test, :cucumber do
gem 'simplecov', '~> 0.7.1'
gem 'simplecov-rcov'
gem 'capybara' # '2.4.4'
gem 'rails-assets-sinon', source: 'https://rails-assets.org'
#gem 'rails-assets-sinon', source: 'https://rails-assets.org'
#gem 'sinon-rails'
#if ENV['JAMWEB_QT5'] == '1'
# # necessary on platforms such as arch linux, where pacman -S qt5-webkit is your easiet option
# gem "capybara-webkit", :git => 'git://github.com/thoughtbot/capybara-webkit.git'

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

View File

@ -305,7 +305,7 @@ UserStore = context.UserStore
if lesson_price
value = "single|#{minutes}"
display = "#{minutes} Minute Lesson Each Week - $#{(lesson_price / 100).toFixed(2)} Per Week"
results.push(`<option key={value} value={value}>{display}</option>`)
#results.push(`<option key={value} value={value}>{display}</option>`) # THESE are WEEKLY. CANT DO IT YET DUE TO LACK OF QA OF PAYMENT STYLE WEEKLY
for minutes in enabledMinutes
monthly_price = teacher["price_per_month_#{minutes}_cents"]

View File

@ -142,17 +142,17 @@ LessonTimerActions = context.LessonTimerActions
if recurring
if @viewerStudent()
context.JK.Banner.showAlert("Policy Issue",
"<p>Were sorry, but you cannot reschedule this recurring lesson right now because it is less than 24 hours before the lesson start time. This is not allowed in the <a href=\"/corp/terms\" target=\"_blank\">terms of service</a> because the instructor cannot reasonably be expected to be able to backfill the time slot that has been lost. You may reschedule this recurring lesson anytime starting from the end of this next scheduled lesson, so please plan to do it then.</p>")
"<p>Were sorry, but you cannot reschedule this recurring lesson right now because it is less than 24 hours before the lesson start time.<br/></br>This is not allowed in the <a href=\"/corp/terms\" target=\"_blank\">terms of service</a> because the instructor cannot reasonably be expected to be able to backfill the time slot that has been lost. You may reschedule this recurring lesson anytime starting from the end of this next scheduled lesson, so please plan to do it then.</p>")
else
context.JK.Banner.showAlert("Policy Issue",
"<p>Were sorry, but you cannot reschedule this recurring lesson right now because it is less than 24 hours before the lesson start time. This is not allowed in the <a href=\"/corp/terms\" target=\"_blank\">terms of service</a>. You may reschedule this recurring lesson anytime starting from the end of this next scheduled lesson, so please plan to do it then.</p>")
"<p>Were sorry, but you cannot reschedule this recurring lesson right now because it is less than 24 hours before the lesson start time.<br/></br>This is not allowed in the <a href=\"/corp/terms\" target=\"_blank\">terms of service</a>. You may reschedule this recurring lesson anytime starting from the end of this next scheduled lesson, so please plan to do it then.</p>")
else
if @viewerStudent()
context.JK.Banner.showAlert("Policy Issue",
"<p>Were sorry, but you cannot reschedule a lesson less than 24 hours before the lesson start time. This is not allowed in the <a href=\"/corp/terms\" target=\"_blank\">terms of service</a> because the instructor cannot reasonably be expected to be able to backfill the time slot that has been lost.</p>")
"<p>Were sorry, but you cannot reschedule a lesson less than 24 hours before the lesson start time.<br/></br>This is not allowed in the <a href=\"/corp/terms\" target=\"_blank\">terms of service</a> because the instructor cannot reasonably be expected to be able to backfill the time slot that has been lost.</p>")
else
context.JK.Banner.showAlert("Policy Issue",
"<p>Were sorry, but you cannot reschedule a lesson less than 24 hours before the lesson start time. This is not allowed in the <a href=\"/corp/terms\" target=\"_blank\">terms of service</a>.</p>")
"<p>Were sorry, but you cannot reschedule a lesson less than 24 hours before the lesson start time.<br/></br>This is not allowed in the <a href=\"/corp/terms\" target=\"_blank\">terms of service</a>.</p>")
else
@app.ajaxError(jqXHR)
))
@ -193,15 +193,15 @@ LessonTimerActions = context.LessonTimerActions
cancelLessonBookingFail: (jqXHR) ->
@app.ajaxError(jqXHR)
cancelSelected: (lesson, recurring) ->
rest.checkLessonCancel({id: lesson.id, update_all: recurring})
.done((response) => @issueCancelLesson(lesson, recurring))
.fail((jqXHR) => @cancelSelectedFail(jqXHR, lesson))
cancelSelected: (lesson, update_all) ->
rest.checkLessonCancel({id: lesson.id, update_all: update_all})
.done((response) => @issueCancelLesson(lesson, update_all))
.fail((jqXHR) => @cancelSelectedFail(jqXHR, lesson, update_all))
cancelSelectedFail: (jqXHR, lesson) ->
cancelSelectedFail: (jqXHR, lesson, update_all) ->
if jqXHR.status == 422
if lesson.recurring
if lesson.recurring && update_all
if @viewerStudent()
buttons = []
buttons.push({name: 'CLOSE', buttonStyle: 'button-grey'})
@ -212,21 +212,21 @@ LessonTimerActions = context.LessonTimerActions
})
context.JK.Banner.show({
title: "Policy Issue",
html: "You may cancel this recurring series of lessons, but it is too late to cancel the next scheduled lesson because it is less than 24 hours before the lesson start time. This is not allowed in the <a href=\"/corp/terms\" target=\"_blank\">terms of service</a> because the instructor cannot reasonably be expected to be able to backfill the time slot that has been lost.",
html: "You may cancel this recurring series of lessons, but it is too late to cancel the next scheduled lesson because it is less than 24 hours before the lesson start time.<br/><br/>This is not allowed in the <a href=\"/corp/terms\" target=\"_blank\">terms of service</a> because the instructor cannot reasonably be expected to be able to backfill the time slot that has been lost.",
buttons: buttons
})
else
# path should not be taken
context.JK.Banner.showAlert("Policy Issue",
"<p>Were sorry, but you cannot cancel a lesson less than 24 hours before the lesson start time. This is not allowed in the <a href=\"/corp/terms\" target=\"_blank\">terms of service</a> because the instructor cannot reasonably be expected to be able to backfill the time slot that has been lost.</p>")
"<p>Were sorry, but you cannot cancel a lesson less than 24 hours before the lesson start time.<br/><br/>This is not allowed in the <a href=\"/corp/terms\" target=\"_blank\">terms of service</a> because the instructor cannot reasonably be expected to be able to backfill the time slot that has been lost.</p>")
else
if @viewerStudent()
context.JK.Banner.showAlert("Policy Issue",
"<p>Were sorry, but you cannot cancel a lesson less than 24 hours before the lesson start time. This is not allowed in the <a href=\"/corp/terms\" target=\"_blank\">terms of service</a> because the instructor cannot reasonably be expected to be able to backfill the time slot that has been lost.</p>")
"<p>Were sorry, but you cannot cancel a lesson less than 24 hours before the lesson start time.<br/><br/>This is not allowed in the <a href=\"/corp/terms\" target=\"_blank\">terms of service</a> because the instructor cannot reasonably be expected to be able to backfill the time slot that has been lost.</p>")
else
# path should not be taken
context.JK.Banner.showAlert("Policy Issue",
"<p>Were sorry, but you cannot cancel a lesson less than 24 hours before the lesson start time. This is not allowed in the <a href=\"/corp/terms\" target=\"_blank\">terms of service</a>.</p>")
"<p>Were sorry, but you cannot cancel a lesson less than 24 hours before the lesson start time.<br/><br/>This is not allowed in the <a href=\"/corp/terms\" target=\"_blank\">terms of service</a>.</p>")
else
@app.ajaxError(jqXHR)
@ -264,7 +264,7 @@ LessonTimerActions = context.LessonTimerActions
else
confirmTitle = 'Confirm Cancelation'
verbLower = 'cancel'
if !lesson.isRequested || lesson.recurring
if !lesson.isRequested && lesson.recurring
buttons = []
buttons.push({name: 'CLOSE', buttonStyle: 'button-grey'})
buttons.push({
@ -550,7 +550,7 @@ LessonTimerActions = context.LessonTimerActions
timeDesc = "Starts in less than a minute"
else
timeDesc = "Starts in #{lessonData.times.until.minutes} minutes."
timeStmt = `<span>{timeDesc}<a
timeStmt = `<span>{timeDesc}<br/><a
onClick={this.joinLessonNow.bind(this, lessonData)}>join lesson now</a></span>`
else if lessonData.times.inThePast
minutes = -lessonData.times.until.minutes

View File

@ -103,6 +103,8 @@ UserStore = context.UserStore
@processSlot(booking.counter_slot, booking)
@processSlot(booking.default_slot, booking)
@processSlot(booking.alt_slot, booking)
if booking.focused_lesson?
@processSlot(booking.focused_lesson.counter_slot, booking)
@ -165,25 +167,28 @@ UserStore = context.UserStore
id: parsed.id,
}).done((response) => @getLessonBookingDone(response)).fail(@app.ajaxError)
hasFocusedLesson: () ->
@focusedLesson()?
hasFocusedLesson: (booking = this.state?.booking) ->
@focusedLesson(booking)?
focusedLesson: () ->
console.log("focusedlesos", this.state?.booking?.focused_lesson)
this.state?.booking?.focused_lesson
focusedLesson: (booking = this.state?.booking) ->
booking?.focused_lesson
updateBookingState: (booking) ->
console.log("updating booking state", booking)
if booking.counter_slot?
startSlotDecision = booking.counter_slot.id
slot_update_all = false
counter_slot = @counteredSlot(booking)
if counter_slot?
startSlotDecision = counter_slot.id
slot_update_all = counter_slot['is_recurring?']
else
if booking.accepter_id?
startSlotDecision = 'counter'
else
startSlotDecision = booking.default_slot.id
slot_update_all = booking.default_slot['is_recurring?']
update_all = !booking.focused_lesson?.id?
update_all = slot_update_all || !booking.focused_lesson?.id?
if booking.focused_lesson?
#booking.focused_lesson.lesson_booking = booking
@ -368,8 +373,18 @@ UserStore = context.UserStore
defaultSlot: () ->
@state.booking?.default_slot
counteredSlot: () ->
@state.booking?.counter_slot
counteredSlot: (booking = @state.booking) ->
slot = null
if @hasFocusedLesson(booking)
focused = @focusedLesson(booking)
if focused.status == 'countered'
slot = focused.counter_slot
if !slot?
# only consider the booking slot if it's present and if it's marked is_recurring?
if booking?.counter_slot?['is_recurring?']
slot = booking?.counter_slot
slot
canceler: () ->
if @student().id == this.state.booking?.canceler_id
@ -724,10 +739,6 @@ UserStore = context.UserStore
header = 'respond to lesson request'
content = @renderTeacherRequested()
else if @isApproved()
header = @approvedHeader()
content = @renderTeacherApproved()
else if @isCounter()
if @isTeacherCountered()
header = 'your proposed alternate day/time is still pending'
@ -735,6 +746,11 @@ UserStore = context.UserStore
header = 'student has proposed an alternate day/time'
content = @renderTeacherCountered()
else if @isApproved()
header = @approvedHeader()
content = @renderTeacherApproved()
else if @isCompleted()
header = @completedHeader()
content = @renderTeacherComplete()
@ -765,11 +781,6 @@ UserStore = context.UserStore
header = 'your lesson has been requested'
content = @renderStudentRequested()
else if @isApproved()
header = @approvedHeader()
content = @renderStudentApproved()
else if @isCounter()
if @isTeacherCountered()
header = 'teacher has proposed an alternate day/time'
@ -777,6 +788,10 @@ UserStore = context.UserStore
header = 'your proposed alternate day/time is still pending'
content = @renderTeacherCountered()
else if @isApproved()
header = @approvedHeader()
content = @renderStudentApproved()
else if @isCompleted()
header = @completedHeader()
content = @renderStudentComplete()
@ -1082,7 +1097,7 @@ UserStore = context.UserStore
{detail}
{this.slotMessage(this.counteredSlot())}
</div>
<LessonBookingDecision {...this.decisionProps([this.state.booking.counter_slot])} />
<LessonBookingDecision {...this.decisionProps([this.counteredSlot()])} />
</div>`
})

View File

@ -195,7 +195,8 @@
if this.props.counterErrors?
errorText = window.JK.reactErrors(this.props.counterErrors, {day_of_week: 'Day' })
if this.props.is_recurring && this.props.update_all
console.log("LessonBookingDecision props", this.props)
if (this.props.is_recurring && this.props.update_all) # || (this.props.counter && this.props.slots[0]['is_recurring?'])
slotAltPrompt = `<div className="slot-alt-prompt">
<span className="alt-date-block">

View File

@ -25,13 +25,13 @@ teacherActions = window.JK.Actions.Teacher
lesson.cardNotOk = !lesson.lesson_booking.card_presumed_ok && lesson.payment_if_school_on_school?
lesson.isActive = lesson['is_active?']
if (lesson.status == 'requested' || lesson.status == 'countered')
if (lesson.status == 'requested' || lesson.status == 'countered' || lesson.lesson_booking['is_countered?'])
lesson.isRequested = true
if lesson.cardNotOk
lesson.displayStatus = 'No Card'
else
lesson.displayStatus = 'Requested'
if lesson['is_active?'] && (lesson.status == 'approved' )
if lesson['is_active?'] && (lesson.status == 'approved' && !lesson.lesson_booking['is_countered?'])
lesson.isScheduled = true
lesson.displayStatus = 'Scheduled'

View File

@ -69,18 +69,20 @@ class ApiLessonSessionsController < ApiController
# check if within 24 hours
if params[:update_all]
# check if the next scheduled lesson is doable
if 15.minutes.from_now > @lesson_session.lesson_booking.next_lesson.music_session.scheduled_start
response = {message: 'time_limit'}
render :json => response, :status => 422
return
end
else
if 15.minutes.from_now > @lesson_session.music_session.scheduled_start
response = {message: 'time_limit'}
render :json => response, :status => 422
return
if @lesson_session.is_approved?
if params[:update_all]
# check if the next scheduled lesson is doable
if 15.minutes.from_now > @lesson_session.lesson_booking.next_lesson.music_session.scheduled_start
response = {message: 'time_limit'}
render :json => response, :status => 422
return
end
else
if 15.minutes.from_now > @lesson_session.music_session.scheduled_start
response = {message: 'time_limit'}
render :json => response, :status => 422
return
end
end
end
@ -88,21 +90,23 @@ class ApiLessonSessionsController < ApiController
end
def cancel_check
if @lesson_session.student.id == current_user.id
# check if within 24 hours
if @lesson_session.is_approved?
if @lesson_session.student.id == current_user.id
# check if within 24 hours
if params[:update_all]
# check if the next scheduled lesson is doable
if 24.hours.from_now > @lesson_session.lesson_booking.next_lesson.music_session.scheduled_start
response = {message: 'time_limit'}
render :json => response, :status => 422
return
end
else
if 24.hours.from_now > @lesson_session.music_session.scheduled_start
response = {message: 'time_limit'}
render :json => response, :status => 422
return
if params[:update_all]
# check if the next scheduled lesson is doable
if 24.hours.from_now > @lesson_session.lesson_booking.next_lesson.music_session.scheduled_start
response = {message: 'time_limit'}
render :json => response, :status => 422
return
end
else
if 24.hours.from_now > @lesson_session.music_session.scheduled_start
response = {message: 'time_limit'}
render :json => response, :status => 422
return
end
end
end
end
@ -142,14 +146,15 @@ class ApiLessonSessionsController < ApiController
end
def rating_decision
if params[:as_student]
if params[:as_student] == "false"
teacher = User.find(params[:teacher_id])
lessons = current_user.lessons_with_teacher(teacher)
rating = current_user.teacher_rating(teacher.teacher).first
else
student = User.find(params[:student_id])
lessons = teacher.lessons_with_student(student)
rating = teacher.student_rating(student).first
else
teacher = User.find(params[:teacher_id])
lessons = current_user.lessons_with_teacher(teacher)
rating = current_user.teacher_rating(teacher.teacher).first
end
render :json => {lesson_count: lessons.count, rating: rating}, :status => 200

View File

@ -15,7 +15,10 @@ child(:alt_slot => :alt_slot) {
}
child(:counter_slot => :counter_slot) {
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package, :is_recurring?
node :pretty_scheduled_start_with_timezone do |slot|
pretty_scheduled_start_slot(slot, true)
end
}

View File

@ -14,13 +14,13 @@ end
child(:lesson_booking => :lesson_booking) {
attributes :card_presumed_ok, :test_drive_package_choice_id, :no_slots
attributes :card_presumed_ok, :test_drive_package_choice_id, :no_slots, :is_countered?
}
child(:counter_slot => :counter_slot) {
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package, :is_recurring?
node :pretty_scheduled_start_with_timezone do |slot|
pretty_scheduled_start_slot(slot, true)
end

View File

@ -9,9 +9,9 @@
<!--<link href='http://fonts.googleapis.com/css?family=Raleway:100,200,300,400,500,600,700' rel='stylesheet' type='text/css'>-->
<%= stylesheet_link_tag "client/client", media: "all" %>
<%= include_gon %>
<% if Rails.env.test? %>
<!--<% if Rails.env.test? %>
<%= javascript_include_tag "sinon" %>
<% end %>
<% end %>-->
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
<meta name="description" content="Enter here to browse the JamKazam platform">

View File

@ -90,10 +90,10 @@ describe "Activate Account Card", :js => true, :type => :feature, :capybara_feat
user1.reload
amazon_2_free_card.reload
amazon_2_free_card.user.should eq(user)
amazon_2_free_card.user.should eq(user1)
amazon_2_free_card.requires_purchase.should be false
amazon_2_free_card.purchased.should be true
user.jamclass_credits.should eq(amazon_2_free_card.credits)
user1.jamclass_credits.should eq(amazon_2_free_card.credits)
end
end
@ -105,7 +105,7 @@ describe "Activate Account Card", :js => true, :type => :feature, :capybara_feat
find('button.redeem-giftcard').trigger(:click)
find('.errors.active', text: "Coupon Code does not exist")
find('.errors.active', text: "This is not a valid code. Please carefully re-enter the code and try again. If it still does not work, please email us at support@jamkazam.com to report this problem.")
fill_in "code", with: amazon_2_free_card.code
@ -117,10 +117,10 @@ describe "Activate Account Card", :js => true, :type => :feature, :capybara_feat
user1.reload
amazon_2_free_card.reload
amazon_2_free_card.user.should eq(user)
amazon_2_free_card.user.should eq(user1)
amazon_2_free_card.requires_purchase.should be false
amazon_2_free_card.purchased.should be true
user.jamclass_credits.should eq(amazon_2_free_card.credits)
user1.jamclass_credits.should eq(amazon_2_free_card.credits)
end
end
end

View File

@ -1656,15 +1656,3 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d
end
end
npm run netsuite-sync -- -u dist/js/pageInit_salesorder.js -f 8433
npm run netsuite-sync -- -u dist/netsuite/client-scripts/cs_promotion.js -f 3577
npm run netsuite-sync -- -u dist/js/line-items.js -f 8433
npm run netsuite-sync -- -u dist/js/popup.js -f 8433
npm run netsuite-sync -- -u dist/netsuite/userevents/salesorder.js -f 3553
npm run netsuite-sync -- -u dist/netsuite/userevents/estimate.js -f 3553
npm run netsuite-sync -- -u dist/netsuite/userevents/so_inject.js -f 3553
npm run netsuite-sync -- -u dist/html/line-item-viewer.html -f 8432
npm run netsuite-sync -- -u dist/html/popup.html -f 8432

View File

@ -25,7 +25,9 @@ describe "Lesson Booking Status page", :js => true, :type => :feature, :capybara
find('h2', text: 'your lesson has been requested')
find('p.proposing-new-time')
#find('p.proposing-new-time')
find('.slot-decision-field label', text: 'Propose alternate day/time')
screenshot
end
@ -83,7 +85,7 @@ describe "Lesson Booking Status page", :js => true, :type => :feature, :capybara
fast_signin(user, "/client#/jamclass/lesson-booking/" + lesson.id)
find('h2', text: "this lesson was canceled (student)")
find('h2', text: "this lesson was canceled (by student)")
screenshot
end
@ -99,7 +101,7 @@ describe "Lesson Booking Status page", :js => true, :type => :feature, :capybara
fast_signin(user, "/client#/jamclass/lesson-booking/" + lesson.id)
find('h2', text: "this lesson was missed (both)")
find('h2', text: "this lesson was missed (by both)")
screenshot
end
@ -161,7 +163,7 @@ describe "Lesson Booking Status page", :js => true, :type => :feature, :capybara
fast_signin(teacher, "/client#/jamclass/lesson-booking/" + lesson.id)
find('h2', text: "this lesson was canceled (student)")
find('h2', text: "this lesson was canceled (by student)")
screenshot
end
@ -171,7 +173,7 @@ describe "Lesson Booking Status page", :js => true, :type => :feature, :capybara
fast_signin(teacher, "/client#/jamclass/lesson-booking/" + lesson.id)
find('h2', text: "this lesson was missed (both)")
find('h2', text: "this lesson was missed (by both)")
screenshot
end
@ -258,9 +260,7 @@ describe "Lesson Booking Status page", :js => true, :type => :feature, :capybara
fast_signin(user, "/client#/jamclass/lesson-booking/" + lesson.lesson_booking.id + "_rescheduling")
find('.request-sent', text: 'Your request has been sent.')
page.should_not have_selector('p.proposing-new-time')
find('p.proposing-new-time')
switch_user(teacher, "/client#/jamclass/lesson-booking/" + lesson.lesson_booking.id + "_rescheduling")

View File

@ -1,5 +1,5 @@
// Teaspoon includes some support files, but you can use anything from your own support path too.
// require support/sinon
// require support/sinon
// require support/chai
// require support/expect
// require support/jasmine-jquery-1.7.0
@ -30,6 +30,6 @@
// You can require your own javascript files here. By default this will include everything in application, however you
// may get better load performance if you require the specific files that are being used in the spec that tests them.
//= require application
//= require support/sinon
// //= require support/sinon
// require support/expect
//= require support/jasmine-jquery-1.7.0