mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-25 20:46:48 +00:00
100 lines
3.1 KiB
Ruby
100 lines
3.1 KiB
Ruby
require 'spree/core/controller_helpers/order_decorator'
|
|
|
|
class CartController < BaseController
|
|
before_filter :check_authorization
|
|
|
|
def populate
|
|
# Without intervention, the Spree::Adjustment#update_adjustable callback is called many times
|
|
# during cart population, for both taxation and enterprise fees. This operation triggers a
|
|
# costly Spree::Order#update!, which only needs to be run once. We avoid this by disabling
|
|
# callbacks on Spree::Adjustment and then manually invoke Spree::Order#update! on success.
|
|
Spree::Adjustment.without_callbacks do
|
|
cart_service = CartService.new(current_order(true))
|
|
|
|
if cart_service.populate(params.slice(:products, :variants, :quantity), true)
|
|
fire_event('spree.cart.add')
|
|
fire_event('spree.order.contents_changed')
|
|
|
|
current_order.cap_quantity_at_stock!
|
|
current_order.update!
|
|
|
|
variant_ids = variant_ids_in(cart_service.variants_h)
|
|
|
|
render json: { error: false, stock_levels: stock_levels(current_order, variant_ids) },
|
|
status: 200
|
|
|
|
else
|
|
render json: { error: true }, status: 412
|
|
end
|
|
end
|
|
populate_variant_attributes
|
|
end
|
|
|
|
# Report the stock levels in the order for all variant ids requested
|
|
def stock_levels(order, variant_ids)
|
|
stock_levels = li_stock_levels(order)
|
|
|
|
li_variant_ids = stock_levels.keys
|
|
(variant_ids - li_variant_ids).each do |variant_id|
|
|
stock_levels[variant_id] = { quantity: 0, max_quantity: 0, on_hand: Spree::Variant.find(variant_id).on_hand }
|
|
end
|
|
|
|
stock_levels
|
|
end
|
|
|
|
def variant_ids_in(variants_h)
|
|
variants_h.map { |v| v[:variant_id].to_i }
|
|
end
|
|
|
|
private
|
|
|
|
def check_authorization
|
|
session[:access_token] ||= params[:token]
|
|
order = Spree::Order.find_by_number(params[:id]) || current_order
|
|
|
|
if order
|
|
authorize! :edit, order, session[:access_token]
|
|
else
|
|
authorize! :create, Spree::Order
|
|
end
|
|
end
|
|
|
|
def populate_variant_attributes
|
|
order = current_order.reload
|
|
|
|
populate_variant_attributes_from_variant(order) if params.key? :variant_attributes
|
|
populate_variant_attributes_from_product(order) if params.key? :quantity
|
|
end
|
|
|
|
def populate_variant_attributes_from_variant(order)
|
|
params[:variant_attributes].each do |variant_id, attributes|
|
|
order.set_variant_attributes(Spree::Variant.find(variant_id), attributes)
|
|
end
|
|
end
|
|
|
|
def populate_variant_attributes_from_product(order)
|
|
params[:products].each do |_product_id, variant_id|
|
|
max_quantity = params[:max_quantity].to_i
|
|
order.set_variant_attributes(Spree::Variant.find(variant_id),
|
|
max_quantity: max_quantity)
|
|
end
|
|
end
|
|
|
|
def li_stock_levels(order)
|
|
Hash[
|
|
order.line_items.map do |li|
|
|
[li.variant.id,
|
|
{ quantity: li.quantity,
|
|
max_quantity: li.max_quantity,
|
|
on_hand: wrap_json_infinity(li.variant.on_hand) }]
|
|
end
|
|
]
|
|
end
|
|
|
|
# Rails to_json encodes Float::INFINITY as Infinity, which is not valid JSON
|
|
# Return it as a large integer (max 32 bit signed int)
|
|
def wrap_json_infinity(number)
|
|
number == Float::INFINITY ? 2147483647 : number
|
|
end
|
|
end
|