require 'spec_helper' describe AffiliatePartner do let!(:user) { FactoryGirl.create(:user) } let(:partner) { FactoryGirl.create(:affiliate_partner) } let!(:legalese) { FactoryGirl.create(:affiliate_legalese) } let(:jam_track) {FactoryGirl.create(:jam_track) } describe "unpaid" do it "succeeds with no data" do AffiliatePartner.unpaid.length.should eq(0) end it "finds one unpaid partner" do quarter = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, closed:true, paid:false, due_amount_in_cents: AffiliatePartner::PAY_THRESHOLD) AffiliatePartner.unpaid.should eq([partner]) end it "finds one unpaid partner with two quarters that exceed threshold" do # this $5 quarter is not enough to make the threshold quarter = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, year:2016, closed:true, paid:false, due_amount_in_cents: AffiliatePartner::PAY_THRESHOLD / 2) AffiliatePartner.unpaid.should eq([]) # this should get the user over the hump quarter = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, year:2015, closed:true, paid:false, due_amount_in_cents: AffiliatePartner::PAY_THRESHOLD / 2) AffiliatePartner.unpaid.should eq([partner]) end it "does not find paid or closed quarters" do quarter = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, year:2016, closed:true, paid:true, due_amount_in_cents: AffiliatePartner::PAY_THRESHOLD) AffiliatePartner.unpaid.should eq([]) quarter = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, year:2015, closed:false, paid:true, due_amount_in_cents: AffiliatePartner::PAY_THRESHOLD) AffiliatePartner.unpaid.should eq([]) end end it "user-partner association" do user_partner = FactoryGirl.create(:user, affiliate_partner: partner) user_partner.affiliate_partner.should_not be_nil user_partner.affiliate_partner.present?.should be_true end it 'has user referrals' do expect(partner.referral_user_count).to eq(0) uu = FactoryGirl.create(:user) uu.affiliate_referral = partner uu.save partner.reload expect(uu.affiliate_referral).to eq(partner) expect(partner.referral_user_count).to eq(1) expect(partner.user_referrals[0]).to eq(uu) end it 'groups referrals properly' do FactoryGirl.create(:user, :created_at => Time.now - 7.days, :affiliate_referral_id => partner.id) FactoryGirl.create(:user, :created_at => Time.now - 7.days, :affiliate_referral_id => partner.id) FactoryGirl.create(:user, :created_at => Time.now - 6.days, :affiliate_referral_id => partner.id) FactoryGirl.create(:user, :created_at => Time.now - 6.days, :affiliate_referral_id => partner.id) FactoryGirl.create(:user, :created_at => Time.now - 3.days, :affiliate_referral_id => partner.id) FactoryGirl.create(:user, :created_at => Time.now - 2.days, :affiliate_referral_id => partner.id) partner.reload expect(partner.referral_user_count).to eq(6) by_date = partner.referrals_by_date expect(by_date.count).to eq(4) keys = by_date.keys expect(Date.parse(keys.first)).to eq(Date.parse((Time.now - 2.days).to_s)) expect(by_date[keys.first]).to eq(1) expect(Date.parse(keys.last)).to eq(Date.parse((Time.now - 7.days).to_s)) expect(by_date[keys.last]).to eq(2) end it 'updates address correctly' do addy = partner.address.clone addy[AffiliatePartner::KEY_ADDR1] = Faker::Address.street_address addy[AffiliatePartner::KEY_ADDR2] = Faker::Address.secondary_address addy[AffiliatePartner::KEY_CITY] = Faker::Address.city addy[AffiliatePartner::KEY_STATE] = Faker::Address.state_abbr addy[AffiliatePartner::KEY_COUNTRY] = Faker::Address.country partner.update_address_value(AffiliatePartner::KEY_ADDR1, addy[AffiliatePartner::KEY_ADDR1]) partner.update_address_value(AffiliatePartner::KEY_ADDR2, addy[AffiliatePartner::KEY_ADDR2]) partner.update_address_value(AffiliatePartner::KEY_CITY, addy[AffiliatePartner::KEY_CITY]) partner.update_address_value(AffiliatePartner::KEY_STATE, addy[AffiliatePartner::KEY_STATE]) partner.update_address_value(AffiliatePartner::KEY_COUNTRY, addy[AffiliatePartner::KEY_COUNTRY]) expect(partner.address[AffiliatePartner::KEY_ADDR1]).to eq(addy[AffiliatePartner::KEY_ADDR1]) expect(partner.address[AffiliatePartner::KEY_ADDR2]).to eq(addy[AffiliatePartner::KEY_ADDR2]) expect(partner.address[AffiliatePartner::KEY_CITY]).to eq(addy[AffiliatePartner::KEY_CITY]) expect(partner.address[AffiliatePartner::KEY_STATE]).to eq(addy[AffiliatePartner::KEY_STATE]) expect(partner.address[AffiliatePartner::KEY_COUNTRY]).to eq(addy[AffiliatePartner::KEY_COUNTRY]) end it 'associates legalese' do end describe "should_attribute_sale?" do it "user with no affiliate relationship" do shopping_cart = ShoppingCart.create user, jam_track, 1 user.should_attribute_sale?(shopping_cart).should be_false end it "user with an affiliate relationship buying a jamtrack" do user.affiliate_referral = partner user.save! shopping_cart = ShoppingCart.create user, jam_track, 1, false user.should_attribute_sale?(shopping_cart).should eq({fee_in_cents:20}) end it "user with an affiliate relationship (with a custom rate) buying a jamtrack" do user.affiliate_referral = partner user.save! partner.rate = 0.25 partner.save! shopping_cart = ShoppingCart.create user, jam_track, 1, false user.should_attribute_sale?(shopping_cart).should eq({fee_in_cents:50}) end it "user with an affiliate relationship redeeming a jamtrack" do user.affiliate_referral = partner user.save! shopping_cart = ShoppingCart.create user, jam_track, 1, true user.should_attribute_sale?(shopping_cart).should eq({fee_in_cents:0}) end it "user with an expired affiliate relationship redeeming a jamtrack" do user.affiliate_referral = partner user.created_at = (365 * 2 + 1).days.ago user.save! shopping_cart = ShoppingCart.create user, jam_track, 1, false user.should_attribute_sale?(shopping_cart).should be_false end end describe "created_within_affiliate_window" do it "user created very recently" do partner.created_within_affiliate_window(user, Time.now).should be_true end it "user created 2 years, 1 day asgo" do days_future = 365 * 2 + 1 partner.created_within_affiliate_window(user, days_future.days.from_now).should be_false end end describe "tally_up" do let(:partner1) {FactoryGirl.create(:affiliate_partner)} let(:partner2) {FactoryGirl.create(:affiliate_partner)} let(:payment1) {FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner1)} let(:user_partner1) { FactoryGirl.create(:user, affiliate_referral: partner1)} let(:user_partner2) { FactoryGirl.create(:user, affiliate_referral: partner2)} let(:sale) {Sale.create_jam_track_sale(user_partner1)} describe "ensure_quarters_exist" do it "runs OK with no data" do AffiliatePartner.ensure_quarters_exist(2015, 0) AffiliateQuarterlyPayment.count.should eq(0) end it "creates new slots" do partner1.touch partner2.touch AffiliatePartner.ensure_quarters_exist(2015, 0) AffiliateQuarterlyPayment.count.should eq(2) quarter = partner1.quarters.first quarter.year.should eq(2015) quarter.quarter.should eq(0) quarter = partner2.quarters.first quarter.year.should eq(2015) quarter.quarter.should eq(0) end it "creates one slot, ignoring other" do partner1.touch partner2.touch payment1.touch AffiliateQuarterlyPayment.count.should eq(1) AffiliatePartner.ensure_quarters_exist(2015, 0) AffiliateQuarterlyPayment.count.should eq(2) quarter = partner1.quarters.first quarter.year.should eq(2015) quarter.quarter.should eq(0) quarter = partner2.quarters.first quarter.year.should eq(2015) quarter.quarter.should eq(0) end end describe "close_quarters" do it "runs OK with no data" do AffiliateQuarterlyPayment.count.should eq(0) AffiliatePartner.close_quarters(2015, 1) end it "ignores current quarter" do partner1.touch partner2.touch AffiliatePartner.ensure_quarters_exist(2015, 0) AffiliateQuarterlyPayment.count.should eq(2) AffiliatePartner.close_quarters(2015, 0) AffiliateQuarterlyPayment.where(closed: true).count.should eq(0) end it "closes previous quarter" do partner1.touch partner2.touch AffiliatePartner.ensure_quarters_exist(2015, 0) AffiliateQuarterlyPayment.count.should eq(2) AffiliatePartner.close_quarters(2015, 1) AffiliateQuarterlyPayment.where(closed: true).count.should eq(2) end it "closes previous quarter (edge case)" do partner1.touch partner2.touch AffiliatePartner.ensure_quarters_exist(2014, 3) AffiliateQuarterlyPayment.count.should eq(2) AffiliatePartner.close_quarters(2015, 0) AffiliateQuarterlyPayment.where(closed: true).count.should eq(2) end end describe "tally_partner_totals" do it "runs OK with no data" do AffiliatePartner.tally_partner_totals AffiliatePartner.count.should eq(0) end it "updates partner when there is no data to tally" do partner1.touch partner1.cumulative_earnings_in_cents.should eq(0) partner1.referral_user_count.should eq(0) AffiliatePartner.tally_partner_totals partner1.reload partner1.cumulative_earnings_in_cents.should eq(0) partner1.referral_user_count.should eq(0) end it "updates referral_user_count" do FactoryGirl.create(:user, affiliate_referral: partner1) AffiliatePartner.tally_partner_totals partner1.reload partner1.referral_user_count.should eq(1) partner1.cumulative_earnings_in_cents.should eq(0) FactoryGirl.create(:user, affiliate_referral: partner2) AffiliatePartner.tally_partner_totals partner1.reload partner1.referral_user_count.should eq(1) partner1.cumulative_earnings_in_cents.should eq(0) partner2.reload partner2.referral_user_count.should eq(1) partner2.cumulative_earnings_in_cents.should eq(0) FactoryGirl.create(:user, affiliate_referral: partner2) AffiliatePartner.tally_partner_totals partner1.reload partner1.referral_user_count.should eq(1) partner1.cumulative_earnings_in_cents.should eq(0) partner2.reload partner2.referral_user_count.should eq(2) partner2.cumulative_earnings_in_cents.should eq(0) end it "updates cumulative_earnings_in_cents" do FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner1, year:2015, quarter:0, due_amount_in_cents: 0, closed:true, paid:true) AffiliatePartner.tally_partner_totals partner1.reload partner1.referral_user_count.should eq(0) partner1.cumulative_earnings_in_cents.should eq(0) FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner2, year:2015, quarter:0, due_amount_in_cents: 10, closed:true, paid:true) AffiliatePartner.tally_partner_totals partner1.reload partner1.referral_user_count.should eq(0) partner1.cumulative_earnings_in_cents.should eq(0) partner2.reload partner2.referral_user_count.should eq(0) partner2.cumulative_earnings_in_cents.should eq(10) FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner2, year:2015, quarter:1, due_amount_in_cents: 100, closed:true, paid:true) AffiliatePartner.tally_partner_totals partner1.reload partner1.referral_user_count.should eq(0) partner1.cumulative_earnings_in_cents.should eq(0) partner2.reload partner2.referral_user_count.should eq(0) partner2.cumulative_earnings_in_cents.should eq(110) FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner1, year:2015, quarter:1, due_amount_in_cents: 100, closed:true, paid:true) AffiliatePartner.tally_partner_totals partner1.reload partner1.referral_user_count.should eq(0) partner1.cumulative_earnings_in_cents.should eq(100) partner2.reload partner2.referral_user_count.should eq(0) partner2.cumulative_earnings_in_cents.should eq(110) # a paid=false quarterly payment does not yet reflect in cumulative earnings FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner1, year:2015, quarter:2, due_amount_in_cents: 1000, closed:false, paid:false) AffiliatePartner.tally_partner_totals partner1.reload partner1.referral_user_count.should eq(0) partner1.cumulative_earnings_in_cents.should eq(100) partner2.reload partner2.referral_user_count.should eq(0) partner2.cumulative_earnings_in_cents.should eq(110) end end describe "total_quarters" do it "runs OK with no data" do AffiliateQuarterlyPayment.count.should eq(0) AffiliatePartner.total_quarters(2015, 0) end it "totals 0 with no sales data" do partner1.touch partner2.touch AffiliatePartner.ensure_quarters_exist(2015, 0) AffiliateQuarterlyPayment.count.should eq(2) AffiliatePartner.total_quarters(2015, 0) quarter = partner1.quarters.first quarter.due_amount_in_cents.should eq(0) quarter.last_updated.should_not be_nil quarter = partner2.quarters.first quarter.due_amount_in_cents.should eq(0) quarter.last_updated.should_not be_nil end it "totals with sales data" do partner1.touch partner2.touch # create a freebie for partner1 shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, true freebie_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) freebie_sale.affiliate_referral_fee_in_cents.should eq(0) freebie_sale.created_at = Date.new(2015, 1, 1) freebie_sale.affiliate_distributions.first.created_at = freebie_sale.created_at freebie_sale.affiliate_distributions.first.save! freebie_sale.save! AffiliatePartner.ensure_quarters_exist(2015, 0) AffiliateQuarterlyPayment.count.should eq(2) AffiliatePartner.total_quarters(2015, 0) quarter = partner1.quarters.first quarter.due_amount_in_cents.should eq(0) quarter.jamtracks_sold.should eq(0) quarter = partner2.quarters.first quarter.due_amount_in_cents.should eq(0) quarter.jamtracks_sold.should eq(0) # create a real sale for partner1 shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) real_sale.affiliate_referral_fee_in_cents.should eq(20) real_sale.created_at = Date.new(2015, 1, 1) real_sale.save! real_sale.affiliate_distributions.first.created_at = real_sale.created_at real_sale.affiliate_distributions.first.save! AffiliatePartner.ensure_quarters_exist(2015, 0) AffiliatePartner.total_quarters(2015, 0) quarter = partner1.quarters.first quarter.due_amount_in_cents.should eq(20) quarter.jamtracks_sold.should eq(1) quarter = partner2.quarters.first quarter.due_amount_in_cents.should eq(0) quarter.jamtracks_sold.should eq(0) # create a real sale for partner2 shopping_cart = ShoppingCart.create user_partner2, jam_track, 1, false real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) real_sale.affiliate_referral_fee_in_cents.should eq(20) real_sale.created_at = Date.new(2015, 1, 1) real_sale.save! real_sale.affiliate_distributions.first.created_at = real_sale.created_at real_sale.affiliate_distributions.first.save! AffiliatePartner.ensure_quarters_exist(2015, 0) AffiliatePartner.total_quarters(2015, 0) quarter = partner1.quarters.first quarter.due_amount_in_cents.should eq(20) quarter.jamtracks_sold.should eq(1) quarter = partner2.quarters.first quarter.due_amount_in_cents.should eq(20) quarter.jamtracks_sold.should eq(1) # create a real sale for partner1 shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) real_sale.affiliate_referral_fee_in_cents.should eq(20) real_sale.created_at = Date.new(2015, 1, 1) real_sale.save! real_sale.affiliate_distributions.first.created_at = real_sale.created_at real_sale.affiliate_distributions.first.save! AffiliatePartner.ensure_quarters_exist(2015, 0) AffiliatePartner.total_quarters(2015, 0) quarter = partner1.quarters.first quarter.due_amount_in_cents.should eq(40) quarter.jamtracks_sold.should eq(2) quarter = partner2.quarters.first quarter.due_amount_in_cents.should eq(20) quarter.jamtracks_sold.should eq(1) # create a real sale for a non-affiliated user shopping_cart = ShoppingCart.create user, jam_track, 1, false real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) real_sale.affiliate_referral_fee_in_cents.should be_nil real_sale.created_at = Date.new(2015, 1, 1) real_sale.save! AffiliatePartner.ensure_quarters_exist(2015, 0) AffiliatePartner.total_quarters(2015, 0) quarter = partner1.quarters.first quarter.due_amount_in_cents.should eq(40) quarter.jamtracks_sold.should eq(2) quarter = partner2.quarters.first quarter.due_amount_in_cents.should eq(20) quarter.jamtracks_sold.should eq(1) # create a real sale but in previous quarter (should no have effect on the quarter being computed) shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) real_sale.affiliate_referral_fee_in_cents.should eq(20) real_sale.created_at = Date.new(2014, 12, 31) real_sale.save! real_sale.affiliate_distributions.first.created_at = real_sale.created_at real_sale.affiliate_distributions.first.save! AffiliatePartner.ensure_quarters_exist(2015, 0) AffiliatePartner.total_quarters(2015, 0) quarter = partner1.quarters.first quarter.due_amount_in_cents.should eq(40) quarter.jamtracks_sold.should eq(2) quarter = partner2.quarters.first quarter.due_amount_in_cents.should eq(20) quarter.jamtracks_sold.should eq(1) # create a real sale but in later quarter (should no have effect on the quarter being computed) shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) real_sale.affiliate_referral_fee_in_cents.should eq(20) real_sale.created_at = Date.new(2015, 4, 1) real_sale.save! real_sale.affiliate_distributions.first.created_at = real_sale.created_at real_sale.affiliate_distributions.first.save! real_sale_later = real_sale AffiliatePartner.ensure_quarters_exist(2015, 0) AffiliatePartner.total_quarters(2015, 0) quarter = partner1.quarters.first quarter.due_amount_in_cents.should eq(40) quarter.jamtracks_sold.should eq(2) quarter = partner2.quarters.first quarter.due_amount_in_cents.should eq(20) quarter.jamtracks_sold.should eq(1) # create a real sale but then refund it shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) real_sale.affiliate_referral_fee_in_cents.should eq(20) real_sale.created_at = Date.new(2015, 3, 31) real_sale.save! real_sale.affiliate_distributions.first.created_at = real_sale.created_at real_sale.affiliate_distributions.first.save! AffiliatePartner.ensure_quarters_exist(2015, 0) AffiliatePartner.total_quarters(2015, 0) quarter = partner1.quarters.first quarter.due_amount_in_cents.should eq(60) quarter.jamtracks_sold.should eq(3) quarter = partner2.quarters.first quarter.due_amount_in_cents.should eq(20) # now refund it real_sale.affiliate_refunded_at = Date.new(2015, 3, 1) real_sale.affiliate_refunded = true real_sale.save! real_sale.affiliate_distributions.first.affiliate_refunded_at = real_sale.affiliate_refunded_at real_sale.affiliate_distributions.first.affiliate_refunded = real_sale.affiliate_refunded real_sale.affiliate_distributions.first.save! AffiliatePartner.ensure_quarters_exist(2015, 0) AffiliatePartner.total_quarters(2015, 0) quarter = partner1.quarters.first quarter.due_amount_in_cents.should eq(40) quarter = partner2.quarters.first quarter.due_amount_in_cents.should eq(20) quarter.jamtracks_sold.should eq(1) # create the 2nd quarter, which should add up the sale created a few bits up AffiliatePartner.ensure_quarters_exist(2015, 1) AffiliatePartner.total_quarters(2015, 1) payment = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(1, 2015, partner1.id) payment.due_amount_in_cents.should eq(20) # and now refund it in the 3rd quarter real_sale_later.affiliate_refunded_at = Date.new(2015, 7, 1) real_sale_later.affiliate_refunded = true real_sale_later.save! real_sale_later.affiliate_distributions.first.affiliate_refunded_at = real_sale_later.affiliate_refunded_at real_sale_later.affiliate_distributions.first.affiliate_refunded = real_sale_later.affiliate_refunded real_sale_later.affiliate_distributions.first.save! AffiliatePartner.total_quarters(2015, 1) payment = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(1, 2015, partner1.id) payment.due_amount_in_cents.should eq(20) payment.jamtracks_sold.should eq(1) # now catch the one refund in the 3rd quarter AffiliatePartner.ensure_quarters_exist(2015, 2) AffiliatePartner.total_quarters(2015, 2) payment = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(2, 2015, partner1.id) payment.due_amount_in_cents.should eq(-20) payment.jamtracks_sold.should eq(-1) end end describe "tally_up complete" do it "runs OK with no data" do AffiliatePartner.tally_up(Date.new(2015, 1, 1)) end it "successive runs" do GenericState.singleton.affiliate_tallied_at.should be_nil AffiliatePartner.tally_up(Date.new(2015, 1, 1)) GenericState.singleton.affiliate_tallied_at.should_not be_nil AffiliateQuarterlyPayment.count.should eq(0) # partner is created partner1.touch AffiliatePartner.tally_up(Date.new(2015, 1, 1)) AffiliateQuarterlyPayment.count.should eq(2) AffiliateMonthlyPayment.count.should eq(6) quarter_previous = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(3, 2014, partner1.id) quarter_previous.due_amount_in_cents.should eq(0) quarter_previous.closed.should be_true quarter = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(0, 2015, partner1.id) quarter.due_amount_in_cents.should eq(0) quarter.closed.should be_false month_previous= AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(10, 2014, partner1.id) month_previous.due_amount_in_cents.should eq(0) month_previous.closed.should be_true month_previous.jamtracks_sold.should eq(0) month_previous= AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(11, 2014, partner1.id) month_previous.due_amount_in_cents.should eq(0) month_previous.closed.should be_true month_previous.jamtracks_sold.should eq(0) month_previous= AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(12, 2014, partner1.id) month_previous.due_amount_in_cents.should eq(0) month_previous.closed.should be_true month_previous.jamtracks_sold.should eq(0) month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(1, 2015, partner1.id) month_previous.due_amount_in_cents.should eq(0) month_previous.closed.should be_true month_previous.jamtracks_sold.should eq(0) month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(2, 2015, partner1.id) month_previous.due_amount_in_cents.should eq(0) month_previous.closed.should be_true month.jamtracks_sold.should eq(0) month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(3, 2015, partner1.id) month_previous.due_amount_in_cents.should eq(0) month_previous.closed.should be_true month_previous.jamtracks_sold.should eq(0) shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) real_sale.affiliate_referral_fee_in_cents.should eq(20) real_sale.created_at = Date.new(2015, 4, 1) real_sale.save! real_sale.affiliate_distributions.first.created_at = real_sale.created_at real_sale.affiliate_distributions.first.save! AffiliatePartner.tally_up(Date.new(2015, 4, 1)) AffiliateQuarterlyPayment.count.should eq(3) quarter = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(0, 2015, partner1.id) quarter.due_amount_in_cents.should eq(0) quarter.jamtracks_sold.should eq(0) quarter.closed.should be_true quarter2 = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(1, 2015, partner1.id) quarter2.due_amount_in_cents.should eq(20) quarter2.jamtracks_sold.should eq(1) quarter2.closed.should be_false month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(1, 2015, partner1.id) month.due_amount_in_cents.should eq(0) month.jamtracks_sold.should eq(0) month.closed.should be_true month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(2, 2015, partner1.id) month.due_amount_in_cents.should eq(0) month.jamtracks_sold.should eq(0) month.closed.should be_true month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(3, 2015, partner1.id) month.due_amount_in_cents.should eq(0) month.jamtracks_sold.should eq(0) month.closed.should be_true month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(4, 2015, partner1.id) month.due_amount_in_cents.should eq(20) month.jamtracks_sold.should eq(1) month.closed.should be_false month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(5, 2015, partner1.id) month.due_amount_in_cents.should eq(0) month.jamtracks_sold.should eq(0) month.closed.should be_false month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(6, 2015, partner1.id) month.due_amount_in_cents.should eq(0) month.jamtracks_sold.should eq(0) month.closed.should be_false # now sneak in a purchase in the 1st quarter, which makes no sense, but proves that closed quarters are not touched shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil) real_sale.affiliate_referral_fee_in_cents.should eq(20) real_sale.created_at = Date.new(2015, 1, 1) real_sale.save! real_sale.affiliate_distributions.first.created_at = real_sale.created_at real_sale.affiliate_distributions.first.save! AffiliatePartner.tally_up(Date.new(2015, 4, 2)) quarter = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(0, 2015, partner1.id) quarter.due_amount_in_cents.should eq(0) quarter.jamtracks_sold.should eq(0) quarter.closed.should be_true month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(1, 2015, partner1.id) month.due_amount_in_cents.should eq(0) month.closed.should be_true month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(2, 2015, partner1.id) month.due_amount_in_cents.should eq(0) month.jamtracks_sold.should eq(0) month.closed.should be_true month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(3, 2015, partner1.id) month.due_amount_in_cents.should eq(0) month.jamtracks_sold.should eq(0) month.closed.should be_true end end describe "tally_traffic_totals" do it "runs OK with no data" do AffiliatePartner.tally_traffic_totals(Date.yesterday, Date.today) end it "can deal with simple signup case" do user_partner1.touch day0 = user_partner1.created_at.to_date # simulate what happens when this scheduled job first ever runs AffiliatePartner.tally_traffic_totals(nil, day0) AffiliateTrafficTotal.count.should eq(1) traffic_total_day_before = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0 - 1, user_partner1.affiliate_referral_id) traffic_total_day_before.visits.should eq(0) traffic_total_day_before.signups.should eq(0) # then simulate when it runs on the same day as it ran on the day before AffiliatePartner.tally_traffic_totals(day0, day0) AffiliateTrafficTotal.count.should eq(1) traffic_total_day_before = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0 - 1, user_partner1.affiliate_referral_id) traffic_total_day_before.visits.should eq(0) traffic_total_day_before.signups.should eq(0) # now run it on the next day, which should catch the signup event day1 = day0 + 1 AffiliatePartner.tally_traffic_totals(day0, day1) AffiliateTrafficTotal.count.should eq(2) traffic_total_day_before = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0 - 1, user_partner1.affiliate_referral_id) traffic_total_day_before.visits.should eq(0) traffic_total_day_before.signups.should eq(0) traffic_total_day0 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0, user_partner1.affiliate_referral_id) traffic_total_day0.visits.should eq(0) traffic_total_day0.signups.should eq(1) # add in a visit visit = FactoryGirl.create(:affiliate_referral_visit, affiliate_partner: user_partner1.affiliate_referral) # it won't get seen though because we've moved on AffiliatePartner.tally_traffic_totals(day1, day1) AffiliateTrafficTotal.count.should eq(2) traffic_total_day_before = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0 - 1, user_partner1.affiliate_referral_id) traffic_total_day_before.visits.should eq(0) traffic_total_day_before.signups.should eq(0) traffic_total_day0 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0, user_partner1.affiliate_referral_id) traffic_total_day0.visits.should eq(0) traffic_total_day0.signups.should eq(1) # manipulate the visit created_at so we can record it visit.created_at = day1 visit.save! day2 = day1 + 1 AffiliatePartner.tally_traffic_totals(day1, day2) AffiliateTrafficTotal.count.should eq(3) traffic_total_day_before = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0 - 1, user_partner1.affiliate_referral_id) traffic_total_day_before.visits.should eq(0) traffic_total_day_before.signups.should eq(0) traffic_total_day0 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0, user_partner1.affiliate_referral_id) traffic_total_day0.visits.should eq(0) traffic_total_day0.signups.should eq(1) traffic_total_day1 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day1, user_partner1.affiliate_referral_id) traffic_total_day1.visits.should eq(1) traffic_total_day1.signups.should eq(0) # now create 2 records on day 2 for visits and signups both, and a partner with their own visit and signup, and do a final check user_partner2.touch visit2 = FactoryGirl.create(:affiliate_referral_visit, affiliate_partner: user_partner1.affiliate_referral) visit3 = FactoryGirl.create(:affiliate_referral_visit, affiliate_partner: user_partner1.affiliate_referral) visit_partner2 = FactoryGirl.create(:affiliate_referral_visit, affiliate_partner: user_partner2.affiliate_referral) visit2.created_at = day2 visit3.created_at = day2 visit_partner2.created_at = day2 visit2.save! visit3.save! visit_partner2.save! user2 = FactoryGirl.create(:user, affiliate_referral:user_partner1.affiliate_referral) user3 = FactoryGirl.create(:user, affiliate_referral:user_partner1.affiliate_referral) user2.created_at = day2 user3.created_at = day2 user_partner2.created_at = day2 user2.save! user3.save! user_partner2.save! day3 = day2 + 1 AffiliatePartner.tally_traffic_totals(day2, day3) AffiliateTrafficTotal.count.should eq(5) traffic_total_day_before = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0 - 1, user_partner1.affiliate_referral_id) traffic_total_day_before.visits.should eq(0) traffic_total_day_before.signups.should eq(0) traffic_total_day0 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0, user_partner1.affiliate_referral_id) traffic_total_day0.visits.should eq(0) traffic_total_day0.signups.should eq(1) traffic_total_day1 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day1, user_partner1.affiliate_referral_id) traffic_total_day1.visits.should eq(1) traffic_total_day1.signups.should eq(0) traffic_total_day2 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day2, user_partner1.affiliate_referral_id) traffic_total_day2.visits.should eq(2) traffic_total_day2.signups.should eq(2) traffic_total_day2 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day2, user_partner2.affiliate_referral_id) traffic_total_day2.visits.should eq(1) traffic_total_day2.signups.should eq(1) end end describe "boundary_dates" do it "1st quarter" do start_date, end_date = AffiliatePartner.boundary_dates(2015, 0) start_date.should eq(Date.new(2015, 1, 1)) end_date.should eq(Date.new(2015, 3, 31)) end it "2nd quarter" do start_date, end_date = AffiliatePartner.boundary_dates(2015, 1) start_date.should eq(Date.new(2015, 4, 1)) end_date.should eq(Date.new(2015, 6, 30)) end it "3rd quarter" do start_date, end_date = AffiliatePartner.boundary_dates(2015, 2) start_date.should eq(Date.new(2015, 7, 1)) end_date.should eq(Date.new(2015, 9, 30)) end it "4th quarter" do start_date, end_date = AffiliatePartner.boundary_dates(2015, 3) start_date.should eq(Date.new(2015, 10, 1)) end_date.should eq(Date.new(2015, 12, 31)) end end describe "edge case" do it "year change" do partner.touch last_day_of_year = Date.new(2015, 12, 31) first_day_of_next_year = Date.new(2016, 01, 01) AffiliatePartner.tally_up(last_day_of_year) AffiliatePartner.tally_up(first_day_of_next_year) quarterly_payment = AffiliateQuarterlyPayment.where(year: 2016, quarter: 0, affiliate_partner_id: partner.id).first quarterly_payment.closed.should be_false AffiliatePartner.tally_up(Date.new(2016, 01, 02)) quarterly_payment.reload quarterly_payment.closed.should be_false end end describe "boundary_dates_for_month" do it "invalid month" do expect{AffiliatePartner.boundary_dates_for_month(2015, 0)}.to raise_error end it "January" do start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 1) start_date.should eq(Date.new(2015, 1, 1)) end_date.should eq(Date.new(2015, 1, 31)) end it "February" do start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 2) start_date.should eq(Date.new(2015, 2, 1)) end_date.should eq(Date.new(2015, 2, 28)) end it "March" do start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 3) start_date.should eq(Date.new(2015, 3, 1)) end_date.should eq(Date.new(2015, 3, 31)) end it "April" do start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 4) start_date.should eq(Date.new(2015, 4, 1)) end_date.should eq(Date.new(2015, 4, 30)) end it "May" do start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 5) start_date.should eq(Date.new(2015, 5, 1)) end_date.should eq(Date.new(2015, 5, 31)) end it "June" do start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 6) start_date.should eq(Date.new(2015, 6, 1)) end_date.should eq(Date.new(2015, 6, 30)) end it "July" do start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 7) start_date.should eq(Date.new(2015, 7, 1)) end_date.should eq(Date.new(2015, 7, 31)) end it "August" do start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 8) start_date.should eq(Date.new(2015, 8, 1)) end_date.should eq(Date.new(2015, 8, 31)) end it "September" do start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 9) start_date.should eq(Date.new(2015, 9, 1)) end_date.should eq(Date.new(2015, 9, 30)) end it "October" do start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 10) start_date.should eq(Date.new(2015, 10, 1)) end_date.should eq(Date.new(2015, 10, 31)) end it "November" do start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 11) start_date.should eq(Date.new(2015, 11, 1)) end_date.should eq(Date.new(2015, 11, 30)) end it "December" do start_date, end_date = AffiliatePartner.boundary_dates_for_month(2015, 12) start_date.should eq(Date.new(2015, 12, 1)) end_date.should eq(Date.new(2015, 12, 31)) end it "February in a leap year" do start_date, end_date = AffiliatePartner.boundary_dates_for_month(2016, 2) start_date.should eq(Date.new(2016, 2, 1)) end_date.should eq(Date.new(2016, 2, 29)) end end end end