Files
openfoodnetwork/app/jobs/open_order_cycle_job.rb
Maikel Linke 406018e7eb Simplify resetting variants
I was hoping to reduce the query count but it stayed the same. In fact,
I'm expecting the query count to be higher with this version. The
DfcCatalogImporter queries all variants and links at once while the OC
job is not pre-loading the variants at the moment. We can optimise the
job though.

If we kept the old version and there were multiple catalogs per variant
then we would call the importer with the reset multiple times. The job
is iterating through each link only once though. So depending on the
ratio of catalogs to variants, I'm not sure which version would be more
efficient.

No version is properly dealing with the edge-case of multiple catalogs
per variant anyway. Imagine there are two catalogs with different stock
levels. Which one do we choose? Or do we add up?
And if the variant disappears from one catalog we still want to sell it
through the other. But depending on the order of processing, we may
reset the variant if it's missing in the last catalog. But let's worry
about that when it actually happens. Maybe it will be better to restrict
variants to one catalog.
2025-03-27 15:12:45 +11:00

72 lines
2.4 KiB
Ruby

# frozen_string_literal: true
# Run any pre-conditions and mark order cycle as open.
#
# Currently, an order cycle is considered open in the shopfront when orders_open_at >= now.
# But now there are some pre-conditions for opening an order cycle, so we would like to change that.
# Instead, the presence of opened_at (and absence of processed_at) should indicate it is open.
class OpenOrderCycleJob < ApplicationJob
sidekiq_options retry_for: 10.minutes
def perform(order_cycle_id)
ActiveRecord::Base.transaction do
# Fetch order cycle if it's still unopened, and lock DB row until finished
order_cycle = OrderCycle.lock.find_by!(id: order_cycle_id, opened_at: nil)
sync_remote_variants(order_cycle)
# Mark as opened
opened_at = Time.zone.now
order_cycle.update_columns(opened_at:)
# And notify any subscribers
OrderCycles::WebhookService.create_webhook_job(order_cycle, 'order_cycle.opened', opened_at)
end
end
private
def sync_remote_variants(order_cycle)
# Sync any remote variants for each supplier
order_cycle.suppliers.each do |supplier|
links = variant_links_for(order_cycle, supplier)
next if links.empty?
# 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.
import_variants(links, dfc_user)
end
end
# Fetch all remote variants for this supplier in the order cycle
def variant_links_for(order_cycle, supplier)
variants = order_cycle.exchanges.incoming.from_enterprise(supplier)
.joins(:exchange_variants).select('exchange_variants.variant_id')
SemanticLink.where(subject_id: variants)
end
def import_variants(links, dfc_user)
# 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 = DfcCatalog.load(dfc_user, catalog_url)
catalog.apply_wholesale_values!
catalog_links.each do |link|
catalog_item = catalog.item(link.semantic_id)
if catalog_item
SuppliedProductImporter.update_product(catalog_item, link.subject)
else
DfcCatalogImporter.reset_variant(link.subject)
end
end
end
end
end