Adding job to send confirm emails for standing orders on order cycle close

This commit is contained in:
Rob Harrington
2016-12-09 12:29:24 +11:00
parent 2a03477597
commit e068c4831b
5 changed files with 132 additions and 7 deletions

View File

@@ -5,6 +5,12 @@ class OrderCycleOpenCloseJob
order_cycles.each do |order_cycle|
Delayed::Job.enqueue(StandingOrderPlacementJob.new(order_cycle))
end
order_cycles = recently_closed_order_cycles.all
recently_closed_order_cycles.update_all(standing_orders_confirmed_at: Time.now)
order_cycles.each do |order_cycle|
Delayed::Job.enqueue(StandingOrderConfirmJob.new(order_cycle))
end
end
private
@@ -17,4 +23,13 @@ class OrderCycleOpenCloseJob
10.minutes.ago, Time.now, 10.minutes.ago, Time.now
)
end
def recently_closed_order_cycles
return @recently_closed_order_cycles unless @recently_closed_order_cycles.nil?
@recently_closed_order_cycles =
OrderCycle.closed.where(
'standing_orders_confirmed_at IS NULL AND (orders_close_at BETWEEN (?) AND (?) OR updated_at BETWEEN (?) AND (?))',
10.minutes.ago, Time.now, 10.minutes.ago, Time.now
)
end
end

View File

@@ -0,0 +1,28 @@
class StandingOrderConfirmJob
attr_accessor :order_cycle
def initialize(order_cycle)
@order_cycle = order_cycle
end
def perform
orders.each do |order|
process(order)
end
end
private
def orders
Spree::Order.complete.where(order_cycle_id: order_cycle)
.merge(StandingOrderOrder.not_canceled).joins(:standing_order_order).readonly(false)
end
def process(order)
send_confirm_email(order)
end
def send_confirm_email(order)
Spree::OrderMailer.standing_order_email(order.id, 'confirmation', {}).deliver
end
end

View File

@@ -6,6 +6,7 @@ class StandingOrderOrder < ActiveRecord::Base
scope :closed, -> { joins(order: :order_cycle).merge(OrderCycle.closed) }
scope :not_closed, -> { joins(order: :order_cycle).merge(OrderCycle.not_closed) }
scope :not_canceled, where('standing_order_orders.canceled_at IS NULL')
def state
return 'canceled' if canceled?

View File

@@ -17,16 +17,45 @@ describe OrderCycleOpenCloseJob do
end
end
describe "running the job" do
let!(:order_cycle) { create(:simple_order_cycle, orders_open_at: 5.minutes.ago) }
describe "finding recently closed order cycles" do
let!(:order_cycle1) { create(:simple_order_cycle, orders_close_at: 11.minutes.ago, updated_at: 11.minutes.ago) }
let!(:order_cycle2) { create(:simple_order_cycle, orders_close_at: 11.minutes.ago, updated_at: 9.minutes.ago) }
let!(:order_cycle3) { create(:simple_order_cycle, orders_close_at: 9.minutes.ago, updated_at: 9.minutes.ago) }
let!(:order_cycle4) { create(:simple_order_cycle, orders_close_at: 2.minutes.ago, standing_orders_confirmed_at: 1.minute.ago ) }
let!(:order_cycle5) { create(:simple_order_cycle, orders_close_at: 1.minute.from_now) }
it "marks the order cycle as processed by setting standing_orders_placed_at" do
expect{job.perform}.to change{order_cycle.reload.standing_orders_placed_at}
expect(order_cycle.standing_orders_placed_at).to be_within(5.seconds).of Time.now
it "returns unprocessed order cycles whose orders_close_at or updated_at date is within the past 10 minutes" do
order_cycles = job.send(:recently_closed_order_cycles)
expect(order_cycles).to include order_cycle2, order_cycle3
expect(order_cycles).to_not include order_cycle1, order_cycle4, order_cycle5
end
end
describe "running the job" do
context "when an order cycle has just opened" do
let!(:order_cycle) { create(:simple_order_cycle, orders_open_at: 5.minutes.ago) }
it "marks the order cycle as processed by setting standing_orders_placed_at" do
expect{job.perform}.to change{order_cycle.reload.standing_orders_placed_at}
expect(order_cycle.standing_orders_placed_at).to be_within(5.seconds).of Time.now
end
it "enqueues a StandingOrderPlacementJob for each recently opened order_cycle" do
expect{job.perform}.to enqueue_job StandingOrderPlacementJob
end
end
it "enqueues a StandingOrderPlacementJob for each recently opened order_cycle" do
expect{job.perform}.to enqueue_job StandingOrderPlacementJob
context "when an order cycle has just closed" do
let!(:order_cycle) { create(:simple_order_cycle, orders_close_at: 5.minutes.ago) }
it "marks the order cycle as processed by setting standing_orders_placed_at" do
expect{job.perform}.to change{order_cycle.reload.standing_orders_confirmed_at}
expect(order_cycle.standing_orders_confirmed_at).to be_within(5.seconds).of Time.now
end
it "enqueues a StandingOrderPlacementJob for each recently opened order_cycle" do
expect{job.perform}.to enqueue_job StandingOrderConfirmJob
end
end
end
end

View File

@@ -0,0 +1,52 @@
require 'spec_helper'
describe StandingOrderConfirmJob do
let(:shop) { create(:distributor_enterprise) }
let(:order_cycle1) { create(:simple_order_cycle, coordinator: shop) }
let(:order_cycle2) { create(:simple_order_cycle, coordinator: shop) }
let(:schedule1) { create(:schedule, order_cycles: [order_cycle1, order_cycle2]) }
let(:standing_order1) { create(:standing_order_with_items, shop: shop, schedule: schedule1) }
let!(:job) { StandingOrderConfirmJob.new(order_cycle1) }
describe "finding standing_order orders for the specified order cycle" do
let(:order1) { create(:order, order_cycle: order_cycle1) } # Incomplete + Linked + OC Matches
let(:order2) { create(:order, order_cycle: order_cycle1, completed_at: 5.minutes.ago) } # Complete + Not-Linked + OC Matches
let(:order3) { create(:order, order_cycle: order_cycle2, completed_at: 5.minutes.ago) } # Complete + Linked + OC Mismatch
let(:order4) { create(:order, order_cycle: order_cycle1, completed_at: 5.minutes.ago) } # Complete + Linked + OC Matches + Cancelled
let(:order5) { create(:order, order_cycle: order_cycle1, completed_at: 5.minutes.ago) } # Complete + Linked + OC Matches
let(:cancelled_standing_order_order) { standing_order1.standing_order_orders.find_by_order_id(order4.id) }
before do
standing_order1.orders = [order1, order3, order4, order5]
cancelled_standing_order_order.update_attribute(:canceled_at, 1.minute.ago)
end
it "only returns incomplete orders in the relevant order cycle that are linked to a standing order" do
orders = job.send(:orders)
expect(orders).to include order5
expect(orders).to_not include order1, order2, order3, order4
end
end
describe "processing a standing order order" do
let(:order) { standing_order1.orders.first }
before do
form = StandingOrderForm.new(standing_order1)
form.send(:initialise_orders!)
while !standing_order1.orders.first.completed? do break unless order.next! end
allow(job).to receive(:send_confirm_email).and_call_original
Spree::MailMethod.create!(
environment: Rails.env,
preferred_mails_from: 'spree@example.com'
)
end
it "sends only a standing order confirm email, no regular confirmation emails" do
ActionMailer::Base.deliveries.clear
expect{job.send(:process, order)}.to_not enqueue_job ConfirmOrderJob
expect(job).to have_received(:send_confirm_email).with(order).once
expect(ActionMailer::Base.deliveries.count).to be 1
end
end
end