mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Merge pull request #11084 from abdellani/update_invoice_status_automatically
set invoice status automatically after creation
This commit is contained in:
@@ -4,6 +4,7 @@ class Invoice < ApplicationRecord
|
||||
belongs_to :order, class_name: 'Spree::Order'
|
||||
serialize :data, Hash
|
||||
before_validation :serialize_order
|
||||
after_create :cancel_previous_invoices
|
||||
|
||||
def presenter
|
||||
@presenter ||= Invoice::DataPresenter.new(self)
|
||||
@@ -14,4 +15,8 @@ class Invoice < ApplicationRecord
|
||||
|
||||
self.data = Invoice::OrderSerializer.new(order).serializable_hash
|
||||
end
|
||||
|
||||
def cancel_previous_invoices
|
||||
order.invoices.where.not(id:).update_all(cancelled: true)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
%td.align-center.label
|
||||
= invoice.presenter.total
|
||||
%td.align-center.label
|
||||
= t(invoice.status)
|
||||
= t(invoice.cancelled ? :cancelled : :active)
|
||||
%td.align-center.label
|
||||
=link_to(t(:download),print_admin_order_path(@order,invoice_id: invoice.id),target: "_blank")
|
||||
|
||||
|
||||
@@ -394,6 +394,11 @@ en:
|
||||
confirm_resend_order_confirmation: "Are you sure you want to resend the order confirmation email?"
|
||||
must_have_valid_business_number: "%{enterprise_name} must have a valid ABN before invoices can be sent."
|
||||
invoice: "Invoice"
|
||||
invoices: "Invoices"
|
||||
file: "File"
|
||||
active: "Active"
|
||||
download: "Download"
|
||||
cancelled: "Cancelled"
|
||||
more: "More"
|
||||
say_no: "No"
|
||||
say_yes: "Yes"
|
||||
|
||||
14
db/migrate/20230629015322_set_default_invoice_status.rb
Normal file
14
db/migrate/20230629015322_set_default_invoice_status.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class SetDefaultInvoiceStatus < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_column :invoices, :cancelled, :boolean, default: false, null: false
|
||||
ActiveRecord::Base.connection.execute(<<-SQL.squish
|
||||
UPDATE invoices
|
||||
SET cancelled = true
|
||||
WHERE status = 'inactive'
|
||||
SQL
|
||||
)
|
||||
remove_column :invoices, :status, :string
|
||||
end
|
||||
end
|
||||
@@ -306,12 +306,12 @@ ActiveRecord::Schema[7.0].define(version: 2023_07_06_033212) do
|
||||
|
||||
create_table "invoices", force: :cascade do |t|
|
||||
t.bigint "order_id"
|
||||
t.string "status"
|
||||
t.integer "number"
|
||||
t.jsonb "data"
|
||||
t.date "date", default: -> { "CURRENT_TIMESTAMP" }
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.boolean "cancelled", default: false, null: false
|
||||
t.index ["order_id"], name: "index_invoices_on_order_id"
|
||||
end
|
||||
|
||||
|
||||
@@ -3,18 +3,18 @@
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Invoice, type: :model do
|
||||
let(:distributor) { create(:distributor_enterprise) }
|
||||
let(:order) { create(:order, :with_line_item, :completed, distributor:) }
|
||||
describe 'presenter' do
|
||||
it 'should return an instance of Invoice::DataPresenter' do
|
||||
invoice = create(:invoice)
|
||||
invoice = create(:invoice, order:)
|
||||
expect(invoice.presenter).to be_a(Invoice::DataPresenter)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'serialize_order' do
|
||||
let!(:distributor) { create(:distributor_enterprise) }
|
||||
let!(:order) { create(:order, :with_line_item, :completed, distributor: distributor) }
|
||||
it 'serializes the order' do
|
||||
invoice = create(:invoice, order: order)
|
||||
invoice = create(:invoice, order:)
|
||||
expect(invoice.data).to eq(Invoice::OrderSerializer.new(order).serializable_hash)
|
||||
end
|
||||
end
|
||||
|
||||
104
spec/system/admin/orders/invoices_spec.rb
Normal file
104
spec/system/admin/orders/invoices_spec.rb
Normal file
@@ -0,0 +1,104 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'system_helper'
|
||||
|
||||
describe '
|
||||
As an administrator
|
||||
I want to create an invoice for an order
|
||||
' do
|
||||
include WebHelper
|
||||
include AuthenticationHelper
|
||||
|
||||
let(:user) { create(:user) }
|
||||
let(:product) { create(:simple_product) }
|
||||
let(:distributor) { create(:distributor_enterprise, owner: user, charges_sales_tax: true) }
|
||||
let(:order_cycle) do
|
||||
create(:simple_order_cycle, name: 'One', distributors: [distributor],
|
||||
variants: [product.variants.first])
|
||||
end
|
||||
|
||||
let(:order) do
|
||||
create(:order_with_totals_and_distribution,
|
||||
distributor:, user:,
|
||||
order_cycle:, state: 'complete',
|
||||
payment_state: 'balance_due')
|
||||
end
|
||||
let(:customer) { order.customer }
|
||||
|
||||
before do
|
||||
Flipper.enable(:invoices)
|
||||
order.finalize!
|
||||
login_as_admin
|
||||
visit spree.edit_admin_order_path(order)
|
||||
end
|
||||
|
||||
context 'when the order has no invoices' do
|
||||
it 'creates an invoice for the order' do
|
||||
click_link 'Invoices'
|
||||
|
||||
expect {
|
||||
click_link 'New Invoice'
|
||||
expect(page).to have_no_link "New Invoice"
|
||||
}.to change { order.invoices.count }.by(1)
|
||||
|
||||
invoice = order.invoices.first
|
||||
expect(invoice.cancelled).to eq false
|
||||
expect(invoice.number).to eq 1
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the order has an invoice' do
|
||||
let!(:latest_invoice){ create(:invoice, order:, number: 1, cancelled: false) }
|
||||
|
||||
context 'order not updated since latest invoice' do
|
||||
it 'should not render new invoice button' do
|
||||
click_link 'Invoices'
|
||||
expect(page).to_not have_link 'New Invoice'
|
||||
end
|
||||
end
|
||||
|
||||
# For reference check:
|
||||
# https://docs.google.com/spreadsheets/d/1hOM6UL4mWeRCFLcDQ3fTkbhbUQ2WvIUCCA1IerDBtUA/edit#gid=0
|
||||
context 'order updated since latest invoice' do
|
||||
context 'changes require regenerating' do
|
||||
let(:new_note){ 'new note' }
|
||||
before do
|
||||
order.update!(note: new_note)
|
||||
end
|
||||
|
||||
it 'updates the lastest invoice for the order' do
|
||||
click_link 'Invoices'
|
||||
expect {
|
||||
click_link 'New Invoice'
|
||||
expect(page).to have_no_link "New Invoice"
|
||||
}.to change { order.reload.invoices.count }.by(0)
|
||||
.and change { latest_invoice.reload.presenter.note }.from("").to(new_note)
|
||||
|
||||
expect(latest_invoice.reload.cancelled).to eq false
|
||||
end
|
||||
end
|
||||
|
||||
context 'changes require generating a new invoice' do
|
||||
before do
|
||||
order.line_items.first.update!(quantity: 2)
|
||||
end
|
||||
|
||||
it 'creates a new invoice for the order' do
|
||||
click_link 'Invoices'
|
||||
expect {
|
||||
click_link 'New Invoice'
|
||||
expect(page).to have_no_link "New Invoice"
|
||||
}.to change { order.reload.invoices.count }.by(1)
|
||||
|
||||
expect(latest_invoice.reload.cancelled).to eq true
|
||||
expect(latest_invoice.presenter.sorted_line_items.first.quantity).to eq 1
|
||||
|
||||
new_invoice = order.invoices.last
|
||||
expect(new_invoice.cancelled).to eq false
|
||||
expect(new_invoice.number).to eq 2
|
||||
expect(new_invoice.presenter.sorted_line_items.first.quantity).to eq 2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user