diff --git a/app/reflexes/send_invoice_reflex.rb b/app/reflexes/send_invoice_reflex.rb
new file mode 100644
index 0000000000..8f75ac185c
--- /dev/null
+++ b/app/reflexes/send_invoice_reflex.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class SendInvoiceReflex < ApplicationReflex
+ def confirm(order_ids)
+ Spree::Order.where(id: order_ids).find_each do |o|
+ Spree::OrderMailer.invoice_email(o.id).deliver_later unless o.distributor.can_invoice?
+ end
+
+ flash[:success] = I18n.t("admin.send_invoice_feedback", count: order_ids.count)
+ cable_ready.dispatch_event(name: "modal:close")
+ morph "#flashes", render(partial: "shared/flashes", locals: { flashes: flash })
+ end
+end
diff --git a/app/views/spree/admin/orders/index.html.haml b/app/views/spree/admin/orders/index.html.haml
index 047de811a5..538ece2c5d 100644
--- a/app/views/spree/admin/orders/index.html.haml
+++ b/app/views/spree/admin/orders/index.html.haml
@@ -33,6 +33,9 @@
%div.menu_item
%span.name{ "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "resend_confirmation" }
= t('.resend_confirmation')
+ %div.menu_item
+ %span.name{ "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "send_invoice" }
+ = t('.send_invoice')
%div.menu_item
%span.name.invoices-modal{'ng-controller' => 'bulkInvoiceCtrl', 'ng-click' => 'createBulkInvoice()' }
= t('.print_invoices')
@@ -124,6 +127,11 @@
= render ConfirmModalComponent.new(id: "resend_confirmation", confirm_actions: "click->resend-confirmation-email#confirm", controllers: "resend-confirmation-email") do
.margin-bottom-30
= t('.resend_confirmation_confirm_html')
+
+= render ConfirmModalComponent.new(id: "send_invoice", confirm_actions: "click->send-invoice#confirm", controllers: "send-invoice") do
+ .margin-bottom-30
+ = t('.send_invoice_confirm_html')
+
= render ConfirmModalComponent.new(id: "cancel_orders", confirm_actions: "click->cancel-orders#confirm", controllers: "cancel-orders", message: "spree/admin/orders/messages/cancel_orders") do
.margin-bottom-30
= t("js.admin.orders.cancel_the_order_html")
diff --git a/app/webpacker/controllers/send_invoice_controller.js b/app/webpacker/controllers/send_invoice_controller.js
new file mode 100644
index 0000000000..37c80d01c7
--- /dev/null
+++ b/app/webpacker/controllers/send_invoice_controller.js
@@ -0,0 +1,11 @@
+import BulkActionsController from "./bulk_actions_controller";
+
+export default class extends BulkActionsController {
+ connect() {
+ super.connect();
+ }
+
+ confirm() {
+ super.confirm("SendInvoiceReflex#confirm");
+ }
+}
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 761411574e..414ed14575 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1602,6 +1602,9 @@ en:
resend_confirmation_emails_feedback:
one: "Confirmation email sent for 1 order."
other: "Confirmation emails sent for %{count} orders."
+ send_invoice_feedback:
+ one: "Invoice email sent for 1 order."
+ other: "Invoice emails sent for %{count} orders."
# API
#
@@ -3942,6 +3945,8 @@ See the %{link} to find out more about %{sitename}'s features and to start using
cancel_orders: "Cancel Orders"
resend_confirmation: "Resend Confirmation"
resend_confirmation_confirm_html: "This will resend the confirmation email to the customer.
Are you sure you want to proceed?"
+ send_invoice: "Send Invoices"
+ send_invoice_confirm_html: "This will email customer invoices for all selected complete orders.
Are you sure you want to proceed?"
selected:
zero: "No order selected"
one: "1 order selected"
diff --git a/spec/system/admin/orders_spec.rb b/spec/system/admin/orders_spec.rb
index 2325ba02f4..2e9b4453a6 100644
--- a/spec/system/admin/orders_spec.rb
+++ b/spec/system/admin/orders_spec.rb
@@ -384,6 +384,26 @@ describe '
login_as_admin_and_visit spree.admin_orders_path
end
+ it "can bulk send invoice for 2 orders" do
+ page.find("#listing_orders tbody tr:nth-child(1) input[name='order_ids[]']").click
+ page.find("#listing_orders tbody tr:nth-child(2) input[name='order_ids[]']").click
+
+ page.find("span.icon-reorder", text: "ACTIONS").click
+ within ".ofn-drop-down-with-prepend .menu" do
+ page.find("span", text: "Send Invoices").click
+ end
+
+ 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
+
it "can bulk send email to 2 orders" do
page.find("#listing_orders tbody tr:nth-child(1) input[name='order_ids[]']").click
page.find("#listing_orders tbody tr:nth-child(2) input[name='order_ids[]']").click