jamclass enabled
This commit is contained in:
parent
5d82f555c5
commit
92b2e13ee8
File diff suppressed because one or more lines are too long
|
|
@ -347,4 +347,5 @@ track_school_signups.sql
|
|||
add_test_drive_types.sql
|
||||
updated_subjects.sql
|
||||
update_payment_history.sql
|
||||
lesson_booking_schools.sql
|
||||
lesson_booking_schools.sql
|
||||
lesson_booking_schools_2.sql
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE lesson_bookings ADD COLUMN same_school BOOLEAN DEFAULT FALSE NOT NULL;
|
||||
ALTER TABLE schools ADD COLUMN affiliate_partner_id INTEGER REFERENCES affiliate_partners(id);
|
||||
|
|
@ -52,7 +52,7 @@ class ArtifactUploader < CarrierWave::Uploader::Base
|
|||
# Add a white list of extensions which are allowed to be uploaded.
|
||||
# For images you might use something like this:
|
||||
def extension_white_list
|
||||
%w(exe msi dmg)
|
||||
%w(exe msi dmg zip)
|
||||
end
|
||||
|
||||
# Override the filename of the uploaded files:
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
|
|||
self.table_name = 'affiliate_partners'
|
||||
|
||||
belongs_to :partner_user, :class_name => "JamRuby::User", :foreign_key => :partner_user_id, inverse_of: :affiliate_partner
|
||||
has_one :school, class_name: "JamRuby::School"
|
||||
has_many :user_referrals, :class_name => "JamRuby::User", :foreign_key => :affiliate_referral_id
|
||||
belongs_to :affiliate_legalese, :class_name => "JamRuby::AffiliateLegalese", :foreign_key => :legalese_id
|
||||
has_many :sale_line_items, :class_name => 'JamRuby::SaleLineItem', foreign_key: :affiliate_referral_id
|
||||
|
|
@ -62,7 +63,7 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
|
|||
# used by admin
|
||||
def self.create_with_params(params={})
|
||||
raise 'not supported'
|
||||
oo = self.new
|
||||
oo = AffiliatePartner.new
|
||||
oo.partner_name = params[:partner_name].try(:strip)
|
||||
oo.partner_code = params[:partner_code].try(:strip).try(:downcase)
|
||||
oo.partner_user = User.where(:email => params[:user_email].try(:strip)).limit(1).first
|
||||
|
|
@ -74,15 +75,25 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
|
|||
|
||||
# used by web
|
||||
def self.create_with_web_params(user, params={})
|
||||
oo = self.new
|
||||
oo = AffiliatePartner.new
|
||||
oo.partner_name = params[:partner_name].try(:strip)
|
||||
oo.partner_user = user if user # user is not required
|
||||
oo.entity_type = params[:entity_type] || ENTITY_TYPES.first
|
||||
oo.signed_at = Time.now
|
||||
signed_legalese
|
||||
oo.save
|
||||
oo
|
||||
end
|
||||
|
||||
def self.create_from_school(school)
|
||||
oo = AffiliatePartner.new
|
||||
oo.partner_name = "Affiliate from School #{school.id}"
|
||||
oo.partner_user = school.owner
|
||||
oo.entity_type = 'Other'
|
||||
oo.school = school
|
||||
oo.signed_at = nil
|
||||
oo.save
|
||||
end
|
||||
|
||||
def self.coded_id(code=nil)
|
||||
self.where(:partner_code => code).limit(1).pluck(:id).first if code.present?
|
||||
end
|
||||
|
|
@ -126,7 +137,11 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
|
|||
# subtract the total quantity from the freebie quantity, to see how much we should attribute to them
|
||||
real_quantity = product_info[:quantity].to_i - product_info[:marked_for_redeem].to_i
|
||||
|
||||
applicable_rate = shopping_cart.is_lesson? ? lesson_rate : rate
|
||||
if shopping_cart.is_lesson?
|
||||
applicable_rate = lesson_rate
|
||||
else
|
||||
applicable_rate = rate
|
||||
end
|
||||
|
||||
{fee_in_cents: (product_info[:price] * 100 * real_quantity * applicable_rate.to_f).round}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ module JamRuby
|
|||
|
||||
@@log = Logging.logger[LessonBooking]
|
||||
|
||||
attr_accessor :accepting, :countering, :canceling, :countered_slot, :countered_lesson
|
||||
attr_accessor :accepting, :countering, :canceling, :countered_slot, :countered_lesson, :current_purchase, :current_lesson
|
||||
|
||||
STATUS_REQUESTED = 'requested'
|
||||
STATUS_CANCELED = 'canceled'
|
||||
|
|
@ -51,6 +51,7 @@ module JamRuby
|
|||
validates :recurring, inclusion: {in: [true, false]}
|
||||
validates :sent_notices, inclusion: {in: [true, false]}
|
||||
validates :card_presumed_ok, inclusion: {in: [true, false]}
|
||||
validates :same_school, inclusion: {in: [true, false]}
|
||||
validates :active, inclusion: {in: [true, false]}
|
||||
validates :lesson_length, inclusion: {in: [30, 45, 60, 90, 120]}
|
||||
validates :payment_style, inclusion: {in: PAYMENT_STYLES}
|
||||
|
|
@ -112,7 +113,20 @@ module JamRuby
|
|||
|
||||
# here for shopping_cart
|
||||
def product_info
|
||||
{price: booked_price, real_price: booked_price, total_price: booked_price}
|
||||
if is_test_drive?
|
||||
real_price = 0
|
||||
elsif is_monthly_payment?
|
||||
raise "no purchase assigned to lesson booking for monthly payment!" if current_purchase.nil?
|
||||
real_price = self.current_purchase.teacher_distribution.jamkazam_margin
|
||||
else
|
||||
if current_lesson.nil?
|
||||
puts "OHOHOMOOMG #{self.inspect}"
|
||||
raise "no purchase assigned to lesson booking for lesson!"
|
||||
end
|
||||
|
||||
real_price = self.current_lesson.teacher_distribution.jamkazam_margin
|
||||
end
|
||||
{price: real_price, real_price: real_price, total_price: real_price}
|
||||
end
|
||||
# here for shopping_cart
|
||||
def price
|
||||
|
|
@ -357,7 +371,9 @@ module JamRuby
|
|||
end
|
||||
|
||||
def requires_teacher_distribution?(target)
|
||||
if target.is_a?(JamRuby::LessonSession)
|
||||
if school_on_school?
|
||||
false
|
||||
elsif target.is_a?(JamRuby::LessonSession)
|
||||
is_test_drive? || (is_normal? && !is_monthly_payment?)
|
||||
elsif target.is_a?(JamRuby::LessonPackagePurchase)
|
||||
is_monthly_payment?
|
||||
|
|
@ -694,6 +710,12 @@ module JamRuby
|
|||
lesson_booking.school = lesson_booking.teacher.teacher.school
|
||||
end
|
||||
|
||||
if user
|
||||
lesson_booking.same_school = !!(lesson_booking.school && user.school && (lesson_booking.school.id == user.school.id))
|
||||
else
|
||||
lesson_booking.same_school = false
|
||||
end
|
||||
|
||||
# two-way association slots, for before_validation loic in slot to work
|
||||
lesson_booking.lesson_booking_slots = lesson_booking_slots
|
||||
lesson_booking_slots.each do |slot|
|
||||
|
|
@ -718,7 +740,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
def school_on_school?
|
||||
teacher.teacher.school && student.school && (teacher.teacher.school.id == student.school.id)
|
||||
same_school
|
||||
end
|
||||
|
||||
def self.find_bookings_needing_sessions(minimum_start_time)
|
||||
|
|
@ -760,6 +782,7 @@ module JamRuby
|
|||
.joins("LEFT JOIN lesson_package_purchases ON (lesson_package_purchases.lesson_booking_id = lesson_bookings.id AND (lesson_package_purchases.year = #{current_month_first_day.year} AND lesson_package_purchases.month = #{current_month_first_day.month}))")
|
||||
.where("lesson_package_purchases.id IS NULL OR (lesson_package_purchases.id IS NOT NULL AND lesson_package_purchases.post_processed = false)")
|
||||
.where(payment_style: PAYMENT_STYLE_MONTHLY)
|
||||
.where(same_school: false)
|
||||
.active
|
||||
.where('music_sessions.scheduled_start >= ?', current_month_first_day)
|
||||
.where('music_sessions.scheduled_start <= ?', current_month_last_day).uniq
|
||||
|
|
|
|||
|
|
@ -121,15 +121,20 @@ module JamRuby
|
|||
user
|
||||
end
|
||||
|
||||
# test drive purchase doesn't have a tea
|
||||
def school_on_school?
|
||||
teacher.teacher.school && student.school && (teacher.teacher.school.id == student.school.id)
|
||||
if teacher
|
||||
teacher.teacher.school && student.school && (teacher.teacher.school.id == student.school.id)
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def bill_monthly(force = false)
|
||||
|
||||
if school_on_school?
|
||||
success = true
|
||||
raise "school-on-school: should not be here"
|
||||
else
|
||||
lesson_payment_charge.charge(force)
|
||||
success = lesson_payment_charge.billed
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ module JamRuby
|
|||
@@log = Logging.logger[LessonSession]
|
||||
|
||||
delegate :sent_billing_notices, :last_billing_attempt_at, :billing_attempts, :billing_should_retry, :billed_at, :billing_error_detail, :billing_error_reason, :is_card_declined?, :is_card_expired?, :last_billed_at_date, :sent_billing_notices, to: :lesson_payment_charge, allow_nil: true
|
||||
delegate :is_test_drive?, :is_single_free?, :is_normal?, :approved_before?, :is_active?, :recurring, :is_monthly_payment?, to: :lesson_booking
|
||||
delegate :is_test_drive?, :is_single_free?, :is_normal?, :approved_before?, :is_active?, :recurring, :is_monthly_payment?, :school_on_school?, to: :lesson_booking
|
||||
delegate :pretty_scheduled_start, to: :music_session
|
||||
|
||||
|
||||
|
|
@ -176,13 +176,19 @@ module JamRuby
|
|||
def billed
|
||||
if lesson_booking.is_test_drive?
|
||||
false
|
||||
else
|
||||
elsif lesson_payment_charge
|
||||
lesson_payment_charge.billed
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def amount_charged
|
||||
lesson_payment_charge.amount_in_cents / 100.0
|
||||
if lesson_payment_charge
|
||||
lesson_payment_charge.amount_in_cents / 100.0
|
||||
else
|
||||
0.0
|
||||
end
|
||||
end
|
||||
|
||||
def self.analysis_to_json(analysis, preserve_object = false)
|
||||
|
|
@ -398,10 +404,6 @@ module JamRuby
|
|||
@parsed_analysis || analysis ? JSON.parse(analysis) : nil
|
||||
end
|
||||
|
||||
def school_on_school?
|
||||
teacher.teacher.school && student.school && (teacher.teacher.school.id == student.school.id)
|
||||
end
|
||||
|
||||
def validate_creating
|
||||
if !is_requested? && !is_approved?
|
||||
self.errors.add(:status, "is not valid for a new lesson session.")
|
||||
|
|
@ -490,7 +492,13 @@ module JamRuby
|
|||
query = query.where('(lesson_sessions.teacher_id = ? or music_sessions.user_id = ?)', user.id, user.id)
|
||||
end
|
||||
|
||||
query = query.where('lesson_bookings.card_presumed_ok = true OR (music_sessions.user_id = ?)', user.id)
|
||||
if user.school_id
|
||||
school_extra = "OR (lesson_bookings.school_id = '#{user.school_id}')"
|
||||
else
|
||||
school_extra = ''
|
||||
end
|
||||
|
||||
query = query.where('lesson_bookings.card_presumed_ok = true OR (music_sessions.user_id = ?) ' + school_extra, user.id)
|
||||
|
||||
current_page = params[:page].nil? ? 1 : params[:page].to_i
|
||||
next_page = current_page + 1
|
||||
|
|
|
|||
|
|
@ -228,6 +228,11 @@ module JamRuby
|
|||
|
||||
if sale.valid?
|
||||
|
||||
if lesson_booking
|
||||
lesson_booking.current_lesson = lesson_session
|
||||
lesson_booking.current_purchase = lesson_package_purchase
|
||||
end
|
||||
|
||||
sale_line_item = SaleLineItem.create_from_lesson_package(current_user, sale, lesson_package_type, lesson_booking)
|
||||
|
||||
price_info = charge_stripe_for_lesson(current_user, lesson_booking, lesson_package_type, sale_line_item, lesson_session, lesson_package_purchase, force)
|
||||
|
|
@ -251,10 +256,12 @@ module JamRuby
|
|||
purchase = price_info[:purchase]
|
||||
else
|
||||
# should not get out of testing. This would be very rare (i.e., from a big regression). Sale is always valid at this point.
|
||||
puts "invalid sale object"
|
||||
raise "invalid sale object"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
{sale: sale, stripe_charge: stripe_charge, purchase: purchase}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,15 @@ module JamRuby
|
|||
line_item
|
||||
end
|
||||
|
||||
def add_referral_if_needed(user, shopping_cart, lesson_booking)
|
||||
# if the teacher came from an affiliate, this is our chance to account for that (the student's affiliate status was accounted for in create_from_shopping_cart)
|
||||
referral_info = user.should_attribute_sale?(shopping_cart, lesson_booking)
|
||||
|
||||
if referral_info
|
||||
self.affiliate_distributions << AffiliateDistribution.create(user.affiliate_referral, referral_info[:fee_in_cents], self)
|
||||
self.save!
|
||||
end
|
||||
end
|
||||
# in a shopping-cart less world (ios purchase), let's reuse as much logic as possible
|
||||
def self.create_from_lesson_package(current_user, sale, lesson_package_type, lesson_booking)
|
||||
teacher = lesson_booking.teacher if lesson_booking
|
||||
|
|
@ -98,12 +107,20 @@ module JamRuby
|
|||
line_item = create_from_shopping_cart(sale, shopping_cart, nil, nil, nil, lesson_booking)
|
||||
|
||||
if lesson_booking
|
||||
# if the teacher came from an affiliate, this is our chance to account for that (the student's affiliate status was accounted for in create_from_shopping_cart)
|
||||
referral_info = teacher.should_attribute_sale?(shopping_cart, lesson_booking)
|
||||
|
||||
if referral_info
|
||||
line_item.affiliate_distributions << AffiliateDistribution.create(teacher.affiliate_referral, referral_info[:fee_in_cents], line_item)
|
||||
line_item.save!
|
||||
teacher = lesson_booking.teacher
|
||||
student = lesson_booking.student
|
||||
|
||||
if lesson_booking.is_test_drive?
|
||||
# no referral for test drives
|
||||
elsif lesson_booking.school_on_school?
|
||||
# no referral; we don't make money on school-on-school
|
||||
else
|
||||
line_item.add_referral_if_needed(student, shopping_cart, lesson_booking)
|
||||
|
||||
if lesson_booking.school.nil?
|
||||
line_item.add_referral_if_needed(teacher, shopping_cart, lesson_booking)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -131,7 +148,7 @@ module JamRuby
|
|||
|
||||
# determine if we need to associate this sale with a partner
|
||||
user = shopping_cart.user
|
||||
referral_info = user.should_attribute_sale?(shopping_cart, instance)
|
||||
referral_info = user.should_attribute_sale?(shopping_cart, instance) if !instance || !instance.is_a?(LessonBooking) # all affiliate stuff is handled elsewhere
|
||||
|
||||
if referral_info
|
||||
sale_line_item.affiliate_distributions << AffiliateDistribution.create(user.affiliate_referral, referral_info[:fee_in_cents], sale_line_item)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ module JamRuby
|
|||
attr_accessible :original_fpfile, :cropped_fpfile, :cropped_large_fpfile, :cropped_s3_path, :cropped_large_s3_path, :photo_url, :large_photo_url, :crop_selection
|
||||
|
||||
belongs_to :user, class_name: ::JamRuby::User, inverse_of: :owned_school
|
||||
belongs_to :affiliate_partner, class_name: "JamRuby::AffiliatePartner"
|
||||
has_many :students, class_name: ::JamRuby::User
|
||||
has_many :teachers, class_name: ::JamRuby::Teacher
|
||||
has_many :school_invitations, class_name: 'JamRuby::SchoolInvitation'
|
||||
|
|
@ -27,8 +28,12 @@ module JamRuby
|
|||
validates :correspondence_email, email: true, allow_blank: true
|
||||
validate :validate_avatar_info
|
||||
|
||||
after_create :create_affiliate
|
||||
before_save :stringify_avatar_info, :if => :updating_avatar
|
||||
|
||||
def create_affiliate
|
||||
AffiliatePartner.create_from_school(self)
|
||||
end
|
||||
def update_from_params(params)
|
||||
self.name = params[:name] if params[:name].present?
|
||||
self.scheduling_communication = params[:scheduling_communication] if params[:scheduling_communication].present?
|
||||
|
|
|
|||
|
|
@ -58,6 +58,10 @@ module JamRuby
|
|||
# only show teachers with ready for session set to true
|
||||
query = query.where('teachers.ready_for_session_at IS NOT NULL')
|
||||
|
||||
if params[:onlyMySchool] && params[:onlyMySchool] != 'false' && user.school_id
|
||||
query = query.where("teachers.school_id = ?", user.school_id)
|
||||
end
|
||||
|
||||
instruments = params[:instruments]
|
||||
if instruments && !instruments.blank? && instruments.length > 0
|
||||
query = query.joins("inner JOIN teachers_instruments AS tinst ON tinst.teacher_id = teachers.id")
|
||||
|
|
|
|||
|
|
@ -80,11 +80,37 @@ module JamRuby
|
|||
'$%.2f' % real_distribution
|
||||
end
|
||||
|
||||
def jamkazam_margin_in_cents
|
||||
if is_test_drive?
|
||||
0
|
||||
else
|
||||
if school
|
||||
# if school exists, use it's rate
|
||||
rate = school.jamkazam_rate
|
||||
else
|
||||
# otherwise use the teacher's rate
|
||||
rate = teacher.teacher.jamkazam_rate
|
||||
end
|
||||
amount_in_cents * (rate)
|
||||
end
|
||||
end
|
||||
|
||||
def jamkazam_margin
|
||||
(jamkazam_margin_in_cents / 100).round(2)
|
||||
end
|
||||
|
||||
def calculate_teacher_fee
|
||||
if is_test_drive?
|
||||
0
|
||||
else
|
||||
(amount_in_cents * (teacher.teacher.jamkazam_rate + 0.03)).round
|
||||
if school
|
||||
# if school exists, use it's rate
|
||||
rate = school.jamkazam_rate
|
||||
else
|
||||
# otherwise use the teacher's rate
|
||||
rate = teacher.teacher.jamkazam_rate
|
||||
end
|
||||
(amount_in_cents * (rate + 0.03)).round
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -116,7 +142,7 @@ module JamRuby
|
|||
if lesson_session
|
||||
lesson_session.timed_description
|
||||
else
|
||||
lesson_package_purchase.description
|
||||
lesson_package_purchase.timed_description
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ module JamRuby
|
|||
# bands
|
||||
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"
|
||||
belongs_to :teacher, :class_name => "JamRuby::Teacher", foreign_key: :teacher_id
|
||||
|
||||
# genres
|
||||
has_many :genre_players, as: :player, class_name: "JamRuby::GenrePlayer", dependent: :destroy
|
||||
|
|
@ -1106,6 +1106,7 @@ module JamRuby
|
|||
school_id = options[:school_id]
|
||||
school_interest = options[:school_interest]
|
||||
|
||||
school = School.find(school_id) if school_id
|
||||
user = User.new
|
||||
user.validate_instruments = true
|
||||
UserManager.active_record_transaction do |user_manager|
|
||||
|
|
@ -1139,10 +1140,12 @@ module JamRuby
|
|||
if school_id.present?
|
||||
if user.is_a_student
|
||||
user.school_id = school_id
|
||||
user.affiliate_referral = school.affiliate_partner
|
||||
elsif user.is_a_teacher
|
||||
school = School.find_by_id(school_id)
|
||||
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)
|
||||
user.affiliate_referral = school.affiliate_partner
|
||||
end
|
||||
else
|
||||
if user.is_a_teacher
|
||||
|
|
@ -1869,6 +1872,7 @@ module JamRuby
|
|||
return false
|
||||
end
|
||||
|
||||
|
||||
if affiliate_referral
|
||||
referral_info = affiliate_referral.should_attribute_sale?(shopping_cart, self, instance)
|
||||
else
|
||||
|
|
@ -2109,10 +2113,22 @@ module JamRuby
|
|||
end
|
||||
|
||||
def has_rated_teacher(teacher)
|
||||
teacher_rating(teacher).count > 0
|
||||
end
|
||||
|
||||
def has_rated_student(student)
|
||||
student_rating(student).count > 0
|
||||
end
|
||||
|
||||
def teacher_rating(teacher)
|
||||
if teacher.is_a?(JamRuby::User)
|
||||
teacher = teacher.teacher
|
||||
end
|
||||
Review.where(target_id: teacher.id).where(target_type: teacher.class.to_s).count > 0
|
||||
Review.where(target_id: teacher.id).where(target_type: teacher.class.to_s)
|
||||
end
|
||||
|
||||
def student_rating(student)
|
||||
Review.where(target_id: student.id).where(target_type: "JamRuby::User")
|
||||
end
|
||||
|
||||
def has_rated_student(student)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@ describe "Monthly Recurring Lesson Flow" do
|
|||
let(:lesson_booking_slot_recurring2) { FactoryGirl.build(:lesson_booking_slot_recurring) }
|
||||
let(:valid_single_slots) { [lesson_booking_slot_single1, lesson_booking_slot_single2] }
|
||||
let(:valid_recurring_slots) { [lesson_booking_slot_recurring1, lesson_booking_slot_recurring2] }
|
||||
let(:affiliate_partner) { FactoryGirl.create(:affiliate_partner) }
|
||||
let(:affiliate_partner2) { FactoryGirl.create(:affiliate_partner, lesson_rate: 0.30) }
|
||||
let(:school) {FactoryGirl.create(:school)}
|
||||
|
||||
|
||||
|
||||
after {Timecop.return}
|
||||
|
|
@ -37,12 +41,15 @@ describe "Monthly Recurring Lesson Flow" do
|
|||
|
||||
########## Need validate their credit card
|
||||
token = create_stripe_token
|
||||
result = user.payment_update({token: token, zip: '78759', normal: true})
|
||||
result = user.payment_update({token: token, zip: '78759', normal: true, booking_id: booking.id})
|
||||
puts "result #{result.inspect}"
|
||||
booking.reload
|
||||
booking.card_presumed_ok.should be_true
|
||||
booking.errors.any?.should be_false
|
||||
lesson.errors.any?.should be_false
|
||||
booking = result[:lesson]
|
||||
lesson = booking.lesson_sessions[0]
|
||||
lesson.errors.any?.should be_false
|
||||
|
||||
booking.sent_notices.should be_true
|
||||
lesson.music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
|
||||
lesson.amount_charged.should be 0.0
|
||||
|
|
@ -147,6 +154,9 @@ describe "Monthly Recurring Lesson Flow" do
|
|||
# artificially end the session, which is covered by other background jobs
|
||||
lesson_session.music_session.session_removed_at = end_time
|
||||
lesson_session.music_session.save!
|
||||
|
||||
Timecop.travel(end_time + 1)
|
||||
|
||||
LessonSession.hourly_check
|
||||
lesson_session.reload
|
||||
lesson_session.analysed.should be_true
|
||||
|
|
@ -223,9 +233,259 @@ describe "Monthly Recurring Lesson Flow" do
|
|||
|
||||
lesson.amount_charged.should eql 0.0
|
||||
lesson_session.billing_error_reason.should be_nil
|
||||
lesson_session.sent_billing_notices.should be false
|
||||
lesson_session.sent_billing_notices.should be nil
|
||||
user.reload
|
||||
user.remaining_test_drives.should eql 0
|
||||
UserMailer.deliveries.length.should eql 1 # one for student
|
||||
UserMailer.deliveries.length.should eql 0 # one for student
|
||||
end
|
||||
|
||||
it "works (school on school)" do
|
||||
|
||||
# get user and teacher into same school
|
||||
user.school = school
|
||||
user.save!
|
||||
teacher.school = school
|
||||
teacher.save!
|
||||
|
||||
# if it's later in the month, we'll make 2 lesson_package_purchases (prorated one, and next month's), which can throw off some assertions later on
|
||||
Timecop.travel(Date.new(2016, 3, 20))
|
||||
|
||||
# user has no test drives, no credit card on file, but attempts to book a lesson
|
||||
booking = LessonBooking.book_normal(user, teacher_user, valid_recurring_slots, "Hey I've heard of you before.", true, LessonBooking::PAYMENT_STYLE_MONTHLY, 60)
|
||||
booking.errors.any?.should be_false
|
||||
booking.card_presumed_ok.should be_false
|
||||
booking.user.should eql user
|
||||
booking.card_presumed_ok.should be_false
|
||||
booking.sent_notices.should be_true
|
||||
booking.booked_price.should eql 30.00
|
||||
|
||||
|
||||
user.reload
|
||||
user.stripe_customer_id.should be nil
|
||||
user.remaining_test_drives.should eql 0
|
||||
user.lesson_purchases.length.should eql 0
|
||||
|
||||
booking.lesson_sessions.length.should eql 1
|
||||
lesson_session = booking.lesson_sessions[0]
|
||||
lesson_session.status.should eql LessonBooking::STATUS_REQUESTED
|
||||
booking.status.should eql LessonBooking::STATUS_REQUESTED
|
||||
|
||||
######### Teacher counters with new slot
|
||||
teacher_countered_slot = FactoryGirl.build(:lesson_booking_slot_single, hour: 14, update_all: true)
|
||||
UserMailer.deliveries.clear
|
||||
lesson_session.counter({proposer: teacher_user, slot: teacher_countered_slot, message: 'Does this work?'})
|
||||
booking.reload
|
||||
booking.errors.any?.should be false
|
||||
lesson_session.lesson_booking.errors.any?.should be false
|
||||
lesson_session.lesson_booking_slots.length.should eql 1
|
||||
lesson_session.lesson_booking_slots[0].proposer.should eql teacher_user
|
||||
teacher_counter = lesson_session.lesson_booking_slots.order(:created_at).last
|
||||
teacher_counter.should eql teacher_countered_slot
|
||||
teacher_counter.proposer.should eql teacher_user
|
||||
booking.lesson_booking_slots.length.should eql 3
|
||||
UserMailer.deliveries.length.should eql 1
|
||||
chat = ChatMessage.unscoped.order(:created_at).last
|
||||
chat.channel.should eql ChatMessage::CHANNEL_LESSON
|
||||
chat.message.should eql 'Does this work?'
|
||||
chat.user.should eql teacher_user
|
||||
chat.target_user.should eql user
|
||||
notification = Notification.unscoped.order(:created_at).last
|
||||
notification.session_id.should eql lesson_session.music_session.id
|
||||
notification.student_directed.should eql true
|
||||
notification.purpose.should eql 'counter'
|
||||
notification.description.should eql NotificationTypes::LESSON_MESSAGE
|
||||
|
||||
######### Student counters with new slot
|
||||
student_countered_slot = FactoryGirl.build(:lesson_booking_slot_single, hour: 16, update_all: true)
|
||||
UserMailer.deliveries.clear
|
||||
lesson_session.counter({proposer: user, slot: student_countered_slot, message: 'Does this work better?'})
|
||||
lesson_session.errors.any?.should be false
|
||||
lesson_session.lesson_booking.errors.any?.should be false
|
||||
lesson_session.lesson_booking_slots.length.should eql 2
|
||||
student_counter = booking.lesson_booking_slots.order(:created_at).last
|
||||
student_counter.proposer.should eql user
|
||||
booking.reload
|
||||
booking.lesson_booking_slots.length.should eql 4
|
||||
UserMailer.deliveries.length.should eql 1
|
||||
chat = ChatMessage.unscoped.order(:created_at).last
|
||||
chat.message.should eql 'Does this work better?'
|
||||
chat.channel.should eql ChatMessage::CHANNEL_LESSON
|
||||
chat.user.should eql user
|
||||
chat.target_user.should eql teacher_user
|
||||
notification = Notification.unscoped.order(:created_at).last
|
||||
notification.session_id.should eql lesson_session.music_session.id
|
||||
notification.student_directed.should eql false
|
||||
notification.purpose.should eql 'counter'
|
||||
notification.description.should eql NotificationTypes::LESSON_MESSAGE
|
||||
|
||||
######## Teacher accepts slot
|
||||
UserMailer.deliveries.clear
|
||||
lesson_session.accept({message: 'Yeah I got this', slot: student_counter.id, update_all: false})
|
||||
UserMailer.deliveries.each do |del|
|
||||
# puts del.inspect
|
||||
end
|
||||
# get acceptance emails, as well as 'your stuff is accepted'
|
||||
UserMailer.deliveries.length.should eql 2
|
||||
lesson_session.errors.any?.should be_false
|
||||
lesson_session.reload
|
||||
lesson_session.slot.should eql student_counter
|
||||
lesson_session.status.should eql LessonSession::STATUS_APPROVED
|
||||
booking.reload
|
||||
booking.default_slot.should eql student_counter
|
||||
lesson_session.music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
|
||||
booking.status.should eql LessonBooking::STATUS_APPROVED
|
||||
|
||||
UserMailer.deliveries.length.should eql 2
|
||||
chat = ChatMessage.unscoped.order(:created_at).last
|
||||
chat.message.should eql 'Yeah I got this'
|
||||
chat.purpose.should eql 'Lesson Approved'
|
||||
chat.channel.should eql ChatMessage::CHANNEL_LESSON
|
||||
chat.user.should eql teacher_user
|
||||
chat.target_user.should eql user
|
||||
notification = Notification.unscoped.order(:created_at).last
|
||||
notification.session_id.should eql lesson_session.music_session.id
|
||||
notification.student_directed.should eql true
|
||||
notification.purpose.should eql 'accept'
|
||||
notification.description.should eql NotificationTypes::LESSON_MESSAGE
|
||||
|
||||
|
||||
# teacher & student get into session
|
||||
start = lesson_session.scheduled_start
|
||||
end_time = lesson_session.scheduled_start + (60 * lesson_session.duration)
|
||||
uh2 = FactoryGirl.create(:music_session_user_history, user: teacher_user, history: lesson_session.music_session, created_at: start, session_removed_at: end_time)
|
||||
# artificially end the session, which is covered by other background jobs
|
||||
lesson_session.music_session.session_removed_at = end_time
|
||||
lesson_session.music_session.save!
|
||||
|
||||
Timecop.travel(end_time + 1)
|
||||
|
||||
LessonSession.hourly_check
|
||||
lesson_session.reload
|
||||
lesson_session.analysed.should be_true
|
||||
analysis = JSON.parse(lesson_session.analysis)
|
||||
analysis["reason"].should eql LessonSessionAnalyser::STUDENT_FAULT
|
||||
analysis["student"].should eql LessonSessionAnalyser::NO_SHOW
|
||||
if lesson_session.billing_error_detail
|
||||
puts "monthly recurring lesson flow #{lesson_session.billing_error_detail}" # this should not occur, but helps a great deal if a regression occurs and running all the tests
|
||||
end
|
||||
|
||||
# let user pay for it
|
||||
LessonBooking.hourly_check
|
||||
|
||||
LessonPaymentCharge.count.should eql 0
|
||||
TeacherDistribution.count.should eql 0
|
||||
|
||||
user.reload
|
||||
user.lesson_purchases.length.should eql 0
|
||||
user.sales.length.should eql 0
|
||||
|
||||
|
||||
TeacherPayment.count.should eql 0
|
||||
TeacherPayment.hourly_check
|
||||
TeacherPayment.count.should eql 0
|
||||
|
||||
|
||||
# teacher & student get into session
|
||||
start = lesson_session.scheduled_start
|
||||
end_time = lesson_session.scheduled_start + (60 * lesson_session.duration)
|
||||
uh2 = FactoryGirl.create(:music_session_user_history, user: teacher_user, history: lesson_session.music_session, created_at: start, session_removed_at: end_time)
|
||||
# artificially end the session, which is covered by other background jobs
|
||||
lesson_session.music_session.session_removed_at = end_time
|
||||
lesson_session.music_session.save!
|
||||
|
||||
|
||||
UserMailer.deliveries.clear
|
||||
# background code comes around and analyses the session
|
||||
LessonSession.hourly_check
|
||||
lesson_session.reload
|
||||
lesson_session.analysed.should be_true
|
||||
analysis = JSON.parse(lesson_session.analysis)
|
||||
analysis["reason"].should eql LessonSessionAnalyser::STUDENT_FAULT
|
||||
analysis["student"].should eql LessonSessionAnalyser::NO_SHOW
|
||||
if lesson_session.billing_error_detail
|
||||
puts "monthly recurring lesson flow #{lesson_session.billing_error_detail}" # this should not occur, but helps a great deal if a regression occurs and running all the tests
|
||||
end
|
||||
|
||||
lesson_session.amount_charged.should eql 0.0
|
||||
lesson_session.billing_error_reason.should be_nil
|
||||
lesson_session.sent_billing_notices.should be_nil
|
||||
user.reload
|
||||
user.remaining_test_drives.should eql 0
|
||||
UserMailer.deliveries.length.should eql 0 # one for student
|
||||
|
||||
LessonPaymentCharge.count.should eql 0
|
||||
TeacherDistribution.count.should eql 0
|
||||
end
|
||||
|
||||
|
||||
it "affiliate gets their cut" do
|
||||
user.affiliate_referral = affiliate_partner
|
||||
user.save!
|
||||
teacher_user.affiliate_referral = affiliate_partner2
|
||||
teacher_user.save!
|
||||
|
||||
lesson = monthly_lesson(user, teacher_user, true)
|
||||
|
||||
user.reload
|
||||
|
||||
user.lesson_purchases.count.should eql 1
|
||||
lesson_package_purchase = user.lesson_purchases.first
|
||||
teacher_distribution = lesson_package_purchase.teacher_distribution
|
||||
|
||||
|
||||
user.sales.count.should eql 1
|
||||
user.sales[0].sale_line_items[0].affiliate_distributions.count.should eql 2
|
||||
affiliate_partner.affiliate_distributions.count.should eql 1
|
||||
affiliate_partner2.affiliate_distributions.count.should eql 1
|
||||
partner1_distribution = affiliate_partner.affiliate_distributions.first
|
||||
partner2_distribution = affiliate_partner2.affiliate_distributions.first
|
||||
partner1_distribution.sale_line_item.should eql partner2_distribution.sale_line_item
|
||||
partner1_distribution.affiliate_referral_fee_in_cents.should eql (teacher_distribution.jamkazam_margin_in_cents * affiliate_partner.lesson_rate).round
|
||||
partner2_distribution.affiliate_referral_fee_in_cents.should eql (teacher_distribution.jamkazam_margin_in_cents * affiliate_partner2.lesson_rate).round
|
||||
end
|
||||
|
||||
it "school affiliate gets nothing when teacher school is involved" do
|
||||
teacher.school = school
|
||||
teacher.save!
|
||||
|
||||
user.affiliate_referral = affiliate_partner
|
||||
user.save!
|
||||
|
||||
lesson = monthly_lesson(user, teacher_user, true)
|
||||
|
||||
user.sales.count.should eql 1
|
||||
user.sales[0].sale_line_items[0].affiliate_distributions.count.should eql 1
|
||||
user.lesson_purchases.count.should eql 1
|
||||
lesson_package_purchase = user.lesson_purchases.first
|
||||
teacher_distribution = lesson_package_purchase.teacher_distribution
|
||||
|
||||
|
||||
affiliate_partner.affiliate_distributions.count.should eql 1
|
||||
partner1_distribution = affiliate_partner.affiliate_distributions.first
|
||||
partner1_distribution.affiliate_referral_fee_in_cents.should eql (teacher_distribution.jamkazam_margin_in_cents * affiliate_partner.lesson_rate).round
|
||||
school.affiliate_partner.affiliate_distributions.count.should eql 0
|
||||
end
|
||||
|
||||
it "student school affiliates gets cut when student school is involved. so does teacher's" do
|
||||
user.affiliate_referral = school.affiliate_partner
|
||||
user.save!
|
||||
|
||||
teacher_user.affiliate_referral = affiliate_partner
|
||||
teacher_user.save!
|
||||
|
||||
lesson = monthly_lesson(user, teacher_user, true)
|
||||
|
||||
user.sales.count.should eql 1
|
||||
user.sales[0].sale_line_items[0].affiliate_distributions.count.should eql 2
|
||||
user.lesson_purchases.count.should eql 1
|
||||
lesson_package_purchase = user.lesson_purchases.first
|
||||
teacher_distribution = lesson_package_purchase.teacher_distribution
|
||||
|
||||
|
||||
affiliate_partner.affiliate_distributions.count.should eql 1
|
||||
partner1_distribution = affiliate_partner.affiliate_distributions.count.should eql 1
|
||||
school.affiliate_partner.affiliate_distributions.count.should eql 1
|
||||
school_partner_distribution = school.affiliate_partner.affiliate_distributions.first
|
||||
school_partner_distribution.affiliate_referral_fee_in_cents.should eql (teacher_distribution.jamkazam_margin_in_cents * school.affiliate_partner.lesson_rate).round
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,8 +12,12 @@ describe "Normal Lesson Flow" do
|
|||
let(:lesson_booking_slot_recurring2) { FactoryGirl.build(:lesson_booking_slot_recurring) }
|
||||
let(:valid_single_slots) { [lesson_booking_slot_single1, lesson_booking_slot_single2] }
|
||||
let(:valid_recurring_slots) { [lesson_booking_slot_recurring1, lesson_booking_slot_recurring2] }
|
||||
let(:affiliate_partner) { FactoryGirl.create(:affiliate_partner) }
|
||||
let(:affiliate_partner2) { FactoryGirl.create(:affiliate_partner, lesson_rate: 0.30) }
|
||||
let(:school) {FactoryGirl.create(:school)}
|
||||
|
||||
after {Timecop.return}
|
||||
|
||||
describe "stripe mocked" do
|
||||
before {
|
||||
StripeMock.clear_errors
|
||||
|
|
@ -22,7 +26,6 @@ describe "Normal Lesson Flow" do
|
|||
teacher.save!
|
||||
}
|
||||
after { StripeMock.stop }
|
||||
after {Timecop.return}
|
||||
|
||||
it "bill failure" do
|
||||
|
||||
|
|
@ -434,22 +437,18 @@ describe "Normal Lesson Flow" do
|
|||
booking.school.should be_true
|
||||
booking.card_presumed_ok.should be_false
|
||||
booking.user.should eql user
|
||||
user.unprocessed_normal_lesson.should eql []
|
||||
booking.sent_notices.should be_false
|
||||
user.unprocessed_normal_lesson.should be_nil
|
||||
booking.sent_notices.should be_true
|
||||
booking.booked_price.should eql 30.00
|
||||
booking.is_requested?.should be_true
|
||||
booking.sent_notices.should be_true
|
||||
lesson.music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
|
||||
booking.lesson_sessions[0].music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
|
||||
LessonPaymentCharge.count.should eql 0
|
||||
|
||||
user.reload
|
||||
user.stripe_customer_id.should_not be nil
|
||||
user.stripe_customer_id.should be_nil
|
||||
user.remaining_test_drives.should eql 0
|
||||
user.lesson_purchases.length.should eql 0
|
||||
|
||||
customer = Stripe::Customer.retrieve(user.stripe_customer_id)
|
||||
customer.email.should eql user.email
|
||||
|
||||
booking.lesson_sessions.length.should eql 1
|
||||
lesson_session = booking.lesson_sessions[0]
|
||||
lesson_session.status.should eql LessonBooking::STATUS_REQUESTED
|
||||
|
|
@ -550,35 +549,75 @@ describe "Normal Lesson Flow" do
|
|||
if lesson_session.billing_error_detail
|
||||
puts "testdrive flow #{lesson_session.billing_error_detail}" # this should not occur, but helps a great deal if a regression occurs and running all the tests
|
||||
end
|
||||
lesson_session.billed.should be true
|
||||
lesson_session.billed.should be false
|
||||
user.reload
|
||||
user.lesson_purchases.length.should eql 1
|
||||
lesson_purchase = user.lesson_purchases[0]
|
||||
lesson_purchase.price.should eql 30.00
|
||||
lesson_purchase.lesson_package_type.is_normal?.should eql true
|
||||
lesson_purchase.price_in_cents.should eql 3000
|
||||
user.sales.length.should eql 1
|
||||
sale = user.sales.first
|
||||
sale.stripe_charge_id.should_not be_nil
|
||||
sale.recurly_tax_in_cents.should eql (100 * booking.booked_price.to_f * 0.0825).round.to_i
|
||||
sale.recurly_total_in_cents.should eql ((100 * booking.booked_price.to_f * 0.0825).round + 100 * booking.booked_price.to_f).to_i
|
||||
sale.recurly_subtotal_in_cents.should eql (100 * booking.booked_price).to_i
|
||||
sale.recurly_currency.should eql 'USD'
|
||||
sale.stripe_charge_id.should_not be_nil
|
||||
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.single.id
|
||||
line_item.lesson_package_purchase.should eql lesson_purchase
|
||||
lesson_purchase.sale_line_item.should eql line_item
|
||||
lesson.amount_charged.should eql (sale.recurly_total_in_cents / 100.0).to_f
|
||||
user.lesson_purchases.length.should eql 0
|
||||
user.sales.length.should eql 0
|
||||
lesson_session.amount_charged.should eql 0.0
|
||||
lesson_session.billing_error_reason.should be_nil
|
||||
lesson_session.sent_billing_notices.should be true
|
||||
lesson_session.sent_billing_notices.should be_nil
|
||||
user.reload
|
||||
user.remaining_test_drives.should eql 0
|
||||
UserMailer.deliveries.length.should eql 2 # one for student, one for teacher
|
||||
UserMailer.deliveries.length.should eql 0 # one for student, one for teacher
|
||||
|
||||
LessonPaymentCharge.count.should eql 0
|
||||
TeacherDistribution.count.should eql 0
|
||||
end
|
||||
|
||||
it "affiliate gets their cut" do
|
||||
user.affiliate_referral = affiliate_partner
|
||||
user.save!
|
||||
teacher_user.affiliate_referral = affiliate_partner2
|
||||
teacher_user.save!
|
||||
|
||||
lesson = normal_lesson(user, teacher_user, true)
|
||||
|
||||
user.reload
|
||||
user.sales.count.should eql 1
|
||||
user.sales[0].sale_line_items[0].affiliate_distributions.count.should eql 2
|
||||
affiliate_partner.affiliate_distributions.count.should eql 1
|
||||
affiliate_partner2.affiliate_distributions.count.should eql 1
|
||||
partner1_distribution = affiliate_partner.affiliate_distributions.first
|
||||
partner2_distribution = affiliate_partner2.affiliate_distributions.first
|
||||
partner1_distribution.sale_line_item.should eql partner2_distribution.sale_line_item
|
||||
partner1_distribution.affiliate_referral_fee_in_cents.should eql (3000 * 0.25 * affiliate_partner.lesson_rate).round
|
||||
partner2_distribution.affiliate_referral_fee_in_cents.should eql (3000 * 0.25 * affiliate_partner2.lesson_rate).round
|
||||
end
|
||||
|
||||
it "school affiliate gets nothing when teacher school is involved" do
|
||||
teacher.school = school
|
||||
teacher.save!
|
||||
|
||||
user.affiliate_referral = affiliate_partner
|
||||
user.save!
|
||||
|
||||
lesson = normal_lesson(user, teacher_user, true)
|
||||
|
||||
user.sales.count.should eql 1
|
||||
user.sales[0].sale_line_items[0].affiliate_distributions.count.should eql 1
|
||||
|
||||
affiliate_partner.affiliate_distributions.count.should eql 1
|
||||
partner1_distribution = affiliate_partner.affiliate_distributions.first
|
||||
partner1_distribution.affiliate_referral_fee_in_cents.should eql (3000 * 0.25 * affiliate_partner.lesson_rate).round
|
||||
school.affiliate_partner.affiliate_distributions.count.should eql 0
|
||||
end
|
||||
|
||||
it "student school affiliates gets cut when student school is involved. so does teacher's" do
|
||||
user.affiliate_referral = school.affiliate_partner
|
||||
user.save!
|
||||
|
||||
teacher_user.affiliate_referral = affiliate_partner
|
||||
teacher_user.save!
|
||||
|
||||
lesson = normal_lesson(user, teacher_user, true)
|
||||
|
||||
user.sales.count.should eql 1
|
||||
user.sales[0].sale_line_items[0].affiliate_distributions.count.should eql 2
|
||||
|
||||
affiliate_partner.affiliate_distributions.count.should eql 1
|
||||
partner1_distribution = affiliate_partner.affiliate_distributions.count.should eql 1
|
||||
school.affiliate_partner.affiliate_distributions.count.should eql 1
|
||||
school_partner_distribution = school.affiliate_partner.affiliate_distributions.first
|
||||
school_partner_distribution.affiliate_referral_fee_in_cents.should eql (3000 * 0.25 * school.affiliate_partner.lesson_rate).round
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ describe "Recurring Lesson Flow" do
|
|||
let(:valid_single_slots) { [lesson_booking_slot_single1, lesson_booking_slot_single2] }
|
||||
let(:valid_recurring_slots) { [lesson_booking_slot_recurring1, lesson_booking_slot_recurring2] }
|
||||
|
||||
before(:each) do
|
||||
after(:each) do
|
||||
Timecop.return
|
||||
end
|
||||
it "works" do
|
||||
|
|
|
|||
|
|
@ -12,12 +12,18 @@ describe "TestDrive Lesson Flow" do
|
|||
let(:lesson_booking_slot_recurring2) { FactoryGirl.build(:lesson_booking_slot_recurring) }
|
||||
let(:valid_single_slots) { [lesson_booking_slot_single1, lesson_booking_slot_single2] }
|
||||
let(:valid_recurring_slots) { [lesson_booking_slot_recurring1, lesson_booking_slot_recurring2] }
|
||||
let(:affiliate_partner) { FactoryGirl.create(:affiliate_partner) }
|
||||
let(:affiliate_partner2) { FactoryGirl.create(:affiliate_partner, lesson_rate: 0.30) }
|
||||
let(:school) {FactoryGirl.create(:school)}
|
||||
|
||||
|
||||
before {
|
||||
Timecop.return
|
||||
teacher.stripe_account_id = stripe_account1_id
|
||||
teacher.save!
|
||||
}
|
||||
after {
|
||||
Timecop.return
|
||||
}
|
||||
|
||||
it "works" do
|
||||
|
||||
|
|
@ -224,5 +230,9 @@ describe "TestDrive Lesson Flow" do
|
|||
teacher_payment.teacher_payment_charge.amount_in_cents.should eql 1000
|
||||
teacher_payment.teacher_payment_charge.fee_in_cents.should eql 0
|
||||
|
||||
user.sales.count.should eql 1
|
||||
sale = user.sales[0]
|
||||
sale.sale_line_items.count.should eql 1
|
||||
sale.sale_line_items[0].affiliate_distributions.count.should eql 0
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -291,7 +291,7 @@ describe LessonBooking do
|
|||
end
|
||||
|
||||
describe "billable_monthlies" do
|
||||
before do
|
||||
after do
|
||||
Timecop.return
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ describe LessonSession do
|
|||
let(:lesson_booking) {b = LessonBooking.book_normal(user, teacher, [slot1, slot2], "Hey I've heard of you before.", false, LessonBooking::PAYMENT_STYLE_SINGLE, 60); b.card_presumed_ok = true; b.save!; b}
|
||||
let(:lesson_session) {lesson_booking.lesson_sessions[0]}
|
||||
|
||||
after{Timecop.return}
|
||||
describe "accept" do
|
||||
it "can accept" do
|
||||
|
||||
|
|
@ -18,18 +19,20 @@ describe LessonSession do
|
|||
|
||||
describe "upcoming_sessions_reminder" do
|
||||
it "succeeds" do
|
||||
lesson = normal_lesson(user, teacher)
|
||||
UserMailer.deliveries.clear
|
||||
LessonSession.upcoming_sessions_reminder
|
||||
lesson_session.touch
|
||||
lesson_session.sent_starting_notice.should be_false
|
||||
lesson_session.is_requested?.should be_true
|
||||
lesson_session.music_session.scheduled_start = 15.minutes.from_now
|
||||
lesson_session.music_session.save!
|
||||
#UserMailer.deliveries.count.should eql 2
|
||||
lesson.touch
|
||||
lesson.sent_starting_notice.should be_false
|
||||
lesson.is_approved?.should be_true
|
||||
lesson.music_session.scheduled_start = 15.minutes.from_now
|
||||
lesson.music_session.save!
|
||||
LessonSession.upcoming_sessions_reminder
|
||||
UserMailer.deliveries.count.should eql 2
|
||||
UserMailer.deliveries.clear
|
||||
lesson_session.reload
|
||||
lesson_session.sent_starting_notice.should be_true
|
||||
lesson.reload
|
||||
lesson.sent_starting_notice.should be_true
|
||||
LessonSession.upcoming_sessions_reminder
|
||||
UserMailer.deliveries.count.should eql 0
|
||||
end
|
||||
|
|
|
|||
|
|
@ -527,7 +527,6 @@ describe MusicSession do
|
|||
dd = Time.now - (interval.to_i + 1).days
|
||||
Timecop.travel(dd)
|
||||
msess1 = FactoryGirl.create(:music_session, creator: creator, scheduled_start: dd)
|
||||
Timecop.return
|
||||
msess2 = FactoryGirl.create(:music_session, creator: creator)
|
||||
music_sessions, user_scores = sms(searcher, default_opts)
|
||||
expect(music_sessions.length).to be(1)
|
||||
|
|
@ -921,7 +920,6 @@ describe MusicSession do
|
|||
dd = Time.now - (interval.to_i + 1).days
|
||||
Timecop.travel(dd)
|
||||
msess1 = FactoryGirl.create(:music_session)
|
||||
Timecop.return
|
||||
msess2 = FactoryGirl.create(:music_session)
|
||||
purging = MusicSession.purgeable_sessions
|
||||
expect(purging.size).to be(1)
|
||||
|
|
@ -934,7 +932,6 @@ describe MusicSession do
|
|||
dd = Time.now - (interval.to_i + 1).days
|
||||
Timecop.travel(dd)
|
||||
msess1 = FactoryGirl.create(:music_session, scheduled_start: Time.now)
|
||||
Timecop.return
|
||||
msess2 = FactoryGirl.create(:music_session, scheduled_start: Time.now)
|
||||
purging = MusicSession.purgeable_sessions
|
||||
expect(purging.size).to be(1)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ describe MusicSessionUserHistory do
|
|||
let(:user_history1) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => music_session.creator) }
|
||||
let(:user_history2) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => some_user) }
|
||||
|
||||
after {
|
||||
Timecop.return
|
||||
}
|
||||
describe "create" do
|
||||
pending
|
||||
it {user_history1.music_session_id.should == music_session.id }
|
||||
|
|
@ -31,7 +34,6 @@ describe MusicSessionUserHistory do
|
|||
users = [user_history1, user_history2]
|
||||
Timecop.travel(Time.now + (MusicSessionUserHistory::MIN_SESSION_DURATION_RATING * 1.5).seconds)
|
||||
expect( user_history1.should_rate_session? ).to eq(true)
|
||||
Timecop.return
|
||||
end
|
||||
|
||||
it 'should rate fails' do
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ describe Sale do
|
|||
let(:jam_track3) { FactoryGirl.create(:jam_track) }
|
||||
let(:gift_card) { GiftCardType.jam_track_5 }
|
||||
|
||||
before(:each) {
|
||||
after(:each) {
|
||||
Timecop.return
|
||||
}
|
||||
def assert_free_line_item(sale_line_item, jamtrack)
|
||||
|
|
@ -698,8 +698,8 @@ describe Sale do
|
|||
partner1_distribution = affiliate_partner.affiliate_distributions.first
|
||||
partner2_distribution = affiliate_partner2.affiliate_distributions.first
|
||||
partner1_distribution.sale_line_item.should eql partner2_distribution.sale_line_item
|
||||
partner1_distribution.affiliate_referral_fee_in_cents.should eql (3000 * affiliate_partner.lesson_rate).round
|
||||
partner2_distribution.affiliate_referral_fee_in_cents.should eql (3000 * affiliate_partner2.lesson_rate).round
|
||||
partner1_distribution.affiliate_referral_fee_in_cents.should eql (3000 * 0.25 * affiliate_partner.lesson_rate).round
|
||||
partner2_distribution.affiliate_referral_fee_in_cents.should eql (3000 * 0.25 * affiliate_partner2.lesson_rate).round
|
||||
end
|
||||
|
||||
it "book recurring, monthly" do
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ describe TeacherPayment do
|
|||
end
|
||||
|
||||
it "charges school" do
|
||||
teacher.touch
|
||||
normal_distribution.school = school
|
||||
normal_distribution.ready = true
|
||||
normal_distribution.save!
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
module StripeMock
|
||||
class ErrorQueue
|
||||
def clear
|
||||
|
|
@ -12,13 +11,13 @@ module StripeMock
|
|||
end
|
||||
end
|
||||
|
||||
def testdrive_lesson(user, teacher, slots = nil)
|
||||
def testdrive_lesson(user, teacher, finish = false)
|
||||
|
||||
if slots.nil?
|
||||
slots = []
|
||||
slots << FactoryGirl.build(:lesson_booking_slot_single)
|
||||
slots << FactoryGirl.build(:lesson_booking_slot_single)
|
||||
end
|
||||
#if slots.nil?
|
||||
slots = []
|
||||
slots << FactoryGirl.build(:lesson_booking_slot_single)
|
||||
slots << FactoryGirl.build(:lesson_booking_slot_single)
|
||||
#end
|
||||
|
||||
if user.stored_credit_card == false
|
||||
user.stored_credit_card = true
|
||||
|
|
@ -27,7 +26,10 @@ def testdrive_lesson(user, teacher, slots = nil)
|
|||
|
||||
|
||||
booking = LessonBooking.book_test_drive(user, teacher, slots, "Hey I've heard of you before.")
|
||||
#puts "BOOKING #{booking.errors.inspect}"
|
||||
if booking.errors.any?
|
||||
puts "BOOKING #{booking.errors.inspect}"
|
||||
end
|
||||
|
||||
booking.errors.any?.should be_false
|
||||
lesson = booking.lesson_sessions[0]
|
||||
booking.card_presumed_ok.should be_true
|
||||
|
|
@ -42,21 +44,39 @@ def testdrive_lesson(user, teacher, slots = nil)
|
|||
lesson.slot.should eql slots[0]
|
||||
lesson.status.should eql LessonSession::STATUS_APPROVED
|
||||
|
||||
if finish
|
||||
# teacher & student get into session
|
||||
start = lesson.scheduled_start
|
||||
end_time = lesson.scheduled_start + (60 * lesson.duration)
|
||||
uh2 = FactoryGirl.create(:music_session_user_history, user: teacher_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
|
||||
end
|
||||
|
||||
lesson
|
||||
end
|
||||
|
||||
|
||||
def normal_lesson(user, teacher, slots = nil)
|
||||
def normal_lesson(user, teacher, finish = false)
|
||||
|
||||
if slots.nil?
|
||||
slots = []
|
||||
slots << FactoryGirl.build(:lesson_booking_slot_single)
|
||||
slots << FactoryGirl.build(:lesson_booking_slot_single)
|
||||
end
|
||||
#if slots.nil?
|
||||
slots = []
|
||||
slots << FactoryGirl.build(:lesson_booking_slot_single)
|
||||
slots << FactoryGirl.build(:lesson_booking_slot_single)
|
||||
#end
|
||||
|
||||
if user.stored_credit_card == false
|
||||
user.stored_credit_card = true
|
||||
user.save!
|
||||
token = create_stripe_token
|
||||
result = user.payment_update({token: token, zip: '78759', normal: true})
|
||||
#user.stored_credit_card = true
|
||||
#user.save!
|
||||
end
|
||||
|
||||
booking = LessonBooking.book_normal(user, teacher, slots, "Hey I've heard of you before.", false, LessonBooking::PAYMENT_STYLE_SINGLE, 60)
|
||||
|
|
@ -76,21 +96,34 @@ def normal_lesson(user, teacher, slots = nil)
|
|||
lesson.status.should eql LessonSession::STATUS_APPROVED
|
||||
lesson.music_session.should_not be_nil
|
||||
|
||||
if finish
|
||||
# teacher & student get into session
|
||||
start = lesson.scheduled_start
|
||||
end_time = lesson.scheduled_start + (60 * lesson.duration)
|
||||
uh2 = FactoryGirl.create(:music_session_user_history, user: teacher_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
|
||||
end
|
||||
|
||||
lesson
|
||||
end
|
||||
|
||||
|
||||
def monthly_lesson(user, teacher, slots = nil)
|
||||
def monthly_lesson(user, teacher, finish = true)
|
||||
|
||||
if slots.nil?
|
||||
slots = []
|
||||
slots << FactoryGirl.build(:lesson_booking_slot_recurring)
|
||||
slots << FactoryGirl.build(:lesson_booking_slot_recurring)
|
||||
end
|
||||
slots = []
|
||||
slots << FactoryGirl.build(:lesson_booking_slot_recurring)
|
||||
slots << FactoryGirl.build(:lesson_booking_slot_recurring)
|
||||
|
||||
if user.stored_credit_card == false
|
||||
user.stored_credit_card = true
|
||||
user.save!
|
||||
token = create_stripe_token
|
||||
result = user.payment_update({token: token, zip: '78759', normal: true})
|
||||
end
|
||||
|
||||
booking = LessonBooking.book_normal(user, teacher, slots, "Hey I've heard of you before.", true, LessonBooking::PAYMENT_STYLE_MONTHLY, 60)
|
||||
|
|
@ -110,5 +143,29 @@ def monthly_lesson(user, teacher, slots = nil)
|
|||
lesson.status.should eql LessonSession::STATUS_APPROVED
|
||||
lesson.music_session.should_not be_nil
|
||||
|
||||
if finish
|
||||
# teacher & student get into session
|
||||
start = lesson.scheduled_start
|
||||
end_time = lesson.scheduled_start + (60 * lesson.duration)
|
||||
uh2 = FactoryGirl.create(:music_session_user_history, user: teacher_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
|
||||
|
||||
today = Date.today
|
||||
if today.month == 12
|
||||
next_month = Date.new(today.year + 1, 1, 1)
|
||||
else
|
||||
next_month = Date.new(today.year, today.month + 1, 1)
|
||||
end
|
||||
|
||||
#Timecop.travel(next_month)
|
||||
LessonBooking.hourly_check
|
||||
end
|
||||
|
||||
lesson
|
||||
end
|
||||
|
|
@ -92,9 +92,14 @@
|
|||
|
||||
$('.homecard.jamclass').on('click', function() {
|
||||
|
||||
context.JK.Banner.showNotice("Coming Soon!", "JamClass is just around the corner.")
|
||||
if (gon.jamclass_enabled) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
context.JK.Banner.showNotice("Coming Soon!", "JamClass is just around the corner.")
|
||||
return false;
|
||||
|
||||
return false;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2480,6 +2480,16 @@
|
|||
});
|
||||
}
|
||||
|
||||
function createReview(options) {
|
||||
|
||||
return $.ajax({
|
||||
type: "POST",
|
||||
url: '/api/reviews',
|
||||
dataType: "json",
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(options),
|
||||
});
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
return self;
|
||||
|
|
@ -2703,6 +2713,7 @@
|
|||
this.deleteSchoolStudent = deleteSchoolStudent;
|
||||
this.listTeacherDistributions = listTeacherDistributions;
|
||||
this.lessonStartTime = lessonStartTime;
|
||||
this.createReview = createReview;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -96,7 +96,8 @@ UserStore = context.UserStore
|
|||
|
||||
userDetailDone: (response) ->
|
||||
if response.id == @state.teacherId
|
||||
@setState({teacher: response, isSelf: response.id == context.JK.currentUserId})
|
||||
school_on_school = response.teacher.school_id? && @state.user?.school_id? && response.teacher.school_id == @state.user.school_id
|
||||
@setState({teacher: response, isSelf: response.id == context.JK.currentUserId, school_on_school: school_on_school})
|
||||
else
|
||||
logger.debug("BookLesson: ignoring teacher details", response.id, @state.teacherId)
|
||||
|
||||
|
|
@ -226,7 +227,7 @@ UserStore = context.UserStore
|
|||
booked: (response) ->
|
||||
@setState({updating: false})
|
||||
UserActions.refresh()
|
||||
if response.user['has_stored_credit_card?']
|
||||
if response.user['has_stored_credit_card?'] || @state.school_on_school
|
||||
context.JK.Banner.showNotice("Lesson Requested","The teacher has been notified of your lesson request, and should respond soon.<br/><br/>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.id}"
|
||||
url = "/client#/jamclass"
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ UserStore = context.UserStore
|
|||
|
||||
acceptLessonBookingFail: (response ) ->
|
||||
@setState({updatingLesson: false})
|
||||
logger.debug("accept lesson booking failed", response)
|
||||
logger.debug("accept lesson booking failed " + response.responseText)
|
||||
@app.ajaxError(arguments[0], arguments[1], arguments[2])
|
||||
|
||||
cancelLessonBookingFail: (jqXHR) ->
|
||||
|
|
@ -699,12 +699,9 @@ UserStore = context.UserStore
|
|||
|
||||
renderTeacherRequested: () ->
|
||||
|
||||
console.log("renderTeacherRequested")
|
||||
if @isTestDrive()
|
||||
console.log("test drive")
|
||||
action = `<p className="action">Has requested a TestDrive {this.lessonLength()}-minute lesson, for which you will be paid $10.</p>`
|
||||
else
|
||||
console.log("normal")
|
||||
action = `<p className="action">Has requested a {this.lessonDesc()} lesson, for which you will be paid {this.lessonPaymentAmt()}.</p>`
|
||||
|
||||
`<div className="contents">
|
||||
|
|
|
|||
|
|
@ -159,6 +159,7 @@ UserStore = context.UserStore
|
|||
e.preventDefault()
|
||||
|
||||
if !window.Stripe?
|
||||
logger.error("no window.Stripe")
|
||||
@app.layout.notify({
|
||||
title: 'Payment System Not Loaded',
|
||||
text: "Please refresh this page and try to enter your info again. Sorry for the inconvenience!"
|
||||
|
|
@ -230,6 +231,7 @@ UserStore = context.UserStore
|
|||
|
||||
@setState({updating: true})
|
||||
|
||||
logger.debug("creating stripe token")
|
||||
window.Stripe.card.createToken(data, (status, response) => (@stripeResponseHandler(status, response)));
|
||||
|
||||
stripeResponseHandler: (status, response) ->
|
||||
|
|
@ -269,6 +271,7 @@ UserStore = context.UserStore
|
|||
data.name = @root.find('#set-user-on-card').val()
|
||||
|
||||
@setState({updating: true})
|
||||
logger.debug("submitting purchase info: " + JSON.stringify(data))
|
||||
rest.submitStripe(data).done((response) => @stripeSubmitted(response)).fail((jqXHR) => @stripeSubmitFailure(jqXHR))
|
||||
|
||||
stripeSubmitted: (response) ->
|
||||
|
|
@ -287,8 +290,6 @@ UserStore = context.UserStore
|
|||
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)
|
||||
|
|
@ -336,6 +337,7 @@ UserStore = context.UserStore
|
|||
window.location = "/client#/teachers/search"
|
||||
|
||||
stripeSubmitFailure: (jqXHR) ->
|
||||
logger.debug("stripe submission failure", jqXHR.responseText)
|
||||
@setState({updating: false})
|
||||
handled = false
|
||||
if jqXHR.status == 422
|
||||
|
|
|
|||
|
|
@ -0,0 +1,103 @@
|
|||
context = window
|
||||
|
||||
@RateUserDialog = React.createClass({
|
||||
|
||||
mixins: [Reflux.listenTo(@AppStore, "onAppInit")]
|
||||
teacher: false
|
||||
|
||||
parseId:(id) ->
|
||||
if !id?
|
||||
{id: null, type: null}
|
||||
else
|
||||
bits = id.split('_')
|
||||
if bits.length == 2
|
||||
{id: bits[1], type: bits[0]}
|
||||
else
|
||||
{id: null, type: null}
|
||||
|
||||
beforeShow: (args) ->
|
||||
logger.debug("RateUserDialog.beforeShow", args.d1)
|
||||
@firstName = ''
|
||||
@lastName = ''
|
||||
@email = ''
|
||||
|
||||
@setState({target: null})
|
||||
|
||||
rest.getUserDetail({id: args.d1}).done((response) => @userLookupDone(response)).fail((jqXHR) => @userLookupFail(jqXHR))
|
||||
afterHide: () ->
|
||||
|
||||
userLookupDone: (response) ->
|
||||
@setState({target: response})
|
||||
|
||||
userLookupFail: (jqXHR) ->
|
||||
@app.ajaxError(jqXHR, null, null)
|
||||
|
||||
onAppInit: (@app) ->
|
||||
dialogBindings = {
|
||||
'beforeShow': @beforeShow,
|
||||
'afterHide': @afterHide
|
||||
};
|
||||
|
||||
@app.bindDialog('rate-user', dialogBindings);
|
||||
|
||||
|
||||
componentDidMount: () ->
|
||||
@root = $(@getDOMNode())
|
||||
|
||||
getInitialState: () ->
|
||||
{inviteErrors: null}
|
||||
|
||||
doCancel: (e) ->
|
||||
e.preventDefault()
|
||||
@app.layout.closeDialog('rate-user', true);
|
||||
|
||||
doRating: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
rest.createReview({id: target})
|
||||
|
||||
createDone:(response) ->
|
||||
context.SchoolActions.addInvitation(@state.teacher, response)
|
||||
context.JK.Banner.showNotice("invitation sent", "Your invitation has been sent!")
|
||||
@app.layout.closeDialog('invite-school-user')
|
||||
|
||||
createFail: (jqXHR) ->
|
||||
|
||||
handled = false
|
||||
|
||||
if jqXHR.status == 422
|
||||
errors = JSON.parse(jqXHR.responseText)
|
||||
@setState({inviteErrors: errors})
|
||||
handled = true
|
||||
|
||||
if !handled
|
||||
@app.ajaxError(jqXHR, null, null)
|
||||
|
||||
render: () ->
|
||||
|
||||
if @state.user?.teacher?
|
||||
title = 'Rate Teacher'
|
||||
help = `<p>Please rate this teacher based on your experience with them.</p>`
|
||||
else
|
||||
title = 'Rate Student'
|
||||
help = `<p>Please rate this student based on your experience with them.</p>`
|
||||
|
||||
|
||||
`<div>
|
||||
<div className="content-head">
|
||||
<img className="content-icon" src="/assets/content/icon_add.png" height={19} width={19}/>
|
||||
|
||||
<h1>{title}</h1>
|
||||
</div>
|
||||
<div className="dialog-inner">
|
||||
|
||||
{help}
|
||||
|
||||
<div className="actions">
|
||||
<a onClick={this.doCancel} className="button-grey">CANCEL</a>
|
||||
<a onClick={this.doRating} className="button-orange">SUBMIT RATING</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
})
|
||||
|
|
@ -11,7 +11,7 @@ LocationActions = @LocationActions
|
|||
LIMIT: 20
|
||||
|
||||
getInitialState: () ->
|
||||
{options: {}}
|
||||
{options: {onlyMySchool: true}}
|
||||
|
||||
onAppInit: (@app) ->
|
||||
@app.bindScreen('jamclass/searchOptions', {beforeShow: @beforeShow, afterShow: @afterShow})
|
||||
|
|
@ -22,6 +22,7 @@ LocationActions = @LocationActions
|
|||
afterShow: (e) ->
|
||||
|
||||
onUserChanged: (@user) ->
|
||||
@setState(user: @user?.user)
|
||||
|
||||
onTeacherSearchChanged: (options) ->
|
||||
@setState({options: options})
|
||||
|
|
@ -59,12 +60,25 @@ LocationActions = @LocationActions
|
|||
handleYearsTeaching: (e) ->
|
||||
yearsTeaching = $(e.target).val()
|
||||
|
||||
logger.debug("years teaching:", yearsTeaching)
|
||||
options = @state.options
|
||||
options['years-teaching'] = yearsTeaching
|
||||
@setState({options: options})
|
||||
|
||||
onlyMySchoolChange: (e) ->
|
||||
$target = $(e.target)
|
||||
checked = $target.is(':checked')
|
||||
options = @state.options
|
||||
options.onlyMySchool = checked
|
||||
@setState(options)
|
||||
|
||||
render: () ->
|
||||
if @state.user?.school_id?
|
||||
onlySchoolOption =
|
||||
`<div className="search-criteria school-options">
|
||||
<h3>School Options</h3>
|
||||
<input type="checkbox" name="onlyMySchool" className="onlyMySchool" checked={this.state.options.onlyMySchool} onChange={this.onlyMySchoolChange}/><label htmlFor="onlyMySchool">Only Show Teachers<br/>In My School</label>
|
||||
</div>`
|
||||
|
||||
selectedAge = null
|
||||
yearsTeaching = []
|
||||
for yr in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 40, 45, 50]
|
||||
|
|
@ -129,6 +143,7 @@ LocationActions = @LocationActions
|
|||
<div className="search-criteria">
|
||||
<SelectLocation onItemChanged={this.handleLocationChange}/>
|
||||
</div>
|
||||
{onlySchoolOption}
|
||||
</div>
|
||||
<div className="actions">
|
||||
<a className="button-grey" onClick={this.onCancel}>CANCEL</a>
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ ProfileActions = @ProfileActions
|
|||
@needToSearch = false
|
||||
|
||||
afterHide: (e) ->
|
||||
@contentBodyScroller.off('scroll')
|
||||
|
||||
onTeacherSearchStore: (storeChanged) ->
|
||||
@needToSearch = true
|
||||
|
|
@ -97,16 +98,17 @@ ProfileActions = @ProfileActions
|
|||
))
|
||||
|
||||
|
||||
if @state.next == null
|
||||
@contentBodyScroller.off('scroll')
|
||||
if @state.currentPage == 1 and @state.results.length == 0
|
||||
@endOfList.text('No Teachers found matching your search').show()
|
||||
logger.debug("TeacherSearch: empty search")
|
||||
else if @state.currentPage > 0
|
||||
logger.debug("end of search")
|
||||
@endOfList.text('No more Teachers').show()
|
||||
else
|
||||
@registerInfiniteScroll(@contentBodyScroller)
|
||||
if @visible
|
||||
if @state.next == null
|
||||
@contentBodyScroller.off('scroll')
|
||||
if @state.currentPage == 1 and @state.results.length == 0
|
||||
@endOfList.text('No Teachers found matching your search').show()
|
||||
logger.debug("TeacherSearch: empty search")
|
||||
else if @state.currentPage > 0
|
||||
logger.debug("end of search")
|
||||
@endOfList.text('No more Teachers').show()
|
||||
else
|
||||
@registerInfiniteScroll(@contentBodyScroller)
|
||||
|
||||
moreAboutTeacher: (user, e) ->
|
||||
e.preventDefault()
|
||||
|
|
@ -176,6 +178,10 @@ ProfileActions = @ProfileActions
|
|||
searchOptions = TeacherSearchStore.getState()
|
||||
|
||||
summary = ''
|
||||
|
||||
if searchOptions.onlyMySchool
|
||||
summary += "my school teachers only"
|
||||
|
||||
instruments = searchOptions.instruments
|
||||
if instruments? && instruments.length > 0
|
||||
if instruments.length == 1
|
||||
|
|
@ -233,8 +239,12 @@ 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?']
|
||||
school_on_school = user.teacher.school_id? && @state.user?.school_id? && user.teacher.school_id == @state.user.school_id
|
||||
|
||||
bookSingleBtn = null
|
||||
bookTestDriveBtn = null
|
||||
|
||||
if !school_on_school && (!@state.user? || @state.user.remaining_test_drives > 0 || @state.user['can_buy_test_drive?'])
|
||||
bookTestDriveBtn = `<a className="button-orange try-test-drive" onClick={this.bookTestDrive.bind(this, user)}>BOOK TESTDRIVE LESSON</a>`
|
||||
else
|
||||
bookSingleBtn = `<a className="button-orange try-normal" onClick={this.bookNormalLesson.bind(this, user)}>BOOK LESSON</a>`
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ UserStore = context.UserStore
|
|||
|
||||
beforeHide: (e) ->
|
||||
|
||||
|
||||
afterShow: (e) ->
|
||||
logger.debug("TestDriveSelection: afterShow", e.id)
|
||||
|
||||
|
|
@ -60,7 +59,7 @@ UserStore = context.UserStore
|
|||
packageSelect: (packageType, e) ->
|
||||
e.preventDefault()
|
||||
|
||||
console.log("test-drive-#{packageType}")
|
||||
logger.debug("user selected test-drive-#{packageType}")
|
||||
rest.updateUser({desired_package: "test-drive-#{packageType}"}).done((response) => @packageSelectedDone(response)).fail((jqXHR) => @packageSelectedFail(jqXHR))
|
||||
|
||||
|
||||
|
|
@ -72,7 +71,6 @@ UserStore = context.UserStore
|
|||
|
||||
url = "/client#/jamclass/book-lesson/test-drive"
|
||||
|
||||
console.log("TEACHER", JSON.stringify(@state.teacher))
|
||||
if @state.teacher?
|
||||
url += '_' + @state.teacher.id
|
||||
else
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ TeacherSearchResultsActions = @TeacherSearchResultsActions
|
|||
query.years_teaching = searchOptions['years-teaching']
|
||||
query.country = searchOptions.location?.country
|
||||
query.region = searchOptions.location?.region
|
||||
query.onlyMySchool = searchOptions.onlyMySchool
|
||||
query
|
||||
|
||||
query
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ TeacherSearchActions = @TeacherSearchActions
|
|||
@TeacherSearchStore = Reflux.createStore(
|
||||
{
|
||||
listenables: TeacherSearchActions
|
||||
searchOptions: {}
|
||||
searchOptions: {onlyMySchool: true}
|
||||
viewingTeacher: null
|
||||
|
||||
init: ->
|
||||
|
|
|
|||
|
|
@ -86,6 +86,16 @@
|
|||
margin-top:10px;
|
||||
}
|
||||
}
|
||||
.school-options {
|
||||
label {
|
||||
display:inline-block;
|
||||
vertical-align:middle;
|
||||
}
|
||||
input {
|
||||
vertical-align: middle;
|
||||
margin-right:10px;
|
||||
}
|
||||
}
|
||||
|
||||
.years-teaching-header {
|
||||
margin-top:30px;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ class ApiReviewsController < ApiController
|
|||
# Create a review:
|
||||
def create
|
||||
@review = Review.create(params)
|
||||
respond_with_model(@review)
|
||||
end
|
||||
|
||||
# List reviews matching targets for given review summary:
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ module ClientHelper
|
|||
gon.session_stat_thresholds = Rails.application.config.session_stat_thresholds
|
||||
gon.midi_enabled = Rails.application.config.midi_enabled
|
||||
gon.chat_blast = Rails.application.config.chat_blast
|
||||
gon.jamclass_enabled = Rails.application.config.jamclass_enabled
|
||||
|
||||
# is this the native client or browser?
|
||||
@nativeClient = is_native_client?
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
object @review
|
||||
|
||||
extends "api_reviews/show"
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
object @review
|
||||
|
||||
attributes :id, :rating
|
||||
|
|
@ -35,7 +35,8 @@ attributes :id,
|
|||
:teaches_test_drive,
|
||||
:test_drives_per_week,
|
||||
:errors,
|
||||
:profile_pct
|
||||
:profile_pct,
|
||||
:school_id
|
||||
|
||||
|
||||
child :review_summary => :review_summary do
|
||||
|
|
@ -107,3 +108,9 @@ node :experiences_award do |teacher|
|
|||
}
|
||||
end # collect
|
||||
end
|
||||
|
||||
if current_user
|
||||
node :has_rated_teacher do |teacher|
|
||||
current_user.has_rated_teacher(teacher)
|
||||
end
|
||||
end
|
||||
|
|
@ -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?, :lesson_package_type_id
|
||||
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, :school_id
|
||||
|
||||
node :owned_school_id do |user|
|
||||
user.owned_school.id if user.owned_school
|
||||
|
|
@ -97,6 +97,9 @@ elsif current_user
|
|||
node :internet_score do |user|
|
||||
current_user.score_info(user)
|
||||
end
|
||||
node :has_rated_student do |user|
|
||||
current_user.has_rated_student(user)
|
||||
end
|
||||
end
|
||||
|
||||
child :friends => :friends do
|
||||
|
|
|
|||
|
|
@ -437,6 +437,6 @@ if defined?(Bundler)
|
|||
config.lesson_wait_time_window_minutes = 10
|
||||
config.end_of_wait_window_forgiveness_minutes = 1
|
||||
config.olark_enabled = true
|
||||
|
||||
config.jamclass_enabled = false
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@ describe "Single Lesson", :js => true, :type => :feature, :capybara_feature => t
|
|||
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)}
|
||||
let(:school) {FactoryGirl.create(:school)}
|
||||
|
||||
|
||||
before(:each) do
|
||||
LessonPackagePurchase.destroy_all
|
||||
LessonBooking.destroy_all
|
||||
Recording.delete_all
|
||||
Diagnostic.delete_all
|
||||
|
|
@ -19,12 +21,8 @@ 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
|
||||
|
|
@ -39,6 +37,14 @@ describe "Single Lesson", :js => true, :type => :feature, :capybara_feature => t
|
|||
end
|
||||
it "succeeds" do
|
||||
|
||||
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
|
||||
|
||||
visit "/client#/teachers/search"
|
||||
|
||||
Timecop.travel(Date.new(2016, 04, 01))
|
||||
|
|
@ -90,6 +96,7 @@ describe "Single Lesson", :js => true, :type => :feature, :capybara_feature => t
|
|||
|
||||
lesson_booking = LessonBooking.where(teacher_id: teacher_user).order(:created_at).last
|
||||
lesson_booking.should_not be_nil
|
||||
lesson_booking.same_school.should be_false
|
||||
lesson_session = LessonSession.where(teacher_id: teacher_user).order(:created_at).last
|
||||
lesson_session.teacher.should eql teacher_user
|
||||
|
||||
|
|
@ -198,7 +205,177 @@ describe "Single Lesson", :js => true, :type => :feature, :capybara_feature => t
|
|||
lesson_session2.reload
|
||||
lesson_session2.analysed.should be_true
|
||||
analysis = JSON.parse(lesson_session2.analysis)
|
||||
analysis["reason"].should eql LessonSessionAnalyser::NEITHER_SHOW
|
||||
analysis["reason"].should eql LessonSessionAnalyser::TEACHER_FAULT
|
||||
lesson_session2.billing_attempts.should eql 0
|
||||
lesson_session2.billed.should eql false
|
||||
lesson_session2.success.should be_false
|
||||
|
||||
lesson_session2.teacher_distribution.should be_nil
|
||||
end
|
||||
|
||||
|
||||
it "succeeds (school-on-school)" do
|
||||
|
||||
teacher_user.teacher.school = school
|
||||
teacher_user.teacher.save
|
||||
user.school = school
|
||||
user.save!
|
||||
|
||||
sign_in_poltergeist user
|
||||
|
||||
visit "/client#/teachers/search"
|
||||
|
||||
Timecop.travel(Date.new(2016, 04, 01))
|
||||
|
||||
find('.teacher-search-result[data-teacher-id="' + teacher_user.id + '"] .try-normal').trigger(:click)
|
||||
|
||||
# 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'
|
||||
|
||||
select('60 Minute Lesson for $30.00', :from => "booking-options-for-teacher")
|
||||
sleep 3
|
||||
|
||||
find('a.book-lesson-btn', text: 'BOOK LESSON').trigger(:click)
|
||||
|
||||
#find('h2', text: 'your lesson has been requested')
|
||||
|
||||
#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'
|
||||
|
||||
#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 1 # this single one
|
||||
lesson_booking = user.student_lesson_bookings.order(:created_at).last
|
||||
lesson_booking.is_requested?.should be_true
|
||||
lesson_booking.card_presumed_ok.should be_false
|
||||
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_booking.school.should eql school
|
||||
lesson_booking.same_school.should be_true
|
||||
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, teacher_id: teacher_user.id).order(:created_at).first
|
||||
lesson_package_purchase.should be_nil
|
||||
user.reload
|
||||
user.remaining_test_drives.should eql 0
|
||||
user.sales.count.should eql 0
|
||||
|
||||
# jamclass scren
|
||||
find('h2', text: 'my lessons')
|
||||
find('tr[data-lesson-session-id="' + lesson_session.id + '"] .displayStatusColumn', text: 'Requested')
|
||||
find('tr[data-lesson-session-id="' + lesson_session.id + '"] .first_name', text: teacher_user.first_name)
|
||||
|
||||
# open up hover
|
||||
find('tr[data-lesson-session-id="' + lesson_session.id + '"] .lesson-session-actions-btn').trigger(:click)
|
||||
|
||||
# check out the status
|
||||
find('li[data-lesson-option="status"] a', text: 'View Status').trigger(:click)
|
||||
|
||||
# and now go to the session status screen
|
||||
find('h2', text: 'your lesson has been requested')
|
||||
|
||||
# let's make a second request to a different teacher now
|
||||
|
||||
# let's make sure we can ask for another lesson too!
|
||||
teacher_user2.teacher.ready_for_session_at = Time.now
|
||||
teacher_user2.teacher.save!
|
||||
|
||||
visit "/client#/teachers/search"
|
||||
find('span.search-summary', text: 'my school teachers only')
|
||||
find('a.teacher-search-options').trigger(:click)
|
||||
find('input.onlyMySchool').trigger(:click) # uncheck
|
||||
find('a.search-btn').trigger(:click)
|
||||
find('span.search-summary', text: 'all teachers')
|
||||
find('.teacher-search-result[data-teacher-id="' + teacher_user2.id + '"] .try-test-drive').trigger(:click)
|
||||
|
||||
select_test_drive(4)
|
||||
|
||||
fill_out_single_lesson
|
||||
|
||||
fill_out_payment
|
||||
|
||||
sleep 5
|
||||
|
||||
find('h2', text: 'my lessons')
|
||||
# dismiss banner
|
||||
find('a.button-orange', text:'CLOSE').trigger(:click)
|
||||
|
||||
user.reload
|
||||
user.has_stored_credit_card?.should be_true
|
||||
lesson_session1 = lesson_session
|
||||
lesson_booking = LessonBooking.where(teacher_id: teacher_user2.id).first
|
||||
lesson_booking.should_not be_nil
|
||||
lesson_booking.card_presumed_ok.should be_true
|
||||
lesson_session = LessonSession.where(teacher_id: teacher_user2.id).first
|
||||
lesson_session.teacher.should eql teacher_user2
|
||||
lesson_session2 = lesson_session
|
||||
|
||||
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 3
|
||||
user.sales.count.should eql 1
|
||||
|
||||
# approve by teacher:
|
||||
teacher_approve(lesson_session1)
|
||||
|
||||
successful_lesson(lesson_session1)
|
||||
|
||||
LessonSession.hourly_check
|
||||
lesson_session1.reload
|
||||
lesson_session1.analysed.should be_true
|
||||
analysis = JSON.parse(lesson_session1.analysis)
|
||||
analysis["reason"].should eql LessonSessionAnalyser::SUCCESS
|
||||
lesson_session1.success.should be_true
|
||||
lesson_session1.billing_attempts.should eql nil
|
||||
lesson_session1.billed.should eql false
|
||||
|
||||
LessonBooking.hourly_check
|
||||
|
||||
lesson_session1.reload
|
||||
teacher_distribution = lesson_session1.teacher_distribution
|
||||
teacher_distribution.should be_nil
|
||||
|
||||
# check the second session, which no one went too
|
||||
|
||||
|
||||
lesson_session2.reload
|
||||
lesson_session2.analysed.should be_false
|
||||
|
||||
# approve by teacher:
|
||||
teacher_approve(lesson_session2)
|
||||
LessonSession.hourly_check
|
||||
LessonBooking.hourly_check
|
||||
|
||||
lesson_session2.reload
|
||||
lesson_session2.analysed.should be_true
|
||||
analysis = JSON.parse(lesson_session2.analysis)
|
||||
analysis["reason"].should eql LessonSessionAnalyser::TEACHER_FAULT
|
||||
lesson_session2.billing_attempts.should eql 0
|
||||
lesson_session2.billed.should eql false
|
||||
lesson_session2.success.should be_false
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ describe "Test Drive", :js => true, :type => :feature, :capybara_feature => true
|
|||
lesson_package_purchase = LessonPackagePurchase.where(user_id: user.id).first
|
||||
lesson_package_purchase.should_not be_nil
|
||||
lesson_package_purchase.lesson_package_type.is_test_drive?.should be_true
|
||||
lesson_package_purchase.lesson_payment_charge.should_not be_nil
|
||||
lesson_package_purchase.lesson_payment_charge.should be_nil
|
||||
user.reload
|
||||
user.remaining_test_drives.should eql 3
|
||||
#lesson_package_purchase.amount_charged.should eql 49.99
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ describe "School Landing", :js => true, :type => :feature, :capybara_feature =>
|
|||
user.is_a_teacher.should be false
|
||||
user.school_interest.should be true
|
||||
user.owned_school.should_not be_nil
|
||||
user.owned_school.affiliate_partner.should_not be_nil
|
||||
user.musician.should be true
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
require 'spec_helper'
|
||||
require 'spec_helper'
|
||||
|
||||
describe "Student Landing", :js => true, :type => :feature, :capybara_feature => true do
|
||||
|
||||
|
|
@ -52,6 +52,7 @@ describe "Student Landing", :js => true, :type => :feature, :capybara_feature =>
|
|||
student.musician.should be true
|
||||
student.teacher.should be_nil
|
||||
student.school.should eql school
|
||||
student.affiliate_referral.should eql school.affiliate_partner
|
||||
|
||||
find('#user-profile #username', text: student.name)
|
||||
|
||||
|
|
@ -87,6 +88,7 @@ describe "Student Landing", :js => true, :type => :feature, :capybara_feature =>
|
|||
student.musician.should be true
|
||||
student.teacher.should be_nil
|
||||
student.school.should eql school
|
||||
student.affiliate_referral.should eql school.affiliate_partner
|
||||
|
||||
school_invitation.reload
|
||||
school_invitation.accepted.should be_true
|
||||
|
|
@ -109,6 +111,7 @@ describe "Student Landing", :js => true, :type => :feature, :capybara_feature =>
|
|||
find('#user-profile #username', text: user.name)
|
||||
|
||||
user.reload
|
||||
user.affiliate_referral.should be_nil
|
||||
#user.is_a_student.should be true
|
||||
#user.is_a_teacher.should be false
|
||||
#user.musician.should be true
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ describe "Teacher Landing", :js => true, :type => :feature, :capybara_feature =>
|
|||
teacher.teacher.should_not be_nil
|
||||
teacher.school.should be_nil
|
||||
teacher.teacher.school.should eql school
|
||||
teacher.affiliate_referral.should eql school.affiliate_partner
|
||||
|
||||
find('#user-profile #username', text: teacher.name)
|
||||
UserMailer.deliveries.count.should eql 2
|
||||
|
|
@ -85,6 +86,7 @@ describe "Teacher Landing", :js => true, :type => :feature, :capybara_feature =>
|
|||
teacher.teacher.should_not be_nil
|
||||
teacher.school.should be_nil
|
||||
teacher.teacher.school.should eql school
|
||||
teacher.affiliate_referral.should eql school.affiliate_partner
|
||||
|
||||
school_invitation.reload
|
||||
school_invitation.accepted.should be_true
|
||||
|
|
@ -107,6 +109,7 @@ describe "Teacher Landing", :js => true, :type => :feature, :capybara_feature =>
|
|||
find('#user-profile #username', text: user.name)
|
||||
|
||||
user.reload
|
||||
user.affiliate_referral.should be_nil
|
||||
#user.is_a_student.should be true
|
||||
#user.is_a_teacher.should be false
|
||||
#user.musician.should be true
|
||||
|
|
|
|||
|
|
@ -63,6 +63,9 @@ def fill_out_payment
|
|||
fill_in 'zip', with: '78759'
|
||||
|
||||
find('.purchase-btn').trigger(:click)
|
||||
|
||||
# it needs to go 'disabled state' to indicate it's updating
|
||||
find('.purchase-btn.disabled')
|
||||
end
|
||||
|
||||
def select_test_drive(count = 4)
|
||||
|
|
|
|||
Loading…
Reference in New Issue