* relax user id on charges

This commit is contained in:
Seth Call 2016-05-12 17:41:25 -05:00
parent cfb8e27850
commit 94128e7115
7 changed files with 176 additions and 8 deletions

View File

@ -1 +1 @@
ALTER TABLE charges ADD COLUMN user_id VARCHAR(64) REFERENCES users(id) NOT NULL;
ALTER TABLE charges ADD COLUMN user_id VARCHAR(64) REFERENCES users(id);

View File

@ -87,7 +87,7 @@ module JamRuby
end
def after_create
if card_presumed_ok && !sent_notices
if (card_presumed_ok || school_on_school?) && !sent_notices
send_notices
end
end
@ -691,7 +691,7 @@ module JamRuby
lesson_booking.description = description
lesson_booking.status = STATUS_REQUESTED
if lesson_booking.teacher && lesson_booking.teacher.teacher.school
lesson_booking.school = school
lesson_booking.school = lesson_booking.teacher.teacher.school
end
# two-way association slots, for before_validation loic in slot to work
@ -710,13 +710,16 @@ module JamRuby
end
def self.unprocessed(current_user)
LessonBooking.where(user_id: current_user.id).where(card_presumed_ok: false)
LessonBooking.where(user_id: current_user.id).where(card_presumed_ok: false).where('school_id IS NULL')
end
def self.requested(current_user)
LessonBooking.where(user_id: current_user.id).where(status: STATUS_REQUESTED)
end
def school_on_school?
teacher.teacher.school && student.school && (teacher.teacher.school.id == student.school.id)
end
def self.find_bookings_needing_sessions(minimum_start_time)
MusicSession.select([:lesson_booking_id]).joins(:lesson_session => :lesson_booking).where("lesson_bookings.active = true").where('lesson_bookings.recurring = true').where("scheduled_start is not null").where("scheduled_start > ?", minimum_start_time).group(:lesson_booking_id).having('count(lesson_booking_id) < 2')

View File

@ -33,7 +33,7 @@ module JamRuby
end
def create_charge
if lesson_booking && lesson_booking.is_monthly_payment?
if !school_on_school? && lesson_booking && lesson_booking.is_monthly_payment?
self.lesson_payment_charge = LessonPaymentCharge.new
lesson_payment_charge.user = user
lesson_payment_charge.amount_in_cents = 0

View File

@ -75,7 +75,7 @@ module JamRuby
scope :past_cancel_window, -> { joins(:music_session).where('music_sessions.scheduled_start > ?', 24.hours.from_now) }
def create_charge
if !is_test_drive? && !is_monthly_payment?
if !school_on_school? && !is_test_drive? && !is_monthly_payment?
self.lesson_payment_charge = LessonPaymentCharge.new
lesson_payment_charge.user = @assigned_student
lesson_payment_charge.amount_in_cents = 0

View File

@ -12,6 +12,7 @@ describe "Normal Lesson Flow" do
let(:lesson_booking_slot_recurring2) { FactoryGirl.build(:lesson_booking_slot_recurring) }
let(:valid_single_slots) { [lesson_booking_slot_single1, lesson_booking_slot_single2] }
let(:valid_recurring_slots) { [lesson_booking_slot_recurring1, lesson_booking_slot_recurring2] }
let(:school) {FactoryGirl.create(:school)}
describe "stripe mocked" do
before {
@ -417,4 +418,167 @@ describe "Normal Lesson Flow" do
user.remaining_test_drives.should eql 0
UserMailer.deliveries.length.should eql 2 # one for student, one for teacher
end
it "works (school on school)" do
# get user and teacher into same school
user.school = school
user.save!
teacher.school = school
teacher.save!
# user has no test drives, no credit card on file, but attempts to book a lesson
booking = LessonBooking.book_normal(user, teacher_user, valid_single_slots, "Hey I've heard of you before.", false, LessonBooking::PAYMENT_STYLE_SINGLE, 60)
booking.errors.any?.should be_false
booking.school.should be_true
booking.card_presumed_ok.should be_false
booking.user.should eql user
user.unprocessed_normal_lesson.should eql []
booking.sent_notices.should be_false
booking.booked_price.should eql 30.00
booking.is_requested?.should be_true
booking.sent_notices.should be_true
lesson.music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
LessonPaymentCharge.count.should eql 0
user.reload
user.stripe_customer_id.should_not be nil
user.remaining_test_drives.should eql 0
user.lesson_purchases.length.should eql 0
customer = Stripe::Customer.retrieve(user.stripe_customer_id)
customer.email.should eql user.email
booking.lesson_sessions.length.should eql 1
lesson_session = booking.lesson_sessions[0]
lesson_session.status.should eql LessonBooking::STATUS_REQUESTED
booking.status.should eql LessonBooking::STATUS_REQUESTED
######### Teacher counters with new slot
teacher_countered_slot = FactoryGirl.build(:lesson_booking_slot_single, hour: 14)
UserMailer.deliveries.clear
lesson_session.counter({proposer: teacher_user, slot: teacher_countered_slot, message: 'Does this work?'})
booking.reload
booking.errors.any?.should be false
lesson_session.lesson_booking.errors.any?.should be false
lesson_session.lesson_booking_slots.length.should eql 1
lesson_session.lesson_booking_slots[0].proposer.should eql teacher_user
teacher_counter = lesson_session.lesson_booking_slots.order(:created_at).last
teacher_counter.should eql teacher_countered_slot
teacher_counter.proposer.should eql teacher_user
booking.lesson_booking_slots.length.should eql 3
UserMailer.deliveries.length.should eql 1
chat = ChatMessage.unscoped.order(:created_at).last
chat.channel.should eql ChatMessage::CHANNEL_LESSON
chat.message.should eql 'Does this work?'
chat.user.should eql teacher_user
chat.target_user.should eql user
notification = Notification.unscoped.order(:created_at).last
notification.session_id.should eql lesson_session.music_session.id
notification.student_directed.should eql true
notification.purpose.should eql 'counter'
notification.description.should eql NotificationTypes::LESSON_MESSAGE
######### Student counters with new slot
student_countered_slot = FactoryGirl.build(:lesson_booking_slot_single, hour: 16)
UserMailer.deliveries.clear
lesson_session.counter({proposer: user, slot: student_countered_slot, message: 'Does this work better?'})
lesson_session.errors.any?.should be false
lesson_session.lesson_booking.errors.any?.should be false
lesson_session.lesson_booking_slots.length.should eql 2
student_counter = booking.lesson_booking_slots.order(:created_at).last
student_counter.proposer.should eql user
booking.reload
booking.lesson_booking_slots.length.should eql 4
UserMailer.deliveries.length.should eql 1
chat = ChatMessage.unscoped.order(:created_at).last
chat.message.should eql 'Does this work better?'
chat.channel.should eql ChatMessage::CHANNEL_LESSON
chat.user.should eql user
chat.target_user.should eql teacher_user
notification = Notification.unscoped.order(:created_at).last
notification.session_id.should eql lesson_session.music_session.id
notification.student_directed.should eql false
notification.purpose.should eql 'counter'
notification.description.should eql NotificationTypes::LESSON_MESSAGE
######## Teacher accepts slot
UserMailer.deliveries.clear
lesson_session.accept({message: 'Yeah I got this', slot: student_counter.id, update_all: false})
lesson_session.errors.any?.should be_false
lesson_session.reload
lesson_session.slot.should eql student_counter
lesson_session.status.should eql LessonSession::STATUS_APPROVED
booking.reload
booking.default_slot.should eql student_counter
lesson_session.music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
booking.status.should eql LessonBooking::STATUS_APPROVED
UserMailer.deliveries.length.should eql 2
chat = ChatMessage.unscoped.order(:created_at).last
chat.message.should eql 'Yeah I got this'
chat.purpose.should eql 'Lesson Approved'
chat.channel.should eql ChatMessage::CHANNEL_LESSON
chat.user.should eql teacher_user
chat.target_user.should eql user
notification = Notification.unscoped.order(:created_at).last
notification.session_id.should eql lesson_session.music_session.id
notification.student_directed.should eql true
notification.purpose.should eql 'accept'
notification.description.should eql NotificationTypes::LESSON_MESSAGE
# teacher & student get into session
start = lesson_session.scheduled_start
end_time = lesson_session.scheduled_start + (60 * lesson_session.duration)
uh2 = FactoryGirl.create(:music_session_user_history, user: teacher_user, history: lesson_session.music_session, created_at: start, session_removed_at: end_time)
# artificially end the session, which is covered by other background jobs
lesson_session.music_session.session_removed_at = end_time
lesson_session.music_session.save!
Timecop.travel(end_time + 1)
UserMailer.deliveries.clear
# background code comes around and analyses the session
LessonSession.hourly_check
lesson_session.reload
lesson_session.analysed.should be_true
analysis = JSON.parse(lesson_session.analysis)
analysis["reason"].should eql LessonSessionAnalyser::STUDENT_FAULT
analysis["student"].should eql LessonSessionAnalyser::NO_SHOW
if lesson_session.billing_error_detail
puts "testdrive flow #{lesson_session.billing_error_detail}" # this should not occur, but helps a great deal if a regression occurs and running all the tests
end
lesson_session.billed.should be true
user.reload
user.lesson_purchases.length.should eql 1
lesson_purchase = user.lesson_purchases[0]
lesson_purchase.price.should eql 30.00
lesson_purchase.lesson_package_type.is_normal?.should eql true
lesson_purchase.price_in_cents.should eql 3000
user.sales.length.should eql 1
sale = user.sales.first
sale.stripe_charge_id.should_not be_nil
sale.recurly_tax_in_cents.should eql (100 * booking.booked_price.to_f * 0.0825).round.to_i
sale.recurly_total_in_cents.should eql ((100 * booking.booked_price.to_f * 0.0825).round + 100 * booking.booked_price.to_f).to_i
sale.recurly_subtotal_in_cents.should eql (100 * booking.booked_price).to_i
sale.recurly_currency.should eql 'USD'
sale.stripe_charge_id.should_not be_nil
line_item = sale.sale_line_items[0]
line_item.quantity.should eql 1
line_item.product_type.should eql SaleLineItem::LESSON
line_item.product_id.should eq LessonPackageType.single.id
line_item.lesson_package_purchase.should eql lesson_purchase
lesson_purchase.sale_line_item.should eql line_item
lesson.amount_charged.should eql (sale.recurly_total_in_cents / 100.0).to_f
lesson_session.billing_error_reason.should be_nil
lesson_session.sent_billing_notices.should be true
user.reload
user.remaining_test_drives.should eql 0
UserMailer.deliveries.length.should eql 2 # one for student, one for teacher
LessonPaymentCharge.count.should eql 0
TeacherDistribution.count.should eql 0
end
end

View File

@ -17,7 +17,8 @@ teacherActions = window.JK.Actions.Teacher
lesson.me = me
lesson.other = other
lesson.isAdmin = context.JK.currentUserAdmin
lesson.cardNotOk = !lesson.lesson_booking.card_presumed_ok
lesson.schoolOnSchool = lesson['school_on_school?']
lesson.cardNotOk = !lesson.schoolOnSchool && !lesson.lesson_booking.card_presumed_ok
if (lesson.status == 'requested' || lesson.status == 'countered')
lesson.isRequested = true

View File

@ -2,7 +2,7 @@ object @lesson_session
attributes :id, :lesson_booking_id, :lesson_type, :duration, :price, :teacher_complete, :student_complete,
: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
:teacher_canceled_reason, :status, :success, :teacher_unread_messages, :student_unread_messages, :is_active?, :recurring, :analysed, :school_on_school?
node do |lesson_session|
{