diff --git a/app/jobs/standing_order_placement_job.rb b/app/jobs/standing_order_placement_job.rb index 118cbf5b76..956584d858 100644 --- a/app/jobs/standing_order_placement_job.rb +++ b/app/jobs/standing_order_placement_job.rb @@ -19,7 +19,10 @@ class StandingOrderPlacementJob def process(order) return if order.completed? - changes = cap_quantity_and_store_changes(order) unless order.completed? + changes = cap_quantity_and_store_changes(order) + if order.line_items.where('quantity > 0').empty? + return send_empty_email(order, changes) + end move_to_completion(order) send_placement_email(order, changes) end @@ -66,4 +69,8 @@ class StandingOrderPlacementJob return unless order.completed? Spree::OrderMailer.standing_order_email(order.id, 'placement', changes).deliver end + + def send_empty_email(order, changes) + Spree::OrderMailer.standing_order_email(order.id, 'empty', changes).deliver + end end diff --git a/app/views/spree/order_mailer/standing_order_email.html.haml b/app/views/spree/order_mailer/standing_order_email.html.haml index dd519f20ba..60d8191b6e 100644 --- a/app/views/spree/order_mailer/standing_order_email.html.haml +++ b/app/views/spree/order_mailer/standing_order_email.html.haml @@ -27,11 +27,15 @@ %p = t("email_so_#{@type}_details_html", distributor: @order.distributor.name) -- if @changes.any? +- if @changes.any? && @type == 'placement' %p.callout = t("email_so_placement_changes") + = render 'order_summary' -= render 'payment' -= render 'shipping' -= render 'special_instructions' + +- unless @type == 'empty' + = render 'payment' + = render 'shipping' + = render 'special_instructions' + = render 'signoff' diff --git a/config/locales/en.yml b/config/locales/en.yml index 4be858f6f8..c64dea4474 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1218,6 +1218,9 @@ See the %{link} to find out more about %{sitename}'s features and to start using email_so_confirmation_intro_html: "Your order with %{distributor} is now confirmed" email_so_confirmation_explainer_html: "This order was automatically placed for you, and it has now been finalised." email_so_confirmation_details_html: "Here's everything you need to know about your order from %{distributor}:" + email_so_empty_intro_html: "We tried to place a new order with %{distributor}, but had some problems..." + email_so_empty_explainer_html: "Unfortunately, none of products that you ordered were available. The original quantities that you requested appear crossed-out below." + email_so_empty_details_html: "Here are the details of the order for %{distributor}:" email_shipping_delivery_details: Delivery details email_shipping_delivery_time: "Delivery on:" email_shipping_delivery_address: "Delivery address:" diff --git a/spec/jobs/standing_order_placement_job_spec.rb b/spec/jobs/standing_order_placement_job_spec.rb index b1e4b17dba..aef6db69aa 100644 --- a/spec/jobs/standing_order_placement_job_spec.rb +++ b/spec/jobs/standing_order_placement_job_spec.rb @@ -122,12 +122,11 @@ describe StandingOrderPlacementJob do let(:standing_order) { create(:standing_order, with_items: true) } let(:proxy_order) { create(:proxy_order, standing_order: standing_order) } let!(:order) { proxy_order.initialise_order! } - let(:changes) { {} } before do expect_any_instance_of(Spree::Payment).to_not receive(:process!) - allow(job).to receive(:cap_quantity_and_store_changes) { changes } allow(job).to receive(:send_placement_email) + allow(job).to receive(:send_empty_email) end context "when the order is already complete" do @@ -142,18 +141,31 @@ describe StandingOrderPlacementJob do end context "when the order is not already complete" do - it "processes the order to completion, but does not process the payment" do - # If this spec starts complaining about no shipping methods being available - # on CI, there is probably another spec resetting the currency though Rails.cache.clear - ActionMailer::Base.deliveries.clear - expect{job.send(:process, order)}.to change{order.reload.completed_at}.from(nil) - expect(order.completed_at).to be_within(5.seconds).of Time.now - expect(order.payments.first.state).to eq "checkout" + context "when no stock items are available after capping stock" do + before do + allow(job).to receive(:unavailable_stock_lines_for) { order.line_items } + end + + it "does not place the order, sends an empty_order email" do + expect{job.send(:process, order)}.to_not change{order.reload.completed_at}.from(nil) + expect(job).to_not have_received(:send_placement_email) + expect(job).to have_received(:send_empty_email) + end end - it "does not enqueue confirmation emails" do - expect{job.send(:process, order)}.to_not enqueue_job ConfirmOrderJob - expect(job).to have_received(:send_placement_email).with(order, changes).once + context "when at least one stock item is available after capping stock" do + it "processes the order to completion, but does not process the payment" do + # If this spec starts complaining about no shipping methods being available + # on CI, there is probably another spec resetting the currency though Rails.cache.clear + expect{job.send(:process, order)}.to change{order.reload.completed_at}.from(nil) + expect(order.completed_at).to be_within(5.seconds).of Time.now + expect(order.payments.first.state).to eq "checkout" + end + + it "does not enqueue confirmation emails" do + expect{job.send(:process, order)}.to_not enqueue_job ConfirmOrderJob + expect(job).to have_received(:send_placement_email).with(order, anything).once + end end end end diff --git a/spec/mailers/order_mailer_spec.rb b/spec/mailers/order_mailer_spec.rb index ecc19db510..864e3f1ab9 100644 --- a/spec/mailers/order_mailer_spec.rb +++ b/spec/mailers/order_mailer_spec.rb @@ -108,4 +108,21 @@ describe Spree::OrderMailer do expect(body).to include "This order was automatically placed for you" end end + + describe "empty order notification for standing orders" do + let(:standing_order) { create(:standing_order, with_items: true) } + let(:proxy_order) { create(:proxy_order, standing_order: standing_order) } + let!(:order) { proxy_order.initialise_order! } + + before do + expect do + Spree::OrderMailer.standing_order_email(order.id, 'empty', {}).deliver + end.to change{Spree::OrderMailer.deliveries.count}.by(1) + end + + it "sends the email" do + body = Spree::OrderMailer.deliveries.last.body.encoded + expect(body).to include "Unfortunately, none of products that you ordered were available" + end + end end