mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
This means we avoid fetching all of the hub's variants every time we scope a product. Applies to every product loaded when displaying a shops's product list.
99 lines
2.8 KiB
Ruby
99 lines
2.8 KiB
Ruby
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
|