Skip to content

Commit

Permalink
Calculators and Actions: Ignore automatic items
Browse files Browse the repository at this point in the history
Automatic items are probably already 100% discounted, and it's really
hard to make their discounts play well with others.
  • Loading branch information
mamhoff committed Nov 7, 2023
1 parent ce07341 commit 1588b7f
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@ module SolidusFriendlyPromotions
module LineItemDecorator
def self.prepended(base)
base.belongs_to :managed_by_order_action, class_name: "SolidusFriendlyPromotions::PromotionAction", optional: true
base.validate :validate_managed_quantity_same, on: :update
end

private

def validate_managed_quantity_same
if managed_by_order_action && quantity_changed?
errors.add(:quantity, :cannot_be_changed_for_automated_items)
end
end

Spree::LineItem.prepend self
Spree::LineItem.prepend SolidusFriendlyPromotions::DiscountableAmount
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ def reset_current_discounts
shipments.each(&:reset_current_discounts)
end

# This helper method excludes line items that are managed by an order action for the benefit
# of calculators and actions that discount normal line items. Line items that are managed by an
# order actions handle their discounts themselves.
def discountable_line_items
line_items.reject(&:managed_by_order_action)
end

def apply_shipping_promotions
if Spree::Config.promotion_adjuster_class <= SolidusFriendlyPromotions::FriendlyPromotionAdjuster
recalculate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def compute_amount(line_item)
private

def actionable_line_items(order)
order.line_items.select do |item|
order.discountable_line_items.select do |item|
promotion.rules.select do |rule|
rule.applicable?(item)
end.all? { |rule| rule.eligible?(item) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def compute_line_item(line_item)
private

def eligible_line_items(order)
order.line_items.select do |line_item|
order.discountable_line_items.select do |line_item|
calculable.promotion.eligible_by_applicable_rules?(line_item)
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ def perform_order_actions(lane_promotions, lane)
end

def adjust_line_items(promotions)
order.line_items.select do |line_item|
line_item.variant.product.promotionable? && !line_item.managed_by_order_action
order.discountable_line_items.select do |line_item|
line_item.variant.product.promotionable?
end.map do |line_item|
discounts = generate_discounts(promotions, line_item)
chosen_item_discounts = SolidusFriendlyPromotions.config.discount_chooser_class.new(discounts).call
Expand Down
4 changes: 4 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -257,3 +257,7 @@ en:
attributes:
base:
disallowed_with_apply_automatically: Could not create promotion code on promotion that apply automatically
spree/line_item:
attributes:
quantity:
cannot_be_changed_for_automated_items: cannot be changed on a line item managed by a promotion action
21 changes: 21 additions & 0 deletions spec/models/spree/line_item_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,25 @@
expect { subject }.to change { line_item.current_discounts.length }.from(1).to(0)
end
end

describe "changing quantities" do
context "when line item is managed by an automation" do
let(:order) { create(:order) }
let(:variant) { create(:variant) }
let(:promotion) { create(:friendly_promotion, apply_automatically: true) }
let(:promotion_action) { SolidusFriendlyPromotions::Actions::CreateDiscountedItem.create!(calculator: hundred_percent, preferred_variant_id: variant.id, promotion: promotion) }
let(:hundred_percent) { SolidusFriendlyPromotions::Calculators::Percent.new(preferred_percent: 100) }

before do
order.line_items.create!(variant: variant, managed_by_order_action: promotion_action, quantity: 1)
end

it "makes the line item invalid" do
line_item = order.line_items.first
line_item.quantity = 2
expect { line_item.save! }.to raise_exception(ActiveRecord::RecordInvalid)
expect(line_item.errors.full_messages.first).to eq("Quantity cannot be changed on a line item managed by a promotion action")
end
end
end
end

0 comments on commit 1588b7f

Please sign in to comment.