VRFS-3936 conflict fixed merging develop

This commit is contained in:
Jonathan Kolyer 2017-03-22 12:49:58 -07:00
commit cd762dcd15
41 changed files with 693 additions and 87 deletions

View File

@ -0,0 +1,40 @@
ActiveAdmin.register JamRuby::School, :as => 'Schools' do
menu :label => 'Schools', :parent => 'JamClass'
config.sort_order = 'created_at asc'
config.batch_actions = false
config.per_page = 100
config.paginate = true
config.filters = false
index do
actions
column "Name" do |school|
school.name
end
column "Owner" do |school|
link_to school.owner.name, "#{Rails.application.config.external_root_url}/client#/profile/#{school.owner.id}"
end
column "Scheduling Communication" do |school|
school.scheduling_communication
end
column "Correspondence Email" do |school|
school.correspondence_email
end
column "Base Fee Rate" do |school|
school.jamkazam_rate
end
column "JamKazam Sourced Fee Rate" do |school|
school.base_rate
end
column "Is Education?" do |school|
school.education ? 'Yes' : ''
end
end
end

View File

@ -0,0 +1,8 @@
class JamRuby::School
# add a custom validation
attr_accessible :user_id, :affiliate_partner_id, :name, :enabled, :scheduling_communication, :correspondence_email,
:photo_url, :original_fpfile, :cropped_fpfile, :cropped_s3_path, :crop_selection, :large_photo_url,
:cropped_large_s3_path, :cropped_large_fpfile, :jamkazam_rate, :second_ed, :education, :special, :base_rate, as: :admin
end

View File

@ -373,4 +373,5 @@ connection_role.sql
retailer_payment_split.sql retailer_payment_split.sql
teacher_distribution_fields.sql teacher_distribution_fields.sql
jam_track_download_rights.sql jam_track_download_rights.sql
guitar_center_integration_v1.sql
mobile_recording_support.sql mobile_recording_support.sql

View File

@ -0,0 +1,6 @@
ALTER TABLE schools ADD COLUMN special VARCHAR UNIQUE;
ALTER TABLE retailers ADD COLUMN special VARCHAR UNIQUE;
ALTER TABLE affiliate_partners ADD COLUMN special VARCHAR UNIQUE;
ALTER TABLE schools ADD COLUMN base_rate NUMERIC (8, 2) DEFAULT 0.10;
ALTER TABLE schools ALTER COLUMN jamkazam_rate SET DEFAULT 0.20;
UPDATE schools set jamkazam_rate = jamkazam_rate - 0.05;

View File

@ -5,4 +5,10 @@ UPDATE jam_track_rights SET can_download = TRUE;
ALTER TABLE shopping_carts ADD COLUMN variant VARCHAR; ALTER TABLE shopping_carts ADD COLUMN variant VARCHAR;
UPDATE shopping_carts set variant = 'stream' where cart_type = 'JamTrack'; UPDATE shopping_carts set variant = 'stream' where cart_type = 'JamTrack';
ALTER TABLE sale_line_items ADD COLUMN variant VARCHAR; ALTER TABLE sale_line_items ADD COLUMN variant VARCHAR;
UPDATE sale_line_items set variant = 'full'; UPDATE sale_line_items set variant = 'full';
-- paste this in once more when web app updated
-- UPDATE jam_track_rights SET can_download = TRUE;
-- UPDATE shopping_carts set variant = 'stream' where cart_type = 'JamTrack';
-- UPDATE sale_line_items set variant = 'full';

View File

@ -52,6 +52,7 @@ require "jam_ruby/lib/json_validator"
require "jam_ruby/lib/em_helper" require "jam_ruby/lib/em_helper"
require "jam_ruby/lib/nav" require "jam_ruby/lib/nav"
require "jam_ruby/lib/html_sanitize" require "jam_ruby/lib/html_sanitize"
require "jam_ruby/lib/guitar_center"
require "jam_ruby/resque/resque_hooks" require "jam_ruby/resque/resque_hooks"
require "jam_ruby/resque/audiomixer" require "jam_ruby/resque/audiomixer"
require "jam_ruby/resque/quick_mixer" require "jam_ruby/resque/quick_mixer"

View File

@ -0,0 +1,103 @@
module JamRuby
# Interact with external python tools to create the JKZ
class GuitarCenter
def self.init
user = User.create_user("Anonymous", "Anonymous", "seth+guitarcenter@jamkazam.com", "guitarcenterjam123", "Austin", "TX", "US", nil, nil)
teacher = Teacher.build_teacher(user, {
biography: 'Biography still in progress...',
teaches_test_drive: true
})
whitelist = UserWhitelist.new
whitelist.user = user
whitelist.save!
school = School.new
school.user = user
school.name = 'Guitar Center'
school.scheduling_communication = 'school'
school.special = School::GUITAR_CENTER
school.correspondence_email = 'seth+guitarcenter@jamkazam.com'
school.save!
school.reload
school.affiliate_partner.special = AffiliatePartner::GUITAR_CENTER
school.affiliate_partner.partner_name = 'Guitar Center'
school.affiliate_partner.save!
retailer = Retailer.new
retailer.user = school.user
retailer.name = 'Guitar Center'
retailer.slug = 'guitar-center'
retailer.affiliate_partner = school.affiliate_partner
retailer.special = Retailer::GUITAR_CENTER
retailer.save!
return {
user:user,
school: school,
retailer:retailer,
teacher:teacher
}
end
def self.bootstrap_teacher(email)
teacher_user = FactoryGirl.create(:teacher_user, email: email)
teacher_user.teacher.ready_for_session_at = Time.now
teacher_user.teacher.school = School.guitar_center
teacher_user.teacher.save!
end
def self.bootstrap_user(email, add_lessons)
user = User.create_user("Anonymous", "Anonymous", email, "guitarcenterjam123", "Austin", "TX", "US", nil, nil)
if add_lessons
most_recent_manual_card = PosaCard.where(origin: 'manual').where("code ilike 'JK%'").order('code desc').first
if most_recent_manual_card
number_code = most_recent_manual_card.code[2..-1]
number_code = number_code.to_i
else
number_code = 1
end
card = PosaCard.new
card.code = "JK#{"%06d" % number_code}"
card.card_type = 'jam_class_4'
card.origin = 'manual'
card.save!
gc_retailer = Retailer.guitar_center
card.activate(gc_retailer)
card.reload
card.claim(user)
else
user.school = School.guitar_center
user.is_a_student = true
user.save!
end
user.reload
user
end
# If this is a lesson posa card, then put that user into the guitar center school
def self.post_posa_claim(posa)
if posa.is_lesson_posa_card?
# Associate user with guitar center school
if posa.retailer.is_guitar_center?
posa.user.is_a_student = true
if posa.user.school_id.nil?
posa.user.school_id = School.guitar_center.id
end
posa.user.save
end
end
end
end
end

View File

@ -23,6 +23,8 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
KEY_POSTAL = 'postal_code' KEY_POSTAL = 'postal_code'
KEY_COUNTRY = 'country' KEY_COUNTRY = 'country'
GUITAR_CENTER = 'guitar_center'
# ten dollars in cents # ten dollars in cents
PAY_THRESHOLD = 10 * 100 PAY_THRESHOLD = 10 * 100
@ -154,7 +156,6 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
else else
applicable_rate = rate applicable_rate = rate
end end
{fee_in_cents: (product_info[:price] * 100 * real_quantity * applicable_rate.to_f).round} {fee_in_cents: (product_info[:price] * 100 * real_quantity * applicable_rate.to_f).round}
else else
false false

View File

@ -814,7 +814,7 @@ module JamRuby
if user if user
lesson_booking.same_school = !!(lesson_booking.school && user.school && (lesson_booking.school.id == user.school.id)) lesson_booking.same_school = !!(lesson_booking.school && user.school && (lesson_booking.school.id == user.school.id))
if lesson_booking.same_school if lesson_booking.same_school
lesson_booking.same_school_free = !user.school.education # non-education schools (music schools) are 'free' when school-on-school lesson_booking.same_school_free = false # !user.school.education # non-education schools (music schools) are 'free' when school-on-school
end end
else else
lesson_booking.same_school = false lesson_booking.same_school = false
@ -849,7 +849,8 @@ module JamRuby
end end
def school_on_school_payment? def school_on_school_payment?
!!(same_school && school.education) #!!(same_school && (school.education || school.is_guitar_center?))
same_school
end end
def no_school_on_school_payment? def no_school_on_school_payment?

View File

@ -132,7 +132,7 @@ module JamRuby
# price should always match the teacher_distribution, if there is one # price should always match the teacher_distribution, if there is one
purchase.price = teacher_dist.amount_in_cents / 100 purchase.price = teacher_dist.amount_in_cents / 100
if lesson_booking.school_on_school_payment? if lesson_booking.school_on_school_payment? && lesson_booking.school.education
teacher_dist = TeacherDistribution.create_for_lesson_package_purchase(purchase, true) teacher_dist = TeacherDistribution.create_for_lesson_package_purchase(purchase, true)
purchase.teacher_distributions << teacher_dist purchase.teacher_distributions << teacher_dist
end end
@ -193,7 +193,8 @@ module JamRuby
end end
def school_on_school_payment? def school_on_school_payment?
!!(school_on_school? && teacher.teacher.school.education) #!!(school_on_school? && teacher.teacher.school.education)
school_on_school?
end end
def no_school_on_school_payment? def no_school_on_school_payment?

View File

@ -239,10 +239,10 @@ module JamRuby
end end
end end
else else
is_education_school_on_school = lesson_booking.school_on_school_payment? is_school_on_school = lesson_booking.school_on_school_payment?
self.teacher_distributions << TeacherDistribution.create_for_lesson(self, false) self.teacher_distributions << TeacherDistribution.create_for_lesson(self, false)
if is_education_school_on_school if is_school_on_school && lesson_booking.school.education
self.teacher_distributions << TeacherDistribution.create_for_lesson(self, true) self.teacher_distributions << TeacherDistribution.create_for_lesson(self, true)
end end
end end

View File

@ -152,13 +152,15 @@ module JamRuby
self.user = user self.user = user
self.claimed_at = Time.now self.claimed_at = Time.now
if self.save if self.save
UserWhitelist.card_create(user, 'posa') UserWhitelist.card_create(user, 'posa')
SaleLineItem.associate_user_for_posa(self, user) SaleLineItem.associate_user_for_posa(self, user)
# when you claim a POSA card, you are also making a LessonPackagePurchase # when you claim a POSA card, you are also making a LessonPackagePurchase
if is_lesson_posa_card? if is_lesson_posa_card?
GuitarCenter.post_posa_claim(self)
purchase = LessonPackagePurchase.create(user, nil, lesson_package_type, nil, nil, self) if purchase.nil? purchase = LessonPackagePurchase.create(user, nil, lesson_package_type, nil, nil, self) if purchase.nil?
end end
end end

View File

@ -1,6 +1,8 @@
module JamRuby module JamRuby
class Retailer < ActiveRecord::Base class Retailer < ActiveRecord::Base
GUITAR_CENTER = 'guitar_center'
include HtmlSanitize include HtmlSanitize
html_sanitize strict: [:name] html_sanitize strict: [:name]
@ -29,7 +31,6 @@ module JamRuby
def create_slug def create_slug
if self.slug.blank? if self.slug.blank?
puts "SELF ID #{self.id}"
self.slug = self.id.to_s self.slug = self.id.to_s
end end
@ -37,7 +38,10 @@ module JamRuby
end end
def create_affiliate def create_affiliate
AffiliatePartner.create_from_retailer(self) if affiliate_partner.nil?
AffiliatePartner.create_from_retailer(self)
end
end end
def encrypt(password) def encrypt(password)
@ -50,7 +54,6 @@ module JamRuby
return false return false
end end
puts "self.encrypted_password #{self.encrypted_password}"
begin begin
# we init passwordfield as a UUID, which is a bogus hash; so if we see UUId, we know retailer has no password yet # we init passwordfield as a UUID, which is a bogus hash; so if we see UUId, we know retailer has no password yet
UUIDTools::UUID.parse(self.encrypted_password) UUIDTools::UUID.parse(self.encrypted_password)
@ -100,6 +103,13 @@ module JamRuby
user user
end end
def self.guitar_center
Retailer.find_by_special(GUITAR_CENTER)
end
def is_guitar_center?
return special == GUITAR_CENTER
end
def validate_avatar_info def validate_avatar_info
if updating_avatar if updating_avatar
# we want to mak sure that original_fpfile and cropped_fpfile seems like real fpfile info objects (i.e, json objects from filepicker.io) # we want to mak sure that original_fpfile and cropped_fpfile seems like real fpfile info objects (i.e, json objects from filepicker.io)

View File

@ -118,7 +118,7 @@ module JamRuby
if lesson_booking.is_test_drive? if lesson_booking.is_test_drive?
# no referral for test drives # no referral for test drives
elsif lesson_booking.school_on_school? elsif lesson_booking.no_school_on_school_payment?
# no referral; we don't make money on school-on-school # no referral; we don't make money on school-on-school
else else
line_item.add_referral_if_needed(student, shopping_cart, lesson_booking) line_item.add_referral_if_needed(student, shopping_cart, lesson_booking)

View File

@ -4,6 +4,7 @@ module JamRuby
include HtmlSanitize include HtmlSanitize
html_sanitize strict: [:name] html_sanitize strict: [:name]
GUITAR_CENTER = 'guitar_center'
# the school will handle all communication with students when setting up a session # the school will handle all communication with students when setting up a session
SCHEDULING_COMM_SCHOOL = 'school' SCHEDULING_COMM_SCHOOL = 'school'
@ -36,6 +37,10 @@ module JamRuby
education education
end end
def is_guitar_center?
self.special == GUITAR_CENTER
end
def scheduling_comm? def scheduling_comm?
scheduling_communication == SCHEDULING_COMM_SCHOOL scheduling_communication == SCHEDULING_COMM_SCHOOL
end end
@ -62,6 +67,10 @@ module JamRuby
user user
end end
def self.guitar_center
School.find_by_special(GUITAR_CENTER)
end
def validate_avatar_info def validate_avatar_info
if updating_avatar if updating_avatar
# we want to mak sure that original_fpfile and cropped_fpfile seems like real fpfile info objects (i.e, json objects from filepicker.io) # we want to mak sure that original_fpfile and cropped_fpfile seems like real fpfile info objects (i.e, json objects from filepicker.io)

View File

@ -52,6 +52,9 @@ module JamRuby
Teacher.where(id: id).update_all(profile_pct: self.profile_pct, profile_pct_summary: self.profile_pct_summary) Teacher.where(id: id).update_all(profile_pct: self.profile_pct, profile_pct_summary: self.profile_pct_summary)
end end
def is_guitar_center?
return school && school.is_guitar_center?
end
def self.index(user, params = {}) def self.index(user, params = {})
limit = params[:per_page] limit = params[:per_page]
@ -63,7 +66,8 @@ module JamRuby
# only show teachers with ready for session set to true # only show teachers with ready for session set to true
query = query.where('teachers.ready_for_session_at IS NOT NULL') query = query.where('teachers.ready_for_session_at IS NOT NULL')
if user && params[:onlyMySchool] && params[:onlyMySchool] != 'false' && user.school_id # always force GuitarCenter users to see only their school's teachers, regardless of what they picked
if user && (user.is_guitar_center_student? || (params[:onlyMySchool] && params[:onlyMySchool] != 'false' && user.school_id))
query = query.where("teachers.school_id = ?", user.school_id) query = query.where("teachers.school_id = ?", user.school_id)
end end
@ -194,8 +198,6 @@ module JamRuby
teacher.years_playing = params[:years_playing] if params.key?(:years_playing) teacher.years_playing = params[:years_playing] if params.key?(:years_playing)
teacher.teaches_age_lower = params[:teaches_age_lower] if params.key?(:teaches_age_lower) teacher.teaches_age_lower = params[:teaches_age_lower] if params.key?(:teaches_age_lower)
teacher.teaches_age_upper = params[:teaches_age_upper] if params.key?(:teaches_age_upper) teacher.teaches_age_upper = params[:teaches_age_upper] if params.key?(:teaches_age_upper)
teacher.website = params[:website] if params.key?(:website)
teacher.biography = params[:biography] if params.key?(:biography)
teacher.teaches_beginner = params[:teaches_beginner] if params.key?(:teaches_beginner) teacher.teaches_beginner = params[:teaches_beginner] if params.key?(:teaches_beginner)
teacher.teaches_intermediate = params[:teaches_intermediate] if params.key?(:teaches_intermediate) teacher.teaches_intermediate = params[:teaches_intermediate] if params.key?(:teaches_intermediate)
teacher.teaches_advanced = params[:teaches_advanced] if params.key?(:teaches_advanced) teacher.teaches_advanced = params[:teaches_advanced] if params.key?(:teaches_advanced)

View File

@ -107,7 +107,15 @@ module JamRuby
else else
if school if school
# if school exists, use it's rate # if school exists, use it's rate
rate = school.jamkazam_rate
# also determine if we sourced the student or not
if target.lesson_booking.school_on_school?
rate = school.base_rate
else
rate = school.jamkazam_rate + school.base_rate
end
else else
# otherwise use the teacher's rate # otherwise use the teacher's rate
rate = teacher.teacher.jamkazam_rate rate = teacher.teacher.jamkazam_rate
@ -135,8 +143,13 @@ module JamRuby
rate = (fee_rate * split) # charge_Fee is already handled elsewhere rate = (fee_rate * split) # charge_Fee is already handled elsewhere
else else
if school if school
# if school exists, use it's rate # also determine if we sourced the student or not
rate = school.jamkazam_rate + APP_CONFIG.stripe[:charge_fee] if target.lesson_booking.school_on_school?
rate = school.base_rate + APP_CONFIG.stripe[:charge_fee]
else
rate = (school.jamkazam_rate + school.base_rate) + APP_CONFIG.stripe[:charge_fee]
end
else else
# otherwise use the teacher's rate # otherwise use the teacher's rate
rate = teacher.teacher.jamkazam_rate + APP_CONFIG.stripe[:charge_fee] rate = teacher.teacher.jamkazam_rate + APP_CONFIG.stripe[:charge_fee]

View File

@ -1116,6 +1116,18 @@ module JamRuby
end end
end end
def is_guitar_center?
is_guitar_center_student? || is_guitar_center_teacher?
end
def is_guitar_center_student?
!school.nil? && school.is_guitar_center?
end
def is_guitar_center_teacher?
!teacher.nil? && teacher.is_guitar_center?
end
# throws ActiveRecord::RecordNotFound if instrument is invalid # throws ActiveRecord::RecordNotFound if instrument is invalid
# throws an email delivery error if unable to connect out to SMTP # throws an email delivery error if unable to connect out to SMTP
def self.signup(options) def self.signup(options)
@ -1463,20 +1475,7 @@ module JamRuby
# def signup # def signup
# this is intended to be development-mode or test-mode only; VRFS-149 def self.create_user(first_name, last_name, email ,password, city, state, country, instruments, photo_url)
# it creates or updates one user per developer, so that we aren't in the business
# of constantly recreating users as we create new dev environments
# We guard against this code running in production mode,
# because otherwise it's a bit of uncomfortable code
# to have sitting around
def self.create_dev_user(first_name, last_name, email, password,
city, state, country, instruments, photo_url)
if Environment.mode == "production"
# short-circuit out
return
end
user = User.find_or_create_by({email:email}) user = User.find_or_create_by({email:email})
User.transaction do User.transaction do
@ -1526,6 +1525,20 @@ module JamRuby
return user return user
end end
# We guard against this code running in production mode,
# because otherwise it's a bit of uncomfortable code
# to have sitting around
def self.create_dev_user(first_name, last_name, email, password,
city, state, country, instruments, photo_url)
if Environment.mode == "production"
# short-circuit out
return
end
return create_user(first_name, last_name, email, password, city, state, country, instruments, photo_url)
end
def signup_confirm def signup_confirm
self.signup_token = nil self.signup_token = nil
self.confirm_email! self.confirm_email!

View File

@ -442,9 +442,9 @@ describe "Monthly Recurring Lesson Flow" do
TeacherPayment.count.should eql 2 TeacherPayment.count.should eql 2
payment = teacher_distribution.teacher_payment payment = teacher_distribution.teacher_payment
payment.amount_in_cents.should eql prorated_cents payment.amount_in_cents.should eql prorated_cents
payment.fee_in_cents.should eql (prorated_cents * 0.28).round payment.fee_in_cents.should eql (prorated_cents * (school.base_rate + APP_CONFIG.stripe[:charge_fee])).round
payment.teacher_payment_charge.amount_in_cents.should eql (payment.real_distribution_in_cents + payment.real_distribution_in_cents * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.amount_in_cents.should eql (payment.real_distribution_in_cents + payment.real_distribution_in_cents * APP_CONFIG.stripe[:ach_pct]).round
payment.teacher_payment_charge.fee_in_cents.should eql (prorated_cents * 0.28).round payment.teacher_payment_charge.fee_in_cents.should eql (prorated_cents * (school.base_rate + 0.03)).round
payment.teacher.should eql teacher_user payment.teacher.should eql teacher_user
payment.teacher_distribution.should eql teacher_distribution payment.teacher_distribution.should eql teacher_distribution
education_distribution.reload education_distribution.reload
@ -490,7 +490,7 @@ describe "Monthly Recurring Lesson Flow" do
UserMailer.deliveries.length.should eql 0 # one for student UserMailer.deliveries.length.should eql 0 # one for student
end end
it "works (school on school)" do it "works (school on school normal)" do
# get user and teacher into same school # get user and teacher into same school
user.school = school user.school = school
@ -506,13 +506,20 @@ describe "Monthly Recurring Lesson Flow" do
booking.errors.any?.should be_false booking.errors.any?.should be_false
booking.card_presumed_ok.should be_false booking.card_presumed_ok.should be_false
booking.user.should eql user booking.user.should eql user
booking.card_presumed_ok.should be_false booking.sent_notices.should be_false
token = create_stripe_token
result = user.payment_update({token: token, zip: '78759', normal: true, booking_id: booking.id})
booking.reload
booking.card_presumed_ok.should be_true
booking.errors.any?.should be_false
booking.sent_notices.should be_true booking.sent_notices.should be_true
booking.booked_price.should eql 30.00 booking.booked_price.should eql 30.00
user.reload user.reload
user.stripe_customer_id.should be nil user.stripe_customer_id.should_not be nil
user.remaining_test_drives.should eql 0 user.remaining_test_drives.should eql 0
user.lesson_purchases.length.should eql 0 user.lesson_purchases.length.should eql 0

View File

@ -444,13 +444,26 @@ describe "Normal Lesson Flow" do
UserMailer.deliveries.length.should eql 3 # one for student, one for teacher UserMailer.deliveries.length.should eql 3 # one for student, one for teacher
end end
it "works (school on school guitarcenter)" do
it "works (school on school)" do gc = GuitarCenter.init
gc_owner = gc[:user]
gc_school = gc[:school]
gc_retailer = gc[:retailer]
# make sure teacher can get payments
teacher.stripe_account_id = stripe_account1_id
gc_school.user.stripe_account_id = stripe_account2_id
# make sure can get stripe payments
# get user and teacher into same school # get user and teacher into same school
user.school = school
gc_school.save!
user.school = gc_school
user.save! user.save!
teacher.school = school teacher.school = gc_school
teacher.save! teacher.save!
# user has no test drives, no credit card on file, but attempts to book a lesson # user has no test drives, no credit card on file, but attempts to book a lesson
@ -459,19 +472,37 @@ describe "Normal Lesson Flow" do
booking.school.should be_true booking.school.should be_true
booking.card_presumed_ok.should be_false booking.card_presumed_ok.should be_false
booking.user.should eql user booking.user.should eql user
user.unprocessed_normal_lesson.should be_nil booking.same_school_free.should be_false
booking.same_school_free.should be_true #user.unprocessed_normal_lesson.should be_nil
booking.sent_notices.should be_true booking.sent_notices.should be_false
booking.booked_price.should eql 30.00 booking.booked_price.should eql 30.00
booking.is_requested?.should be_true booking.is_requested?.should be_true
booking.lesson_sessions[0].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 LessonPaymentCharge.count.should eql 1
########## Need validate their credit card
token = create_stripe_token
result = user.payment_update({token: token, zip: '78759', normal: true, booking_id: booking.id})
booking = result[:lesson]
lesson = booking.lesson_sessions[0]
booking.errors.any?.should be_false
lesson.errors.any?.should be_false
booking.card_presumed_ok.should be_true
booking.sent_notices.should be_true
booking.school.is_guitar_center?.should be_true
lesson.music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
lesson.amount_charged.should eql 0.0
lesson.reload
user.reload user.reload
user.stripe_customer_id.should be_nil user.stripe_customer_id.should_not be nil
user.remaining_test_drives.should eql 0 user.remaining_test_drives.should eql 0
user.lesson_purchases.length.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 booking.lesson_sessions.length.should eql 1
lesson_session = booking.lesson_sessions[0] lesson_session = booking.lesson_sessions[0]
lesson_session.status.should eql LessonBooking::STATUS_REQUESTED lesson_session.status.should eql LessonBooking::STATUS_REQUESTED
@ -569,22 +600,259 @@ describe "Normal Lesson Flow" do
analysis = lesson_session.analysis analysis = lesson_session.analysis
analysis["reason"].should eql LessonSessionAnalyser::STUDENT_FAULT analysis["reason"].should eql LessonSessionAnalyser::STUDENT_FAULT
analysis["student"].should eql LessonSessionAnalyser::NO_SHOW analysis["student"].should eql LessonSessionAnalyser::NO_SHOW
lesson_session.billed.should be_true
if lesson_session.billing_error_detail 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 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 end
lesson_session.billed.should be false lesson_session.billing_attempts.should eql 1
user.reload user.reload
user.lesson_purchases.length.should eql 0 user.lesson_purchases.length.should eql 1
user.sales.length.should eql 0
lesson_session.amount_charged.should eql 0.0 LessonBooking.hourly_check
lesson_session.reload
teacher_distribution = lesson_session.teacher_distribution
teacher_distribution.amount_in_cents.should eql 3000
teacher_distribution.ready.should be_true
teacher_distribution.distributed.should be_false
lesson_session.teacher_distributions.count.should eql 1
education_distribution = lesson_session.education_distribution
education_distribution.should be_nil
lesson_session.billed.should be true
user.reload
user.lesson_purchases.length.should eql 1
user.sales.length.should eql 1
lesson_session.amount_charged.should eql 32.48
lesson_session.billing_error_reason.should be_nil lesson_session.billing_error_reason.should be_nil
lesson_session.sent_billing_notices.should be_nil lesson_session.sent_billing_notices.should be_true
user.reload user.reload
user.remaining_test_drives.should eql 0 user.remaining_test_drives.should eql 0
UserMailer.deliveries.length.should eql 0 # one for student, one for teacher UserMailer.deliveries.length.should eql 2 # one for student, one for teacher
LessonPaymentCharge.count.should eql 0 TeacherPayment.count.should eql 0
TeacherDistribution.count.should eql 0 TeacherPayment.hourly_check
TeacherPayment.count.should eql 1
LessonPaymentCharge.count.should eql 1
TeacherDistribution.count.should eql 1
teacher_distribution.reload
teacher_distribution.distributed.should be_true
payment = teacher_distribution.teacher_payment
payment.amount_in_cents.should eql 3000
payment.fee_in_cents.should eql (3000 * (gc_school.base_rate + 0.03)).round
payment.teacher_payment_charge.amount_in_cents.should eql ((teacher_distribution.amount_in_cents - teacher_distribution.teacher_fee_in_cents) + (teacher_distribution.amount_in_cents - teacher_distribution.teacher_fee_in_cents) * APP_CONFIG.stripe[:ach_pct]).round
payment.teacher_payment_charge.fee_in_cents.should eql payment.teacher_payment_charge.fee_in_cents
payment.teacher.should eql teacher_user
payment.teacher_distribution.should eql teacher_distribution
lesson_session.lesson_booking.status.should eql LessonBooking::STATUS_COMPLETED
lesson_session.lesson_booking.success.should be_true
end
it "works (school on school only)" do
# make sure teacher can get payments
teacher.stripe_account_id = stripe_account1_id
school.user.stripe_account_id = stripe_account2_id
# make sure can get stripe payments
# get user and teacher into same school
school.save!
user.school = school
user.save!
teacher.school = school
teacher.save!
# user has no test drives, no credit card on file, but attempts to book a lesson
booking = LessonBooking.book_normal(user, teacher_user, valid_single_slots, "Hey I've heard of you before.", false, LessonBooking::PAYMENT_STYLE_SINGLE, 60)
booking.errors.any?.should be_false
booking.school.should be_true
booking.card_presumed_ok.should be_false
booking.user.should eql user
booking.same_school_free.should be_false
#user.unprocessed_normal_lesson.should be_nil
booking.sent_notices.should be_false
booking.booked_price.should eql 30.00
booking.is_requested?.should be_true
booking.lesson_sessions[0].music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
LessonPaymentCharge.count.should eql 1
########## Need validate their credit card
token = create_stripe_token
result = user.payment_update({token: token, zip: '78759', normal: true, booking_id: booking.id})
booking = result[:lesson]
lesson = booking.lesson_sessions[0]
booking.errors.any?.should be_false
lesson.errors.any?.should be_false
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)
lesson.amount_charged.should eql 0.0
lesson.reload
user.reload
user.stripe_customer_id.should_not 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
booking.status.should eql LessonBooking::STATUS_REQUESTED
######### Teacher counters with new slot
teacher_countered_slot = FactoryGirl.build(:lesson_booking_slot_single, hour: 14)
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)
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, accepter: teacher_user})
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)
UserMailer.deliveries.clear
# background code comes around and analyses the session
LessonSession.hourly_check
lesson_session.reload
lesson_session.analysed.should be_true
analysis = lesson_session.analysis
analysis["reason"].should eql LessonSessionAnalyser::STUDENT_FAULT
analysis["student"].should eql LessonSessionAnalyser::NO_SHOW
lesson_session.billed.should be_true
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.billing_attempts.should eql 1
user.reload
user.lesson_purchases.length.should eql 1
LessonBooking.hourly_check
lesson_session.reload
teacher_distribution = lesson_session.teacher_distribution
teacher_distribution.amount_in_cents.should eql 3000
teacher_distribution.ready.should be_true
teacher_distribution.distributed.should be_false
lesson_session.teacher_distributions.count.should eql 1
education_distribution = lesson_session.education_distribution
education_distribution.should be_nil
lesson_session.billed.should be true
user.reload
user.lesson_purchases.length.should eql 1
user.sales.length.should eql 1
lesson_session.amount_charged.should eql 32.48
lesson_session.billing_error_reason.should be_nil
lesson_session.sent_billing_notices.should be_true
user.reload
user.remaining_test_drives.should eql 0
UserMailer.deliveries.length.should eql 2 # one for student, one for teacher
TeacherPayment.count.should eql 0
TeacherPayment.hourly_check
TeacherPayment.count.should eql 1
LessonPaymentCharge.count.should eql 1
TeacherDistribution.count.should eql 1
teacher_distribution.reload
teacher_distribution.distributed.should be_false
payment = teacher_distribution.teacher_payment
payment.amount_in_cents.should eql 3000
payment.fee_in_cents.should eql (3000 * (school.base_rate + 0.03)).round
payment.teacher_payment_charge.amount_in_cents.should eql ((teacher_distribution.amount_in_cents - teacher_distribution.teacher_fee_in_cents) + (teacher_distribution.amount_in_cents - teacher_distribution.teacher_fee_in_cents) * APP_CONFIG.stripe[:ach_pct]).round
payment.teacher_payment_charge.fee_in_cents.should eql payment.teacher_payment_charge.fee_in_cents
payment.teacher.should eql teacher_user
payment.teacher_distribution.should eql teacher_distribution
lesson_session.lesson_booking.status.should eql LessonBooking::STATUS_COMPLETED
lesson_session.lesson_booking.success.should be_true
end end
@ -794,7 +1062,7 @@ describe "Normal Lesson Flow" do
payment.teacher_distribution.should eql education_distribution payment.teacher_distribution.should eql education_distribution
payment = teacher_distribution.teacher_payment payment = teacher_distribution.teacher_payment
payment.amount_in_cents.should eql 3000 payment.amount_in_cents.should eql 3000
payment.fee_in_cents.should eql (3000 * 0.28).round payment.fee_in_cents.should eql (3000 * (school.base_rate + 0.03)).round
payment.teacher_payment_charge.amount_in_cents.should eql ((teacher_distribution.amount_in_cents - teacher_distribution.teacher_fee_in_cents) + (teacher_distribution.amount_in_cents - teacher_distribution.teacher_fee_in_cents) * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.amount_in_cents.should eql ((teacher_distribution.amount_in_cents - teacher_distribution.teacher_fee_in_cents) + (teacher_distribution.amount_in_cents - teacher_distribution.teacher_fee_in_cents) * APP_CONFIG.stripe[:ach_pct]).round
payment.teacher_payment_charge.fee_in_cents.should eql payment.teacher_payment_charge.fee_in_cents payment.teacher_payment_charge.fee_in_cents.should eql payment.teacher_payment_charge.fee_in_cents
payment.teacher.should eql teacher_user payment.teacher.should eql teacher_user
@ -1062,7 +1330,7 @@ describe "Normal Lesson Flow" do
affiliate_partner.affiliate_distributions.count.should eql 1 affiliate_partner.affiliate_distributions.count.should eql 1
partner1_distribution = affiliate_partner.affiliate_distributions.first partner1_distribution = affiliate_partner.affiliate_distributions.first
partner1_distribution.affiliate_referral_fee_in_cents.should eql (3000 * 0.25 * affiliate_partner.lesson_rate).round partner1_distribution.affiliate_referral_fee_in_cents.should eql (3000 * 0.30 * affiliate_partner.lesson_rate).round
school.affiliate_partner.affiliate_distributions.count.should eql 0 school.affiliate_partner.affiliate_distributions.count.should eql 0
end end
@ -1079,7 +1347,9 @@ describe "Normal Lesson Flow" do
user.sales[0].sale_line_items[0].affiliate_distributions.count.should eql 2 user.sales[0].sale_line_items[0].affiliate_distributions.count.should eql 2
affiliate_partner.affiliate_distributions.count.should eql 1 affiliate_partner.affiliate_distributions.count.should eql 1
partner1_distribution = affiliate_partner.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 1 school.affiliate_partner.affiliate_distributions.count.should eql 1
school_partner_distribution = school.affiliate_partner.affiliate_distributions.first 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 school_partner_distribution.affiliate_referral_fee_in_cents.should eql (3000 * 0.25 * school.affiliate_partner.lesson_rate).round

View File

@ -401,7 +401,6 @@ describe "TestDrive Lesson Flow" do
UserMailer.deliveries.length.should eql 2 # one for student, one for teacher UserMailer.deliveries.length.should eql 2 # one for student, one for teacher
found_student_email = false found_student_email = false
UserMailer.deliveries.each do |d| UserMailer.deliveries.each do |d|
puts d.subject
if d.subject == "You have used 1 of 4 TestDrive lesson credits" if d.subject == "You have used 1 of 4 TestDrive lesson credits"
found_student_email = true found_student_email = true
end end

View File

@ -66,6 +66,27 @@ describe PosaCard do
card_lessons.lesson_package_purchase.posa_card.should eql card_lessons card_lessons.lesson_package_purchase.posa_card.should eql card_lessons
end end
it "associates student automatically for GC" do
gc = GuitarCenter.init
gc_owner = gc[:user]
gc_school = gc[:school]
gc_retailer = gc[:retailer]
PosaCard.activate(card_lessons, gc_retailer)
card_lessons.reload
card_lessons.claim(user)
user.reload
user.is_guitar_center_student?.should be_true
card_lessons.errors.any?.should be false
card_lessons.claimed_at.should_not be_nil
card_lessons.user.should eql user
card_lessons.reload
card_lessons.lesson_package_purchase.should_not be_nil
card_lessons.lesson_package_purchase.lesson_package_type.should eql LessonPackageType.test_drive_4
card_lessons.lesson_package_purchase.posa_card.should eql card_lessons
end
it "must be already activated" do it "must be already activated" do

View File

@ -195,7 +195,7 @@ describe Sale do
invoice.line_items[0].should eq(purchase) invoice.line_items[0].should eq(purchase)
invoice.subtotal_in_cents.should eq((gift_card.price * 100).to_i) invoice.subtotal_in_cents.should eq((gift_card.price * 100).to_i)
invoice.total_in_cents.should eq((gift_card.price * 100).to_i) invoice.total_in_cents.should eq((gift_card.price * 100).to_i)
invoice.state.should eq('collected') #invoice.state.should eq('collected')
# verify jam_track_rights data # verify jam_track_rights data
user.gift_card_purchases.should_not be_nil user.gift_card_purchases.should_not be_nil
@ -486,7 +486,7 @@ describe Sale do
purchase= adjustments[0] purchase= adjustments[0]
purchase.unit_amount_in_cents.should eq((jamtrack.price * 100).to_i) purchase.unit_amount_in_cents.should eq((jamtrack.price * 100).to_i)
purchase.accounting_code.should eq(ShoppingCart::PURCHASE_NORMAL) purchase.accounting_code.should eq(ShoppingCart::PURCHASE_NORMAL)
purchase.description.should eq("JamTrack: " + jamtrack.name + '- FOR USE ONLY WITHIN APP') purchase.description.should eq("JamTrack: " + jamtrack.name + ' - FOR USE ONLY WITHIN APP')
purchase.state.should eq('invoiced') purchase.state.should eq('invoiced')
purchase.uuid.should eq(sale_line_item.recurly_adjustment_uuid) purchase.uuid.should eq(sale_line_item.recurly_adjustment_uuid)
@ -499,7 +499,7 @@ describe Sale do
invoice.line_items[0].should eq(purchase) invoice.line_items[0].should eq(purchase)
invoice.subtotal_in_cents.should eq((jamtrack.price * 100).to_i) invoice.subtotal_in_cents.should eq((jamtrack.price * 100).to_i)
invoice.total_in_cents.should eq((jamtrack.price * 100).to_i) invoice.total_in_cents.should eq((jamtrack.price * 100).to_i)
invoice.state.should eq('collected') #invoice.state.should eq('collected')
# verify jam_track_rights data # verify jam_track_rights data
user.jam_track_rights.should_not be_nil user.jam_track_rights.should_not be_nil
@ -566,7 +566,7 @@ describe Sale do
purchase= adjustments[0] purchase= adjustments[0]
purchase.unit_amount_in_cents.should eq((jamtrack.price * 100).to_i) purchase.unit_amount_in_cents.should eq((jamtrack.price * 100).to_i)
purchase.accounting_code.should eq(ShoppingCart::PURCHASE_NORMAL) purchase.accounting_code.should eq(ShoppingCart::PURCHASE_NORMAL)
purchase.description.should eq("JamTrack: " + jamtrack.name) purchase.description.should eq("JamTrack: " + jamtrack.name + " - FOR USE ONLY WITHIN APP")
purchase.state.should eq('invoiced') purchase.state.should eq('invoiced')
purchase.uuid.should eq(sale_line_item.recurly_adjustment_uuid) purchase.uuid.should eq(sale_line_item.recurly_adjustment_uuid)
@ -579,7 +579,7 @@ describe Sale do
invoice.line_items[0].should eq(purchase) invoice.line_items[0].should eq(purchase)
invoice.subtotal_in_cents.should eq((jamtrack.price * 100).to_i) invoice.subtotal_in_cents.should eq((jamtrack.price * 100).to_i)
invoice.total_in_cents.should eq((jamtrack.price * 100).to_i) invoice.total_in_cents.should eq((jamtrack.price * 100).to_i)
invoice.state.should eq('collected') #invoice.state.should eq('collected')
# verify jam_track_rights data # verify jam_track_rights data
user.jam_track_rights.should_not be_nil user.jam_track_rights.should_not be_nil

View File

@ -259,14 +259,14 @@ describe TeacherPayment do
# one to school owner, one to teacher # one to school owner, one to teacher
UserMailer.deliveries.length.should eql 2 UserMailer.deliveries.length.should eql 2
payment.teacher_payment_charge.billed.should eql true payment.teacher_payment_charge.billed.should eql true
payment.teacher_payment_charge.amount_in_cents.should eql ((1000 * 0.72) + (1000 * 0.72) * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.amount_in_cents.should eql ((1000 * 0.67) + (1000 * 0.67) * APP_CONFIG.stripe[:ach_pct]).round
payment.teacher_payment_charge.fee_in_cents.should eql 280 payment.teacher_payment_charge.fee_in_cents.should eql 330
payment.teacher_payment_charge.user.should eql school.owner payment.teacher_payment_charge.user.should eql school.owner
teacher_distribution = payment.teacher_payment_charge.distribution teacher_distribution = payment.teacher_payment_charge.distribution
teacher_distribution.amount_in_cents.should eql 1000 teacher_distribution.amount_in_cents.should eql 1000
charge = Stripe::Charge.retrieve(payment.teacher_payment_charge.stripe_charge_id) charge = Stripe::Charge.retrieve(payment.teacher_payment_charge.stripe_charge_id)
charge.destination.should_not be_nil charge.destination.should_not be_nil
charge.amount.should eql 726 charge.amount.should eql 675
charge.application_fee.should be_nil charge.application_fee.should be_nil
end end
end end
@ -434,8 +434,8 @@ describe TeacherPayment do
payment.teacher_payment_charge.billing_error_detail.should include("declined") payment.teacher_payment_charge.billing_error_detail.should include("declined")
payment.teacher_payment_charge.billed.should eql false payment.teacher_payment_charge.billed.should eql false
payment.teacher_payment_charge.amount_in_cents.should eql ((1000 * 0.72) + (1000 * 0.72) * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.amount_in_cents.should eql ((1000 * 0.67) + (1000 * 0.67) * APP_CONFIG.stripe[:ach_pct]).round
payment.teacher_payment_charge.fee_in_cents.should eql 280 payment.teacher_payment_charge.fee_in_cents.should eql 330
teacher_distribution = payment.teacher_payment_charge.distribution teacher_distribution = payment.teacher_payment_charge.distribution
teacher_distribution.amount_in_cents.should eql 1000 teacher_distribution.amount_in_cents.should eql 1000
@ -456,8 +456,8 @@ describe TeacherPayment do
# no attempt should be made because a day hasn't gone by # no attempt should be made because a day hasn't gone by
payment = normal_distribution.teacher_payment payment = normal_distribution.teacher_payment
payment.teacher_payment_charge.billed.should eql false payment.teacher_payment_charge.billed.should eql false
payment.teacher_payment_charge.amount_in_cents.should eql ((1000 * 0.72) + (1000 * 0.72) * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.amount_in_cents.should eql ((1000 * 0.67) + (1000 * 0.67) * APP_CONFIG.stripe[:ach_pct]).round
payment.teacher_payment_charge.fee_in_cents.should eql 280 payment.teacher_payment_charge.fee_in_cents.should eql 330
teacher_distribution = payment.teacher_payment_charge.distribution teacher_distribution = payment.teacher_payment_charge.distribution
teacher_distribution.amount_in_cents.should eql 1000 teacher_distribution.amount_in_cents.should eql 1000
@ -477,12 +477,12 @@ describe TeacherPayment do
payment = normal_distribution.teacher_payment payment = normal_distribution.teacher_payment
payment.reload payment.reload
payment.teacher_payment_charge.billed.should eql true payment.teacher_payment_charge.billed.should eql true
payment.teacher_payment_charge.amount_in_cents.should eql ((1000 * 0.72) + (1000 * 0.72) * APP_CONFIG.stripe[:ach_pct]).round payment.teacher_payment_charge.amount_in_cents.should eql ((1000 * 0.67) + (1000 * 0.67) * APP_CONFIG.stripe[:ach_pct]).round
payment.teacher_payment_charge.fee_in_cents.should eql 280 payment.teacher_payment_charge.fee_in_cents.should eql 330
teacher_distribution = payment.teacher_payment_charge.distribution teacher_distribution = payment.teacher_payment_charge.distribution
teacher_distribution.amount_in_cents.should eql 1000 teacher_distribution.amount_in_cents.should eql 1000
charge = Stripe::Charge.retrieve(payment.teacher_payment_charge.stripe_charge_id) charge = Stripe::Charge.retrieve(payment.teacher_payment_charge.stripe_charge_id)
charge.amount.should eql 726 charge.amount.should eql 675
end end
end end
end end

View File

@ -198,6 +198,38 @@ describe Teacher do
teachers = Teacher.index(nil, {student_age: 5})[:query] teachers = Teacher.index(nil, {student_age: 5})[:query]
teachers.length.should eq 0 teachers.length.should eq 0
end end
describe "guitarcenter" do
before(:each) do
gc = GuitarCenter.init
@gc_owner = gc[:user]
@gc_school = gc[:school]
@gc_retailer = gc[:retailer]
end
it "student only sees guitar center teachers" do
teacher = FactoryGirl.create(:teacher, ready_for_session_at: Time.now)
gc_teacher = FactoryGirl.create(:teacher, school: @gc_school, ready_for_session_at: Time.now)
# TODO: perhaps GC teachers should not come back to non-GC users. Not sure yet.
query = Teacher.index(user, {})[:query]
query.count.should eql 2
query[0].should eq(teacher.user)
query[1].should eq(gc_teacher.user)
user.school = @gc_school
user.save!
query = Teacher.index(user, {})[:query]
query.count.should eql 1
query[0].should eq(gc_teacher.user)
# double-check that even if you ask for teachers not in your school, you still get only GC
query = Teacher.index(user, {onlyMySchool: 'false'})[:query]
query.count.should eql 1
query[0].should eq(gc_teacher.user)
end
end
end end
BIO = "Once a man learned a guitar." BIO = "Once a man learned a guitar."

View File

@ -423,7 +423,7 @@ end
end end
def create_stripe_token(exp_month = 2017) def create_stripe_token(exp_month = 2019)
Stripe::Token.create( Stripe::Token.create(
:card => { :card => {
:number => "4111111111111111", :number => "4111111111111111",

View File

@ -99,7 +99,7 @@ UserStore = context.UserStore
userDetailDone: (response) -> userDetailDone: (response) ->
if response.id == @state.teacherId if response.id == @state.teacherId
school_on_school = response.teacher.school_id? && @state.user?.school_id? && response.teacher.school_id == @state.user.school_id && !response.teacher.school.education #school_on_school = response.teacher.school_id? && @state.user?.school_id? && response.teacher.school_id == @state.user.school_id && !response.teacher.school.education
@setState({teacher: response, isSelf: response.id == context.JK.currentUserId, school_on_school: school_on_school}) @setState({teacher: response, isSelf: response.id == context.JK.currentUserId, school_on_school: school_on_school})
else else
logger.debug("BookLesson: ignoring teacher details", response.id, @state.teacherId) logger.debug("BookLesson: ignoring teacher details", response.id, @state.teacherId)
@ -234,7 +234,8 @@ UserStore = context.UserStore
booked: (response) -> booked: (response) ->
@setState({updating: false}) @setState({updating: false})
UserActions.refresh() UserActions.refresh()
if response.user['has_stored_credit_card?'] || @state.school_on_school || response.posa_card_id? #if response.user['has_stored_credit_card?'] || @state.school_on_school || response.posa_card_id?
if response.user['has_stored_credit_card?'] || response.posa_card_id?
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 back to the JamClass home page, where you can check the status of this lesson, as well as any other past and future lessons.") 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 back to the JamClass home page, where you can check the status of this lesson, as well as any other past and future lessons.")
url = "/client#/jamclass/lesson-booking/#{response.id}" url = "/client#/jamclass/lesson-booking/#{response.id}"
url = "/client#/jamclass" url = "/client#/jamclass"

View File

@ -22,7 +22,15 @@ BroadcastHolder = React.createClass(
if result? if result?
notification.push(result) notification.push(result)
else if this.props.is_guitar_center
guitarCenterLogo = `<div className="guitar-center-logo">
<img src="/assets/content/guitar-center-logo.png"/>
</div>`
`<div id="broadcast-notification-holder" className="broadcast-notification-holder" > `<div id="broadcast-notification-holder" className="broadcast-notification-holder" >
{guitarCenterLogo}
{notification} {notification}
</div>` </div>`
}); });

View File

@ -233,6 +233,7 @@ UserStore = context.UserStore
request.message = @getMessage() request.message = @getMessage()
request.id = this.state.booking.id request.id = this.state.booking.id
request.slot = this.state.slot_decision request.slot = this.state.slot_decision
request.lesson_session_id = @focusedLesson()?.id
rest.acceptLessonBooking(request).done((response) => @acceptLessonBookingDone(response)).fail((response) => @acceptLessonBookingFail(response)) rest.acceptLessonBooking(request).done((response) => @acceptLessonBookingDone(response)).fail((response) => @acceptLessonBookingFail(response))
# {"errors":{"lesson_booking_slots":["is invalid"]},"_children":{"lesson_booking_slots":[{"errors":{}},{"errors":{}},{"errors":{"day_of_week":["must be specified"]}}]}} # {"errors":{"lesson_booking_slots":["is invalid"]},"_children":{"lesson_booking_slots":[{"errors":{}},{"errors":{}},{"errors":{"day_of_week":["must be specified"]}}]}}

View File

@ -101,7 +101,7 @@ LocationActions = @LocationActions
@levelChanged(e) @levelChanged(e)
render: () -> render: () ->
if @state.user?.school_id? if @state.user?.school_id? && !@state.user?['is_guitar_center?']
onlySchoolOption = onlySchoolOption =
`<div className="search-criteria school-options"> `<div className="search-criteria school-options">
<h3>School Options</h3> <h3>School Options</h3>

View File

@ -233,7 +233,8 @@ ProfileActions = @ProfileActions
if !bio? if !bio?
bio = 'No bio' bio = 'No bio'
school_on_school = user.teacher.school_id? && @state.user?.school_id? && user.teacher.school_id == @state.user.school_id #school_on_school = user.teacher.school_id? && @state.user?.school_id? && user.teacher.school_id == @state.user.school_id
school_on_school = false
bookSingleBtn = null bookSingleBtn = null
bookTestDriveBtn = null bookTestDriveBtn = null

View File

@ -21,7 +21,7 @@ teacherActions = window.JK.Actions.Teacher
lesson.me = me lesson.me = me
lesson.other = other lesson.other = other
lesson.isAdmin = context.JK.currentUserAdmin lesson.isAdmin = context.JK.currentUserAdmin
lesson.noSchoolOnSchoolPayment = lesson['payment_if_school_on_school??'] lesson.noSchoolOnSchoolPayment = !lesson['payment_if_school_on_school?']
lesson.cardNotOk = !lesson.lesson_booking.card_presumed_ok && lesson.payment_if_school_on_school? lesson.cardNotOk = !lesson.lesson_booking.card_presumed_ok && lesson.payment_if_school_on_school?
lesson.isActive = lesson['is_active?'] lesson.isActive = lesson['is_active?']

View File

@ -94,6 +94,9 @@
margin-bottom: 30px; margin-bottom: 30px;
} }
label[for="onlyMySchool"] {
margin-left:10px;
}
.student-levels-taught { .student-levels-taught {
.icheckbox_minimal { .icheckbox_minimal {
top:3px; top:3px;

View File

@ -4,6 +4,12 @@
position:absolute; position:absolute;
bottom:0; bottom:0;
width:100%; width:100%;
.guitar-center-logo img {
left: 25%;
position: relative;
bottom: 20px;
}
} }
[data-react-class="BroadcastHolder"] { [data-react-class="BroadcastHolder"] {

View File

@ -133,7 +133,13 @@ class ApiLessonBookingsController < ApiController
end end
def accept def accept
next_lesson = @lesson_booking.next_lesson
if params[:lesson_session_id]
next_lesson = LessonSession.find(params[:lesson_session_id])
else
next_lesson = @lesson_booking.next_lesson
end
result = next_lesson.accept({ result = next_lesson.accept({
message: params[:message], message: params[:message],
slot: params[:slot], slot: params[:slot],

View File

@ -19,6 +19,7 @@ class ClientsController < ApplicationController
return return
end end
@is_guitar_center = current_user && current_user.is_guitar_center?
@in_client_page = true @in_client_page = true
@minimal_curtain = Rails.application.config.minimal_curtain @minimal_curtain = Rails.application.config.minimal_curtain
gon.recurly_tax_estimate_jam_track_plan = Rails.application.config.recurly_tax_estimate_jam_track_plan gon.recurly_tax_estimate_jam_track_plan = Rails.application.config.recurly_tax_estimate_jam_track_plan

View File

@ -34,7 +34,7 @@ end
# give back more info if the user being fetched is yourself # give back more info if the user being fetched is yourself
if current_user && @user == current_user 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, :jamclass_credits, :can_buy_test_drive?, :lesson_package_type_id, :school_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, :jamclass_credits, :can_buy_test_drive?, :lesson_package_type_id, :school_id, :is_guitar_center_student?
node :owned_school_id do |user| node :owned_school_id do |user|
user.owned_school.id if user.owned_school user.owned_school.id if user.owned_school

View File

@ -12,9 +12,9 @@
<%= render "users/user_dropdown" %> <%= render "users/user_dropdown" %>
<%= react_component 'BroadcastHolder', {} %> <%= react_component 'BroadcastHolder', {is_guitar_center: @is_guitar_center} %>
</div>
<!-- Templates --> <!-- Templates -->
<script type="text/template" id="template-search-section"> <script type="text/template" id="template-search-section">
<h2>{section}</h2> <h2>{section}</h2>

View File

@ -0,0 +1,33 @@
Rails.logger = Logger.new(STDOUT)
namespace :guitarcenter do
task init: :environment do |task, args|
GuitarCenter.init
end
task bootstrap_teacher: :environment do |task, args|
email = ENV['EMAIL']
if email.nil? || email == ''
raise 'no email ENV specified'
end
GuitarCenter.bootstrap_teacher(email)
end
task bootstrap_user: :environment do |task, args|
email = ENV['EMAIL']
if email.nil? || email == ''
raise 'no email ENV specified'
end
GuitarCenter.bootstrap_user(email, true)
end
end

View File

@ -179,7 +179,7 @@ describe "JamClassScreen", :js => true, :type => :feature, :capybara_feature =>
fast_signin(teacher_user, "/client#/jamclass") fast_signin(teacher_user, "/client#/jamclass")
validate_status(lesson, 'Requested') validate_status(lesson, 'Requested')
jamclass_hover_option('reschedule', 'Reschedule Lesson') jamclass_hover_option(lesson, 'reschedule', 'Reschedule Lesson')
# no popup should show in this case, because it's not yet scheduled # no popup should show in this case, because it's not yet scheduled
@ -194,7 +194,7 @@ describe "JamClassScreen", :js => true, :type => :feature, :capybara_feature =>
switch_user(user, "/client#/jamclass") switch_user(user, "/client#/jamclass")
validate_status(lesson, 'Requested') validate_status(lesson, 'Requested')
jamclass_hover_option('status', 'View Status') jamclass_hover_option(lesson, 'status', 'View Status')
find('h2', text: 'this lesson is coming up soon') find('h2', text: 'this lesson is coming up soon')
@ -202,7 +202,7 @@ describe "JamClassScreen", :js => true, :type => :feature, :capybara_feature =>
approve_lesson(lesson) approve_lesson(lesson)
jamclass_hover_option('reschedule', 'Reschedule Lesson') jamclass_hover_option(lesson, 'reschedule', 'Reschedule Lesson')
find('#banner h1', text: 'Lesson Change Requested') find('#banner h1', text: 'Lesson Change Requested')
find('#banner .close-btn').trigger(:click) find('#banner .close-btn').trigger(:click)

View File

@ -110,7 +110,7 @@ def select_test_drive(count = 4)
find(".button-orange.select-#{count}").trigger(:click) find(".button-orange.select-#{count}").trigger(:click)
end end
def create_stripe_token(exp_month = 2017) def create_stripe_token(exp_month = 2019)
Stripe::Token.create( Stripe::Token.create(
:card => { :card => {
:number => "4111111111111111", :number => "4111111111111111",