require 'open_food_network/scope_product_to_hub' class ProductsRenderer class NoProducts < RuntimeError; end DEFAULT_PAGE = 1 DEFAULT_PER_PAGE = 10 def initialize(distributor, order_cycle, customer, args = {}) @distributor = distributor @order_cycle = order_cycle @customer = customer @args = args end def products_json raise NoProducts unless order_cycle && distributor && products ActiveModel::ArraySerializer.new(products, each_serializer: Api::ProductSerializer, current_order_cycle: order_cycle, current_distributor: distributor, variants: variants_for_shop_by_id, master_variants: master_variants_for_shop_by_id, enterprise_fee_calculator: enterprise_fee_calculator).to_json end private attr_reader :order_cycle, :distributor, :customer, :args def products return unless order_cycle @products ||= begin results = distributed_products.products_relation.order(taxon_order) filter_and_paginate(results). each { |product| product_scoper.scope(product) } # Scope results with variant_overrides end end def product_scoper @product_scoper ||= OpenFoodNetwork::ScopeProductToHub.new(distributor) end def enterprise_fee_calculator OpenFoodNetwork::EnterpriseFeeCalculator.new distributor, order_cycle end def filter_and_paginate(query) query. ransack(args[:q]). result. page(args[:page] || DEFAULT_PAGE). per(args[:per_page] || DEFAULT_PER_PAGE) end def distributed_products OrderCycleDistributedProducts.new(distributor, order_cycle, customer) end def taxon_order if distributor.preferred_shopfront_taxon_order.present? distributor .preferred_shopfront_taxon_order .split(",").map { |id| "spree_products.primary_taxon_id=#{id} DESC" } .join(", ") + ", spree_products.name ASC, spree_products.id ASC" else "spree_products.name ASC, spree_products.id" end end def variants_for_shop @variants_for_shop ||= begin scoper = OpenFoodNetwork::ScopeVariantToHub.new(distributor) distributed_products.variants_relation. includes(:default_price, :stock_locations, :product). where(product_id: products). each { |v| scoper.scope(v) } # Scope results with variant_overrides end end def variants_for_shop_by_id index_by_product_id variants_for_shop.reject(&:is_master) end def master_variants_for_shop_by_id index_by_product_id variants_for_shop.select(&:is_master) end def index_by_product_id(variants) variants.each_with_object({}) do |v, vs| vs[v.product_id] ||= [] vs[v.product_id] << v end end end