lots of progress on amazon-readiness
This commit is contained in:
parent
cd9525ac2b
commit
7ff7327ef8
|
|
@ -59,7 +59,7 @@ gem 'resque'
|
|||
gem 'resque-retry'
|
||||
gem 'resque-failed-job-mailer'
|
||||
gem 'resque-lonely_job', '~> 1.0.0'
|
||||
gem 'eventmachine', '1.0.4'
|
||||
gem 'eventmachine', '1.2.3'
|
||||
gem 'amqp', '0.9.8'
|
||||
#gem 'logging-rails', :require => 'logging/rails'
|
||||
gem 'pg_migrate'
|
||||
|
|
@ -82,9 +82,9 @@ gem 'stripe'
|
|||
gem 'zip-codes'
|
||||
gem 'email_validator'
|
||||
|
||||
group :libv8 do
|
||||
gem 'libv8', "~> 4.5.95"
|
||||
end
|
||||
#group :libv8 do
|
||||
# gem 'libv8', "~> 4.5.95"
|
||||
#end
|
||||
|
||||
|
||||
# To use Jbuilder templates for JSON
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
ActiveAdmin.register JamRuby::User, :as => 'InactiveJamClassUsers' do
|
||||
|
||||
menu :label => 'Inactive JamClass Users w/o Credits', :parent => 'JamClass'
|
||||
|
||||
config.sort_order = 'created_at'
|
||||
config.batch_actions = false
|
||||
config.per_page = 100
|
||||
config.paginate = true
|
||||
config.filters = false
|
||||
|
||||
scope("All", default: true) { |scope| scope.includes(:taken_lessons => :music_session).select("distinct(users.id), users.email, users.first_name, users.last_name").joins("inner join posa_cards on posa_cards.user_id = users.id inner join lesson_sessions on lesson_sessions.user_id = users.id left outer join music_sessions on music_sessions.lesson_session_id = music_sessions.id ").where("jamclass_credits = 0") }
|
||||
|
||||
index do
|
||||
column "Name" do |user|
|
||||
span do
|
||||
link_to "#{user.name} (#{user.email})", "#{Rails.application.config.external_root_url}/client#/profile/#{user.id}"
|
||||
end
|
||||
end
|
||||
column "POSA" do |user|
|
||||
span do
|
||||
posa = user.posa_cards[0]
|
||||
if posa.lesson_package_type
|
||||
posa.lesson_package_type.id
|
||||
else
|
||||
posa.card_type
|
||||
end
|
||||
end
|
||||
end
|
||||
column "Last Session" do |user|
|
||||
span do
|
||||
if user.taken_lessons.length == 0
|
||||
"none yet"
|
||||
else
|
||||
most_recent_lesson = user.taken_lessons.order('created_at desc')[0]
|
||||
link_to most_recent_lesson.scheduled_start, admin_lesson_session_path(most_recent_lesson)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
ActiveAdmin.register JamRuby::User, :as => 'InactiveJamClassPOSAUsers' do
|
||||
|
||||
menu :label => 'Inactive JamClass Users w/ Credits', :parent => 'JamClass'
|
||||
|
||||
config.sort_order = 'created_at'
|
||||
config.batch_actions = false
|
||||
config.per_page = 100
|
||||
config.paginate = true
|
||||
config.filters = false
|
||||
|
||||
scope("All", default: true) { |scope| scope.includes(:taken_lessons => :music_session).select("distinct(users.id), users.email, users.first_name, users.last_name, users.jamclass_credits").joins("inner join posa_cards on posa_cards.user_id = users.id left outer join lesson_sessions on lesson_sessions.user_id = users.id left outer join music_sessions on music_sessions.lesson_session_id = music_sessions.id ").where("jamclass_credits > 0 AND music_sessions.id IS NULL OR music_sessions.scheduled_start < ?", Time.now - 7.days) }
|
||||
|
||||
index do
|
||||
column "Name" do |user|
|
||||
span do
|
||||
link_to "#{user.name} (#{user.email})", "#{Rails.application.config.external_root_url}/client#/profile/#{user.id}"
|
||||
end
|
||||
end
|
||||
column "POSA" do |user|
|
||||
span do
|
||||
posa = user.posa_cards[0]
|
||||
if posa.lesson_package_type
|
||||
posa.lesson_package_type.id
|
||||
else
|
||||
posa.card_type
|
||||
end
|
||||
end
|
||||
end
|
||||
column "Credits" do |user|
|
||||
span do
|
||||
user.jamclass_credits
|
||||
end
|
||||
end
|
||||
column "Last Session" do |user|
|
||||
span do
|
||||
if user.taken_lessons.length == 0
|
||||
"none yet"
|
||||
else
|
||||
most_recent_lesson = user.taken_lessons.order('created_at desc')[0]
|
||||
link_to most_recent_lesson.scheduled_start, admin_lesson_session_path(most_recent_lesson)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -17,10 +17,16 @@ ActiveAdmin.register JamRuby::LessonSession, :as => 'LessonSessions' do
|
|||
scope("Completed") { |scope| scope.unscoped.completed.order('created_at desc') }
|
||||
|
||||
index do
|
||||
column "User Link" do |lesson_session|
|
||||
column "Actions" do |teacher|
|
||||
links = ''.html_safe
|
||||
links << link_to("View", resource_path(teacher), :class => "member_link view_link")
|
||||
links << link_to("Edit", edit_resource_path(teacher), :class => "member_link edit_link")
|
||||
links
|
||||
end
|
||||
column "App Link" do |lesson_session|
|
||||
lesson_booking = lesson_session.lesson_booking
|
||||
span do
|
||||
link_to "Web URL", "#{Rails.application.config.external_root_url}/client#/jamclass/lesson-booking/#{lesson_booking.id}"
|
||||
link_to "link", "#{Rails.application.config.external_root_url}/client#/jamclass/lesson-booking/#{lesson_booking.id}"
|
||||
end
|
||||
end
|
||||
column "Status" do |lesson_session|
|
||||
|
|
@ -58,10 +64,10 @@ ActiveAdmin.register JamRuby::LessonSession, :as => 'LessonSessions' do
|
|||
|
||||
show do
|
||||
attributes_table do
|
||||
row "User Link" do |lesson_session|
|
||||
row "App Link" do |lesson_session|
|
||||
lesson_booking = lesson_session.lesson_booking
|
||||
span do
|
||||
link_to "Web URL", "#{Rails.application.config.external_root_url}/client#/jamclass/lesson-booking/#{lesson_booking.id}"
|
||||
link_to "link", "#{Rails.application.config.external_root_url}/client#/jamclass/lesson-booking/#{lesson_booking.id}"
|
||||
end
|
||||
end
|
||||
row "Status" do |lesson_session|
|
||||
|
|
@ -82,13 +88,13 @@ ActiveAdmin.register JamRuby::LessonSession, :as => 'LessonSessions' do
|
|||
row "Teacher" do |lesson_session|
|
||||
teacher = lesson_session.teacher
|
||||
span do
|
||||
link_to "#{teacher.name} (#{teacher.email})", "#{Rails.application.config.external_root_url}/client#/profile/teacher/#{teacher.id}"
|
||||
link_to teacher.admin_name, "#{Rails.application.config.external_root_url}/client#/profile/teacher/#{teacher.id}"
|
||||
end
|
||||
end
|
||||
row "Student" do |lesson_session|
|
||||
student = lesson_session.student
|
||||
span do
|
||||
link_to "#{student.name} (#{student.email})", "#{Rails.application.config.external_root_url}/client#/profile/#{student.id}"
|
||||
link_to student.admin_name, "#{Rails.application.config.external_root_url}/client#/profile/#{student.id}"
|
||||
end
|
||||
end
|
||||
row "Followup Emails Sent" do |lesson_session|
|
||||
|
|
@ -111,6 +117,11 @@ ActiveAdmin.register JamRuby::LessonSession, :as => 'LessonSessions' do
|
|||
lesson_session.timed_description
|
||||
end
|
||||
end
|
||||
row "Session" do |lesson_session|
|
||||
span do
|
||||
link_to "Session", lesson_session.music_session.admin_url
|
||||
end
|
||||
end
|
||||
row "Analysis" do |lesson_session|
|
||||
if lesson_session.analysed
|
||||
span style: "white-space: pre;" do
|
||||
|
|
|
|||
|
|
@ -60,4 +60,51 @@ ActiveAdmin.register JamRuby::MusicSession, :as => 'Music Session' do
|
|||
end
|
||||
end
|
||||
|
||||
show do
|
||||
attributes_table do
|
||||
row :id
|
||||
row :name
|
||||
row :description
|
||||
row :creator do |session|
|
||||
link_to(session.creator.admin_name, session.creator.admin_url)
|
||||
end
|
||||
row :created_at
|
||||
row :started_at
|
||||
row :session_ended_at do |session| session.session_removed_at end
|
||||
row :genre
|
||||
row :recurring_mode
|
||||
row :timezone
|
||||
row :fan_access
|
||||
row :music_access
|
||||
row :approval_required
|
||||
row :open_rsvps
|
||||
row :is_unstructured_rsv
|
||||
row :canceled
|
||||
row :lesson_session do |session|
|
||||
lesson_session = session.lesson_session
|
||||
if lesson_session
|
||||
link_to("Lesson", lesson_session.admin_url)
|
||||
else
|
||||
''
|
||||
end
|
||||
end
|
||||
row 'Session Attendances' do |session|
|
||||
|
||||
table_for(msuh = session.music_session_user_histories) do
|
||||
column :user do |msuh| msuh.user.admin_name end
|
||||
column :joined do |msuh| msuh.created_at.strftime('%b %d %Y, %H:%M') end
|
||||
column :duration do |msuh| "#{msuh.duration_minutes.round} minutes" end
|
||||
column :perf_data do |msuh|
|
||||
unless (uu = msuh.perf_uri).blank?
|
||||
link_to('Per Data Link', uu)
|
||||
else
|
||||
'No Perf Data'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -10,15 +10,31 @@ ActiveAdmin.register_page "POSA Card Uploads" do
|
|||
file = params[:jam_ruby_posa_card][:csv]
|
||||
array_of_arrays = CSV.read(file.tempfile.path)
|
||||
array_of_arrays.each do |row|
|
||||
if row.length != 1
|
||||
raise "UKNONWN CSV FORMAT! Must be 1 column"
|
||||
if row.length != 4
|
||||
raise "UKNONWN CSV FORMAT! Must be 4 columns"
|
||||
end
|
||||
|
||||
code = row[0]
|
||||
lesson_package_type = row[1]
|
||||
preactivate = row[2].strip == "true"
|
||||
requires_purchase = row[3].strip == "true"
|
||||
|
||||
posa_card = PosaCard.new
|
||||
posa_card.code = code
|
||||
posa_card.lesson_package_type = LessonPackageType.find(lesson_package_type)
|
||||
posa_card.preactivate = preactivate
|
||||
posa_card.requires_purchase = requires_purchase
|
||||
posa_card.purchased = !requires_purchase
|
||||
posa_card.card_type = params[:jam_ruby_posa_card][:card_type]
|
||||
|
||||
|
||||
if posa_card.card_type == PosaCard::JAM_CLASS_4
|
||||
posa_card.is_lesson = true
|
||||
posa_card.credits = 4
|
||||
elsif posa_card.card_type == PosaCard::JAM_CLASS_2
|
||||
posa_card.is_lesson = true
|
||||
posa_card.credits = 2
|
||||
end
|
||||
posa_card.origin = file .original_filename
|
||||
posa_card.save!
|
||||
end
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ ActiveAdmin.register JamRuby::Teacher, :as => 'Teachers' do
|
|||
end
|
||||
|
||||
end
|
||||
=begin
|
||||
|
||||
column "Background Check" do |teacher|
|
||||
div do
|
||||
if teacher.background_check_at
|
||||
|
|
@ -56,25 +56,25 @@ ActiveAdmin.register JamRuby::Teacher, :as => 'Teachers' do
|
|||
br
|
||||
end
|
||||
span do
|
||||
link_to(mark_background_check_admin_teacher_path(teacher.id), {confirm: "Mark as background checked?"}) do
|
||||
"mark as checked"
|
||||
link_to(edit_admin_teacher_background_check_path(teacher.id)) do
|
||||
"update background check"
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
span do
|
||||
''
|
||||
'NO'
|
||||
end
|
||||
span do
|
||||
br
|
||||
end
|
||||
span do
|
||||
link_to("mark as checked", mark_background_check_admin_teacher_path(teacher.id), {confirm: "Mark as background checked?"})
|
||||
link_to("update background check", edit_admin_teacher_background_check_path(teacher.id))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
=end
|
||||
|
||||
column "Session Ready" do |teacher|
|
||||
div do
|
||||
if teacher.ready_for_session_at
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
ActiveAdmin.register JamRuby::Teacher, :as => 'TeacherBackgroundCheck' do
|
||||
|
||||
|
||||
config.filters = false
|
||||
menu :label => 'Teacher Background Check', :parent => 'JamClass'
|
||||
|
||||
|
||||
|
||||
form do |f|
|
||||
f.inputs 'Set Background Check' do
|
||||
f.input :background_check_at, as: :date_select
|
||||
end
|
||||
f.actions
|
||||
end
|
||||
|
||||
|
||||
index do
|
||||
column "Actions" do |teacher|
|
||||
links = ''.html_safe
|
||||
links << link_to("View", resource_path(teacher), :class => "member_link view_link")
|
||||
links << link_to("Edit", edit_resource_path(teacher), :class => "member_link edit_link")
|
||||
links
|
||||
end
|
||||
|
||||
column 'User' do |oo|
|
||||
oo.user.email
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
@ -87,7 +87,7 @@ module JamAdmin
|
|||
config.recurly_root_url = 'https://jamkazam-development.recurly.com'
|
||||
|
||||
# where is rabbitmq?
|
||||
config.rabbitmq_host = "localhost"
|
||||
config.rabbitmq_host = "127.0.0.1"
|
||||
config.rabbitmq_port = 5672
|
||||
|
||||
# set to false to instead use amazon. You will also need to supply amazon secrets
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
class JamRuby::Teacher
|
||||
|
||||
attr_accessible :short_bio, as: :admin
|
||||
attr_accessible :short_bio, :background_check_at, as: :admin
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>The page you were looking for doesn't exist (404)</title>
|
||||
<style type="text/css">
|
||||
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
||||
div.dialog {
|
||||
width: 25em;
|
||||
padding: 0 4em;
|
||||
margin: 4em auto 0 auto;
|
||||
border: 1px solid #ccc;
|
||||
border-right-color: #999;
|
||||
border-bottom-color: #999;
|
||||
}
|
||||
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- This file lives in public/404.html -->
|
||||
<div class="dialog">
|
||||
<h1>The page you were looking for doesn't exist.</h1>
|
||||
<p>You may have mistyped the address or the page may have moved.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>The change you wanted was rejected (422)</title>
|
||||
<style type="text/css">
|
||||
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
||||
div.dialog {
|
||||
width: 25em;
|
||||
padding: 0 4em;
|
||||
margin: 4em auto 0 auto;
|
||||
border: 1px solid #ccc;
|
||||
border-right-color: #999;
|
||||
border-bottom-color: #999;
|
||||
}
|
||||
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- This file lives in public/422.html -->
|
||||
<div class="dialog">
|
||||
<h1>The change you wanted was rejected.</h1>
|
||||
<p>Maybe you tried to change something you didn't have access to.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>We're sorry, but something went wrong (500)</title>
|
||||
<style type="text/css">
|
||||
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
||||
div.dialog {
|
||||
width: 25em;
|
||||
padding: 0 4em;
|
||||
margin: 4em auto 0 auto;
|
||||
border: 1px solid #ccc;
|
||||
border-right-color: #999;
|
||||
border-bottom-color: #999;
|
||||
}
|
||||
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- This file lives in public/500.html -->
|
||||
<div class="dialog">
|
||||
<h1>We're sorry, but something went wrong.</h1>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
|
||||
#
|
||||
# To ban all spiders from the entire site uncomment the next two lines:
|
||||
# User-Agent: *
|
||||
# Disallow: /
|
||||
|
|
@ -376,3 +376,4 @@ jam_track_download_rights.sql
|
|||
guitar_center_integration_v1.sql
|
||||
mobile_recording_support.sql
|
||||
youtube_broadcast.sql
|
||||
amazon_v1.sql
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
-- create new lesson package types
|
||||
|
||||
ALTER TABLE lesson_package_types ADD COLUMN is_test_drive BOOLEAN NOT NULL DEFAULT TRUE;
|
||||
UPDATE lesson_package_types SET is_test_drive = FALSE WHERE id in('single', 'single-free');
|
||||
|
||||
INSERT INTO lesson_package_types (id, name, description, package_type, price, is_test_drive) VALUES ('amazon-test-drive-free-4', 'Test Drive (4)', 'Four free lessons which you can use to find that ideal teacher.', 'test-drive-4', 0.0, TRUE);
|
||||
INSERT INTO lesson_package_types (id, name, description, package_type, price, is_test_drive) VALUES ('amazon-test-drive-free-2', 'Test Drive (2)', 'Two free lessons which you can use to find that ideal teacher.', 'test-drive-2', 0.0, TRUE);
|
||||
INSERT INTO lesson_package_types (id, name, description, package_type, price, is_test_drive) VALUES ('amazon-test-drive-paid-4', 'Test Drive (4)', 'Four reduced-price lessons which you can use to find that ideal teacher.', 'test-drive-4', 19.99, TRUE);
|
||||
|
||||
|
||||
-- need new posa card types for Amazon -- should be able to point to lesson package type
|
||||
ALTER TABLE posa_cards ADD COLUMN lesson_package_type_id VARCHAR(64) REFERENCES lesson_package_types(id) ON DELETE SET NULL;
|
||||
ALTER TABLE posa_cards ADD COLUMN credits INTEGER NOT NULL DEFAULT 1;
|
||||
ALTER TABLE posa_cards ADD COLUMN is_lesson BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
ALTER TABLE posa_cards ADD COLUMN preactivate BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
ALTER TABLE posa_cards ADD COLUMN requires_purchase BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
ALTER TABLE posa_cards ADD COLUMN purchased BOOLEAN NOT NULL DEFAULT TRUE;
|
||||
|
||||
ALTER TABLE lesson_bookings ADD COLUMN posa_card_purchased BOOLEAN NOT NULL DEFAULT TRUE;
|
||||
|
||||
update posa_cards set credits = 5 where card_type = 'jam_tracks_5';
|
||||
update posa_cards set credits = 10 where card_type = 'jam_tracks_10';
|
||||
update posa_cards set credits = 4 where card_type = 'jam_class_4';
|
||||
update posa_cards set is_lesson = TRUE where card_type = 'jam_class_4';
|
||||
update posa_cards set lesson_package_type_id = 'test-drive' where card_type = 'jam_class_4';
|
||||
|
||||
ALTER TABLE lesson_package_purchases ADD COLUMN total_roll_forward_amount_in_cents INTEGER;
|
||||
ALTER TABLE lesson_package_purchases ADD COLUMN remaining_roll_forward_amount_in_cents INTEGER;
|
||||
ALTER TABLE lesson_package_purchases ADD COLUMN reduced_roll_forward_amount_in_cents INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
ALTER TABLE lesson_package_purchases ADD COLUMN expected_session_times INTEGER;
|
||||
ALTER TABLE lesson_package_purchases ADD COLUMN actual_session_times INTEGER;
|
||||
ALTER TABLE teacher_distributions ADD COLUMN reduced_roll_forward_amount_in_cents INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
ALTER TABLE lesson_bookings ADD COLUMN remaining_roll_forward_amount_in_cents INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
ALTER TABLE users ADD COLUMN lesson_package_needs_purchase_id VARCHAR(64) REFERENCES lesson_package_types(id) ON DELETE SET NULL;
|
||||
|
||||
|
|
@ -20,6 +20,14 @@ module JamRuby
|
|||
subject: options[:subject])
|
||||
end
|
||||
|
||||
def jamclass_alerts(options)
|
||||
mail(to: APP_CONFIG.email_jamclass_alerts_alias,
|
||||
from: APP_CONFIG.email_generic_from,
|
||||
body: options[:body],
|
||||
content_type: "text/plain",
|
||||
subject: options[:subject])
|
||||
end
|
||||
|
||||
def crash_alert(options)
|
||||
mail(to: APP_CONFIG.email_crashes_alias,
|
||||
from: APP_CONFIG.email_generic_from,
|
||||
|
|
|
|||
|
|
@ -355,7 +355,7 @@ SQL
|
|||
|
||||
if active_music_session
|
||||
music_session = active_music_session.music_session
|
||||
if music_session.session_controller_id && !active_music_session.users.exists?(music_session.session_controller)
|
||||
if music_session.session_controller_id && !active_music_session.users.exists?(music_session.session_controller.id)
|
||||
# find next in line, because the current 'session controller' is not part of the session
|
||||
next_in_line(music_session, active_music_session)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -88,13 +88,12 @@ module JamRuby
|
|||
# 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
|
||||
# Associate user with guitar center school
|
||||
if posa.retailer && posa.retailer.is_guitar_center?
|
||||
if posa.user.school_id.nil?
|
||||
posa.user.school_id = School.guitar_center.id
|
||||
end
|
||||
|
||||
posa.user.save
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ module JamRuby
|
|||
|
||||
@@log = Logging.logger[LessonBooking]
|
||||
|
||||
attr_accessor :accepting, :countering, :canceling, :autocanceling, :countered_slot, :countered_lesson, :current_purchase, :current_lesson
|
||||
attr_accessor :accepting, :countering, :canceling, :autocanceling, :countered_slot, :countered_lesson, :current_purchase, :current_lesson, :expected_session_times, :adjustment_in_cents
|
||||
|
||||
STATUS_REQUESTED = 'requested'
|
||||
STATUS_CANCELED = 'canceled'
|
||||
|
|
@ -97,7 +97,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
def after_create
|
||||
if (posa_card || card_presumed_ok || !payment_if_school_on_school?) && !sent_notices
|
||||
if ((posa_card && posa_card.purchased) || card_presumed_ok || !payment_if_school_on_school?) && !sent_notices
|
||||
send_notices
|
||||
end
|
||||
end
|
||||
|
|
@ -188,7 +188,7 @@ module JamRuby
|
|||
success = self.save
|
||||
|
||||
if !success
|
||||
puts "unable to accept lesson booking #{errors.inspect}"
|
||||
#puts "unable to accept lesson booking #{errors.inspect}"
|
||||
end
|
||||
success
|
||||
end
|
||||
|
|
@ -467,6 +467,11 @@ module JamRuby
|
|||
|
||||
def resolved_test_drive_package
|
||||
result = nil
|
||||
# posa card is best indicator of lesson package type
|
||||
if posa_card
|
||||
return posa_card.lesson_package_type
|
||||
end
|
||||
|
||||
purchase = student.most_recent_test_drive_purchase
|
||||
if purchase
|
||||
# for lessons already packaged
|
||||
|
|
@ -528,21 +533,22 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def distribution_price_in_cents(target, education, split = nil, fee_rate = nil)
|
||||
distribution = teacher_distribution_price_in_cents(target)
|
||||
def distribution_price_in_cents(target, education, split = nil)
|
||||
|
||||
|
||||
if split
|
||||
distribution = teacher_distribution_price_in_cents(target, split)
|
||||
(distribution * split).round
|
||||
|
||||
# when a split is provided, we also pin down the teacher_fee_in_cents, instead of assuming a bunch of stuff
|
||||
elsif education
|
||||
distribution = teacher_distribution_price_in_cents(target, 0.0625)
|
||||
(distribution * 0.0625).round # 0.0625 is 1/4th of 25%
|
||||
else
|
||||
distribution = teacher_distribution_price_in_cents(target)
|
||||
distribution
|
||||
end
|
||||
end
|
||||
|
||||
def teacher_distribution_price_in_cents(target)
|
||||
def teacher_distribution_price_in_cents(target, split = nil)
|
||||
if is_single_free?
|
||||
0
|
||||
elsif is_test_drive?
|
||||
|
|
@ -558,13 +564,76 @@ module JamRuby
|
|||
# we are in the month being billed. we should set the start date based on today
|
||||
start_date = today
|
||||
end
|
||||
(LessonSessionMonthlyPrice.price(self, start_date) * 100).round
|
||||
price, times = LessonSessionMonthlyPrice.price(self, start_date)
|
||||
|
||||
price_in_cents = (price * 100).round
|
||||
# OK, we have a suggested price based on date, but we need to now adjust if previous lessons have been unsuccessful
|
||||
|
||||
adjusted_price_in_cents = LessonSessionMonthlyPrice.adjust_for_missed_lessons(self, price_in_cents, split)
|
||||
|
||||
self.expected_session_times = times # save for later
|
||||
self.adjustment_in_cents = price_in_cents - adjusted_price_in_cents
|
||||
adjusted_price_in_cents
|
||||
else
|
||||
booked_price * 100
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# find any lesson package purchases for this lesson booking for previous months that have not had adjustments
|
||||
# we have to base this on 'now', meaning we do not consider months until they are fully closed
|
||||
# this does mean, because we collect up to a week in advance of a new month starting, that a student will likely not see adjustments until 2 cycles forward
|
||||
def self.previous_needing_adjustment
|
||||
now = Time.now.utc
|
||||
year = now.year
|
||||
month = now.month
|
||||
|
||||
if month == 1
|
||||
previous_year = year - 1
|
||||
previous_month = 12
|
||||
else
|
||||
previous_year = year
|
||||
previous_month = month - 1
|
||||
end
|
||||
|
||||
LessonPackagePurchase.where(recurring: true).where('month <= ?', previous_month).where('year <= ?', previous_year).where('actual_session_times is null').where('expected_session_times is not null')
|
||||
.limit(500)
|
||||
end
|
||||
|
||||
def self.adjust_for_missed_sessions
|
||||
|
||||
# Go to previous lesson_package_purchase month, and see if we need to adjust for a roll forward due to missed sessions
|
||||
previous_purchases = LessonBooking.previous_needing_adjustment
|
||||
|
||||
previous_purchases.each do |previous_purchase|
|
||||
|
||||
# XXX other monthly code uses session start time. should we be doing that?
|
||||
successful_lessons = LessonSession.where(lesson_booking: previous_purchase.lesson_booking).where(success: true).where('analysed_at >= ? AND analysed_at < ?', previous_purchase.beginning_of_month_at, previous_purchase.end_of_month_at)
|
||||
|
||||
previous_purchase.actual_session_times = successful_lessons.count
|
||||
# find out how many actual lessons were had, and then we can adjust price of this current distribution (amount_in_cents) accordingly
|
||||
|
||||
ratio = previous_purchase.actual_session_times.to_f / previous_purchase.expected_session_times.to_f
|
||||
|
||||
if ratio < 1
|
||||
# discount next month for student
|
||||
amount_paid_last_month_in_cents = previous_purchase.price_in_cents # this does not include tax. It's just the expected price of the booking
|
||||
previous_purchase.remaining_roll_forward_amount_in_cents = previous_purchase.total_roll_forward_amount_in_cents = (amount_paid_last_month_in_cents * ratio).round
|
||||
|
||||
# if there is a roll forward, add it to the lesson booking
|
||||
previous_purchase.lesson_booking.remaining_roll_forward_amount_in_cents += previous_purchase.remaining_roll_forward_amount_in_cents
|
||||
previous_purchase.lesson_booking.save!
|
||||
|
||||
else
|
||||
previous_purchase.total_roll_forward_amount_in_cents = 0
|
||||
previous_purchase.applied_roll_forward_amount_in_cents = 0
|
||||
end
|
||||
|
||||
previous_purchase.save
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def is_single_free?
|
||||
lesson_type == LESSON_TYPE_FREE
|
||||
end
|
||||
|
|
@ -674,6 +743,9 @@ module JamRuby
|
|||
|
||||
def card_approved
|
||||
self.card_presumed_ok = true
|
||||
if posa_card_id
|
||||
self.posa_card_purchased = true
|
||||
end
|
||||
if self.save && !sent_notices
|
||||
send_notices
|
||||
end
|
||||
|
|
@ -792,7 +864,10 @@ module JamRuby
|
|||
if lesson_type == LESSON_TYPE_TEST_DRIVE
|
||||
# if the user has any jamclass credits, then we should get their most recent posa purchase
|
||||
if user.jamclass_credits > 0
|
||||
lesson_booking.posa_card = user.most_recent_posa_purchase.posa_card
|
||||
lesson_booking.posa_card = user.most_recent_posa_card
|
||||
if lesson_booking.posa_card
|
||||
lesson_booking.posa_card_purchased = lesson_booking.posa_card.purchased
|
||||
end
|
||||
else
|
||||
# otherwise, it's a normal test drive, and we should honor test_drive_package_choice if specified
|
||||
lesson_booking.test_drive_package_choice = test_drive_package_choice
|
||||
|
|
@ -837,7 +912,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
def self.unprocessed(current_user)
|
||||
LessonBooking.where(user_id: current_user.id).where(card_presumed_ok: false).where(same_school_free: false).where(posa_card:nil)
|
||||
LessonBooking.where(user_id: current_user.id).where(card_presumed_ok: false).where(same_school_free: false).where('posa_card_id is null OR (posa_card_id is not null AND posa_card_purchased = false)')
|
||||
end
|
||||
|
||||
def self.requested(current_user)
|
||||
|
|
@ -902,9 +977,15 @@ module JamRuby
|
|||
# check for any recurring sessions where there are not at least 2 sessions into the future. If not, we need to make sure they get made
|
||||
def self.hourly_check
|
||||
schedule_upcoming_lessons
|
||||
|
||||
# order matters: bill_monthly code will use the adjustments made in here to correct billing roll forward
|
||||
adjust_for_missed_sessions
|
||||
|
||||
# needs to come after 'adjust_for_missed_sessions'
|
||||
bill_monthlies
|
||||
end
|
||||
|
||||
|
||||
def self.bill_monthlies
|
||||
now = Time.now
|
||||
billable_monthlies(now).each do |lesson_booking|
|
||||
|
|
|
|||
|
|
@ -29,17 +29,27 @@ module JamRuby
|
|||
after_create :add_test_drives
|
||||
after_create :create_charge
|
||||
|
||||
|
||||
|
||||
|
||||
def validate_test_drive
|
||||
if user
|
||||
# if this is a posa card purchase, we won't stop it from getting created
|
||||
if posa_card_id
|
||||
if posa_card
|
||||
return
|
||||
end
|
||||
if lesson_package_type.is_test_drive? && !user.can_buy_test_drive?
|
||||
|
||||
if lesson_package_type.is_test_drive?
|
||||
if user.lesson_package_needs_purchase_id
|
||||
# if lesson_package_needs_purchase is set, we need to let the purchase go through because the user alrady has the credits; gotta let them pay
|
||||
return
|
||||
end
|
||||
if !user.can_buy_test_drive?
|
||||
errors.add(:user, "can not buy test drive right now because you have already purchased it within the last year")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_charge
|
||||
if payment_if_school_on_school? && lesson_booking && lesson_booking.is_monthly_payment?
|
||||
|
|
@ -61,7 +71,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
def add_test_drives
|
||||
if posa_card_id
|
||||
if posa_card
|
||||
#user.jamclass_credits incremented in posa_card.rb
|
||||
return
|
||||
end
|
||||
|
|
@ -85,12 +95,28 @@ module JamRuby
|
|||
lesson_payment_charge.amount_in_cents / 100.0
|
||||
end
|
||||
|
||||
def beginning_of_month_at
|
||||
Date.new(year, month, 1).to_time.utc.beginning_of_month
|
||||
end
|
||||
|
||||
def end_of_month_at
|
||||
Date.new(year, month, 1).to_time.utc.end_of_month
|
||||
end
|
||||
|
||||
def period_over?
|
||||
Time.now.utc > end_of_month_at
|
||||
end
|
||||
|
||||
def self.create(user, lesson_booking, lesson_package_type, year = nil, month = nil, posa_card = nil)
|
||||
purchase = LessonPackagePurchase.new
|
||||
purchase.user = user
|
||||
purchase.lesson_booking = lesson_booking
|
||||
purchase.teacher = lesson_booking.teacher if lesson_booking
|
||||
purchase.posa_card = posa_card
|
||||
if !purchase.posa_card && lesson_booking
|
||||
# the lesson booking has a posa card? if so, we should track that
|
||||
purchase.posa_card = lesson_booking.posa_card
|
||||
end
|
||||
|
||||
if year
|
||||
purchase.year = year
|
||||
|
|
@ -117,6 +143,7 @@ module JamRuby
|
|||
purchase.teacher_distributions << teacher_dist
|
||||
# price should always match the teacher_distribution, if there is one
|
||||
purchase.price = teacher_dist.amount_in_cents / 100
|
||||
purchase.reduced_roll_forward_amount_in_cents += teacher_dist.reduced_roll_forward_amount_in_cents
|
||||
end
|
||||
|
||||
if retailer_split && retailer_split > 0
|
||||
|
|
@ -124,33 +151,39 @@ module JamRuby
|
|||
teacher_dist.retailer = teacher.teacher.retailer
|
||||
teacher_dist.save
|
||||
purchase.teacher_distributions << teacher_dist
|
||||
purchase.reduced_roll_forward_amount_in_cents += teacher_dist.reduced_roll_forward_amount_in_cents
|
||||
end
|
||||
|
||||
else
|
||||
teacher_dist = TeacherDistribution.create_for_lesson_package_purchase(purchase, false)
|
||||
purchase.teacher_distributions << teacher_dist
|
||||
purchase.reduced_roll_forward_amount_in_cents += teacher_dist.reduced_roll_forward_amount_in_cents
|
||||
# price should always match the teacher_distribution, if there is one
|
||||
purchase.price = teacher_dist.amount_in_cents / 100
|
||||
|
||||
if lesson_booking.school_on_school_payment? && lesson_booking.school.education
|
||||
teacher_dist = TeacherDistribution.create_for_lesson_package_purchase(purchase, true)
|
||||
purchase.teacher_distributions << teacher_dist
|
||||
purchase.reduced_roll_forward_amount_in_cents += teacher_dist.reduced_roll_forward_amount_in_cents
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# record expected times for times played in the month
|
||||
purchase.expected_session_times = lesson_booking.expected_session_times
|
||||
end
|
||||
else
|
||||
purchase.recurring = false
|
||||
end
|
||||
|
||||
if lesson_booking
|
||||
|
||||
purchase.lesson_package_type = lesson_package_type ? lesson_package_type : lesson_booking.lesson_package_type
|
||||
purchase.price = lesson_booking.booked_price if purchase.price.nil?
|
||||
else
|
||||
purchase.lesson_package_type = lesson_package_type
|
||||
purchase.price = lesson_package_type.price if purchase.price.nil?
|
||||
end
|
||||
|
||||
purchase.save
|
||||
purchase
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,11 +6,16 @@ module JamRuby
|
|||
|
||||
PRODUCT_TYPE = 'LessonPackageType'
|
||||
|
||||
TEST_DRIVE_4_ID = 'test-drive'
|
||||
|
||||
SINGLE_FREE = 'single-free'
|
||||
TEST_DRIVE_4 = 'test-drive'
|
||||
TEST_DRIVE_4 = 'test-drive-4'
|
||||
TEST_DRIVE_2 = 'test-drive-2'
|
||||
TEST_DRIVE_1 = 'test-drive-1'
|
||||
SINGLE = 'single'
|
||||
AMAZON_TEST_DRIVE_4_PAID_ID = 'amazon-test-drive-paid-4'
|
||||
AMAZON_TEST_DRIVE_FREE_2_ID = 'amazon-test-drive-free-2'
|
||||
AMAZON_TEST_DRIVE_FREE_4_ID = 'amazon-test-drive-free-4'
|
||||
|
||||
LESSON_PACKAGE_TYPES =
|
||||
[
|
||||
|
|
@ -22,14 +27,18 @@ module JamRuby
|
|||
]
|
||||
|
||||
has_many :user_desired_packages, class_name: "JamRuby::User", :foreign_key => "lesson_package_type_id", inverse_of: :desired_package
|
||||
has_many :users_needing_purchase, class_name: "JamRuby::User", :foreign_key => "lesson_package_needs_purchase_id", inverse_of: :lesson_package_needs_purchase
|
||||
has_many :posa_cards, class_name: "JamRuby::PosaCard"
|
||||
|
||||
validates :name, presence: true
|
||||
validates :description, presence: true
|
||||
validates :price, presence: true
|
||||
validates :package_type, presence: true, inclusion: {in: LESSON_PACKAGE_TYPES}
|
||||
|
||||
def self.test_drive_package_ids
|
||||
[TEST_DRIVE_4, TEST_DRIVE_2, TEST_DRIVE_1]
|
||||
LessonPackageType.select("id").where(is_test_drive: true).map {|i| i.id }
|
||||
end
|
||||
|
||||
def self.monthly
|
||||
LessonPackageType.find(MONTHLY)
|
||||
end
|
||||
|
|
@ -38,8 +47,20 @@ module JamRuby
|
|||
LessonPackageType.find(SINGLE_FREE)
|
||||
end
|
||||
|
||||
def self.amazon_test_drive_free_4
|
||||
LessonPackageType.find(AMAZON_TEST_DRIVE_FREE_4_ID)
|
||||
end
|
||||
|
||||
def self.amazon_test_drive_free_2
|
||||
LessonPackageType.find(AMAZON_TEST_DRIVE_FREE_2_ID)
|
||||
end
|
||||
|
||||
def self.amazon_test_drive_paid_4
|
||||
LessonPackageType.find(AMAZON_TEST_DRIVE_4_PAID_ID)
|
||||
end
|
||||
|
||||
def self.test_drive_4
|
||||
LessonPackageType.find(TEST_DRIVE_4)
|
||||
LessonPackageType.find(TEST_DRIVE_4_ID)
|
||||
end
|
||||
|
||||
def self.test_drive_2
|
||||
|
|
@ -54,6 +75,7 @@ module JamRuby
|
|||
LessonPackageType.find(SINGLE)
|
||||
end
|
||||
|
||||
|
||||
def booked_price(lesson_booking)
|
||||
if is_single_free?
|
||||
0
|
||||
|
|
@ -94,7 +116,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
def is_test_drive?
|
||||
id.start_with?('test-drive')
|
||||
is_test_drive
|
||||
end
|
||||
|
||||
def is_normal?
|
||||
|
|
@ -112,7 +134,7 @@ module JamRuby
|
|||
def plan_code
|
||||
if package_type == SINGLE_FREE
|
||||
"lesson-package-single-free"
|
||||
elsif package_type == 'test-drive-4'
|
||||
elsif package_type == TEST_DRIVE_4
|
||||
"lesson-package-test-drive-4"
|
||||
elsif package_type == TEST_DRIVE_2
|
||||
"lesson-package-test-drive-2"
|
||||
|
|
|
|||
|
|
@ -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?, :school_on_school?, :school_on_school_payment?, :no_school_on_school_payment?, :payment_if_school_on_school?, :scheduling_email, :teacher_school_emails, :school_and_teacher, :school_over_teacher, :school_and_teacher_ids, :school_over_teacher_ids, :posa_card, to: :lesson_booking
|
||||
delegate :is_test_drive?, :is_single_free?, :is_normal?, :approved_before?, :is_active?, :recurring, :is_monthly_payment?, :school_on_school?, :school_on_school_payment?, :no_school_on_school_payment?, :payment_if_school_on_school?, :scheduling_email, :teacher_school_emails, :school_and_teacher, :school_over_teacher, :school_and_teacher_ids, :school_over_teacher_ids, :posa_card, :remaining_roll_forward_amount_in_cents, to: :lesson_booking
|
||||
delegate :pretty_scheduled_start, to: :music_session
|
||||
|
||||
|
||||
|
|
@ -712,7 +712,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
# only show 'fully booked lessons'; not those they can not possibly be paid for
|
||||
query = query.where('lesson_bookings.posa_card_id IS NOT NULL OR lesson_bookings.card_presumed_ok = true OR (music_sessions.user_id = ?) ' + school_extra, user.id)
|
||||
query = query.where('(lesson_bookings.posa_card_id IS NOT NULL AND lesson_bookings.posa_card_purchased) OR 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
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ module JamRuby
|
|||
|
||||
raise "lesson_booking is not monthly paid #{lesson_booking.admin_url}" if !lesson_booking.is_monthly_payment?
|
||||
|
||||
|
||||
data = lesson_booking.predicted_times_for_month(start_day.year, start_day.month)
|
||||
|
||||
times = data[:times]
|
||||
|
|
@ -33,7 +34,53 @@ module JamRuby
|
|||
result = lesson_booking.booked_price
|
||||
end
|
||||
|
||||
result
|
||||
[result, times.length]
|
||||
end
|
||||
|
||||
def self.adjust_for_missed_lessons(lesson_booking, price_in_cents, split)
|
||||
|
||||
if !split
|
||||
split = 1.0
|
||||
end
|
||||
|
||||
adjusted_price_in_cents = price_in_cents
|
||||
|
||||
lesson_package_purchases = LessonPackagePurchase.where(lesson_booking: lesson_booking).where('remaining_roll_forward_amount_in_cents > 0').order(:created_at)
|
||||
remaining_roll_forward = 0
|
||||
skip_crediting = false
|
||||
reduced_amount = 0
|
||||
|
||||
lesson_package_purchases.each do |lesson_package_purchase|
|
||||
|
||||
if !skip_crediting
|
||||
|
||||
take_off = (lesson_package_purchase.remaining_roll_forward_amount_in_cents * split).round
|
||||
|
||||
amount_remaining_after_adjustment = price_in_cents - take_off
|
||||
|
||||
if amount_remaining_after_adjustment <= 0
|
||||
# there isn't enough 'price_in_cents' to eat up the needed credit, so we say this teacher_distribution has no due price, and break out of the loo
|
||||
adjusted_price_in_cents = 0
|
||||
reduced_amount += price_in_cents
|
||||
lesson_package_purchase.remaining_roll_forward_amount_in_cents -= price_in_cents
|
||||
skip_crediting = true
|
||||
else
|
||||
adjusted_price_in_cents = amount_remaining_after_adjustment
|
||||
reduced_amount += take_off
|
||||
# this lesson_package_purchase is now cleared out - totally credited!
|
||||
lesson_package_purchase.remaining_roll_forward_amount_in_cents = 0
|
||||
end
|
||||
end
|
||||
|
||||
remaining_roll_forward = remaining_roll_forward + lesson_package_purchase.remaining_roll_forward_amount_in_cents
|
||||
|
||||
lesson_package_purchase.save!
|
||||
end
|
||||
|
||||
lesson_booking.remaining_roll_forward_amount_in_cents = remaining_roll_forward
|
||||
lesson_booking.save!
|
||||
|
||||
adjusted_price_in_cents
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -126,7 +126,6 @@ module JamRuby
|
|||
|
||||
def refresh_stream(user, broadcast)
|
||||
stream_data = get_livestream(user)
|
||||
puts "REFRESH STREAM #{stream_data}"
|
||||
broadcast.stream_id = stream_data["id"]
|
||||
broadcast.stream_status = stream_data["status"]["streamStatus"]
|
||||
broadcast.stream_name = stream_data["cdn"]["ingestionInfo"]["streamName"]
|
||||
|
|
@ -185,7 +184,6 @@ module JamRuby
|
|||
|
||||
if livestream
|
||||
# if livestream["status"]["streamStatus"] == "active"
|
||||
puts "LI EVESATREMA STATATUESNUHOENTUHENOSTHU #{livestream["status"]["streamStatus"]}"
|
||||
transition_broadcast(user, broadcast, 'live', google_client)
|
||||
# end
|
||||
else
|
||||
|
|
@ -1254,6 +1252,10 @@ SQL
|
|||
sessions
|
||||
end
|
||||
|
||||
def admin_url
|
||||
APP_CONFIG.admin_root_url + "/admin/music_sessions/" + id
|
||||
end
|
||||
|
||||
private
|
||||
def generate_share_token
|
||||
|
||||
|
|
|
|||
|
|
@ -7,20 +7,25 @@ module JamRuby
|
|||
JAM_TRACKS_5 = 'jam_tracks_5'
|
||||
JAM_TRACKS_10 = 'jam_tracks_10'
|
||||
JAM_CLASS_4 = 'jam_class_4'
|
||||
JAM_CLASS_2 = 'jam_class_2'
|
||||
CARD_TYPES =
|
||||
[
|
||||
JAM_TRACKS_5,
|
||||
JAM_TRACKS_10,
|
||||
JAM_CLASS_4
|
||||
JAM_CLASS_4,
|
||||
JAM_CLASS_2
|
||||
]
|
||||
|
||||
|
||||
belongs_to :user, class_name: "JamRuby::User"
|
||||
belongs_to :retailer, class_name: "JamRuby::Retailer"
|
||||
belongs_to :lesson_package_type, class_name: "JamRuby::LessonPackageType"
|
||||
|
||||
has_many :posa_card_purchases, class_name: 'JamRuby::PosaCardPurchase'
|
||||
has_one :lesson_package_purchase, class_name: 'JamRuby::LessonPackagePurchase'
|
||||
has_one :jam_track_right, class_name: "JamRuby::JamTrackRight"
|
||||
|
||||
|
||||
validates :card_type, presence: true, inclusion: {in: CARD_TYPES}
|
||||
validates :code, presence: true, uniqueness: true
|
||||
|
||||
|
|
@ -34,20 +39,9 @@ module JamRuby
|
|||
validate :within_one_year
|
||||
|
||||
def is_lesson_posa_card?
|
||||
card_type == JAM_CLASS_4
|
||||
self.is_lesson
|
||||
end
|
||||
|
||||
def credits
|
||||
if card_type == JAM_TRACKS_5
|
||||
5
|
||||
elsif card_type == JAM_TRACKS_10
|
||||
10
|
||||
elsif card_type == JAM_CLASS_4
|
||||
4
|
||||
else
|
||||
raise "unknown card type #{card_type}"
|
||||
end
|
||||
end
|
||||
|
||||
def already_activated
|
||||
if activated_at && activated_at_was && activated_at_changed?
|
||||
|
|
@ -60,7 +54,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
def within_one_year
|
||||
if user && claimed_at && claimed_at_was && claimed_at_changed?
|
||||
if user && claimed_at && !claimed_at_was && claimed_at_changed?
|
||||
if !user.can_claim_posa_card
|
||||
self.errors.add(:claimed_at, 'was within 1 year')
|
||||
end
|
||||
|
|
@ -86,7 +80,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
def must_be_activated
|
||||
if claimed_at && !activated_at
|
||||
if claimed_at && !preactivate && !activated_at
|
||||
self.errors.add(:activated_at, 'must already be set')
|
||||
end
|
||||
end
|
||||
|
|
@ -94,11 +88,11 @@ module JamRuby
|
|||
def check_attributed
|
||||
if user && user_id_changed?
|
||||
if card_type == JAM_TRACKS_5
|
||||
user.gifted_jamtracks += 5
|
||||
user.gifted_jamtracks += credits
|
||||
elsif card_type == JAM_TRACKS_10
|
||||
user.gifted_jamtracks += 10
|
||||
elsif card_type == JAM_CLASS_4
|
||||
user.jamclass_credits += 4
|
||||
user.gifted_jamtracks += credits
|
||||
elsif is_lesson_posa_card?
|
||||
user.jamclass_credits += credits
|
||||
else
|
||||
raise "unknown card type #{card_type}"
|
||||
end
|
||||
|
|
@ -106,18 +100,6 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def lesson_package_type
|
||||
if card_type == JAM_TRACKS_5
|
||||
raise 'not a lesson package: ' + card_type
|
||||
elsif card_type == JAM_TRACKS_10
|
||||
raise 'not a lesson package: ' + card_type
|
||||
elsif card_type == JAM_CLASS_4
|
||||
LessonPackageType.test_drive_4
|
||||
else
|
||||
raise "unknown card type #{card_type}"
|
||||
end
|
||||
end
|
||||
|
||||
def product_info
|
||||
price = nil
|
||||
plan_code = nil
|
||||
|
|
@ -128,9 +110,9 @@ module JamRuby
|
|||
elsif card_type == JAM_TRACKS_10
|
||||
price = 19.99
|
||||
plan_code = 'posa-jatracks-10'
|
||||
elsif card_type == JAM_CLASS_4
|
||||
price = 49.99
|
||||
plan_code = 'posa-jamclass-4'
|
||||
elsif is_lesson_posa_card?
|
||||
price = lesson_package_type.price
|
||||
plan_code = "posa-jamclass-#{credits}"
|
||||
else
|
||||
raise "unknown card type #{card_type}"
|
||||
end
|
||||
|
|
@ -148,20 +130,53 @@ module JamRuby
|
|||
self.save
|
||||
end
|
||||
|
||||
def has_been_purchased(create_purchase)
|
||||
if !purchased
|
||||
|
||||
#release flag on user account indicating they need to buy this card
|
||||
user.lesson_package_needs_purchase = nil
|
||||
user.save
|
||||
|
||||
# indicate this has been purchased
|
||||
self.purchased = true
|
||||
self.save
|
||||
|
||||
if is_lesson_posa_card? && create_purchase
|
||||
LessonPackagePurchase.create(user, nil, lesson_package_type, nil, nil, self)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def claim(user)
|
||||
self.user = user
|
||||
self.claimed_at = Time.now
|
||||
|
||||
if self.save
|
||||
if user.errors.any?
|
||||
# happens on signup if bad email etc
|
||||
return
|
||||
end
|
||||
|
||||
UserWhitelist.card_create(user, 'posa')
|
||||
|
||||
if !preactivate
|
||||
SaleLineItem.associate_user_for_posa(self, user)
|
||||
end
|
||||
|
||||
if requires_purchase
|
||||
# this is a flag on the account that makes it so the user can't buy any TD's on the payment page until they clear this up, because we've given them credits
|
||||
user.lesson_package_needs_purchase = self.lesson_package_type
|
||||
user.save
|
||||
end
|
||||
|
||||
# when you claim a POSA card, you are also making a LessonPackagePurchase
|
||||
if is_lesson_posa_card?
|
||||
|
||||
GuitarCenter.post_posa_claim(self)
|
||||
|
||||
purchase = LessonPackagePurchase.create(user, nil, lesson_package_type, nil, nil, self) if purchase.nil?
|
||||
if purchased
|
||||
LessonPackagePurchase.create(user, nil, lesson_package_type, nil, nil, self)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -171,8 +186,8 @@ module JamRuby
|
|||
'JT-5'
|
||||
elsif card_type == JAM_TRACKS_10
|
||||
'JT-10'
|
||||
elsif card_type == JAM_CLASS_4
|
||||
'JC-4'
|
||||
elsif is_lesson_posa_card?
|
||||
"JC-#{credits}"
|
||||
else
|
||||
raise "unknown card type #{card_type}"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -233,8 +233,8 @@ module JamRuby
|
|||
free && non_free
|
||||
end
|
||||
|
||||
def self.purchase_test_drive(current_user, lesson_package_type, booking = nil)
|
||||
self.purchase_lesson(nil, current_user, booking, lesson_package_type)
|
||||
def self.purchase_test_drive(current_user, lesson_package_type, booking = nil, posa_card = nil)
|
||||
self.purchase_lesson(nil, current_user, booking, lesson_package_type, nil, nil, false, posa_card)
|
||||
end
|
||||
|
||||
def self.post_sale_test_failure
|
||||
|
|
@ -261,7 +261,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
# this is easy to make generic, but right now, it just purchases lessons
|
||||
def self.purchase_lesson(charge, current_user, lesson_booking, lesson_package_type, lesson_session = nil, lesson_package_purchase = nil, force = false)
|
||||
def self.purchase_lesson(charge, current_user, lesson_booking, lesson_package_type, lesson_session = nil, lesson_package_purchase = nil, force = false, posa_card = nil)
|
||||
stripe_charge = nil
|
||||
sale = nil
|
||||
purchase = nil
|
||||
|
|
@ -279,7 +279,7 @@ module JamRuby
|
|||
|
||||
sale_line_item = SaleLineItem.create_from_lesson_package(current_user, sale, lesson_package_type, lesson_booking)
|
||||
|
||||
price_info = charge_stripe_for_lesson(charge, current_user, lesson_booking, lesson_package_type, sale_line_item, lesson_session, lesson_package_purchase, force)
|
||||
price_info = charge_stripe_for_lesson(charge, current_user, lesson_booking, lesson_package_type, sale_line_item, lesson_session, lesson_package_purchase, force, posa_card)
|
||||
|
||||
post_sale_test_failure
|
||||
|
||||
|
|
@ -310,7 +310,7 @@ module JamRuby
|
|||
{sale: sale, stripe_charge: stripe_charge, purchase: purchase}
|
||||
end
|
||||
|
||||
def self.charge_stripe_for_lesson(charge, current_user, lesson_booking, lesson_package_type, sale_line_item, lesson_session = nil, lesson_package_purchase = nil, force = false)
|
||||
def self.charge_stripe_for_lesson(charge, current_user, lesson_booking, lesson_package_type, sale_line_item, lesson_session = nil, lesson_package_purchase = nil, force = false, posa_card = nil)
|
||||
if lesson_package_purchase
|
||||
target = lesson_package_purchase
|
||||
elsif lesson_session
|
||||
|
|
@ -322,10 +322,9 @@ module JamRuby
|
|||
current_user.sync_stripe_customer
|
||||
|
||||
purchase = lesson_package_purchase
|
||||
purchase = LessonPackagePurchase.create(current_user, lesson_booking, lesson_package_type) if purchase.nil?
|
||||
purchase = LessonPackagePurchase.create(current_user, lesson_booking, lesson_package_type, nil, nil, posa_card) if purchase.nil?
|
||||
|
||||
if purchase.errors.any?
|
||||
puts "purchase errors #{purchase.errors.inspect}"
|
||||
price_info = {}
|
||||
price_info[:purchase] = purchase
|
||||
return price_info
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ module JamRuby
|
|||
query = query.where("teaches_age_lower <= ? AND (CASE WHEN teaches_age_upper = 0 THEN true ELSE teaches_age_upper >= ? END)", student_age, student_age)
|
||||
end
|
||||
|
||||
# don't show phantom teachers that teach 'bass guitar', 'acoustic guitar', 'electric_guitar'
|
||||
# don't show phantom teachers that teach 'bass guitar', 'acoustic guitar', 'electric guitar'
|
||||
query = query.where("((select count(checkgt.instrument_id) from teachers_instruments checkgt where checkgt.teacher_id = teachers.id AND checkgt.instrument_id IN ('bass guitar', 'acoustic guitar', 'electric guitar') ) = 0 AND phantom = true) OR phantom = false")
|
||||
|
||||
# order in this way: https://jamkazam.atlassian.net/browse/VRFS-4058
|
||||
|
|
@ -349,8 +349,8 @@ module JamRuby
|
|||
reviews.order('created_at desc').limit(20)
|
||||
end
|
||||
|
||||
def mark_background_checked
|
||||
self.background_check_at = Time.now
|
||||
def mark_background_checked(time)
|
||||
self.background_check_at = time
|
||||
self.save!
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -55,14 +55,14 @@ module JamRuby
|
|||
end
|
||||
|
||||
def self.create_for_lesson_package_purchase(lesson_package_purchase, for_education, split = nil, fee_rate = nil)
|
||||
|
||||
distribution = create(lesson_package_purchase, for_education, split, fee_rate)
|
||||
distribution.lesson_package_purchase = lesson_package_purchase
|
||||
distribution.education = for_education
|
||||
|
||||
|
||||
# lock down the teacher_fee_in_cents
|
||||
distribution.teacher_fee_in_cents = distribution.calculate_teacher_fee(split, fee_rate)
|
||||
|
||||
distribution.reduced_roll_forward_amount_in_cents = lesson_package_purchase.lesson_booking.adjustment_in_cents
|
||||
distribution
|
||||
end
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ module JamRuby
|
|||
distribution.teacher = target.teacher
|
||||
distribution.ready = false
|
||||
distribution.distributed = false
|
||||
distribution.amount_in_cents = target.lesson_booking.distribution_price_in_cents(target, education, split, fee_rate)
|
||||
distribution.amount_in_cents = target.lesson_booking.distribution_price_in_cents(target, education, split)
|
||||
distribution.school = target.lesson_booking.school
|
||||
distribution
|
||||
end
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ module JamRuby
|
|||
def last_billed_at_date
|
||||
teacher_payment_charge.last_billed_at_date
|
||||
end
|
||||
|
||||
def charge_retry_hours
|
||||
24
|
||||
end
|
||||
|
|
@ -93,6 +94,8 @@ module JamRuby
|
|||
payment.amount_in_cents = payment.teacher_distribution.amount_in_cents
|
||||
payment.fee_in_cents = payment.teacher_distribution.calculate_teacher_fee
|
||||
|
||||
if payment.teacher_distribution.amount_in_cents > 0
|
||||
|
||||
effective_in_cents = payment.real_distribution_in_cents
|
||||
|
||||
if payment.teacher_payment_charge.nil?
|
||||
|
|
@ -118,6 +121,15 @@ module JamRuby
|
|||
payment.teacher_distribution.distributed = true
|
||||
payment.teacher_distribution.save!
|
||||
end
|
||||
else
|
||||
|
||||
# 0 amount distribution; these occur in 100% roll forward scenarios (previous month was completely missed)
|
||||
payment.save!
|
||||
payment.teacher_distribution.distributed = true
|
||||
payment.teacher_distribution.save!
|
||||
|
||||
end
|
||||
|
||||
payment
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ module JamRuby
|
|||
attr_accessible :first_name, :last_name, :email, :city, :password, :password_confirmation, :state, :country, :birth_date, :subscribe_email, :terms_of_service, :original_fpfile, :cropped_fpfile, :cropped_large_fpfile, :cropped_s3_path, :cropped_large_s3_path, :photo_url, :large_photo_url, :crop_selection
|
||||
|
||||
# updating_password corresponds to a lost_password
|
||||
attr_accessor :test_drive_packaging, :validate_instruments, :updating_password, :updating_email, :updated_email, :update_email_confirmation_url, :administratively_created, :current_password, :setting_password, :confirm_current_password, :updating_avatar, :updating_progression_field, :mods_json, :expecting_gift_card
|
||||
attr_accessor :test_drive_packaging, :validate_instruments, :updating_password, :updating_email, :updated_email, :update_email_confirmation_url, :administratively_created, :current_password, :setting_password, :confirm_current_password, :updating_avatar, :updating_progression_field, :mods_json, :expecting_gift_card, :purchase_required
|
||||
belongs_to :icecast_server_group, class_name: "JamRuby::IcecastServerGroup", inverse_of: :users, foreign_key: 'icecast_server_group_id'
|
||||
|
||||
has_many :controlled_sessions, :class_name => "JamRuby::MusicSession", inverse_of: :session_controller, foreign_key: :session_controller_id
|
||||
|
|
@ -178,7 +178,7 @@ module JamRuby
|
|||
has_many :test_drive_package_choice_teachers, :class_name => "JamRuby::TestDrivePackageChoiceTeacher", :foreign_key => "teacher_id"
|
||||
has_many :test_drive_package_choices, :class_name => "JamRuby::TestDrivePackageChoice", :foreign_key => "user_id", inverse_of: :user
|
||||
belongs_to :desired_package, :class_name => "JamRuby::LessonPackageType", :foreign_key => "lesson_package_type_id", inverse_of: :user_desired_packages # used to hold whether user last wanted test drive 4/2/1
|
||||
|
||||
belongs_to :lesson_package_needs_purchase, :class_name => "JamRuby::LessonPackageType", :foreign_key => "lesson_package_needs_purchase_id", inverse_of: :users_needing_purchase
|
||||
# Shopping carts
|
||||
has_many :shopping_carts, :class_name => "JamRuby::ShoppingCart"
|
||||
|
||||
|
|
@ -477,7 +477,7 @@ module JamRuby
|
|||
|
||||
def age
|
||||
now = Time.now.utc.to_date
|
||||
self.birth_date.nil? ? "" : now.year - self.birth_date.year - (self.birth_date.to_date.change(:year => now.year) > now ? 1 : 0)
|
||||
self.birth_date.nil? ? nil : now.year - self.birth_date.year - (self.birth_date.to_date.change(:year => now.year) > now ? 1 : 0)
|
||||
end
|
||||
|
||||
def session_count
|
||||
|
|
@ -685,6 +685,8 @@ module JamRuby
|
|||
id
|
||||
end
|
||||
|
||||
|
||||
|
||||
def set_password(old_password, new_password, new_password_confirmation)
|
||||
|
||||
# so that UserObserver knows to send a confirmation email on success
|
||||
|
|
@ -1358,17 +1360,21 @@ module JamRuby
|
|||
|
||||
# if a gift card value was passed in, then try to find that gift card and apply it to user
|
||||
if gift_card
|
||||
|
||||
# first try posa card
|
||||
posa_card = PosaCard.where(code: gift_card).first
|
||||
|
||||
if posa_card
|
||||
posa_card.claim(user)
|
||||
user.posa_cards << posa_card
|
||||
user.purchase_required = posa_card.requires_purchase # temporary; just so the signup page knows to send them to payment place
|
||||
else
|
||||
|
||||
user.expecting_gift_card = true
|
||||
found_gift_card = GiftCard.where(code: gift_card).where(user_id: nil).first
|
||||
user.gift_cards << found_gift_card if found_gift_card
|
||||
if found_gift_card
|
||||
user.gift_cards << found_gift_card
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1448,6 +1454,17 @@ module JamRuby
|
|||
#if school && school.education
|
||||
# UserMailer.student_education_welcome_message(user).deliver_now
|
||||
#else
|
||||
body = "Name: #{user.name}\n"
|
||||
body << "Email: #{user.email}\n"
|
||||
body << "Admin: #{user.admin_student_url}\n"
|
||||
if posa_card
|
||||
body << "Package Details: \n"
|
||||
body << " Package: #{posa_card.lesson_package_type.id}\n"
|
||||
body << " Credits: #{posa_card.credits}\n"
|
||||
body << " Code: #{posa_card.code}\n"
|
||||
end
|
||||
|
||||
AdminMailer.jamclass_alerts({subject: "#{user.name} just signed up as a student", body: body}).deliver_now
|
||||
UserMailer.student_welcome_message(user).deliver_now
|
||||
#end
|
||||
elsif user.is_a_teacher
|
||||
|
|
@ -1975,6 +1992,10 @@ module JamRuby
|
|||
APP_CONFIG.admin_root_url + "/admin/users/" + id
|
||||
end
|
||||
|
||||
def admin_student_url
|
||||
APP_CONFIG.admin_root_url + "/admin/students" # should add id; not yet supported
|
||||
end
|
||||
|
||||
def jam_track_rights_admin_url
|
||||
APP_CONFIG.admin_root_url + "/admin/jam_track_rights?q[user_id_equals]=#{id}&commit=Filter&order=created_at DESC"
|
||||
end
|
||||
|
|
@ -2042,7 +2063,7 @@ module JamRuby
|
|||
|
||||
# validate if within waiting period
|
||||
def can_claim_posa_card
|
||||
posa_cards.where('card_type = ?', PosaCard::JAM_CLASS_4).where('claimed_at > ?', APP_CONFIG.jam_class_card_wait_period_year.years.ago).count == 0
|
||||
posa_cards.where('is_lesson = ?', true).where('claimed_at > ?', APP_CONFIG.jam_class_card_wait_period_year.years.ago).count == 0
|
||||
end
|
||||
|
||||
def lessons_with_teacher(teacher)
|
||||
|
|
@ -2197,6 +2218,7 @@ module JamRuby
|
|||
lesson_package_type = nil
|
||||
uncollectables = nil
|
||||
choice = nil
|
||||
posa_card = nil
|
||||
User.transaction do
|
||||
|
||||
if params[:name].present?
|
||||
|
|
@ -2209,20 +2231,29 @@ module JamRuby
|
|||
if params[:test_drive]
|
||||
self.reload
|
||||
if booking
|
||||
# bookin will indicate test package
|
||||
lesson_package_type = booking.resolved_test_drive_package
|
||||
posa_card = booking.posa_card
|
||||
elsif choice
|
||||
# packages also indicate lesson package
|
||||
lesson_package_type = choice.lesson_package_type
|
||||
elsif self.lesson_package_needs_purchase
|
||||
# user has a POSA card requiring purchase, so this takes preference over the 'desired_package' (a user could have both set, but we force user to pay for POSA_CARD requiring purchase before picking up a random TD purchase)
|
||||
lesson_package_type = self.lesson_package_needs_purchase
|
||||
# also update POSA cards indicating they have been bought. This below code is a little bit
|
||||
posa_card = self.posa_cards.where(requires_purchase: true).where(purchased:false).order(:created_at).first
|
||||
else
|
||||
# the user has at some point b4 indicated interest in a package; so in absence of above indicators, this is what they are buying
|
||||
lesson_package_type = self.desired_package
|
||||
end
|
||||
|
||||
if lesson_package_type.nil?
|
||||
lesson_package_type = LessonPackageType.test_drive_4
|
||||
end
|
||||
|
||||
|
||||
result = Sale.purchase_test_drive(self, lesson_package_type, booking)
|
||||
result = Sale.purchase_test_drive(self, lesson_package_type, booking, posa_card)
|
||||
test_drive = result[:sale]
|
||||
purchase = result[:purchase]
|
||||
|
||||
if posa_card && !purchase.errors.any?
|
||||
posa_card.has_been_purchased(false)
|
||||
end
|
||||
if booking && !purchase.errors.any?
|
||||
# the booking would not have a lesson_package_purchase associated yet, so let's associate it
|
||||
booking.lesson_sessions.update_all(lesson_package_purchase_id: purchase.id)
|
||||
|
|
@ -2233,6 +2264,7 @@ module JamRuby
|
|||
|
||||
end
|
||||
|
||||
|
||||
{lesson: booking, test_drive: test_drive, purchase: purchase, lesson_package_type: lesson_package_type, uncollectables: uncollectables, package: choice}
|
||||
end
|
||||
|
||||
|
|
@ -2256,6 +2288,10 @@ module JamRuby
|
|||
lesson_purchases.where('lesson_package_type_id in (?)', LessonPackageType.test_drive_package_ids).where('posa_card_id is not null').order('created_at desc').first
|
||||
end
|
||||
|
||||
def most_recent_posa_card
|
||||
posa_cards.where('lesson_package_type_id in (?)', LessonPackageType.test_drive_package_ids).order('created_at desc').first
|
||||
end
|
||||
|
||||
def most_recent_test_drive_purchase
|
||||
lesson_purchases.where('lesson_package_type_id in (?)', LessonPackageType.test_drive_package_ids).order('created_at desc').first
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ module JamRuby
|
|||
LessonSession.hourly_check
|
||||
TeacherPayment.hourly_check
|
||||
|
||||
|
||||
@@log.debug("done")
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -901,7 +901,24 @@ FactoryGirl.define do
|
|||
|
||||
factory :posa_card, class: 'JamRuby::PosaCard' do
|
||||
sequence(:code) { |n| n.to_s }
|
||||
card_type JamRuby::PosaCardType::JAM_TRACKS_5
|
||||
card_type JamRuby::PosaCard::JAM_TRACKS_5
|
||||
credits 5
|
||||
requires_purchase false
|
||||
purchased true
|
||||
|
||||
factory :posa_card_lesson_2 do
|
||||
card_type JamRuby::PosaCard::JAM_CLASS_2
|
||||
credits 2
|
||||
lesson_package_type { JamRuby::LessonPackageType.test_drive_2 }
|
||||
is_lesson true
|
||||
end
|
||||
|
||||
factory :posa_card_lesson_4 do
|
||||
card_type JamRuby::PosaCard::JAM_CLASS_4
|
||||
credits 4
|
||||
lesson_package_type { JamRuby::LessonPackageType.test_drive_4 }
|
||||
is_lesson true
|
||||
end
|
||||
end
|
||||
|
||||
factory :posa_card_type, class: 'JamRuby::PosaCardType' do
|
||||
|
|
|
|||
|
|
@ -241,6 +241,47 @@ describe "Monthly Recurring Lesson Flow" do
|
|||
user.reload
|
||||
user.remaining_test_drives.should eql 0
|
||||
UserMailer.deliveries.length.should eql 0 # one for student
|
||||
|
||||
booking.remaining_roll_forward_amount_in_cents.should eql 0
|
||||
lesson_purchase.remaining_roll_forward_amount_in_cents.should be_nil
|
||||
lesson_purchase.expected_session_times.should eql 2
|
||||
lesson_purchase.actual_session_times.should be_nil
|
||||
|
||||
Timecop.travel(Date.new(2016, 4, 1))
|
||||
LessonBooking.adjust_for_missed_sessions
|
||||
# we should find remaining/totals in lesson purcahse as well as booking rolled up
|
||||
booking.reload
|
||||
lesson_purchase.reload
|
||||
lesson_purchase.actual_session_times.should eql 1
|
||||
lesson_purchase.expected_session_times.should eql 2
|
||||
booking.remaining_roll_forward_amount_in_cents.should eql (lesson_purchase.price * 100 * (1.0/2.0)).round
|
||||
lesson_purchase.remaining_roll_forward_amount_in_cents.should eql (lesson_purchase.price * 100 * (1.0/2.0)).round
|
||||
lesson_purchase.total_roll_forward_amount_in_cents.should eql (lesson_purchase.price * 100 * (1.0/2.0)).round
|
||||
|
||||
# but once we bill out, we'll not credit as heavily
|
||||
LessonBooking.bill_monthlies
|
||||
booking.reload
|
||||
lesson_purchase.reload
|
||||
lesson_purchase.actual_session_times.should eql 1
|
||||
lesson_purchase.expected_session_times.should eql 2
|
||||
booking.remaining_roll_forward_amount_in_cents.should eql 0
|
||||
lesson_purchase.remaining_roll_forward_amount_in_cents.should eql 0
|
||||
lesson_purchase.total_roll_forward_amount_in_cents.should eql (lesson_purchase.price * 100 * (1.0/2.0)).round
|
||||
|
||||
|
||||
booking.lesson_package_purchases.count.should eql 2
|
||||
next_purchase = booking.lesson_package_purchases.order(:created_at)[1]
|
||||
next_purchase.remaining_roll_forward_amount_in_cents.should be nil
|
||||
next_purchase.total_roll_forward_amount_in_cents.should be nil
|
||||
next_purchase.expected_session_times.should eql 4
|
||||
next_purchase.actual_session_times.should be_nil
|
||||
|
||||
next_purchase.teacher_distributions.count.should eql 1
|
||||
distribution = next_purchase.teacher_distributions[0]
|
||||
distribution.amount_in_cents.should eql (3000 - 750) # booked price is 30. one lesson is 7.50
|
||||
distribution.teacher_fee_in_cents.should eql ((3000 - 750) * 0.28).round # booked price is 30. one lesson is 7.50. take out .28
|
||||
distribution.reduced_roll_forward_amount_in_cents.should eql 750
|
||||
next_purchase.reduced_roll_forward_amount_in_cents.should eql 750
|
||||
end
|
||||
|
||||
it "works (school on school education)" do
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ describe "TestDrive Lesson Flow" do
|
|||
let(:affiliate_partner) { FactoryGirl.create(:affiliate_partner) }
|
||||
let(:affiliate_partner2) { FactoryGirl.create(:affiliate_partner, lesson_rate: 0.30) }
|
||||
let(:school) { FactoryGirl.create(:school) }
|
||||
let(:card_lessons) {FactoryGirl.create(:posa_card, card_type: JamRuby::PosaCardType::JAM_CLASS_4)}
|
||||
let(:card_lessons) {FactoryGirl.create(:posa_card_lesson_4)}
|
||||
let(:retailer) {FactoryGirl.create(:retailer)}
|
||||
|
||||
before {
|
||||
|
|
@ -271,6 +271,7 @@ describe "TestDrive Lesson Flow" do
|
|||
booking.user.should eql user
|
||||
booking.sent_notices.should be_true
|
||||
booking.posa_card.should eql card_lessons
|
||||
booking.posa_card_purchased.should be_true
|
||||
user.unprocessed_test_drive.should be_nil
|
||||
teacher_user.has_booked_test_drive_with_student?(user).should be_true
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe LessonPackageType do
|
||||
|
||||
it "test drive packages" do
|
||||
# 3 builtt-in, 3 amazon
|
||||
LessonPackageType.test_drive_package_ids.count.should eql 6
|
||||
end
|
||||
|
||||
describe "amazon price" do
|
||||
it "4-count" do
|
||||
LessonPackageType.amazon_test_drive_free_4.price.should eql 0
|
||||
end
|
||||
|
||||
it "2-count" do
|
||||
LessonPackageType.amazon_test_drive_free_2.price.should eql 0
|
||||
end
|
||||
|
||||
it "4-count reduced" do
|
||||
LessonPackageType.amazon_test_drive_paid_4.price.should eql 19.99
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -26,7 +26,9 @@ describe LessonSessionMonthlyPrice do
|
|||
|
||||
booking.booked_price.should eql 30.00
|
||||
|
||||
booking.booked_price.should eql(LessonSessionMonthlyPrice.price(booking, jan1))
|
||||
price, times = LessonSessionMonthlyPrice.price(booking, jan1)
|
||||
booking.booked_price.should eql(price)
|
||||
times.should eql(5)
|
||||
end
|
||||
|
||||
it "middle of the month" do
|
||||
|
|
@ -38,7 +40,10 @@ describe LessonSessionMonthlyPrice do
|
|||
|
||||
booking.booked_price.should eql 30.00
|
||||
|
||||
((booking.booked_price * 0.75).round(2)).should eql(LessonSessionMonthlyPrice.price(booking, jan17))
|
||||
price, times = LessonSessionMonthlyPrice.price(booking, jan17)
|
||||
((booking.booked_price * 0.75).round(2)).should eql(price)
|
||||
times.should eql(3)
|
||||
|
||||
end
|
||||
|
||||
it "end of the month which has a last billable day based on slot" do
|
||||
|
|
@ -50,7 +55,9 @@ describe LessonSessionMonthlyPrice do
|
|||
|
||||
booking.booked_price.should eql 30.00
|
||||
|
||||
((booking.booked_price * 0.25).round(2)).should eql(LessonSessionMonthlyPrice.price(booking, jan17))
|
||||
price, times = LessonSessionMonthlyPrice.price(booking, jan17)
|
||||
((booking.booked_price * 0.25).round(2)).should eql(price)
|
||||
times.should eql(1)
|
||||
end
|
||||
|
||||
it "end of the month which is not a last billable days" do
|
||||
|
|
@ -62,7 +69,9 @@ describe LessonSessionMonthlyPrice do
|
|||
|
||||
booking.booked_price.should eql 30.00
|
||||
|
||||
((booking.booked_price * 0.0).round(2)).should eql(LessonSessionMonthlyPrice.price(booking, feb29))
|
||||
price, times = LessonSessionMonthlyPrice.price(booking, feb29)
|
||||
((booking.booked_price * 0.0).round(2)).should eql(price)
|
||||
times.should eql(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ describe PosaCard do
|
|||
let(:user) {FactoryGirl.create(:user)}
|
||||
let(:card) {FactoryGirl.create(:posa_card)}
|
||||
let(:card2) {FactoryGirl.create(:posa_card)}
|
||||
let(:card_lessons) {FactoryGirl.create(:posa_card, card_type: JamRuby::PosaCardType::JAM_CLASS_4)}
|
||||
let(:card_lessons) {FactoryGirl.create(:posa_card_lesson_4)}
|
||||
let(:card_lessons_2) {FactoryGirl.create(:posa_card_lesson_2)}
|
||||
let(:retailer) {FactoryGirl.create(:retailer)}
|
||||
it "created by factory" do
|
||||
card.touch
|
||||
|
|
@ -42,10 +43,12 @@ describe PosaCard do
|
|||
end
|
||||
|
||||
describe "claim" do
|
||||
it "succeeds" do
|
||||
it "succeeds simple" do
|
||||
PosaCard.activate(card, retailer)
|
||||
card.reload
|
||||
card.claim(user)
|
||||
user.reload
|
||||
user.jamclass_credits.should be 0
|
||||
|
||||
card.errors.any?.should be false
|
||||
card.claimed_at.should_not be_nil
|
||||
|
|
@ -56,16 +59,33 @@ describe PosaCard do
|
|||
PosaCard.activate(card_lessons, retailer)
|
||||
card_lessons.reload
|
||||
card_lessons.claim(user)
|
||||
user.jamclass_credits.should be 4
|
||||
|
||||
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.lesson_package_type.should eql card_lessons.lesson_package_type
|
||||
card_lessons.lesson_package_purchase.posa_card.should eql card_lessons
|
||||
end
|
||||
|
||||
it "succeeds with jamclass type 2-count" do
|
||||
PosaCard.activate(card_lessons_2, retailer)
|
||||
card_lessons_2.reload
|
||||
card_lessons_2.claim(user)
|
||||
user.reload
|
||||
user.jamclass_credits.should be 2
|
||||
|
||||
card_lessons_2.errors.any?.should be false
|
||||
card_lessons_2.claimed_at.should_not be_nil
|
||||
card_lessons_2.user.should eql user
|
||||
card_lessons_2.reload
|
||||
card_lessons_2.lesson_package_purchase.should_not be_nil
|
||||
card_lessons_2.lesson_package_purchase.lesson_package_type.should eql card_lessons_2.lesson_package_type
|
||||
card_lessons_2.lesson_package_purchase.posa_card.should eql card_lessons_2
|
||||
end
|
||||
|
||||
it "associates student automatically for GC" do
|
||||
gc = GuitarCenter.init
|
||||
gc_owner = gc[:user]
|
||||
|
|
@ -83,7 +103,7 @@ describe PosaCard do
|
|||
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.lesson_package_type.should eql card_lessons.lesson_package_type
|
||||
card_lessons.lesson_package_purchase.posa_card.should eql card_lessons
|
||||
end
|
||||
|
||||
|
|
@ -120,16 +140,16 @@ describe PosaCard do
|
|||
end
|
||||
|
||||
it "can't be within one year" do
|
||||
PosaCard.activate(card, retailer)
|
||||
card.reload
|
||||
card.claim(user)
|
||||
PosaCard.activate(card_lessons, retailer)
|
||||
card_lessons.reload
|
||||
card_lessons.claim(user)
|
||||
|
||||
PosaCard.activate(card2, retailer)
|
||||
card2.reload
|
||||
card2.claim(user)
|
||||
PosaCard.activate(card_lessons_2, retailer)
|
||||
card_lessons_2.reload
|
||||
card_lessons_2.claim(user)
|
||||
|
||||
card2.errors.any?.should be true
|
||||
card2.errors[:user].should eql ['was within 1 year']
|
||||
card_lessons_2.errors.any?.should be true
|
||||
card_lessons_2.errors[:claimed_at].should eql ['was within 1 year']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -889,6 +889,7 @@ describe Sale do
|
|||
end
|
||||
|
||||
it "can succeed with no booking; just intent" do
|
||||
user.desired_package = LessonPackageType.test_drive_4
|
||||
intent = TeacherIntent.create(user, teacher, 'book-test-drive')
|
||||
token = create_stripe_token
|
||||
result = user.payment_update({token: token, zip: '78759', test_drive: true})
|
||||
|
|
@ -912,6 +913,7 @@ describe Sale do
|
|||
end
|
||||
|
||||
it "will reject second test drive purchase" do
|
||||
user.desired_package = LessonPackageType.test_drive_4
|
||||
intent = TeacherIntent.create(user, teacher, 'book-test-drive')
|
||||
token = create_stripe_token
|
||||
result = user.payment_update({token: token, zip: '78759', test_drive: true})
|
||||
|
|
|
|||
|
|
@ -710,7 +710,7 @@ describe User do
|
|||
user.age.should == 9
|
||||
|
||||
user.birth_date = nil
|
||||
user.age.should == ""
|
||||
user.age.should == nil
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ def app_config
|
|||
'alerts@jamkazam.com'
|
||||
end
|
||||
|
||||
def email_jamclass_alerts_alias
|
||||
'jamclass-alerts@jamkazam.com'
|
||||
end
|
||||
|
||||
def email_crashes_alias
|
||||
'clientcrash@jamkazam.com'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@
|
|||
context.JK.Banner.showAlert(
|
||||
{ title: "Close JamKazam Application",
|
||||
buttons: [
|
||||
{name: 'CANCEL SHUTDOWN', click: function() {
|
||||
logger.debug("'CANCEL SHUTDOWN' selected")
|
||||
context.JK.Banner.hide();
|
||||
}},
|
||||
{name: 'COMPLETELY SHUT DOWN THE APP', click: function() {
|
||||
logger.debug("'COMPLETELY SHUT DOWN THE APP' selected")
|
||||
context.jamClient.ShutdownApplication()
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ UserStore = context.UserStore
|
|||
userDetailDone: (response) ->
|
||||
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
|
||||
@setState({teacher: response, isSelf: response.id == context.JK.currentUserId, school_on_school: school_on_school})
|
||||
@setState({teacher: response, isSelf: response.id == context.JK.currentUserId})
|
||||
else
|
||||
logger.debug("BookLesson: ignoring teacher details", response.id, @state.teacherId)
|
||||
|
||||
|
|
@ -235,7 +235,7 @@ UserStore = context.UserStore
|
|||
@setState({updating: false})
|
||||
UserActions.refresh()
|
||||
#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?
|
||||
if response.user['has_stored_credit_card?'] || (response.posa_card_id? && response.posa_card_purchased)
|
||||
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"
|
||||
|
|
@ -302,13 +302,14 @@ UserStore = context.UserStore
|
|||
else
|
||||
for minutes in enabledMinutes
|
||||
lesson_price = teacher["price_per_lesson_#{minutes}_cents"]
|
||||
if lesson_price
|
||||
value = "single|#{minutes}"
|
||||
display = "#{minutes} Minute Lesson Each Week - $#{(lesson_price / 100).toFixed(2)} Per Week"
|
||||
results.push(`<option key={value} value={value}>{display}</option>`)
|
||||
|
||||
|
||||
for minutes in enabledMinutes
|
||||
monthly_price = teacher["price_per_month_#{minutes}_cents"]
|
||||
if monthly_price
|
||||
value = "monthly|#{minutes}"
|
||||
display = "#{minutes} Minute Lesson Each Week - $#{(monthly_price / 100).toFixed(2)} Per Month"
|
||||
results.push(`<option value={value}>{display}</option>`)
|
||||
|
|
@ -348,8 +349,8 @@ UserStore = context.UserStore
|
|||
|
||||
am_pm = [`<option key="AM" value="AM">AM</option>`, `<option key="PM" value="PM">PM</option>`]
|
||||
|
||||
bookLessonClasses = classNames({"button-orange": true, 'book-lesson-btn': true, disabled: !this.state.teacher? && !@state.updating})
|
||||
cancelClasses = classNames({"button-grey": true, disabled: !this.state.teacher? && !@state.updating})
|
||||
bookLessonClasses = classNames({"button-orange": true, 'book-lesson-btn': true, disabled: !this.state.teacher? || @state.updating})
|
||||
cancelClasses = classNames({"button-grey": true, disabled: !this.state.teacher? || @state.updating})
|
||||
|
||||
descriptionErrors = context.JK.reactSingleFieldErrors('description', @state.descriptionErrors)
|
||||
bookedPriceErrors = context.JK.reactSingleFieldErrors('booked_price', @state.bookedPriceErrors)
|
||||
|
|
|
|||
|
|
@ -233,6 +233,11 @@ LessonTimerActions = context.LessonTimerActions
|
|||
rescheduleLesson: (lesson) ->
|
||||
if lesson.recurring
|
||||
buttons = []
|
||||
buttons.push({
|
||||
name: 'CANCEL',
|
||||
buttonStyle: 'button-grey',
|
||||
click: (() => (logger.debug("cancelling out of reschedule dialog")))
|
||||
})
|
||||
buttons.push({
|
||||
name: 'THIS LESSON',
|
||||
buttonStyle: 'button-orange',
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ UserStore = context.UserStore
|
|||
return
|
||||
|
||||
slot.slotTime = @slotTime(slot, booking)
|
||||
slot.is_recurring = @isRecurring()
|
||||
slot.is_recurring = slot.slot_type == 'recurring'
|
||||
if slot['is_teacher_created?']
|
||||
slot.creatorRole = 'teacher'
|
||||
slot.creatorRoleRelative = 'teacher'
|
||||
|
|
@ -169,6 +169,7 @@ UserStore = context.UserStore
|
|||
@focusedLesson()?
|
||||
|
||||
focusedLesson: () ->
|
||||
console.log("focusedlesos", this.state?.booking?.focused_lesson)
|
||||
this.state?.booking?.focused_lesson
|
||||
|
||||
updateBookingState: (booking) ->
|
||||
|
|
@ -425,10 +426,22 @@ UserStore = context.UserStore
|
|||
false
|
||||
|
||||
isApproved: () ->
|
||||
if @hasFocusedLesson()
|
||||
@focusedLesson().status == 'approved'
|
||||
else
|
||||
@state.booking?.status == 'approved'
|
||||
|
||||
isCanceled: () ->
|
||||
@state.booking?.status == 'canceled'
|
||||
|
||||
cancelled = @state.booking?.status == 'canceled'
|
||||
if cancelled
|
||||
# if the booking is canceelled, lessons are done too. No need to check the focused lesson
|
||||
return true
|
||||
else
|
||||
if @hasFocusedLesson()
|
||||
return @focusedLesson().status == 'canceled'
|
||||
else
|
||||
cancelled
|
||||
|
||||
isSuspended: () ->
|
||||
@state.booking?.status == 'suspended'
|
||||
|
|
@ -498,13 +511,15 @@ UserStore = context.UserStore
|
|||
text = "Preferred day/time for lesson is #{this.slotTime(defaultSlot)}. Secondary option is #{this.slotTime(altSlot)}."
|
||||
|
||||
slotTime: (slot, booking = this.state.booking) ->
|
||||
if @hasFocusedLesson() || !@isRecurring(booking)
|
||||
if @hasFocusedLesson() || slot.slot_type == 'single' #!@isRecurring(booking)
|
||||
slot.pretty_start_time
|
||||
else
|
||||
"#{this.dayOfWeek(slot)} at #{this.dayTime(slot)}"
|
||||
|
||||
slotTimePhrase: (slot) ->
|
||||
if @isRecurring()
|
||||
console.log("SLOT", slot)
|
||||
if slot.slot_type == 'recurring'
|
||||
# if @isRecurring()
|
||||
"each " + @slotTime(slot)
|
||||
else
|
||||
@slotTime(slot)
|
||||
|
|
@ -709,6 +724,10 @@ UserStore = context.UserStore
|
|||
header = 'respond to lesson request'
|
||||
content = @renderTeacherRequested()
|
||||
|
||||
else if @isApproved()
|
||||
header = @approvedHeader()
|
||||
content = @renderTeacherApproved()
|
||||
|
||||
else if @isCounter()
|
||||
if @isTeacherCountered()
|
||||
header = 'your proposed alternate day/time is still pending'
|
||||
|
|
@ -716,10 +735,6 @@ UserStore = context.UserStore
|
|||
header = 'student has proposed an alternate day/time'
|
||||
content = @renderTeacherCountered()
|
||||
|
||||
else if @isApproved()
|
||||
header = @approvedHeader()
|
||||
content = @renderTeacherApproved()
|
||||
|
||||
else if @isCompleted()
|
||||
header = @completedHeader()
|
||||
content = @renderTeacherComplete()
|
||||
|
|
@ -750,6 +765,11 @@ UserStore = context.UserStore
|
|||
header = 'your lesson has been requested'
|
||||
content = @renderStudentRequested()
|
||||
|
||||
else if @isApproved()
|
||||
header = @approvedHeader()
|
||||
content = @renderStudentApproved()
|
||||
|
||||
|
||||
else if @isCounter()
|
||||
if @isTeacherCountered()
|
||||
header = 'teacher has proposed an alternate day/time'
|
||||
|
|
@ -757,10 +777,6 @@ UserStore = context.UserStore
|
|||
header = 'your proposed alternate day/time is still pending'
|
||||
content = @renderTeacherCountered()
|
||||
|
||||
else if @isApproved()
|
||||
header = @approvedHeader()
|
||||
content = @renderStudentApproved()
|
||||
|
||||
else if @isCompleted()
|
||||
header = @completedHeader()
|
||||
content = @renderStudentComplete()
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@
|
|||
proposeAltLabelText = "Propose alternate day/time"
|
||||
for slot, i in @props.slots
|
||||
|
||||
if this.props.is_recurring
|
||||
if slot.is_recurring
|
||||
slotDetail = `<div className="slot-detail">Each {slot.slotTime}</div>`
|
||||
else
|
||||
slotDetail = `<div className="slot-detail">{slot.slotTime}</div>`
|
||||
|
|
|
|||
|
|
@ -307,33 +307,31 @@ UserStore = context.UserStore
|
|||
if response.test_drive?
|
||||
# ok, they bought a package
|
||||
if response.lesson_package_type?
|
||||
# always of form test-drive-#
|
||||
prefixLength = "test-drive-".length
|
||||
packageLength = response.lesson_package_type.package_type.length
|
||||
|
||||
testDriveCount = response.lesson_package_type.package_type.substring(prefixLength, packageLength)
|
||||
testDriveCount = response.lesson_package_type.credits
|
||||
|
||||
logger.debug("testDriveCount: " + testDriveCount)
|
||||
|
||||
testDriveCountInt = parseInt(testDriveCount);
|
||||
if context._.isNaN(testDriveCountInt)
|
||||
testDriveCountInt = 3
|
||||
context.JK.GA.trackTestDrivePurchase(testDriveCount);
|
||||
|
||||
context.JK.GA.trackTestDrivePurchase(testDriveCountInt);
|
||||
|
||||
if response.test_drive?.teacher_id
|
||||
teacher_id = response.test_drive.teacher_id
|
||||
if testDriveCount == '1'
|
||||
if response.package?
|
||||
logger.debug("packaged TD purchase...")
|
||||
# the user bought a package that already includes the 1, 2, or 4 teachers as part of it
|
||||
if testDriveCount == 1
|
||||
text = "You have purchased 1 TestDrive credit and have used it to request a JamClass with #{@state.package.teachers[0].user.name}. The teacher has received your request and should respond shortly."
|
||||
else if response.package?
|
||||
text = "Each teacher has received your request and should respond shortly."
|
||||
else
|
||||
text = "You have purchased #{testDriveCount} TestDrive credits and have used 1 credit to request a JamClass with #{@state.teacher.name}. The teacher has received your request and should respond shortly."
|
||||
location = "/client#/jamclass"
|
||||
else
|
||||
if @state.teacher?.id
|
||||
|
||||
# the user bought the testdrive, and there is a teacher of interest in context (but no booking)
|
||||
text = "Each teacher has received your request and should respond shortly."
|
||||
location = "/client#/jamclass"
|
||||
else if response.lesson?
|
||||
logger.debug("TD with a lesson booking...")
|
||||
# there is a lesson booking in context, so the user has gotten a credit + gotten a lesson request going forward
|
||||
text = "You have purchased #{testDriveCount} TestDrive credits and have used 1 credit to request a JamClass with #{@state.teacher?.name}. The teacher has received your request and should respond shortly."
|
||||
location = "/client#/jamclass"
|
||||
else if response.teacher?.id
|
||||
logger.debug("straight TD package + teacher interest")
|
||||
# the user bought a test drive straight up with no lesson-booking, but previously showed interest in a teacher
|
||||
teacher_id = response.teacher.id
|
||||
if testDriveCount == '1'
|
||||
text = "You now have 1 TestDrive credit.<br/><br/>We've taken you to the lesson booking screen for the teacher you initially showed interest in."
|
||||
location = "/client#/jamclass/book-lesson/test-drive_" + teacher_id
|
||||
|
|
@ -341,8 +339,9 @@ UserStore = context.UserStore
|
|||
text = "You now have #{testDriveCount} TestDrive credits that you can take with #{testDriveCount} different teachers.<br/><br/>We've taken you to the lesson booking screen for the teacher you initially showed interest in."
|
||||
location = "/client#/jamclass/book-lesson/test-drive_" + teacher_id
|
||||
else
|
||||
# the user bought test drive, but 'cold' , i.e., no teacher in context
|
||||
if testDriveCount == '1'
|
||||
logger.debug("straight TD package")
|
||||
# the user bought test drive, but 'cold' , and, no teacher in context
|
||||
if testDriveCount == 1
|
||||
text = "You now have 1 TestDrive credit.<br/><br/>We've taken you to the Teacher Search screen, so you can search for teachers right for you."
|
||||
location = "/client#/teachers/search"
|
||||
else
|
||||
|
|
@ -495,14 +494,24 @@ UserStore = context.UserStore
|
|||
else
|
||||
alert("unknown package type")
|
||||
else
|
||||
if this.state.user.lesson_package_type_id == 'test-drive'
|
||||
# the UI is currenty the same whether the user is browsing around indicating what type of TD they want, or
|
||||
# if they bought a POSA card required puchase, and have the this.state.user.lesson_package_needs_purchase_id
|
||||
# we just need to figure out which is set, giving preference to the POSA requiring purchase
|
||||
lesson_package_type_id = this.state.user.lesson_package_needs_purchase_id
|
||||
if !lesson_package_type_id?
|
||||
lesson_package_type_id = this.state.user.lesson_package_type_id
|
||||
|
||||
if lesson_package_type_id == 'test-drive'
|
||||
explanation = `<span>You are purchasing the TestDrive package of JamClass by JamKazam. This purchase entitles you to take 4 private online music lessons - 1 each from 4 different instructors in the JamClass instructor community. The price of this TestDrive package is $49.99.</span>`
|
||||
else if this.state.user.lesson_package_type_id == 'test-drive-1'
|
||||
else if lesson_package_type_id == 'test-drive-1'
|
||||
explanation =`<span>You are purchasing the TestDrive package of JamClass by JamKazam. This purchase entitles you to take 1 private online music lesson from an instructor in the JamClass instructor community. The price of this TestDrive package is $14.99.</span>`
|
||||
else if this.state.user.lesson_package_type_id == 'test-drive-2'
|
||||
else if lesson_package_type_id == 'test-drive-2'
|
||||
explanation =`<span>You are purchasing the TestDrive package of JamClass by JamKazam. This purchase entitles you to take 2 private online music lessons - 1 each from 2 different instructors in the JamClass instructor community. The price of this TestDrive package is $29.99.</span>`
|
||||
else if lesson_package_type_id == 'amazon-test-drive-paid-4'
|
||||
explanation = `<span>You are purchasing the TestDrive package of JamClass by JamKazam. This purchase entitles you to take 4 private online music lessons - 1 each from 4 different instructors in the JamClass instructor community. The price of this TestDrive package is $19.99.</span>`
|
||||
else
|
||||
alert("You do not have a test drive package selected: " + this.state.user.lesson_package_type_id )
|
||||
explanation = `<span>Loading your TestDrive packaging info...</span>`
|
||||
#alert("You do not have a test drive package selected: " + this.state.user.lesson_package_type_id )
|
||||
|
||||
|
||||
bookingDetail = `<p>{explanation}
|
||||
|
|
@ -531,7 +540,7 @@ UserStore = context.UserStore
|
|||
</p>`
|
||||
else if this.state.lesson.payment_style == 'weekly'
|
||||
bookingInfo = `<p>You are booking a weekly recurring series of {lesson_length}-minute
|
||||
lessons, to be paid individually as each lesson is taken, until cancelled.</p>`
|
||||
lessons for ${this.bookedPrice()}, to be paid individually as each lesson is taken, until cancelled.</p>`
|
||||
bookingDetail = `<p>
|
||||
Your card will be charged on the day of each lesson. If you need to cancel a lesson, you must do so at
|
||||
least 24 hours before the lesson is scheduled, or you will be charged for the lesson in full.
|
||||
|
|
@ -542,7 +551,7 @@ UserStore = context.UserStore
|
|||
</p>`
|
||||
else if this.state.lesson.payment_style == 'monthly'
|
||||
bookingInfo = `<p>You are booking a weekly recurring series of {lesson_length}-minute
|
||||
lessons, to be paid for monthly until cancelled.</p>`
|
||||
lessons for ${this.bookedPrice()}, to be paid for monthly until cancelled.</p>`
|
||||
bookingDetail = `<p>
|
||||
Your card will be charged on the first day of each month. Canceling individual lessons does not earn a
|
||||
refund when buying monthly. To cancel, you must cancel at least 24 hours before the beginning of the
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ proficiencyDescriptionMap = {
|
|||
# mount it
|
||||
@profileClipboard = new Clipboard($profileLink.get(0), {
|
||||
text: =>
|
||||
return context.JK.makeAbsolute('/client#/teacher/profile/' + @state.user.teacher?.id)
|
||||
return context.JK.makeAbsolute('/client#/teacher/profile/' + @state.user.id)
|
||||
})
|
||||
else if $profileLink.length == 0 && @profileClipboard?
|
||||
@profileClipboard.destroy()
|
||||
|
|
@ -245,10 +245,15 @@ proficiencyDescriptionMap = {
|
|||
|
||||
biography = biography.replace(/\n/g, "<br/>")
|
||||
|
||||
`<div className="section bio">
|
||||
<a className="copy-profile-link button-orange" href='#' onClick={this.copyProfileLink}>
|
||||
# make button available only if this is the current user viewing
|
||||
if @state.userId == @user?.id
|
||||
|
||||
copyUrlToClipboard = `<a className="copy-profile-link button-orange" href='#' onClick={this.copyProfileLink}>
|
||||
COPY PROFILE URL TO CLIPBOARD
|
||||
</a><h3>Teacher Profile {this.editProfileLink('edit profile', 'introduction')}</h3>
|
||||
</a>`
|
||||
|
||||
`<div className="section bio">
|
||||
{copyUrlToClipboard}<h3>Teacher Profile {this.editProfileLink('edit profile', 'introduction')}</h3>
|
||||
<div className="section-content">
|
||||
<div dangerouslySetInnerHTML={{__html: biography}}></div>
|
||||
</div>
|
||||
|
|
@ -696,6 +701,17 @@ proficiencyDescriptionMap = {
|
|||
else
|
||||
age = null
|
||||
|
||||
backgroundCheck = null
|
||||
backgroundCheckAt = @state.user?.teacher?.background_check_at
|
||||
|
||||
if backgroundCheckAt
|
||||
backgroundCheck =
|
||||
`<div className="backgroundCheck">
|
||||
<div>Background Check:</div>
|
||||
|
||||
<div className="background-check-time">{context.JK.formatDateShort(new Date(backgroundCheckAt))} <img src="/assets/content/background-check.png" /></div>
|
||||
</div>`
|
||||
|
||||
`<div className="profile-about-left">
|
||||
<div className="left-content">
|
||||
<div className="location">
|
||||
|
|
@ -709,6 +725,8 @@ proficiencyDescriptionMap = {
|
|||
<div className="last-signed-in">Last Signed In:</div>
|
||||
<div>{"very recently"}</div>
|
||||
</div>
|
||||
|
||||
{backgroundCheck}
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
|
|
|
|||
|
|
@ -137,10 +137,10 @@ ProfileActions = @ProfileActions
|
|||
|
||||
if @state.next == null
|
||||
@contentBodyScroller.off('scroll')
|
||||
if @state.currentPage == 1 and @state.results.length == 0
|
||||
if @state.currentPage == 1 and @state.results.length == 0 && !@state.searching
|
||||
@endOfList.text('No Teachers found matching your search').show()
|
||||
logger.debug("TeacherSearch: empty search")
|
||||
else if @state.currentPage > 0
|
||||
else if @state.currentPage > 0 && !@state.searching
|
||||
logger.debug("end of search")
|
||||
@endOfList.text('No more Teachers').show()
|
||||
else
|
||||
|
|
@ -238,13 +238,16 @@ ProfileActions = @ProfileActions
|
|||
|
||||
bookSingleBtn = null
|
||||
bookTestDriveBtn = null
|
||||
|
||||
backgroundCheck = null
|
||||
if user.teacher.background_check_at
|
||||
backgroundCheck = `<img className="background-check" src="/assets/content/background-check.png" />`
|
||||
if !school_on_school && (!@state.user? || @state.user.jamclass_credits > 0 || @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>`
|
||||
resultsJsx.push(`<div key={user.id} className="teacher-search-result" data-teacher-id={user.id}>
|
||||
<div className="user-avatar">
|
||||
{backgroundCheck}
|
||||
<div className="avatar small">
|
||||
<img src={photo_url} />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,200 @@
|
|||
context = window
|
||||
rest = context.JK.Rest()
|
||||
ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
|
||||
|
||||
badCode = 'This is not a valid code. Please carefully re-enter the code and try again. If it still does not work, please email us at support@jamkazam.com to report this problem.'
|
||||
@AccountActivatePage = React.createClass({
|
||||
|
||||
render: () ->
|
||||
|
||||
|
||||
if this.state.formErrors?
|
||||
for key, value of this.state.formErrors
|
||||
break
|
||||
|
||||
errorText = context.JK.getFullFirstError(key, @state.formErrors, {email: 'Email', password: 'Password', gift_card: 'Coupon Code', posa_cards: 'Coupon Code', 'terms_of_service' : 'The terms of service', claimed_at: "Last coupon code used"})
|
||||
|
||||
if errorText? && errorText.indexOf('does not exist') > -1
|
||||
errorText = 'This is not a valid code. Please carefully re-enter the code and try again. If it still does not work, please email us at support@jamkazam.com to report this problem.'
|
||||
|
||||
if errorText? && errorText.indexOf('must already be set') > -1
|
||||
errorText = 'This card has not been activated by a retailer and cannot currently be used. If you purchased this card from a store, please return to the store and have the store activate the card. Only the store where you purchased this card can activate it.'
|
||||
|
||||
if errorText? && errorText.indexOf('already claimed') > -1
|
||||
errorText = 'This card has already been claimed. If you believe this is in error, please email us at support@jamkazam.com to report this problem.'
|
||||
|
||||
buttonClassnames = classNames({'redeem-giftcard': true, 'button-orange': true, disabled: @state.processing || @state.done })
|
||||
|
||||
|
||||
if @state.done
|
||||
if this.state.gifted_jamtracks
|
||||
|
||||
button =
|
||||
`<div key="done" className="done-action">
|
||||
<div>You now have {this.state.gifted_jamtracks} JamTracks credits on your account!</div>
|
||||
<div><a className="go-browse" href="/client#/jamtrack">go to JamTracks home page</a></div>
|
||||
</div>`
|
||||
else
|
||||
if this.state.purchase_required
|
||||
button =
|
||||
`<div key="done" className="done-action jam-class purchase-needed">
|
||||
<div>You have claimed <span className="amount-gifted">{this.state.jamclass_credits}</span> 30-minute JamClass credits, but still need to enter your credit card info!</div>
|
||||
<div><a className="go-browse" href="/client#/jamclass/lesson-payment/test-drive">go to the lesson payment page</a></div>
|
||||
</div>`
|
||||
else
|
||||
button =
|
||||
`<div key="done" className="done-action jam-class all-done">
|
||||
<div>You now have <span className="amount-gifted">{this.state.jamclass_credits}</span> 30-minute JamClass credits on your account!</div>
|
||||
<div><a className="go-browse" href="/client#/jamclass/searchOptions">go to JamClass teacher search page</a></div>
|
||||
</div>`
|
||||
else
|
||||
if context.JK.currentUserId?
|
||||
if @state.processing
|
||||
buttonText = 'ACTIVATING COUPON CODE...'
|
||||
else
|
||||
buttonText = 'ACTIVATE COUPON CODE'
|
||||
else
|
||||
if @state.processing
|
||||
buttonText = 'ACTIVATING ACCOUNT...'
|
||||
else
|
||||
buttonText = 'ACTIVATE ACCOUNT'
|
||||
|
||||
button = `<button key="button" className={buttonClassnames} onClick={this.action}>{buttonText}</button>`
|
||||
|
||||
action = `<ReactCSSTransitionGroup transitionName="session-track-list">
|
||||
{button}
|
||||
</ReactCSSTransitionGroup>`
|
||||
|
||||
title = 'Activate Account'
|
||||
|
||||
if context.JK.currentUserId?
|
||||
form =
|
||||
`<form onSubmit={this.submit}>
|
||||
<label>Coupon Code:</label><input type="text" name="code"/>
|
||||
{action}
|
||||
</form>`
|
||||
instruments = `<p className="instructions">Enter the 10-digit code you received in your email and click the Activate button below.</p>`
|
||||
else
|
||||
form =
|
||||
`<form onSubmit={this.submit}>
|
||||
<label>Coupon Code:</label><input type="text" name="code"/>
|
||||
<label>Email:</label><input type="text" name="email"/>
|
||||
<label>Password:</label><input type="password" name="password"/>
|
||||
<div className="clearall"/>
|
||||
<input className="terms-checkbox" type="checkbox" name="terms" /><label className="terms-help">I have read and agree to the JamKazam <a href="/corp/terms" onClick={this.termsClicked}>terms of service</a></label>
|
||||
<div className="clearall"/>
|
||||
{action}
|
||||
</form>`
|
||||
instruments = `<p className="instructions">Enter the 10-digit code you received in your email and click the Activate button below.</p>`
|
||||
|
||||
|
||||
classes = classNames({'redeem-container': true, 'not-logged-in': !context.JK.currentUserId?, 'logged-in': context.JK.currentUserId? })
|
||||
`<div className={classes}>
|
||||
<div className="redeem-content">
|
||||
<h2>{title}</h2>
|
||||
{instruments}
|
||||
{form}
|
||||
<div className={classNames({'errors': true, 'active': this.state.formErrors})}>
|
||||
{errorText}
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
getInitialState: () ->
|
||||
{formErrors: null, processing:false, gifted_jamtracks: null, jamclass_credits: null, purchase_required: null}
|
||||
|
||||
privacyPolicy: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
context.JK.popExternalLink('/corp/privacy')
|
||||
|
||||
termsClicked: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
context.JK.popExternalLink('/corp/terms')
|
||||
|
||||
componentDidMount:() ->
|
||||
$root = $(this.getDOMNode())
|
||||
$checkbox = $root.find('.terms-checkbox')
|
||||
console.log("$checkbox", $checkbox)
|
||||
context.JK.checkbox($checkbox)
|
||||
|
||||
submit: (e) ->
|
||||
@action(e)
|
||||
action: (e) ->
|
||||
|
||||
if @state.done || @state.processing
|
||||
e.preventDefault()
|
||||
return
|
||||
|
||||
if context.JK.currentUserId?
|
||||
@redeem(e)
|
||||
else
|
||||
@signup(e)
|
||||
|
||||
redeem: (e) ->
|
||||
e.preventDefault()
|
||||
return if @state.done || @state.processing
|
||||
|
||||
$root = $(@getDOMNode())
|
||||
$code = $root.find('input[name="code"]')
|
||||
code = $code.val()
|
||||
|
||||
|
||||
@setState({processing:true})
|
||||
|
||||
rest.redeemGiftCard({gift_card: code})
|
||||
.done((response) =>
|
||||
|
||||
@setState({formErrors: null, processing:false, done: true, gifted_jamtracks: response.gifted_jamtracks, jamclass_credits: response.jamclass_credits, purchase_required: response.purchase_required})
|
||||
|
||||
).fail((jqXHR) =>
|
||||
@setState({processing:false})
|
||||
|
||||
if jqXHR.status == 422
|
||||
response = JSON.parse(jqXHR.responseText)
|
||||
if response.errors
|
||||
@setState({formErrors: response.errors})
|
||||
else
|
||||
context.JK.app.notify({title: 'Unknown Error', text: jqXHR.responseText})
|
||||
else
|
||||
context.JK.app.notifyServerError(jqXHR, "Unable to Apply Coupon")
|
||||
)
|
||||
|
||||
signup: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
return if @state.done || @state.processing
|
||||
|
||||
$root = $(@getDOMNode())
|
||||
$email = $root.find('input[name="email"]')
|
||||
$code = $root.find('input[name="code"]')
|
||||
$password = $root.find('input[name="password"]')
|
||||
terms = $root.find('input[name="terms"]').is(':checked')
|
||||
|
||||
@setState({processing:true})
|
||||
email = $email.val()
|
||||
password = $password.val()
|
||||
code = $code.val()
|
||||
if !code
|
||||
# must pass up non-null value to indicate user is trying to redeem giftcard while creating account
|
||||
code = ''
|
||||
|
||||
rest.signup({email: email, password: password, gift_card: code, terms: terms})
|
||||
.done((response) =>
|
||||
|
||||
@setState({formErrors: null, processing:false, done: true, gifted_jamtracks: response.gifted_jamtracks, jamclass_credits: response.jamclass_credits, purchase_required: response.purchase_required})
|
||||
|
||||
).fail((jqXHR) =>
|
||||
@setState({processing:false})
|
||||
|
||||
if jqXHR.status == 422
|
||||
response = JSON.parse(jqXHR.responseText)
|
||||
if response.errors
|
||||
@setState({formErrors: response.errors})
|
||||
else
|
||||
context.JK.app.notify({title: 'Unknown Signup Error', text: jqXHR.responseText})
|
||||
else
|
||||
context.JK.app.notifyServerError(jqXHR, "Unable to Sign Up")
|
||||
)
|
||||
})
|
||||
|
|
@ -34,6 +34,13 @@ badCode = 'This is not a valid code. Please carefully re-enter the code and try
|
|||
<div>You now have {this.state.gifted_jamtracks} JamTracks credits on your account!</div>
|
||||
<div><a className="go-browse" href="/client#/jamtrack">go to JamTracks home page</a></div>
|
||||
</div>`
|
||||
else
|
||||
if this.state.purchase_required
|
||||
button =
|
||||
`<div key="done" className="done-action">
|
||||
<div>You have claimed {this.state.gifted_jamclass} 30-minute JamClass credits, but still need to enter your credit card info!</div>
|
||||
<div><a className="go-browse" href="/client#/jamclass/lesson-payment/test-drive">go to the lesson payment page</a></div>
|
||||
</div>`
|
||||
else
|
||||
button =
|
||||
`<div key="done" className="done-action">
|
||||
|
|
@ -66,7 +73,7 @@ badCode = 'This is not a valid code. Please carefully re-enter the code and try
|
|||
<div className="clearall"/>
|
||||
{action}
|
||||
</form>`
|
||||
instruments = `<p className="instructions">“Enter the 10-digit code from the back of your gift card and click the Redeem button below.</p>`
|
||||
instruments = `<p className="instructions">Enter the 10-digit code from the back of your gift card and click the Redeem button below.</p>`
|
||||
|
||||
|
||||
classes = classNames({'redeem-container': true, 'not-logged-in': !context.JK.currentUserId?, 'logged-in': context.JK.currentUserId? })
|
||||
|
|
@ -121,10 +128,13 @@ badCode = 'This is not a valid code. Please carefully re-enter the code and try
|
|||
$code = $root.find('input[name="code"]')
|
||||
code = $code.val()
|
||||
|
||||
|
||||
@setState({processing:true})
|
||||
|
||||
rest.redeemGiftCard({gift_card: code})
|
||||
.done((response) =>
|
||||
|
||||
@setState({formErrors: null, processing:false, done: true, gifted_jamtracks: response.gifted_jamtracks, gifted_jamclass: response.gifted_jamclass})
|
||||
@setState({formErrors: null, processing:false, done: true, gifted_jamtracks: response.gifted_jamtracks, gifted_jamclass: response.gifted_jamclass, purchase_required: response.purchase_required})
|
||||
|
||||
).fail((jqXHR) =>
|
||||
@setState({processing:false})
|
||||
|
|
@ -161,7 +171,7 @@ badCode = 'This is not a valid code. Please carefully re-enter the code and try
|
|||
rest.signup({email: email, password: password, gift_card: code, terms: terms})
|
||||
.done((response) =>
|
||||
|
||||
@setState({formErrors: null, processing:false, done: true, gifted_jamtracks: response.gifted_jamtracks, gifted_jamclass: response.gifted_jamclass})
|
||||
@setState({formErrors: null, processing:false, done: true, gifted_jamtracks: response.gifted_jamtracks, gifted_jamclass: response.gifted_jamclass, purchase_required: response.purchase_required})
|
||||
|
||||
).fail((jqXHR) =>
|
||||
@setState({processing:false})
|
||||
|
|
|
|||
|
|
@ -41,9 +41,9 @@ teacherActions = window.JK.Actions.Teacher
|
|||
else if lesson.status == 'canceled'
|
||||
lesson.displayStatus = 'Canceled'
|
||||
if lesson.student_canceled
|
||||
lesson.displayStatus = 'Canceled (Student)'
|
||||
lesson.displayStatus = 'Canceled (by Student)'
|
||||
else if lesson.teacher_canceled
|
||||
lesson.displayStatus = 'Canceled (Teacher)'
|
||||
lesson.displayStatus = 'Canceled (by Teacher)'
|
||||
|
||||
else if lesson.status == 'suspended'
|
||||
lesson.displayStatus = 'Suspended'
|
||||
|
|
@ -60,15 +60,15 @@ teacherActions = window.JK.Actions.Teacher
|
|||
if lesson.analysis?.teacher_analysis?.missed && lesson.analysis?.student_analysis?.missed
|
||||
lesson.missedRole = 'both student and teacher'
|
||||
lesson.missedUser = lesson.teacher
|
||||
lesson.displayStatus = 'Missed (Both)'
|
||||
lesson.displayStatus = 'Missed (by Both)'
|
||||
else if lesson.analysis?.teacher_analysis?.missed
|
||||
lesson.missedRole = 'the teacher'
|
||||
lesson.missedUser = lesson.teacher
|
||||
lesson.displayStatus = 'Missed (Teacher)'
|
||||
lesson.displayStatus = 'Missed (by Teacher)'
|
||||
else if lesson.analysis?.student_analysis?.missed
|
||||
lesson.missedRole = 'the student'
|
||||
lesson.missedUser = lesson.student
|
||||
lesson.displayStatus = 'Missed (Student)'
|
||||
lesson.displayStatus = 'Missed (by Student)'
|
||||
else
|
||||
lesson.displayStatus = 'Missed'
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,14 @@
|
|||
|
||||
.backgroundCheck {
|
||||
margin-top:20px;
|
||||
img {
|
||||
margin-left: 10px;
|
||||
position: relative;
|
||||
top: 4px;
|
||||
}
|
||||
.background-check-time {
|
||||
margin-top:10px;
|
||||
}
|
||||
}
|
||||
|
||||
.introductory-video {
|
||||
|
|
|
|||
|
|
@ -98,6 +98,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
.background-check {
|
||||
position: absolute;
|
||||
top: 34px;
|
||||
left: 24px;
|
||||
}
|
||||
.user-avatar {
|
||||
text-align:center;
|
||||
float:left;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
@import "client/common";
|
||||
|
||||
body.web.account_activate {
|
||||
|
||||
h2 {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
label{
|
||||
margin-bottom:4px;
|
||||
color:$ColorTextTypical;
|
||||
}
|
||||
|
||||
input{
|
||||
margin-bottom:20px;
|
||||
width:200px;
|
||||
}
|
||||
|
||||
.redeem-container {
|
||||
margin-left:350px;
|
||||
width:400px;
|
||||
padding-top:20px;
|
||||
|
||||
&.logged-in {
|
||||
button {
|
||||
margin-top:10px !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.not-logged-in {
|
||||
|
||||
}
|
||||
}
|
||||
.redeem-content {
|
||||
|
||||
}
|
||||
p.instructions {
|
||||
line-height:125%;
|
||||
color:$ColorTextTypical;
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
button {
|
||||
display:block !important;
|
||||
height: 29px !important;
|
||||
margin-bottom: 10px;
|
||||
margin-right: 0px;
|
||||
font-size: 16px !important;
|
||||
padding: 7px 3px !important;
|
||||
line-height:inherit !important;
|
||||
margin-left:2px !important;
|
||||
margin-top:15px;
|
||||
}
|
||||
|
||||
.icheckbox_minimal {
|
||||
float: left;
|
||||
top: -2px;
|
||||
margin-left: 0;
|
||||
margin-right:10px;
|
||||
}
|
||||
|
||||
.errors {
|
||||
font-size:14px;
|
||||
height:20px;
|
||||
margin:0;
|
||||
visibility: hidden;
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
|
||||
&.active {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
.terms-help {
|
||||
float:left;
|
||||
margin-top:-5px;
|
||||
font-size:12px;
|
||||
width:178px;
|
||||
}
|
||||
|
||||
.done-action {
|
||||
margin-top: 20px;
|
||||
line-height: 125%;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -343,6 +343,35 @@ class ApiMusicSessionsController < ApiController
|
|||
end
|
||||
render :json => {}, :status => :ok
|
||||
end
|
||||
|
||||
|
||||
begin
|
||||
|
||||
lesson_link = nil
|
||||
session_link = @history.music_session.admin_url
|
||||
if @history.music_session.lesson_session
|
||||
session_type = "Lesson"
|
||||
lesson_link = @history.music_session.lesson_session.admin_url
|
||||
else
|
||||
session_type = "Session"
|
||||
end
|
||||
|
||||
|
||||
subject = "#{current_user.name} Rated Their #{session_type}!"
|
||||
body = "Session Type: #{session_type}\n"
|
||||
body << "Session Rating: #{@history.good_rating? ? "Good" : "Bad"}\n"
|
||||
body << "User: #{current_user.email}\n"
|
||||
body << "Music Session URL: #{session_link}\n"
|
||||
if lesson_link
|
||||
body << "Lesson URL: #{lesson_link}\n"
|
||||
end
|
||||
body << "Session Comments: #{@history.rating_comment}\n"
|
||||
|
||||
AdminMailer.jamclass_alerts({subject: subject, body: body}).deliver_now
|
||||
rescue Exception => e
|
||||
logger.error("Exception sending out ratings email. Boo #{e}")
|
||||
end
|
||||
|
||||
elsif request.get?
|
||||
render :json => { :should_rate_session => @history.should_rate_session? }, :status => :ok
|
||||
end
|
||||
|
|
|
|||
|
|
@ -25,9 +25,10 @@ class ApiUsersController < ApiController
|
|||
end
|
||||
|
||||
def calendar
|
||||
@user=lookup_user
|
||||
ics = CalendarManager.new.create_ics_feed(@user)
|
||||
send_data ics, :filename => 'JamKazam', :disposition => 'inline', :type => "text/calendar"
|
||||
#@user=lookup_user
|
||||
#ics = CalendarManager.new.create_ics_feed(@user)
|
||||
#send_data ics, :filename => 'JamKazam', :disposition => 'inline', :type => "text/calendar"
|
||||
render :json => {}, :status => 200
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
@ -1015,12 +1016,12 @@ class ApiUsersController < ApiController
|
|||
if @posa_card.errors.any?
|
||||
respond_with_model(@posa_card)
|
||||
else
|
||||
if @posa_card.card_type == PosaCard::JAM_CLASS_4
|
||||
render json: {gifted_jamclass: 4}, status: 200
|
||||
if @posa_card.is_lesson_posa_card?
|
||||
render json: {gifted_jamclass: @posa_card.credits}, status: 200
|
||||
elsif @posa_card.card_type == PosaCard::JAM_TRACKS_10
|
||||
render json: {gifted_jamtracks: 10}, status: 200
|
||||
render json: {gifted_jamtracks: @posa_card.credits}, status: 200
|
||||
elsif @posa_card.card_type == PosaCard::JAM_TRACKS_5
|
||||
render json: {gifted_jamtracks: 5}, status: 200
|
||||
render json: {gifted_jamtracks: @posa_card.credits}, status: 200
|
||||
else
|
||||
raise 'unknown card_type ' + @posa_card.card_type
|
||||
end
|
||||
|
|
|
|||
|
|
@ -310,6 +310,12 @@ class LandingsController < ApplicationController
|
|||
render 'redeem_giftcard', layout: 'web'
|
||||
end
|
||||
|
||||
def account_activate
|
||||
@no_landing_tag = true
|
||||
@landing_tag_play_learn_earn = true
|
||||
render 'account_activate', layout: 'web'
|
||||
end
|
||||
|
||||
def buy_gift_card
|
||||
@no_landing_tag = true
|
||||
@landing_tag_play_learn_earn = true
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
object @lesson_booking
|
||||
|
||||
attributes :id, :status, :lesson_type, :payment_style, :recurring, :teacher_id, :description, :lesson_length, :created_at, :user_id, :active, :accepter_id, :canceler_id, :cancel_message, :booked_price, :card_presumed_ok, :no_slots, :posa_card_id
|
||||
attributes :id, :status, :lesson_type, :payment_style, :recurring, :teacher_id, :description, :lesson_length, :created_at, :user_id, :active, :accepter_id, :canceler_id, :cancel_message, :booked_price, :card_presumed_ok, :no_slots, :posa_card_id, :posa_card_purchased, :remaining_roll_forward_amount_in_cents
|
||||
|
||||
child(:lesson_booking_slots => :slots) {
|
||||
attributes :id, :preferred_day, :day_of_week, :hour, :minute, :slot_type, :pretty_scheduled_start, :message, :pretty_start_time, :proposer_id, :is_student_created?, :is_teacher_created?, :timezone, :pretty_timezone, :from_package
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ object @lesson_session
|
|||
:status, :student_canceled, :teacher_canceled, :student_canceled_at, :teacher_canceled_at, :student_canceled_reason,
|
||||
:teacher_canceled_reason, :status, :success, :teacher_unread_messages, :student_unread_messages, :is_active?, :recurring,
|
||||
:analysed, :school_on_school?, :no_school_on_school_payment?, :payment_if_school_on_school?, :teacher_id, :student_id, :pretty_scheduled_start, :scheduled_start, :teacher_short_canceled,
|
||||
:best_display_time
|
||||
:best_display_time, :remaining_roll_forward_amount_in_cents
|
||||
|
||||
node do |lesson_session|
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,15 +1,18 @@
|
|||
object @lesson
|
||||
|
||||
if @lesson
|
||||
if @lesson # is a LessonBooking
|
||||
node :lesson do |lesson|
|
||||
{id: @lesson.id }
|
||||
{
|
||||
id: @lesson.id,
|
||||
teacher_id: @lesson.teacher_id
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if @test_drive
|
||||
if @test_drive # is a Sale object
|
||||
node :test_drive do |lesson|
|
||||
{teacher_id: @test_drive.id}
|
||||
{id: @test_drive.id}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -29,7 +32,7 @@ end
|
|||
|
||||
if @lesson_package_type
|
||||
node :lesson_package_type do |lesson_package_type|
|
||||
{package_type: @lesson_package_type.package_type}
|
||||
{package_type: @lesson_package_type.package_type, credits: @lesson_package_type.test_drive_count}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ attributes :id,
|
|||
:test_drives_per_week,
|
||||
:errors,
|
||||
:profile_pct,
|
||||
:school_id
|
||||
:school_id,
|
||||
:background_check_at
|
||||
|
||||
|
||||
child :review_summary => :review_summary do
|
||||
|
|
|
|||
|
|
@ -34,7 +34,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, :jamclass_credits, :can_buy_test_drive?, :lesson_package_type_id, :school_id, :is_guitar_center_student?
|
||||
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?, :purchase_required, :lesson_package_needs_purchase_id
|
||||
|
||||
node :owned_school_id do |user|
|
||||
user.owned_school.id if user.owned_school
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ object @user
|
|||
attributes :id, :first_name, :last_name, :name, :photo_url
|
||||
|
||||
child :teacher do |teacher|
|
||||
attributes :id, :biography, :school_id
|
||||
attributes :id, :biography, :school_id, :background_check_at
|
||||
|
||||
child :school do |school|
|
||||
attributes :id, :education
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
- provide(:page_name, 'landing_page full account_activate')
|
||||
- provide(:description, 'Here you can redeem a code and associate it with your JamKazam account.')
|
||||
- provide(:title, 'Activate Account')
|
||||
|
||||
= react_component 'AccountActivatePage'
|
||||
|
|
@ -251,6 +251,7 @@ if defined?(Bundler)
|
|||
config.email_social_alias = 'social@jamkazam.com'
|
||||
config.email_crashes_alias = 'clientcrash@jamkazam.com'
|
||||
config.email_alerts_alias = 'alerts@jamkazam.com' # should be used for 'oh no' server down/service down sorts of emails
|
||||
config.email_jamclass_alerts_alias= 'jamclass-alerts@jamkazam.com'
|
||||
config.email_generic_from = 'nobody@jamkazam.com'
|
||||
config.email_recurly_notice = 'recurly-alerts@jamkazam.com'
|
||||
config.email_smtp_address = 'smtp.sendgrid.net'
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ SampleApp::Application.configure do
|
|||
config.minimal_curtain = true
|
||||
config.video_available= ENV['VIDEO_AVAILABILITY'] || "full"
|
||||
config.email_generic_from = 'nobody-dev@jamkazam.com'
|
||||
config.email_jamclass_alerts_alias= ENV['ALERT_EMAIL'] || 'jamclass-alerts-dev@jamkazam.com'
|
||||
config.email_alerts_alias = ENV['ALERT_EMAIL'] || 'alerts-dev@jamkazam.com'
|
||||
config.email_crashes_alias = ENV['ALERT_EMAIL'] || 'clientcrash-dev@jamkazam.com'
|
||||
config.email_social_alias = ENV['ALERT_EMAIL'] || 'social-dev@jamkazam.com'
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ SampleApp::Application.configure do
|
|||
|
||||
config.websocket_gateway_enable = false
|
||||
config.websocket_gateway_port = 6759
|
||||
config.websocket_gateway_uri = "ws://localhost:#{config.websocket_gateway_port}/websocket"
|
||||
config.websocket_gateway_uri = "ws://127.0.0.1:#{config.websocket_gateway_port}/websocket"
|
||||
|
||||
#config.websocket_gateway_connect_time_stale_client = 4
|
||||
#config.websocket_gateway_connect_time_expire_client = 6
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ Rails.application.routes.draw do
|
|||
delete '/signout', to: 'sessions#destroy'
|
||||
|
||||
match '/redeem_giftcard', to: 'landings#redeem_giftcard', via: :get
|
||||
match '/account/activate/code', to: 'landings#account_activate', via: :get
|
||||
|
||||
# landing pageslanding
|
||||
get '/jamtracks', to: 'landings#simple_jamtracks', as: 'landing_simple_jamtracks'
|
||||
|
|
|
|||
|
|
@ -13,8 +13,70 @@ rescue TypeError
|
|||
puts "for production, we ignore type error"
|
||||
end
|
||||
|
||||
def generate
|
||||
[*('a'..'z'),*('0'..'9')].shuffle[0,10].join.upcase
|
||||
end
|
||||
|
||||
def gc_10
|
||||
CSV.open("gift-card-10.csv", "wb") do |csv|
|
||||
for i in 1..150
|
||||
csv << [generate()]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def gc_20
|
||||
CSV.open("gift-card-20.csv", "wb") do |csv|
|
||||
for i in 1..100
|
||||
csv << [generate()]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# round to. we make
|
||||
|
||||
#One set of 200 codes that when redeemed translate into 5 (not 10) JamTracks each.
|
||||
|
||||
#One set of 200 codes that when redeemed translate into 4 JamClass lessons each.
|
||||
|
||||
def gc_5jt_2
|
||||
CSV.open("posa-cards-jt-5.csv", "wb") do |csv|
|
||||
for i in 1..250
|
||||
csv << [generate()]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def gc_4jc_2
|
||||
CSV.open("posa-cards-jc-4.csv", "wb") do |csv|
|
||||
for i in 1..250
|
||||
csv << [generate()]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
namespace :lessons do
|
||||
|
||||
task amazon_gift_cards: :environment do|task, args|
|
||||
CSV.open("posa-cards-amazon-test-drive-paid-4.csv", "wb") do |csv|
|
||||
for i in 1..250
|
||||
csv << [generate(), 'amazon-test-drive-paid-4', true, true]
|
||||
end
|
||||
end
|
||||
|
||||
CSV.open("posa-cards-amazon-test-drive-free-4.csv", "wb") do |csv|
|
||||
for i in 1..250
|
||||
csv << [generate(), 'amazon-test-drive-free-4',true, false]
|
||||
end
|
||||
end
|
||||
|
||||
CSV.open("posa-cards-amazon-test-drive-free-2.csv", "wb") do |csv|
|
||||
for i in 1..250
|
||||
csv << [generate(), 'amazon-test-drive-free-2',true, false]
|
||||
end
|
||||
end
|
||||
end
|
||||
task book_completed: :environment do |task, args|
|
||||
|
||||
user = User.find_by_email(ENV['STUDENT'])
|
||||
|
|
@ -68,7 +130,7 @@ namespace :lessons do
|
|||
end
|
||||
|
||||
|
||||
booking = LessonBooking.book_normal(user, teacher, slots, "Hey I've heard of you before.", recurring, payment_style, 60)
|
||||
booking = LessonBooking.book_normal(user, teacher, slots, "Hey I've heard of you before.", recurring, payment_style, 30)
|
||||
if booking.errors.any?
|
||||
puts booking.errors.inspect
|
||||
raise "booking failed"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
def generate
|
||||
[*('a'..'z'),*('0'..'9')].shuffle[0,10].join.upcase
|
||||
end
|
||||
|
||||
def gc_10
|
||||
CSV.open("gift-card-10.csv", "wb") do |csv|
|
||||
for i in 1..150
|
||||
csv << [generate()]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def gc_20
|
||||
CSV.open("gift-card-20.csv", "wb") do |csv|
|
||||
for i in 1..100
|
||||
csv << [generate()]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# round to. we make
|
||||
|
||||
#One set of 200 codes that when redeemed translate into 5 (not 10) JamTracks each.
|
||||
|
||||
#One set of 200 codes that when redeemed translate into 4 JamClass lessons each.
|
||||
|
||||
def gc_5jt_2
|
||||
CSV.open("posa-cards-jt-5.csv", "wb") do |csv|
|
||||
for i in 1..250
|
||||
csv << [generate()]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def gc_4jc_2
|
||||
CSV.open("posa-cards-jc-4.csv", "wb") do |csv|
|
||||
for i in 1..250
|
||||
csv << [generate()]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def amazon_gift_cards
|
||||
CSV.open("posa-cards-amazon-test-drive-paid-4.csv", "wb") do |csv|
|
||||
for i in 1..250
|
||||
csv << [generate(), 'amazon-test-drive-paid-4', true, true]
|
||||
end
|
||||
end
|
||||
|
||||
CSV.open("posa-cards-amazon-test-drive-free-4.csv", "wb") do |csv|
|
||||
for i in 1..250
|
||||
csv << [generate(), 'amazon-test-drive-free-4',true, false]
|
||||
end
|
||||
end
|
||||
|
||||
CSV.open("posa-cards-amazon-test-drive-free-2.csv", "wb") do |csv|
|
||||
for i in 1..250
|
||||
csv << [generate(), 'amazon-test-drive-free-2',true, false]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
|
@ -34,11 +34,12 @@ describe ApiJamblastersController, type: :controller do
|
|||
response.status.should == 200
|
||||
end
|
||||
|
||||
it "disallows different user" do
|
||||
user2 = FactoryGirl.create(:user)
|
||||
get :is_allowed, {:format => 'json', jbid: jamblaster.client_id, user_id: user2.id}
|
||||
response.status.should == 403
|
||||
end
|
||||
|
||||
#it "disallows different user" do
|
||||
# user2 = FactoryGirl.create(:user)
|
||||
# get :is_allowed, {:format => 'json', jbid: jamblaster.client_id, user_id: user2.id}
|
||||
# response.status.should == 403
|
||||
#end
|
||||
end
|
||||
|
||||
describe "not already associated" do
|
||||
|
|
|
|||
|
|
@ -870,7 +870,41 @@ FactoryGirl.define do
|
|||
|
||||
factory :posa_card, class: 'JamRuby::PosaCard' do
|
||||
sequence(:code) { |n| n.to_s }
|
||||
card_type JamRuby::PosaCardType::JAM_TRACKS_5
|
||||
card_type JamRuby::PosaCard::JAM_TRACKS_5
|
||||
requires_purchase false
|
||||
purchased true
|
||||
|
||||
factory :posa_card_lesson_2 do
|
||||
card_type JamRuby::PosaCard::JAM_CLASS_2
|
||||
credits 2
|
||||
lesson_package_type { JamRuby::LessonPackageType.test_drive_2 }
|
||||
is_lesson true
|
||||
end
|
||||
|
||||
factory :posa_card_lesson_4 do
|
||||
card_type JamRuby::PosaCard::JAM_CLASS_4
|
||||
credits 4
|
||||
lesson_package_type { JamRuby::LessonPackageType.test_drive_4 }
|
||||
is_lesson true
|
||||
end
|
||||
|
||||
factory :amazon_2_free do
|
||||
card_type JamRuby::PosaCard::JAM_CLASS_2
|
||||
credits 2
|
||||
lesson_package_type { JamRuby::LessonPackageType.amazon_test_drive_free_2 }
|
||||
is_lesson true
|
||||
preactivate true
|
||||
end
|
||||
|
||||
factory :amazon_4_paid do
|
||||
card_type JamRuby::PosaCard::JAM_CLASS_4
|
||||
credits 2
|
||||
lesson_package_type { JamRuby::LessonPackageType.amazon_test_drive_paid_4 }
|
||||
is_lesson true
|
||||
requires_purchase true
|
||||
purchased false
|
||||
preactivate true
|
||||
end
|
||||
end
|
||||
|
||||
factory :posa_card_type, class: 'JamRuby::PosaCardType' do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,126 @@
|
|||
require 'spec_helper'
|
||||
|
||||
# tests what happens when the websocket connection goes away
|
||||
describe "Activate Account Card", :js => true, :type => :feature, :capybara_feature => true do
|
||||
|
||||
subject { page }
|
||||
|
||||
let(:user1) { FactoryGirl.create(:user) }
|
||||
|
||||
let(:amazon_2_free_card) { FactoryGirl.create(:amazon_2_free) }
|
||||
|
||||
before(:all) do
|
||||
User.delete_all
|
||||
end
|
||||
|
||||
describe "not logged in" do
|
||||
describe "amazon_2_free_card" do
|
||||
it "succeeds" do
|
||||
visit '/account/activate/code'
|
||||
|
||||
amazon_2_free_card.credits.should eql 2
|
||||
|
||||
find('h2', text: 'Activate Account')
|
||||
fill_in "code", with: amazon_2_free_card.code
|
||||
fill_in "email", with: "amzposa1@jamkazam.com"
|
||||
fill_in "password", with: "jam123"
|
||||
find('.redeem-container ins', visible: false).trigger(:click)
|
||||
|
||||
find('button.redeem-giftcard', text: 'ACTIVATE ACCOUNT').trigger(:click)
|
||||
|
||||
find('.jam-class.all-done span.amount-gifted', text: amazon_2_free_card.credits)
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
|
||||
find('h2', text: 'search teachers')
|
||||
|
||||
user = User.find_by_email("amzposa1@jamkazam.com")
|
||||
amazon_2_free_card.reload
|
||||
amazon_2_free_card.user.should eq(user)
|
||||
amazon_2_free_card.requires_purchase.should be false
|
||||
amazon_2_free_card.purchased.should be true
|
||||
user.reload
|
||||
user.jamclass_credits.should eq(amazon_2_free_card.credits)
|
||||
end
|
||||
|
||||
it "validates correctly" do
|
||||
visit '/account/activate/code'
|
||||
|
||||
find('h2', text: 'Activate Account')
|
||||
|
||||
find('button.redeem-giftcard', text: 'ACTIVATE ACCOUNT').trigger(:click)
|
||||
|
||||
find('.errors.active', text: "Email can't be blank")
|
||||
|
||||
find('h2', text: 'Activate Account')
|
||||
fill_in "code", with: amazon_2_free_card.code
|
||||
fill_in "email", with: "amzpos2@jamkazam.com"
|
||||
fill_in "password", with: "jam123"
|
||||
find('.redeem-container ins', visible: false).trigger(:click)
|
||||
|
||||
find('button.redeem-giftcard', text: 'ACTIVATE ACCOUNT').trigger(:click)
|
||||
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
|
||||
find('h2', text: 'search teachers')
|
||||
|
||||
user = User.find_by_email("amzpos2@jamkazam.com")
|
||||
amazon_2_free_card.reload
|
||||
amazon_2_free_card.user.should eq(user)
|
||||
amazon_2_free_card.requires_purchase.should be false
|
||||
amazon_2_free_card.purchased.should be true
|
||||
user.reload
|
||||
user.jamclass_credits.should eq(amazon_2_free_card.credits)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
describe "logged in" do
|
||||
it "succeeds" do
|
||||
fast_signin(user1, '/account/activate/code')
|
||||
|
||||
find('h2', text: 'Activate Account')
|
||||
fill_in "code", with: amazon_2_free_card.code
|
||||
|
||||
find('button.redeem-giftcard', text: 'ACTIVATE COUPON CODE').trigger(:click)
|
||||
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
|
||||
find('h2', text: 'search teachers')
|
||||
|
||||
user1.reload
|
||||
amazon_2_free_card.reload
|
||||
amazon_2_free_card.user.should eq(user)
|
||||
amazon_2_free_card.requires_purchase.should be false
|
||||
amazon_2_free_card.purchased.should be true
|
||||
user.jamclass_credits.should eq(amazon_2_free_card.credits)
|
||||
end
|
||||
end
|
||||
|
||||
describe "logged in" do
|
||||
it "validates" do
|
||||
fast_signin(user1, '/account/activate/code')
|
||||
|
||||
find('h2', text: 'Activate Account')
|
||||
|
||||
find('button.redeem-giftcard').trigger(:click)
|
||||
|
||||
find('.errors.active', text: "Coupon Code does not exist")
|
||||
|
||||
fill_in "code", with: amazon_2_free_card.code
|
||||
|
||||
find('button.redeem-giftcard').trigger(:click)
|
||||
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
|
||||
find('h2', text: 'search teachers')
|
||||
|
||||
user1.reload
|
||||
amazon_2_free_card.reload
|
||||
amazon_2_free_card.user.should eq(user)
|
||||
amazon_2_free_card.requires_purchase.should be false
|
||||
amazon_2_free_card.purchased.should be true
|
||||
user.jamclass_credits.should eq(amazon_2_free_card.credits)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -7,7 +7,7 @@ describe "Test Drive", :js => true, :type => :feature, :capybara_feature => true
|
|||
let(:user) { FactoryGirl.create(:user, traditional_band: true,paid_sessions: true, paid_sessions_hourly_rate: 1, paid_sessions_daily_rate:1 ) }
|
||||
let(:teacher_user) {FactoryGirl.create(:teacher_user, ready_for_session_at: Time.now)}
|
||||
let(:teacher_user2) {FactoryGirl.create(:teacher_user, ready_for_session_at: Time.now)}
|
||||
let(:card_lessons) {FactoryGirl.create(:posa_card, card_type: JamRuby::PosaCardType::JAM_CLASS_4)}
|
||||
let(:card_lessons) {FactoryGirl.create(:posa_card_lesson_4)}
|
||||
let(:retailer) {FactoryGirl.create(:retailer)}
|
||||
|
||||
before(:each) do
|
||||
|
|
|
|||
|
|
@ -12,6 +12,13 @@ describe UsersController, :type => :api do
|
|||
#login(authenticated_user.email, authenticated_user.password, 200, true)
|
||||
}
|
||||
|
||||
def login(user)
|
||||
# login as fan
|
||||
post '/api/auth_session.json', { :email => user.email, :password => user.password }.to_json, "CONTENT_TYPE" => 'application/json'
|
||||
last_response.status.should == 200
|
||||
JSON.parse(last_response.body).should == { "success" => true }
|
||||
end
|
||||
|
||||
it "unsubscribe" do
|
||||
user.subscribe_email.should eql true
|
||||
get '/unsubscribe/' + user.unsubscribe_token
|
||||
|
|
@ -73,13 +80,13 @@ describe UsersController, :type => :api do
|
|||
describe "logged in" do
|
||||
|
||||
it "should not set origin with no referrer info" do
|
||||
controller.current_user = user
|
||||
login(user)
|
||||
get :home
|
||||
response.cookies["origin"].should be_nil
|
||||
end
|
||||
|
||||
it "should not set origin with referrer info" do
|
||||
controller.current_user = user
|
||||
login(user)
|
||||
get :home, utm_valid_cookie
|
||||
response.cookies["origin"].should be_nil
|
||||
end
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ Thread.new do
|
|||
:connect_time_stale_browser => 4,
|
||||
:connect_time_expire_browser => 6,
|
||||
:max_connections_per_user => 20,
|
||||
:rabbitmq_host => 'localhost',
|
||||
:rabbitmq_host => '127.0.0.1',
|
||||
:rabbitmq_port => 5672,
|
||||
:calling_thread => current,
|
||||
:cidr => ['0.0.0.0/0'],
|
||||
|
|
|
|||
|
|
@ -25,13 +25,13 @@ development:
|
|||
test:
|
||||
port: 6759
|
||||
verbose: true
|
||||
rabbitmq_host: localhost
|
||||
rabbitmq_host: 127.0.0.1
|
||||
rabbitmq_port: 5672
|
||||
<<: *defaults
|
||||
|
||||
production:
|
||||
port: 6767
|
||||
verbose: false
|
||||
rabbitmq_host: localhost
|
||||
rabbitmq_host: 127.0.0.1
|
||||
rabbitmq_port: 5672
|
||||
<<: *defaults
|
||||
|
|
|
|||
Loading…
Reference in New Issue