mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
implement the invoice data generator
This commit is contained in:
committed by
Konrad
parent
d9efd10ac0
commit
fa14dc370b
@@ -1,4 +1,4 @@
|
||||
class Invoice::LineItemSerializer < ActiveModel::Serializer
|
||||
attributes :added_tax, :currency, :included_tax, :price_with_adjustments, :quantity, :variant_id
|
||||
attributes :id, :added_tax, :currency, :included_tax, :price_with_adjustments, :quantity, :variant_id
|
||||
has_one :variant, serializer: Invoice::VariantSerializer
|
||||
end
|
||||
|
||||
64
app/services/invoice_data_generator.rb
Normal file
64
app/services/invoice_data_generator.rb
Normal file
@@ -0,0 +1,64 @@
|
||||
class InvoiceDataGenerator
|
||||
attr :order
|
||||
|
||||
def initialize(order)
|
||||
@order = order
|
||||
end
|
||||
|
||||
# Give the latest invoice's data and the currect order data
|
||||
# we want to generate a new invoice data that:
|
||||
# 1. keeps the immutable attributes
|
||||
# 2. include the update details from the order
|
||||
def generate
|
||||
return new_data if old_data.nil?
|
||||
|
||||
# keep the immutable attributes
|
||||
update_order_attributes
|
||||
update_line_items
|
||||
update_payment_methods
|
||||
|
||||
new_data
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_order_attributes
|
||||
[:distributor, :order_cycle, :customer].each do |attribute|
|
||||
new_data[attribute] = old_data[attribute]
|
||||
end
|
||||
|
||||
return unless new_data[:shipping_method_id] == old_data[:shipping_method_id]
|
||||
|
||||
new_data[:shipping_method] = old_data[:shipping_method]
|
||||
end
|
||||
|
||||
# if the variant, product or supplier details are updated
|
||||
# we want to keep the old details in the invoice
|
||||
def update_line_items
|
||||
new_data[:sorted_line_items].each do |new_line_item|
|
||||
old_line_item = old_data[:sorted_line_items].find { |li| li[:id] == new_line_item[:id] }
|
||||
next if old_line_item.nil?
|
||||
|
||||
new_line_item[:variant] = old_line_item[:variant]
|
||||
end
|
||||
end
|
||||
|
||||
# if the payment method is updated,
|
||||
# we want to keep the old payment method in the invoice
|
||||
def update_payment_methods
|
||||
new_data[:payments].each do |new_payment|
|
||||
old_payment = old_data[:payments].find { |p| p[:id] == new_payment[:id] }
|
||||
next if old_payment.nil?
|
||||
|
||||
new_payment[:payment_method] = old_payment[:payment_method]
|
||||
end
|
||||
end
|
||||
|
||||
def new_data
|
||||
@new_data ||= order.serialize_for_invoice
|
||||
end
|
||||
|
||||
def old_data
|
||||
@old_data ||= order.invoices&.last.data
|
||||
end
|
||||
end
|
||||
79
spec/services/invoice_data_generator_spec.rb
Normal file
79
spec/services/invoice_data_generator_spec.rb
Normal file
@@ -0,0 +1,79 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe InvoiceDataGenerator do
|
||||
describe '#generate' do
|
||||
let!(:order) { create(:completed_order_with_fees) }
|
||||
let!(:latest_invoice){ create(:invoice, order: order, data: order.serialize_for_invoice) }
|
||||
let(:new_invoice_data) {
|
||||
InvoiceDataGenerator.new(order).generate
|
||||
}
|
||||
let(:new_invoice) { create(:invoice, order: order, data: new_invoice_data) }
|
||||
let(:new_invoice_presenter) { new_invoice.presenter }
|
||||
|
||||
context "mutable attribute updated" do
|
||||
it "should reflect the changes" do
|
||||
new_note = "This is an updated note"
|
||||
order.update!(note: new_note)
|
||||
|
||||
expect(new_invoice_presenter.order_note).to eq(new_note)
|
||||
end
|
||||
end
|
||||
|
||||
context "immutable attribute updated" do
|
||||
let!(:old_distributor_name) { latest_invoice.presenter.distributor.abn }
|
||||
it "should not reflect the changes" do
|
||||
order.distributor.update!(name: 'NEW ABN')
|
||||
expect(new_invoice_presenter.distributor.abn).to eq(old_distributor_name)
|
||||
end
|
||||
end
|
||||
|
||||
context "shipping method" do
|
||||
it "should keep the old sm details if the shipping method id doesn't change" do
|
||||
shipping_method = order.shipping_method
|
||||
old_shipping_method_name = shipping_method.name
|
||||
shipping_method.update!(name: "NEW NAME")
|
||||
|
||||
expect(new_invoice_presenter.shipping_method.name).to eq(old_shipping_method_name)
|
||||
end
|
||||
|
||||
it "should update the sm details if the shipping method id is updated" do
|
||||
new_shipping_method = create(:shipping_method)
|
||||
order.distributor.shipping_methods << new_shipping_method
|
||||
order.select_shipping_method new_shipping_method.id
|
||||
|
||||
expect(new_invoice_presenter.shipping_method.name).to eq(new_shipping_method.name)
|
||||
end
|
||||
end
|
||||
|
||||
context "line items" do
|
||||
it "should reflect the changes" do
|
||||
line_item = order.line_items.first
|
||||
new_quantity = line_item.quantity + 1
|
||||
line_item.update!(quantity: new_quantity)
|
||||
|
||||
expect(new_invoice_presenter.sorted_line_items.first.quantity).to eq(new_quantity)
|
||||
end
|
||||
|
||||
it "should not reflect variant changes" do
|
||||
line_item = order.line_items.first
|
||||
old_variant_name = line_item.variant.display_name
|
||||
line_item.variant.update!(display_name: "NEW NAME")
|
||||
|
||||
expect(new_invoice_presenter.sorted_line_items.first.variant.display_name).to eq(old_variant_name)
|
||||
end
|
||||
end
|
||||
|
||||
context "order without invoices" do
|
||||
let!(:order) { create(:completed_order_with_fees) }
|
||||
let(:new_invoice_data) {
|
||||
InvoiceDataGenerator.new(order).generate
|
||||
}
|
||||
|
||||
it "should generate a new invoice" do
|
||||
expect(new_invoice_data).to eql order.serialize_for_invoice
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -5,7 +5,7 @@ require 'spec_helper'
|
||||
describe OrderInvoiceComparator do
|
||||
describe '#can_generate_new_invoice?' do
|
||||
let!(:order) { create(:completed_order_with_fees) }
|
||||
let!(:invoice){ create(:invoice, order: order) }
|
||||
let!(:invoice){ create(:invoice, order: order, data: order.serialize_for_invoice) }
|
||||
let(:current_state_invoice){ order.current_state_invoice }
|
||||
let(:subject) {
|
||||
OrderInvoiceComparator.new.can_generate_new_invoice?(current_state_invoice, invoice)
|
||||
@@ -47,7 +47,7 @@ describe OrderInvoiceComparator do
|
||||
|
||||
describe '#can_update_latest_invoice?' do
|
||||
let!(:order) { create(:completed_order_with_fees) }
|
||||
let!(:invoice){ create(:invoice, order: order) }
|
||||
let!(:invoice){ create(:invoice, order: order, data: order.serialize_for_invoice) }
|
||||
let(:current_state_invoice){ order.current_state_invoice }
|
||||
let(:subject) {
|
||||
OrderInvoiceComparator.new.can_update_latest_invoice?(current_state_invoice, invoice)
|
||||
|
||||
Reference in New Issue
Block a user