diff --git a/app/decorators/models/solidus_friendly_promotions/order_decorator.rb b/app/decorators/models/solidus_friendly_promotions/order_decorator.rb index f360230f..081ffdb5 100644 --- a/app/decorators/models/solidus_friendly_promotions/order_decorator.rb +++ b/app/decorators/models/solidus_friendly_promotions/order_decorator.rb @@ -30,7 +30,7 @@ def reset_current_discounts end def apply_shipping_promotions - if Spree::Config.promotion_adjuster_class <= SolidusFriendlyPromotions::OrderDiscounter + if Spree::Config.promotion_adjuster_class <= SolidusFriendlyPromotions::FriendlyPromotionAdjuster recalculate else super diff --git a/app/models/solidus_friendly_promotions/discountable_amount.rb b/app/models/concerns/solidus_friendly_promotions/discountable_amount.rb similarity index 100% rename from app/models/solidus_friendly_promotions/discountable_amount.rb rename to app/models/concerns/solidus_friendly_promotions/discountable_amount.rb diff --git a/app/models/solidus_friendly_promotions/rules/line_item_applicable_order_rule.rb b/app/models/concerns/solidus_friendly_promotions/rules/line_item_applicable_order_rule.rb similarity index 100% rename from app/models/solidus_friendly_promotions/rules/line_item_applicable_order_rule.rb rename to app/models/concerns/solidus_friendly_promotions/rules/line_item_applicable_order_rule.rb diff --git a/app/models/solidus_friendly_promotions/rules/line_item_level_rule.rb b/app/models/concerns/solidus_friendly_promotions/rules/line_item_level_rule.rb similarity index 100% rename from app/models/solidus_friendly_promotions/rules/line_item_level_rule.rb rename to app/models/concerns/solidus_friendly_promotions/rules/line_item_level_rule.rb diff --git a/app/models/solidus_friendly_promotions/rules/order_level_rule.rb b/app/models/concerns/solidus_friendly_promotions/rules/order_level_rule.rb similarity index 100% rename from app/models/solidus_friendly_promotions/rules/order_level_rule.rb rename to app/models/concerns/solidus_friendly_promotions/rules/order_level_rule.rb diff --git a/app/models/solidus_friendly_promotions/rules/shipment_level_rule.rb b/app/models/concerns/solidus_friendly_promotions/rules/shipment_level_rule.rb similarity index 100% rename from app/models/solidus_friendly_promotions/rules/shipment_level_rule.rb rename to app/models/concerns/solidus_friendly_promotions/rules/shipment_level_rule.rb diff --git a/app/models/solidus_friendly_promotions/discount_chooser.rb b/app/models/solidus_friendly_promotions/discount_chooser.rb deleted file mode 100644 index 5e478e84..00000000 --- a/app/models/solidus_friendly_promotions/discount_chooser.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -module SolidusFriendlyPromotions - class DiscountChooser - attr_reader :item - - def initialize(item) - @item = item - end - - def call(discounts) - Array.wrap( - discounts.min_by do |discount| - [discount.amount, -discount.source&.id.to_i] - end - ) - end - end -end diff --git a/app/models/solidus_friendly_promotions/friendly_promotion_adjuster.rb b/app/models/solidus_friendly_promotions/friendly_promotion_adjuster.rb new file mode 100644 index 00000000..c5d1a3c3 --- /dev/null +++ b/app/models/solidus_friendly_promotions/friendly_promotion_adjuster.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module SolidusFriendlyPromotions + class FriendlyPromotionAdjuster + attr_reader :order, :promotions, :dry_run + + def initialize(order, dry_run_promotion: nil) + @order = order + @dry_run = !!dry_run_promotion + @promotions = LoadPromotions.new(order: order, dry_run_promotion: dry_run_promotion).call + end + + def call + order.reset_current_discounts + + return order if order.shipped? + discounted_order = DiscountOrder.new(order, promotions, dry_run: dry_run).call + + PersistDiscountedOrder.new(discounted_order).call unless dry_run + + order.reset_current_discounts + order + end + end +end diff --git a/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/choose_discounts.rb b/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/choose_discounts.rb new file mode 100644 index 00000000..9121a47a --- /dev/null +++ b/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/choose_discounts.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module SolidusFriendlyPromotions + class FriendlyPromotionAdjuster + class ChooseDiscounts + attr_reader :discounts + + def initialize(discounts) + @discounts = discounts + end + + def call + Array.wrap( + discounts.min_by do |discount| + [discount.amount, -discount.source&.id.to_i] + end + ) + end + end + end +end diff --git a/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/discount_order.rb b/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/discount_order.rb new file mode 100644 index 00000000..ed58011a --- /dev/null +++ b/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/discount_order.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +module SolidusFriendlyPromotions + class FriendlyPromotionAdjuster + class DiscountOrder + attr_reader :order, :promotions, :dry_run + + def initialize(order, promotions, dry_run: false) + @order = order + @promotions = promotions + @dry_run = dry_run + end + + def call + return order if order.shipped? + + SolidusFriendlyPromotions::Promotion.ordered_lanes.each do |lane, _index| + lane_promotions = eligible_promotions_for_promotable(promotions.select { |promotion| promotion.lane == lane }, order) + line_item_discounts = adjust_line_items(lane_promotions) + shipment_discounts = adjust_shipments(lane_promotions) + shipping_rate_discounts = adjust_shipping_rates(lane_promotions) + (line_item_discounts + shipment_discounts + shipping_rate_discounts).each do |item, chosen_discounts| + item.current_discounts.concat(chosen_discounts) + end + end + + order + end + + private + + def adjust_line_items(promotions) + order.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 + [line_item, chosen_item_discounts] + end + end + + def adjust_shipments(promotions) + order.shipments.map do |shipment| + discounts = generate_discounts(promotions, shipment) + chosen_item_discounts = SolidusFriendlyPromotions.config.discount_chooser_class.new(discounts).call + [shipment, chosen_item_discounts] + end + end + + def adjust_shipping_rates(promotions) + order.shipments.flat_map(&:shipping_rates).select(&:cost).map do |rate| + discounts = generate_discounts(promotions, rate) + chosen_item_discounts = SolidusFriendlyPromotions.config.discount_chooser_class.new(discounts).call + [rate, chosen_item_discounts] + end + end + + def eligible_promotions_for_promotable(possible_promotions, promotable) + possible_promotions.select do |candidate| + candidate.eligible_by_applicable_rules?(promotable, dry_run: dry_run) + end + end + + def generate_discounts(possible_promotions, item) + eligible_promotions = eligible_promotions_for_promotable(possible_promotions, item) + eligible_promotions.flat_map do |promotion| + promotion.actions.select do |action| + action.can_discount?(item) + end.map do |action| + action.discount(item) + end.compact + end + end + end + end +end diff --git a/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/load_promotions.rb b/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/load_promotions.rb new file mode 100644 index 00000000..235e8f6b --- /dev/null +++ b/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/load_promotions.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +module SolidusFriendlyPromotions + class FriendlyPromotionAdjuster + class LoadPromotions + def initialize(order:, dry_run_promotion: nil) + @order = order + @dry_run_promotion = dry_run_promotion + end + + def call + promos = connected_order_promotions | sale_promotions + promos << dry_run_promotion if dry_run_promotion + promos.flat_map(&:actions).group_by(&:preload_relations).each do |preload_relations, actions| + preload(records: actions, associations: preload_relations) + end + promos.flat_map(&:rules).group_by(&:preload_relations).each do |preload_relations, rules| + preload(records: rules, associations: preload_relations) + end + promos.reject { |promotion| promotion.usage_limit_exceeded?(excluded_orders: [order]) } + end + + private + + attr_reader :order, :dry_run_promotion + + def preload(records:, associations:) + ActiveRecord::Associations::Preloader.new(records: records, associations: associations).call + end + + def connected_order_promotions + eligible_connected_promotion_ids = order.friendly_order_promotions.select do |order_promotion| + order_promotion.promotion_code.nil? || !order_promotion.promotion_code.usage_limit_exceeded?(excluded_orders: [order]) + end.map(&:promotion_id) + order.friendly_promotions.active(reference_time).where(id: eligible_connected_promotion_ids).includes(promotion_includes) + end + + def sale_promotions + SolidusFriendlyPromotions::Promotion.where(apply_automatically: true).active(reference_time).includes(promotion_includes) + end + + def reference_time + order.completed_at || Time.current + end + + def promotion_includes + [ + :rules, + :actions + ] + end + end + end +end diff --git a/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/persist_discounted_order.rb b/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/persist_discounted_order.rb new file mode 100644 index 00000000..5bc1e3e2 --- /dev/null +++ b/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/persist_discounted_order.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +module SolidusFriendlyPromotions + class FriendlyPromotionAdjuster + class PersistDiscountedOrder + def initialize(order) + @order = order + end + + def call + order.line_items.each do |line_item| + update_adjustments(line_item, line_item.current_discounts) + end + + order.shipments.each do |shipment| + update_adjustments(shipment, shipment.current_discounts) + end + + order.shipments.flat_map(&:shipping_rates).each do |shipping_rate| + shipping_rate.discounts = shipping_rate.current_discounts.map do |discount| + SolidusFriendlyPromotions::ShippingRateDiscount.create!( + shipping_rate: shipping_rate, + amount: discount.amount, + label: discount.label, + promotion_action: discount.source + ) + end + end + order.reset_current_discounts + order.promo_total = (order.line_items + order.shipments).sum(&:promo_total) + order + end + + private + + attr_reader :order + + # Walk through the discounts for an item and update adjustments for it. Once + # all of the discounts have been added as adjustments, remove any old tax + # adjustments that weren't touched. + # + # @private + # @param [#adjustments] item a {Spree::LineItem} or {Spree::Shipment} + # @param [Array] item_discounts a list of calculated discounts for an item + # @return [void] + def update_adjustments(item, item_discounts) + promotion_adjustments = item.adjustments.select(&:promotion?) + + active_adjustments = item_discounts.map do |item_discount| + update_adjustment(item, item_discount) + end + item.update(promo_total: active_adjustments.sum(&:amount)) + # Remove any tax adjustments tied to promotion actions which no longer match. + unmatched_adjustments = promotion_adjustments - active_adjustments + + item.adjustments.destroy(unmatched_adjustments) + end + + # Update or create a new tax adjustment on an item. + # + # @private + # @param [#adjustments] item a {Spree::LineItem} or {Spree::Shipment} + # @param [SolidusFriendlyPromotions::ItemDiscount] tax_item calculated discounts for an item + # @return [Spree::Adjustment] the created or updated tax adjustment + def update_adjustment(item, discount_item) + adjustment = item.adjustments.detect do |item_adjustment| + item_adjustment.source == discount_item.source + end + + adjustment ||= item.adjustments.new( + source: discount_item.source, + order_id: item.is_a?(Spree::Order) ? item.id : item.order_id, + label: discount_item.label, + eligible: true + ) + adjustment.update!(amount: discount_item.amount) + adjustment + end + end + end +end diff --git a/app/models/solidus_friendly_promotions/friendly_promotion_discounter.rb b/app/models/solidus_friendly_promotions/friendly_promotion_discounter.rb deleted file mode 100644 index e0618fa5..00000000 --- a/app/models/solidus_friendly_promotions/friendly_promotion_discounter.rb +++ /dev/null @@ -1,76 +0,0 @@ -# frozen_string_literal: true - -module SolidusFriendlyPromotions - class FriendlyPromotionDiscounter - attr_reader :order, :promotions, :collect_eligibility_results - - def initialize(order, promotions, collect_eligibility_results: false) - @order = order - @promotions = promotions - @collect_eligibility_results = collect_eligibility_results - end - - def call - return order if order.shipped? - - order.reset_current_discounts - - SolidusFriendlyPromotions::Promotion.ordered_lanes.each do |lane, _index| - lane_promotions = eligible_promotions_for_promotable(promotions.select { |promotion| promotion.lane == lane }, order) - line_item_discounts = adjust_line_items(lane_promotions) - shipment_discounts = adjust_shipments(lane_promotions) - shipping_rate_discounts = adjust_shipping_rates(lane_promotions) - (line_item_discounts + shipment_discounts + shipping_rate_discounts).each do |item, chosen_discounts| - item.current_discounts.concat(chosen_discounts) - end - end - - order - end - - private - - def adjust_line_items(promotions) - order.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(line_item).call(discounts) - [line_item, chosen_item_discounts] - end - end - - def adjust_shipments(promotions) - order.shipments.map do |shipment| - discounts = generate_discounts(promotions, shipment) - chosen_item_discounts = SolidusFriendlyPromotions.config.discount_chooser_class.new(shipment).call(discounts) - [shipment, chosen_item_discounts] - end - end - - def adjust_shipping_rates(promotions) - order.shipments.flat_map(&:shipping_rates).select(&:cost).map do |rate| - discounts = generate_discounts(promotions, rate) - chosen_item_discounts = SolidusFriendlyPromotions.config.discount_chooser_class.new(rate).call(discounts) - [rate, chosen_item_discounts] - end - end - - def eligible_promotions_for_promotable(possible_promotions, promotable) - possible_promotions.select do |candidate| - candidate.eligible_by_applicable_rules?(promotable, collect_eligibility_results: collect_eligibility_results) - end - end - - def generate_discounts(possible_promotions, item) - eligible_promotions = eligible_promotions_for_promotable(possible_promotions, item) - eligible_promotions.flat_map do |promotion| - promotion.actions.select do |action| - action.can_discount?(item) - end.map do |action| - action.discount(item) - end.compact - end - end - end -end diff --git a/app/models/solidus_friendly_promotions/order_discounter.rb b/app/models/solidus_friendly_promotions/order_discounter.rb deleted file mode 100644 index e6aece34..00000000 --- a/app/models/solidus_friendly_promotions/order_discounter.rb +++ /dev/null @@ -1,84 +0,0 @@ -# frozen_string_literal: true - -module SolidusFriendlyPromotions - class OrderDiscounter - attr_reader :promotions - - def initialize(order) - @order = order - @promotions = PromotionLoader.new(order: order).call - end - - def call - discountable_order = FriendlyPromotionDiscounter.new(order, promotions).call - - discountable_order.line_items.each do |line_item| - update_adjustments(line_item, line_item.current_discounts) - end - - discountable_order.shipments.each do |shipment| - update_adjustments(shipment, shipment.current_discounts) - end - - discountable_order.shipments.flat_map(&:shipping_rates).each do |shipping_rate| - shipping_rate.discounts = shipping_rate.current_discounts.map do |discount| - SolidusFriendlyPromotions::ShippingRateDiscount.create!( - shipping_rate: shipping_rate, - amount: discount.amount, - label: discount.label, - promotion_action: discount.source - ) - end - end - order.reset_current_discounts - order.promo_total = (order.line_items + order.shipments).sum(&:promo_total) - order - end - - private - - attr_reader :order - - # Walk through the discounts for an item and update adjustments for it. Once - # all of the discounts have been added as adjustments, remove any old tax - # adjustments that weren't touched. - # - # @private - # @param [#adjustments] item a {Spree::LineItem} or {Spree::Shipment} - # @param [Array] item_discounts a list of calculated discounts for an item - # @return [void] - def update_adjustments(item, item_discounts) - promotion_adjustments = item.adjustments.select(&:promotion?) - - active_adjustments = item_discounts.map do |item_discount| - update_adjustment(item, item_discount) - end - item.update(promo_total: active_adjustments.sum(&:amount)) - # Remove any tax adjustments tied to promotion actions which no longer match. - unmatched_adjustments = promotion_adjustments - active_adjustments - - item.adjustments.destroy(unmatched_adjustments) - end - - # Update or create a new tax adjustment on an item. - # - # @private - # @param [#adjustments] item a {Spree::LineItem} or {Spree::Shipment} - # @param [SolidusFriendlyPromotions::ItemDiscount] tax_item calculated discounts for an item - # @return [Spree::Adjustment] the created or updated tax adjustment - def update_adjustment(item, discount_item) - adjustment = item.adjustments.detect do |item_adjustment| - item_adjustment.source == discount_item.source - end - - adjustment ||= item.adjustments.new( - source: discount_item.source, - order_id: item.is_a?(Spree::Order) ? item.id : item.order_id, - label: discount_item.label, - eligible: true - ) - adjustment.update!(amount: discount_item.amount) - adjustment - end - end -end diff --git a/app/models/solidus_friendly_promotions/promotion.rb b/app/models/solidus_friendly_promotions/promotion.rb index 7598c518..bf92f473 100644 --- a/app/models/solidus_friendly_promotions/promotion.rb +++ b/app/models/solidus_friendly_promotions/promotion.rb @@ -127,7 +127,7 @@ def eligibility_results @eligibility_results ||= SolidusFriendlyPromotions::EligibilityResults.new(self) end - def eligible_by_applicable_rules?(promotable, collect_eligibility_results: false) + def eligible_by_applicable_rules?(promotable, dry_run: false) applicable_rules = rules.select do |rule| rule.applicable?(promotable) end @@ -135,9 +135,9 @@ def eligible_by_applicable_rules?(promotable, collect_eligibility_results: false applicable_rules.map do |applicable_rule| eligible = applicable_rule.eligible?(promotable) - break [false] if !eligible && !collect_eligibility_results + break [false] if !eligible && !dry_run - if collect_eligibility_results + if dry_run if applicable_rule.eligibility_errors.details[:base].first code = applicable_rule.eligibility_errors.details[:base].first[:error_code] message = applicable_rule.eligibility_errors.full_messages.first diff --git a/app/models/solidus_friendly_promotions/promotion_handler/coupon.rb b/app/models/solidus_friendly_promotions/promotion_handler/coupon.rb index 121b2eea..99a01a97 100644 --- a/app/models/solidus_friendly_promotions/promotion_handler/coupon.rb +++ b/app/models/solidus_friendly_promotions/promotion_handler/coupon.rb @@ -74,9 +74,8 @@ def handle_present_promotion return promotion_applied if promotion_exists_on_order?(order, promotion) # Try applying this promotion, with no effects - active_promotions = SolidusFriendlyPromotions::PromotionLoader.new(order: order).call - discounter = SolidusFriendlyPromotions::FriendlyPromotionDiscounter.new(order, active_promotions + [promotion], collect_eligibility_results: true) - discounter.call + Spree::Config.promotion_adjuster_class.new(order, dry_run_promotion: promotion).call + if promotion.eligibility_results.success? order.friendly_order_promotions.create!( promotion: promotion, diff --git a/app/models/solidus_friendly_promotions/promotion_handler/page.rb b/app/models/solidus_friendly_promotions/promotion_handler/page.rb index 2be3681f..d0cc352e 100644 --- a/app/models/solidus_friendly_promotions/promotion_handler/page.rb +++ b/app/models/solidus_friendly_promotions/promotion_handler/page.rb @@ -12,12 +12,7 @@ def initialize(order, path) def activate if promotion - active_promotions = SolidusFriendlyPromotions::PromotionLoader.new(order: order).call - SolidusFriendlyPromotions::FriendlyPromotionDiscounter.new( - order, - active_promotions + [promotion], - collect_eligibility_results: true - ).call + Spree::Config.promotion_adjuster_class.new(order, dry_run_promotion: promotion).call if promotion.eligibility_results.success? order.friendly_promotions << promotion order.recalculate diff --git a/app/models/solidus_friendly_promotions/promotion_loader.rb b/app/models/solidus_friendly_promotions/promotion_loader.rb deleted file mode 100644 index 6e767f04..00000000 --- a/app/models/solidus_friendly_promotions/promotion_loader.rb +++ /dev/null @@ -1,50 +0,0 @@ -# frozen_string_literal: true - -module SolidusFriendlyPromotions - class PromotionLoader - def initialize(order:) - @order = order - end - - def call - promos = connected_order_promotions | sale_promotions - promos.flat_map(&:actions).group_by(&:preload_relations).each do |preload_relations, actions| - preload(records: actions, associations: preload_relations) - end - promos.flat_map(&:rules).group_by(&:preload_relations).each do |preload_relations, rules| - preload(records: rules, associations: preload_relations) - end - promos.reject { |promotion| promotion.usage_limit_exceeded?(excluded_orders: [order]) } - end - - private - - attr_reader :order - - def preload(records:, associations:) - ActiveRecord::Associations::Preloader.new(records: records, associations: associations).call - end - - def connected_order_promotions - eligible_connected_promotion_ids = order.friendly_order_promotions.select do |order_promotion| - order_promotion.promotion_code.nil? || !order_promotion.promotion_code.usage_limit_exceeded?(excluded_orders: [order]) - end.map(&:promotion_id) - order.friendly_promotions.active(reference_time).where(id: eligible_connected_promotion_ids).includes(promotion_includes) - end - - def sale_promotions - SolidusFriendlyPromotions::Promotion.where(apply_automatically: true).active(reference_time).includes(promotion_includes) - end - - def reference_time - order.completed_at || Time.current - end - - def promotion_includes - [ - :rules, - :actions - ] - end - end -end diff --git a/lib/generators/solidus_friendly_promotions/install/templates/initializer.rb b/lib/generators/solidus_friendly_promotions/install/templates/initializer.rb index 84b60be6..0632d153 100644 --- a/lib/generators/solidus_friendly_promotions/install/templates/initializer.rb +++ b/lib/generators/solidus_friendly_promotions/install/templates/initializer.rb @@ -2,7 +2,7 @@ # Replace solidus core's order contents and promotion adjuster classes with ours. Spree::Config.order_contents_class = "SolidusFriendlyPromotions::SimpleOrderContents" -Spree::Config.promotion_adjuster_class = "SolidusFriendlyPromotions::OrderDiscounter" +Spree::Config.promotion_adjuster_class = "SolidusFriendlyPromotions::FriendlyPromotionAdjuster" # Replace the promotions menu from core with ours Spree::Backend::Config.configure do |config| @@ -58,7 +58,7 @@ SolidusFriendlyPromotions.configure do |config| # This class chooses which promotion should apply to a line item in case # that more than one promotion is eligible. - config.discount_chooser_class = "SolidusFriendlyPromotions::DiscountChooser" + config.discount_chooser_class = "SolidusFriendlyPromotions::FriendlyPromotionAdjuster::ChooseDiscounts" # How many promotions should be displayed on the index page in the admin. config.promotions_per_page = 25 diff --git a/spec/lib/solidus_friendly_promotions/configuration_spec.rb b/spec/lib/solidus_friendly_promotions/configuration_spec.rb index 136f18f1..83a0d105 100644 --- a/spec/lib/solidus_friendly_promotions/configuration_spec.rb +++ b/spec/lib/solidus_friendly_promotions/configuration_spec.rb @@ -15,7 +15,7 @@ describe ".promotion_chooser_class" do it "is the promotion chooser" do - expect(subject.discount_chooser_class).to eq(SolidusFriendlyPromotions::DiscountChooser) + expect(subject.discount_chooser_class).to eq(SolidusFriendlyPromotions::FriendlyPromotionAdjuster::ChooseDiscounts) end end diff --git a/spec/models/solidus_friendly_promotions/friendly_promotion_adjuster/choose_discounts_spec.rb b/spec/models/solidus_friendly_promotions/friendly_promotion_adjuster/choose_discounts_spec.rb new file mode 100644 index 00000000..b8357c05 --- /dev/null +++ b/spec/models/solidus_friendly_promotions/friendly_promotion_adjuster/choose_discounts_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe SolidusFriendlyPromotions::FriendlyPromotionAdjuster::ChooseDiscounts do + subject { described_class.new(discounts).call } + + let(:source_1) { create(:friendly_promotion, :with_adjustable_action).actions.first } + let(:source_2) { create(:friendly_promotion, :with_adjustable_action).actions.first } + let(:good_discount) { SolidusFriendlyPromotions::ItemDiscount.new(amount: -2, source: source_1) } + let(:bad_discount) { SolidusFriendlyPromotions::ItemDiscount.new(amount: -1, source: source_2) } + + let(:discounts) do + [ + good_discount, + bad_discount + ] + end + + it { is_expected.to contain_exactly(good_discount) } +end diff --git a/spec/models/solidus_friendly_promotions/friendly_promotion_discounter_spec.rb b/spec/models/solidus_friendly_promotions/friendly_promotion_adjuster/discount_order_spec.rb similarity index 97% rename from spec/models/solidus_friendly_promotions/friendly_promotion_discounter_spec.rb rename to spec/models/solidus_friendly_promotions/friendly_promotion_adjuster/discount_order_spec.rb index 276acb0d..06058a2c 100644 --- a/spec/models/solidus_friendly_promotions/friendly_promotion_discounter_spec.rb +++ b/spec/models/solidus_friendly_promotions/friendly_promotion_adjuster/discount_order_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" -RSpec.describe SolidusFriendlyPromotions::FriendlyPromotionDiscounter do +RSpec.describe SolidusFriendlyPromotions::FriendlyPromotionAdjuster::DiscountOrder do context "shipped orders" do let(:promotions) { [] } let(:order) { create(:order, shipment_state: "shipped") } @@ -33,14 +33,14 @@ end end - describe "collecting eligibility results" do + describe "collecting eligibility results in a dry run" do let(:shirt) { create(:product, name: "Shirt") } let(:order) { create(:order_with_line_items, line_items_attributes: [{variant: shirt.master, quantity: 1}]) } let(:rules) { [product_rule] } let!(:promotion) { create(:friendly_promotion, :with_adjustable_action, rules: rules, name: "20% off Shirts", apply_automatically: true) } let(:product_rule) { SolidusFriendlyPromotions::Rules::Product.new(products: [shirt], preferred_line_item_applicable: false) } let(:promotions) { [promotion] } - let(:discounter) { described_class.new(order, promotions, collect_eligibility_results: true) } + let(:discounter) { described_class.new(order, promotions, dry_run: true) } subject { discounter.call } diff --git a/spec/models/solidus_friendly_promotions/promotion_loader_spec.rb b/spec/models/solidus_friendly_promotions/friendly_promotion_adjuster/load_promotions_spec.rb similarity index 96% rename from spec/models/solidus_friendly_promotions/promotion_loader_spec.rb rename to spec/models/solidus_friendly_promotions/friendly_promotion_adjuster/load_promotions_spec.rb index 0b0ca6eb..be873cc2 100644 --- a/spec/models/solidus_friendly_promotions/promotion_loader_spec.rb +++ b/spec/models/solidus_friendly_promotions/friendly_promotion_adjuster/load_promotions_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" -RSpec.describe SolidusFriendlyPromotions::PromotionLoader do +RSpec.describe SolidusFriendlyPromotions::FriendlyPromotionAdjuster::LoadPromotions do describe "selecting promotions" do subject { described_class.new(order: order).call } diff --git a/spec/models/solidus_friendly_promotions/order_discounter_spec.rb b/spec/models/solidus_friendly_promotions/friendly_promotion_adjuster_spec.rb similarity index 98% rename from spec/models/solidus_friendly_promotions/order_discounter_spec.rb rename to spec/models/solidus_friendly_promotions/friendly_promotion_adjuster_spec.rb index 184c240e..d17b44e4 100644 --- a/spec/models/solidus_friendly_promotions/order_discounter_spec.rb +++ b/spec/models/solidus_friendly_promotions/friendly_promotion_adjuster_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" -RSpec.describe SolidusFriendlyPromotions::OrderDiscounter, type: :model do +RSpec.describe SolidusFriendlyPromotions::FriendlyPromotionAdjuster, type: :model do subject(:discounter) { described_class.new(order) } let(:line_item) { create(:line_item) } diff --git a/spec/models/spree/order_spec.rb b/spec/models/spree/order_spec.rb index d880ca56..7110912a 100644 --- a/spec/models/spree/order_spec.rb +++ b/spec/models/spree/order_spec.rb @@ -47,7 +47,7 @@ around do |example| Spree::Config.promotion_adjuster_class = Spree::Promotion::OrderAdjustmentsRecalculator example.run - Spree::Config.promotion_adjuster_class = SolidusFriendlyPromotions::OrderDiscounter + Spree::Config.promotion_adjuster_class = SolidusFriendlyPromotions::FriendlyPromotionAdjuster end it "does call the promotion handler shipping" do