diff --git a/db/manifest b/db/manifest index f9df5d1fe..6de316f20 100755 --- a/db/manifest +++ b/db/manifest @@ -343,4 +343,5 @@ teacher_progression.sql teacher_complete.sql lessons.sql lessons_unread_messages.sql -track_school_signups.sql \ No newline at end of file +track_school_signups.sql +add_test_drive_types.sql \ No newline at end of file diff --git a/db/up/add_test_drive_types.sql b/db/up/add_test_drive_types.sql new file mode 100644 index 000000000..01584db3d --- /dev/null +++ b/db/up/add_test_drive_types.sql @@ -0,0 +1,4 @@ +INSERT INTO lesson_package_types (id, name, description, package_type, price) VALUES ('test-drive-2', 'Test Drive (2)', 'Two reduced-price lessons which you can use to find that ideal teacher.', 'test-drive-2', 29.99); +INSERT INTO lesson_package_types (id, name, description, package_type, price) VALUES ('test-drive-1', 'Test Drive (1)', 'One reduced-price lessons which you can use to find that ideal teacher.', 'test-drive-1', 15.99); +UPDATE lesson_package_types set name = 'Test Drive (4)', package_type = 'test-drive-4' WHERE id = 'test-drive'; +ALTER TABLE users ADD COLUMN lesson_package_type_id VARCHAR(64) REFERENCES lesson_package_types(id); \ No newline at end of file diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_welcome_message.text.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_welcome_message.text.erb index aa851747f..0cff2ed3e 100644 --- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_welcome_message.text.erb +++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_welcome_message.text.erb @@ -18,7 +18,7 @@ TestDrive lets you take 4 full lessons (30 minutes each) from 4 different teache teacher for you. Finding the right teacher is the single most important determinant of success in your lessons. Would you marry the first person you ever dated? No? Same here. Pick 4 teachers who look great, and then see who you click with. It's a phenomenal value, and then you can stick with the best teacher for you. -Click this link to sign up now for TestDrive (https://www.jamkazam.com/client#/jamclass/book-lesson/purchase_test-drive). +Click this link to sign up now for TestDrive (https://www.jamkazam.com/client#/jamclass/test-drive-selection). Then you can book 4 TestDrive lessons to get rolling. 2. Set Up Your Gear diff --git a/ruby/lib/jam_ruby/models/lesson_booking.rb b/ruby/lib/jam_ruby/models/lesson_booking.rb index b42d72be9..206bacb6a 100644 --- a/ruby/lib/jam_ruby/models/lesson_booking.rb +++ b/ruby/lib/jam_ruby/models/lesson_booking.rb @@ -410,11 +410,26 @@ module JamRuby self.save end + def resolved_test_drive_package + result = nil + purchase = student.most_recent_test_drive_purchase + if purchase + # for lessons already packaged + result = purchase.lesson_package_type + else + # for unbooked lessons + result = student.desired_package + end + if result.nil? + result = LessonPackageType.test_drive_4 + end + result + end def lesson_package_type if is_single_free? LessonPackageType.single_free elsif is_test_drive? - LessonPackageType.test_drive + resolved_test_drive_package elsif is_normal? LessonPackageType.single end @@ -451,7 +466,7 @@ module JamRuby if is_single_free? 0 elsif is_test_drive? - LessonPackageType.test_drive.price + resolved_test_drive_package.price elsif is_normal? teacher.teacher.booking_price(lesson_length, payment_style != PAYMENT_STYLE_MONTHLY) end diff --git a/ruby/lib/jam_ruby/models/lesson_package_purchase.rb b/ruby/lib/jam_ruby/models/lesson_package_purchase.rb index 7662a2632..33e28f395 100644 --- a/ruby/lib/jam_ruby/models/lesson_package_purchase.rb +++ b/ruby/lib/jam_ruby/models/lesson_package_purchase.rb @@ -26,7 +26,7 @@ module JamRuby def validate_test_drive if user - if !user.can_buy_test_drive? + if lesson_package_type.is_test_drive? && !user.can_buy_test_drive? errors.add(:user, "can not buy test drive right now because you have already purchased it within the last year") end end @@ -42,7 +42,7 @@ module JamRuby def add_test_drives if self.lesson_package_type.is_test_drive? - new_test_drives = user.remaining_test_drives + 4 + new_test_drives = user.remaining_test_drives + lesson_package_type.test_drive_count User.where(id: user.id).update_all(remaining_test_drives: new_test_drives) user.remaining_test_drives = new_test_drives end @@ -79,7 +79,7 @@ module JamRuby end if lesson_booking - purchase.lesson_package_type = lesson_booking.lesson_package_type + purchase.lesson_package_type = lesson_package_type ? lesson_package_type : lesson_booking.lesson_package_type purchase.price = lesson_booking.booked_price if purchase.price.nil? else purchase.lesson_package_type = lesson_package_type diff --git a/ruby/lib/jam_ruby/models/lesson_package_type.rb b/ruby/lib/jam_ruby/models/lesson_package_type.rb index d60aaa14a..d151e1355 100644 --- a/ruby/lib/jam_ruby/models/lesson_package_type.rb +++ b/ruby/lib/jam_ruby/models/lesson_package_type.rb @@ -7,21 +7,29 @@ module JamRuby PRODUCT_TYPE = 'LessonPackageType' SINGLE_FREE = 'single-free' - TEST_DRIVE = 'test-drive' + TEST_DRIVE_4 = 'test-drive' + TEST_DRIVE_2 = 'test-drive-2' + TEST_DRIVE_1 = 'test-drive-1' SINGLE = 'single' LESSON_PACKAGE_TYPES = [ SINGLE_FREE, - TEST_DRIVE, + TEST_DRIVE_4, + TEST_DRIVE_2, + TEST_DRIVE_1, SINGLE ] + has_many :user_desired_packages, class_name: "JamRuby::User", :foreign_key => "lesson_package_type_id", inverse_of: :desired_package validates :name, presence: true validates :description, presence: true validates :price, presence: true validates :package_type, presence: true, inclusion: {in: LESSON_PACKAGE_TYPES} + def self.test_drive_package_ids + [TEST_DRIVE_4, TEST_DRIVE_2, TEST_DRIVE_1] + end def self.monthly LessonPackageType.find(MONTHLY) end @@ -30,8 +38,16 @@ module JamRuby LessonPackageType.find(SINGLE_FREE) end - def self.test_drive - LessonPackageType.find(TEST_DRIVE) + def self.test_drive_4 + LessonPackageType.find(TEST_DRIVE_4) + end + + def self.test_drive_2 + LessonPackageType.find(TEST_DRIVE_2) + end + + def self.test_drive_1 + LessonPackageType.find(TEST_DRIVE_1) end def self.single @@ -42,17 +58,21 @@ module JamRuby if is_single_free? 0 elsif is_test_drive? - LessonPackageType.test_drive.price + 10.00 elsif is_normal? lesson_booking.booked_price #teacher.teacher.booking_price(lesson_booking.lesson_length, lesson_booking.payment_style == LessonBooking::PAYMENT_STYLE_SINGLE) end end + def test_drive_count + package_type["test-drive-".length, 1].to_i + end + def description(lesson_booking) if is_single_free? "Single Free Lesson" elsif is_test_drive? - "Test Drive" + "Test Drive (#{test_drive_count})" elsif is_normal? if lesson_booking.recurring "Recurring #{lesson_booking.payment_style == LessonBooking::PAYMENT_STYLE_WEEKLY ? "Weekly" : "Monthly"} #{lesson_booking.lesson_length}m" @@ -71,7 +91,7 @@ module JamRuby end def is_test_drive? - id == TEST_DRIVE + id.start_with?('test-drive') end def is_normal? @@ -86,8 +106,12 @@ module JamRuby def plan_code if package_type == SINGLE_FREE "lesson-package-single-free" - elsif package_type == TEST_DRIVE - "lesson-package-test-drive" + elsif package_type == 'test-drive-4' + "lesson-package-test-drive-4" + elsif package_type == TEST_DRIVE_2 + "lesson-package-test-drive-2" + elsif package_type == TEST_DRIVE_1 + "lesson-package-test-drive-1" elsif package_type == SINGLE "lesson-package-single" else diff --git a/ruby/lib/jam_ruby/models/sale.rb b/ruby/lib/jam_ruby/models/sale.rb index 5cbd4f9d7..d3827ed84 100644 --- a/ruby/lib/jam_ruby/models/sale.rb +++ b/ruby/lib/jam_ruby/models/sale.rb @@ -208,8 +208,8 @@ module JamRuby free && non_free end - def self.purchase_test_drive(current_user, booking = nil) - self.purchase_lesson(current_user, booking, LessonPackageType.test_drive) + def self.purchase_test_drive(current_user, lesson_package_type, booking = nil) + self.purchase_lesson(current_user, booking, lesson_package_type) end def self.purchase_normal(current_user, booking) @@ -273,6 +273,7 @@ module JamRuby purchase = LessonPackagePurchase.create(current_user, lesson_booking, lesson_package_type) if purchase.nil? if purchase.errors.any? + puts "purchase errors #{purchase.errors.inspect}" price_info = {} price_info[:purchase] = purchase return price_info diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index 849828f8f..08c985e9c 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -51,7 +51,7 @@ module JamRuby has_many :user_authorizations, :class_name => "JamRuby::UserAuthorization" has_many :reviews, :class_name => "JamRuby::Review" - has_one :review_summary, :class_name => "JamRuby::ReviewSummary" + has_one :review_summary, :class_name => "JamRuby::ReviewSummary" # calendars (for scheduling NOT in music_session) has_many :calendars, :class_name => "JamRuby::Calendar" @@ -71,7 +71,7 @@ module JamRuby has_many :band_musicians, :class_name => "JamRuby::BandMusician" has_many :bands, :through => :band_musicians, :class_name => "JamRuby::Band" has_one :teacher, :class_name => "JamRuby::Teacher" - + # genres has_many :genre_players, as: :player, class_name: "JamRuby::GenrePlayer", dependent: :destroy has_many :genres, through: :genre_players, class_name: "JamRuby::Genre" @@ -176,6 +176,7 @@ module JamRuby has_many :teacher_lesson_bookings, :class_name => "JamRuby::LessonBooking", :foreign_key => "teacher_id", inverse_of: :teacher has_many :teacher_distributions, :class_name => "JamRuby::TeacherDistribution", :foreign_key => "teacher_id", inverse_of: :teacher has_many :teacher_payments, :class_name => "JamRuby::TeacherPayment", :foreign_key => "teacher_id", inverse_of: :teacher + belongs_to :desired_package, :class_name => "JamRuby::LessonPackageType", :foreign_key => "lesson_package_type_id", inverse_of: :user_desired_packages # used to hold whether user last wanted test drive 4/2/1 # Shopping carts has_many :shopping_carts, :class_name => "JamRuby::ShoppingCart" @@ -260,6 +261,7 @@ module JamRuby teacher.update_profile_pct end end + def user_progression_fields @user_progression_fields ||= Set.new ["first_downloaded_client_at", "first_ran_client_at", "first_music_session_at", "first_real_music_session_at", "first_good_music_session_at", "first_certified_gear_at", "first_invited_at", "first_friended_at", "first_recording_at", "first_social_promoted_at", "first_played_jamtrack_at"] end @@ -1127,7 +1129,7 @@ module JamRuby user.school_id = school_id elsif user.is_a_teacher school = School.find_by_id(school_id) - school_name = school ? school.name : 'a music school' + school_name = school ? school.name : 'a music school' user.teacher = Teacher.build_teacher(user, validate_introduction: true, biography: "Teaches for #{school_name}", school_id: school_id) end else @@ -1320,7 +1322,6 @@ module JamRuby end if affiliate_referral_id.present? - if user.is_a_student UserMailer.student_welcome_message(user).deliver end @@ -1897,7 +1898,7 @@ module JamRuby end def can_buy_test_drive? - lesson_purchases.where(lesson_package_type_id: LessonPackageType.test_drive.id).where('created_at > ?', APP_CONFIG.test_drive_wait_period_year.years.ago).count == 0 + lesson_purchases.where('lesson_package_type_id in (?)', LessonPackageType.test_drive_package_ids).where('created_at > ?', APP_CONFIG.test_drive_wait_period_year.years.ago).count == 0 end def has_test_drives? @@ -1946,6 +1947,7 @@ module JamRuby customer end + def card_approved(token, zip, booking_id) approved_booking = nil @@ -1993,6 +1995,7 @@ module JamRuby normal = nil intent = nil purchase = nil + lesson_package_type = nil User.transaction do if params[:name].present? @@ -2004,16 +2007,29 @@ module JamRuby booking = card_approved(params[:token], params[:zip], params[:booking_id]) if params[:test_drive] self.reload - result = Sale.purchase_test_drive(self, booking) + if booking + lesson_package_type = booking.resolved_test_drive_package + end + if lesson_package_type.nil? + lesson_package_type = LessonPackageType.test_drive_4 + end + + + result = Sale.purchase_test_drive(self, lesson_package_type, booking) test_drive = result[:sale] purchase = result[:purchase] + + if booking && !purchase.errors.any? + # the booking would not have a lesson_package_purchase associated yet, so let's associate it + booking.lesson_sessions.update_all(lesson_package_purchase_id: purchase.id) + end elsif params[:normal] self.reload end end - {lesson: booking, test_drive: test_drive, purchase: purchase} + {lesson: booking, test_drive: test_drive, purchase: purchase, lesson_package_type: lesson_package_type} end def requested_test_drive(teacher = nil) @@ -2033,7 +2049,7 @@ module JamRuby end def most_recent_test_drive_purchase - lesson_purchases.where(lesson_package_type_id: LessonPackageType.test_drive.id).order('created_at desc').first + lesson_purchases.where('lesson_package_type_id in (?)', [LessonPackageType.test_drive_package_ids]).order('created_at desc').first end def test_drive_succeeded(lesson_session) diff --git a/ruby/spec/factories.rb b/ruby/spec/factories.rb index 73c0a9fad..636414916 100644 --- a/ruby/spec/factories.rb +++ b/ruby/spec/factories.rb @@ -980,7 +980,7 @@ FactoryGirl.define do price 30.00 factory :test_drive_purchase do - lesson_package_type { JamRuby::LessonPackageType.test_drive } + lesson_package_type { JamRuby::LessonPackageType.test_drive_4 } association :lesson_booking, factory: :lesson_booking price 49.99 end diff --git a/ruby/spec/jam_ruby/flows/testdrive_lesson_spec.rb b/ruby/spec/jam_ruby/flows/testdrive_lesson_spec.rb index 2fca45714..6bc88f745 100644 --- a/ruby/spec/jam_ruby/flows/testdrive_lesson_spec.rb +++ b/ruby/spec/jam_ruby/flows/testdrive_lesson_spec.rb @@ -20,6 +20,9 @@ describe "TestDrive Lesson Flow" do it "works" do + user.desired_package = LessonPackageType.test_drive_2 + user.save! + # user has no test drives, no credit card on file, but attempts to book a lesson booking = LessonBooking.book_test_drive(user, teacher_user, valid_single_slots, "Hey I've heard of you before.") booking.errors.any?.should be_false @@ -28,20 +31,24 @@ describe "TestDrive Lesson Flow" do booking.card_presumed_ok.should be_false booking.should eql user.unprocessed_test_drive booking.sent_notices.should be_false + user.reload user.remaining_test_drives.should eql 0 ########## Need validate their credit card token = create_stripe_token - result = user.payment_update({token: token, zip: '78759', test_drive: true}) - user.reload - user.remaining_test_drives.should eql 3 + result = user.payment_update({token: token, zip: '78759', test_drive: true, booking_id: booking.id}) booking = result[:lesson] - lesson = booking.lesson_sessions[0] - test_drive = result[:test_drive] booking.errors.any?.should be_false + lesson = booking.lesson_sessions[0] + lesson.errors.any?.should be_false + test_drive = result[:test_drive] test_drive.errors.any?.should be_false + + user.reload + user.remaining_test_drives.should eql 1 + booking.card_presumed_ok.should be_true booking.sent_notices.should be_true lesson.music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0) @@ -49,20 +56,20 @@ describe "TestDrive Lesson Flow" do test_drive.stripe_charge_id.should_not be_nil - test_drive.recurly_tax_in_cents.should be 412 - test_drive.recurly_total_in_cents.should eql 4999 + 412 - test_drive.recurly_subtotal_in_cents.should eql 4999 + test_drive.recurly_tax_in_cents.should be 247 + test_drive.recurly_total_in_cents.should eql 2999 + 247 + test_drive.recurly_subtotal_in_cents.should eql 2999 test_drive.recurly_currency.should eql 'USD' line_item = test_drive.sale_line_items[0] line_item.quantity.should eql 1 line_item.product_type.should eql SaleLineItem::LESSON - line_item.product_id.should eq LessonPackageType.test_drive.id + line_item.product_id.should eq LessonPackageType.test_drive_2.id user.reload user.stripe_customer_id.should_not be nil user.lesson_purchases.length.should eql 1 - user.remaining_test_drives.should eql 3 + user.remaining_test_drives.should eql 1 lesson_purchase = user.lesson_purchases[0] - lesson_purchase.price.should eql 49.99 + lesson_purchase.price.should eql 29.99 lesson_purchase.lesson_package_type.is_test_drive?.should eql true customer = Stripe::Customer.retrieve(user.stripe_customer_id) @@ -173,11 +180,11 @@ describe "TestDrive Lesson Flow" do lesson_session.billing_error_reason.should be_nil lesson_session.sent_notices.should be true purchase = lesson_session.lesson_package_purchase - purchase.should_not be nil - purchase.price_in_cents.should eql 4999 + purchase.should_not be_nil + purchase.price_in_cents.should eql 2999 purchase.lesson_package_type.is_test_drive?.should be true user.reload - user.remaining_test_drives.should eql 3 + user.remaining_test_drives.should eql 1 UserMailer.deliveries.length.should eql 2 # one for student, one for teacher teacher_distribution = lesson_session.teacher_distribution diff --git a/ruby/spec/jam_ruby/models/sale_spec.rb b/ruby/spec/jam_ruby/models/sale_spec.rb index bc278b7e2..c00c8f5f6 100644 --- a/ruby/spec/jam_ruby/models/sale_spec.rb +++ b/ruby/spec/jam_ruby/models/sale_spec.rb @@ -731,7 +731,7 @@ describe Sale do line_item = sale.sale_line_items[0] line_item.quantity.should eql 1 line_item.product_type.should eql SaleLineItem::LESSON - line_item.product_id.should eq LessonPackageType.test_drive.id + line_item.product_id.should eq LessonPackageType.test_drive_4.id user.reload user.stripe_customer_id.should_not be nil @@ -778,7 +778,7 @@ describe Sale do line_item = sale.sale_line_items[0] line_item.quantity.should eql 1 line_item.product_type.should eql SaleLineItem::LESSON - line_item.product_id.should eq LessonPackageType.test_drive.id + line_item.product_id.should eq LessonPackageType.test_drive_4.id user.reload @@ -819,7 +819,7 @@ describe Sale do line_item = sale.sale_line_items[0] line_item.quantity.should eql 1 line_item.product_type.should eql SaleLineItem::LESSON - line_item.product_id.should eq LessonPackageType.test_drive.id + line_item.product_id.should eq LessonPackageType.test_drive_4.id end it "will reject second test drive purchase" do diff --git a/ruby/spec/support/lesson_session.rb b/ruby/spec/support/lesson_session.rb index 401dad8f4..1e13a3e15 100644 --- a/ruby/spec/support/lesson_session.rb +++ b/ruby/spec/support/lesson_session.rb @@ -33,7 +33,7 @@ def testdrive_lesson(user, teacher, slots = nil) booking.card_presumed_ok.should be_true if user.most_recent_test_drive_purchase.nil? - LessonPackagePurchase.create(user, booking, LessonPackageType.test_drive) + LessonPackagePurchase.create(user, booking, LessonPackageType.test_drive_4) end lesson.accept({message: 'Yeah I got this', slot: slots[0]}) @@ -66,7 +66,7 @@ def normal_lesson(user, teacher, slots = nil) booking.card_presumed_ok.should be_true #if user.most_recent_test_drive_purchase.nil? - # LessonPackagePurchase.create(user, booking, LessonPackageType.test_drive) + # LessonPackagePurchase.create(user, booking, LessonPackageType.test_drive_4) #end lesson.accept({message: 'Yeah I got this', slot: slots[0]}) diff --git a/web/app/assets/javascripts/helpBubbleHelper.js b/web/app/assets/javascripts/helpBubbleHelper.js index 11de7b8cb..9c61d67eb 100644 --- a/web/app/assets/javascripts/helpBubbleHelper.js +++ b/web/app/assets/javascripts/helpBubbleHelper.js @@ -161,21 +161,37 @@ return context.JK.prodBubble($element, 'teacher-profile', {}, bigHelpDarkOptions({spikeGirth:0, spikeLength: 0, duration:10000, offsetParent:$offsetParent, width:385, positions:['top', 'right', 'bottom']})) } - helpBubble.showUseRemainingTestDrives = function($element, $offsetParent) { - return context.JK.onceBubble($element, 'side-remaining-test-drives', {}, {offsetParent:$offsetParent, width:260, positions:['right'], postShow: function(container) { + helpBubble.showUseRemainingTestDrives = function($element, $offsetParent, user, callback) { + return context.JK.onceBubble($element, 'side-remaining-test-drives', user, {offsetParent:$offsetParent, width:260, positions:['right'], postShow: function(container) { + var $bookNow = $('a.book-now') + $bookNow.off('click').on('click', function(e) { + e.preventDefault() + callback() + return false; + }) }}) } - helpBubble.showBuyTestDrive = function($element, $offsetParent) { - return context.JK.onceBubble($element, 'side-buy-test-drive', {}, {offsetParent:$offsetParent, width:260, positions:['right'], postShow: function(container) { - + helpBubble.showBuyTestDrive = function($element, $offsetParent, user, callback) { + return context.JK.onceBubble($element, 'side-buy-test-drive', user, {offsetParent:$offsetParent, width:260, positions:['right'], postShow: function(container) { + var $bookNow = $('a.book-now') + $bookNow.off('click').on('click', function(e) { + e.preventDefault() + callback() + return false; + }) }}) } - helpBubble.showBuyNormalLesson = function($element, $offsetParent) { - return context.JK.onceBubble($element, 'side-buy-normal-lesson', {}, {offsetParent:$offsetParent, width:260, positions:['right'], postShow: function(container) { - + helpBubble.showBuyNormalLesson = function($element, $offsetParent, user, callback) { + return context.JK.onceBubble($element, 'side-buy-normal-lesson', user, {offsetParent:$offsetParent, width:260, positions:['right'], postShow: function(container) { + var $bookNow = $('a.book-now') + $bookNow.off('click').on('click', function(e) { + e.preventDefault() + callback() + return false; + }) }}) } })(window, jQuery); \ No newline at end of file diff --git a/web/app/assets/javascripts/react-components/BookLesson.js.jsx.coffee b/web/app/assets/javascripts/react-components/BookLesson.js.jsx.coffee index b92db6176..e16c0126d 100644 --- a/web/app/assets/javascripts/react-components/BookLesson.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/BookLesson.js.jsx.coffee @@ -62,7 +62,7 @@ UserStore = context.UserStore @state.type == 'normal' isTestDrive: () -> - @state.type == 'test-drive' + @state.type?.indexOf('test-drive') == 0 parseId:(id) -> if !id? @@ -79,7 +79,6 @@ UserStore = context.UserStore @resetErrors() beforeShow: (e) -> - logger.debug("BookLesson: beforeShow", e.id) afterShow: (e) -> logger.debug("BookLesson: afterShow", e.id) @@ -268,9 +267,6 @@ UserStore = context.UserStore onCancel: (e) -> e.preventDefault() - isTestDrive: () -> - @state.type == 'test-drive' - isNormal: () -> @state.type == 'normal' @@ -314,11 +310,12 @@ UserStore = context.UserStore results render: () -> + teacher = @state.teacher + photo_url = teacher?.photo_url if !photo_url? photo_url = '/assets/shared/avatar_generic.png' - teacher = @state.teacher if teacher? name = `
{teacher.name}
` @@ -446,6 +443,39 @@ UserStore = context.UserStore BOOK TESTDRIVE LESSON ` + testDriveCredits = 1 + + if this.state.user.lesson_package_type_id == 'test-drive' + testDriveCredits = 4 + else if this.state.user.lesson_package_type_id == 'test-drive-1' + testDriveCredits = 1 + else if this.state.user.lesson_package_type_id == 'test-drive-2' + testDriveCredits = 2 + + if this.state.user.remaining_test_drives > 0 + testDriveBookingInfo = `
+ +

You are booking a single 30-minute TestDrive session.

+ +

You currently have {testDriveLessons} available. If you need to cancel, you must cancel at least 24 hours before the lesson is scheduled to start, or you will be charged 1 TestDrive lesson credit.
+ +

jamclass + policies
+

+
` + else + testDriveBookingInfo = `
+ +

You are booking a single 30-minute TestDrive session.

+ +

Once payment is entered on the next screen, the teacher will be notified, and this lesson will then use 1 of {testDriveCredits} TestDrive credits. If you need to cancel, you must cancel at least 24 hours before the lesson is scheduled to start, or you will be charged 1 TestDrive lesson credit.
+ +

jamclass + policies
+

+
` + + columnLeft = `
{header} {slots} @@ -468,15 +498,7 @@ UserStore = context.UserStore
{name} -
-

You are purchasing a single 30-minute TestDrive session.

- -

You currently have {testDriveLessons} available. If you need to cancel, you must cancel at least 24 hours before the lesson is scheduled to start, or you will be charged 1 TestDrive lesson credit.
- -

jamclass - policies
-

-
+ {testDriveBookingInfo} ` else if @isNormal() diff --git a/web/app/assets/javascripts/react-components/LessonPayment.js.jsx.coffee b/web/app/assets/javascripts/react-components/LessonPayment.js.jsx.coffee index 590d151c5..00369f633 100644 --- a/web/app/assets/javascripts/react-components/LessonPayment.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/LessonPayment.js.jsx.coffee @@ -272,29 +272,58 @@ UserStore = context.UserStore window.UserActions.refresh() # if the response has a lesson, take them there - if response.lesson?.id? + if response.test_drive? + # ok, they bought a package + if response.lesson_package_type? + # always of form test-drive-# + prefixLength = "test-drive-".length + packageLength = response.lesson_package_type.package_type.length + + logger.debug("prefix: " + prefixLength.toString()) + logger.debug("package: " + packageLength.toString()) + testDriveCount = response.lesson_package_type.package_type.substring(prefixLength, packageLength) + + logger.debug("testDriveCount: " + testDriveCount) + + if response.test_drive?.teacher_id + teacher_id = response.test_drive.teacher_id + if testDriveCount == 1 + text = "You have purchased a TestDrive credit and have used it to request a JamClass with #{@state.teacher.name}. The teacher has received your request and should respond shortly." + else + text = "You have purchased #{testDriveCount} TestDrive credits and have used 1 credit it to request a JamClass with #{@state.teacher.name}. The teacher has received your request and should respond shortly." + location = "/client#/jamclass" + else + if @state.teacher?.id + + # the user bought the testdrive, and there is a teacher of interest in context (but no booking) + if testDriveCount == 1 + text = "You now have 1 TestDrive credit.

We've taken you to the lesson booking screen for the teacher you initially showed interest in." + location = "/client#/jamclass/book-lesson/test-drive_" + teacher_id + else + text = "You now have #{testDriveCount} TestDrive credits that you can take with #{testDriveCount} different teachers.

We've taken you to the lesson booking screen for the teacher you initially showed interest in." + location = "/client#/jamclass/book-lesson/test-drive_" + teacher_id + else + # the user bought test drive, but 'cold' , i.e., no teacher in context + if testDriveCount == 1 + text = "You now have 1 TestDrive credit.

We've taken you to the Teacher Search screen, so you can search for teachers right for you." + location = "/client#/teachers/search" + else + text = "You now have #{testDriveCount} TestDrive credits that you can take with #{testDriveCount} different teachers.

We've taken you to the Teacher Search screen, so you can search for teachers right for you." + location = "/client#/teachers/search" + + context.JK.Banner.showNotice("Test Drive Purchased",text) + window.location = location + else + context.JK.Banner.showNotice("Something Went Wrong", "Please email support@jamkazam.com and indicate that your attempt to buy a TestDrive failed") + window.location = "/client#/jamclass/" + + else if response.lesson?.id? context.JK.Banner.showNotice("Lesson Requested","The teacher has been notified of your lesson request, and should respond soon.

We've taken you automatically to the page for this request, and sent an email to you with a link here as well. All communication with the teacher will show up on this page and in email.") url = "/client#/jamclass/lesson-booking/" + response.lesson.id url = "/client#/jamclass" window.location.href = url - else if response.test_drive? - - if response.test_drive?.teacher_id - teacher_id = response.test_drive.teacher_id - else if @state.teacher?.id - teacher_id = @state.teacher.id - - if teacher_id? - text = "You now have 4 lessons that you can take with 4 different teachers.

We've taken you automatically to the lesson booking screen for the teacher you initially showed interest in." - location = "/client#/profile/teacher/" + teacher_id - location = "/client#/jamclass/book-lesson/test-drive_" + teacher_id - else - text = "You now have 4 lessons that you can take with 4 different teachers.

We've taken you automatically to the Teacher Search screen, so you can search for teachers right for you." - location = "/client#/teachers/search" - context.JK.Banner.showNotice("Test Drive Purchased",text) - window.location = location else window.location = "/client#/teachers/search" diff --git a/web/app/assets/javascripts/react-components/TeacherProfile.js.jsx.coffee b/web/app/assets/javascripts/react-components/TeacherProfile.js.jsx.coffee index 4eaf73839..bed688d7b 100644 --- a/web/app/assets/javascripts/react-components/TeacherProfile.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/TeacherProfile.js.jsx.coffee @@ -27,6 +27,7 @@ proficiencyDescriptionMap = { @TeacherProfile = React.createClass({ mixins: [ + PostProcessorMixin, Reflux.listenTo(AppStore, "onAppInit"), Reflux.listenTo(UserStore, "onUserChanged"), Reflux.listenTo(SubjectStore, "onSubjectsChanged"), @@ -89,12 +90,18 @@ proficiencyDescriptionMap = { userDetailDone: (response) -> if response.id == @state.userId + console.log("teacher markup", response) + @postProcessUser(response) @setState({user: response, isSelf: response.id == context.JK.currentUserId}) else logger.debug("ignoring userDetailDone", response.id, @state.userId) - if @visible - @showSideBubble() + @showSideBubbleWhenReady() + + showSideBubbleWhenReady: () -> + if @user? && @state.user? + if @visible + @showSideBubble() beforeHide: (e) -> @visible = false @@ -130,18 +137,22 @@ proficiencyDescriptionMap = { @screen.btOff() showUseRemainingTestDrivesBubble: ( ) -> - console.log("Ok showUseRemainingTestDrivesBubble") - context.JK.HelpBubbleHelper.showUseRemainingTestDrives(@screen, @screen) + context.JK.HelpBubbleHelper.showUseRemainingTestDrives(@screen, @screen, @user, (() => @useRemainingTestDrives())) showBuyTestDriveBubble: () -> - console.log("ok showBuyTestDriveBubble") - context.JK.HelpBubbleHelper.showBuyTestDrive(@screen, @screen) + context.JK.HelpBubbleHelper.showBuyTestDrive(@screen, @screen, @user, (() => @buyTestDrive())) showBuyNormalLessonBubble: () -> - console.log("OK showBuyNormalLessonBubble") - context.JK.HelpBubbleHelper.showBuyNormalLesson(@screen, @screen) + context.JK.HelpBubbleHelper.showBuyNormalLesson(@screen, @screen, @state.user, (() => @buyNormalLesson())) + + useRemainingTestDrives: () -> + window.location.href = "/client#/jamclass/book-lesson/test-drive_#{@state.user.id}" + buyTestDrive: () -> + window.location.href = "/client#/jamclass/test-drive-selection/#{@state.user.id}" + buyNormalLesson: () -> + window.location.href = "/client#/jamclass/book-lesson/normal_#{@state.user.id}" getInitialState: () -> { @@ -157,6 +168,7 @@ proficiencyDescriptionMap = { onUserChanged: (userState) -> @user = userState?.user + @showSideBubbleWhenReady() editProfile: (selected, e) -> e.preventDefault() diff --git a/web/app/assets/javascripts/react-components/TeacherSearchScreen.js.jsx.coffee b/web/app/assets/javascripts/react-components/TeacherSearchScreen.js.jsx.coffee index 0ef216da7..b6a5c93f5 100644 --- a/web/app/assets/javascripts/react-components/TeacherSearchScreen.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/TeacherSearchScreen.js.jsx.coffee @@ -27,7 +27,7 @@ ProfileActions = @ProfileActions refreshing: false getInitialState: () -> - {searchOptions: {}, results: []} + {searchOptions: {}, results: [], user: null} onAppInit: (@app) -> @app.bindScreen('teachers/search', {beforeShow: @beforeShow, afterShow: @afterShow, afterHide: @afterHide}) @@ -59,6 +59,7 @@ ProfileActions = @ProfileActions @setState(results) onUserChanged: (@user) -> + @setState({user: @user?.user}) #onTeacherSearchChanged: (options) -> # if @visible @@ -119,7 +120,8 @@ ProfileActions = @ProfileActions .done((response) => if response.remaining_test_drives == 0 && response['can_buy_test_drive?'] logger.debug("TeacherSearchScreen: user offered test drive") - @app.layout.showDialog('try-test-drive', {d1: user.teacher.id}) + #@app.layout.showDialog('try-test-drive', {d1: user.teacher.id}) + window.location.href = '/client#/jamclass/test-drive-selection/' + user.id else if response.remaining_test_drives > 0 if response.booked_with_teacher && !context.JK.currentUserAdmin logger.debug("TeacherSearchScreen: teacher already test-drived") @@ -130,6 +132,7 @@ ProfileActions = @ProfileActions logger.debug("TeacherSearchScreen: user being sent to book a lesson") window.location.href = '/client#/jamclass/book-lesson/test-drive_' + user.id + #window.location.href = '/client#/jamclass/test-drive-selection/' + user.id else # user has no remaining test drives and can't buy any logger.debug("TeacherSearchScreen: test drive all done") @@ -230,6 +233,11 @@ ProfileActions = @ProfileActions if !bio? bio = 'No bio' + console.log("@state.sur : #{@state.user.remaining_test_drives}, #{@state.user['can_buy_test_drive?']}") + if !@state.user? || @state.user.remaining_test_drives > 0 || @state.user['can_buy_test_drive?'] + bookTestDriveBtn = `BOOK TESTDRIVE LESSON` + else + bookSingleBtn = `BOOK LESSON` resultsJsx.push(`
@@ -246,8 +254,8 @@ ProfileActions = @ProfileActions
MORE ABOUT THIS TEACHER - BOOK TESTDRIVE LESSON - BOOK NORMAL LESSON + {bookTestDriveBtn} + {bookSingleBtn}

diff --git a/web/app/assets/javascripts/react-components/TestDriveSelectionScreen.js.jsx.coffee b/web/app/assets/javascripts/react-components/TestDriveSelectionScreen.js.jsx.coffee new file mode 100644 index 000000000..8a240d9a9 --- /dev/null +++ b/web/app/assets/javascripts/react-components/TestDriveSelectionScreen.js.jsx.coffee @@ -0,0 +1,174 @@ +context = window +rest = context.JK.Rest() +logger = context.JK.logger + +UserStore = context.UserStore + +@TestDriveSelection = React.createClass({ + + mixins: [ + Reflux.listenTo(AppStore, "onAppInit"), + Reflux.listenTo(UserStore, "onUserChanged") + ] + + onAppInit: (@app) -> + @app.bindScreen('jamclass/test-drive-selection', + {afterShow: @afterShow, beforeHide: @beforeHide, navName: 'TestDrive Selection'}) + + onUserChanged: (userState) -> + @setState({user: userState?.user}) + + beforeHide: (e) -> + + + afterShow: (e) -> + logger.debug("TestDriveSelection: afterShow", e.id) + + parsed = @parseId(e.id) + + id = parsed.id + + if id? && id != 'none' && id != 'default' + @setState({teacherId: id, teacher: null}) + else + @setState({teacherId: null, teacher: null}) + + rest.getUserDetail({ + id: id, + show_teacher: true + }).done((response) => @userDetailDone(response)).fail(@app.ajaxError) + + parseId: (id) -> + if !id? + {id: null} + else + {id: id} + + userDetailDone: (response) -> + if response.id == @state.teacherId + @setState({teacher: response, isSelf: response.id == context.JK.currentUserId}) + else + logger.debug("TestDriveSelection: ignoring teacher details", response.id, @state.teacherId) + + getInitialState: () -> + { + user: null, + teacher: null, + teacherId: null, + } + + packageSelect: (packageType, e) -> + e.preventDefault() + + console.log("test-drive-#{packageType}") + rest.updateUser({desired_package: "test-drive-#{packageType}"}).done((response) => @packageSelectedDone(response)).fail((jqXHR) => @packageSelectedFail(jqXHR)) + + + packageSelectedFail: (jqXHR) -> + console.log("package selected fail: " + jqXHR.responseText) + @app.ajaxError(jqXHR) + + packageSelectedDone:(response) -> + + url = "/client#/jamclass/book-lesson/test-drive" + + console.log("TEACHER", JSON.stringify(@state.teacher)) + if @state.teacher? + url += '_' + @state.teacher.id + else + url = "/client#/jamclass/lesson-payment/test-drive" + + window.location.href = url + + avatar: (name = 'your choice', photo_url = '/assets/shared/avatar_generic.png') -> + `
+
+ +
+
` + render: () -> + teacher_name = @state.teacher?.name + photo_url = @state.teacher?.photo_url + if !photo_url? + photo_url = '/assets/shared/avatar_generic.png' + + `
+
` +}) \ No newline at end of file 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 1c77ab5d1..1b75d8d98 100644 --- a/web/app/assets/javascripts/react-components/mixins/PostProcessorMixin.js.coffee +++ b/web/app/assets/javascripts/react-components/mixins/PostProcessorMixin.js.coffee @@ -19,7 +19,6 @@ teacherActions = window.JK.Actions.Teacher lesson.isAdmin = context.JK.currentUserAdmin lesson.cardNotOk = !lesson.lesson_booking.card_presumed_ok - console.log("lesson.isAdmin",lesson.isAdmin ) if (lesson.status == 'requested' || lesson.status == 'countered') lesson.isRequested = true if lesson.cardNotOk @@ -56,4 +55,40 @@ teacherActions = window.JK.Actions.Teacher user.musician_profile = '/client#/profile/' + user.id user.best_profile = user.musician_profile + if user.is_a_teacher + cheapest_lesson_stmt = '(no pricing set yet)' + lowestPrice = null + lowestDuration = null + single = true + enabledMinutes = [] + for minutes in [30, 45, 60, 90, 120] + duration_enabled = user.teacher["lesson_duration_#{minutes}"] + + if duration_enabled + enabledMinutes.push(minutes) + if user.teacher.prices_per_lesson + for minutes in enabledMinutes + lesson_price = user.teacher["price_per_lesson_#{minutes}_cents"] + if lesson_price? + if !lowestPrice? || lesson_price < lowestPrice + lowestPrice = lesson_price + single = true + lowestDuration = minutes + for minutes in enabledMinutes + lesson_price = user.teacher["price_per_month_#{minutes}_cents"] + if lesson_price? + if !lowestPrice? || (lesson_price / 4) < lowestPrice + lowestPrice = lesson_price / 4 + single = false + lowestDuration = minutes + + if lowestPrice? + if single + # lowest price appears to be a single lesson + cheapest_lesson_stmt = "$#{lowestPrice / 100} for #{lowestDuration} minutes" + else + # lowest price appears to be a monthly recurring lesson + cheapest_lesson_stmt = "$#{Math.round(lowestPrice * 4) / 100} per month" + + user.cheapest_lesson_stmt = cheapest_lesson_stmt } \ No newline at end of file diff --git a/web/app/assets/javascripts/utils.js b/web/app/assets/javascripts/utils.js index 87dd50dbc..ec6bb6cf6 100644 --- a/web/app/assets/javascripts/utils.js +++ b/web/app/assets/javascripts/utils.js @@ -143,8 +143,13 @@ options = {}; } + var originalPostShow = options.postShow; options.postShow = function(container) { context.JK.popExternalLinks($(container)) + + if (originalPostShow) { + originalPostShow(container); + } } diff --git a/web/app/assets/stylesheets/client/common.css.scss b/web/app/assets/stylesheets/client/common.css.scss index d3a9974f4..c7f836220 100644 --- a/web/app/assets/stylesheets/client/common.css.scss +++ b/web/app/assets/stylesheets/client/common.css.scss @@ -64,22 +64,6 @@ $labelFontSize: 12px; } -select { - - border: 0 !important; /*Removes border*/ - -webkit-appearance: none; /*Removes default chrome and safari style*/ - -moz-appearance: none; /* Removes Default Firefox style*/ - appearance: none; - background: url('/assets/down_arrow_black_pad.png') no-repeat; /*Adds background-image*/ - background-position: right center; /*Position of the background-image*/ - text-indent: 0.01px; /* Removes default arrow from firefox*/ - text-overflow: ""; /*Removes default arrow from firefox*/ - cursor: pointer; - padding-right:20px; - &::-ms-expand { - display: none; - } -} @mixin border_box_sizing { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; diff --git a/web/app/assets/stylesheets/client/help.css.scss b/web/app/assets/stylesheets/client/help.css.scss index f29cd263e..ec34250dd 100644 --- a/web/app/assets/stylesheets/client/help.css.scss +++ b/web/app/assets/stylesheets/client/help.css.scss @@ -99,6 +99,7 @@ body.jam, body.web, .dialog{ } p { margin:.8em 1em; + line-height:120%; } .book-now { width:100px; diff --git a/web/app/assets/stylesheets/client/jamkazam.css.scss b/web/app/assets/stylesheets/client/jamkazam.css.scss index 9d2577e84..8b972af82 100644 --- a/web/app/assets/stylesheets/client/jamkazam.css.scss +++ b/web/app/assets/stylesheets/client/jamkazam.css.scss @@ -76,8 +76,21 @@ a.arrow-down { } select { - padding:3px; - font-size:15px; + + border: 0 !important; /*Removes border*/ + -webkit-appearance: none; /*Removes default chrome and safari style*/ + -moz-appearance: none; /* Removes Default Firefox style*/ + appearance: none; + background: #C5C5C5 url('/assets/down_arrow_black_pad.png') no-repeat; /*Adds background-image*/ + background-position: right center; /*Position of the background-image*/ + text-indent: 0.01px; /* Removes default arrow from firefox*/ + text-overflow: ""; /*Removes default arrow from firefox*/ + cursor: pointer; + padding:3px 20px 3px 3px; + &::-ms-expand { + display: none; + } + font-size:15px; border-radius: 6px; } diff --git a/web/app/assets/stylesheets/client/react-components/LessonBooking.css.scss b/web/app/assets/stylesheets/client/react-components/LessonBooking.css.scss index 6e5b1ddcb..fbed0c14d 100644 --- a/web/app/assets/stylesheets/client/react-components/LessonBooking.css.scss +++ b/web/app/assets/stylesheets/client/react-components/LessonBooking.css.scss @@ -16,6 +16,20 @@ .column-left { float:left; padding-right:20px; + + .slot.slot-2 { + border-style: solid; + border-width: 1px 0 0 0; + border-color: #cccccc; + padding-top: 20px; + } + + .description { + border-style: solid; + border-width: 1px 0 0 0; + border-color: #cccccc; + padding-top: 20px; + } } .column-right { float:right; @@ -56,7 +70,7 @@ textarea { width:100%; @include border_box_sizing; - height:125px; + height:75px; } .field { display:inline-block; @@ -99,7 +113,7 @@ } .jamclass-policies { text-align:center; - margin-top:-20px; + margin-top:-10px; } .actions { margin-left:-3px; @@ -138,7 +152,7 @@ width:80%; } } - select.hour { - margin-left:20px; + select.am_pm { + margin-left:13px; } } diff --git a/web/app/assets/stylesheets/client/react-components/TestDriveSelectionScreen.css.scss b/web/app/assets/stylesheets/client/react-components/TestDriveSelectionScreen.css.scss new file mode 100644 index 000000000..39d459f10 --- /dev/null +++ b/web/app/assets/stylesheets/client/react-components/TestDriveSelectionScreen.css.scss @@ -0,0 +1,164 @@ +@import "client/common"; + + +$fluid-break: 1335px; +@mixin layout-small { + @media (max-width: #{$fluid-break - 1px}) { + @content; + } +} + +@mixin layout-normal { + @media (min-width: #{$fluid-break}) { + @content; + } +} + + +#test-drive-selection { + + + + div[data-react-class="TestDriveSelection"] { + height: 100%; + } + .content-body-scroller { + height: 100%; + padding: 30px; + @include border_box_sizing; + } + + h2 { + font-size: 24px; + font-weight: 700; + margin-bottom: 20px !important; + display: inline-block; + } + + .test-drive-selection-wrapper { + float:left; + text-align:center; + width:31%; + + &.select-4 { + + } + &.select-2 { + margin:0 3.5%; + } + &.select-1 { + + } + } + .test-drive-selection { + display:inline-block; + border-radius:10px; + border-width:1px; + border-color:$ColorScreenPrimary; + border-style:solid; + margin-bottom:15px; + + @media (max-width: 1180px) { + min-height:360px; + } + @media (min-width: 1181px) { + min-height:340px; + } + @media (min-width: 1450px) { + min-height:305px; + } + } + + a.select-package { + margin-bottom:15px; + max-width: 140px; + width: 100%; + } + + .price-notice { + color:white; + font-size:16px; + } + + .td-header { + height:45px; + color:white; + text-align:center; + font-size:24px; + line-height: 45px; + vertical-align: middle; + background-color:$ColorScreenPrimary; + + border-top-left-radius: 10px; + border-top-right-radius: 10px; + + @media (max-width: 1130px) { + font-size:16px; + } + } + .td-content { + @include border-box_sizing; + padding:10px; + width:100%; + + } + + .avatars { + margin-bottom:20px; + } + .td-msg { + margin-bottom:20px; + + @media (max-width: 1400px) { + min-height:42px; + } + } + .td-desc { + line-height:120%; + color:$ColorTextTypical; + } + + .avatar-header { + display:inline-block; + } + .avatar { + display:inline-block; + padding:1px; + width:48px; + height:48px; + background-color:#ed4818; + margin:10px 8px 0 0; + -webkit-border-radius:24px; + -moz-border-radius:24px; + border-radius:24px; + float:none; + + @include layout-small { + width:32px; + height:32px; + -webkit-border-radius:16px; + -moz-border-radius:16px; + border-radius:16px; + margin:10px 6px 0 0; + } + } + .avatar img { + width: 48px; + height: 48px; + -webkit-border-radius:24px; + -moz-border-radius:24px; + border-radius:24px; + @include layout-small { + width:32px; + height:32px; + -webkit-border-radius:16px; + -moz-border-radius:16px; + border-radius:16px; + } + } + .selection-area { + width:100%; + padding-top:20px; + } + +} \ No newline at end of file diff --git a/web/app/controllers/api_stripe_controller.rb b/web/app/controllers/api_stripe_controller.rb index 9501141a5..72eec53c6 100644 --- a/web/app/controllers/api_stripe_controller.rb +++ b/web/app/controllers/api_stripe_controller.rb @@ -14,6 +14,7 @@ class ApiStripeController < ApiController @lesson = data[:lesson] @test_drive = data[:test_drive] @normal = data[:normal] + @lesson_package_type = data[:lesson_package_type] end end diff --git a/web/app/controllers/api_users_controller.rb b/web/app/controllers/api_users_controller.rb index a6b43b1e3..74077b465 100644 --- a/web/app/controllers/api_users_controller.rb +++ b/web/app/controllers/api_users_controller.rb @@ -1,6 +1,5 @@ require 'sanitize' -class -ApiUsersController < ApiController +class ApiUsersController < ApiController before_filter :api_signed_in_user, :except => [:create, :calendar, :show, :signup_confirm, :auth_session_create, :complete, :finalize_update_email, :isp_scoring, :add_play, :crash_dump, :validate_data, :google_auth, :user_event] before_filter :auth_user, :only => [:session_settings_show, :session_history_index, :session_user_history_index, :update, :delete, :authorizations, :test_drive_status, @@ -178,6 +177,7 @@ ApiUsersController < ApiController @user.is_a_student = params[:student] if params.has_key?(:student) @user.is_a_teacher = params[:teacher] if params.has_key?(:teacher) @user.school_interest = !!params[:school_interest] + @user.desired_package = LessonPackageType.find_by_package_type!(params[:desired_package]) if params.has_key?(:desired_package) @user.save if @user.errors.any? diff --git a/web/app/views/api_stripe/store.rabl b/web/app/views/api_stripe/store.rabl index 953850168..27e32132a 100644 --- a/web/app/views/api_stripe/store.rabl +++ b/web/app/views/api_stripe/store.rabl @@ -9,16 +9,21 @@ end if @test_drive node :test_drive do |lesson| - attributes :teacher_id + {teacher_id: @test_drive.id} end end if @normal node :normal do |lesson| - attributes :teacher_id + {teacher_id: @normal.teacher_id} + end +end + +if @lesson_package_type + node :lesson_package_type do |lesson_package_type| + {package_type: @lesson_package_type.package_type} end end - diff --git a/web/app/views/api_users/show.rabl b/web/app/views/api_users/show.rabl index d9df9fd03..5cf41f03e 100644 --- a/web/app/views/api_users/show.rabl +++ b/web/app/views/api_users/show.rabl @@ -28,7 +28,7 @@ end # give back more info if the user being fetched is yourself if current_user && @user == current_user - attributes :email, :original_fpfile, :cropped_fpfile, :crop_selection, :session_settings, :show_whats_next, :show_whats_next_count, :subscribe_email, :auth_twitter, :new_notifications, :sales_count, :reuse_card, :purchased_jamtracks_count, :first_downloaded_client_at, :created_at, :first_opened_jamtrack_web_player, :gifted_jamtracks, :has_redeemable_jamtrack, :remaining, :has_stored_credit_card?, :remaining_test_drives, :can_buy_test_drive? + attributes :email, :original_fpfile, :cropped_fpfile, :crop_selection, :session_settings, :show_whats_next, :show_whats_next_count, :subscribe_email, :auth_twitter, :new_notifications, :sales_count, :reuse_card, :purchased_jamtracks_count, :first_downloaded_client_at, :created_at, :first_opened_jamtrack_web_player, :gifted_jamtracks, :has_redeemable_jamtrack, :remaining, :has_stored_credit_card?, :remaining_test_drives, :can_buy_test_drive?, :lesson_package_type_id node :owned_school_id do |user| user.owned_school.id if user.owned_school diff --git a/web/app/views/clients/_help.html.slim b/web/app/views/clients/_help.html.slim index ad30e8b0c..cdaacd3d8 100644 --- a/web/app/views/clients/_help.html.slim +++ b/web/app/views/clients/_help.html.slim @@ -403,6 +403,7 @@ script type="text/template" id="template-help-teacher-profile" script type="text/template" id="template-help-side-remaining-test-drives" .side-remaining-test-drives + h2 Book TestDrive Lesson p You currently have {{data.remaining_test_drives}} TestDrive lesson credits available. a.book-now.button-orange BOOK NOW! @@ -418,7 +419,7 @@ script type="text/template" id="template-help-side-buy-test-drive" script type="text/template" id="template-help-side-buy-normal-lesson" .side-buy-normal-lesson h2 Book Lesson - p Lessons with {{data.first_name}} start at just ${{data.cheapest_lesson_stmt}}. + p Lessons with {{data.first_name}} start at just {{data.cheapest_lesson_stmt}}. a.book-now.button-orange BOOK NOW! p Or call us at p 877-376-8742 (877-37-MUSIC) diff --git a/web/app/views/clients/index.html.erb b/web/app/views/clients/index.html.erb index 297594f77..05f278e03 100644 --- a/web/app/views/clients/index.html.erb +++ b/web/app/views/clients/index.html.erb @@ -50,6 +50,7 @@ <%= render "clients/jamclass/lesson_payment" %> <%= render "clients/jamclass/lesson_session" %> <%= render "clients/jamclass/lesson_booking" %> +<%= render "clients/jamclass/test_drive_selection" %> <%= render "clients/jamclass/jamclass_student" %> <%= render "users/feed_music_session_ajax" %> <%= render "users/feed_recording_ajax" %> diff --git a/web/app/views/clients/jamclass/_lesson_booking.html.slim b/web/app/views/clients/jamclass/_lesson_booking.html.slim index b483b4fc0..a50e244be 100644 --- a/web/app/views/clients/jamclass/_lesson_booking.html.slim +++ b/web/app/views/clients/jamclass/_lesson_booking.html.slim @@ -1,7 +1,7 @@ #lesson-booking.screen.secondary layout="screen" layout-id="jamclass/lesson-booking" layout-arg="id" .content-head .content-icon - = image_tag "content/icon_account.png", :size => "27x20" + = image_tag "content/icon_musicians.png", :size => "20x20" h1 | jamclass = render "screen_navigation" diff --git a/web/app/views/clients/jamclass/_test_drive_selection.html.slim b/web/app/views/clients/jamclass/_test_drive_selection.html.slim new file mode 100644 index 000000000..5108e3f2b --- /dev/null +++ b/web/app/views/clients/jamclass/_test_drive_selection.html.slim @@ -0,0 +1,10 @@ +#test-drive-selection.screen.secondary layout="screen" layout-id="jamclass/test-drive-selection" layout-arg="id" + .content-head + .content-icon + = image_tag "content/icon_musicians.png", :size => "20x20" + h1 + | jamclass + = render "screen_navigation" + .content-body + = react_component 'TestDriveSelection', {} + diff --git a/web/lib/tasks/lesson.rake b/web/lib/tasks/lesson.rake index 92da6d0e2..a2963c3ab 100644 --- a/web/lib/tasks/lesson.rake +++ b/web/lib/tasks/lesson.rake @@ -71,7 +71,7 @@ namespace :lessons do lesson = booking.lesson_sessions[0] if user.most_recent_test_drive_purchase.nil? - LessonPackagePurchase.create(user, booking, LessonPackageType.test_drive) + LessonPackagePurchase.create(user, booking, LessonPackageType.test_drive_4) end #lesson.accept({message: 'Yeah I got this', slot: slots[0]}) diff --git a/web/spec/factories.rb b/web/spec/factories.rb index 5e2fcfb62..3c7b09c4a 100644 --- a/web/spec/factories.rb +++ b/web/spec/factories.rb @@ -950,7 +950,7 @@ FactoryGirl.define do price 30.00 factory :test_drive_purchase do - lesson_package_type { JamRuby::LessonPackageType.test_drive } + lesson_package_type { JamRuby::LessonPackageType.test_drive_4 } association :lesson_booking, factory: :lesson_booking price 49.99 end diff --git a/web/spec/features/book_monthly_recurring_lesson_spec.rb b/web/spec/features/book_monthly_recurring_lesson_spec.rb index 5b9987014..81e9b718d 100644 --- a/web/spec/features/book_monthly_recurring_lesson_spec.rb +++ b/web/spec/features/book_monthly_recurring_lesson_spec.rb @@ -7,6 +7,7 @@ describe "Book Monthly Recurring Lesson", :js => true, :type => :feature, :capyb let(:user) { FactoryGirl.create(:user, traditional_band: true,paid_sessions: true, paid_sessions_hourly_rate: 1, paid_sessions_daily_rate:1 ) } let(:teacher_user) {FactoryGirl.create(:teacher_user, first_name: "Teacher1", ready_for_session_at: Time.now)} let(:teacher_user2) {FactoryGirl.create(:teacher_user, ready_for_session_at: Time.now)} + let(:teacher_user3) {FactoryGirl.create(:teacher_user, ready_for_session_at: Time.now)} after(:each) do Timecop.return @@ -23,7 +24,12 @@ describe "Book Monthly Recurring Lesson", :js => true, :type => :feature, :capyb UserMailer.deliveries.clear emulate_client - sign_in_poltergeist user + # create an old test drive and fakely use up all the credits so that we can book the lesson + Timecop.travel(Date.new(2016, 03, 01)) + testdrive_lesson(user, teacher_user3) + user.remaining_test_drives = 0 + user.save! + user.reload teacher_user.teacher.ready_for_session_at = Time.now @@ -38,10 +44,11 @@ describe "Book Monthly Recurring Lesson", :js => true, :type => :feature, :capyb it "succeeds" do - visit "/client#/teachers/search" + Timecop.travel(Date.new(2016, 04, 01)) - # let's do a time half-way into the month, so we can prove some pro-rating - Timecop.travel(Date.new(2016, 04, 15)) + sign_in_poltergeist user + + visit "/client#/teachers/search" find('.teacher-search-result[data-teacher-id="' + teacher_user.id + '"] .try-normal').trigger(:click) @@ -61,32 +68,35 @@ describe "Book Monthly Recurring Lesson", :js => true, :type => :feature, :capyb find('a.book-lesson-btn', text: 'BOOK LESSON').trigger(:click) - find('h2', text: 'enter payment info for lesson') + #find('h2', text: 'enter payment info for lesson') - user.student_lesson_bookings.count.should eql 1 - lesson_booking = user.student_lesson_bookings.first - lesson_booking.is_requested?.should be_true - lesson_booking.card_presumed_ok.should be_false - lesson_booking.recurring.should be true - lesson_booking.is_monthly_payment?.should be true - fill_in 'card-number', with: '4111111111111111' - fill_in 'expiration', with: '11/2016' - fill_in 'cvv', with: '111' - fill_in 'zip', with: '78759' + #fill_in 'card-number', with: '4111111111111111' + #fill_in 'expiration', with: '11/2016' + #fill_in 'cvv', with: '111' + #fill_in 'zip', with: '78759' - find('.purchase-btn').trigger(:click) + #find('.purchase-btn').trigger(:click) # we tell user they have test drive purchased, and take them to the teacher screen find('#banner h1', text: 'Lesson Requested') # dismiss banner find('a.button-orange', text:'CLOSE').trigger(:click) + + user.student_lesson_bookings.count.should eql 2 + lesson_booking = user.student_lesson_bookings.order(:created_at).last + lesson_booking.is_requested?.should be_true + lesson_booking.card_presumed_ok.should be_true + lesson_booking.recurring.should be true + lesson_booking.is_monthly_payment?.should be true + + lesson_booking = LessonBooking.where(teacher_id: teacher_user).first lesson_booking.should_not be_nil lesson_session = LessonSession.where(teacher_id: teacher_user).first lesson_session.teacher.should eql teacher_user - lesson_package_purchase = LessonPackagePurchase.where(user_id: user.id).first + lesson_package_purchase = LessonPackagePurchase.where(user_id: user.id, teacher_id: teacher_user.id).first lesson_package_purchase.should be_nil user.reload user.remaining_test_drives.should eql 0 @@ -150,7 +160,7 @@ describe "Book Monthly Recurring Lesson", :js => true, :type => :feature, :capyb lesson_booking.recurring.should be false LessonSession.where(teacher_id: teacher_user2).count.should eql 1 - lesson_package_purchase = LessonPackagePurchase.where(user_id: user.id).first + lesson_package_purchase = LessonPackagePurchase.where(user_id: user.id, teacher_id: teacher_user.id).first lesson_package_purchase.should be_nil user.reload user.remaining_test_drives.should eql 0 @@ -176,13 +186,13 @@ describe "Book Monthly Recurring Lesson", :js => true, :type => :feature, :capyb lesson_session1.billed.should eql false lesson_session1.success.should be_true - user.lesson_purchases.count.should eql 0 + user.lesson_purchases.count.should eql 1 LessonBooking.hourly_check user.reload - lesson_package_purchase = user.lesson_purchases.count.should eql 1 - lesson_package_purchase = user.lesson_purchases.first + lesson_package_purchase = user.lesson_purchases.count.should eql 2 + lesson_package_purchase = user.lesson_purchases.where(teacher_id: teacher_user.id).last teacher_distribution = lesson_package_purchase.teacher_distribution teacher_distribution.amount_in_cents.should eql 3000 / 2 teacher_distribution.ready.should be_true diff --git a/web/spec/features/book_recurring_lesson_spec.rb b/web/spec/features/book_recurring_lesson_spec.rb index 038689ca4..511af9d2b 100644 --- a/web/spec/features/book_recurring_lesson_spec.rb +++ b/web/spec/features/book_recurring_lesson_spec.rb @@ -7,6 +7,7 @@ describe "Book Single Recurring Lesson", :js => true, :type => :feature, :capyba let(:user) { FactoryGirl.create(:user, traditional_band: true,paid_sessions: true, paid_sessions_hourly_rate: 1, paid_sessions_daily_rate:1 ) } let(:teacher_user) {FactoryGirl.create(:teacher_user, first_name: "Teacher1", ready_for_session_at: Time.now)} let(:teacher_user2) {FactoryGirl.create(:teacher_user, ready_for_session_at: Time.now)} + let(:teacher_user3) {FactoryGirl.create(:teacher_user, ready_for_session_at: Time.now)} after(:each) do Timecop.return @@ -23,8 +24,17 @@ describe "Book Single Recurring Lesson", :js => true, :type => :feature, :capyba UserMailer.deliveries.clear emulate_client - sign_in_poltergeist user + # create an old test drive and fakely use up all the credits so that we can book the lesson + Timecop.travel(Date.new(2016, 03, 01)) + testdrive_lesson(user, teacher_user3) + user.remaining_test_drives = 0 + user.save! + user.reload + teacher_user.teacher.ready_for_session_at = Time.now + teacher_user.teacher.save! + teacher_user.teacher.price_per_lesson_60_cents.should eql 3000 + Teacher.index(user, {})[:query].count.should eql 1 teacher_user.teacher.ready_for_session_at = Time.now teacher_user.teacher.save! @@ -38,10 +48,13 @@ describe "Book Single Recurring Lesson", :js => true, :type => :feature, :capyba it "succeeds" do - visit "/client#/teachers/search" Timecop.travel(Date.new(2016, 04, 01)) + sign_in_poltergeist user + + visit "/client#/teachers/search" + find('.teacher-search-result[data-teacher-id="' + teacher_user.id + '"] .try-normal').trigger(:click) @@ -60,32 +73,35 @@ describe "Book Single Recurring Lesson", :js => true, :type => :feature, :capyba find('a.book-lesson-btn', text: 'BOOK LESSON').trigger(:click) - find('h2', text: 'enter payment info for lesson') + # find('h2', text: 'enter payment info for lesson') - user.student_lesson_bookings.count.should eql 1 - lesson_booking = user.student_lesson_bookings.first - lesson_booking.is_requested?.should be_true - lesson_booking.card_presumed_ok.should be_false - lesson_booking.recurring.should be true - lesson_booking.is_monthly_payment?.should be false - fill_in 'card-number', with: '4111111111111111' - fill_in 'expiration', with: '11/2016' - fill_in 'cvv', with: '111' - fill_in 'zip', with: '78759' + #fill_in 'card-number', with: '4111111111111111' + #fill_in 'expiration', with: '11/2016' + #fill_in 'cvv', with: '111' + #fill_in 'zip', with: '78759' - find('.purchase-btn').trigger(:click) + #find('.purchase-btn').trigger(:click) # we tell user they have test drive purchased, and take them to the teacher screen find('#banner h1', text: 'Lesson Requested') # dismiss banner find('a.button-orange', text:'CLOSE').trigger(:click) + + + user.student_lesson_bookings.count.should eql 2 + lesson_booking = user.student_lesson_bookings.order(:created_at).last + lesson_booking.is_requested?.should be_true + lesson_booking.card_presumed_ok.should be_true + lesson_booking.recurring.should be true + lesson_booking.is_monthly_payment?.should be false + lesson_booking = LessonBooking.where(teacher_id: teacher_user).first lesson_booking.should_not be_nil lesson_session = LessonSession.where(teacher_id: teacher_user).first lesson_session.teacher.should eql teacher_user - lesson_package_purchase = LessonPackagePurchase.where(user_id: user.id).first + lesson_package_purchase = LessonPackagePurchase.where(user_id: user.id, teacher_id: teacher_user.id).first lesson_package_purchase.should be_nil user.reload user.remaining_test_drives.should eql 0 @@ -149,7 +165,7 @@ describe "Book Single Recurring Lesson", :js => true, :type => :feature, :capyba lesson_booking.recurring.should be false LessonSession.where(teacher_id: teacher_user2).count.should eql 1 - lesson_package_purchase = LessonPackagePurchase.where(user_id: user.id).first + lesson_package_purchase = LessonPackagePurchase.where(user_id: user.id, teacher_id: teacher_user.id).first lesson_package_purchase.should be_nil user.reload user.remaining_test_drives.should eql 0 @@ -175,7 +191,7 @@ describe "Book Single Recurring Lesson", :js => true, :type => :feature, :capyba lesson_session1.billed.should eql true lesson_session1.success.should be_true lesson_session1.lesson_payment_charge.billed.should be_true - lesson_session1.lesson_payment_charge.amount_in_cents.should eql 3000 + lesson_session1.lesson_payment_charge.amount_in_cents.should eql (3000 + (3000 * 0.0825).round) lesson_session1.lesson_payment_charge.fee_in_cents.should eql 0 lesson_session1.lesson_payment_charge.stripe_charge_id.should_not be_nil lesson_session1.lesson_payment_charge.post_processed.should be_true diff --git a/web/spec/features/book_single_lesson_spec.rb b/web/spec/features/book_single_lesson_spec.rb index 9914eeea6..608e8afc8 100644 --- a/web/spec/features/book_single_lesson_spec.rb +++ b/web/spec/features/book_single_lesson_spec.rb @@ -7,6 +7,7 @@ describe "Single Lesson", :js => true, :type => :feature, :capybara_feature => t let(:user) { FactoryGirl.create(:user, traditional_band: true,paid_sessions: true, paid_sessions_hourly_rate: 1, paid_sessions_daily_rate:1 ) } let(:teacher_user) {FactoryGirl.create(:teacher_user, first_name: "Teacher1", ready_for_session_at: Time.now)} let(:teacher_user2) {FactoryGirl.create(:teacher_user, ready_for_session_at: Time.now)} + let(:teacher_user3) {FactoryGirl.create(:teacher_user, ready_for_session_at: Time.now)} before(:each) do @@ -17,14 +18,16 @@ describe "Single Lesson", :js => true, :type => :feature, :capybara_feature => t UserMailer.deliveries.clear emulate_client + # create an old test drive and fakely use up all the credits so that we can book the lesson + Timecop.travel(Date.new(2016, 03, 01)) + testdrive_lesson(user, teacher_user3) + user.remaining_test_drives = 0 + user.save! + user.reload sign_in_poltergeist user - - teacher_user.teacher.ready_for_session_at = Time.now teacher_user.teacher.save! - teacher_user.teacher.price_per_lesson_60_cents.should eql 3000 - Teacher.index(user, {})[:query].count.should eql 1 @@ -62,33 +65,35 @@ describe "Single Lesson", :js => true, :type => :feature, :capybara_feature => t #find('h2', text: 'your lesson has been requested') - find('h2', text: 'enter payment info for lesson') - - user.student_lesson_bookings.count.should eql 1 - lesson_booking = user.student_lesson_bookings.first - lesson_booking.is_requested?.should be_true - lesson_booking.card_presumed_ok.should be_false - lesson_booking.recurring.should be false + #find('h2', text: 'enter payment info for lesson') + #fill_in 'card-number', with: '4111111111111111' + #fill_in 'expiration', with: '11/2016' + #fill_in 'cvv', with: '111' + #fill_in 'zip', with: '78759' - fill_in 'card-number', with: '4111111111111111' - fill_in 'expiration', with: '11/2016' - fill_in 'cvv', with: '111' - fill_in 'zip', with: '78759' - - find('.purchase-btn').trigger(:click) + #find('.purchase-btn').trigger(:click) # we tell user they have test drive purchased, and take them to the teacher screen find('#banner h1', text: 'Lesson Requested') # dismiss banner find('a.button-orange', text:'CLOSE').trigger(:click) - lesson_booking = LessonBooking.where(teacher_id: teacher_user).first + + user.student_lesson_bookings.count.should eql 2 # this single one, and the test drive created in the before section of the test + lesson_booking = user.student_lesson_bookings.order(:created_at).last + lesson_booking.is_requested?.should be_true + lesson_booking.card_presumed_ok.should be_true + lesson_booking.recurring.should be false + + + + lesson_booking = LessonBooking.where(teacher_id: teacher_user).order(:created_at).last lesson_booking.should_not be_nil - lesson_session = LessonSession.where(teacher_id: teacher_user).first + lesson_session = LessonSession.where(teacher_id: teacher_user).order(:created_at).last lesson_session.teacher.should eql teacher_user - lesson_package_purchase = LessonPackagePurchase.where(user_id: user.id).first + lesson_package_purchase = LessonPackagePurchase.where(user_id: user.id, teacher_id: teacher_user.id).order(:created_at).first lesson_package_purchase.should be_nil user.reload user.remaining_test_drives.should eql 0 @@ -151,7 +156,7 @@ describe "Single Lesson", :js => true, :type => :feature, :capybara_feature => t lesson_session.teacher.should eql teacher_user2 lesson_session2 = lesson_session - lesson_package_purchase = LessonPackagePurchase.where(user_id: user.id).first + lesson_package_purchase = LessonPackagePurchase.where(user_id: user.id, teacher_id: teacher_user.id).order(:created_at).first lesson_package_purchase.should be_nil user.reload user.remaining_test_drives.should eql 0 @@ -167,9 +172,9 @@ describe "Single Lesson", :js => true, :type => :feature, :capybara_feature => t lesson_session1.analysed.should be_true analysis = JSON.parse(lesson_session1.analysis) analysis["reason"].should eql LessonSessionAnalyser::SUCCESS - lesson_session1.billing_attempts.should be_true - lesson_session1.billed.should eql true lesson_session1.success.should be_true + lesson_session1.billing_attempts.should eql 1 + lesson_session1.billed.should eql true LessonBooking.hourly_check diff --git a/web/spec/features/book_test_drive_spec.rb b/web/spec/features/book_test_drive_spec.rb index 2dd9906fb..2082a5842 100644 --- a/web/spec/features/book_test_drive_spec.rb +++ b/web/spec/features/book_test_drive_spec.rb @@ -37,18 +37,20 @@ describe "Test Drive", :js => true, :type => :feature, :capybara_feature => true find('.teacher-search-result[data-teacher-id="' + teacher_user.id + '"] .try-test-drive').trigger(:click) + # no longer true # TryTestDriveDialog shows - find('.purchase-testdrive-now').trigger(:click) + #find('.purchase-testdrive-now').trigger(:click) - fill_in 'card-number', with: '4111111111111111' - fill_in 'expiration', with: '11/2016' - fill_in 'cvv', with: '111' - fill_in 'zip', with: '78759' + select_test_drive(4) - find('.purchase-btn').trigger(:click) + fill_out_single_lesson + + fill_out_payment # we tell user they have test drive purchased, and take them to the teacher screen find('#banner h1', text: 'Test Drive Purchased') + find('#banner .dialog-inner', text: "You have purchased #{4} TestDrive credits and have used 1 credit it to request a JamClass with #{teacher_user.name}") + # dismiss banner find('a.button-orange', text:'CLOSE').trigger(:click) @@ -58,35 +60,12 @@ describe "Test Drive", :js => true, :type => :feature, :capybara_feature => true lesson_package_purchase.lesson_package_type.is_test_drive?.should be_true lesson_package_purchase.lesson_payment_charge.should_not be_nil user.reload - user.remaining_test_drives.should eql 4 + user.remaining_test_drives.should eql 3 #lesson_package_purchase.amount_charged.should eql 49.99 user.sales.count.should eql 1 sale = user.sales.first sale.recurly_total_in_cents.should eql 5411 - # the spec says take them back to search; there is some wasted effort here by the student; they have to click the teacher 2x. Ok? - find('.teacher-search-result[data-teacher-id="' + teacher_user.id + '"] .try-test-drive').trigger(:click) - - find('h2', text: 'book testdrive lesson') - find('.booking-info', text: '4 TestDrive lesson credits') - - # book the lesson - fill_in "slot-1-date", with: "Sun Apr 17 2016" - #find('.slot.slot-1 input.hasDatepicker').trigger(:click) - # click 4-6 - find('td a', text: '17').trigger(:click) - - #find('.slot.slot-2 input.hasDatepicker').trigger(:click) - # click 4-7 - fill_in "slot-2-date", with: "Mon Apr 18 2016" - find('td a', text: '18').trigger(:click) - - fill_in 'user-description', with: 'abc def dog neck' - - sleep 3 - - - find('a.book-lesson-btn', text: 'BOOK TESTDRIVE LESSON').trigger(:click) find('h2', text: 'my lessons') @@ -112,8 +91,6 @@ describe "Test Drive", :js => true, :type => :feature, :capybara_feature => true find('h2', text: 'book testdrive lesson') find('.booking-info', text: '3 TestDrive lesson credits') - # dismiss banner - find('a.button-orange', text:'CLOSE').trigger(:click) # approve by teacher: teacher_approve(lesson_session1) diff --git a/web/spec/support/lessons.rb b/web/spec/support/lessons.rb index ce0d4e9ac..375b93b40 100644 --- a/web/spec/support/lessons.rb +++ b/web/spec/support/lessons.rb @@ -28,4 +28,90 @@ def teacher_approve(lesson_session) find('.schedule.button-orange').trigger(:click) visit "/client#/jamclass" find('tr[data-lesson-session-id="' + lesson_session.id + '"] .displayStatusColumn', text: 'Scheduled') -end \ No newline at end of file +end + +def fill_out_single_lesson + + find('h2', text: 'book testdrive lesson') + find('.booking-info', text: 'If you need to cancel') + + # book the lesson + fill_in "slot-1-date", with: "Sun Apr 17 2016" + #find('.slot.slot-1 input.hasDatepicker').trigger(:click) + # click 4-6 + find('td a', text: '17').trigger(:click) + + #find('.slot.slot-2 input.hasDatepicker').trigger(:click) + # click 4-7 + fill_in "slot-2-date", with: "Mon Apr 18 2016" + find('td a', text: '18').trigger(:click) + + fill_in 'user-description', with: 'abc def dog neck' + + sleep 3 + + + find('a.book-lesson-btn', text: 'BOOK TESTDRIVE LESSON').trigger(:click) + +end + +def fill_out_payment + + fill_in 'card-number', with: '4111111111111111' + fill_in 'expiration', with: '11/2016' + fill_in 'cvv', with: '111' + fill_in 'zip', with: '78759' + + find('.purchase-btn').trigger(:click) +end + +def select_test_drive(count = 4) + find(".button-orange.select-#{count}").trigger(:click) +end + +def create_stripe_token(exp_month = 2017) + Stripe::Token.create( + :card => { + :number => "4111111111111111", + :exp_month => 2, + :exp_year => exp_month, + :cvc => "314" + }, + ).id +end + + +def testdrive_lesson(user, teacher, slots = nil) + + if slots.nil? + slots = [] + slots << FactoryGirl.build(:lesson_booking_slot_single) + slots << FactoryGirl.build(:lesson_booking_slot_single) + end + + if !user.stored_credit_card + token = create_stripe_token + user.payment_update({token: token, zip: '78759'}) + user.save! + user.stored_credit_card.should be_true + end + + + booking = LessonBooking.book_test_drive(user, teacher, slots, "Hey I've heard of you before.") + #puts "BOOKING #{booking.errors.inspect}" + booking.errors.any?.should be_false + lesson = booking.lesson_sessions[0] + booking.card_presumed_ok.should be_true + + if user.most_recent_test_drive_purchase.nil? + LessonPackagePurchase.create(user, booking, LessonPackageType.test_drive_4) + end + + lesson.accept({message: 'Yeah I got this', slot: slots[0]}) + lesson.errors.any?.should be_false + lesson.reload + lesson.slot.should eql slots[0] + lesson.status.should eql LessonSession::STATUS_APPROVED + + lesson +end