Synchronise remote products when order cycle opens

I considered pre-loading the variant and product with includes, But can't do that here because it's a polymorphic relationship.
This commit is contained in:
David Cook
2025-02-12 17:20:37 +11:00
committed by Maikel Linke
parent bdced0b9e2
commit 5b21c81ca5
3 changed files with 606 additions and 0 deletions

View File

@@ -5,6 +5,37 @@ class OrderCycleOpenedJob < ApplicationJob
def perform
ActiveRecord::Base.transaction do
recently_opened_order_cycles.find_each do |order_cycle|
# Process the order cycle. this might take a while, so this should be shifted to a separate job to allow concurrent processing.
order_cycle.suppliers.each do |supplier|
# Find authorised user to access remote products
dfc_user = supplier.owner # we assume the owner's account is the one used to import from dfc.
# Fetch all variants for this supplier in the order cycle
variants = order_cycle.exchanges.incoming.from_enterprise(supplier).joins(:exchange_variants).select('exchange_variants.variant_id')
links = SemanticLink.where(subject_id: variants)
# Find any catalogues associated with the variants
catalogs = links.group_by do |link|
FdcUrlBuilder.new(link.semantic_id).catalog_url
end
# Import selected variants from each catalog
catalogs.each do |catalog_url, catalog_links|
catalog_json = DfcRequest.new(dfc_user).call(catalog_url)
graph = DfcIo.import(catalog_json)
catalog = DfcCatalog.new(graph)
catalog.apply_wholesale_values!
catalog_links.each do |link|
catalog_item = catalog.item(link.semantic_id)
SuppliedProductImporter.update_product(catalog_item, link.subject) if catalog_item
end
end
end
# And notify any subscribers
OrderCycles::WebhookService.create_webhook_job(order_cycle, 'order_cycle.opened')
end
mark_as_opened(recently_opened_order_cycles)

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +1,13 @@
# frozen_string_literal: true
require 'spec_helper'
require_relative '../../engines/dfc_provider/spec/support/authorization_helper'
RSpec.describe OrderCycleOpenedJob do
include AuthorizationHelper
#todo: I don't think we need order cycles with exchanges. we don't need the factory at all here.
# also, maybe rearrange the spec. test selection with opened_at. then webhooks can have it's own define block.
let(:oc_opened_before) {
create(:order_cycle, orders_open_at: 1.hour.ago)
}
@@ -59,4 +64,40 @@ RSpec.describe OrderCycleOpenedJob do
threads.each(&:join)
end
end
describe "syncing remote products" do
let!(:user) { create(:oidc_user, owned_enterprises: [enterprise]) }
let(:enterprise) { create(:supplier_enterprise) }
let!(:variant) { create(:variant, name: "Sauce", supplier_id: enterprise.id) }
let!(:order_cycle) { create(:simple_order_cycle, orders_open_at: Time.zone.now,
suppliers: [enterprise], variants: [variant]) }
before do
user.oidc_account.update!(token: allow_token_for(email: user.email))
end
# should we move any parts of importing to a separate class, and test it separately?
it "synchronises products from a FDC catalog", vcr: true do
user.update!(oidc_account: build(:testdfc_account))
# One product is existing in OFN
product_id =
"https://env-0105831.jcloud-ver-jpe.ik-server.com/api/dfc/Enterprises/test-hodmedod/SuppliedProducts/44519466467635"
variant.semantic_links << SemanticLink.new(semantic_id: product_id)
expect {
OrderCycleOpenedJob.perform_now
variant.reload
order_cycle.reload
}.to change { order_cycle.opened_at }
.and change { enterprise.supplied_products.count }.by(0) # It should not add products, only update existing
.and change { variant.display_name }
.and change { variant.unit_value }
# 18.85 wholesale variant price divided by 12 cans in the slab.
.and change { variant.price }.to(1.57)
.and change { variant.on_demand }.to(true)
.and change { variant.on_hand }.by(0)
.and query_database 45
end
end
end