mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-04 22:16:08 +00:00
Refactoring invoice update process to use new AccountInvoice model
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user