mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-30 21:27:17 +00:00
The cancellation happens async in Javascript. Therefore we need to wait for and outcome on the page to know that the action finished. The expectation needs to be around that whole block. We actually want only one job enqueued if the same backorder is affected. Time to fix that.
555 lines
22 KiB
Ruby
555 lines
22 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "system_helper"
|
|
|
|
RSpec.describe '
|
|
As an administrator
|
|
I want to perform bulk order actions
|
|
' do
|
|
include AuthenticationHelper
|
|
include WebHelper
|
|
|
|
let(:owner) { create(:user) }
|
|
let(:owner2) { create(:user) }
|
|
let(:customer) { create(:user) }
|
|
let(:customer2) { create(:user) }
|
|
let(:customer3) { create(:user) }
|
|
let(:customer4) { create(:user) }
|
|
let(:customer5) { create(:user) }
|
|
let(:billing_address) { create(:address, :randomized) }
|
|
let(:billing_address2) { create(:address, :randomized) }
|
|
let(:billing_address3) { create(:address, :randomized) }
|
|
let(:billing_address4) { create(:address, :randomized) }
|
|
let(:billing_address5) { create(:address, :randomized) }
|
|
let(:product) { create(:simple_product) }
|
|
let(:distributor) {
|
|
create(:distributor_enterprise, owner:, with_payment_and_shipping: true,
|
|
charges_sales_tax: true)
|
|
}
|
|
let(:distributor2) { create(:distributor_enterprise_with_tax, owner:) }
|
|
let(:distributor3) {
|
|
create(:distributor_enterprise, owner:, with_payment_and_shipping: true,
|
|
charges_sales_tax: true)
|
|
}
|
|
let(:distributor4) {
|
|
create(:distributor_enterprise, owner:, with_payment_and_shipping: true,
|
|
charges_sales_tax: true)
|
|
}
|
|
let(:distributor5) { create(:distributor_enterprise, owner: owner2, charges_sales_tax: true) }
|
|
let!(:shipping_method) {
|
|
create(:shipping_method_with, :pickup, name: "pick_up",
|
|
distributors: [distributor, distributor2, distributor3])
|
|
}
|
|
let!(:shipping_method2) {
|
|
create(:shipping_method_with, :pickup, name: "delivery",
|
|
distributors: [distributor4, distributor5])
|
|
}
|
|
let(:order_cycle) do
|
|
create(:simple_order_cycle, name: 'One', distributors: [distributor, distributor2,
|
|
distributor3, distributor4],
|
|
variants: [product.variants.first])
|
|
end
|
|
|
|
context "with a complete order" do
|
|
let(:order) do
|
|
create(:order_with_totals_and_distribution, user: customer, distributor:,
|
|
order_cycle:,
|
|
state: 'complete', payment_state: 'balance_due',
|
|
bill_address_id: billing_address.id)
|
|
end
|
|
|
|
let!(:order_cycle2) {
|
|
create(:simple_order_cycle, name: 'Two', orders_close_at: 2.weeks.from_now)
|
|
}
|
|
let!(:order_cycle3) {
|
|
create(:simple_order_cycle, name: 'Three', orders_close_at: 3.weeks.from_now)
|
|
}
|
|
let!(:order_cycle4) {
|
|
create(:simple_order_cycle, name: 'Four', orders_close_at: 4.weeks.from_now)
|
|
}
|
|
let!(:order_cycle5) do
|
|
create(:simple_order_cycle, name: 'Five', coordinator: distributor5,
|
|
distributors: [distributor5], variants: [product.variants.first])
|
|
end
|
|
|
|
let!(:order2) {
|
|
create(:order_ready_to_ship, user: customer2, distributor: distributor2,
|
|
order_cycle: order_cycle2, completed_at: 2.days.ago,
|
|
bill_address_id: billing_address2.id)
|
|
}
|
|
let!(:order3) {
|
|
create(:order_with_credit_payment, user: customer3, distributor: distributor3,
|
|
order_cycle: order_cycle3,
|
|
bill_address_id: billing_address3.id)
|
|
}
|
|
let!(:order4) {
|
|
create(:order_with_credit_payment, user: customer4, distributor: distributor4,
|
|
order_cycle: order_cycle4,
|
|
bill_address_id: billing_address4.id)
|
|
}
|
|
let!(:order5) {
|
|
create(:order_ready_to_ship, user: customer5, distributor: distributor5,
|
|
order_cycle: order_cycle5,
|
|
bill_address_id: billing_address5.id)
|
|
}
|
|
|
|
context "as a super admin" do
|
|
before do
|
|
login_as_admin
|
|
visit spree.admin_orders_path
|
|
end
|
|
|
|
context "can bulk send invoices per email" do
|
|
before do
|
|
Spree::Config[:enable_invoices?] = true
|
|
Spree::Config[:enterprise_number_required_on_invoices?] = false
|
|
end
|
|
|
|
shared_examples "can bulk send confirmation email from 2 orders" do
|
|
it "can bulk send invoices per email, but only for the 'complete' or 'resumed' ones" do
|
|
within "#listing_orders" do
|
|
page.find("input[name='bulk_ids[]'][value='#{order2.id}']").click
|
|
page.find("input[name='bulk_ids[]'][value='#{order3.id}']").click
|
|
page.find("input[name='bulk_ids[]'][value='#{order4.id}']").click
|
|
page.find("input[name='bulk_ids[]'][value='#{order5.id}']").click
|
|
end
|
|
|
|
page.find("span.icon-reorder", text: "Actions").click
|
|
|
|
within ".ofn-drop-down .menu" do
|
|
page.find("span", text: "Send Invoices").click
|
|
end
|
|
|
|
expect(page).to have_content "This will email customer invoices " \
|
|
"for all selected complete orders."
|
|
expect(page).to have_content "Are you sure you want to proceed?"
|
|
|
|
within ".reveal-modal" do
|
|
expect {
|
|
find_button("Confirm").click
|
|
}.to enqueue_job(ActionMailer::MailDeliveryJob).exactly(:twice)
|
|
end
|
|
|
|
expect(page).to have_content "Invoice emails sent for 2 orders."
|
|
end
|
|
end
|
|
|
|
context "with multiple orders with differents states" do
|
|
before do
|
|
order2.update(state: "canceled")
|
|
order3.update(state: "payment")
|
|
order4.update(state: "complete")
|
|
order5.update(state: "resumed")
|
|
end
|
|
|
|
it_behaves_like "can bulk send confirmation email from 2 orders"
|
|
|
|
describe "ABN" do
|
|
context "ABN is not required" do
|
|
before do
|
|
allow(Spree::Config).to receive(:enterprise_number_required_on_invoices?)
|
|
.and_return false
|
|
end
|
|
it_behaves_like "can bulk send confirmation email from 2 orders"
|
|
end
|
|
context "ABN is required" do
|
|
before do
|
|
allow(Spree::Config).to receive(:enterprise_number_required_on_invoices?)
|
|
.and_return true
|
|
end
|
|
context "All the distributors setup the ABN" do
|
|
before do
|
|
order4.distributor.update(abn: "123456789")
|
|
order5.distributor.update(abn: "987654321")
|
|
end
|
|
context "all the orders are invoiceable (completed/resumed)" do
|
|
it_behaves_like "can bulk send confirmation email from 2 orders"
|
|
end
|
|
end
|
|
context "the distributor of one of the order didn't set the ABN" do
|
|
context "ABN is nil" do
|
|
before do
|
|
order4.distributor.update(abn: "123456789")
|
|
order5.distributor.update(abn: nil)
|
|
end
|
|
|
|
context "with legal invoices feature disabled" do
|
|
before { pending("Emails are not sent in this case") }
|
|
it_behaves_like "can bulk send confirmation email from 2 orders"
|
|
end
|
|
end
|
|
|
|
context "ABN is an empty string" do
|
|
before do
|
|
order4.distributor.update(abn: "123456789")
|
|
order5.distributor.update(abn: "")
|
|
end
|
|
|
|
context "with legal invoices feature disabled" do
|
|
before { pending("Emails are not sent in this case") }
|
|
it_behaves_like "can bulk send confirmation email from 2 orders"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "can bulk print invoices" do
|
|
let(:order4_selector){ "#order_#{order4.id} input[name='bulk_ids[]']" }
|
|
let(:order5_selector){ "#order_#{order5.id} input[name='bulk_ids[]']" }
|
|
|
|
shared_examples "can bulk print invoices from 2 orders" do
|
|
it "bulk prints invoices in pdf format" do
|
|
page.find(order4_selector).click
|
|
page.find(order5_selector).click
|
|
|
|
page.find("span.icon-reorder", text: "Actions").click
|
|
within ".ofn-drop-down .menu" do
|
|
expect {
|
|
page.find("span", text: "Print Invoices").click # Prints invoices in bulk
|
|
}.to enqueue_job(BulkInvoiceJob).exactly(:once)
|
|
end
|
|
|
|
expect(page).to have_content "Compiling Invoices"
|
|
expect(page).to have_content "Please wait until the PDF is ready " \
|
|
"before closing this modal."
|
|
|
|
# we don't run Sidekiq in test environment, so we need to manually run enqueued jobs
|
|
# to generate PDF files, and change the modal accordingly
|
|
perform_enqueued_jobs(only: BulkInvoiceJob)
|
|
|
|
expect(page).to have_content "Bulk Invoice created"
|
|
|
|
within ".modal-content" do
|
|
expect(page).to have_link(class: "button", text: "View File", href: /invoices/)
|
|
|
|
invoice_content = extract_pdf_content
|
|
|
|
expect(invoice_content).to have_content("TAX INVOICE", count: 2)
|
|
expect(invoice_content).to have_content(order4.number.to_s)
|
|
expect(invoice_content).to have_content(order5.number.to_s)
|
|
expect(invoice_content).to have_content(distributor4.name.to_s)
|
|
expect(invoice_content).to have_content(distributor5.name.to_s)
|
|
expect(invoice_content).to have_content(order_cycle4.name.to_s)
|
|
expect(invoice_content).to have_content(order_cycle5.name.to_s)
|
|
end
|
|
end
|
|
end
|
|
|
|
shared_examples "should ignore the non invoiceable order" do
|
|
it "bulk prints invoices in pdf format" do
|
|
page.find(order4_selector).click
|
|
page.find(order5_selector).click
|
|
|
|
page.find("span.icon-reorder", text: "Actions").click
|
|
within ".ofn-drop-down .menu" do
|
|
expect {
|
|
page.find("span", text: "Print Invoices").click # Prints invoices in bulk
|
|
}.to enqueue_job(BulkInvoiceJob).exactly(:once)
|
|
end
|
|
|
|
expect(page).to have_content "Compiling Invoices"
|
|
expect(page).to have_content "Please wait until the PDF is ready " \
|
|
"before closing this modal."
|
|
|
|
perform_enqueued_jobs(only: BulkInvoiceJob)
|
|
|
|
expect(page).to have_content "Bulk Invoice created"
|
|
|
|
within ".modal-content" do
|
|
expect(page).to have_link(class: "button", text: "View File",
|
|
href: /invoices/)
|
|
|
|
invoice_content = extract_pdf_content
|
|
|
|
expect(invoice_content).to have_content("TAX INVOICE", count: 1)
|
|
expect(invoice_content).not_to have_content(order4.number.to_s)
|
|
expect(invoice_content).to have_content(order5.number.to_s)
|
|
expect(invoice_content).not_to have_content(distributor4.name.to_s)
|
|
expect(invoice_content).to have_content(distributor5.name.to_s)
|
|
expect(invoice_content).not_to have_content(order_cycle4.name.to_s)
|
|
expect(invoice_content).to have_content(order_cycle5.name.to_s)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "ABN is not required" do
|
|
before do
|
|
allow(Spree::Config).to receive(:enterprise_number_required_on_invoices?)
|
|
.and_return false
|
|
end
|
|
|
|
it_behaves_like "can bulk print invoices from 2 orders"
|
|
|
|
context "with legal invoices feature", feature: :invoices do
|
|
it_behaves_like "can bulk print invoices from 2 orders"
|
|
end
|
|
|
|
context "when cable_ready fails" do
|
|
# The backup polling is slower. Let's wait for it.
|
|
around do |example|
|
|
polling_interval = 5 # seconds
|
|
wait_time = Capybara.default_max_wait_time + polling_interval
|
|
|
|
using_wait_time(wait_time) do
|
|
example.run
|
|
end
|
|
end
|
|
|
|
# Don't send anything via web sockets.
|
|
before do
|
|
expect_any_instance_of(BulkInvoiceJob)
|
|
.to receive(:broadcast)
|
|
.and_return(nil) # do nothing
|
|
end
|
|
|
|
it_behaves_like "can bulk print invoices from 2 orders"
|
|
end
|
|
|
|
context "one of the two orders is not invoiceable" do
|
|
before do
|
|
order4.cancel!
|
|
end
|
|
|
|
it_behaves_like "should ignore the non invoiceable order"
|
|
context "with legal invoices feature", feature: :invoices do
|
|
it_behaves_like "should ignore the non invoiceable order"
|
|
end
|
|
end
|
|
|
|
context "ordering by customer name" do
|
|
context "ascending" do
|
|
let!(:surnames) {
|
|
[order2.name.gsub(/.* /, ""), order3.name.gsub(/.* /, ""),
|
|
order4.name.gsub(/.* /, ""), order5.name.gsub(/.* /, "")].sort
|
|
}
|
|
it "orders by customer name ascending" do
|
|
page.find('a', text: "Name").click # orders alphabetically (asc)
|
|
sleep(0.5) # waits for column sorting
|
|
|
|
page.find("#selectAll").click
|
|
|
|
print_all_invoices
|
|
|
|
invoice_content = extract_pdf_content
|
|
|
|
expect(
|
|
invoice_content.join
|
|
).to match(/#{surnames[0]}.*#{surnames[1]}.*#{surnames[2]}.*#{surnames[3]}/m)
|
|
end
|
|
end
|
|
context "descending" do
|
|
let!(:surnames) {
|
|
[order2.name.gsub(/.* /, ""), order3.name.gsub(/.* /, ""),
|
|
order4.name.gsub(/.* /, ""), order5.name.gsub(/.* /, "")].sort.reverse
|
|
}
|
|
it "order by customer name descending" do
|
|
page.find('a', text: "Name").click # orders alphabetically (asc)
|
|
sleep(0.5) # waits for column sorting
|
|
page.find('a', text: "Name").click # orders alphabetically (desc)
|
|
sleep(0.5) # waits for column sorting
|
|
|
|
page.find("#selectAll").click
|
|
|
|
print_all_invoices
|
|
|
|
invoice_content = extract_pdf_content
|
|
|
|
expect(
|
|
invoice_content.join
|
|
).to match(/#{surnames[0]}.*#{surnames[1]}.*#{surnames[2]}.*#{surnames[3]}/m)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
context "ABN is required" do
|
|
before do
|
|
allow(Spree::Config).to receive(:enterprise_number_required_on_invoices?)
|
|
.and_return true
|
|
end
|
|
context "All the distributors setup the ABN" do
|
|
before do
|
|
order4.distributor.update(abn: "123456789")
|
|
order5.distributor.update(abn: "987654321")
|
|
end
|
|
context "all the orders are invoiceable (completed/resumed)" do
|
|
it_behaves_like "can bulk print invoices from 2 orders"
|
|
context "with legal invoices feature", feature: :invoices do
|
|
it_behaves_like "can bulk print invoices from 2 orders"
|
|
end
|
|
end
|
|
|
|
context "one of the two orders is not invoiceable" do
|
|
before do
|
|
order4.cancel!
|
|
end
|
|
|
|
it_behaves_like "should ignore the non invoiceable order"
|
|
context "with legal invoices feature", feature: :invoices do
|
|
it_behaves_like "should ignore the non invoiceable order"
|
|
end
|
|
end
|
|
end
|
|
context "the distributor of one of the order didn't set the ABN" do
|
|
shared_examples "should not print the invoice" do
|
|
it "should render a warning message" do
|
|
page.find(order4_selector).click
|
|
page.find(order5_selector).click
|
|
|
|
page.find("span.icon-reorder", text: "Actions").click
|
|
within ".ofn-drop-down .menu" do
|
|
expect {
|
|
page.find("span", text: "Print Invoices").click # Prints invoices in bulk
|
|
}.not_to enqueue_job(BulkInvoiceJob)
|
|
end
|
|
|
|
expect(page).not_to have_content "Compiling Invoices"
|
|
expect(page).not_to have_content "Please wait until the PDF is ready " \
|
|
"before closing this modal."
|
|
|
|
expect(page).to have_content "#{
|
|
order5.distributor.name
|
|
} must have a valid ABN before invoices can be used."
|
|
end
|
|
end
|
|
|
|
context "ABN is nil" do
|
|
before do
|
|
order4.distributor.update(abn: "123456789")
|
|
order5.distributor.update(abn: nil)
|
|
end
|
|
|
|
context "with legal invoices feature disabled" do
|
|
it_behaves_like "should not print the invoice"
|
|
end
|
|
|
|
context "with legal invoices feature", feature: :invoices do
|
|
it_behaves_like "should not print the invoice"
|
|
end
|
|
end
|
|
|
|
context "ABN is an empty string" do
|
|
before do
|
|
order4.distributor.update(abn: "123456789")
|
|
order5.distributor.update(abn: "")
|
|
end
|
|
|
|
context "with legal invoices feature disabled" do
|
|
it_behaves_like "can bulk print invoices from 2 orders"
|
|
end
|
|
|
|
context "with legal invoices feature", feature: :invoices do
|
|
it_behaves_like "should not print the invoice"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
it "can bulk cancel 2 orders" do
|
|
page.find("#listing_orders tbody tr:nth-child(1) input[name='bulk_ids[]']").click
|
|
page.find("#listing_orders tbody tr:nth-child(2) input[name='bulk_ids[]']").click
|
|
|
|
page.find("span.icon-reorder", text: "Actions").click
|
|
within ".ofn-drop-down .menu" do
|
|
page.find("span", text: "Cancel Orders").click
|
|
end
|
|
|
|
expect(page).to have_content "Are you sure you want to proceed?"
|
|
expect(page).to have_content "This will cancel the current order."
|
|
|
|
within ".reveal-modal" do
|
|
uncheck "Send a cancellation email to the customer"
|
|
expect {
|
|
click_on "Cancel" # Cancels the cancel action
|
|
}.not_to enqueue_mail
|
|
end
|
|
|
|
expect(page).not_to have_content "This will cancel the current order."
|
|
|
|
page.find("span.icon-reorder", text: "Actions").click
|
|
within ".ofn-drop-down .menu" do
|
|
page.find("span", text: "Cancel Orders").click
|
|
end
|
|
|
|
expect {
|
|
within ".reveal-modal" do
|
|
click_on "Confirm" # Confirms the cancel action
|
|
end
|
|
expect(page).to have_content("CANCELLED", count: 2)
|
|
}.to enqueue_job(AmendBackorderJob).exactly(:twice)
|
|
# You can't combine negative matchers.
|
|
.and enqueue_mail.exactly(0).times
|
|
end
|
|
end
|
|
|
|
context "for a hub manager" do
|
|
before do
|
|
login_as owner2
|
|
visit spree.admin_orders_path
|
|
end
|
|
|
|
it "displays the orders for the respective distributor" do
|
|
expect(page).to have_content order5.number # displays the only order for distributor5
|
|
expect(page).not_to have_content order.number
|
|
expect(page).not_to have_content order2.number
|
|
expect(page).not_to have_content order3.number
|
|
expect(page).not_to have_content order4.number
|
|
end
|
|
|
|
it "cannot send emails to orders if permission have been revoked in the meantime" do
|
|
page.find("#listing_orders tbody tr:nth-child(1) input[name='bulk_ids[]']").click
|
|
# Find the clicked order
|
|
order = Spree::Order.find_by(
|
|
id: page.find("#listing_orders tbody tr:nth-child(1) input[name='bulk_ids[]']").value
|
|
)
|
|
# Revoke permission for the current user on that specific order by changing its owners
|
|
order.update_attribute(:distributor, distributor)
|
|
order.update_attribute(:order_cycle, order_cycle)
|
|
|
|
page.find("span.icon-reorder", text: "Actions").click
|
|
within ".ofn-drop-down .menu" do
|
|
page.find("span", text: "Resend Confirmation").click
|
|
end
|
|
|
|
expect(page).to have_content "Are you sure you want to proceed?"
|
|
|
|
within ".reveal-modal" do
|
|
expect {
|
|
find_button("Confirm").click
|
|
}.not_to enqueue_job(ActionMailer::MailDeliveryJob)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def extract_pdf_content
|
|
# Extract last part of invoice URL
|
|
link = page.find(class: "button", text: "View File")
|
|
filename = link[:href].match %r{/invoices/.*}
|
|
|
|
# Load invoice temp file directly instead of downloading
|
|
reader = PDF::Reader.new("tmp/#{filename}.pdf")
|
|
reader.pages.map(&:text)
|
|
end
|
|
|
|
def print_all_invoices
|
|
page.find("span.icon-reorder", text: "Actions").click
|
|
within ".ofn-drop-down .menu" do
|
|
expect {
|
|
page.find("span", text: "Print Invoices").click # Prints invoices in bulk
|
|
}.to enqueue_job(BulkInvoiceJob).exactly(:once)
|
|
end
|
|
|
|
expect(page).to have_content "Compiling Invoices"
|
|
expect(page).to have_content "Please wait until the PDF is ready " \
|
|
"before closing this modal."
|
|
|
|
perform_enqueued_jobs(only: BulkInvoiceJob)
|
|
|
|
expect(page).to have_content "Bulk Invoice created"
|
|
end
|
|
end
|