diff --git a/app/jobs/backorder_job.rb b/app/jobs/backorder_job.rb index 401f824d6a..c949425513 100644 --- a/app/jobs/backorder_job.rb +++ b/app/jobs/backorder_job.rb @@ -1,10 +1,6 @@ # frozen_string_literal: true class BackorderJob < ApplicationJob - FDC_BASE_URL = "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod" - FDC_CATALOG_URL = "#{FDC_BASE_URL}/SuppliedProducts".freeze - FDC_ORDERS_URL = "#{FDC_BASE_URL}/Orders".freeze - # In the current FDC project, one shop wants to review and adjust orders # before finalising. They also run a market stall and need to adjust stock # levels after the market. This should be done within four hours. @@ -36,9 +32,14 @@ class BackorderJob < ApplicationJob def self.place_backorder(order, linked_variants) user = order.distributor.owner - orderer = FdcBackorderer.new(user) + + # We are assuming that all variants are linked to the same wholesale + # shop and its catalog: + urls = FdcUrlBuilder.new(linked_variants[0].semantic_links[0].semantic_id) + orderer = FdcBackorderer.new(user, urls) + backorder = orderer.find_or_build_order(order) - broker = load_broker(order.distributor.owner) + broker = load_broker(order.distributor.owner, urls) ordered_quantities = {} linked_variants.each do |variant| @@ -73,13 +74,13 @@ class BackorderJob < ApplicationJob retail_quantity end - def self.load_broker(user) - FdcOfferBroker.new(load_catalog(user)) + def self.load_broker(user, urls) + FdcOfferBroker.new(load_catalog(user, urls)) end - def self.load_catalog(user) + def self.load_catalog(user, urls) api = DfcRequest.new(user) - catalog_json = api.call(FDC_CATALOG_URL) + catalog_json = api.call(urls.catalog_url) DfcIo.import(catalog_json) end diff --git a/app/jobs/complete_backorder_job.rb b/app/jobs/complete_backorder_job.rb index 10dc90de85..0f51e0ea76 100644 --- a/app/jobs/complete_backorder_job.rb +++ b/app/jobs/complete_backorder_job.rb @@ -16,13 +16,13 @@ class CompleteBackorderJob < ApplicationJob # Having the id makes sure that we don't accidentally finalise # someone else's order. def perform(user, distributor, order_cycle, order_id) - service = FdcBackorderer.new(user) - order = service.find_order(order_id) + order = FdcBackorderer.new(user, nil).find_order(order_id) + urls = FdcUrlBuilder.new(order.lines[0].offer.offeredItem.semanticId) variants = order_cycle.variants_distributed_by(distributor) - adjust_quantities(user, order, variants) + adjust_quantities(user, order, urls, variants) - service.complete_order(order) + FdcBackorderer.new(user, urls).complete_order(order) end # Check if we have enough stock to reduce the backorder. @@ -30,8 +30,8 @@ class CompleteBackorderJob < ApplicationJob # Our local stock can increase when users cancel their orders. # But stock levels could also have been adjusted manually. So we review all # quantities before finalising the order. - def adjust_quantities(user, order, variants) - broker = FdcOfferBroker.new(BackorderJob.load_catalog(user)) + def adjust_quantities(user, order, urls, variants) + broker = FdcOfferBroker.new(BackorderJob.load_catalog(user, urls)) order.lines.each do |line| line.quantity = line.quantity.to_i diff --git a/app/services/fdc_backorderer.rb b/app/services/fdc_backorderer.rb index 6d70345242..c5b3aa5cf1 100644 --- a/app/services/fdc_backorderer.rb +++ b/app/services/fdc_backorderer.rb @@ -2,14 +2,11 @@ # Place and update orders based on missing stock. class FdcBackorderer - FDC_BASE_URL = "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod" - FDC_ORDERS_URL = "#{FDC_BASE_URL}/Orders".freeze - FDC_SALE_SESSION_URL = "#{FDC_BASE_URL}/SalesSession/#".freeze + attr_reader :user, :urls - attr_reader :user - - def initialize(user) + def initialize(user, urls) @user = user + @urls = urls end def find_or_build_order(ofn_order) @@ -17,13 +14,13 @@ class FdcBackorderer end def build_new_order(ofn_order) - OrderBuilder.new_order(ofn_order, FDC_ORDERS_URL).tap do |order| + OrderBuilder.new_order(ofn_order, urls.orders_url).tap do |order| order.saleSession = build_sale_session(ofn_order) end end def find_open_order - graph = import(FDC_ORDERS_URL) + graph = import(urls.orders_url) open_orders = graph&.select do |o| o.semanticType == "dfc-b:Order" && o.orderStatus[:path] == "Held" end @@ -125,12 +122,12 @@ class FdcBackorderer end def new?(order) - order.semanticId == FDC_ORDERS_URL + order.semanticId == urls.orders_url end def build_sale_session(order) SaleSessionBuilder.build(order.order_cycle).tap do |session| - session.semanticId = FDC_SALE_SESSION_URL + session.semanticId = urls.sale_session_url end end end diff --git a/app/services/fdc_url_builder.rb b/app/services/fdc_url_builder.rb new file mode 100644 index 0000000000..9bab228377 --- /dev/null +++ b/app/services/fdc_url_builder.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +# The DFC standard doesn't include endpoint discovery yet. +# So for now we are guessing URLs based on our FDC pilot project. +class FdcUrlBuilder + attr_reader :catalog_url, :orders_url, :sale_session_url + + # At the moment, we start with a product link like this: + # + # https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635 + def initialize(semantic_id) + @catalog_url, _slash, _id = semantic_id.rpartition("/") + @orders_url = @catalog_url.sub("/SuppliedProducts", "/Orders") + @sale_session_url = @catalog_url.sub("/SuppliedProducts", "/SalesSession/#") + end +end diff --git a/spec/jobs/backorder_job_spec.rb b/spec/jobs/backorder_job_spec.rb index b36dcfa359..fe4a65e869 100644 --- a/spec/jobs/backorder_job_spec.rb +++ b/spec/jobs/backorder_job_spec.rb @@ -57,7 +57,8 @@ RSpec.describe BackorderJob do ) completion_time = Date.tomorrow.noon + 4.hours - orderer = FdcBackorderer.new(user) + urls = FdcUrlBuilder.new(product_link) + orderer = FdcBackorderer.new(user, urls) backorder = orderer.build_new_order(order) backorder.client = "https://openfoodnetwork.org.uk/api/dfc/enterprises/203468" diff --git a/spec/jobs/complete_backorder_job_spec.rb b/spec/jobs/complete_backorder_job_spec.rb index bc11991414..619333a055 100644 --- a/spec/jobs/complete_backorder_job_spec.rb +++ b/spec/jobs/complete_backorder_job_spec.rb @@ -4,7 +4,11 @@ require 'spec_helper' RSpec.describe CompleteBackorderJob do let(:user) { build(:testdfc_user) } - let(:catalog) { BackorderJob.load_catalog(user) } + let(:catalog) { BackorderJob.load_catalog(user, urls) } + let(:urls) { FdcUrlBuilder.new(product_link) } + let(:product_link) { + "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635" + } let(:retail_product) { catalog.find { |item| item.semanticType == "dfc-b:SuppliedProduct" } } @@ -12,7 +16,7 @@ RSpec.describe CompleteBackorderJob do flow = catalog.find { |item| item.semanticType == "dfc-b:AsPlannedProductionFlow" } catalog.find { |item| item.semanticId == flow.product } } - let(:orderer) { FdcBackorderer.new(user) } + let(:orderer) { FdcBackorderer.new(user, urls) } let(:order) { backorder = orderer.find_or_build_order(ofn_order) broker = FdcOfferBroker.new(catalog) diff --git a/spec/services/fdc_backorderer_spec.rb b/spec/services/fdc_backorderer_spec.rb index 8aa9d347b6..6884b28d6c 100644 --- a/spec/services/fdc_backorderer_spec.rb +++ b/spec/services/fdc_backorderer_spec.rb @@ -3,7 +3,11 @@ require 'spec_helper' RSpec.describe FdcBackorderer do - let(:subject) { FdcBackorderer.new(order.distributor.owner) } + let(:subject) { FdcBackorderer.new(order.distributor.owner, urls) } + let(:urls) { FdcUrlBuilder.new(product_link) } + let(:product_link) { + "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635" + } let(:order) { create(:completed_order_with_totals) } let(:account) { OidcAccount.new( @@ -25,11 +29,11 @@ RSpec.describe FdcBackorderer do # Build a new order when no open one is found: order.order_cycle = build(:order_cycle) backorder = subject.find_or_build_order(order) - expect(backorder.semanticId).to eq FdcBackorderer::FDC_ORDERS_URL + expect(backorder.semanticId).to eq urls.orders_url expect(backorder.lines).to eq [] # Add items and place the new order: - catalog = BackorderJob.load_catalog(order.distributor.owner) + catalog = BackorderJob.load_catalog(order.distributor.owner, urls) product = catalog.find { |i| i.semanticType == "dfc-b:SuppliedProduct" } offer = FdcOfferBroker.new(nil).offer_of(product) line = subject.find_or_build_order_line(backorder, offer) @@ -55,19 +59,19 @@ RSpec.describe FdcBackorderer do describe "#find_or_build_order" do it "builds an order object" do account.updated_at = Time.zone.now - stub_request(:get, FdcBackorderer::FDC_ORDERS_URL) + stub_request(:get, urls.orders_url) .to_return(status: 200, body: "{}") backorder = subject.find_or_build_order(order) - expect(backorder.semanticId).to eq FdcBackorderer::FDC_ORDERS_URL + expect(backorder.semanticId).to eq urls.orders_url expect(backorder.lines).to eq [] end end describe "#find_or_build_order_line" do it "add quantity to an existing line item", vcr: true do - catalog = BackorderJob.load_catalog(order.distributor.owner) + catalog = BackorderJob.load_catalog(order.distributor.owner, urls) backorder = subject.find_or_build_order(order) existing_line = backorder.lines[0] diff --git a/spec/services/fdc_offer_broker_spec.rb b/spec/services/fdc_offer_broker_spec.rb index 024cd9b257..2e4ffb3a5d 100644 --- a/spec/services/fdc_offer_broker_spec.rb +++ b/spec/services/fdc_offer_broker_spec.rb @@ -4,7 +4,11 @@ require 'spec_helper' RSpec.describe FdcOfferBroker do subject { FdcOfferBroker.new(catalog) } - let(:catalog) { BackorderJob.load_catalog(user) } + let(:catalog) { BackorderJob.load_catalog(user, urls) } + let(:urls) { FdcUrlBuilder.new(product_link) } + let(:product_link) { + "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635" + } let(:user) { build(:testdfc_user) } let(:product) { catalog.find { |item| item.semanticType == "dfc-b:SuppliedProduct" } diff --git a/spec/services/fdc_url_builder_spec.rb b/spec/services/fdc_url_builder_spec.rb new file mode 100644 index 0000000000..5557cccf2a --- /dev/null +++ b/spec/services/fdc_url_builder_spec.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe FdcUrlBuilder do + subject(:urls) { FdcUrlBuilder.new(product_link) } + let(:product_link) { + "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635" + } + + it "knows the right URLs" do + expect(subject.catalog_url).to eq "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts" + expect(subject.orders_url).to eq "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/Orders" + expect(subject.sale_session_url).to eq "https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SalesSession/#" + end +end