diff --git a/app/jobs/update_bill_items.rb b/app/jobs/update_bill_items.rb index 00dfd333db..c8e156778c 100644 --- a/app/jobs/update_bill_items.rb +++ b/app/jobs/update_bill_items.rb @@ -1,4 +1,4 @@ -UpdateBillItems = Struct.new(:lala) do +UpdateBillItems = Struct.new("UpdateBillItems") do def perform # If it is the first of the month, calculate turnover for the previous month up until midnight last night # Otherwise, calculate turnover for the current month @@ -9,56 +9,50 @@ UpdateBillItems = Struct.new(:lala) do # Cycle through enterprises enterprises.each do |enterprise| + start_for_enterprise = [start_date, enterprise.created_at].max + #end_for_enterprise = [start_date, enterprise.deleted].min + # Cycle through previous versions of this enterprise - versions = enterprise.versions.where('created_at >= (?)', start_date) - bill_items = [] + versions = enterprise.versions.where('created_at >= (?)', start_for_enterprise).order(:created_at) trial_start = enterprise.shop_trial_start_date trial_expiry = enterprise.shop_trial_expiry versions.each do |version| - begins_at = bill_items.last.andand.ends_at || [start_date, enterprise.created_at].max + begins_at = version.previous.andand.created_at || start_for_enterprise ends_at = version.created_at - split_for_trial(version.reify, begins_at, ends_at, trial_start, trial_expiry).each do |bill_item| - bill_items << bill_item - end + split_for_trial(version.reify, begins_at, ends_at, trial_start, trial_expiry) end # Update / create bill_item for current start - begins_at = bill_items.last.andand.ends_at || [start_date, enterprise.created_at].max + begins_at = versions.last.andand.created_at || start_for_enterprise ends_at = end_date - split_for_trial(enterprise, begins_at, ends_at, trial_start, trial_expiry).each do |bill_item| - bill_items << bill_item - end + split_for_trial(enterprise, begins_at, ends_at, trial_start, trial_expiry) end end def split_for_trial(enterprise, begins_at, ends_at, trial_start, trial_expiry) - bill_items = [] - trial_start = trial_expiry = begins_at-1.day if trial_start.nil? || trial_expiry.nil? # If the trial begins after ends_at, create a bill for the entire period # Otherwise, create a normal bill_item from the begins_at until the start of the trial if trial_start > begins_at - bill_items << update_bill_item(enterprise, begins_at, [ends_at, trial_start].min, false) + update_bill_item(enterprise, begins_at, [ends_at, trial_start].min, false) end # If all or some of the trial occurs between begins_at and ends_at # Create a trial bill_item from the from begins_at or trial_start, whichever occurs last, until ends_at, or trial_expiry whichever occurs first if trial_expiry >= begins_at && trial_start <= ends_at - bill_items << update_bill_item(enterprise, [trial_start, begins_at].max, [ends_at, trial_expiry].min, true) + update_bill_item(enterprise, [trial_start, begins_at].max, [ends_at, trial_expiry].min, true) end # If the trial finishes before begins_at, or trial has not been set, create a bill for the entire period # Otherwise, create a normal bill_item from the end of the trial until ends_at if trial_expiry < ends_at - bill_items << update_bill_item(enterprise, [trial_expiry, begins_at].max, ends_at, false) + update_bill_item(enterprise, [trial_expiry, begins_at].max, ends_at, false) end - - bill_items end def update_bill_item(enterprise, begins_at, ends_at, trial) @@ -66,9 +60,36 @@ UpdateBillItems = Struct.new(:lala) do sells = enterprise.sells orders = Spree::Order.where('distributor_id = (?) AND completed_at >= (?) AND completed_at < (?)', enterprise.id, begins_at, ends_at) - bill_item = BillItem.where(begins_at: begins_at, sells: sells, trial: trial, owner_id: owner_id, enterprise_id: enterprise.id).first - bill_item ||= BillItem.new(begins_at: begins_at, sells: sells, trial: trial, owner_id: owner_id, enterprise_id: enterprise.id) - bill_item.update_attributes({ends_at: ends_at, turnover: orders.sum(&:total)}) + # Snagging any BillItems which overlap + overlapping_bill_items = BillItem.where('begins_at <= (?) AND ends_at >= (?) AND enterprise_id = (?)',ends_at, begins_at, enterprise.id) + overlapping_bill_items.each do |bill_item| + if bill_item.sells != sells || bill_item.trial != trial || bill_item.owner_id != owner_id + Bugsnag.notify(RuntimeError.new("Duplicate BillItem"), { + bill_items: { + new: { + begins_at: begins_at, + ends_at: ends_at, + sells: sells, + trial: trial, + turnover: orders.sum(&:total), + owner_id: owner_id, + enterprise_id: enterprise.id + }.as_json, + existing: bill_item.as_json + } + }) + end + end + + bill_item = BillItem.where(begins_at: begins_at, enterprise_id: enterprise.id).first + bill_item ||= BillItem.new(begins_at: begins_at, enterprise_id: enterprise.id) + bill_item.update_attributes({ + ends_at: ends_at, + sells: sells, + trial: trial, + owner_id: owner_id, + turnover: orders.sum(&:total) + }) bill_item end diff --git a/spec/factories.rb b/spec/factories.rb index 169d2d5c02..57b0c95106 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -215,6 +215,16 @@ FactoryGirl.define do code { SecureRandom.base64(150) } user end + + factory :bill_item do + begins_at { Time.now.beginning_of_month } + ends_at { Time.now.beginning_of_month + 1.month } + sells { ['none', 'own', 'any'].sample } + trial { [true, false].sample } + enterprise + owner { FactoryGirl.create :user } + turnover { BigDecimal.new("#{rand(5000)}.#{rand(99)}") } + end end diff --git a/spec/jobs/update_bill_items_spec.rb b/spec/jobs/update_bill_items_spec.rb index 6d94999f22..828a5b706e 100644 --- a/spec/jobs/update_bill_items_spec.rb +++ b/spec/jobs/update_bill_items_spec.rb @@ -1,7 +1,379 @@ require 'spec_helper' +def travel_to(time) + around { |example| Timecop.travel(start_of_july + time) { example.run } } +end + describe UpdateBillItems do - describe "smoke tests" do + describe "unit tests" do + let!(:start_of_july) { Time.now.beginning_of_year + 6.months } + + let!(:updater) { UpdateBillItems.new } + + describe "perform", versioning: true do + let!(:enterprise) { create(:supplier_enterprise, created_at: start_of_july - 1.month, sells: 'any') } + + before do + allow(Enterprise).to receive(:select) { [enterprise] } + end + + context "on the first of the month" do + travel_to(3.hours) + + it "processes the previous month" do + expect(updater).to receive(:split_for_trial) + .with(enterprise, start_of_july - 1.month, start_of_july, nil, nil) + updater.perform + end + end + + context "on all other days" do + travel_to(1.day + 3.hours) + + it "processes the current month up until previous midnight" do + expect(updater).to receive(:split_for_trial) + .with(enterprise, start_of_july, start_of_july + 1.day, nil, nil) + updater.perform + end + end + + context "when an enterprise is created before the beginning of the current month" do + travel_to(28.days) + + context "when no alterations to sells or owner have been made during the current month" do + + it "begins at the start of the month" do + expect(updater).to receive(:split_for_trial) + .with(enterprise, start_of_july, start_of_july + 28.days, nil, nil) + updater.perform + end + end + + context "when sells has been changed within the current month" do + before do + Timecop.freeze(start_of_july + 10.days) do + # NOTE: Sells is changed between when order1 and order2 are placed + enterprise.update_attribute(:sells, 'own') + end + end + + travel_to(28.days) + + it "processes each sells period separately" do + allow(updater).to receive(:split_for_trial).twice + updater.perform + + expect(updater).to have_received(:split_for_trial) + .with(enterprise.versions.first.reify, start_of_july, start_of_july + 10.days, nil, nil) + + expect(updater).to have_received(:split_for_trial) + .with(enterprise, start_of_july + 10.days, start_of_july + 28.days, nil, nil) + end + end + + context "when owner has been changed within the current month" do + let!(:new_owner) { create(:user) } + + before do + Timecop.freeze(start_of_july + 10.days) do + # NOTE: Sells is changed between when order1 and order2 are placed + enterprise.update_attribute(:owner, new_owner) + end + end + + travel_to(28.days) + + it "processes each ownership period separately" do + allow(updater).to receive(:split_for_trial).twice + updater.perform + + expect(updater).to have_received(:split_for_trial) + .with(enterprise.versions.first.reify, start_of_july, start_of_july + 10.days, nil, nil) + + expect(updater).to have_received(:split_for_trial) + .with(enterprise, start_of_july + 10.days, start_of_july + 28.days, nil, nil) + end + end + + context "when some other attribute has been changed within the current month" do + before do + Timecop.freeze(start_of_july + 10.days) do + # NOTE: Sells is changed between when order1 and order2 are placed + enterprise.update_attribute(:name, 'Some New Name') + end + end + + travel_to(28.days) + + it "does not create a version, and so does not split the period" do + expect(enterprise.versions).to eq [] + allow(updater).to receive(:split_for_trial).once + updater.perform + expect(updater).to have_received(:split_for_trial) + .with(enterprise, start_of_july, start_of_july + 28.days, nil, nil) + end + end + + context "where sells or owner_id were altered during the previous month (ie. June)" do + let!(:new_owner) { create(:user) } + + before do + Timecop.freeze(start_of_july - 20.days) do + # NOTE: Sells is changed between when order1 and order2 are placed + enterprise.update_attribute(:sells, 'own') + end + Timecop.freeze(start_of_july - 10.days) do + # NOTE: Sells is changed between when order1 and order2 are placed + enterprise.update_attribute(:owner, new_owner) + end + end + + travel_to(28.days) + + it "ignores those verions" do + allow(updater).to receive(:split_for_trial).once + updater.perform + expect(updater).to have_received(:split_for_trial) + .with(enterprise, start_of_july, start_of_july + 28.days, nil, nil) + end + end + end + + context "when an enterprise is created during the current month" do + before do + enterprise.update_attribute(:created_at, start_of_july + 10.days) + end + + travel_to(28.days) + + it "begins at the date the enterprise was created" do + allow(updater).to receive(:split_for_trial).once + updater.perform + expect(updater).to have_received(:split_for_trial) + .with(enterprise, start_of_july + 10.days, start_of_july + 28.days, nil, nil) + end + end + + pending "when an enterprise is deleted during the current month" do + before do + enterprise.update_attribute(:deleted_at, start_of_july + 20.days) + end + + travel_to(28.days) + + it "ends at the date the enterprise was deleted" do + allow(updater).to receive(:split_for_trial) + updater.perform + expect(updater).to have_received(:split_for_trial) + .with(enterprise, start_of_july, start_of_july + 20.days, nil, nil) + end + end + end + + describe "split_for_trial" do + let!(:enterprise) { double(:enterprise) } + let(:begins_at) { start_of_july } + let(:ends_at) { begins_at + 30.days } + + context "when trial_start is nil" do + let(:trial_start) { nil } + let(:trial_expiry) { begins_at + 3.days } + + before do + allow(updater).to receive(:update_bill_item).once + updater.split_for_trial(enterprise, begins_at, ends_at, trial_start, trial_expiry) + end + + it "calls update_bill_item once for the entire period" do + expect(updater).to have_received(:update_bill_item) + .with(enterprise, begins_at, ends_at, false) + end + end + + context "when trial_expiry is nil" do + let(:trial_start) { begins_at + 3.days } + let(:trial_expiry) { nil } + + before do + allow(updater).to receive(:update_bill_item).once + updater.split_for_trial(enterprise, begins_at, ends_at, trial_start, trial_expiry) + end + + it "calls update_bill_item once for the entire period" do + expect(updater).to have_received(:update_bill_item) + .with(enterprise, begins_at, ends_at, false) + end + end + + context "when the trial begins before begins_at" do + let(:trial_start) { begins_at - 10.days } + + context "and the trial ends before begins_at" do + let(:trial_expiry) { begins_at - 5.days } + + before do + allow(updater).to receive(:update_bill_item).once + updater.split_for_trial(enterprise, begins_at, ends_at, trial_start, trial_expiry) + end + + it "calls update_bill_item once for the entire period" do + expect(updater).to have_received(:update_bill_item) + .with(enterprise, begins_at, ends_at, false) + end + end + + context "and the trial ends after begins_at" do + let(:trial_expiry) { begins_at + 5.days } + + before do + allow(updater).to receive(:update_bill_item).twice + updater.split_for_trial(enterprise, begins_at, ends_at, trial_start, trial_expiry) + end + + it "calls update_bill_item once for the trial period" do + expect(updater).to have_received(:update_bill_item) + .with(enterprise, begins_at, trial_expiry, true) + end + + it "calls update_bill_item once for the non-trial period" do + expect(updater).to have_received(:update_bill_item) + .with(enterprise, trial_expiry, ends_at, false) + end + end + + context "and the trial ends after ends_at" do + let(:trial_expiry) { ends_at + 5.days } + + before do + allow(updater).to receive(:update_bill_item).once + updater.split_for_trial(enterprise, begins_at, ends_at, trial_start, trial_expiry) + end + + it "calls update_bill_item once for the entire (trial) period" do + expect(updater).to have_received(:update_bill_item) + .with(enterprise, begins_at, ends_at, true) + end + end + end + + context "when the trial begins after begins_at" do + let(:trial_start) { begins_at + 5.days } + + context "and the trial begins after ends_at" do + let(:trial_start) { ends_at + 5.days } + let(:trial_expiry) { ends_at + 10.days } + + before do + allow(updater).to receive(:update_bill_item).once + updater.split_for_trial(enterprise, begins_at, ends_at, trial_start, trial_expiry) + end + + it "calls update_bill_item once for the entire period" do + expect(updater).to have_received(:update_bill_item) + .with(enterprise, begins_at, ends_at, false) + end + end + + context "and the trial ends before ends_at" do + let(:trial_expiry) { ends_at - 2.days } + + before do + allow(updater).to receive(:update_bill_item).exactly(3).times + updater.split_for_trial(enterprise, begins_at, ends_at, trial_start, trial_expiry) + end + + it "calls update_bill_item once for the non-trial period before the trial" do + expect(updater).to have_received(:update_bill_item) + .with(enterprise, begins_at, trial_start, false) + end + + it "calls update_bill_item once for the trial period" do + expect(updater).to have_received(:update_bill_item) + .with(enterprise, trial_start, trial_expiry, true) + end + + it "calls update_bill_item once for the non-trial period after the trial" do + expect(updater).to have_received(:update_bill_item) + .with(enterprise, trial_expiry, ends_at, false) + end + end + + context "and the trial ends after ends_at" do + let(:trial_expiry) { ends_at + 5.days } + + before do + allow(updater).to receive(:update_bill_item).twice + updater.split_for_trial(enterprise, begins_at, ends_at, trial_start, trial_expiry) + end + + it "calls update_bill_item once for the non-trial period" do + expect(updater).to have_received(:update_bill_item) + .with(enterprise, begins_at, trial_start, false) + end + + it "calls update_bill_item once for the trial period" do + expect(updater).to have_received(:update_bill_item) + .with(enterprise, trial_start, ends_at, true) + end + end + end + end + + describe "update_bill_item" do + let!(:enterprise) { create(:enterprise, sells: 'any') } + + let!(:existing) { create(:bill_item, enterprise: enterprise, begins_at: start_of_july) } + + context "when arguments match both 'begins_at' and 'enterprise_id' of an existing bill item" do + it "updates the existing bill item" do + expect{ + updater.update_bill_item(enterprise, start_of_july, start_of_july + 20.days, false) + }.to_not change{ BillItem.count } + existing.reload + expect(existing.owner_id).to eq enterprise.owner_id + expect(existing.ends_at).to eq start_of_july + 20.days + expect(existing.sells).to eq enterprise.sells + expect(existing.trial).to eq false + end + end + + context "when 'begins_at' does not match an existing bill item" do + before do + expect{ + updater.update_bill_item(enterprise, start_of_july + 20.days, start_of_july + 30.days, false) + }.to change{ BillItem.count }.from(1).to(2) + end + + it "creates a new existing bill item" do + bill_item = BillItem.last + expect(bill_item.owner_id).to eq enterprise.owner_id + expect(bill_item.ends_at).to eq start_of_july + 30.days + expect(bill_item.sells).to eq enterprise.sells + expect(bill_item.trial).to eq false + end + end + + context "when 'enterprise_id' does not match an existing bill item" do + let!(:new_enterprise) { create(:enterprise, sells: 'own') } + + before do + expect{ + updater.update_bill_item(new_enterprise, start_of_july, start_of_july + 20.days, false) + }.to change{ BillItem.count }.from(1).to(2) + end + + it "creates a new existing bill item" do + bill_item = BillItem.last + expect(bill_item.owner_id).to eq new_enterprise.owner_id + expect(bill_item.ends_at).to eq start_of_july + 20.days + expect(bill_item.sells).to eq new_enterprise.sells + expect(bill_item.trial).to eq false + end + end + end + end + + describe "validation tests" do # Chose july to test with because June has 30 days and so is easy to calculate end date for shop trial let!(:start_of_july) { Time.now.beginning_of_year + 6.months } @@ -23,7 +395,7 @@ describe UpdateBillItems do enterprise.update_attribute(:created_at, start_of_july - 2.months) end - context "where the sells property of the enterprise has not been altered within the current billing period" do + context "where the sells and owner_id properties of the enterprise have not been altered within the current billing period" do before do Timecop.travel(start_of_july + 28.days) end @@ -34,7 +406,7 @@ describe UpdateBillItems do context "where no trial information has been set" do before do - UpdateBillItems.new('lala').perform + UpdateBillItems.new.perform end let(:bill_items) { BillItem.order(:id) } @@ -52,7 +424,7 @@ describe UpdateBillItems do context "where a trial ended during the current billing period" do before do enterprise.update_attribute(:shop_trial_start_date, start_of_july - 10.days) - UpdateBillItems.new('lala').perform + UpdateBillItems.new.perform end let(:bill_items) { BillItem.order(:id) } @@ -72,7 +444,7 @@ describe UpdateBillItems do context "where the trial began part-way through the current billing period" do before do enterprise.update_attribute(:shop_trial_start_date, start_of_july + 10.days) - UpdateBillItems.new('lala').perform + UpdateBillItems.new.perform end let(:bill_items) { BillItem.order(:id) } @@ -106,7 +478,7 @@ describe UpdateBillItems do context "where no trial information has been set" do before do - UpdateBillItems.new('lala').perform + UpdateBillItems.new.perform end let(:bill_items) { BillItem.order(:id) } @@ -126,7 +498,7 @@ describe UpdateBillItems do context "where a trial ended during the current billing period, after sells was changed" do before do enterprise.update_attribute(:shop_trial_start_date, start_of_july - 10.days) - UpdateBillItems.new('lala').perform + UpdateBillItems.new.perform end let(:bill_items) { BillItem.order(:id) } @@ -147,7 +519,7 @@ describe UpdateBillItems do context "where a trial ended during the current billing period, before sells was changed" do before do enterprise.update_attribute(:shop_trial_start_date, start_of_july - 22.days) - UpdateBillItems.new('lala').perform + UpdateBillItems.new.perform end let(:bill_items) { BillItem.order(:id) } @@ -168,7 +540,7 @@ describe UpdateBillItems do context "where the trial began part-way through the current billing period, after sells was changed" do before do enterprise.update_attribute(:shop_trial_start_date, start_of_july + 18.days) - UpdateBillItems.new('lala').perform + UpdateBillItems.new.perform end let(:bill_items) { BillItem.order(:id) } @@ -189,7 +561,7 @@ describe UpdateBillItems do context "where the trial began part-way through the current billing period, before sells was changed" do before do enterprise.update_attribute(:shop_trial_start_date, start_of_july + 8.days) - UpdateBillItems.new('lala').perform + UpdateBillItems.new.perform end let(:bill_items) { BillItem.order(:id) } @@ -207,6 +579,142 @@ describe UpdateBillItems do end end end + + context "where the owner_id property of the enterprise has been altered within the current billing period" do + let!(:original_owner) { enterprise.owner } + let!(:new_owner) { create(:user) } + + before do + Timecop.freeze(start_of_july + 10.days) do + # NOTE: Sells is changed between when order1 and order2 are placed + enterprise.update_attribute(:owner, new_owner) + end + + Timecop.travel(start_of_july + 28.days) + end + + after do + Timecop.return + end + + context "where no trial information has been set" do + before do + UpdateBillItems.new.perform + end + + let(:bill_items) { BillItem.order(:id) } + + it "splits the billing period into a separate item for each owner" do + expect(bill_items.count).to eq 2 + expect(bill_items.map(&:owner_id)).to eq [original_owner.id, new_owner.id] + expect(bill_items.map(&:sells)).to eq ['any', 'any'] + expect(bill_items.map(&:trial)).to eq [false, false] + expect(bill_items.map(&:begins_at)).to eq [start_of_july, start_of_july + 10.days] + expect(bill_items.map(&:ends_at)).to eq [start_of_july + 10.days, start_of_july + 28.days] + end + + it "splits the turnover for the month to date" do + expect(bill_items.first.turnover).to eq order1.total + expect(bill_items.last.turnover).to eq order2.total + order3.total + end + end + + context "where a trial ended during the current billing period, after owner was changed" do + before do + enterprise.update_attribute(:shop_trial_start_date, start_of_july - 10.days) + UpdateBillItems.new.perform + end + + let(:bill_items) { BillItem.order(:id) } + + it "splits out the distinct ownership periods and trial period into separate bill items" do + expect(bill_items.count).to eq 3 + expect(bill_items.map(&:owner_id)).to eq [original_owner.id, new_owner.id, new_owner.id] + expect(bill_items.map(&:sells)).to eq ['any', 'any', 'any'] + expect(bill_items.map(&:trial)).to eq [true, true, false] + expect(bill_items.map(&:begins_at)).to eq [start_of_july, start_of_july + 10.days, start_of_july + 20.days] + expect(bill_items.map(&:ends_at)).to eq [start_of_july + 10.days, start_of_july + 20.days, start_of_july + 28.days] + end + + it "splits out the trial period into a separate bill item" do + expect(bill_items.first.turnover).to eq order1.total + expect(bill_items.second.turnover).to eq order2.total + expect(bill_items.last.turnover).to eq order3.total + end + end + + context "where a trial ended during the current billing period, before owner was changed" do + before do + enterprise.update_attribute(:shop_trial_start_date, start_of_july - 22.days) + UpdateBillItems.new.perform + end + + let(:bill_items) { BillItem.order(:id) } + + it "splits out the distinct sells periods and trial period into separate bill items" do + expect(bill_items.count).to eq 3 + expect(bill_items.map(&:owner_id)).to eq [original_owner.id, original_owner.id, new_owner.id] + expect(bill_items.map(&:sells)).to eq ['any', 'any', 'any'] + expect(bill_items.map(&:trial)).to eq [true, false, false] + expect(bill_items.map(&:begins_at)).to eq [start_of_july, start_of_july + 8.days, start_of_july + 10.days] + expect(bill_items.map(&:ends_at)).to eq [start_of_july + 8.days, start_of_july + 10.days, start_of_july + 28.days] + end + + it "splits out the trial period into a separate bill item" do + expect(bill_items.first.turnover).to eq order1.total + expect(bill_items.second.turnover).to eq 0 + expect(bill_items.last.turnover).to eq (order2.total + order3.total) + end + end + + context "where the trial began part-way through the current billing period, after owner was changed" do + before do + enterprise.update_attribute(:shop_trial_start_date, start_of_july + 18.days) + UpdateBillItems.new.perform + end + + let(:bill_items) { BillItem.order(:id) } + + it "splits out the distinct ownership periods and trial period into separate bill items" do + expect(bill_items.count).to eq 3 + expect(bill_items.map(&:owner_id)).to eq [original_owner.id, new_owner.id, new_owner.id] + expect(bill_items.map(&:sells)).to eq ['any', 'any', 'any'] + expect(bill_items.map(&:trial)).to eq [false, false, true] + expect(bill_items.map(&:begins_at)).to eq [start_of_july, start_of_july + 10.days, start_of_july + 18.days] + expect(bill_items.map(&:ends_at)).to eq [start_of_july + 10.days, start_of_july + 18.days, start_of_july + 28.days] + end + + it "splits out the trial period into a separate bill item" do + expect(bill_items.first.turnover).to eq order1.total + expect(bill_items.second.turnover).to eq order2.total + expect(bill_items.last.turnover).to eq order3.total + end + end + + context "where the trial began part-way through the current billing period, before owner was changed" do + before do + enterprise.update_attribute(:shop_trial_start_date, start_of_july + 8.days) + UpdateBillItems.new.perform + end + + let(:bill_items) { BillItem.order(:id) } + + it "splits out the distinct ownership periods and trial period into separate bill items" do + expect(bill_items.count).to eq 3 + expect(bill_items.map(&:owner_id)).to eq [original_owner.id, original_owner.id, new_owner.id] + expect(bill_items.map(&:sells)).to eq ['any', 'any', 'any'] + expect(bill_items.map(&:trial)).to eq [false, true, true] + expect(bill_items.map(&:begins_at)).to eq [start_of_july, start_of_july + 8.days, start_of_july + 10.days] + expect(bill_items.map(&:ends_at)).to eq [start_of_july + 8.days, start_of_july + 10.days, start_of_july + 28.days] + end + + it "splits out the trial period into a separate bill item" do + expect(bill_items.first.turnover).to eq order1.total + expect(bill_items.second.turnover).to eq 0 + expect(bill_items.last.turnover).to eq (order2.total + order3.total) + end + end + end end context "where the enterprise was created after the beginning of the current billing period", versioning: true do @@ -225,7 +733,7 @@ describe UpdateBillItems do context "where no trial information has been set" do before do - UpdateBillItems.new('lala').perform + UpdateBillItems.new.perform end let(:bill_items) { BillItem.order(:id) } @@ -246,7 +754,7 @@ describe UpdateBillItems do context "where a trial ended during the current billing period" do before do enterprise.update_attribute(:shop_trial_start_date, start_of_july - 10.days) - UpdateBillItems.new('lala').perform + UpdateBillItems.new.perform end let(:bill_items) { BillItem.order(:id) } @@ -268,7 +776,7 @@ describe UpdateBillItems do context "where the trial began part-way through the current billing period" do before do enterprise.update_attribute(:shop_trial_start_date, start_of_july + 10.days) - UpdateBillItems.new('lala').perform + UpdateBillItems.new.perform end let(:bill_items) { BillItem.order(:id) } @@ -304,7 +812,7 @@ describe UpdateBillItems do context "where no trial information has been set" do before do - UpdateBillItems.new('lala').perform + UpdateBillItems.new.perform end let(:bill_items) { BillItem.order(:id) } @@ -326,7 +834,7 @@ describe UpdateBillItems do context "where a trial ended during the current billing period, after sells was changed" do before do enterprise.update_attribute(:shop_trial_start_date, start_of_july - 10.days) - UpdateBillItems.new('lala').perform + UpdateBillItems.new.perform end let(:bill_items) { BillItem.order(:id) } @@ -349,7 +857,7 @@ describe UpdateBillItems do context "where a trial ended during the current billing period, before sells was changed" do before do enterprise.update_attribute(:shop_trial_start_date, start_of_july - 22.days) - UpdateBillItems.new('lala').perform + UpdateBillItems.new.perform end let(:bill_items) { BillItem.order(:id) } @@ -372,7 +880,7 @@ describe UpdateBillItems do context "where the trial began part-way through the current billing period, after sells was changed" do before do enterprise.update_attribute(:shop_trial_start_date, start_of_july + 18.days) - UpdateBillItems.new('lala').perform + UpdateBillItems.new.perform end let(:bill_items) { BillItem.order(:id) } @@ -395,7 +903,7 @@ describe UpdateBillItems do context "where the trial began part-way through the current billing period, before sells was changed" do before do enterprise.update_attribute(:shop_trial_start_date, start_of_july + 8.days) - UpdateBillItems.new('lala').perform + UpdateBillItems.new.perform end let(:bill_items) { BillItem.order(:id) }