Files
openfoodnetwork/app/services/fdc_offer_broker.rb
2025-01-07 11:03:34 +11:00

73 lines
2.1 KiB
Ruby

# frozen_string_literal: true
# Finds wholesale offers for retail products.
class FdcOfferBroker
# TODO: Find a better way to provide this data.
Solution = Struct.new(:product, :factor, :offer)
RetailSolution = Struct.new(:retail_product_id, :factor)
attr_reader :catalog
def initialize(catalog)
@catalog = catalog
end
def best_offer(product_id)
Solution.new(
wholesale_product(product_id),
contained_quantity(product_id),
offer_of(wholesale_product(product_id))
)
end
def wholesale_product(product_id)
production_flow = catalog.item("#{product_id}/AsPlannedProductionFlow")
if production_flow
production_flow.product
else
# We didn't find a wholesale variant, falling back to the given product.
catalog.item(product_id)
end
end
def contained_quantity(product_id)
consumption_flow = catalog.item("#{product_id}/AsPlannedConsumptionFlow")
# If we don't find a transformation, we return the original product,
# which contains exactly one of itself (identity).
consumption_flow&.quantity&.value&.to_i || 1
end
def wholesale_to_retail(wholesale_product_id)
production_flow = flow_producing(wholesale_product_id)
return RetailSolution.new(wholesale_product_id, 1) if production_flow.nil?
consumption_flow = catalog.item(
production_flow.semanticId.sub("AsPlannedProductionFlow", "AsPlannedConsumptionFlow")
)
retail_product_id = consumption_flow.product.semanticId
contained_quantity = consumption_flow.quantity.value.to_i
RetailSolution.new(retail_product_id, contained_quantity)
end
def offer_of(product)
product&.catalogItems&.first&.offers&.first&.tap do |offer|
# Unfortunately, the imported catalog doesn't provide the reverse link:
offer.offeredItem = product
end
end
def flow_producing(wholesale_product_id)
@production_flows_by_product_id ||= production_flows.index_by { |flow| flow.product.semanticId }
@production_flows_by_product_id[wholesale_product_id]
end
def production_flows
@production_flows ||= catalog.select_type("dfc-b:AsPlannedProductionFlow")
end
end