solidus_friendly_promotions 1.0.0.pre → 1.0.0.rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/MIGRATING.md +1 -1
- data/app/controllers/solidus_friendly_promotions/admin/promotions_controller.rb +1 -1
- data/app/decorators/models/solidus_friendly_promotions/line_item_decorator.rb +20 -0
- data/app/decorators/models/solidus_friendly_promotions/order_decorator.rb +11 -0
- data/app/javascript/solidus_friendly_promotions.js +5 -2
- data/app/models/concerns/solidus_friendly_promotions/actions/order_level_action.rb +15 -0
- data/app/models/concerns/solidus_friendly_promotions/calculators/promotion_calculator.rb +11 -0
- data/app/models/solidus_friendly_promotions/actions/adjust_line_item_quantity_groups.rb +1 -9
- data/app/models/solidus_friendly_promotions/actions/create_discounted_item.rb +50 -0
- data/app/models/solidus_friendly_promotions/calculators/distributed_amount.rb +3 -9
- data/app/models/solidus_friendly_promotions/calculators/flat_rate.rb +2 -0
- data/app/models/solidus_friendly_promotions/calculators/flexi_rate.rb +2 -0
- data/app/models/solidus_friendly_promotions/calculators/percent.rb +2 -0
- data/app/models/solidus_friendly_promotions/calculators/tiered_flat_rate.rb +2 -0
- data/app/models/solidus_friendly_promotions/calculators/tiered_percent.rb +2 -0
- data/app/models/solidus_friendly_promotions/calculators/tiered_percent_on_eligible_item_quantity.rb +36 -0
- data/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/discount_order.rb +19 -1
- data/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/persist_discounted_order.rb +0 -1
- data/app/models/solidus_friendly_promotions/friendly_promotion_adjuster.rb +7 -0
- data/app/models/solidus_friendly_promotions/promotion.rb +7 -1
- data/app/models/solidus_friendly_promotions/promotion_handler/null.rb +20 -0
- data/app/models/solidus_friendly_promotions/promotion_rule.rb +1 -1
- data/app/models/solidus_friendly_promotions/rules/minimum_quantity.rb +1 -7
- data/app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_calculator_fields.erb +1 -0
- data/app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_create_discounted_item.html.erb +19 -0
- data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_flat_rate/_fields.html.erb +1 -1
- data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_percent/_fields.html.erb +1 -1
- data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_percent_on_eligible_item_quantity/_fields.html.erb +34 -0
- data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_percent_on_eligible_item_quantity/_tier_fields.html.erb +27 -0
- data/app/views/solidus_friendly_promotions/admin/promotions/_table.html.erb +56 -0
- data/app/views/solidus_friendly_promotions/admin/promotions/_table_filter.html.erb +69 -0
- data/app/views/solidus_friendly_promotions/admin/promotions/edit.html.erb +13 -11
- data/app/views/solidus_friendly_promotions/admin/promotions/index.html.erb +2 -103
- data/config/locales/en.yml +28 -1
- data/db/migrate/20231104135812_add_managed_by_order_action_to_line_items.rb +5 -0
- data/lib/generators/solidus_friendly_promotions/install/templates/initializer.rb +18 -5
- data/lib/solidus_friendly_promotions/version.rb +1 -1
- data/lib/solidus_friendly_promotions.rb +1 -0
- data/solidus_friendly_promotions.gemspec +1 -0
- metadata +27 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84ea9571f3d2a4a2dfe9e789c0f3887a0aca2d9559a68004806cd67c395fc959
|
4
|
+
data.tar.gz: 929a14c4f917aad08c6bf7faa7f93c7be071dc43ad72641ddf0394cf336022db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e49887ad42376b60165ab1d5a8067942adde8d9861681e165b0617155eb74f42a5ea97f2bd94ce929ee5627156ab249ab392b5259e775ecdb53414444bb94be
|
7
|
+
data.tar.gz: cc68b4daf7520de18dbe22bd0b74a73e1a4b009d031d8703b86f7e6d5ad11cfd5999159b48cdb0bfc7801235fe8587bc5c7cfe56a76fb18eee3fef7b48c903a4
|
data/MIGRATING.md
CHANGED
@@ -32,7 +32,7 @@ module SolidusFriendlyPromotions
|
|
32
32
|
return @collection if @collection
|
33
33
|
|
34
34
|
params[:q] ||= HashWithIndifferentAccess.new
|
35
|
-
params[:q][:s] ||= "
|
35
|
+
params[:q][:s] ||= "updated_at desc"
|
36
36
|
|
37
37
|
@collection = super
|
38
38
|
@search = @collection.ransack(params[:q])
|
@@ -2,6 +2,26 @@
|
|
2
2
|
|
3
3
|
module SolidusFriendlyPromotions
|
4
4
|
module LineItemDecorator
|
5
|
+
def self.prepended(base)
|
6
|
+
base.attr_accessor :quantity_setter
|
7
|
+
base.belongs_to :managed_by_order_action, class_name: "SolidusFriendlyPromotions::PromotionAction", optional: true
|
8
|
+
base.validate :validate_managed_quantity_same, on: :update
|
9
|
+
base.after_save :reset_quantity_setter
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def validate_managed_quantity_same
|
15
|
+
if managed_by_order_action && quantity_changed? && quantity_setter != managed_by_order_action
|
16
|
+
errors.add(:quantity, :cannot_be_changed_for_automated_items)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def reset_quantity_setter
|
21
|
+
@quantity_setter = nil
|
22
|
+
end
|
23
|
+
|
24
|
+
Spree::LineItem.prepend self
|
5
25
|
Spree::LineItem.prepend SolidusFriendlyPromotions::DiscountableAmount
|
6
26
|
end
|
7
27
|
end
|
@@ -29,6 +29,13 @@ module SolidusFriendlyPromotions
|
|
29
29
|
shipments.each(&:reset_current_discounts)
|
30
30
|
end
|
31
31
|
|
32
|
+
# This helper method excludes line items that are managed by an order action for the benefit
|
33
|
+
# of calculators and actions that discount normal line items. Line items that are managed by an
|
34
|
+
# order actions handle their discounts themselves.
|
35
|
+
def discountable_line_items
|
36
|
+
line_items.reject(&:managed_by_order_action)
|
37
|
+
end
|
38
|
+
|
32
39
|
def apply_shipping_promotions
|
33
40
|
if Spree::Config.promotion_adjuster_class <= SolidusFriendlyPromotions::FriendlyPromotionAdjuster
|
34
41
|
recalculate
|
@@ -37,6 +44,10 @@ module SolidusFriendlyPromotions
|
|
37
44
|
end
|
38
45
|
end
|
39
46
|
|
47
|
+
def free_from_order_action?(line_item, _options)
|
48
|
+
!line_item.managed_by_order_action
|
49
|
+
end
|
50
|
+
|
40
51
|
Spree::Order.prepend self
|
41
52
|
end
|
42
53
|
end
|
@@ -4,9 +4,12 @@ import "solidus_friendly_promotions/jquery/option_value_picker"
|
|
4
4
|
|
5
5
|
Turbo.session.drive = false;
|
6
6
|
|
7
|
-
|
7
|
+
const initPickers = ({ _target }) => {
|
8
8
|
Spree.initNumberWithCurrency();
|
9
9
|
$(".product_picker").productAutocomplete();
|
10
10
|
$(".user_picker").userAutocomplete();
|
11
11
|
$(".taxon_picker").taxonAutocomplete();
|
12
|
-
|
12
|
+
$(".variant_autocomplete").variantAutocomplete();
|
13
|
+
};
|
14
|
+
document.addEventListener("turbo:frame-load", initPickers);
|
15
|
+
document.addEventListener("DOMContentLoaded", initPickers);
|
@@ -58,7 +58,7 @@ module SolidusFriendlyPromotions
|
|
58
58
|
adjustment_amount = adjustment_amount.abs
|
59
59
|
|
60
60
|
order = line_item.order
|
61
|
-
line_items =
|
61
|
+
line_items = promotion.applicable_line_items(order)
|
62
62
|
|
63
63
|
item_units = line_items.sort_by do |line_item|
|
64
64
|
[-line_item.quantity, line_item.id]
|
@@ -78,14 +78,6 @@ module SolidusFriendlyPromotions
|
|
78
78
|
|
79
79
|
private
|
80
80
|
|
81
|
-
def actionable_line_items(order)
|
82
|
-
order.line_items.select do |item|
|
83
|
-
promotion.rules.select do |rule|
|
84
|
-
rule.applicable?(item)
|
85
|
-
end.all? { |rule| rule.eligible?(item) }
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
81
|
##
|
90
82
|
# Used specifically for PercentOnLineItem calculator. That calculator uses
|
91
83
|
# `line_item.amount`, however we might not necessarily want to discount the
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidusFriendlyPromotions
|
4
|
+
module Actions
|
5
|
+
class CreateDiscountedItem < PromotionAction
|
6
|
+
include OrderLevelAction
|
7
|
+
preference :variant_id, :integer
|
8
|
+
preference :quantity, :integer, default: 1
|
9
|
+
preference :necessary_quantity, :integer, default: 1
|
10
|
+
|
11
|
+
def perform(order)
|
12
|
+
line_item = find_item(order) || create_item(order)
|
13
|
+
set_quantity(line_item, determine_item_quantity(order))
|
14
|
+
line_item.current_discounts << discount(line_item)
|
15
|
+
end
|
16
|
+
|
17
|
+
def remove_from(order)
|
18
|
+
line_item = find_item(order)
|
19
|
+
order.line_items.destroy(line_item)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def find_item(order)
|
25
|
+
order.line_items.detect { |line_item| line_item.managed_by_order_action == self }
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_item(order)
|
29
|
+
order.line_items.create!(quantity: determine_item_quantity(order), variant: variant, managed_by_order_action: self)
|
30
|
+
end
|
31
|
+
|
32
|
+
def determine_item_quantity(order)
|
33
|
+
applicable_line_items = promotion.applicable_line_items(order)
|
34
|
+
# Integer division will floor automatically, which is what we want here:
|
35
|
+
# 1 Item, 2 needed: 1 * 1 / 2 => 0
|
36
|
+
# 5 items, 2 preferred, 2 needed: 5 / 2 * 2 => 4
|
37
|
+
applicable_line_items.sum(&:quantity) / preferred_necessary_quantity * preferred_quantity
|
38
|
+
end
|
39
|
+
|
40
|
+
def set_quantity(line_item, quantity)
|
41
|
+
line_item.quantity_setter = self
|
42
|
+
line_item.quantity = quantity
|
43
|
+
end
|
44
|
+
|
45
|
+
def variant
|
46
|
+
Spree::Variant.find(preferred_variant_id)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -9,6 +9,8 @@ require_dependency "spree/calculator"
|
|
9
9
|
module SolidusFriendlyPromotions
|
10
10
|
module Calculators
|
11
11
|
class DistributedAmount < Spree::Calculator
|
12
|
+
include PromotionCalculator
|
13
|
+
|
12
14
|
preference :amount, :decimal, default: 0
|
13
15
|
preference :currency, :string, default: -> { Spree::Config[:currency] }
|
14
16
|
|
@@ -16,7 +18,7 @@ module SolidusFriendlyPromotions
|
|
16
18
|
return 0 unless line_item
|
17
19
|
return 0 unless preferred_currency.casecmp(line_item.currency).zero?
|
18
20
|
|
19
|
-
distributable_line_items =
|
21
|
+
distributable_line_items = calculable.promotion.applicable_line_items(line_item.order)
|
20
22
|
return 0 unless line_item.in?(distributable_line_items)
|
21
23
|
|
22
24
|
DistributedAmountsHandler.new(
|
@@ -24,14 +26,6 @@ module SolidusFriendlyPromotions
|
|
24
26
|
preferred_amount
|
25
27
|
).amount(line_item)
|
26
28
|
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def eligible_line_items(order)
|
31
|
-
order.line_items.select do |line_item|
|
32
|
-
calculable.promotion.eligible_by_applicable_rules?(line_item)
|
33
|
-
end
|
34
|
-
end
|
35
29
|
end
|
36
30
|
end
|
37
31
|
end
|
@@ -5,6 +5,8 @@ require_dependency "spree/calculator"
|
|
5
5
|
module SolidusFriendlyPromotions
|
6
6
|
module Calculators
|
7
7
|
class FlatRate < Spree::Calculator
|
8
|
+
include PromotionCalculator
|
9
|
+
|
8
10
|
preference :amount, :decimal, default: 0
|
9
11
|
preference :currency, :string, default: -> { Spree::Config[:currency] }
|
10
12
|
|
@@ -5,6 +5,8 @@ require_dependency "spree/calculator"
|
|
5
5
|
module SolidusFriendlyPromotions
|
6
6
|
module Calculators
|
7
7
|
class FlexiRate < Spree::Calculator
|
8
|
+
include PromotionCalculator
|
9
|
+
|
8
10
|
preference :first_item, :decimal, default: 0
|
9
11
|
preference :additional_item, :decimal, default: 0
|
10
12
|
preference :max_items, :integer, default: 0
|
@@ -5,6 +5,8 @@ require_dependency "spree/calculator"
|
|
5
5
|
module SolidusFriendlyPromotions
|
6
6
|
module Calculators
|
7
7
|
class TieredFlatRate < Spree::Calculator
|
8
|
+
include PromotionCalculator
|
9
|
+
|
8
10
|
preference :base_amount, :decimal, default: 0
|
9
11
|
preference :tiers, :hash, default: {}
|
10
12
|
preference :currency, :string, default: -> { Spree::Config[:currency] }
|
@@ -5,6 +5,8 @@ require_dependency "spree/calculator"
|
|
5
5
|
module SolidusFriendlyPromotions
|
6
6
|
module Calculators
|
7
7
|
class TieredPercent < Spree::Calculator
|
8
|
+
include PromotionCalculator
|
9
|
+
|
8
10
|
preference :base_percent, :decimal, default: 0
|
9
11
|
preference :tiers, :hash, default: {}
|
10
12
|
preference :currency, :string, default: -> { Spree::Config[:currency] }
|
data/app/models/solidus_friendly_promotions/calculators/tiered_percent_on_eligible_item_quantity.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require_dependency "spree/calculator"
|
2
|
+
|
3
|
+
module SolidusFriendlyPromotions
|
4
|
+
module Calculators
|
5
|
+
class TieredPercentOnEligibleItemQuantity < SolidusFriendlyPromotions::Calculators::TieredPercent
|
6
|
+
before_validation do
|
7
|
+
# Convert tier values to decimals. Strings don't do us much good.
|
8
|
+
if preferred_tiers.is_a?(Hash)
|
9
|
+
self.preferred_tiers = preferred_tiers.map do |key, value|
|
10
|
+
[cast_to_d(key.to_i), cast_to_d(value.to_s)]
|
11
|
+
end.to_h
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def compute_line_item(line_item)
|
16
|
+
order = line_item.order
|
17
|
+
|
18
|
+
_base, percent = preferred_tiers.sort.reverse.detect do |value, _|
|
19
|
+
eligible_line_items_quantity_total(order) >= value
|
20
|
+
end
|
21
|
+
if preferred_currency.casecmp(order.currency).zero?
|
22
|
+
currency_exponent = ::Money::Currency.find(preferred_currency).exponent
|
23
|
+
(line_item.discountable_amount * (percent || preferred_base_percent) / 100).round(currency_exponent)
|
24
|
+
else
|
25
|
+
0
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def eligible_line_items_quantity_total(order)
|
32
|
+
calculable.promotion.applicable_line_items(order).sum(&:quantity)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -16,6 +16,7 @@ module SolidusFriendlyPromotions
|
|
16
16
|
|
17
17
|
SolidusFriendlyPromotions::Promotion.ordered_lanes.each do |lane, _index|
|
18
18
|
lane_promotions = eligible_promotions_for_promotable(promotions.select { |promotion| promotion.lane == lane }, order)
|
19
|
+
perform_order_actions(lane_promotions, lane) unless dry_run
|
19
20
|
line_item_discounts = adjust_line_items(lane_promotions)
|
20
21
|
shipment_discounts = adjust_shipments(lane_promotions)
|
21
22
|
shipping_rate_discounts = adjust_shipping_rates(lane_promotions)
|
@@ -29,8 +30,25 @@ module SolidusFriendlyPromotions
|
|
29
30
|
|
30
31
|
private
|
31
32
|
|
33
|
+
def perform_order_actions(lane_promotions, lane)
|
34
|
+
lane_promotions.each do |promotion|
|
35
|
+
promotion.actions.select { |action| action.level == :order }.each { |action| action.perform(order) }
|
36
|
+
end
|
37
|
+
|
38
|
+
automated_line_items = order.line_items.select(&:managed_by_order_action)
|
39
|
+
return if automated_line_items.empty?
|
40
|
+
|
41
|
+
ineligible_line_items = automated_line_items.select do |line_item|
|
42
|
+
line_item.managed_by_order_action.promotion.lane == lane && !line_item.managed_by_order_action.in?(lane_promotions.flat_map(&:actions))
|
43
|
+
end
|
44
|
+
|
45
|
+
ineligible_line_items.each do |line_item|
|
46
|
+
line_item.managed_by_order_action.remove_from(order)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
32
50
|
def adjust_line_items(promotions)
|
33
|
-
order.
|
51
|
+
order.discountable_line_items.select do |line_item|
|
34
52
|
line_item.variant.product.promotionable?
|
35
53
|
end.map do |line_item|
|
36
54
|
discounts = generate_discounts(promotions, line_item)
|
@@ -19,6 +19,13 @@ module SolidusFriendlyPromotions
|
|
19
19
|
PersistDiscountedOrder.new(discounted_order).call unless dry_run
|
20
20
|
|
21
21
|
order.reset_current_discounts
|
22
|
+
|
23
|
+
unless dry_run
|
24
|
+
# Since automations might have added a line item, we need to recalculate item total and item count here.
|
25
|
+
order.item_total = order.line_items.sum(&:amount)
|
26
|
+
order.item_count = order.line_items.sum(&:quantity)
|
27
|
+
order.promo_total = (order.line_items + order.shipments).sum(&:promo_total)
|
28
|
+
end
|
22
29
|
order
|
23
30
|
end
|
24
31
|
end
|
@@ -48,7 +48,7 @@ module SolidusFriendlyPromotions
|
|
48
48
|
end
|
49
49
|
|
50
50
|
self.allowed_ransackable_associations = ["codes"]
|
51
|
-
self.allowed_ransackable_attributes = %w[name path promotion_category_id]
|
51
|
+
self.allowed_ransackable_attributes = %w[name customer_label path promotion_category_id lane updated_at]
|
52
52
|
self.allowed_ransackable_scopes = %i[active]
|
53
53
|
|
54
54
|
# All orders that have been discounted using this promotion
|
@@ -155,6 +155,12 @@ module SolidusFriendlyPromotions
|
|
155
155
|
end.all?
|
156
156
|
end
|
157
157
|
|
158
|
+
def applicable_line_items(order)
|
159
|
+
order.discountable_line_items.select do |line_item|
|
160
|
+
eligible_by_applicable_rules?(line_item)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
158
164
|
private
|
159
165
|
|
160
166
|
def apply_automatically_disallowed_with_paths
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidusFriendlyPromotions
|
4
|
+
module PromotionHandler
|
5
|
+
# We handle shipping promotions just like other promotions, so we don't need a
|
6
|
+
# special promotion handler for shipping. However, Solidus wants us to implement one.
|
7
|
+
# This is what this class is for.
|
8
|
+
class Null
|
9
|
+
attr_reader :order
|
10
|
+
attr_accessor :error, :success
|
11
|
+
|
12
|
+
def initialize(order)
|
13
|
+
@order = order
|
14
|
+
end
|
15
|
+
|
16
|
+
def activate
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -49,7 +49,7 @@ module SolidusFriendlyPromotions
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def eligibility_error_message(key, options = {})
|
52
|
-
I18n.t(key,
|
52
|
+
I18n.t(key, scope: [:solidus_friendly_promotions, :eligibility_errors, self.class.name.underscore], **options)
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
@@ -27,13 +27,7 @@ module SolidusFriendlyPromotions
|
|
27
27
|
# @param order [Spree::Order] the order we want to check eligibility on
|
28
28
|
# @return [Boolean] true if promotion is eligible, false otherwise
|
29
29
|
def eligible?(order)
|
30
|
-
applicable_line_items
|
31
|
-
promotion.rules.select do |rule|
|
32
|
-
rule.applicable?(line_item)
|
33
|
-
end.all? { _1.eligible?(line_item) }
|
34
|
-
end
|
35
|
-
|
36
|
-
if applicable_line_items.sum(&:quantity) < preferred_minimum_quantity
|
30
|
+
if promotion.applicable_line_items(order).sum(&:quantity) < preferred_minimum_quantity
|
37
31
|
eligibility_errors.add(
|
38
32
|
:base,
|
39
33
|
eligibility_error_message(:quantity_less_than_minimum, count: preferred_minimum_quantity),
|
data/app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_calculator_fields.erb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
|
2
2
|
<% calculator = promotion_action.calculator %>
|
3
3
|
<% type_name = calculator.type.demodulize.underscore %>
|
4
|
+
<%= calculator.description %>
|
4
5
|
<% if lookup_context.exists?("fields", ["solidus_friendly_promotions/admin/promotion_actions/calculators/#{type_name}"], true) %>
|
5
6
|
<%= render "solidus_friendly_promotions/admin/promotion_actions/calculators/#{type_name}/fields", calculator: calculator, prefix: param_prefix, form: form %>
|
6
7
|
<% else %>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<%= fields_for param_prefix, promotion_action do |form| %>
|
2
|
+
<div class="field">
|
3
|
+
<%= form.label :preferred_variant_id %>
|
4
|
+
<%= form.text_field :preferred_variant_id, class: "variant_autocomplete fullwidth" %>
|
5
|
+
<%= form.label :preferred_quantity %>
|
6
|
+
<%= form.number_field :preferred_quantity, class: "fullwidth" %>
|
7
|
+
</div>
|
8
|
+
<div class="field">
|
9
|
+
<%= form.label :preferred_necessary_quantity %>
|
10
|
+
<%= form.number_field :preferred_necessary_quantity, class: "fullwidth" %>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<%= render(
|
15
|
+
"solidus_friendly_promotions/admin/promotion_actions/actions/calculator_fields",
|
16
|
+
promotion_action: promotion_action,
|
17
|
+
param_prefix: param_prefix,
|
18
|
+
form: form
|
19
|
+
) %>
|
@@ -28,7 +28,7 @@
|
|
28
28
|
<%= render "solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_flat_rate/tier_fields", tier: tier, form: form %>
|
29
29
|
<% end %>
|
30
30
|
<div class="mb-3" data-calculator-tiers-target="links">
|
31
|
-
<%= link_to
|
31
|
+
<%= link_to t(:add_tier, scope: [:solidus_friendly_promotions, :admin, :promotions, :calculator]), "#", class: "btn btn-outline-primary", data: { action: "click->calculator-tiers#add_association" } %>
|
32
32
|
</div>
|
33
33
|
</div>
|
34
34
|
</div>
|
@@ -28,7 +28,7 @@
|
|
28
28
|
<%= render "solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_percent/tier_fields", tier: tier, form: form %>
|
29
29
|
<% end %>
|
30
30
|
<div class="mb-3" data-calculator-tiers-target="links">
|
31
|
-
<%= link_to
|
31
|
+
<%= link_to t(:add_tier, scope: [:solidus_friendly_promotions, :admin, :promotions, :calculator]), "#", class: "btn btn-outline-primary", data: { action: "click->calculator-tiers#add_association" } %>
|
32
32
|
</div>
|
33
33
|
</div>
|
34
34
|
</div>
|
@@ -0,0 +1,34 @@
|
|
1
|
+
<%= render "spree/admin/shared/preference_fields/#{calculator.preference_type(:base_percent)}",
|
2
|
+
name: "#{prefix}[calculator_attributes][preferred_base_percent]",
|
3
|
+
value: calculator.preferred_base_percent,
|
4
|
+
label: calculator.class.human_attribute_name(:preferred_base_percent) %>
|
5
|
+
|
6
|
+
<div class="field">
|
7
|
+
<%= label_tag(
|
8
|
+
"#{prefix}[calculator_attributes][preferred_currency]",
|
9
|
+
t('spree.currency')
|
10
|
+
) %>
|
11
|
+
<%= select_tag(
|
12
|
+
"#{prefix}[calculator_attributes][preferred_currency]",
|
13
|
+
options_for_select(
|
14
|
+
Spree::Config.available_currencies,
|
15
|
+
calculator.preferred_currency || Spree::Config[:currency]
|
16
|
+
),
|
17
|
+
{ class: 'custom-select fullwidth' }
|
18
|
+
) %>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<div class="field">
|
22
|
+
<%= label_tag nil, calculator.class.human_attribute_name(:tiers) %>
|
23
|
+
<div data-controller="calculator-tiers">
|
24
|
+
<template data-calculator-tiers-target="template">
|
25
|
+
<%= render "solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_percent/tier_fields", tier: [nil, nil], form: form %>
|
26
|
+
</template>
|
27
|
+
<% form.object.calculator.preferred_tiers.each do |tier| %>
|
28
|
+
<%= render "solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_percent/tier_fields", tier: tier, form: form %>
|
29
|
+
<% end %>
|
30
|
+
<div class="mb-3" data-calculator-tiers-target="links">
|
31
|
+
<%= link_to t(:add_tier, scope: [:solidus_friendly_promotions, :admin, :promotions, :calculator]), "#", class: "btn btn-outline-primary", data: { action: "click->calculator-tiers#add_association" } %>
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
</div>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<div class="fullwidth tier calculator-tiers">
|
2
|
+
<a class="fa fa-trash remove" data-action="click->calculator-tiers#remove_association"></a>
|
3
|
+
<div class="row">
|
4
|
+
<div class="col-6">
|
5
|
+
<input
|
6
|
+
class="js-base-input form-control"
|
7
|
+
data-action="calculator-tiers#propagate_base_to_value_input"
|
8
|
+
type="text"
|
9
|
+
value="<%= tier[0] %>"
|
10
|
+
>
|
11
|
+
</div>
|
12
|
+
<div class="col-6">
|
13
|
+
<div class="input-group">
|
14
|
+
<input
|
15
|
+
class="js-value-input form-control right-align"
|
16
|
+
name="<%= form.object_name %>[calculator_attributes][preferred_tiers][<%= tier[0] %>]"
|
17
|
+
type="text"
|
18
|
+
value="<%= tier[1] %>"
|
19
|
+
>
|
20
|
+
<div class="input-group-append">
|
21
|
+
<span class="input-group-text">%</span>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
<div class="clear"></div>
|
27
|
+
</div>
|
@@ -0,0 +1,56 @@
|
|
1
|
+
<table class="index">
|
2
|
+
<thead>
|
3
|
+
<tr>
|
4
|
+
<th><%= sort_link @search, :name %></th>
|
5
|
+
<th><%= SolidusFriendlyPromotions::Promotion.human_attribute_name(:code) %></th>
|
6
|
+
<th><%= SolidusFriendlyPromotions::Promotion.human_attribute_name(:status) %></th>
|
7
|
+
<th><%= SolidusFriendlyPromotions::Promotion.human_attribute_name(:usage) %></th>
|
8
|
+
<th><%= sort_link @search, :starts_at %></th>
|
9
|
+
<th><%= sort_link @search, :expires_at %></th>
|
10
|
+
<th><%= SolidusFriendlyPromotions::Promotion.human_attribute_name(:lane) %></th>
|
11
|
+
<th><%= sort_link @search, :updated_at %></th>
|
12
|
+
<th class="actions"></th>
|
13
|
+
</tr>
|
14
|
+
</thead>
|
15
|
+
<tbody>
|
16
|
+
<% promotions.each do |promotion| %>
|
17
|
+
<tr id="<%= spree_dom_id promotion %>">
|
18
|
+
<td><%= promotion.name %></td>
|
19
|
+
<td>
|
20
|
+
<%= (promotion.codes.size == 1) ? promotion.codes.pluck(:value).first : t('solidus_friendly_promotions.number_of_codes', count: promotion.codes.size) %>
|
21
|
+
</td>
|
22
|
+
<td>
|
23
|
+
<span class="pill pill-<%= promotion.active? ? 'active' : 'inactive' %>">
|
24
|
+
<%= t(admin_promotion_status(promotion), scope: 'solidus_friendly_promotions.admin.promotion_status') %>
|
25
|
+
</span>
|
26
|
+
</td>
|
27
|
+
<td>
|
28
|
+
<% if promotion.usage_limit.nil? %>
|
29
|
+
<%= promotion.discounted_orders.exists? ? t(:say_yes, scope: :spree) : t(:say_no, scope: :spree) %>
|
30
|
+
<% else %>
|
31
|
+
<%= promotion.usage_count %> / <%= promotion.usage_limit %>
|
32
|
+
<% end %>
|
33
|
+
<td>
|
34
|
+
<%= l(promotion.starts_at, format: :short) if promotion.starts_at %>
|
35
|
+
</td>
|
36
|
+
<td>
|
37
|
+
<%= l(promotion.expires_at, format: :short) if promotion.expires_at %>
|
38
|
+
</td>
|
39
|
+
<td>
|
40
|
+
<%= SolidusFriendlyPromotions::Promotion.human_enum_name(:lane, promotion.lane) %>
|
41
|
+
</td>
|
42
|
+
<td>
|
43
|
+
<%= l(promotion.updated_at, format: :short) %>
|
44
|
+
</td>
|
45
|
+
<td class="actions">
|
46
|
+
<% if can?(:edit, promotion) %>
|
47
|
+
<%= link_to_edit promotion, no_text: true %>
|
48
|
+
<% end %>
|
49
|
+
<% if can?(:destroy, promotion) %>
|
50
|
+
<%= link_to_delete promotion, no_text: true %>
|
51
|
+
<% end %>
|
52
|
+
</td>
|
53
|
+
</tr>
|
54
|
+
<% end %>
|
55
|
+
</tbody>
|
56
|
+
</table>
|
@@ -0,0 +1,69 @@
|
|
1
|
+
<% content_for :table_filter_title do %>
|
2
|
+
<%= t('spree.search') %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<% content_for :table_filter do %>
|
6
|
+
<div data-hook="admin_promotions_index_search">
|
7
|
+
<%= search_form_for [:admin, search] do |f| %>
|
8
|
+
<div class="row">
|
9
|
+
<div class="col-4">
|
10
|
+
<div class="field">
|
11
|
+
<%= label_tag :q_name_cont, SolidusFriendlyPromotions::Promotion.human_attribute_name(:name) %>
|
12
|
+
<%= f.text_field :name_cont, tabindex: 1 %>
|
13
|
+
</div>
|
14
|
+
</div>
|
15
|
+
|
16
|
+
<div class="col-4">
|
17
|
+
<div class="field">
|
18
|
+
<%= label_tag :q_customer_label_cont, SolidusFriendlyPromotions::Promotion.human_attribute_name(:customer_label) %>
|
19
|
+
<%= f.text_field :customer_label_cont, tabindex: 1 %>
|
20
|
+
</div>
|
21
|
+
</div>
|
22
|
+
|
23
|
+
<div class="col-2">
|
24
|
+
<div class="field">
|
25
|
+
<%= label_tag :q_codes_value_cont, SolidusFriendlyPromotions::Promotion.human_attribute_name(:code) %>
|
26
|
+
<%= f.text_field :codes_value_cont, tabindex: 1 %>
|
27
|
+
</div>
|
28
|
+
</div>
|
29
|
+
|
30
|
+
<div class="col-2">
|
31
|
+
<div class="field">
|
32
|
+
<%= label_tag :q_path_cont, SolidusFriendlyPromotions::Promotion.human_attribute_name(:path) %>
|
33
|
+
<%= f.text_field :path_cont, tabindex: 1 %>
|
34
|
+
</div>
|
35
|
+
</div>
|
36
|
+
|
37
|
+
<div class="col-2">
|
38
|
+
<div class="date-range-filter field">
|
39
|
+
<%= label_tag :q_active, SolidusFriendlyPromotions::Promotion.human_attribute_name(:active) %>
|
40
|
+
<%= f.text_field :active, value: params[:q][:active],
|
41
|
+
class: 'datepicker datepicker-from fullwidth',
|
42
|
+
data: { :'enable-time' => true, :'default-hour' => 0 } %>
|
43
|
+
</div>
|
44
|
+
</div>
|
45
|
+
|
46
|
+
<div class="col-2">
|
47
|
+
<div class="field">
|
48
|
+
<%= label_tag :q_promotion_category_id_eq, SolidusFriendlyPromotions::PromotionCategory.model_name.human %><br>
|
49
|
+
<%= f.collection_select(:promotion_category_id_eq, @promotion_categories, :id, :name, { include_blank: t(:all, scope: :spree) }, { class: 'custom-select fullwidth' }) %>
|
50
|
+
</div>
|
51
|
+
</div>
|
52
|
+
|
53
|
+
<div class="col-2">
|
54
|
+
<div class="field">
|
55
|
+
<%= label_tag :q_lane_eq, SolidusFriendlyPromotions::Promotion.human_attribute_name(:lane) %><br>
|
56
|
+
<%= f.select(:lane_eq, SolidusFriendlyPromotions::Promotion.lane_options, { include_blank: t(:all, scope: :spree) }, { class: 'custom-select fullwidth' }) %>
|
57
|
+
</div>
|
58
|
+
</div>
|
59
|
+
|
60
|
+
</div>
|
61
|
+
|
62
|
+
<div class="actions filter-actions">
|
63
|
+
<div data-hook="admin_promotions_index_search_buttons">
|
64
|
+
<%= button_tag t('spree.filter_results'), class: 'btn btn-primary' %>
|
65
|
+
</div>
|
66
|
+
</div>
|
67
|
+
<% end %>
|
68
|
+
</div>
|
69
|
+
<% end %>
|
@@ -48,26 +48,28 @@
|
|
48
48
|
</div>
|
49
49
|
|
50
50
|
<div class="row">
|
51
|
-
<% [:line_item, :shipment].each do |level| %>
|
51
|
+
<% [:order, :line_item, :shipment].each do |level| %>
|
52
52
|
<% if promotion_actions_by_level(@promotion, level).any? %>
|
53
|
-
<div class="col
|
53
|
+
<div class="col-<%= level == :order ? 12 : 6 %>">
|
54
54
|
<fieldset>
|
55
55
|
<legend align="center"><%= t("#{level}_actions", scope: :solidus_friendly_promotions) %></legend>
|
56
56
|
|
57
57
|
<%= render partial: 'solidus_friendly_promotions/admin/promotion_actions/promotion_action', collection: promotion_actions_by_level(@promotion, level), locals: {} %>
|
58
58
|
</fieldset>
|
59
59
|
</div>
|
60
|
-
|
61
|
-
<
|
62
|
-
<
|
60
|
+
<% if level != :order %>
|
61
|
+
<div class="col-6">
|
62
|
+
<fieldset>
|
63
|
+
<legend align="center"><%= t("#{level}_rules", scope: :solidus_friendly_promotions) %></legend>
|
63
64
|
|
64
|
-
|
65
|
+
<%= render partial: 'solidus_friendly_promotions/admin/promotion_rules/promotion_rule', collection: promotion_rules_by_level(@promotion, level), locals: { level: level } %>
|
65
66
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
67
|
+
<%= turbo_frame_tag @promotion, "new_#{level}_promotion_rule" do %>
|
68
|
+
<%= link_to t(:add_rule, scope: :solidus_friendly_promotions), solidus_friendly_promotions.new_admin_promotion_promotion_rule_path(@promotion, level: level), class: 'btn btn-secondary' %>
|
69
|
+
<% end %>
|
70
|
+
</fieldset>
|
71
|
+
</div>
|
72
|
+
<% end %>
|
71
73
|
<% end %>
|
72
74
|
<% end %>
|
73
75
|
</div>
|
@@ -8,113 +8,12 @@
|
|
8
8
|
<% end %>
|
9
9
|
<% end %>
|
10
10
|
|
11
|
-
|
12
|
-
<%= t('spree.search') %>
|
13
|
-
<% end %>
|
14
|
-
|
15
|
-
<% content_for :table_filter do %>
|
16
|
-
<div data-hook="admin_promotions_index_search">
|
17
|
-
<%= search_form_for [:admin, @search] do |f| %>
|
18
|
-
<div class="row">
|
19
|
-
<div class="col-4">
|
20
|
-
<div class="field">
|
21
|
-
<%= label_tag :q_name_cont, SolidusFriendlyPromotions::Promotion.human_attribute_name(:name) %>
|
22
|
-
<%= f.text_field :name_cont, tabindex: 1 %>
|
23
|
-
</div>
|
24
|
-
</div>
|
25
|
-
|
26
|
-
<div class="col-2">
|
27
|
-
<div class="field">
|
28
|
-
<%= label_tag :q_codes_value_cont, SolidusFriendlyPromotions::Promotion.human_attribute_name(:code) %>
|
29
|
-
<%= f.text_field :codes_value_cont, tabindex: 1 %>
|
30
|
-
</div>
|
31
|
-
</div>
|
32
|
-
|
33
|
-
<div class="col-2">
|
34
|
-
<div class="field">
|
35
|
-
<%= label_tag :q_path_cont, SolidusFriendlyPromotions::Promotion.human_attribute_name(:path) %>
|
36
|
-
<%= f.text_field :path_cont, tabindex: 1 %>
|
37
|
-
</div>
|
38
|
-
</div>
|
39
|
-
|
40
|
-
<div class="col-2">
|
41
|
-
<div class="field">
|
42
|
-
<%= label_tag :q_promotion_category_id_eq, SolidusFriendlyPromotions::PromotionCategory.model_name.human %><br>
|
43
|
-
<%= f.collection_select(:promotion_category_id_eq, @promotion_categories, :id, :name, { include_blank: t('solidus_friendly_promotions.match_choices.all') }, { class: 'custom-select fullwidth' }) %>
|
44
|
-
</div>
|
45
|
-
</div>
|
46
|
-
|
47
|
-
<div class="col-2">
|
48
|
-
<div class="field">
|
49
|
-
<%= label_tag :active, SolidusFriendlyPromotions::Promotion.human_attribute_name(:active) %><br>
|
50
|
-
<%= f.check_box :active, label: false, as: :boolean, checked_value: true %>
|
51
|
-
</div>
|
52
|
-
</div>
|
53
|
-
</div>
|
54
|
-
|
55
|
-
<div class="clearfix"></div>
|
56
|
-
|
57
|
-
<div class="actions filter-actions">
|
58
|
-
<div data-hook="admin_promotions_index_search_buttons">
|
59
|
-
<%= button_tag t('spree.filter_results'), class: 'btn btn-primary' %>
|
60
|
-
</div>
|
61
|
-
</div>
|
62
|
-
<% end %>
|
63
|
-
</div>
|
64
|
-
<% end %>
|
11
|
+
<%= render "table_filter", search: @search %>
|
65
12
|
|
66
13
|
<%= paginate @promotions, theme: "solidus_admin" %>
|
67
14
|
|
68
15
|
<% if @promotions.length > 0 %>
|
69
|
-
|
70
|
-
<thead>
|
71
|
-
<tr>
|
72
|
-
<th><%= SolidusFriendlyPromotions::Promotion.human_attribute_name(:name) %></th>
|
73
|
-
<th><%= SolidusFriendlyPromotions::Promotion.human_attribute_name(:code) %></th>
|
74
|
-
<th><%= SolidusFriendlyPromotions::Promotion.human_attribute_name(:status) %></th>
|
75
|
-
<th><%= SolidusFriendlyPromotions::Promotion.human_attribute_name(:usage_limit) %></th>
|
76
|
-
<th><%= SolidusFriendlyPromotions::Promotion.human_attribute_name(:uses) %></th>
|
77
|
-
<th><%= SolidusFriendlyPromotions::Promotion.human_attribute_name(:starts_at) %></th>
|
78
|
-
<th><%= SolidusFriendlyPromotions::Promotion.human_attribute_name(:expires_at) %></th>
|
79
|
-
<th class="actions"></th>
|
80
|
-
</tr>
|
81
|
-
</thead>
|
82
|
-
<tbody>
|
83
|
-
<% @promotions.each do |promotion| %>
|
84
|
-
<tr id="<%= spree_dom_id promotion %>">
|
85
|
-
<td><%= promotion.name %></td>
|
86
|
-
<td>
|
87
|
-
<%= (promotion.codes.size == 1) ? promotion.codes.pluck(:value).first : t('solidus_friendly_promotions.number_of_codes', count: promotion.codes.size) %>
|
88
|
-
</td>
|
89
|
-
<td>
|
90
|
-
<span class="pill pill-<%= promotion.active? ? 'active' : 'inactive' %>">
|
91
|
-
<%= t(admin_promotion_status(promotion), scope: 'solidus_friendly_promotions.admin.promotion_status') %>
|
92
|
-
</span>
|
93
|
-
</td>
|
94
|
-
<td>
|
95
|
-
<%= promotion.usage_limit.nil? ? "∞" : promotion.usage_limit %>
|
96
|
-
</td>
|
97
|
-
<td>
|
98
|
-
<%= promotion.usage_count %>
|
99
|
-
</td>
|
100
|
-
<td>
|
101
|
-
<%= promotion.starts_at.to_fs(:long) if promotion.starts_at %>
|
102
|
-
</td>
|
103
|
-
<td>
|
104
|
-
<%= promotion.expires_at.to_fs(:long) if promotion.expires_at %>
|
105
|
-
</td>
|
106
|
-
<td class="actions">
|
107
|
-
<% if can?(:edit, promotion) %>
|
108
|
-
<%= link_to_edit promotion, no_text: true %>
|
109
|
-
<% end %>
|
110
|
-
<% if can?(:destroy, promotion) %>
|
111
|
-
<%= link_to_delete promotion, no_text: true %>
|
112
|
-
<% end %>
|
113
|
-
</td>
|
114
|
-
</tr>
|
115
|
-
<% end %>
|
116
|
-
</tbody>
|
117
|
-
</table>
|
16
|
+
<%= render "table", promotions: @promotions %>
|
118
17
|
<% else %>
|
119
18
|
<div class="no-objects-found">
|
120
19
|
<%= render 'spree/admin/shared/no_objects_found',
|
data/config/locales/en.yml
CHANGED
@@ -23,6 +23,7 @@ en:
|
|
23
23
|
shipment_rules: Shipment Rules
|
24
24
|
line_item_actions: Line Item Actions
|
25
25
|
shipment_actions: Shipment Actions
|
26
|
+
order_actions: Order Actions
|
26
27
|
invalid_promotion_rule_level: Invalid Promotion Rule Level. Must be one of "order", "shipment", or "line_item"
|
27
28
|
invalid_promotion_action: Invalid promotion action.
|
28
29
|
invalid_promotion_rule: Invalid promotion rule.
|
@@ -33,7 +34,7 @@ en:
|
|
33
34
|
new_promotion: New Promotion
|
34
35
|
new_promotion_category: New Promotion Category
|
35
36
|
new_promotion_code_batch: New Promotion Code Batch
|
36
|
-
number_of_codes:
|
37
|
+
number_of_codes: "%{count} codes"
|
37
38
|
legacy_promotions: Legacy Promotions
|
38
39
|
no_rules_added: No Rules Added
|
39
40
|
promotion_successfully_created: Promotion has been successfully created!
|
@@ -145,6 +146,8 @@ en:
|
|
145
146
|
starts_at_placeholder: Immediately
|
146
147
|
edit:
|
147
148
|
order_rules: Order Rules
|
149
|
+
calculator:
|
150
|
+
add_tier: Add tier
|
148
151
|
promotion_status:
|
149
152
|
active: Active
|
150
153
|
expired: Expired
|
@@ -161,6 +164,7 @@ en:
|
|
161
164
|
models:
|
162
165
|
solidus_friendly_promotions/actions/adjust_shipment: Discount matching shipments
|
163
166
|
solidus_friendly_promotions/actions/adjust_line_item: Discount matching line items
|
167
|
+
solidus_friendly_promotions/actions/create_discounted_item: Create discounted line item
|
164
168
|
solidus_friendly_promotions/actions/adjust_line_item_quantity_groups: Discount matching line items based on quantity groups
|
165
169
|
solidus_friendly_promotions/calculators/distributed_amount: Distributed Amount
|
166
170
|
solidus_friendly_promotions/calculators/percent: Flat Percent
|
@@ -168,6 +172,7 @@ en:
|
|
168
172
|
solidus_friendly_promotions/calculators/flexi_rate: Flexible Rate
|
169
173
|
solidus_friendly_promotions/calculators/tiered_flat_rate: Tiered Flat Rate
|
170
174
|
solidus_friendly_promotions/calculators/tiered_percent: Tiered Percent
|
175
|
+
solidus_friendly_promotions/calculators/tiered_percent_on_eligible_item_quantity: Tiered Percent based on eligible item quantity
|
171
176
|
solidus_friendly_promotions/rules/first_order: First Order
|
172
177
|
solidus_friendly_promotions/rules/first_repeat_purchase_since: First Repeat Purchase Since
|
173
178
|
solidus_friendly_promotions/rules/item_total: Item Total
|
@@ -189,6 +194,7 @@ en:
|
|
189
194
|
solidus_friendly_promotions/promotion:
|
190
195
|
active: Active
|
191
196
|
customer_label: Customer-facing label
|
197
|
+
usage: Usage
|
192
198
|
lanes:
|
193
199
|
pre: Pre
|
194
200
|
default: Default
|
@@ -199,6 +205,10 @@ en:
|
|
199
205
|
description: Creates a promotion credit on matching line items
|
200
206
|
solidus_friendly_promotions/actions/adjust_shipment:
|
201
207
|
description: Creates a promotion credit on matching shipments
|
208
|
+
solidus_friendly_promotions/actions/create_discounted_item:
|
209
|
+
description: Creates a discounted item with the quantity the applicable line items.
|
210
|
+
preferred_quantity: Quantity per applicable line item quantity
|
211
|
+
preferred_necessary_quantity: Number of items needed for a discounted item
|
202
212
|
solidus_friendly_promotions/rules/first_order:
|
203
213
|
description: Must be the customer's first order
|
204
214
|
solidus_friendly_promotions/rules/first_repeat_purchase_since:
|
@@ -242,14 +252,31 @@ en:
|
|
242
252
|
solidus_friendly_promotions/rules/user_role:
|
243
253
|
description: Order includes User with specified Role(s)
|
244
254
|
solidus_friendly_promotions/calculators/tiered_flat_rate:
|
255
|
+
description: Flat Rate in tiers based on item amount
|
245
256
|
preferred_base_amount: Base Amount
|
246
257
|
tiers: Tiers
|
247
258
|
solidus_friendly_promotions/calculators/tiered_percent:
|
259
|
+
description: Tiered percentage based on order's item total
|
248
260
|
preferred_base_percent: Base Percent
|
249
261
|
tiers: Tiers
|
262
|
+
solidus_friendly_promotions/calculators/tiered_percent_on_eligible_item_quantity:
|
263
|
+
description: Tiered percentage based on eligible item quantity
|
264
|
+
preferred_base_percent: Base Percent
|
265
|
+
tiers: Tiers
|
266
|
+
solidus_friendly_promotions/calculators/flat_rate:
|
267
|
+
description: Provides a flat rate discount
|
268
|
+
solidus_friendly_promotions/calculators/percent:
|
269
|
+
description: Provides a discount calculated by percent of the discountable amount of the item being discounted
|
270
|
+
solidus_friendly_promotions/calculators/distributed_amount:
|
271
|
+
description: Distributed the configured amount among all eligible line items of the order
|
272
|
+
|
250
273
|
errors:
|
251
274
|
models:
|
252
275
|
solidus_friendly_promotions/promotion_code:
|
253
276
|
attributes:
|
254
277
|
base:
|
255
278
|
disallowed_with_apply_automatically: Could not create promotion code on promotion that apply automatically
|
279
|
+
spree/line_item:
|
280
|
+
attributes:
|
281
|
+
quantity:
|
282
|
+
cannot_be_changed_for_automated_items: cannot be changed on a line item managed by a promotion action
|
@@ -4,6 +4,10 @@
|
|
4
4
|
Spree::Config.order_contents_class = "SolidusFriendlyPromotions::SimpleOrderContents"
|
5
5
|
Spree::Config.promotion_adjuster_class = "SolidusFriendlyPromotions::FriendlyPromotionAdjuster"
|
6
6
|
|
7
|
+
Rails.application.config.to_prepare do |config|
|
8
|
+
Spree::Order.line_item_comparison_hooks << :free_from_order_action?
|
9
|
+
end
|
10
|
+
|
7
11
|
# Replace the promotions menu from core with ours
|
8
12
|
Spree::Backend::Config.configure do |config|
|
9
13
|
config.menu_items = config.menu_items.map do |item|
|
@@ -13,7 +17,7 @@ Spree::Backend::Config.configure do |config|
|
|
13
17
|
if item.respond_to?(:children)
|
14
18
|
Spree::BackendConfiguration::MenuItem.new(
|
15
19
|
label: :promotions,
|
16
|
-
icon: "bullhorn",
|
20
|
+
icon: config.admin_updated_navbar ? "ri-megaphone-line" : "bullhorn",
|
17
21
|
condition: -> { can?(:admin, SolidusFriendlyPromotions::Promotion) },
|
18
22
|
url: -> { SolidusFriendlyPromotions::Engine.routes.url_helpers.admin_promotions_path },
|
19
23
|
data_hook: :admin_promotion_sub_tabs,
|
@@ -69,7 +73,8 @@ SolidusFriendlyPromotions.configure do |config|
|
|
69
73
|
"SolidusFriendlyPromotions::Calculators::FlexiRate",
|
70
74
|
"SolidusFriendlyPromotions::Calculators::Percent",
|
71
75
|
"SolidusFriendlyPromotions::Calculators::TieredFlatRate",
|
72
|
-
"SolidusFriendlyPromotions::Calculators::TieredPercent"
|
76
|
+
"SolidusFriendlyPromotions::Calculators::TieredPercent",
|
77
|
+
"SolidusFriendlyPromotions::Calculators::TieredPercentOnEligibleItemQuantity"
|
73
78
|
],
|
74
79
|
"SolidusFriendlyPromotions::Actions::AdjustLineItem" => [
|
75
80
|
"SolidusFriendlyPromotions::Calculators::DistributedAmount",
|
@@ -77,11 +82,18 @@ SolidusFriendlyPromotions.configure do |config|
|
|
77
82
|
"SolidusFriendlyPromotions::Calculators::FlexiRate",
|
78
83
|
"SolidusFriendlyPromotions::Calculators::Percent",
|
79
84
|
"SolidusFriendlyPromotions::Calculators::TieredFlatRate",
|
80
|
-
"SolidusFriendlyPromotions::Calculators::TieredPercent"
|
85
|
+
"SolidusFriendlyPromotions::Calculators::TieredPercent",
|
86
|
+
"SolidusFriendlyPromotions::Calculators::TieredPercentOnEligibleItemQuantity"
|
81
87
|
],
|
82
88
|
"SolidusFriendlyPromotions::Actions::AdjustLineItemQuantityGroups" => [
|
83
89
|
"SolidusFriendlyPromotions::Calculators::FlatRate",
|
84
|
-
"SolidusFriendlyPromotions::Calculators::Percent"
|
90
|
+
"SolidusFriendlyPromotions::Calculators::Percent",
|
91
|
+
"SolidusFriendlyPromotions::Calculators::TieredPercentOnEligibleItemQuantity"
|
92
|
+
],
|
93
|
+
"SolidusFriendlyPromotions::Actions::CreateDiscountedItem" => [
|
94
|
+
"SolidusFriendlyPromotions::Calculators::FlatRate",
|
95
|
+
"SolidusFriendlyPromotions::Calculators::Percent",
|
96
|
+
"SolidusFriendlyPromotions::Calculators::TieredPercentOnEligibleItemQuantity"
|
85
97
|
]
|
86
98
|
)
|
87
99
|
|
@@ -113,6 +125,7 @@ SolidusFriendlyPromotions.configure do |config|
|
|
113
125
|
config.actions = [
|
114
126
|
"SolidusFriendlyPromotions::Actions::AdjustLineItem",
|
115
127
|
"SolidusFriendlyPromotions::Actions::AdjustLineItemQuantityGroups",
|
116
|
-
"SolidusFriendlyPromotions::Actions::AdjustShipment"
|
128
|
+
"SolidusFriendlyPromotions::Actions::AdjustShipment",
|
129
|
+
"SolidusFriendlyPromotions::Actions::CreateDiscountedItem"
|
117
130
|
]
|
118
131
|
end
|
@@ -6,6 +6,7 @@ require "solidus_support"
|
|
6
6
|
require "turbo-rails"
|
7
7
|
require "importmap-rails"
|
8
8
|
require "stimulus-rails"
|
9
|
+
require "ransack-enum"
|
9
10
|
require "solidus_friendly_promotions/nested_class_set"
|
10
11
|
require "solidus_friendly_promotions/configuration"
|
11
12
|
require "solidus_friendly_promotions/version"
|
@@ -33,6 +33,7 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.add_dependency "turbo-rails", "~> 1.4"
|
34
34
|
spec.add_dependency "stimulus-rails", "~> 1.2"
|
35
35
|
spec.add_dependency "importmap-rails", "~> 1.2"
|
36
|
+
spec.add_dependency "ransack-enum", "~> 1.0"
|
36
37
|
spec.add_development_dependency "rspec-activemodel-mocks", "~> 1.0"
|
37
38
|
spec.add_development_dependency "shoulda-matchers", "~> 5.3"
|
38
39
|
spec.add_development_dependency "solidus_dev_support", "~> 2.6"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: solidus_friendly_promotions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.rc.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Meyerhoff
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-11-
|
11
|
+
date: 2023-11-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: solidus_core
|
@@ -86,6 +86,20 @@ dependencies:
|
|
86
86
|
- - "~>"
|
87
87
|
- !ruby/object:Gem::Version
|
88
88
|
version: '1.2'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: ransack-enum
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '1.0'
|
96
|
+
type: :runtime
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '1.0'
|
89
103
|
- !ruby/object:Gem::Dependency
|
90
104
|
name: rspec-activemodel-mocks
|
91
105
|
requirement: !ruby/object:Gem::Requirement
|
@@ -188,6 +202,8 @@ files:
|
|
188
202
|
- app/javascript/solidus_friendly_promotions/jquery/option_value_picker.js
|
189
203
|
- app/jobs/solidus_friendly_promotions/promotion_code_batch_job.rb
|
190
204
|
- app/mailers/solidus_friendly_promotions/promotion_code_batch_mailer.rb
|
205
|
+
- app/models/concerns/solidus_friendly_promotions/actions/order_level_action.rb
|
206
|
+
- app/models/concerns/solidus_friendly_promotions/calculators/promotion_calculator.rb
|
191
207
|
- app/models/concerns/solidus_friendly_promotions/discountable_amount.rb
|
192
208
|
- app/models/concerns/solidus_friendly_promotions/rules/line_item_applicable_order_rule.rb
|
193
209
|
- app/models/concerns/solidus_friendly_promotions/rules/line_item_level_rule.rb
|
@@ -197,12 +213,14 @@ files:
|
|
197
213
|
- app/models/solidus_friendly_promotions/actions/adjust_line_item.rb
|
198
214
|
- app/models/solidus_friendly_promotions/actions/adjust_line_item_quantity_groups.rb
|
199
215
|
- app/models/solidus_friendly_promotions/actions/adjust_shipment.rb
|
216
|
+
- app/models/solidus_friendly_promotions/actions/create_discounted_item.rb
|
200
217
|
- app/models/solidus_friendly_promotions/calculators/distributed_amount.rb
|
201
218
|
- app/models/solidus_friendly_promotions/calculators/flat_rate.rb
|
202
219
|
- app/models/solidus_friendly_promotions/calculators/flexi_rate.rb
|
203
220
|
- app/models/solidus_friendly_promotions/calculators/percent.rb
|
204
221
|
- app/models/solidus_friendly_promotions/calculators/tiered_flat_rate.rb
|
205
222
|
- app/models/solidus_friendly_promotions/calculators/tiered_percent.rb
|
223
|
+
- app/models/solidus_friendly_promotions/calculators/tiered_percent_on_eligible_item_quantity.rb
|
206
224
|
- app/models/solidus_friendly_promotions/distributed_amounts_handler.rb
|
207
225
|
- app/models/solidus_friendly_promotions/eligibility_result.rb
|
208
226
|
- app/models/solidus_friendly_promotions/eligibility_results.rb
|
@@ -223,6 +241,7 @@ files:
|
|
223
241
|
- app/models/solidus_friendly_promotions/promotion_code/batch_builder.rb
|
224
242
|
- app/models/solidus_friendly_promotions/promotion_code_batch.rb
|
225
243
|
- app/models/solidus_friendly_promotions/promotion_handler/coupon.rb
|
244
|
+
- app/models/solidus_friendly_promotions/promotion_handler/null.rb
|
226
245
|
- app/models/solidus_friendly_promotions/promotion_handler/page.rb
|
227
246
|
- app/models/solidus_friendly_promotions/promotion_rule.rb
|
228
247
|
- app/models/solidus_friendly_promotions/promotion_rules_store.rb
|
@@ -256,6 +275,7 @@ files:
|
|
256
275
|
- app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_adjust_line_item_quantity_groups.html.erb
|
257
276
|
- app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_adjust_shipment.html.erb
|
258
277
|
- app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_calculator_fields.erb
|
278
|
+
- app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_create_discounted_item.html.erb
|
259
279
|
- app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/_default_fields.html.erb
|
260
280
|
- app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/distributed_amount/_fields.html.erb
|
261
281
|
- app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/flat_rate/_fields.html.erb
|
@@ -263,6 +283,8 @@ files:
|
|
263
283
|
- app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_flat_rate/_tier_fields.html.erb
|
264
284
|
- app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_percent/_fields.html.erb
|
265
285
|
- app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_percent/_tier_fields.html.erb
|
286
|
+
- app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_percent_on_eligible_item_quantity/_fields.html.erb
|
287
|
+
- app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_percent_on_eligible_item_quantity/_tier_fields.html.erb
|
266
288
|
- app/views/solidus_friendly_promotions/admin/promotion_actions/edit.html.erb
|
267
289
|
- app/views/solidus_friendly_promotions/admin/promotion_actions/new.html.erb
|
268
290
|
- app/views/solidus_friendly_promotions/admin/promotion_categories/_form.html.erb
|
@@ -296,6 +318,8 @@ files:
|
|
296
318
|
- app/views/solidus_friendly_promotions/admin/promotions/_activations_edit.html.erb
|
297
319
|
- app/views/solidus_friendly_promotions/admin/promotions/_activations_new.html.erb
|
298
320
|
- app/views/solidus_friendly_promotions/admin/promotions/_form.html.erb
|
321
|
+
- app/views/solidus_friendly_promotions/admin/promotions/_table.html.erb
|
322
|
+
- app/views/solidus_friendly_promotions/admin/promotions/_table_filter.html.erb
|
299
323
|
- app/views/solidus_friendly_promotions/admin/promotions/edit.html.erb
|
300
324
|
- app/views/solidus_friendly_promotions/admin/promotions/index.html.erb
|
301
325
|
- app/views/solidus_friendly_promotions/admin/promotions/new.html.erb
|
@@ -338,6 +362,7 @@ files:
|
|
338
362
|
- db/migrate/20231012020928_add_db_comments_to_friendly_products_promotion_rules.rb
|
339
363
|
- db/migrate/20231012120928_add_db_comments_to_friendly_promotion_categories.rb
|
340
364
|
- db/migrate/20231013181921_add_original_promotion_ids.rb
|
365
|
+
- db/migrate/20231104135812_add_managed_by_order_action_to_line_items.rb
|
341
366
|
- lib/generators/solidus_friendly_promotions/install/install_generator.rb
|
342
367
|
- lib/generators/solidus_friendly_promotions/install/templates/initializer.rb
|
343
368
|
- lib/solidus_friendly_promotions.rb
|