Skip to content

Commit

Permalink
Merge pull request #13065 from mkllnk/dfc-amend-nothing
Browse files Browse the repository at this point in the history
Admin updates can trigger new backorders until the order cycle is closed
  • Loading branch information
mkllnk authored Jan 22, 2025
2 parents 31c7173 + 06d9d96 commit c258bee
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 9 deletions.
1 change: 1 addition & 0 deletions app/controllers/checkout_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ def confirm_order
end
@order.process_payments!
@order.confirm!
BackorderJob.check_stock(@order)
order_completion_reset @order
end

Expand Down
14 changes: 11 additions & 3 deletions app/jobs/amend_backorder_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,16 @@ def perform(order)
def amend_backorder(order)
backorder = BackorderUpdater.new.amend_backorder(order)

user = order.distributor.owner
urls = nil # Not needed to send order. The backorder id is the URL.
FdcBackorderer.new(user, urls).send_order(backorder) if backorder
if backorder
user = order.distributor.owner
urls = nil # Not needed to send order. The backorder id is the URL.
FdcBackorderer.new(user, urls).send_order(backorder)
elsif !order.order_cycle.closed?

# We don't have an order to amend but the order cycle is or will open.
# We can assume that this job was triggered by an admin creating a new
# order or adding backorderable items to an order.
BackorderJob.new.place_backorder(order)
end
end
end
2 changes: 0 additions & 2 deletions app/models/spree/order.rb
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,6 @@ def finalize!

deliver_order_confirmation_email

BackorderJob.check_stock(self)

state_changes.create(
previous_state: 'cart',
next_state: 'complete',
Expand Down
7 changes: 5 additions & 2 deletions app/services/backorder_updater.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def amend_backorder(order)

backorder = orderer.find_open_order(order)

update(backorder, user, distributor, order_cycle)
update(backorder, user, distributor, order_cycle) if backorder
end

# Update a given backorder according to a distributor's order cycle.
Expand Down Expand Up @@ -58,6 +58,9 @@ def update_order_lines(backorder, order_cycle, variants, broker, orderer)
variants.map do |variant|
link = variant.semantic_links[0].semantic_id
solution = broker.best_offer(link)

next unless solution.offer

line = orderer.find_or_build_order_line(backorder, solution.offer)
if variant.on_demand
adjust_stock(variant, solution, line)
Expand All @@ -66,7 +69,7 @@ def update_order_lines(backorder, order_cycle, variants, broker, orderer)
end

line
end
end.compact
end

def cancel_stale_lines(unprocessed_lines, managed_variants, broker)
Expand Down
27 changes: 27 additions & 0 deletions spec/jobs/amend_backorder_job_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -130,5 +130,32 @@
.to change { backorder.lines.count }.from(2).to(1)
.and change { beans.reload.on_hand }.by(-12)
end

it "creates a new order" do
stub_request(:get, catalog_url).to_return(body: catalog_json)

# Record the placed backorder:
backorder = nil
allow_any_instance_of(FdcBackorderer).to receive(:find_order) do |*_args|
backorder
end
allow_any_instance_of(FdcBackorderer).to receive(:send_order) do |*args|
backorder = args[1]
end

# Call amending before a backorder has been placed.
expect { subject.amend_backorder(order) }
.to change { backorder.present? }
.to(true)

# We ordered a case of 12 cans: -3 + 12 = 9
expect(beans.on_hand).to eq 9

# Stock controlled items don't change stock in backorder:
expect(chia_seed.on_hand).to eq 7

expect(backorder.lines[0].quantity).to eq 1 # beans
expect(backorder.lines[1].quantity).to eq 5 # chia
end
end
end
45 changes: 43 additions & 2 deletions spec/services/backorder_updater_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

RSpec.describe BackorderUpdater do
let(:order) { create(:completed_order_with_totals) }
let(:order_cycle) { order.order_cycle }
let(:distributor) { order.distributor }
let(:beans) { beans_item.variant }
let(:beans_item) { order.line_items[0] }
Expand Down Expand Up @@ -107,11 +108,51 @@
.to change { backorder.lines.count }.from(2).to(1)
.and change { beans.reload.on_hand }.by(-12)
end

it "skips updating if there's is no backorder" do
allow_any_instance_of(FdcBackorderer).to receive(:find_open_order)
.and_return(nil)

expect { subject.amend_backorder(order) }.not_to raise_error
end
end

describe "#distributed_linked_variants" do
let(:order_cycle) { order.order_cycle }
describe "#update_order_lines" do
it "skips unavailable items" do
stub_request(:get, catalog_url).to_return(body: catalog_json)

# Record the placed backorder:
backorder = nil
allow_any_instance_of(FdcBackorderer).to receive(:find_order) do |*_args|
backorder
end
allow_any_instance_of(FdcBackorderer).to receive(:send_order) do |*args|
backorder = args[1]
end

BackorderJob.new.place_backorder(order)

# Now one of the products becomes unavailable in the catalog.
# I simulate that by changing the link so something unknown.
beans.semantic_links[0].update!(semantic_id: "https://example.net/unknown")

variants = [beans, chia_seed]
reference_link = chia_seed.semantic_links[0].semantic_id
urls = FdcUrlBuilder.new(reference_link)
catalog = DfcCatalog.load(user, urls.catalog_url)
orderer = FdcBackorderer.new(user, urls)
broker = FdcOfferBroker.new(catalog)
updated_lines = subject.update_order_lines(
backorder, order_cycle, variants, broker, orderer
)

expect(updated_lines.count).to eq 1
expect(updated_lines[0].offer.offeredItem.semanticId)
.to eq chia_seed.semantic_links[0].semantic_id
end
end

describe "#distributed_linked_variants" do
it "selects available variants with semantic links" do
variants = subject.distributed_linked_variants(order_cycle, distributor)
expect(variants).to match_array [beans, chia_seed]
Expand Down
23 changes: 23 additions & 0 deletions spec/system/consumer/checkout/backorder_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

require "system_helper"

RSpec.describe "Checkout" do
include ShopWorkflow
include CheckoutHelper

let(:variant) { order.variants.first }
let(:order) { create(:order_ready_for_confirmation) }

before do
variant.semantic_links << SemanticLink.new(semantic_id: "https://product")
set_order order
login_as create(:user)
end

it "triggers a backorder" do
visit checkout_step_path(:summary)

expect { place_order }.to enqueue_job BackorderJob
end
end

0 comments on commit c258bee

Please sign in to comment.