From d0bbf92dd1b0f4f100127b1b1d303280e0a42af4 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Sun, 14 Jan 2018 10:12:15 -0600 Subject: [PATCH] booking prices in --- admin/README.md | 4 ++ admin/app/admin/jam_ruby_artifact_updates.rb | 2 - admin/app/admin/lesson_session.rb | 17 +++++ admin/app/admin/teachers.rb | 62 +++++++++++++++++-- admin/app/helpers/json_input.rb | 2 + ruby/lib/jam_ruby/models/lesson_session.rb | 15 ++++- ruby/lib/jam_ruby/models/teacher.rb | 20 +++++- .../jam_ruby/flows/testdrive_lesson_spec.rb | 3 + 8 files changed, 114 insertions(+), 11 deletions(-) create mode 100644 admin/app/helpers/json_input.rb diff --git a/admin/README.md b/admin/README.md index d1aff509d..4054c1390 100644 --- a/admin/README.md +++ b/admin/README.md @@ -8,3 +8,7 @@ Immediately the focus is on using active_scaffolding that provides visibility in Overtime we can add more administrative functions and views, but initially this is one of the easiest ways to give 'powertools' behind the scenes with an entirely separate authentication model. + +Examples of: + +Button on Show Page of Item: 'Send Client Update Notice' in jam_ruby_artifact_updates.rb \ No newline at end of file diff --git a/admin/app/admin/jam_ruby_artifact_updates.rb b/admin/app/admin/jam_ruby_artifact_updates.rb index e2a45afe4..de0a4f65b 100644 --- a/admin/app/admin/jam_ruby_artifact_updates.rb +++ b/admin/app/admin/jam_ruby_artifact_updates.rb @@ -18,10 +18,8 @@ ActiveAdmin.register JamRuby::ArtifactUpdate, :as => 'Artifacts' do end f.actions - end - action_item :only => [:show] do link_to('Send Client Update Notice', send_client_update_notice_admin_artifact_path(resource.id)) end diff --git a/admin/app/admin/lesson_session.rb b/admin/app/admin/lesson_session.rb index 51477d292..376c0cc98 100644 --- a/admin/app/admin/lesson_session.rb +++ b/admin/app/admin/lesson_session.rb @@ -16,6 +16,18 @@ ActiveAdmin.register JamRuby::LessonSession, :as => 'LessonSessions' do scope("Missed") { |scope| scope.unscoped.missed.order('created_at desc') } scope("Completed") { |scope| scope.unscoped.completed.order('created_at desc') } + action_item :only => [:show] do + link_to('Mark As Success', mark_success_admin_lesson_session_path(resource.id)) + end + + member_action :mark_success, :method => :get do + if !resource.success + resource.mark_lesson(true, true) + end + redirect_to :back + + end + index do column "Actions" do |teacher| links = ''.html_safe @@ -64,6 +76,11 @@ ActiveAdmin.register JamRuby::LessonSession, :as => 'LessonSessions' do show do attributes_table do + row "Lesson Booking" do |lesson_session| + span do + link_to "Lesson Booking", lesson_session.lesson_booking.admin_url + end + end row "App Link" do |lesson_session| lesson_booking = lesson_session.lesson_booking span do diff --git a/admin/app/admin/teachers.rb b/admin/app/admin/teachers.rb index 7dc2529a0..86817f171 100644 --- a/admin/app/admin/teachers.rb +++ b/admin/app/admin/teachers.rb @@ -10,8 +10,8 @@ ActiveAdmin.register JamRuby::Teacher, :as => 'Teachers' do scope("All", default: true) { |scope| scope.unscoped.order("background_check_at > '#{(Date.today - 365).to_s}}' NULLS FIRST, ready_for_session_at IS NULL DESC") } scope("All Sorted By Sign Up") { |scope| scope.unscoped.order("teachers.created_at DESC, background_check_at > '#{(Date.today - 365).to_s}}' NULLS FIRST, ready_for_session_at IS NULL DESC") } - scope("50% and Session Ready" ) { |scope| scope.unscoped.where('profile_pct >= ?', 50.0).where('ready_for_session_at IS NOT NULL').order("background_check_at > '#{(Date.today - 365).to_s}}' NULLS FIRST, ready_for_session_at IS NULL DESC") } - scope("50% and Not Session Ready" ) { |scope| scope.unscoped.where('profile_pct > ?', 50.0).where('ready_for_session_at IS NULL').order("background_check_at > '#{(Date.today - 365).to_s}}' NULLS FIRST, ready_for_session_at IS NULL DESC") } + scope("50% and Session Ready") { |scope| scope.unscoped.where('profile_pct >= ?', 50.0).where('ready_for_session_at IS NOT NULL').order("background_check_at > '#{(Date.today - 365).to_s}}' NULLS FIRST, ready_for_session_at IS NULL DESC") } + scope("50% and Not Session Ready") { |scope| scope.unscoped.where('profile_pct > ?', 50.0).where('ready_for_session_at IS NULL').order("background_check_at > '#{(Date.today - 365).to_s}}' NULLS FIRST, ready_for_session_at IS NULL DESC") } index do column "Name" do |teacher| @@ -156,21 +156,25 @@ ActiveAdmin.register JamRuby::Teacher, :as => 'Teachers' do br br div do - h5 do "Completed Sections" end + h5 do + "Completed Sections" + end teacher.pct_complete.each do |k, v| if k != :pct && v div do - k + k end end end br br - h5 do "Uncompleted Sections" end + h5 do + "Uncompleted Sections" + end teacher.pct_complete.each do |k, v| if k != :pct && !v div do - k + k end end end @@ -274,6 +278,52 @@ ActiveAdmin.register JamRuby::Teacher, :as => 'Teachers' do end end + row "Booking Prices" do |teacher| + div do + table = teacher.booking_price_table + if table[:single].length == 0 and table[:monthly].length == 0 + 'No Pricing' + else + if table[:single].length > 0 + div do + span do + 'SINGLE' + end + span do + br + end + table[:single].each do |single| + span do + "#{single[:minutes]} min = $#{'%.2f' % (single[:price]/100.0)}" + end + span do + br + end + end + end + end + if table[:monthly].length > 0 + div do + span do + 'MONTHLY' + end + span do + br + end + table[:monthly].each do |monthly| + span do + "#{monthly[:minutes]} min = $#{'%.2f' % (monthly[:price]/100.0)}" + end + span do + br + end + end + end + end + end + + end + end end end diff --git a/admin/app/helpers/json_input.rb b/admin/app/helpers/json_input.rb new file mode 100644 index 000000000..a1f402ebe --- /dev/null +++ b/admin/app/helpers/json_input.rb @@ -0,0 +1,2 @@ +class JsonInput < Formtastic::Inputs::StringInput +end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/lesson_session.rb b/ruby/lib/jam_ruby/models/lesson_session.rb index 67ddc40f2..a4feb1010 100644 --- a/ruby/lib/jam_ruby/models/lesson_session.rb +++ b/ruby/lib/jam_ruby/models/lesson_session.rb @@ -171,15 +171,16 @@ module JamRuby end end + # give 2 days to auto-cancel; this lets people just jump in a session and mark it done def self.auto_cancel - 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| + MusicSession.joins(lesson_session: :lesson_booking).where('lesson_sessions.status = ? OR lesson_bookings.status = ?', LessonSession::STATUS_REQUESTED, LessonBooking::STATUS_COUNTERED).where("? > scheduled_start + (INTERVAL '2 days' * (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 = ? 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| + MusicSession.joins(lesson_session: :lesson_booking).where('(lesson_sessions.status = ? OR lesson_sessions.status = ?) AND lesson_bookings.status != ?', LessonSession::STATUS_APPROVED, LessonBooking::STATUS_REQUESTED, 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 @@ -218,6 +219,12 @@ module JamRuby end def mark_lesson(success, administratively_marked = false) + if !self.success && (is_requested? || is_unconfirmed?) + # what's going on here is that we will just mark a session as a success if the the people got in in case of requested sessions + # but otherwise, leave it alone, so that the people can after-the-fact reschedule it (don't close it out and treat as a failure) + return + end + self.success = success self.analysed_at = Time.now self.analysed = true @@ -576,6 +583,10 @@ module JamRuby status == STATUS_COUNTERED end + def is_unconfirmed? + status == STATUS_UNCONFIRMED + end + def analysis_json @parsed_analysis || analysis end diff --git a/ruby/lib/jam_ruby/models/teacher.rb b/ruby/lib/jam_ruby/models/teacher.rb index fa87417e2..91a8b0532 100644 --- a/ruby/lib/jam_ruby/models/teacher.rb +++ b/ruby/lib/jam_ruby/models/teacher.rb @@ -327,6 +327,24 @@ module JamRuby end end + def booking_price_table + table = {single:[], monthly:[]} + durations_allowed = [] + [30, 45, 60, 90, 120].each do |i| + durations_allowed << i if self["lesson_duration_#{i}"] + end + + durations_allowed.each do |i| + if self["price_per_lesson_#{i}_cents"] + table[:single] << {minutes: i, price: self["price_per_lesson_#{i}_cents"]} + end + if self["price_per_month_#{i}_cents"] + table[:monthly] << {minutes: i, price: self["price_per_month_#{i}_cents"]} + end + end + table + end + def offer_pricing unless prices_per_lesson.present? || prices_per_month.present? errors.add(:offer_pricing, "Must choose to price per lesson or per month") @@ -478,7 +496,7 @@ module JamRuby elsif instruments.length == 2 return 'Teaches ' + instruments[0].description + ' and ' + instruments[1].description else - return 'Teaches ' + instruments.map {|i| i.description}.join(', ') + return 'Teaches ' + instruments.map { |i| i.description }.join(', ') end end end diff --git a/ruby/spec/jam_ruby/flows/testdrive_lesson_spec.rb b/ruby/spec/jam_ruby/flows/testdrive_lesson_spec.rb index a4a3996c5..ca7d90f28 100644 --- a/ruby/spec/jam_ruby/flows/testdrive_lesson_spec.rb +++ b/ruby/spec/jam_ruby/flows/testdrive_lesson_spec.rb @@ -251,6 +251,9 @@ describe "TestDrive Lesson Flow" do LessonBooking.bookings(user, teacher_user, nil).count.should eql 1 LessonBooking.engaged_bookings(user, teacher_user, nil).count.should eql 1 teacher_user.has_booked_test_drive_with_student?(user).should be_true + + booking.reload + booking.lesson_sessions.length.should eql 1 end it "works using posa card" do