solidus_friendly_promotions 1.0.0.pre → 1.0.0.rc.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/decorators/models/solidus_friendly_promotions/line_item_decorator.rb +14 -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/solidus_friendly_promotions/actions/adjust_line_item_quantity_groups.rb +1 -1
- data/app/models/solidus_friendly_promotions/actions/create_discounted_item.rb +35 -0
- data/app/models/solidus_friendly_promotions/calculators/distributed_amount.rb +1 -1
- 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_handler/null.rb +20 -0
- data/app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_create_discounted_item.html.erb +15 -0
- data/app/views/solidus_friendly_promotions/admin/promotions/edit.html.erb +13 -11
- data/config/locales/en.yml +8 -0
- 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 +10 -1
- data/lib/solidus_friendly_promotions/version.rb +1 -1
- metadata +6 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac98e07030bf9f63775dafdffc94d3a6be02b8050664037469f57a32dc71da43
|
4
|
+
data.tar.gz: fdd1d7e3fbbfc92cb347af92c28c5f518d91724a330408a576d47449c6e8f201
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9eb24c1fabf89ee0b61731b8541e1459dfe9d508ffc2721f8f1384df382c1653b94f407c04438a2047ebf0fc868e4849fc5f88b821ab141eac44b21bde910b9
|
7
|
+
data.tar.gz: 1e89490f9daf5ad6480b37bc47581bb7ba4a948bb1af7aa7b9539b3c094c6549db4055132b53155e3fc419f881b71d64c81577ba447d188e704eda176bd5b808
|
@@ -2,6 +2,20 @@
|
|
2
2
|
|
3
3
|
module SolidusFriendlyPromotions
|
4
4
|
module LineItemDecorator
|
5
|
+
def self.prepended(base)
|
6
|
+
base.belongs_to :managed_by_order_action, class_name: "SolidusFriendlyPromotions::PromotionAction", optional: true
|
7
|
+
base.validate :validate_managed_quantity_same, on: :update
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def validate_managed_quantity_same
|
13
|
+
if managed_by_order_action && quantity_changed?
|
14
|
+
errors.add(:quantity, :cannot_be_changed_for_automated_items)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Spree::LineItem.prepend self
|
5
19
|
Spree::LineItem.prepend SolidusFriendlyPromotions::DiscountableAmount
|
6
20
|
end
|
7
21
|
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);
|
@@ -79,7 +79,7 @@ module SolidusFriendlyPromotions
|
|
79
79
|
private
|
80
80
|
|
81
81
|
def actionable_line_items(order)
|
82
|
-
order.
|
82
|
+
order.discountable_line_items.select do |item|
|
83
83
|
promotion.rules.select do |rule|
|
84
84
|
rule.applicable?(item)
|
85
85
|
end.all? { |rule| rule.eligible?(item) }
|
@@ -0,0 +1,35 @@
|
|
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
|
+
|
10
|
+
def perform(order)
|
11
|
+
line_item = find_item(order) || create_item(order)
|
12
|
+
line_item.current_discounts << discount(line_item)
|
13
|
+
end
|
14
|
+
|
15
|
+
def remove_from(order)
|
16
|
+
line_item = find_item(order)
|
17
|
+
order.line_items.destroy(line_item)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def find_item(order)
|
23
|
+
order.line_items.detect { |line_item| line_item.managed_by_order_action == self }
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_item(order)
|
27
|
+
order.line_items.create!(quantity: preferred_quantity, variant: variant, managed_by_order_action: self)
|
28
|
+
end
|
29
|
+
|
30
|
+
def variant
|
31
|
+
Spree::Variant.find(preferred_variant_id)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
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
|
@@ -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
|
@@ -0,0 +1,15 @@
|
|
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
|
+
<% end %>
|
9
|
+
|
10
|
+
<%= render(
|
11
|
+
"solidus_friendly_promotions/admin/promotion_actions/actions/calculator_fields",
|
12
|
+
promotion_action: promotion_action,
|
13
|
+
param_prefix: param_prefix,
|
14
|
+
form: form
|
15
|
+
) %>
|
@@ -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>
|
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.
|
@@ -161,6 +162,7 @@ en:
|
|
161
162
|
models:
|
162
163
|
solidus_friendly_promotions/actions/adjust_shipment: Discount matching shipments
|
163
164
|
solidus_friendly_promotions/actions/adjust_line_item: Discount matching line items
|
165
|
+
solidus_friendly_promotions/actions/create_discounted_item: Create discounted line item
|
164
166
|
solidus_friendly_promotions/actions/adjust_line_item_quantity_groups: Discount matching line items based on quantity groups
|
165
167
|
solidus_friendly_promotions/calculators/distributed_amount: Distributed Amount
|
166
168
|
solidus_friendly_promotions/calculators/percent: Flat Percent
|
@@ -199,6 +201,8 @@ en:
|
|
199
201
|
description: Creates a promotion credit on matching line items
|
200
202
|
solidus_friendly_promotions/actions/adjust_shipment:
|
201
203
|
description: Creates a promotion credit on matching shipments
|
204
|
+
solidus_friendly_promotions/actions/create_discounted_item:
|
205
|
+
description: Creates a discounted item
|
202
206
|
solidus_friendly_promotions/rules/first_order:
|
203
207
|
description: Must be the customer's first order
|
204
208
|
solidus_friendly_promotions/rules/first_repeat_purchase_since:
|
@@ -253,3 +257,7 @@ en:
|
|
253
257
|
attributes:
|
254
258
|
base:
|
255
259
|
disallowed_with_apply_automatically: Could not create promotion code on promotion that apply automatically
|
260
|
+
spree/line_item:
|
261
|
+
attributes:
|
262
|
+
quantity:
|
263
|
+
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|
|
@@ -82,6 +86,10 @@ SolidusFriendlyPromotions.configure do |config|
|
|
82
86
|
"SolidusFriendlyPromotions::Actions::AdjustLineItemQuantityGroups" => [
|
83
87
|
"SolidusFriendlyPromotions::Calculators::FlatRate",
|
84
88
|
"SolidusFriendlyPromotions::Calculators::Percent"
|
89
|
+
],
|
90
|
+
"SolidusFriendlyPromotions::Actions::CreateDiscountedItem" => [
|
91
|
+
"SolidusFriendlyPromotions::Calculators::FlatRate",
|
92
|
+
"SolidusFriendlyPromotions::Calculators::Percent"
|
85
93
|
]
|
86
94
|
)
|
87
95
|
|
@@ -113,6 +121,7 @@ SolidusFriendlyPromotions.configure do |config|
|
|
113
121
|
config.actions = [
|
114
122
|
"SolidusFriendlyPromotions::Actions::AdjustLineItem",
|
115
123
|
"SolidusFriendlyPromotions::Actions::AdjustLineItemQuantityGroups",
|
116
|
-
"SolidusFriendlyPromotions::Actions::AdjustShipment"
|
124
|
+
"SolidusFriendlyPromotions::Actions::AdjustShipment",
|
125
|
+
"SolidusFriendlyPromotions::Actions::CreateDiscountedItem"
|
117
126
|
]
|
118
127
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
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.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Meyerhoff
|
@@ -188,6 +188,7 @@ files:
|
|
188
188
|
- app/javascript/solidus_friendly_promotions/jquery/option_value_picker.js
|
189
189
|
- app/jobs/solidus_friendly_promotions/promotion_code_batch_job.rb
|
190
190
|
- app/mailers/solidus_friendly_promotions/promotion_code_batch_mailer.rb
|
191
|
+
- app/models/concerns/solidus_friendly_promotions/actions/order_level_action.rb
|
191
192
|
- app/models/concerns/solidus_friendly_promotions/discountable_amount.rb
|
192
193
|
- app/models/concerns/solidus_friendly_promotions/rules/line_item_applicable_order_rule.rb
|
193
194
|
- app/models/concerns/solidus_friendly_promotions/rules/line_item_level_rule.rb
|
@@ -197,6 +198,7 @@ files:
|
|
197
198
|
- app/models/solidus_friendly_promotions/actions/adjust_line_item.rb
|
198
199
|
- app/models/solidus_friendly_promotions/actions/adjust_line_item_quantity_groups.rb
|
199
200
|
- app/models/solidus_friendly_promotions/actions/adjust_shipment.rb
|
201
|
+
- app/models/solidus_friendly_promotions/actions/create_discounted_item.rb
|
200
202
|
- app/models/solidus_friendly_promotions/calculators/distributed_amount.rb
|
201
203
|
- app/models/solidus_friendly_promotions/calculators/flat_rate.rb
|
202
204
|
- app/models/solidus_friendly_promotions/calculators/flexi_rate.rb
|
@@ -223,6 +225,7 @@ files:
|
|
223
225
|
- app/models/solidus_friendly_promotions/promotion_code/batch_builder.rb
|
224
226
|
- app/models/solidus_friendly_promotions/promotion_code_batch.rb
|
225
227
|
- app/models/solidus_friendly_promotions/promotion_handler/coupon.rb
|
228
|
+
- app/models/solidus_friendly_promotions/promotion_handler/null.rb
|
226
229
|
- app/models/solidus_friendly_promotions/promotion_handler/page.rb
|
227
230
|
- app/models/solidus_friendly_promotions/promotion_rule.rb
|
228
231
|
- app/models/solidus_friendly_promotions/promotion_rules_store.rb
|
@@ -256,6 +259,7 @@ files:
|
|
256
259
|
- app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_adjust_line_item_quantity_groups.html.erb
|
257
260
|
- app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_adjust_shipment.html.erb
|
258
261
|
- app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_calculator_fields.erb
|
262
|
+
- app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_create_discounted_item.html.erb
|
259
263
|
- app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/_default_fields.html.erb
|
260
264
|
- app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/distributed_amount/_fields.html.erb
|
261
265
|
- app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/flat_rate/_fields.html.erb
|
@@ -338,6 +342,7 @@ files:
|
|
338
342
|
- db/migrate/20231012020928_add_db_comments_to_friendly_products_promotion_rules.rb
|
339
343
|
- db/migrate/20231012120928_add_db_comments_to_friendly_promotion_categories.rb
|
340
344
|
- db/migrate/20231013181921_add_original_promotion_ids.rb
|
345
|
+
- db/migrate/20231104135812_add_managed_by_order_action_to_line_items.rb
|
341
346
|
- lib/generators/solidus_friendly_promotions/install/install_generator.rb
|
342
347
|
- lib/generators/solidus_friendly_promotions/install/templates/initializer.rb
|
343
348
|
- lib/solidus_friendly_promotions.rb
|