Skip to content

Commit 0c5e751

Browse files
committed
wip
1 parent bb73e2a commit 0c5e751

File tree

3 files changed

+110
-0
lines changed

3 files changed

+110
-0
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# frozen_string_literal: true
2+
3+
module SolidusPromotions
4+
class ProductDiscounter
5+
attr_reader :order, :product, :pricing_options, :promotions, :quantity
6+
7+
def initialize(product:, order:, pricing_options:, quantity: 1)
8+
@product = product
9+
@order = order
10+
@pricing_options = pricing_options
11+
@quantity = quantity
12+
@promotions = SolidusPromotions::OrderAdjuster::LoadPromotions.new(order:).call
13+
end
14+
15+
def call
16+
if product.has_variants?
17+
product.variants.each { |variant| discount_variant(variant) }
18+
else
19+
discount_variant(product.master)
20+
end
21+
end
22+
23+
private
24+
25+
def discount_variant(variant)
26+
variant.discountable_price = variant.price_for_options(pricing_options)
27+
28+
return unless variant.product.promotionable?
29+
30+
SolidusPromotions::Promotion.ordered_lanes.each_key do |lane|
31+
lane_promotions = promotions.select { |promotion| promotion.lane == lane }
32+
lane_benefits = eligible_benefits_for_promotable(lane_promotions.flat_map(&:benefits), order)
33+
discounts = generate_discounts(lane_benefits, variant.discountable_price)
34+
chosen_discounts = SolidusPromotions.config.discount_chooser_class.new(discounts).call
35+
variant.discountable_price.current_discounts.concat(chosen_discounts)
36+
end
37+
end
38+
39+
def eligible_benefits_for_promotable(possible_benefits, promotable)
40+
possible_benefits.select do |candidate|
41+
candidate.eligible_by_applicable_conditions?(promotable)
42+
end
43+
end
44+
45+
def generate_discounts(possible_benefits, item)
46+
eligible_benefits = eligible_benefits_for_promotable(possible_benefits, item)
47+
eligible_benefits.select do |benefit|
48+
benefit.can_discount?(item)
49+
end.map do |benefit|
50+
benefit.discount(item, order:, quantity:)
51+
end.compact
52+
end
53+
end
54+
end
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# frozen_string_literal: true
2+
3+
module SolidusPromotions
4+
module VariantPatch
5+
class VariantNotDiscounted < StandardError; end
6+
attr_accessor :discountable_price
7+
8+
def self.prepended(base)
9+
base.extend Spree::DisplayMoney
10+
11+
base.money_methods :discounted_price, :undiscounted_price
12+
end
13+
14+
def undiscounted_price
15+
raise VariantNotDiscounted unless discountable_price
16+
discountable_price.amount
17+
end
18+
19+
def discounted_price
20+
raise VariantNotDiscounted unless discountable_price
21+
discountable_price.discountable_amount
22+
end
23+
24+
def price_discounts
25+
raise VariantNotDiscounted unless discountable_price
26+
discountable_price.current_discounts
27+
end
28+
29+
Spree::Variant.prepend self
30+
end
31+
end
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# frozen_string_literal: true
2+
3+
require "rails_helper"
4+
5+
RSpec.describe SolidusPromotions::ProductDiscounter do
6+
subject do
7+
described_class.new(product:, order:, pricing_options:).call
8+
end
9+
10+
let(:product) { create(:product) }
11+
let(:order) { create(:order) }
12+
let(:pricing_options) do
13+
Spree::Variant::PricingOptions.new
14+
end
15+
16+
let!(:promotion) { create(:solidus_promotion, :with_adjustable_benefit, apply_automatically: true) }
17+
18+
it "applies a discount to the product's price" do
19+
expect { product.discounted_price }.to raise_exception(SolidusPromotions::VariantPatch::VariantNotDiscounted)
20+
subject
21+
# Standard benefit calculator is a flat 10 USD off
22+
expect(product.discounted_price).to eq(9.99)
23+
expect(product.price_discounts.map(&:label)).to include("Promotion (Because we like you)")
24+
end
25+
end

0 commit comments

Comments
 (0)