mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-08 22:56:06 +00:00
The orders file is too big and causes a bottleneck for parallelising specs. Maybe they should be merged with the above specs, but I'm not familiar enough to know for sure.
389 lines
12 KiB
Ruby
389 lines
12 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'system_helper'
|
|
|
|
RSpec.describe '
|
|
As an administrator
|
|
I want to manage invoices for an order
|
|
', feature: :invoices 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, abn: "123456")
|
|
}
|
|
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
|
|
order.finalize!
|
|
login_as_admin
|
|
visit spree.edit_admin_order_path(order)
|
|
end
|
|
|
|
describe 'creating invoices' do
|
|
context 'when the order has no invoices' do
|
|
it 'creates an invoice for the order' do
|
|
click_link 'Invoices'
|
|
|
|
expect {
|
|
click_link "Create or Update Invoice"
|
|
expect(page).not_to have_link "Create or Update 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).not_to have_link "Create or Update 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 "Create or Update Invoice"
|
|
expect(page).not_to have_link "Create or Update 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 "Create or Update Invoice"
|
|
expect(page).not_to have_link "Create or Update 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.first # first invoice is the latest
|
|
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
|
|
|
|
describe 'printing invoices' do
|
|
context 'when the order has no invoices' do
|
|
it 'creates an invoice for the order' do
|
|
expect(order.invoices.count).to eq 0
|
|
page.find("#links-dropdown", text: "ACTIONS").click
|
|
click_link "Print Invoice"
|
|
# wait for PDF to open in new window
|
|
new_window = windows.last
|
|
page.within_window new_window do
|
|
expect(order.invoices.count).to eq 1
|
|
end
|
|
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 '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
|
|
expect(order.invoices.count).to eq 1
|
|
page.find("#links-dropdown", text: "ACTIONS").click
|
|
click_link "Print Invoice"
|
|
new_window = windows.last
|
|
page.within_window new_window do
|
|
expect(order.invoices.count).to eq 1
|
|
end
|
|
expect(latest_invoice.reload.presenter.note).to eq 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
|
|
expect(order.invoices.count).to eq 1
|
|
page.find("#links-dropdown", text: "ACTIONS").click
|
|
click_link "Print Invoice"
|
|
new_window = windows.last
|
|
page.within_window new_window do
|
|
expect(order.invoices.count).to eq 2
|
|
end
|
|
expect(latest_invoice.reload.cancelled).to eq true
|
|
expect(latest_invoice.presenter.sorted_line_items.first.quantity).to eq 1
|
|
|
|
new_invoice = order.invoices.first # first invoice is the latest
|
|
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
|
|
|
|
describe 'listing invoices' do
|
|
let(:date){ Time.current.to_date }
|
|
|
|
let(:first_invoice){ "#{distributor.id}-1" }
|
|
let(:second_invoice){ "#{distributor.id}-2" }
|
|
|
|
let(:row1){
|
|
[
|
|
I18n.l(date, format: :long),
|
|
second_invoice,
|
|
order.total,
|
|
"Active",
|
|
"Download"
|
|
].join(" ")
|
|
}
|
|
|
|
let(:row2){
|
|
[
|
|
I18n.l(date, format: :long),
|
|
first_invoice,
|
|
order.total,
|
|
"Cancelled",
|
|
"Download"
|
|
].join(" ")
|
|
}
|
|
|
|
let(:table_content){
|
|
[
|
|
row1,
|
|
row2
|
|
].join(" ")
|
|
}
|
|
|
|
before do
|
|
create(:invoice, order:, number: 1, cancelled: true, date:)
|
|
create(:invoice, order:, number: 2, cancelled: false, date:)
|
|
end
|
|
|
|
it 'should list the invoices on the reverse order of creation' do
|
|
click_link 'Invoices'
|
|
expect(page).to have_content table_content
|
|
end
|
|
end
|
|
end
|
|
|
|
RSpec.describe "Invoice order states", feature: :invoices do
|
|
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, user:, distributor:,
|
|
order_cycle:, state: 'complete',
|
|
payment_state: 'balance_due')
|
|
end
|
|
let(:customer) { order.customer }
|
|
|
|
before do
|
|
order.finalize!
|
|
|
|
login_as user
|
|
end
|
|
|
|
context "complete" do
|
|
let!(:order1) {
|
|
create(:order_with_totals_and_distribution, user:, distributor:,
|
|
order_cycle:, state: 'complete',
|
|
payment_state: 'balance_due',
|
|
customer_id: customer.id)
|
|
}
|
|
|
|
context "editing the order" do
|
|
before do
|
|
visit spree.edit_admin_order_path(order1)
|
|
end
|
|
|
|
it "displays the invoice tab" do
|
|
expect(page).to have_content "Complete".upcase
|
|
expect(page).to have_content "Invoices".upcase
|
|
end
|
|
end
|
|
|
|
context "visiting the invoices tab" do
|
|
let!(:table_header) {
|
|
[
|
|
"Date/Time",
|
|
"Invoice Number",
|
|
"Amount",
|
|
"Status",
|
|
"File",
|
|
].join(" ").upcase
|
|
}
|
|
|
|
let(:invoice_number){ "#{order.distributor_id}-1" }
|
|
let(:table_contents) {
|
|
[
|
|
Invoice.first.created_at.strftime('%B %d, %Y').to_s,
|
|
invoice_number,
|
|
"0.0",
|
|
"Active",
|
|
"Download"
|
|
].join(" ")
|
|
}
|
|
let(:download_href) {
|
|
"#{spree.print_admin_order_path(order1)}?invoice_id=#{Invoice.last.id}"
|
|
}
|
|
|
|
before do
|
|
Spree::Config[:enterprise_number_required_on_invoices?] = false
|
|
visit spree.admin_order_invoices_path(order1)
|
|
end
|
|
|
|
it "displays the invoices table" do
|
|
# with no invoices, only the table header is displayed
|
|
expect(page).to have_css "table.index"
|
|
expect(page).to have_content "#{customer.first_name} #{customer.last_name} -"
|
|
expect(page.find("table").text).to have_content(table_header)
|
|
|
|
# the New invoice button + the warning should be visible
|
|
expect(page).to have_link "Create or Update Invoice"
|
|
expect(page).to have_content "The order has changed since the last invoice update."
|
|
click_link "Create or Update Invoice"
|
|
|
|
# and disappear after clicking
|
|
expect(page).not_to have_link "Create or Update Invoice"
|
|
expect(page).not_to have_content "The order has changed since the last invoice update."
|
|
|
|
# creating an invoice, displays a second row
|
|
expect(page.find("table").text).to have_content(table_contents)
|
|
|
|
# with a valid invoice download link
|
|
expect(page).to have_link("Download",
|
|
href: download_href)
|
|
end
|
|
|
|
context "the Create or Update Invoice button" do
|
|
context "when an ABN number is mandatory for invoices but not present" do
|
|
before do
|
|
Spree::Config[:enterprise_number_required_on_invoices?] = true
|
|
end
|
|
|
|
it "displays a warning that an ABN is required when it's clicked" do
|
|
visit spree.admin_order_invoices_path(order1)
|
|
message = accept_prompt { click_link "Create or Update Invoice" }
|
|
distributor = order1.distributor
|
|
expect(message)
|
|
.to eq "#{distributor.name} must have a valid ABN before invoices can be used."
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "resumed" do
|
|
let!(:order2) {
|
|
create(:order_with_totals_and_distribution, user:, distributor:,
|
|
order_cycle:, state: 'resumed',
|
|
payment_state: 'balance_due')
|
|
}
|
|
before do
|
|
visit spree.edit_admin_order_path(order2)
|
|
end
|
|
|
|
it "displays the invoice tab" do
|
|
expect(page).to have_content "Resumed".upcase
|
|
expect(page).to have_content "Invoices".upcase
|
|
end
|
|
end
|
|
|
|
context "canceled" do
|
|
let!(:order3) {
|
|
create(:order_with_totals_and_distribution, user:, distributor:,
|
|
order_cycle:, state: 'canceled',
|
|
payment_state: 'balance_due')
|
|
}
|
|
before do
|
|
visit spree.edit_admin_order_path(order3)
|
|
end
|
|
|
|
it "displays the invoice tab" do
|
|
expect(page).to have_content "Cancelled".upcase
|
|
expect(page).to have_content "Invoices".upcase
|
|
end
|
|
end
|
|
|
|
context "cart" do
|
|
let!(:order_empty) {
|
|
create(:order_with_line_items, user:, distributor:, order_cycle:,
|
|
line_items_count: 0)
|
|
}
|
|
before do
|
|
visit spree.edit_admin_order_path(order_empty)
|
|
end
|
|
|
|
it "should not display the invoice tab" do
|
|
expect(page).to have_content "Cart".upcase
|
|
expect(page).not_to have_content "Invoices".upcase
|
|
end
|
|
end
|
|
|
|
context "payment" do
|
|
let!(:order4) do
|
|
create(:order_ready_for_payment, user:, distributor:,
|
|
order_cycle:,
|
|
payment_state: 'balance_due')
|
|
end
|
|
before do
|
|
visit spree.edit_admin_order_path(order4)
|
|
end
|
|
|
|
it "should not display the invoice tab" do
|
|
expect(page).to have_content "Payment".upcase
|
|
expect(page).not_to have_content "Invoices".upcase
|
|
end
|
|
end
|
|
end
|