require 'spec_helper' describe Sale do let(:user) { FactoryGirl.create(:user) } let(:user2) { FactoryGirl.create(:user) } let(:jam_track) { FactoryGirl.create(:jam_track) } let(:jam_track2) { FactoryGirl.create(:jam_track) } let(:jam_track3) { FactoryGirl.create(:jam_track) } let(:gift_card) { GiftCardType.jam_track_5 } let(:posa_card) {FactoryGirl.create(:posa_card)} let(:retailer) {FactoryGirl.create(:retailer)} after(:each) { Timecop.return } def assert_free_line_item(sale_line_item, jamtrack) sale_line_item.recurly_tax_in_cents.should be_nil sale_line_item.recurly_total_in_cents.should be_nil sale_line_item.recurly_currency.should be_nil sale_line_item.recurly_discount_in_cents.should be_nil sale_line_item.product_type.should eq(JamTrack::PRODUCT_TYPE) sale_line_item.unit_price.should eq(jamtrack.price) sale_line_item.quantity.should eq(1) sale_line_item.free.should eq(1) sale_line_item.sales_tax.should be_nil sale_line_item.shipping_handling.should eq(0) sale_line_item.recurly_plan_code.should eq(jamtrack.plan_code) sale_line_item.product_id.should eq(jamtrack.id) end describe "posa_cards" do it "works" do posa_card.card_type.should eql PosaCard::JAM_TRACKS_5 result = Sale.posa_activate(posa_card, retailer) posa_card.errors.any?.should be false posa_card.activated_at.should_not be_nil sale = result[:sale] sale = Sale.find(sale.id) sale.sale_line_items.count.should eql 1 sale_line_item = sale.sale_line_items.first sale.retailer.should eql retailer sale.sale_type.should eql Sale::POSA_SALE sale_line_item.retailer.should eql retailer sale_line_item.unit_price.should eql 9.99 # sale_line_item.quantity.should eql 1 end it "already activated" do result = Sale.posa_activate(posa_card, retailer) posa_card.activated_at.should_not be_nil posa_card.errors.any?.should be false sale = result[:sale] result2 = Sale.posa_activate(posa_card, retailer) posa_card.activated_at.should_not be_nil posa_card.errors.any?.should be true result2[:sale].should be_nil posa_card.errors[:activated_at].should eq ["already activated. Please give card to customer. Thank you!"] end end describe "index" do it "empty" do result = Sale.index(user) result[:query].length.should eq(0) result[:next].should eq(nil) end it "one" do sale = Sale.create_jam_track_sale(user) shopping_cart = ShoppingCart.create(user, jam_track) sale_line_item = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, 'some_adjustment_uuid', nil) result = Sale.index(user) result[:query].length.should eq(1) result[:next].should eq(nil) end it "user filtered correctly" do sale = Sale.create_jam_track_sale(user) shopping_cart = ShoppingCart.create(user, jam_track) sale_line_item = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, 'some_adjustment_uuid', nil) result = Sale.index(user) result[:query].length.should eq(1) result[:next].should eq(nil) sale2 = Sale.create_jam_track_sale(user2) shopping_cart = ShoppingCart.create(user2, jam_track) sale_line_item2 = SaleLineItem.create_from_shopping_cart(sale2, shopping_cart, nil, 'some_adjustment_uuid', nil) result = Sale.index(user) result[:query].length.should eq(1) result[:next].should eq(nil) end end describe "place_order" do let(:user) { FactoryGirl.create(:user) } let(:jamtrack) { FactoryGirl.create(:jam_track) } let(:jamtrack2) { FactoryGirl.create(:jam_track) } let(:jamtrack3) { FactoryGirl.create(:jam_track) } let(:jamtrack4) { FactoryGirl.create(:jam_track) } let(:jam_track_price_in_cents) { (jamtrack.price * 100).to_i } let(:gift_card_price_in_cents) { (gift_card.price * 100).to_i } let(:client) { RecurlyClient.new } let(:billing_info) { info = {} info[:first_name] = user.first_name info[:last_name] = user.last_name info[:address1] = 'Test Address 1' info[:address2] = 'Test Address 2' info[:city] = user.city info[:state] = user.state info[:country] = user.country info[:zip] = '12345' info[:number] = '4111-1111-1111-1111' info[:month] = '08' info[:year] = '2017' info[:verification_value] = '111' info } after(:each) do if user.recurly_code account = Recurly::Account.find(user.recurly_code) if account.present? account.destroy end end end it "for a gift card" do shopping_cart = ShoppingCart.create user, gift_card, 1, false client.find_or_create_account(user, billing_info) sales = Sale.place_order(user, [shopping_cart]) user.reload user.sales.length.should eq(1) sales.should eq(user.sales) sale = sales[0] sale.recurly_invoice_id.should_not be_nil sale.recurly_subtotal_in_cents.should eq(gift_card_price_in_cents) sale.recurly_tax_in_cents.should eq(0) sale.recurly_total_in_cents.should eq(gift_card_price_in_cents) sale.recurly_currency.should eq('USD') sale.order_total.should eq(gift_card.price) sale.sale_line_items.length.should == 1 sale_line_item = sale.sale_line_items[0] # validate we are storing pricing info from recurly sale_line_item.recurly_tax_in_cents.should eq(0) sale_line_item.recurly_total_in_cents.should eq(gift_card_price_in_cents) sale_line_item.recurly_currency.should eq('USD') sale_line_item.recurly_discount_in_cents.should eq(0) sale_line_item.product_type.should eq(GiftCardType::PRODUCT_TYPE) sale_line_item.unit_price.should eq(gift_card.price) sale_line_item.quantity.should eq(1) sale_line_item.free.should eq(0) sale_line_item.sales_tax.should be_nil sale_line_item.shipping_handling.should eq(0) sale_line_item.recurly_plan_code.should eq(gift_card.plan_code) sale_line_item.product_id.should eq(gift_card.id) sale_line_item.recurly_subscription_uuid.should be_nil sale_line_item.recurly_adjustment_uuid.should_not be_nil sale_line_item.recurly_adjustment_credit_uuid.should be_nil sale_line_item.recurly_adjustment_uuid.should_not be_nil # verify subscription is in Recurly recurly_account = client.get_account(user) adjustments = recurly_account.adjustments adjustments.should_not be_nil adjustments.should have(1).items purchase= adjustments[0] purchase.unit_amount_in_cents.should eq((gift_card.price * 100).to_i) purchase.accounting_code.should eq(ShoppingCart::PURCHASE_NORMAL) purchase.description.should eq("JamTracks Gift Card (5)") purchase.state.should eq('invoiced') purchase.uuid.should eq(sale_line_item.recurly_adjustment_uuid) sleep 2 invoices = recurly_account.invoices invoices.should have(1).items invoice = invoices[0] invoice.uuid.should eq(sale.recurly_invoice_id) invoice.line_items.should have(1).items # should have single adjustment associated invoice.line_items[0].should eq(purchase) invoice.subtotal_in_cents.should eq((gift_card.price * 100).to_i) invoice.total_in_cents.should eq((gift_card.price * 100).to_i) #invoice.state.should eq('collected') # verify jam_track_rights data user.gift_card_purchases.should_not be_nil user.gift_card_purchases.should have(1).items user.gift_card_purchases.last.gift_card_type.should eq(GiftCardType.jam_track_5) user.has_redeemable_jamtrack.should be_true sale_line_item.affiliate_referral.should be_nil sale_line_item.affiliate_referral_fee_in_cents.should be_nil end it "for a free jam track" do shopping_cart = ShoppingCart.create user, jamtrack, 1, true client.find_or_create_account(user, billing_info) sales = Sale.place_order(user, [shopping_cart]) user.reload user.sales.length.should eq(1) sales.should eq(user.sales) sale = sales[0] sale.recurly_invoice_id.should be_nil sale.recurly_subtotal_in_cents.should eq(0) sale.recurly_tax_in_cents.should eq(0) sale.recurly_total_in_cents.should eq(0) sale.recurly_currency.should eq('USD') sale.order_total.should eq(0) sale.sale_line_items.length.should == 1 sale_line_item = sale.sale_line_items[0] sale_line_item.recurly_tax_in_cents.should eq(0) sale_line_item.recurly_total_in_cents.should eq(0) sale_line_item.recurly_currency.should eq('USD') sale_line_item.recurly_discount_in_cents.should eq(0) sale_line_item.product_type.should eq(JamTrack::PRODUCT_TYPE) sale_line_item.unit_price.should eq(jamtrack.price) sale_line_item.quantity.should eq(1) sale_line_item.free.should eq(1) sale_line_item.sales_tax.should be_nil sale_line_item.shipping_handling.should eq(0) sale_line_item.recurly_plan_code.should eq(jamtrack.plan_code) sale_line_item.product_id.should eq(jamtrack.id) sale_line_item.recurly_subscription_uuid.should be_nil sale_line_item.recurly_adjustment_uuid.should be_nil sale_line_item.recurly_adjustment_credit_uuid.should be_nil sale_line_item.recurly_adjustment_uuid.should eq(user.jam_track_rights.last.recurly_adjustment_uuid) sale_line_item.recurly_adjustment_credit_uuid.should eq(user.jam_track_rights.last.recurly_adjustment_credit_uuid) # verify subscription is in Recurly recurly_account = client.get_account(user) adjustments = recurly_account.adjustments adjustments.should_not be_nil adjustments.should have(0).items invoices = recurly_account.invoices invoices.should have(0).items # verify jam_track_rights data user.jam_track_rights.should_not be_nil user.jam_track_rights.should have(1).items user.jam_track_rights.last.jam_track.id.should eq(jamtrack.id) user.jam_track_rights.last.redeemed.should be_true user.has_redeemable_jamtrack.should be_false end it "for two jamtracks 1 freebie, 1 purchased" do user.gifted_jamtracks = 2 user.save! jamtrack.allow_free = false jamtrack.price =2.99 jamtrack.save! shopping_cart1 = ShoppingCart.create user, jamtrack, 1, false shopping_cart2 = ShoppingCart.create user, jamtrack2, 1, true client.find_or_create_account(user, billing_info) sales = Sale.place_order(user, [shopping_cart1, shopping_cart2]) user.reload user.sales.length.should eq(1) sale = sales[0] sale.reload sale.recurly_invoice_id.should_not be_nil sale.recurly_subtotal_in_cents.should eq(jamtrack.price * 100) sale.recurly_tax_in_cents.should eq(0) sale.recurly_total_in_cents.should eq(jamtrack.price * 100) sale.recurly_currency.should eq('USD') sale.order_total.should eq(jamtrack.price) sale.sale_line_items.length.should == 2 sale.sale_line_items[0].free.should eql 0 assert_free_line_item(sale.sale_line_items[1], jamtrack2) # verify jam_track_rights data right1 = JamTrackRight.where(user_id: user.id).where(jam_track_id: jamtrack.id).first right2 = JamTrackRight.where(user_id: user.id).where(jam_track_id: jamtrack2.id).first user.jam_track_rights.should have(2).items right1.redeemed.should be_false right2.redeemed.should be_true user.has_redeemable_jamtrack.should be_false user.gifted_jamtracks.should eq(2) end it "for two jam tracks (1 freebie, 1 gifted), then 1 gifted/1 pay" do user.gifted_jamtracks = 2 user.save! shopping_cart1 = ShoppingCart.create user, jamtrack, 1, true shopping_cart2 = ShoppingCart.create user, jamtrack2, 1, true client.find_or_create_account(user, billing_info) sales = Sale.place_order(user, [shopping_cart1, shopping_cart2]) user.reload user.sales.length.should eq(1) sale = sales[0] sale.reload sale.recurly_invoice_id.should be_nil sale.recurly_subtotal_in_cents.should eq(0) sale.recurly_tax_in_cents.should eq(0) sale.recurly_total_in_cents.should eq(0) sale.recurly_currency.should eq('USD') sale.order_total.should eq(0) sale.sale_line_items.length.should == 2 assert_free_line_item(sale.sale_line_items[0], jamtrack) assert_free_line_item(sale.sale_line_items[1], jamtrack2) # verify jam_track_rights data right1 = JamTrackRight.where(user_id: user.id).where(jam_track_id: jamtrack.id).first right2 = JamTrackRight.where(user_id: user.id).where(jam_track_id: jamtrack2.id).first user.jam_track_rights.should have(2).items right1.redeemed.should be_true right2.redeemed.should be_true user.has_redeemable_jamtrack.should be_false user.gifted_jamtracks.should eq(1) # OK! Now make a second purchase; this time, buy one free, one not free shopping_cart3 = ShoppingCart.create user, jamtrack3, 1, true client.find_or_create_account(user, billing_info) sales = Sale.place_order(user, [shopping_cart3]) user.reload user.sales.length.should eq(2) sale = sales[0] sale.reload sale.recurly_invoice_id.should be_nil sale.recurly_subtotal_in_cents.should eq(0) sale.recurly_tax_in_cents.should eq(0) sale.recurly_total_in_cents.should eq(0) sale.recurly_currency.should eq('USD') sale.order_total.should eq(0) sale.sale_line_items.length.should == 1 assert_free_line_item(sale.sale_line_items[0], jamtrack3) end it "for a free jam track with an affiliate association" do partner = FactoryGirl.create(:affiliate_partner) user.affiliate_referral = partner user.save! shopping_cart = ShoppingCart.create user, jamtrack, 1, true client.find_or_create_account(user, billing_info) sales = Sale.place_order(user, [shopping_cart]) user.reload user.sales.length.should eq(1) sales.should eq(user.sales) sale = sales[0] sale.recurly_invoice_id.should be_nil sale.recurly_subtotal_in_cents.should eq(0) sale.recurly_tax_in_cents.should eq(0) sale.recurly_total_in_cents.should eq(0) sale.recurly_currency.should eq('USD') sale.order_total.should eq(0) sale.sale_line_items.length.should == 1 sale_line_item = sale.sale_line_items[0] sale_line_item.recurly_tax_in_cents.should eq(0) sale_line_item.recurly_total_in_cents.should eq(0) sale_line_item.recurly_currency.should eq('USD') sale_line_item.recurly_discount_in_cents.should eq(0) sale_line_item.product_type.should eq(JamTrack::PRODUCT_TYPE) sale_line_item.unit_price.should eq(jamtrack.price) sale_line_item.quantity.should eq(1) sale_line_item.free.should eq(1) sale_line_item.sales_tax.should be_nil sale_line_item.shipping_handling.should eq(0) sale_line_item.recurly_plan_code.should eq(jamtrack.plan_code) sale_line_item.product_id.should eq(jamtrack.id) sale_line_item.recurly_subscription_uuid.should be_nil sale_line_item.recurly_adjustment_uuid.should be_nil sale_line_item.recurly_adjustment_credit_uuid.should be_nil sale_line_item.recurly_adjustment_uuid.should eq(user.jam_track_rights.last.recurly_adjustment_uuid) sale_line_item.recurly_adjustment_credit_uuid.should eq(user.jam_track_rights.last.recurly_adjustment_credit_uuid) sale_line_item.affiliate_referral.should eq(partner) sale_line_item.affiliate_referral_fee_in_cents.should eq(0) # verify subscription is in Recurly recurly_account = client.get_account(user) adjustments = recurly_account.adjustments adjustments.should_not be_nil adjustments.should have(0).items invoices = recurly_account.invoices invoices.should have(0).items # verify jam_track_rights data user.jam_track_rights.should_not be_nil user.jam_track_rights.should have(1).items user.jam_track_rights.last.jam_track.id.should eq(jamtrack.id) user.jam_track_rights.last.redeemed.should be_true user.has_redeemable_jamtrack.should be_false end it "for a normally priced jam track", intermittent: true do # intermittent: sometimes recurly won't mark it 'collected' soon enough for the test to pass user.has_redeemable_jamtrack = false user.save! shopping_cart = ShoppingCart.create user, jamtrack, 1, false client.find_or_create_account(user, billing_info) sales = Sale.place_order(user, [shopping_cart]) user.reload user.sales.length.should eq(1) sales.should eq(user.sales) sale = sales[0] sale.recurly_invoice_id.should_not be_nil sale.recurly_subtotal_in_cents.should eq(jam_track_price_in_cents) sale.recurly_tax_in_cents.should eq(0) sale.recurly_total_in_cents.should eq(jam_track_price_in_cents) sale.recurly_currency.should eq('USD') sale.order_total.should eq(jamtrack.price) sale.sale_line_items.length.should == 1 sale_line_item = sale.sale_line_items[0] # validate we are storing pricing info from recurly sale_line_item.recurly_tax_in_cents.should eq(0) sale_line_item.recurly_total_in_cents.should eq(jam_track_price_in_cents) sale_line_item.recurly_currency.should eq('USD') sale_line_item.recurly_discount_in_cents.should eq(0) sale_line_item.product_type.should eq(JamTrack::PRODUCT_TYPE) sale_line_item.unit_price.should eq(jamtrack.price) sale_line_item.quantity.should eq(1) sale_line_item.free.should eq(0) sale_line_item.sales_tax.should be_nil sale_line_item.shipping_handling.should eq(0) sale_line_item.recurly_plan_code.should eq(jamtrack.plan_code) sale_line_item.product_id.should eq(jamtrack.id) sale_line_item.recurly_subscription_uuid.should be_nil sale_line_item.recurly_adjustment_uuid.should_not be_nil sale_line_item.recurly_adjustment_credit_uuid.should be_nil sale_line_item.recurly_adjustment_uuid.should eq(user.jam_track_rights.last.recurly_adjustment_uuid) # verify subscription is in Recurly recurly_account = client.get_account(user) adjustments = recurly_account.adjustments adjustments.should_not be_nil adjustments.should have(1).items purchase= adjustments[0] purchase.unit_amount_in_cents.should eq((jamtrack.price * 100).to_i) purchase.accounting_code.should eq(ShoppingCart::PURCHASE_NORMAL) purchase.description.should eq("JamTrack: " + jamtrack.name + ' - FOR USE ONLY WITHIN APP') purchase.state.should eq('invoiced') purchase.uuid.should eq(sale_line_item.recurly_adjustment_uuid) sleep 2 invoices = recurly_account.invoices invoices.should have(1).items invoice = invoices[0] invoice.uuid.should eq(sale.recurly_invoice_id) invoice.line_items.should have(1).items # should have single adjustment associated invoice.line_items[0].should eq(purchase) invoice.subtotal_in_cents.should eq((jamtrack.price * 100).to_i) invoice.total_in_cents.should eq((jamtrack.price * 100).to_i) #invoice.state.should eq('collected') # verify jam_track_rights data user.jam_track_rights.should_not be_nil user.jam_track_rights.should have(1).items user.jam_track_rights.last.jam_track.id.should eq(jamtrack.id) user.jam_track_rights.last.redeemed.should be_false user.has_redeemable_jamtrack.should be_false sale_line_item.affiliate_referral.should be_nil sale_line_item.affiliate_referral_fee_in_cents.should be_nil end it "for a normally priced jam track with an affiliate association" do user.has_redeemable_jamtrack = false partner = FactoryGirl.create(:affiliate_partner) user.affiliate_referral = partner user.save! shopping_cart = ShoppingCart.create user, jamtrack, 1, false client.find_or_create_account(user, billing_info) sales = Sale.place_order(user, [shopping_cart]) user.reload user.sales.length.should eq(1) sales.should eq(user.sales) sale = sales[0] sale.recurly_invoice_id.should_not be_nil sale.recurly_subtotal_in_cents.should eq(jam_track_price_in_cents) sale.recurly_tax_in_cents.should eq(0) sale.recurly_total_in_cents.should eq(jam_track_price_in_cents) sale.recurly_currency.should eq('USD') sale.order_total.should eq(jamtrack.price) sale.sale_line_items.length.should == 1 sale_line_item = sale.sale_line_items[0] # validate we are storing pricing info from recurly sale_line_item.recurly_tax_in_cents.should eq(0) sale_line_item.recurly_total_in_cents.should eq(jam_track_price_in_cents) sale_line_item.recurly_currency.should eq('USD') sale_line_item.recurly_discount_in_cents.should eq(0) sale_line_item.product_type.should eq(JamTrack::PRODUCT_TYPE) sale_line_item.unit_price.should eq(jamtrack.price) sale_line_item.quantity.should eq(1) sale_line_item.free.should eq(0) sale_line_item.sales_tax.should be_nil sale_line_item.shipping_handling.should eq(0) sale_line_item.recurly_plan_code.should eq(jamtrack.plan_code) sale_line_item.product_id.should eq(jamtrack.id) sale_line_item.recurly_subscription_uuid.should be_nil sale_line_item.recurly_adjustment_uuid.should_not be_nil sale_line_item.recurly_adjustment_credit_uuid.should be_nil sale_line_item.recurly_adjustment_uuid.should eq(user.jam_track_rights.last.recurly_adjustment_uuid) sale_line_item.affiliate_referral.should eq(partner) sale_line_item.affiliate_referral_fee_in_cents.should eq(20) # verify subscription is in Recurly recurly_account = client.get_account(user) adjustments = recurly_account.adjustments adjustments.should_not be_nil adjustments.should have(1).items purchase= adjustments[0] purchase.unit_amount_in_cents.should eq((jamtrack.price * 100).to_i) purchase.accounting_code.should eq(ShoppingCart::PURCHASE_NORMAL) purchase.description.should eq("JamTrack: " + jamtrack.name + " - FOR USE ONLY WITHIN APP") purchase.state.should eq('invoiced') purchase.uuid.should eq(sale_line_item.recurly_adjustment_uuid) sleep 2 invoices = recurly_account.invoices invoices.should have(1).items invoice = invoices[0] invoice.uuid.should eq(sale.recurly_invoice_id) invoice.line_items.should have(1).items # should have single adjustment associated invoice.line_items[0].should eq(purchase) invoice.subtotal_in_cents.should eq((jamtrack.price * 100).to_i) invoice.total_in_cents.should eq((jamtrack.price * 100).to_i) #invoice.state.should eq('collected') # verify jam_track_rights data user.jam_track_rights.should_not be_nil user.jam_track_rights.should have(1).items user.jam_track_rights.last.jam_track.id.should eq(jamtrack.id) user.jam_track_rights.last.redeemed.should be_false user.has_redeemable_jamtrack.should be_false end it "for a jamtrack already owned" do shopping_cart = ShoppingCart.create user, jamtrack, 1, true client.find_or_create_account(user, billing_info) sales = Sale.place_order(user, [shopping_cart]) user.reload user.sales.length.should eq(1) shopping_cart = ShoppingCart.create user, jamtrack, 1, false sales = Sale.place_order(user, [shopping_cart]) sales.should have(0).items # also, verify that no earlier adjustments were affected recurly_account = client.get_account(user) adjustments = recurly_account.adjustments adjustments.should have(0).items # because the only successful purchase was a freebie, there should be no recurly adjustments end # this test counts on the fact that two adjustments are made when buying a free JamTrack # so if we make the second adjustment invalid from Recurly's standpoint, then # we can see if the first one is ultimately destroyed it "rolls back created adjustments if error" do shopping_cart = ShoppingCart.create user, jamtrack, 1, false # grab the real response; we will modify it to make a nil accounting code adjustment_attrs = shopping_cart.create_adjustment_attributes(user) client.find_or_create_account(user, billing_info) adjustment_attrs[0][:unit_amount_in_cents] = nil # invalid amount ShoppingCart.any_instance.stub(:create_adjustment_attributes).and_return(adjustment_attrs) expect { Sale.place_order(user, [shopping_cart]) }.to raise_error(JamRuby::RecurlyClientError) user.reload user.sales.should have(0).items recurly_account = client.get_account(user) recurly_account.adjustments.should have(0).items end it "rolls back adjustments created before the order" do shopping_cart = ShoppingCart.create user, jamtrack, 1, false client.find_or_create_account(user, billing_info) # create a single adjustment on the account adjustment_attrs = shopping_cart.create_adjustment_attributes(user) recurly_account = client.get_account(user) adjustment = recurly_account.adjustments.new (adjustment_attrs[0]) adjustment.save adjustment.errors.any?.should be_false sales = Sale.place_order(user, [shopping_cart]) user.reload recurly_account = client.get_account(user) adjustments = recurly_account.adjustments adjustments.should have(1).items # two adjustments are created for a free jamtrack; that should be all there is end end describe "lessons" do let(:teacher_user) { FactoryGirl.create(:teacher_user) } let(:teacher) { teacher_user.teacher } let(:lesson_booking_slot_single1) { FactoryGirl.build(:lesson_booking_slot_single) } let(:lesson_booking_slot_single2) { FactoryGirl.build(:lesson_booking_slot_single) } let(:lesson_booking_slot_recurring1) { FactoryGirl.build(:lesson_booking_slot_recurring) } let(:lesson_booking_slot_recurring2) { FactoryGirl.build(:lesson_booking_slot_recurring) } let(:valid_single_slots) { [lesson_booking_slot_single1, lesson_booking_slot_single2] } let(:valid_recurring_slots) { [lesson_booking_slot_recurring1, lesson_booking_slot_recurring2] } let(:affiliate_partner) { FactoryGirl.create(:affiliate_partner) } let(:affiliate_partner2) { FactoryGirl.create(:affiliate_partner, lesson_rate: 0.30) } describe "single" do it "can succeed" do token = create_stripe_token result = user.payment_update({token: token, zip: '72205', normal: true}) lesson_session = normal_lesson(user, teacher_user) # 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) # bill the user LessonSession.hourly_check lesson_session.reload payment = lesson_session.lesson_payment_charge user.sales.count.should eql 1 sale = user.sales.first sale.stripe_charge_id.should_not be_nil sale.recurly_tax_in_cents.should be 0 sale.recurly_total_in_cents.should eql 3000 sale.recurly_subtotal_in_cents.should eql 3000 sale.recurly_currency.should eql 'USD' 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 user.reload user.stripe_customer_id.should_not be nil user.lesson_purchases.length.should eql 1 user.remaining_test_drives.should eql 0 lesson_purchase = user.lesson_purchases[0] lesson_purchase.price.should eql 30.00 lesson_purchase.lesson_package_type.is_normal?.should eql true customer = Stripe::Customer.retrieve(user.stripe_customer_id) customer.email.should eql user.email sale.sale_line_items.count.should eql 1 line_item = sale.sale_line_items[0] line_item.reload line_item.affiliate_distributions.count.should eql 0 end it "affiliate" do user.affiliate_referral = affiliate_partner user.save! teacher_user.affiliate_referral = affiliate_partner2 teacher_user.save! token = create_stripe_token result = user.payment_update({token: token, zip: '78759', normal: true}) lesson_session = normal_lesson(user, teacher_user) # 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) # bill the user LessonSession.hourly_check lesson_session.reload payment = lesson_session.lesson_payment_charge puts lesson_session.billing_error_reason puts lesson_session.billing_error_detail user.reload user.sales.count.should eql 1 sale = user.sales.first sale.stripe_charge_id.should_not be_nil sale.recurly_tax_in_cents.should be 248 sale.recurly_total_in_cents.should eql 3248 sale.recurly_subtotal_in_cents.should eql 3000 sale.recurly_currency.should eql 'USD' 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 user.reload user.stripe_customer_id.should_not be nil user.lesson_purchases.length.should eql 1 user.remaining_test_drives.should eql 0 lesson_purchase = user.lesson_purchases[0] lesson_purchase.price.should eql 30.00 lesson_purchase.lesson_package_type.is_normal?.should eql true customer = Stripe::Customer.retrieve(user.stripe_customer_id) customer.email.should eql user.email sale.sale_line_items.count.should eql 1 line_item = sale.sale_line_items[0] line_item.reload line_item.affiliate_distributions.count.should eql 2 affiliate_partner.reload affiliate_partner2.reload affiliate_partner.affiliate_distributions.count.should eql 1 affiliate_partner2.affiliate_distributions.count.should eql 1 partner1_distribution = affiliate_partner.affiliate_distributions.first partner2_distribution = affiliate_partner2.affiliate_distributions.first partner1_distribution.sale_line_item.should eql partner2_distribution.sale_line_item partner1_distribution.affiliate_referral_fee_in_cents.should eql (3000 * 0.25 * affiliate_partner.lesson_rate).round partner2_distribution.affiliate_referral_fee_in_cents.should eql (3000 * 0.25 * affiliate_partner2.lesson_rate).round end it "book recurring, monthly" do end end describe "purchase_test_drive" do it "can succeed" do user.affiliate_referral = affiliate_partner user.save! teacher_user.affiliate_referral = affiliate_partner2 teacher_user.save! booking = LessonBooking.book_test_drive(user, teacher_user, valid_single_slots, "Hey I've heard of you before.") booking.errors.any?.should be_false booking.user.should eql user booking.card_presumed_ok.should be_false booking.should eql user.unprocessed_test_drive token = create_stripe_token result = user.payment_update({token: token, zip: '72205', test_drive: true, booking_id: booking.id}) booking.reload booking.card_presumed_ok.should be_true user.sales.count.should eql 1 sale = result[:test_drive] sale.stripe_charge_id.should_not be_nil sale.recurly_tax_in_cents.should be 0 sale.recurly_total_in_cents.should eql 4999 sale.recurly_subtotal_in_cents.should eql 4999 sale.recurly_currency.should eql 'USD' line_item = sale.sale_line_items[0] line_item.quantity.should eql 1 line_item.product_type.should eql SaleLineItem::LESSON line_item.product_id.should eq LessonPackageType.test_drive_4.id user.reload user.stripe_customer_id.should_not be nil user.lesson_purchases.length.should eql 1 user.remaining_test_drives.should eql 3 lesson_purchase = user.lesson_purchases[0] lesson_purchase.price.should eql 49.99 lesson_purchase.lesson_package_type.is_test_drive?.should eql true customer = Stripe::Customer.retrieve(user.stripe_customer_id) customer.email.should eql user.email sale.sale_line_items.count.should eql 1 line_item = sale.sale_line_items[0] line_item.reload line_item.affiliate_distributions.count.should eql 0 # test drives don't create affiliate end it "can succeed with tax" do #user.remaining_test_drives = 0 #user.save! booking = LessonBooking.book_test_drive(user, teacher_user, valid_single_slots, "Hey I've heard of you before.") booking.errors.any?.should be_false booking.user.should eql user booking.card_presumed_ok.should be_false booking.should eql user.unprocessed_test_drive user.reload user.remaining_test_drives.should eql 0 token = create_stripe_token result = user.payment_update({token: token, zip: '78759', test_drive: true, booking_id: booking.id}) booking.reload booking.card_presumed_ok.should be_true user.sales.count.should eql 1 sale = result[:test_drive] sale.stripe_charge_id.should_not be_nil sale.recurly_tax_in_cents.should be (4999 * 0.0825).round sale.recurly_total_in_cents.should eql 4999 + (4999 * 0.0825).round sale.recurly_subtotal_in_cents.should eql 4999 sale.recurly_currency.should eql 'USD' line_item = sale.sale_line_items[0] line_item.quantity.should eql 1 line_item.product_type.should eql SaleLineItem::LESSON line_item.product_id.should eq LessonPackageType.test_drive_4.id user.reload user.stripe_customer_id.should_not be nil user.lesson_purchases.length.should eql 1 lesson_purchase = booking.lesson_sessions[0].lesson_package_purchase user.remaining_test_drives.should eql 3 lesson_purchase = user.lesson_purchases[0] lesson_purchase.price.should eql 49.99 lesson_purchase.lesson_package_type.is_test_drive?.should eql true customer = Stripe::Customer.retrieve(user.stripe_customer_id) customer.email.should eql user.email booking.lesson_sessions[0].accept({message: "got it", slot: booking.lesson_booking_slots[0].id}) user.reload user.remaining_test_drives.should eql 3 line_item.affiliate_distributions.count.should eql 0 # test drives don't create affiliate end it "can succeed with no booking; just intent" do intent = TeacherIntent.create(user, teacher, 'book-test-drive') token = create_stripe_token result = user.payment_update({token: token, zip: '78759', test_drive: true}) user.errors.any?.should be_false user.reload user.has_stored_credit_card?.should be_true user.sales.count.should eql 1 sale = result[:test_drive] sale.stripe_charge_id.should_not be_nil sale.recurly_tax_in_cents.should be (4999 * 0.0825).round sale.recurly_total_in_cents.should eql 4999 + (4999 * 0.0825).round sale.recurly_subtotal_in_cents.should eql 4999 sale.recurly_currency.should eql 'USD' line_item = sale.sale_line_items[0] line_item.quantity.should eql 1 line_item.product_type.should eql SaleLineItem::LESSON line_item.product_id.should eq LessonPackageType.test_drive_4.id end it "will reject second test drive purchase" do intent = TeacherIntent.create(user, teacher, 'book-test-drive') token = create_stripe_token result = user.payment_update({token: token, zip: '78759', test_drive: true}) user.errors.any?.should be_false user.reload user.has_stored_credit_card?.should be_true user.sales.count.should eql 1 SaleLineItem.count.should eql 1 Sale.count.should eql 1 purchase = result[:purchase] purchase.errors.any?.should be_false result = user.payment_update({token: token, zip: '78759', test_drive: true}) user.errors.any?.should be_false user.reload user.has_stored_credit_card?.should be_true user.sales.count.should eql 1 purchase = result[:purchase] purchase.errors.any?.should be_true purchase.errors[:user].should eq ["can not buy test drive right now because you have already purchased it within the last year"] SaleLineItem.count.should eql 1 Sale.count.should eql 1 end end end describe "check_integrity_of_jam_track_sales" do let(:user) { FactoryGirl.create(:user) } let(:jam_track) { FactoryGirl.create(:jam_track) } it "empty" do check_integrity = Sale.check_integrity_of_jam_track_sales check_integrity.length.should eq(1) r = check_integrity[0] r.total.to_i.should eq(0) r.voided.to_i.should eq(0) end it "one succeeded sale" do sale = Sale.create_jam_track_sale(user) shopping_cart = ShoppingCart.create(user, jam_track) SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, 'some_recurly_invoice_id', nil) check_integrity = Sale.check_integrity_of_jam_track_sales r = check_integrity[0] r.total.to_i.should eq(1) r.voided.to_i.should eq(0) end it "one voided sale" do sale = Sale.create_jam_track_sale(user) sale.recurly_invoice_id = 'some_recurly_invoice_id' sale.save! shopping_cart = ShoppingCart.create(user, jam_track) SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, 'some_recurly_invoice_id', nil) FactoryGirl.create(:recurly_transaction_web_hook, transaction_type: RecurlyTransactionWebHook::VOID, invoice_id: 'some_recurly_invoice_id') check_integrity = Sale.check_integrity_of_jam_track_sales r = check_integrity[0] r.total.to_i.should eq(1) r.voided.to_i.should eq(1) end end end