Files
openfoodnetwork/app/models/spree/order_contents.rb
Gaetan Craig-Riou 4a6e4d4c6d Ensure shipment is updated when using update_or_create
`Spree::OrderContents#update_or_create` is used to update the cart when
on the /shop page. If you start an order and proceed to the "Order
summary" step, and then decide to update your order by using the shop
link next to the cart, such update wouldn't update the shipment.
This result in the order page in the backoffice displaying the wrong data,
and more importantly, in the stock not being updated.
So now we ensure shipment will be updated, which result in the checkout
flow being restarted, thus making sure the shipment is updated.
2024-12-04 16:30:45 +11:00

132 lines
3.2 KiB
Ruby

# frozen_string_literal: true
module Spree
class OrderContents
attr_accessor :order
def initialize(order)
@order = order
end
# Get current line item for variant if exists
# Add variant qty to line_item
def add(variant, quantity = 1, shipment = nil)
line_item = add_to_line_item(variant, quantity, shipment)
update_shipment(shipment)
update_order
line_item
end
# Get current line item for variant
# Remove variant qty from line_item
def remove(variant, quantity = nil, shipment = nil, restock_item = true)
line_item = remove_from_line_item(variant, quantity, shipment, restock_item)
update_shipment(shipment)
order.update_order_fees! if order.completed?
update_order
line_item
end
def update_or_create(variant, attributes)
line_item = find_line_item_by_variant(variant)
if line_item
line_item.update(attributes)
else
line_item = Spree::LineItem.new(attributes)
line_item.variant = variant
line_item.price = variant.price
order.line_items << line_item
end
update_shipment
order.reload
line_item
end
def update_cart(params)
if order.update(params)
discard_empty_line_items
update_shipment
update_order
true
else
false
end
end
def update_item(line_item, params)
if line_item.update(params)
discard_empty_line_items
order.update_line_item_fees! line_item
order.update_order_fees! if order.completed?
update_shipment
update_order
true
else
false
end
end
private
def discard_empty_line_items
order.line_items = order.line_items.select { |li| li.quantity.positive? }
end
def update_shipment(target_shipment = nil)
if order.completed? || target_shipment.present?
order.update_shipping_fees!
else
order.ensure_updated_shipments
end
end
def add_to_line_item(variant, quantity, shipment = nil)
line_item = find_line_item_by_variant(variant)
if line_item
line_item.target_shipment = shipment
line_item.quantity += quantity.to_i
else
line_item = order.line_items.new(quantity:, variant:)
line_item.target_shipment = shipment
line_item.price = variant.price
end
line_item.save
line_item
end
def remove_from_line_item(variant, quantity, shipment = nil, restock_item = true)
line_item = find_line_item_by_variant(variant, true)
line_item.restock_item = restock_item
quantity.present? ? line_item.quantity += -quantity : line_item.quantity = 0
line_item.target_shipment = shipment
if line_item.quantity == 0
line_item.destroy
else
line_item.save!
end
line_item
end
def find_line_item_by_variant(variant, raise_error = false)
line_item = order.find_line_item_by_variant(variant)
if line_item.blank? && raise_error
raise ActiveRecord::RecordNotFound, "Line item not found for variant #{variant.sku}"
end
line_item
end
def update_order
order.update_order!
order.reload
end
end
end