Refactoring invoice update process to use new AccountInvoice model

This commit is contained in:
Rob Harrington
2015-09-17 18:49:12 +10:00
parent 77c10dafd6
commit 13adb61b3a
7 changed files with 163 additions and 261 deletions

View File

@@ -1,5 +1,5 @@
class FinalizeAccountInvoices
attr_reader :start_date, :end_date
attr_reader :year, :month, :start_date, :end_date
def initialize(year = nil, month = nil)
ref_point = Time.now - 1.month
@@ -17,21 +17,18 @@ class FinalizeAccountInvoices
def perform
return unless settings_are_valid?
invoices = Spree::Order.where('distributor_id = (?) AND created_at >= (?) AND created_at < (?) AND completed_at IS NULL',
@accounts_distributor, start_date, end_date)
invoices.each do |invoice|
finalize(invoice)
end
invoice_orders = AccountInvoice.where(year: year, month: month).map(&:order)
invoice_orders.select{ |order| order.present? && order.completed_at.nil? }.each{ |order| finalize(order) }
end
def finalize(invoice)
def finalize(invoice_order)
# TODO: When we implement per-customer and/or per-user preferences around shipping and payment methods
# we can update these to read from those preferences
invoice.payments.create(payment_method_id: Spree::Config.default_accounts_payment_method_id, amount: invoice.total)
invoice.update_attribute(:shipping_method_id, Spree::Config.default_accounts_shipping_method_id)
while invoice.state != "complete"
invoice.next
invoice_order.payments.create(payment_method_id: Spree::Config.default_accounts_payment_method_id, amount: invoice_order.total)
invoice_order.update_attribute(:shipping_method_id, Spree::Config.default_accounts_shipping_method_id)
while invoice_order.state != "complete"
invoice_order.next
end
end

View File

@@ -1,5 +1,5 @@
class UpdateAccountInvoices
attr_reader :start_date, :end_date
attr_reader :year, :month, :start_date, :end_date
def initialize(year = nil, month = nil)
ref_point = Time.now - 1.day
@@ -17,43 +17,34 @@ class UpdateAccountInvoices
def perform
return unless settings_are_valid?
# Find all users that have owned an enterprise at some point in the relevant period
enterprise_users = Spree::User.joins(:billable_periods)
.where('billable_periods.begins_at >= (?) AND billable_periods.ends_at <= (?) AND deleted_at IS NULL', start_date, end_date)
.select('DISTINCT spree_users.*')
enterprise_users.each do |user|
billable_periods = user.billable_periods.where('begins_at >= (?) AND ends_at <= (?) AND deleted_at IS NULL', start_date, end_date).order(:enterprise_id, :begins_at)
update_invoice_for(user, billable_periods)
end
account_invoices = AccountInvoice.where(year: year, month: month)
account_invoices.each { |account_invoice| update(account_invoice) }
end
def update_invoice_for(user, billable_periods)
def update(account_invoice)
current_adjustments = []
invoice = user.invoice_for(start_date, end_date)
unless account_invoice.order
account_invoice.order = account_invoice.user.orders.new(distributor_id: Spree::Config[:accounts_distributor_id])
end
if invoice.persisted? && invoice.created_at != start_date
Bugsnag.notify(RuntimeError.new("InvoiceDateConflict"), {
start_date: start_date,
end_date: end_date,
existing_invoice: invoice.as_json
})
elsif invoice.complete?
if account_invoice.order.complete?
Bugsnag.notify(RuntimeError.new("InvoiceAlreadyFinalized"), {
invoice: invoice.as_json
invoice_order: account_invoice.order.as_json
})
else
billable_periods.reject{ |bp| bp.turnover == 0 }.each do |billable_period|
current_adjustments << billable_period.ensure_correct_adjustment_for(invoice)
account_invoice.billable_periods.order(:enterprise_id, :begins_at).reject{ |bp| bp.turnover == 0 }.each do |billable_period|
current_adjustments << billable_period.ensure_correct_adjustment_for(account_invoice.order)
end
end
clean_up_and_save(invoice, current_adjustments)
account_invoice.save if current_adjustments.any?
clean_up(account_invoice.order, current_adjustments)
end
def clean_up_and_save(invoice, current_adjustments)
def clean_up(invoice_order, current_adjustments)
# Snag and then delete any obsolete adjustments
obsolete_adjustments = invoice.adjustments.where('source_type = (?) AND id NOT IN (?)', "BillablePeriod", current_adjustments)
obsolete_adjustments = invoice_order.adjustments.where('source_type = (?) AND id NOT IN (?)', "BillablePeriod", current_adjustments)
if obsolete_adjustments.any?
Bugsnag.notify(RuntimeError.new("Obsolete Adjustments"), {
@@ -64,16 +55,12 @@ class UpdateAccountInvoices
obsolete_adjustments.destroy_all
end
if current_adjustments.any?
# Invoices should be "created" at the beginning of the period to which they apply
invoice.created_at = start_date unless invoice.persisted?
invoice.save
else
if current_adjustments.empty?
Bugsnag.notify(RuntimeError.new("Empty Persisted Invoice"), {
invoice: invoice.as_json
}) if invoice.persisted?
invoice_order: invoice_order.as_json
}) if invoice_order.persisted?
invoice.destroy
invoice_order.destroy
end
end

View File

@@ -48,12 +48,6 @@ Spree.user_class.class_eval do
owned_enterprises(:reload).size < enterprise_limit
end
def invoice_for(start_date, end_date)
existing = orders.where('distributor_id = (?) AND created_at >= (?) AND created_at < (?)',
Spree::Config[:accounts_distributor_id], start_date, end_date).first
existing || orders.new(distributor_id: Spree::Config[:accounts_distributor_id])
end
private
def limit_owned_enterprises

View File

@@ -226,7 +226,7 @@ FactoryGirl.define do
turnover { rand(100000).to_f/100 }
account_invoice do
AccountInvoice.where(user_id: owner_id, year: begins_at.year, month: begins_at.month).first ||
FactoryGirl.create(user: owner, year: begins_at.year, month: begins_at.month)
FactoryGirl.create(:account_invoice, user: owner, year: begins_at.year, month: begins_at.month)
end
end

View File

@@ -9,14 +9,21 @@ describe FinalizeAccountInvoices do
describe "unit specs" do
let!(:finalizer) { FinalizeAccountInvoices.new }
let!(:start_of_july) { Time.now.beginning_of_year + 6.months }
let!(:year) { Time.now.year }
describe "perform" do
let!(:accounts_distributor) { create(:distributor_enterprise) }
let!(:invoice1) { create(:order, distributor: accounts_distributor, created_at: start_of_july - 10.days, completed_at: nil) }
let!(:invoice2) { create(:order, distributor: accounts_distributor, created_at: start_of_july - 10.days, completed_at: start_of_july - 10.days) }
let!(:invoice3) { create(:order, distributor: accounts_distributor, created_at: start_of_july, completed_at: nil) }
let!(:invoice4) { create(:order, distributor: accounts_distributor, created_at: start_of_july + 10.days, completed_at: nil) }
let!(:invoice5) { create(:order, distributor: accounts_distributor, created_at: start_of_july - 30.days, completed_at: nil) }
#Invoice from June
let!(:account_invoice1) { create(:account_invoice, year: year, month: 6, order: create(:order, completed_at: nil))}
# We don't care when it was completed, in the future or past
let!(:account_invoice2) { create(:account_invoice, year: year, month: 6, order: create(:order, completed_at: start_of_july - 10.days))}
let!(:account_invoice3) { create(:account_invoice, year: year, month: 6, order: create(:order, completed_at: start_of_july + 10.days))}
# Invoices from July
let!(:account_invoice4) { create(:account_invoice, year: year, month: 7, order: create(:order, completed_at: nil))}
let!(:account_invoice5) { create(:account_invoice, year: year, month: 7, order: create(:order, completed_at: start_of_july + 10.days))}
before do
allow(Enterprise).to receive(:find_by_id) { accounts_distributor }
@@ -70,38 +77,38 @@ describe FinalizeAccountInvoices do
context "and no date arguments are passed to the job" do
travel_to(3.days)
it "finalizes the uncompleted orders for accounts_distributor created in the previous calendar month" do
it "finalizes the uncompleted orders from account_invoices for the previous calendar month" do
finalizer.perform
expect(finalizer).to have_received(:finalize).with(invoice1)
expect(finalizer).to_not have_received(:finalize).with(invoice3)
expect(finalizer).to_not have_received(:finalize).with(invoice2)
expect(finalizer).to_not have_received(:finalize).with(invoice4)
expect(finalizer).to have_received(:finalize).with(invoice5)
expect(finalizer).to have_received(:finalize).with(account_invoice1.order)
expect(finalizer).to_not have_received(:finalize).with(account_invoice2.order)
expect(finalizer).to_not have_received(:finalize).with(account_invoice3.order)
expect(finalizer).to_not have_received(:finalize).with(account_invoice4.order)
expect(finalizer).to_not have_received(:finalize).with(account_invoice5.order)
end
end
context "and specfic start and end dates are passed as arguments" do
let!(:finalizer) { FinalizeAccountInvoices.new(Time.now.year, 6) }
context "an a specific year and month are passed as arguments" do
let!(:finalizer) { FinalizeAccountInvoices.new(Time.now.year, 7) }
before do
allow(finalizer).to receive(:finalizer)
end
context "that ends in the past" do
travel_to(3.hours)
travel_to(1.month + 3.hours)
it "finalizes the uncompleted orders for accounts_distributor created in the specified calendar month" do
it "finalizes the uncompleted orders from account_invoices for the specified calendar month" do
finalizer.perform
expect(finalizer).to have_received(:finalize).with(invoice1)
expect(finalizer).to_not have_received(:finalize).with(invoice3)
expect(finalizer).to_not have_received(:finalize).with(invoice2)
expect(finalizer).to_not have_received(:finalize).with(invoice4)
expect(finalizer).to have_received(:finalize).with(invoice5)
expect(finalizer).to_not have_received(:finalize).with(account_invoice1.order)
expect(finalizer).to_not have_received(:finalize).with(account_invoice2.order)
expect(finalizer).to_not have_received(:finalize).with(account_invoice3.order)
expect(finalizer).to have_received(:finalize).with(account_invoice4.order)
expect(finalizer).to_not have_received(:finalize).with(account_invoice5.order)
end
end
context "that ends in the future" do
travel_to -1.day
travel_to 3.days
it "does not finalize any orders" do
finalizer.perform

View File

@@ -14,12 +14,14 @@ describe UpdateAccountInvoices do
let!(:old_billable_period) { create(:billable_period, owner: user, begins_at: start_of_july - 1.month, ends_at: start_of_july) }
let!(:billable_period1) { create(:billable_period, owner: user, begins_at: start_of_july, ends_at: start_of_july + 12.days) }
let!(:billable_period2) { create(:billable_period, owner: user, begins_at: start_of_july + 12.days, ends_at: start_of_july + 20.days) }
let(:june_account_invoice) { old_billable_period.account_invoice }
let(:july_account_invoice) { billable_period1.account_invoice }
describe "perform" do
let(:accounts_distributor) { double(:accounts_distributor) }
before do
allow(Enterprise).to receive(:find_by_id) { accounts_distributor }
allow(updater).to receive(:update_invoice_for)
allow(updater).to receive(:update)
allow(Bugsnag).to receive(:notify)
end
@@ -34,7 +36,7 @@ describe UpdateAccountInvoices do
it "snags errors and doesn't run" do
expect(Bugsnag).to have_received(:notify).with(RuntimeError.new("InvalidJobSettings"), anything)
expect(updater).to_not have_received(:update_invoice_for)
expect(updater).to_not have_received(:update)
end
end
end
@@ -43,85 +45,86 @@ describe UpdateAccountInvoices do
context "on the first of the month" do
travel_to(3.hours)
it "updates the user's current invoice with billable_periods from the previous month" do
it "updates invoices from the previous month" do
updater.perform
expect(updater).to have_received(:update_invoice_for).once
.with(user, [old_billable_period])
expect(updater).to have_received(:update).once
.with(june_account_invoice)
expect(updater).to_not have_received(:update)
.with(july_account_invoice)
end
end
context "on other days" do
travel_to(20.days)
it "updates the user's current invoice with billable_periods from the current month" do
it "updates invoices from the current month" do
updater.perform
expect(updater).to have_received(:update_invoice_for).once
.with(user, [billable_period1, billable_period2])
expect(updater).to have_received(:update).once
.with(july_account_invoice)
end
end
context "when specfic start and end dates are passed as arguments" do
context "when specfic a specific month (and year) are passed as arguments" do
let!(:updater) { UpdateAccountInvoices.new(Time.now.year, 7) }
before do
allow(updater).to receive(:update_invoice_for)
allow(updater).to receive(:update)
end
context "that just ended (in the past)" do
travel_to(1.month)
it "updates the user's invoice with billable_periods from the previous month" do
it "updates invoices from the previous month" do
updater.perform
expect(updater).to have_received(:update_invoice_for).once
.with(user, [billable_period1, billable_period2])
expect(updater).to have_received(:update).once
.with(july_account_invoice)
end
end
context "that starts in the past and ends in the future (ie. current_month)" do
travel_to 30.days
it "updates the user's invoice with billable_periods from that current month" do
it "updates invoices from that current month" do
updater.perform
expect(updater).to have_received(:update_invoice_for).once
.with(user, [billable_period1, billable_period2])
expect(updater).to have_received(:update).once
.with(july_account_invoice)
end
end
context "that starts in the future" do
travel_to -1.days
it "snags an error and does not update the user's invoice" do
it "snags an error and does not update invoices" do
updater.perform
expect(Bugsnag).to have_received(:notify).with(RuntimeError.new("InvalidJobSettings"), anything)
expect(updater).to_not have_received(:update_invoice_for)
expect(updater).to_not have_received(:update)
end
end
end
end
end
describe "update_invoice_for" do
let(:invoice) { create(:order, user: user) }
describe "update" do
before do
allow(user).to receive(:invoice_for) { invoice }
allow(updater).to receive(:clean_up_and_save)
allow(june_account_invoice).to receive(:save).and_call_original
allow(july_account_invoice).to receive(:save).and_call_original
allow(updater).to receive(:clean_up)
allow(updater).to receive(:finalize)
allow(Bugsnag).to receive(:notify)
end
context "on the first of the month" do
travel_to(3.hours)
context "where an order for the invoice already exists" do
let!(:invoice_order) { create(:order, user: user) }
before do
allow(old_billable_period).to receive(:adjustment_label) { "Old Item" }
allow(old_billable_period).to receive(:bill) { 666.66 }
expect(Spree::Order).to_not receive(:new)
allow(june_account_invoice).to receive(:order) { invoice_order }
end
context "where the invoice was not created at start_date" do
context "where the order is already complete" do
before do
invoice.update_attribute(:created_at, start_of_july - 1.month + 1.day)
updater.update_invoice_for(user, [old_billable_period])
allow(invoice_order).to receive(:complete?) { true }
updater.update(june_account_invoice)
end
it "snags a bug" do
@@ -129,110 +132,65 @@ describe UpdateAccountInvoices do
end
end
context "where the invoice was created at start_date" do
context "where the order is not complete" do
before do
invoice.update_attribute(:created_at, start_of_july - 1.month)
allow(invoice_order).to receive(:complete?) { false }
updater.update(june_account_invoice)
end
context "where the invoice is already complete" do
before do
allow(invoice).to receive(:complete?) { true }
updater.update_invoice_for(user, [old_billable_period])
end
it "snags a bug" do
expect(Bugsnag).to have_received(:notify)
end
it "creates adjustments for each billing item" do
adjustments = invoice_order.adjustments
expect(adjustments.map(&:source_id)).to eq [old_billable_period.id]
expect(adjustments.map(&:amount)).to eq [old_billable_period.bill]
expect(adjustments.map(&:label)).to eq [old_billable_period.adjustment_label]
end
context "where the invoice is not complete" do
before do
allow(invoice).to receive(:complete?) { false }
updater.update_invoice_for(user, [old_billable_period])
end
it "saves the order" do
expect(june_account_invoice).to have_received(:save)
expect(june_account_invoice.order).to be_persisted
end
it "creates adjustments for each billing item" do
adjustments = invoice.adjustments
expect(adjustments.map(&:source_id)).to eq [old_billable_period.id]
expect(adjustments.map(&:amount)).to eq [666.66]
expect(adjustments.map(&:label)).to eq ["Old Item"]
end
it "cleans up and saves the invoice" do
expect(updater).to have_received(:clean_up_and_save).with(invoice, anything).once
end
it "cleans up the order" do
expect(updater).to have_received(:clean_up).with(invoice_order, anything).once
end
end
end
context "on other days" do
travel_to(20.days)
context "where an order for the invoice does not already exist" do
let!(:accounts_distributor) { create(:distributor_enterprise) }
before do
allow(billable_period1).to receive(:adjustment_label) { "BP1 Item" }
allow(billable_period2).to receive(:adjustment_label) { "BP2 Item" }
allow(billable_period1).to receive(:bill) { 123.45 }
allow(billable_period2).to receive(:bill) { 543.21 }
Spree::Config.set({ accounts_distributor_id: accounts_distributor.id })
updater.update(july_account_invoice)
end
context "where the invoice was not created at start_date" do
before do
invoice.update_attribute(:created_at, start_of_july + 1.day)
updater.update_invoice_for(user, [billable_period1, billable_period2])
end
it "snags a bug" do
expect(Bugsnag).to have_received(:notify)
end
it "creates adjustments for each billing item" do
adjustments = july_account_invoice.order.adjustments
expect(adjustments.map(&:source_id)).to eq [billable_period1.id, billable_period2.id]
expect(adjustments.map(&:amount)).to eq [billable_period1.bill, billable_period2.bill]
expect(adjustments.map(&:label)).to eq [billable_period1.adjustment_label, billable_period2.adjustment_label]
end
context "where the invoice was created at start_date" do
before do
invoice.update_attribute(:created_at, start_of_july)
end
it "saves the order" do
expect(july_account_invoice).to have_received(:save)
expect(july_account_invoice.order).to be_persisted
end
context "where the invoice is already complete" do
before do
allow(invoice).to receive(:complete?) { true }
updater.update_invoice_for(user, [billable_period1, billable_period2])
end
it "snags a bug" do
expect(Bugsnag).to have_received(:notify)
end
end
context "where the invoice is not complete" do
before do
allow(invoice).to receive(:complete?) { false }
updater.update_invoice_for(user, [billable_period1, billable_period2])
end
it "creates adjustments for each billing item" do
adjustments = invoice.adjustments
expect(adjustments.map(&:source_id)).to eq [billable_period1.id, billable_period2.id]
expect(adjustments.map(&:amount)).to eq [123.45, 543.21]
expect(adjustments.map(&:label)).to eq ["BP1 Item", "BP2 Item"]
end
it "cleans up and saves the invoice" do
expect(updater).to have_received(:clean_up_and_save).with(invoice, anything).once
end
end
it "cleans up order" do
expect(updater).to have_received(:clean_up).with(july_account_invoice.order, anything).once
end
end
end
describe "clean_up_and_save" do
let!(:invoice) { create(:order) }
let!(:obsolete1) { create(:adjustment, adjustable: invoice) }
let!(:obsolete2) { create(:adjustment, adjustable: invoice) }
let!(:current1) { create(:adjustment, adjustable: invoice) }
let!(:current2) { create(:adjustment, adjustable: invoice) }
describe "clean_up" do
let!(:invoice_order) { create(:order) }
let!(:obsolete1) { create(:adjustment, adjustable: invoice_order) }
let!(:obsolete2) { create(:adjustment, adjustable: invoice_order) }
let!(:current1) { create(:adjustment, adjustable: invoice_order) }
let!(:current2) { create(:adjustment, adjustable: invoice_order) }
before do
allow(invoice).to receive(:save)
allow(invoice).to receive(:destroy)
allow(invoice_order).to receive(:save)
allow(invoice_order).to receive(:destroy)
allow(Bugsnag).to receive(:notify)
end
@@ -244,35 +202,27 @@ describe UpdateAccountInvoices do
before do
allow(obsolete_adjustments).to receive(:destroy_all)
allow(invoice).to receive(:adjustments) { double(:adjustments, where: obsolete_adjustments) }
updater.clean_up_and_save(invoice, current_adjustments)
allow(invoice_order).to receive(:adjustments) { double(:adjustments, where: obsolete_adjustments) }
updater.clean_up(invoice_order, current_adjustments)
end
it "destroys obsolete adjustments and snags a bug" do
expect(obsolete_adjustments).to have_received(:destroy_all)
expect(Bugsnag).to have_received(:notify).with(RuntimeError.new("Obsolete Adjustments"), anything)
end
it "saves the invoice" do
expect(invoice).to have_received(:save)
end
end
context "and obsolete adjustments are not present" do
let!(:obsolete_adjustments) { [] }
before do
allow(invoice).to receive(:adjustments) { double(:adjustments, where: obsolete_adjustments) }
updater.clean_up_and_save(invoice, current_adjustments)
allow(invoice_order).to receive(:adjustments) { double(:adjustments, where: obsolete_adjustments) }
updater.clean_up(invoice_order, current_adjustments)
end
it "has no bugs to snag" do
expect(Bugsnag).to_not have_received(:notify)
end
it "saves the invoice" do
expect(invoice).to have_received(:save)
end
end
end
@@ -284,8 +234,8 @@ describe UpdateAccountInvoices do
before do
allow(obsolete_adjustments).to receive(:destroy_all)
allow(invoice).to receive(:adjustments) { double(:adjustments, where: obsolete_adjustments) }
updater.clean_up_and_save(invoice, current_adjustments)
allow(invoice_order).to receive(:adjustments) { double(:adjustments, where: obsolete_adjustments) }
updater.clean_up(invoice_order, current_adjustments)
end
it "destroys obsolete adjustments and snags a bug" do
@@ -293,8 +243,8 @@ describe UpdateAccountInvoices do
expect(Bugsnag).to have_received(:notify).with(RuntimeError.new("Obsolete Adjustments"), anything)
end
it "destroys the invoice and snags a bug" do
expect(invoice).to have_received(:destroy)
it "destroys the order and snags a bug" do
expect(invoice_order).to have_received(:destroy)
expect(Bugsnag).to have_received(:notify).with(RuntimeError.new("Empty Persisted Invoice"), anything)
end
end
@@ -303,16 +253,16 @@ describe UpdateAccountInvoices do
let!(:obsolete_adjustments) { [] }
before do
allow(invoice).to receive(:adjustments) { double(:adjustments, where: obsolete_adjustments) }
updater.clean_up_and_save(invoice, current_adjustments)
allow(invoice_order).to receive(:adjustments) { double(:adjustments, where: obsolete_adjustments) }
updater.clean_up(invoice_order, current_adjustments)
end
it "has no bugs to snag" do
expect(Bugsnag).to_not have_received(:notify).with(RuntimeError.new("Obsolete Adjustments"), anything)
end
it "destroys the invoice and snags a bug" do
expect(invoice).to have_received(:destroy)
it "destroys the order and snags a bug" do
expect(invoice_order).to have_received(:destroy)
expect(Bugsnag).to have_received(:notify).with(RuntimeError.new("Empty Persisted Invoice"), anything)
end
end
@@ -331,64 +281,67 @@ describe UpdateAccountInvoices do
let!(:billable_period1) { create(:billable_period, sells: 'any', owner: user, begins_at: start_of_july - 1.month, ends_at: start_of_july) }
let!(:billable_period2) { create(:billable_period, owner: user, begins_at: start_of_july, ends_at: start_of_july + 10.days) }
let!(:billable_period3) { create(:billable_period, owner: user, begins_at: start_of_july + 12.days, ends_at: start_of_july + 20.days) }
let!(:july_account_invoice) { billable_period2.account_invoice }
before do
Spree::Config.set({ accounts_distributor_id: accounts_distributor.id })
end
context "when no invoice currently exists" do
context "when no invoice_order currently exists" do
context "when relevant billable periods exist" do
travel_to(20.days)
it "creates an invoice" do
it "creates an invoice_order" do
expect{updater.perform}.to change{Spree::Order.count}.from(0).to(1)
invoice = user.orders.first
expect(invoice.completed_at).to be_nil
billable_adjustments = invoice.adjustments.where('source_type = (?)', 'BillablePeriod')
invoice_order = july_account_invoice.reload.order
expect(user.orders.first).to eq invoice_order
expect(invoice_order.completed_at).to be_nil
billable_adjustments = invoice_order.adjustments.where('source_type = (?)', 'BillablePeriod')
expect(billable_adjustments.map(&:amount)).to eq [billable_period2.bill, billable_period3.bill]
expect(invoice.total).to eq billable_period2.bill + billable_period3.bill
expect(invoice.payments.count).to eq 0
expect(invoice.state).to eq 'cart'
expect(invoice_order.total).to eq billable_period2.bill + billable_period3.bill
expect(invoice_order.payments.count).to eq 0
expect(invoice_order.state).to eq 'cart'
end
end
context "when no relevant billable periods exist" do
travel_to(1.month + 5.days)
it "does not create an invoice" do
it "does not create an order" do
expect{updater.perform}.to_not change{Spree::Order.count}.from(0)
end
end
end
context "when an invoice currently exists" do
let!(:invoice) { create(:order, user: user, distributor: accounts_distributor, created_at: start_of_july) }
let!(:billable_adjustment) { create(:adjustment, adjustable: invoice, source_type: 'BillablePeriod') }
context "when an order already exists" do
let!(:invoice_order) { create(:order, user: user, distributor: accounts_distributor, created_at: start_of_july) }
let!(:billable_adjustment) { create(:adjustment, adjustable: invoice_order, source_type: 'BillablePeriod') }
before do
invoice.line_items.clear
invoice_order.line_items.clear
july_account_invoice.update_attribute(:order, invoice_order)
end
context "when relevant billable periods exist" do
travel_to(20.days)
it "updates the invoice, and clears any obsolete invoices" do
it "updates the order, and clears any obsolete invoices" do
expect{updater.perform}.to_not change{Spree::Order.count}
invoice = user.orders.first
expect(invoice.completed_at).to be_nil
billable_adjustments = invoice.adjustments.where('source_type = (?)', 'BillablePeriod')
invoice_order = user.orders.first
expect(invoice_order.completed_at).to be_nil
billable_adjustments = invoice_order.adjustments.where('source_type = (?)', 'BillablePeriod')
expect(billable_adjustments).to_not include billable_adjustment
expect(billable_adjustments.map(&:amount)).to eq [billable_period2.bill, billable_period3.bill]
expect(invoice.total).to eq billable_period2.bill + billable_period3.bill
expect(invoice.payments.count).to eq 0
expect(invoice.state).to eq 'cart'
expect(invoice_order.total).to eq billable_period2.bill + billable_period3.bill
expect(invoice_order.payments.count).to eq 0
expect(invoice_order.state).to eq 'cart'
end
end
context "when no relevant billable periods exist" do
travel_to(1.month + 5.days)
it "destroys the invoice" do
it "destroys the order" do
expect{updater.perform}.to_not change{Spree::Order.count}.from(1).to(0)
end
end

View File

@@ -79,40 +79,4 @@ describe Spree.user_class do
end
end
end
describe "invoice_for" do
let!(:user) { create(:user) }
let!(:accounts_distributor) { create(:distributor_enterprise) }
let!(:start_of_month) { Time.now.beginning_of_month }
before do
Spree::Config.accounts_distributor_id = accounts_distributor.id
end
context "where no relevant invoice exists for the given period" do
# Created during previous month
let!(:order1) { create(:order, user: user, created_at: start_of_month - 3.hours, completed_at: nil, distributor: accounts_distributor) }
# Incorrect distributor
let!(:order3) { create(:order, user: user, created_at: start_of_month + 3.hours, completed_at: nil, distributor: create(:distributor_enterprise)) }
# Incorrect user
let!(:order4) { create(:order, user: create(:user), created_at: start_of_month + 3.hours, completed_at: nil, distributor: accounts_distributor) }
it "creates a new invoice" do
current_invoice = user.invoice_for(start_of_month, start_of_month + 20.days)
expect(current_invoice).to be_a_new Spree::Order
expect(current_invoice.completed_at).to be nil
expect(current_invoice.distributor).to eq accounts_distributor
expect(current_invoice.user).to eq user
end
end
context "where an invoice exists for the current month" do
let!(:order) { create(:order, user: user, created_at: start_of_month + 3.hours, completed_at: nil, distributor: accounts_distributor) }
it "returns the existing invoice" do
current_invoice = user.invoice_for(start_of_month, start_of_month + 20.days)
expect(current_invoice).to eq order
end
end
end
end