diff --git a/app/jobs/update_bill_items.rb b/app/jobs/update_bill_items.rb index 6867f64466..00dfd333db 100644 --- a/app/jobs/update_bill_items.rb +++ b/app/jobs/update_bill_items.rb @@ -5,11 +5,11 @@ UpdateBillItems = Struct.new(:lala) do start_date = (Time.now - 1.day).beginning_of_month end_date = Time.now.beginning_of_day - enterprises = Enterprise.select([:id, :name, :owner_id, :sells, :shop_trial_start_date]) + enterprises = Enterprise.select([:id, :name, :owner_id, :sells, :shop_trial_start_date, :created_at]) - # Cycle through users + # Cycle through enterprises enterprises.each do |enterprise| - # Cycle through owned_enterprises + # Cycle through previous versions of this enterprise versions = enterprise.versions.where('created_at >= (?)', start_date) bill_items = [] @@ -17,7 +17,7 @@ UpdateBillItems = Struct.new(:lala) do trial_expiry = enterprise.shop_trial_expiry versions.each do |version| - begins_at = bill_items.last.andand.ends_at || start_date + begins_at = bill_items.last.andand.ends_at || [start_date, enterprise.created_at].max ends_at = version.created_at split_for_trial(version.reify, begins_at, ends_at, trial_start, trial_expiry).each do |bill_item| @@ -26,7 +26,7 @@ UpdateBillItems = Struct.new(:lala) do end # Update / create bill_item for current start - begins_at = bill_items.last.andand.ends_at || start_date + begins_at = bill_items.last.andand.ends_at || [start_date, enterprise.created_at].max ends_at = end_date split_for_trial(enterprise, begins_at, ends_at, trial_start, trial_expiry).each do |bill_item| diff --git a/spec/jobs/update_bill_items_spec.rb b/spec/jobs/update_bill_items_spec.rb index bc20108654..6d94999f22 100644 --- a/spec/jobs/update_bill_items_spec.rb +++ b/spec/jobs/update_bill_items_spec.rb @@ -5,18 +5,22 @@ describe UpdateBillItems 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 } + let!(:enterprise) { create(:supplier_enterprise, sells: 'any') } + + let!(:order1) { create(:order, completed_at: start_of_july + 5.days, distributor: enterprise) } + let!(:order2) { create(:order, completed_at: start_of_july + 15.days, distributor: enterprise) } + let!(:order3) { create(:order, completed_at: start_of_july + 25.days, distributor: enterprise) } + + before do + order1.line_items = [ create(:line_item, price: 12.56, order: order1) ] + order2.line_items = [ create(:line_item, price: 87.44, order: order2) ] + order3.line_items = [ create(:line_item, price: 50.00, order: order3) ] + [order1, order2, order3].each(&:update!) + end + context "where the enterprise existed at the beginning of the current billing period", versioning: true do - let!(:enterprise) { create(:supplier_enterprise, created_at: start_of_july - 2.months, sells: 'any') } - - let!(:order1) { create(:order, completed_at: start_of_july + 5.days, distributor: enterprise) } - let!(:order2) { create(:order, completed_at: start_of_july + 15.days, distributor: enterprise) } - let!(:order3) { create(:order, completed_at: start_of_july + 25.days, distributor: enterprise) } - before do - order1.line_items = [ create(:line_item, price: 12.56, order: order1) ] - order2.line_items = [ create(:line_item, price: 87.44, order: order2) ] - order3.line_items = [ create(:line_item, price: 50.00, order: order3) ] - [order1, order2, order3].each(&:update!) + 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 @@ -88,7 +92,7 @@ describe UpdateBillItems do context "where the sells property of the enterprise has been altered within the current billing period" do before do - Timecop.travel(start_of_july + 10.days) 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 @@ -110,6 +114,7 @@ describe UpdateBillItems do it "splits the billing period into a separate item for each sells value" do expect(bill_items.count).to eq 2 expect(bill_items.map(&:sells)).to eq ['any', 'own'] + expect(bill_items.map(&:trial)).to eq [false, false] end it "splits the turnover for the month to date" do @@ -121,10 +126,6 @@ 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) - Timecop.travel(start_of_july + 10.days) do - # NOTE: Sells is changed between when order1 and order2 are placed - enterprise.update_attribute(:sells, 'own') - end UpdateBillItems.new('lala').perform end @@ -208,10 +209,212 @@ describe UpdateBillItems do end end - context "where the enterprise was created after the beginning of the current billing period" do + context "where the enterprise was created after the beginning of the current billing period", versioning: true do + before do + enterprise.update_attribute(:created_at, start_of_july + 7.days) + end + context "where the sells property of the enterprise has not been altered within the current billing period" do + before do + 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('lala').perform + end + + let(:bill_items) { BillItem.order(:id) } + + it "creates a single bill item" do + expect(bill_items.count).to eq 1 + expect(bill_items.map(&:sells)).to eq ['any'] + expect(bill_items.map(&:trial)).to eq [false] + expect(bill_items.map(&:begins_at)).to eq [start_of_july + 7.days] + expect(bill_items.map(&:ends_at)).to eq [start_of_july + 28.days] + end + + it "ignores orders completed before the enterprise was created" do + expect(bill_items.first.turnover).to eq (order2.total + order3.total) + end + end + + 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 + end + + let(:bill_items) { BillItem.order(:id) } + + it "splits out the trial period into a separate bill item" do + expect(bill_items.count).to eq 2 + expect(bill_items.map(&:sells)).to eq ['any', 'any'] + expect(bill_items.map(&:trial)).to eq [true, false] + expect(bill_items.map(&:begins_at)).to eq [start_of_july + 7.days, start_of_july + 20.days] + expect(bill_items.map(&:ends_at)).to eq [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 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" do + before do + enterprise.update_attribute(:shop_trial_start_date, start_of_july + 10.days) + UpdateBillItems.new('lala').perform + end + + let(:bill_items) { BillItem.order(:id) } + + it "splits out the trial period into a separate bill item" do + expect(bill_items.count).to eq 2 + expect(bill_items.map(&:sells)).to eq ['any', 'any'] + expect(bill_items.map(&:trial)).to eq [false, true] + expect(bill_items.map(&:begins_at)).to eq [start_of_july + 7.days, 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 0 + expect(bill_items.last.turnover).to eq order2.total + order3.total + end + end + end + + context "where the sells property of the enterprise has been altered within the current billing period" 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 + + 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('lala').perform + end + + let(:bill_items) { BillItem.order(:id) } + + it "splits the billing period into a separate item for each sells value" do + expect(bill_items.count).to eq 2 + expect(bill_items.map(&:sells)).to eq ['any', 'own'] + expect(bill_items.map(&:trial)).to eq [false, false] + expect(bill_items.map(&:begins_at)).to eq [start_of_july + 7.days, 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 0 + expect(bill_items.last.turnover).to eq order2.total + order3.total + end + end + + 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 + 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(&:sells)).to eq ['any', 'own', 'own'] + expect(bill_items.map(&:trial)).to eq [true, true, false] + expect(bill_items.map(&:begins_at)).to eq [start_of_july + 7.days, 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 0 + 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 sells was changed" do + before do + enterprise.update_attribute(:shop_trial_start_date, start_of_july - 22.days) + UpdateBillItems.new('lala').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(&:sells)).to eq ['any', 'any', 'own'] + expect(bill_items.map(&:trial)).to eq [true, false, false] + expect(bill_items.map(&:begins_at)).to eq [start_of_july + 7.days, 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 0 + 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 sells was changed" do + before do + enterprise.update_attribute(:shop_trial_start_date, start_of_july + 18.days) + UpdateBillItems.new('lala').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(&:sells)).to eq ['any', 'own', 'own'] + expect(bill_items.map(&:trial)).to eq [false, false, true] + expect(bill_items.map(&:begins_at)).to eq [start_of_july + 7.days, 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 0 + 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 sells was changed" do + before do + enterprise.update_attribute(:shop_trial_start_date, start_of_july + 8.days) + UpdateBillItems.new('lala').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(&:sells)).to eq ['any', 'any', 'own'] + expect(bill_items.map(&:trial)).to eq [false, true, true] + expect(bill_items.map(&:begins_at)).to eq [start_of_july + 7.days, 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 0 + expect(bill_items.second.turnover).to eq 0 + expect(bill_items.last.turnover).to eq (order2.total + order3.total) + end + end + end end end - - end