diff --git a/ruby/lib/jam_ruby/models/lesson_session.rb b/ruby/lib/jam_ruby/models/lesson_session.rb index a41f248bc..b9d5cba49 100644 --- a/ruby/lib/jam_ruby/models/lesson_session.rb +++ b/ruby/lib/jam_ruby/models/lesson_session.rb @@ -116,7 +116,7 @@ module JamRuby 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' * (3 + duration))").where('analysed = false').each do |music_session| + 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 end @@ -124,7 +124,7 @@ module JamRuby 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' * (3 + duration))").where('analysed = true').where('lesson_sessions.post_processed = false').where('billing_should_retry = true').each do |music_session| + 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 end @@ -158,6 +158,11 @@ module JamRuby analysis = LessonSessionAnalyser.analyse(self) self.analysis = LessonSession.analysis_to_json(analysis) + + if analysis[:reason] == LessonSessionAnalyser::SESSION_ONGOING + # extra protection against bad code somewhere + return + end self.success = analysis[:bill] self.analysed_at = Time.now self.analysed = true @@ -265,11 +270,11 @@ module JamRuby end def student_missed - analysed && analysis_json["student_analysis"]["missed"] + analysed && !success && analysis_json["student_analysis"]["missed"] end def teacher_missed - analysed && analysis_json["student_analysis"]["missed"] + analysed && !success && analysis_json["teacher_analysis"]["missed"] end def error_display diff --git a/ruby/spec/jam_ruby/flows/testdrive_lesson_spec.rb b/ruby/spec/jam_ruby/flows/testdrive_lesson_spec.rb index ecba48297..5db43fb37 100644 --- a/ruby/spec/jam_ruby/flows/testdrive_lesson_spec.rb +++ b/ruby/spec/jam_ruby/flows/testdrive_lesson_spec.rb @@ -177,7 +177,8 @@ describe "TestDrive Lesson Flow" do UserMailer.deliveries.clear # background code comes around and analyses the session - LessonSession.hourly_check + lesson.analyse + lesson.session_completed lesson_session.reload lesson_session.analysed.should be_true analysis = JSON.parse(lesson_session.analysis) @@ -196,6 +197,13 @@ describe "TestDrive Lesson Flow" do user.reload user.remaining_test_drives.should eql 1 UserMailer.deliveries.length.should eql 2 # one for student, one for teacher + found_student_email = false + UserMailer.deliveries.each do |d| + if d.subject == "You have used 1 of 2 TestDrive lesson credits" + found_student_email = true + end + end + found_student_email.should be_true teacher_distribution = lesson_session.teacher_distribution teacher_distribution.amount_in_cents.should eql 1000 @@ -285,6 +293,22 @@ describe "TestDrive Lesson Flow" do user.remaining_test_drives.should eql 4 end + it "post-lesson emails" do + UserMailer.deliveries.clear + lesson = testdrive_lesson(user, teacher_user, {accept:true, success: true}) + + user.reload + user.remaining_test_drives.should eql 3 + + found_student_email = false + UserMailer.deliveries.each do |d| + if d.subject == "You have used 1 of 4 TestDrive lesson credits" + found_student_email = true + end + end + found_student_email.should be_true + end + # tests that the correct emails are sent out after test drives are done it "both no show, then student no shows" do UserMailer.deliveries.clear @@ -352,7 +376,5 @@ describe "TestDrive Lesson Flow" do # You successfully completed a lesson with #{@student.name}" completed_test_drive.should be_true paid.should be_true - - end end diff --git a/ruby/spec/support/lesson_session.rb b/ruby/spec/support/lesson_session.rb index e73968554..699037ecc 100644 --- a/ruby/spec/support/lesson_session.rb +++ b/ruby/spec/support/lesson_session.rb @@ -82,12 +82,28 @@ def book_lesson(user, teacher, options) end if options[:miss] + # teacher & student get into session + + Timecop.travel(end_time + 1) + lesson.analyse + lesson.session_completed + elsif options[:teacher_miss] + uh2 = FactoryGirl.create(:music_session_user_history, user: user, history: lesson.music_session, created_at: start, session_removed_at: end_time) + # artificially end the session, which is covered by other background jobs + lesson.music_session.session_removed_at = end_time + lesson.music_session.save! + Timecop.travel(end_time + 1) + lesson.analyse + lesson.session_completed + elsif options[:success] + uh1 = FactoryGirl.create(:music_session_user_history, user: user, history: lesson.music_session, created_at: start, session_removed_at: end_time) + uh2 = FactoryGirl.create(:music_session_user_history, user: teacher, history: lesson.music_session, created_at: start, session_removed_at: end_time) + # artificially end the session, which is covered by other background jobs + lesson.music_session.session_removed_at = end_time + lesson.music_session.save! Timecop.travel(end_time + 1) - - lesson.analyse lesson.session_completed - elsif options[:finish] # teacher & student get into session uh2 = FactoryGirl.create(:music_session_user_history, user: teacher, history: lesson.music_session, created_at: start, session_removed_at: end_time) diff --git a/web/app/assets/javascripts/react-components/JamClassScreen.js.jsx.coffee b/web/app/assets/javascripts/react-components/JamClassScreen.js.jsx.coffee index 8e733943d..0969188d4 100644 --- a/web/app/assets/javascripts/react-components/JamClassScreen.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/JamClassScreen.js.jsx.coffee @@ -243,7 +243,7 @@ LessonTimerActions = context.LessonTimerActions cancelLesson: (lesson) -> - if lesson.isRequested + if lesson.isRequested && @viewerTeacher() confirmTitle = 'Confirm Decline' verbLower = 'decline' else diff --git a/web/app/assets/javascripts/react-components/LessonBooking.js.jsx.coffee b/web/app/assets/javascripts/react-components/LessonBooking.js.jsx.coffee index b80a92908..b942ab538 100644 --- a/web/app/assets/javascripts/react-components/LessonBooking.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/LessonBooking.js.jsx.coffee @@ -580,16 +580,13 @@ UserStore = context.UserStore completedHeader: () -> if @isNow() header = 'the lesson is scheduled for right now!' - else if @isPast() + else if @isMissed() header = "this lesson was #{this.displayableLesson().displayStatus.toLowerCase()}" else if @isSuspended() header = 'this lesson was suspended due to billing issues' else header = 'this lesson is over' - else - header = 'this lesson is over' - header approvedHeader: () -> if @isCompleted() @@ -735,7 +732,7 @@ UserStore = context.UserStore whatNow = null summary = `
{this.userHeader(this.displayableLesson().missedUser)} -

This lesson was missed by the {this.displayableLesson().missedRole}.

+

This lesson was missed by {this.displayableLesson().missedRole}.

` else if @isSuspended() whatNow = `
@@ -836,7 +833,7 @@ UserStore = context.UserStore whatNow = null summary = `
{this.userHeader(this.displayableLesson().missedUser)} -

This lesson was missed by the {this.displayableLesson().missedRole}.

+

This lesson was missed by {this.displayableLesson().missedRole}.

` else if @isSuspended() whatNow = `
diff --git a/web/app/assets/javascripts/react-components/mixins/PostProcessorMixin.js.coffee b/web/app/assets/javascripts/react-components/mixins/PostProcessorMixin.js.coffee index 7657a7182..4af579cc2 100644 --- a/web/app/assets/javascripts/react-components/mixins/PostProcessorMixin.js.coffee +++ b/web/app/assets/javascripts/react-components/mixins/PostProcessorMixin.js.coffee @@ -46,26 +46,26 @@ teacherActions = window.JK.Actions.Teacher lesson.displayStatus = 'Suspended' else lesson.missed = true - lesson.missedRole = 'teacher' + lesson.missedRole = 'the teacher' lesson.missedUser = lesson.teacher - if lesson.analysis?.teacher_analysis?.missed && lesson.analysis?.student_analysis?.missed - lesson.missedRole = 'both' - lesson.missedUser = lesson.teacher - lesson.displayStatus = 'Missed (Both)' - else if lesson.analysis?.teacher_analysis?.missed - lesson.missedRole = 'teacher' - lesson.missedUser = lesson.teacher - lesson.displayStatus = 'Missed (Teacher)' - else if lesson.analysis?.student_analysis?.missed - lesson.missedRole = 'student' - lesson.missedUser = lesson.student - lesson.displayStatus = 'Missed (Student)' + if lesson.success + lesson.missed = false + lesson.missedRole = null + lesson.displayStatus = 'Completed' else - if lesson.success - lesson.missed = false - lesson.missedRole = null - lesson.displayStatus = 'Completed' + if lesson.analysis?.teacher_analysis?.missed && lesson.analysis?.student_analysis?.missed + lesson.missedRole = 'both student and teacher' + lesson.missedUser = lesson.teacher + lesson.displayStatus = 'Missed (Both)' + else if lesson.analysis?.teacher_analysis?.missed + lesson.missedRole = 'the teacher' + lesson.missedUser = lesson.teacher + lesson.displayStatus = 'Missed (Teacher)' + else if lesson.analysis?.student_analysis?.missed + lesson.missedRole = 'the student' + lesson.missedUser = lesson.student + lesson.displayStatus = 'Missed (Student)' else lesson.displayStatus = 'Missed' diff --git a/web/spec/features/jamclass_screen_spec.rb b/web/spec/features/jamclass_screen_spec.rb index 3b1c584cb..b15da2cb8 100644 --- a/web/spec/features/jamclass_screen_spec.rb +++ b/web/spec/features/jamclass_screen_spec.rb @@ -25,7 +25,7 @@ describe "JamClassScreen", :js => true, :type => :feature, :capybara_feature => fast_signin(user, "/client#/jamclass") - find('#jam-class-student-screen td.displayStatusColumn', text: 'Missed (Student)') + find('#jam-class-student-screen td.displayStatusColumn', text: 'Completed') end it "shows Missed (Teacher)" do @@ -61,7 +61,12 @@ describe "JamClassScreen", :js => true, :type => :feature, :capybara_feature => # open up hover find('tr[data-lesson-session-id="' + lesson.id + '"] .lesson-session-actions-btn').trigger(:click) - find('li[data-lesson-option="cancel"] a', visible: false, text: 'Decline Request') + find('li[data-lesson-option="cancel"] a', visible: false, text: 'Decline Request').trigger(:click) + # confirm cancelation - + find('#banner h1', text: 'Confirm Decline') + find('#banner .dialog-inner', text:"Are you sure you want to decline this lesson?" ) + # don't cancel yet + find('#banner .no-btn', text: 'CANCEL').trigger(:click) lesson.teacher_unread_messages.should be_true # also check that clicking messages icon shows view status screen (instead of chat dialog) # VRFS-4089 @@ -81,6 +86,9 @@ describe "JamClassScreen", :js => true, :type => :feature, :capybara_feature => find('li[data-lesson-option="cancel"] a', visible: false, text: 'Cancel Request').trigger(:click) # confirm cancelation - + find('#banner h1', text: 'Confirm Cancelation') + find('#banner .dialog-inner', text:"Are you sure you want to cancel this lesson?" ) + find('#banner .yes-btn', text: 'YES').trigger(:click) find('#jam-class-student-screen td.displayStatusColumn', text: 'Canceled (Student)') diff --git a/web/spec/features/lesson_booking_status_spec.rb b/web/spec/features/lesson_booking_status_spec.rb index 8e0dc466b..3857d226e 100644 --- a/web/spec/features/lesson_booking_status_spec.rb +++ b/web/spec/features/lesson_booking_status_spec.rb @@ -87,9 +87,15 @@ describe "Lesson Booking Status page", :js => true, :type => :feature, :capybara it "missed" do lesson = testdrive_lesson(user, teacher, {accept:true, finish:false, miss: true}) + lesson.reload + lesson.status.should eql LessonSession::STATUS_COMPLETED + lesson.success.should be_false + lesson.student_missed.should be_true + lesson.teacher_missed.should be_true + fast_signin(user, "/client#/jamclass/lesson-booking/" + lesson.id) - find('h2', text: "this lesson was missed (teacher)") + find('h2', text: "this lesson was missed (both)") screenshot end @@ -161,7 +167,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 (teacher)") + find('h2', text: "this lesson was missed (both)") screenshot end diff --git a/web/spec/support/lessons.rb b/web/spec/support/lessons.rb index 533ee3055..03d601845 100644 --- a/web/spec/support/lessons.rb +++ b/web/spec/support/lessons.rb @@ -162,12 +162,28 @@ def book_lesson(user, teacher, options) end if options[:miss] + # teacher & student get into session + + Timecop.travel(end_time + 1) + lesson.analyse + lesson.session_completed + elsif options[:teacher_miss] + uh2 = FactoryGirl.create(:music_session_user_history, user: user, history: lesson.music_session, created_at: start, session_removed_at: end_time) + # artificially end the session, which is covered by other background jobs + lesson.music_session.session_removed_at = end_time + lesson.music_session.save! + Timecop.travel(end_time + 1) + lesson.analyse + lesson.session_completed + elsif options[:success] + uh1 = FactoryGirl.create(:music_session_user_history, user: user, history: lesson.music_session, created_at: start, session_removed_at: end_time) + uh2 = FactoryGirl.create(:music_session_user_history, user: teacher, history: lesson.music_session, created_at: start, session_removed_at: end_time) + # artificially end the session, which is covered by other background jobs + lesson.music_session.session_removed_at = end_time + lesson.music_session.save! Timecop.travel(end_time + 1) - - lesson.analyse lesson.session_completed - elsif options[:finish] # teacher & student get into session uh2 = FactoryGirl.create(:music_session_user_history, user: teacher, history: lesson.music_session, created_at: start, session_removed_at: end_time) diff --git a/websocket-gateway/lib/jam_websockets/router.rb b/websocket-gateway/lib/jam_websockets/router.rb index bec42b46b..c08488e64 100644 --- a/websocket-gateway/lib/jam_websockets/router.rb +++ b/websocket-gateway/lib/jam_websockets/router.rb @@ -1469,7 +1469,7 @@ module JamWebsockets user = User.find_by_id(user_id) unless user_id.nil? if music_session - msuh = MusicSessionUserHistory.where(client_id: cid).order('updated_at DESC').first + msuh = MusicSessionUserHistory.where(client_id: cid).order('created_at DESC').first if msuh msuh.session_removed_at = Time.now if msuh.session_removed_at.nil? msuh.save(validate:false)