Skip to content

Commit

Permalink
Create Spree::SimpleOrderContents
Browse files Browse the repository at this point in the history
Spree::OrderContents interacts heavily with the current promotion
system. This adds a new `Spree::SimpleOrderContents` class that we can
use once all the core functionality and specs for the legacy promotion
system are migrated to `solidus_legacy_promotions`.

We're keeping `Spree::OrderContents` though, with the intention of
moving it to `solidus_legacy_promotions` in the future.
  • Loading branch information
mamhoff committed May 22, 2024
1 parent 098260d commit 0674701
Show file tree
Hide file tree
Showing 5 changed files with 465 additions and 355 deletions.
101 changes: 5 additions & 96 deletions core/app/models/spree/order_contents.rb
Original file line number Diff line number Diff line change
@@ -1,39 +1,9 @@
# frozen_string_literal: true

module Spree
class OrderContents
attr_accessor :order

def initialize(order)
@order = order
end

# Add a line items to the order if there is inventory to do so
# and populate Promotions
#
# @param [Spree::Variant] variant The variant the line_item should
# be associated with
# @param [Integer] quantity The line_item quantity
# @param [Hash] options Options for the adding proccess
# Valid options:
# shipment: [Spree::Shipment] LineItem target shipment
#
# @return [Spree::LineItem]
def add(variant, quantity = 1, options = {})
line_item = add_to_line_item(variant, quantity, options)
after_add_or_remove(line_item, options)
end

def remove(variant, quantity = 1, options = {})
line_item = remove_from_line_item(variant, quantity, options)
after_add_or_remove(line_item, options)
end

def remove_line_item(line_item, options = {})
order.line_items.destroy(line_item)
after_add_or_remove(line_item, options)
end

class OrderContents < Spree::SimpleOrderContents
# Updates the order's line items with the params passed in.
# Also runs the PromotionHandler::Cart.
def update_cart(params)
if order.update(params)
unless order.completed?
Expand All @@ -43,7 +13,7 @@ def update_cart(params)
# promotion rules would not be triggered.
reload_totals
order.check_shipments_and_restart_checkout
PromotionHandler::Cart.new(order).activate
::Spree::PromotionHandler::Cart.new(order).activate
end
reload_totals
true
Expand All @@ -52,76 +22,15 @@ def update_cart(params)
end
end

def advance
while @order.next; end
end

def approve(user: nil, name: nil)
if user.blank? && name.blank?
raise ArgumentError, 'user or name must be specified'
end

order.update!(
approver: user,
approver_name: name,
approved_at: Time.current
)
end

private

def after_add_or_remove(line_item, options = {})
reload_totals
shipment = options[:shipment]
shipment.present? ? shipment.update_amounts : order.check_shipments_and_restart_checkout
PromotionHandler::Cart.new(order, line_item).activate
::Spree::PromotionHandler::Cart.new(order, line_item).activate
reload_totals
line_item
end

def reload_totals
@order.recalculate
end

def add_to_line_item(variant, quantity, options = {})
line_item = grab_line_item_by_variant(variant, false, options)

line_item ||= order.line_items.new(
quantity: 0,
variant: variant,
adjustments: [],
)

line_item.quantity += quantity.to_i
line_item.options = ActionController::Parameters.new(options).permit(PermittedAttributes.line_item_attributes).to_h

line_item.target_shipment = options[:shipment]
line_item.save!
line_item
end

def remove_from_line_item(variant, quantity, options = {})
line_item = grab_line_item_by_variant(variant, true, options)
line_item.quantity -= quantity
line_item.target_shipment = options[:shipment]

if line_item.quantity <= 0
order.line_items.destroy(line_item)
else
line_item.save!
end

line_item
end

def grab_line_item_by_variant(variant, raise_error = false, options = {})
line_item = order.find_line_item_by_variant(variant, options)

if !line_item.present? && raise_error
raise ActiveRecord::RecordNotFound, "Line item not found for variant #{variant.sku}"
end

line_item
end
end
end
120 changes: 120 additions & 0 deletions core/app/models/spree/simple_order_contents.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# frozen_string_literal: true

module Spree
class SimpleOrderContents
attr_accessor :order

def initialize(order)
@order = order
end

# Add a line items to the order if there is inventory to do so
# and populate Promotions
#
# @param [Spree::Variant] variant The variant the line_item should
# be associated with
# @param [Integer] quantity The line_item quantity
# @param [Hash] options Options for the adding proccess
# Valid options:
# shipment: [Spree::Shipment] LineItem target shipment
#
# @return [Spree::LineItem]
def add(variant, quantity = 1, options = {})
line_item = add_to_line_item(variant, quantity, options)
after_add_or_remove(line_item, options)
end

def remove(variant, quantity = 1, options = {})
line_item = remove_from_line_item(variant, quantity, options)
after_add_or_remove(line_item, options)
end

def remove_line_item(line_item, options = {})
order.line_items.destroy(line_item)
after_add_or_remove(line_item, options)
end

def update_cart(params)
if order.update(params)
unless order.completed?
order.line_items = order.line_items.select { |li| li.quantity > 0 }
order.check_shipments_and_restart_checkout
end
reload_totals
true
else
false
end
end

def advance
while @order.next; end
end

def approve(user: nil, name: nil)
if user.blank? && name.blank?
raise ArgumentError, 'user or name must be specified'
end

order.update!(
approver: user,
approver_name: name,
approved_at: Time.current
)
end

private

def after_add_or_remove(line_item, options = {})
shipment = options[:shipment]
shipment.present? ? shipment.update_amounts : order.check_shipments_and_restart_checkout
reload_totals
line_item
end

def reload_totals
@order.recalculate
end

def add_to_line_item(variant, quantity, options = {})
line_item = grab_line_item_by_variant(variant, false, options)

line_item ||= order.line_items.new(
quantity: 0,
variant: variant,
adjustments: [],
)

line_item.quantity += quantity.to_i
line_item.options = ActionController::Parameters.new(options).permit(PermittedAttributes.line_item_attributes).to_h

line_item.target_shipment = options[:shipment]
line_item.save!
line_item
end

def remove_from_line_item(variant, quantity, options = {})
line_item = grab_line_item_by_variant(variant, true, options)
line_item.quantity -= quantity
line_item.target_shipment = options[:shipment]

if line_item.quantity <= 0
order.line_items.destroy(line_item)
else
line_item.save!
end

line_item
end

def grab_line_item_by_variant(variant, raise_error = false, options = {})
line_item = order.find_line_item_by_variant(variant, options)

if !line_item.present? && raise_error
raise ActiveRecord::RecordNotFound, "Line item not found for variant #{variant.sku}"
end

line_item
end
end
end
Loading

0 comments on commit 0674701

Please sign in to comment.