solidus_promotions 4.4.1 → 4.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/MIGRATING.md +1 -1
  3. data/README.md +11 -8
  4. data/app/models/solidus_promotions/order_adjuster.rb +1 -1
  5. data/app/models/solidus_promotions/promotion.rb +11 -1
  6. data/app/models/solidus_promotions/promotion_handler/coupon.rb +4 -0
  7. data/app/{decorators/models/solidus_promotions/adjustment_decorator.rb → patches/models/solidus_promotions/adjustment_patch.rb} +1 -1
  8. data/app/{decorators/models/solidus_promotions/line_item_decorator.rb → patches/models/solidus_promotions/line_item_patch.rb} +1 -1
  9. data/app/{decorators/models/solidus_promotions/order_decorator.rb → patches/models/solidus_promotions/order_patch.rb} +1 -1
  10. data/app/{decorators/models/solidus_promotions/order_recalculator_decorator.rb → patches/models/solidus_promotions/order_recalculator_patch.rb} +1 -1
  11. data/app/{decorators/models/solidus_promotions/shipment_decorator.rb → patches/models/solidus_promotions/shipment_patch.rb} +1 -1
  12. data/app/{decorators/models/solidus_promotions/shipping_rate_decorator.rb → patches/models/solidus_promotions/shipping_rate_patch.rb} +1 -1
  13. data/config/locales/promotion_categories.en.yml +8 -1
  14. data/config/locales/promotions.en.yml +3 -0
  15. data/config/routes.rb +1 -1
  16. data/lib/components/admin/solidus_promotions/promotion_categories/edit/component.html.erb +16 -0
  17. data/lib/components/admin/solidus_promotions/promotion_categories/edit/component.rb +16 -0
  18. data/lib/components/admin/solidus_promotions/promotion_categories/edit/component.yml +4 -0
  19. data/lib/components/admin/solidus_promotions/promotion_categories/index/component.rb +21 -8
  20. data/lib/components/admin/solidus_promotions/promotion_categories/new/component.html.erb +16 -0
  21. data/lib/components/admin/solidus_promotions/promotion_categories/new/component.rb +16 -0
  22. data/lib/components/admin/solidus_promotions/promotion_categories/new/component.yml +4 -0
  23. data/lib/components/admin/solidus_promotions/promotions/index/component.rb +6 -4
  24. data/lib/components/admin/solidus_promotions/promotions/index/component.yml +1 -0
  25. data/lib/controllers/admin/solidus_promotions/promotion_categories_controller.rb +30 -16
  26. data/lib/controllers/admin/solidus_promotions/promotions_controller.rb +4 -0
  27. data/lib/controllers/backend/solidus_promotions/admin/benefits_controller.rb +3 -3
  28. data/lib/controllers/backend/solidus_promotions/admin/promotion_codes_controller.rb +4 -0
  29. data/lib/solidus_promotions/engine.rb +4 -4
  30. data/solidus_promotions.gemspec +2 -1
  31. metadata +33 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8d6349051a6426b230165c4ddb9d0f3e3dc90ea2c27ed9e80b5968757135fe67
4
- data.tar.gz: d51b5804b5bcdcfed387a4508bc4cbd7593ee311284b51886cde909423fab6e6
3
+ metadata.gz: c7db30fb68623ede772e5dc6c53bc40205c8d3d929e89df335427b917a9c1857
4
+ data.tar.gz: 42f7f86d1f7c5fef3d62d27565c08b39b01eb3c15a0107c428dfea9afaafcd03
5
5
  SHA512:
6
- metadata.gz: 014bfa7ca43f1c7033656d059e26dd7822188b3c024e5e8ca80ef88c981d6569b5abba6712a230ecb15129baf9f94757af9c6bb2b98b5450d63a18c5c2ce1434
7
- data.tar.gz: b5e9de86e525f26598e37514f2314e3ee47d5ce9c03cfcfae618f92e18f75ef540da6aa43d36e31dd5a4eafc0491c1003b6a6dff82878eec40a4916962bcdee4
6
+ metadata.gz: 114981896806a343b6d5e36db617ecfb4a06fbe3f00f19f4bab46df7db7b473706bc5c2d2a874d2c3d194c4f7002d4f7ca871d00c060faeea5e133403b882d46
7
+ data.tar.gz: 1666caa17bb47b1989b1356227aa7ce1058e2b9fb4b494e9888203ebfeaf114c30325ad288038c1b4e2966c4ec1e09198c75b5e41e060be3435a4cc3ae863d4d
data/MIGRATING.md CHANGED
@@ -44,7 +44,7 @@ bundle exec rails solidus_promotions:migrate_existing_promotions
44
44
 
45
45
  This will create equivalents of the legacy promotion configuration in SolidusPromotions.
46
46
 
47
- Now, change `config/initializers/solidus_promotions.rb` to use your new promotion configuration:
47
+ Now, change `config/initializers/spree.rb` to use your new promotion configuration:
48
48
 
49
49
  ## Change store behavior to use SolidusPromotions
50
50
 
data/README.md CHANGED
@@ -2,17 +2,22 @@
2
2
 
3
3
  This gem contains Solidus' recommended promotion system. It is slated to replace the promotion system in the `legacy_promotions` gem.
4
4
 
5
- The basic architecture is very similar to the legacy promotion system, but with a few decisive tweaks, which I'll explain in the coming sections.
5
+ The basic architecture is very similar to the legacy promotion system, but with a few decisive tweaks, which are explained in the subsequent sections.
6
+
7
+ > [!IMPORTANT]
8
+ > If you are upgrading from a previous version of Solidus, it is advised that you update also the promotion system to the new gem. Please consult the [Migration Guide](./MIGRATING.md).
9
+ > While the current version of Solidus still installs the legacy promotion system, we advise a migration at the earliest convinience to avoid having to rush the migration in the future.
10
+
6
11
 
7
12
  ## Architecture
8
13
 
9
- This extension centralizes promotion handling in the order updater. A service class, the `SolidusPromotions::OrderAdjuster` applies the current promotion configuration to the order, adjusting or removing adjustments as necessary.
14
+ This extension centralizes promotion handling in the order updater significantly improving the performance of cart calculations. A service class, the `SolidusPromotions::OrderAdjuster` applies the current promotion configuration to the order, adjusting or removing adjustments as necessary.
10
15
 
11
16
  `SolidusPromotions::Promotion` objects have benefits, and benefits have conditions. For example, a promotion that is "20% off shirts" would have a benefit of type "AdjustLineItem", and that benefit would have a condition of type "LineItemTaxon" that makes sure only line items with the "shirts" taxon will get the benefit.
12
17
 
13
18
  ### Promotion lanes
14
19
 
15
- Promotions get applied by "lane". Promotions within a lane conflict with each other, whereas promotions that do not share a lane will apply sequentially in the order of the lanes. By default these are "pre", "default" and "post", but you can configure this using the SolidusPromotions initializer:
20
+ Promotions get applied by "lane". Promotions within a lane conflict with each other, whereas promotions that do not share a lane will apply sequentially in the order of the lanes. By default these are "pre", "default" and "post", but they can be configured using the SolidusPromotions initializer:
16
21
 
17
22
  ```rb
18
23
  SolidusPromotions.configure do |config|
@@ -25,11 +30,9 @@ SolidusPromotions.configure do |config|
25
30
  end
26
31
  ```
27
32
 
28
- ### Benefits
29
-
30
- Solidus Friendly Promotions ships with only three benefit types by default that should cover most use cases: `AdjustLineItem`, `AdjustShipment` and `CreateDiscountedItem`. There is no benefit that creates order-level adjustments, as this feature of Solidus' legacy promotions system has proven to be very difficult for customer service and finance departments due to the difficulty of accruing order-level adjustments to individual line items when e.g. processing returns. In order to give a fixed discount to all line items in an order, use the `AdjustLineItem` benefit with the `DistributedAmount` calculator.
33
+ ### Types of Benefits
31
34
 
32
- Alle benefits are calculable. By setting their `calculator` to one of the classes provided, a great range of discounts is possible.
35
+ The new Solidus Promotions Systems ships with three benefit types: `AdjustLineItem`, `AdjustShipment` and `CreateDiscountedItem`. To allow more efficient processing of returns and reduce the complexity for bookkeping and support departmentes fixed discount to all line items in an order can now be given through the `AdjustLineItem` benefit through the `DistributedAmount` calculator significantly reducing amministration issues with refunds.
33
36
 
34
37
  #### `AdjustLineItem`
35
38
 
@@ -119,4 +122,4 @@ SolidusDevSupport::TestingSupport::Factories.load_for(SolidusPromotions::Engine)
119
122
 
120
123
  ## License
121
124
 
122
- Copyright (c) 2024 Martin Meyerhoff, Solidus Team, released under the New BSD License.
125
+ Copyright (c) 2024 Martin Meyerhoff, Solidus Team, released under the [license of the parent repository](https://github.com/solidusio/solidus/blob/main/LICENSE.md).
@@ -13,7 +13,7 @@ module SolidusPromotions
13
13
  def call
14
14
  order.reset_current_discounts
15
15
 
16
- return order if (!SolidusPromotions.config.recalculate_complete_orders && order.complete?) || order.shipped?
16
+ return order unless SolidusPromotions::Promotion.order_activatable?(order)
17
17
 
18
18
  discounted_order = DiscountOrder.new(order, promotions, dry_run: dry_run).call
19
19
 
@@ -2,6 +2,8 @@
2
2
 
3
3
  module SolidusPromotions
4
4
  class Promotion < Spree::Base
5
+ UNACTIVATABLE_ORDER_STATES = ["awaiting_return", "returned", "canceled"]
6
+
5
7
  include Spree::SoftDeletable
6
8
 
7
9
  belongs_to :category, class_name: "SolidusPromotions::PromotionCategory",
@@ -9,7 +11,7 @@ module SolidusPromotions
9
11
  belongs_to :original_promotion, class_name: "Spree::Promotion", optional: true
10
12
  has_many :benefits, class_name: "SolidusPromotions::Benefit", dependent: :destroy
11
13
  has_many :conditions, through: :benefits
12
- has_many :codes, class_name: "SolidusPromotions::PromotionCode", dependent: :destroy
14
+ has_many :codes, class_name: "SolidusPromotions::PromotionCode", dependent: :destroy, inverse_of: :promotion
13
15
  has_many :code_batches, class_name: "SolidusPromotions::PromotionCodeBatch", dependent: :destroy
14
16
  has_many :order_promotions, class_name: "SolidusPromotions::OrderPromotion", dependent: :destroy
15
17
 
@@ -59,6 +61,14 @@ module SolidusPromotions
59
61
  lanes.sort_by(&:last).to_h
60
62
  end
61
63
 
64
+ def self.order_activatable?(order)
65
+ return false if UNACTIVATABLE_ORDER_STATES.include?(order.state)
66
+ return false if order.shipped?
67
+ return false if order.complete? && !SolidusPromotions.config.recalculate_complete_orders
68
+
69
+ true
70
+ end
71
+
62
72
  self.allowed_ransackable_associations = ["codes"]
63
73
  self.allowed_ransackable_attributes = %w[name customer_label path promotion_category_id lane updated_at]
64
74
  self.allowed_ransackable_scopes = %i[active with_discarded]
@@ -26,6 +26,10 @@ module SolidusPromotions
26
26
  self
27
27
  end
28
28
 
29
+ def can_apply?
30
+ SolidusPromotions::Promotion.order_activatable?(order)
31
+ end
32
+
29
33
  def remove
30
34
  if promotion.blank?
31
35
  set_error_code :coupon_code_not_found
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidusPromotions
4
- module AdjustmentDecorator
4
+ module AdjustmentPatch
5
5
  def self.prepended(base)
6
6
  base.scope :solidus_promotion, -> { where(source_type: "SolidusPromotions::Benefit") }
7
7
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidusPromotions
4
- module LineItemDecorator
4
+ module LineItemPatch
5
5
  def self.prepended(base)
6
6
  base.attr_accessor :quantity_setter
7
7
  base.belongs_to :managed_by_order_benefit, class_name: "SolidusPromotions::Benefit", optional: true
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidusPromotions
4
- module OrderDecorator
4
+ module OrderPatch
5
5
  module ClassMethods
6
6
  def allowed_ransackable_associations
7
7
  super + ["solidus_promotions", "solidus_order_promotions"]
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidusPromotions
4
- module OrderRecalculatorDecorator
4
+ module OrderRecalculatorPatch
5
5
  # This is only needed for stores upgrading from the legacy promotion system.
6
6
  # Once we've removed support for the legacy promotion system, we can remove this.
7
7
  def recalculate
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidusPromotions
4
- module ShipmentDecorator
4
+ module ShipmentPatch
5
5
  Spree::Shipment.prepend SolidusPromotions::DiscountableAmount
6
6
 
7
7
  def reset_current_discounts
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidusPromotions
4
- module ShippingRateDecorator
4
+ module ShippingRatePatch
5
5
  def self.prepended(base)
6
6
  base.class_eval do
7
7
  has_many :discounts,
@@ -1,6 +1,13 @@
1
1
  en:
2
+ solidus_admin:
3
+ promotion_categories:
4
+ title: "Promotion Categories"
2
5
  solidus_promotions:
3
6
  promotion_categories:
4
7
  title: "Promotion Categories"
8
+ create:
9
+ success: "Promotion category was successfully created."
10
+ update:
11
+ success: "Promotion category was successfully updated."
5
12
  destroy:
6
- success: "Promotion Categories were successfully removed."
13
+ success: "Promotion categories were successfully removed."
@@ -1,4 +1,7 @@
1
1
  en:
2
+ solidus_admin:
3
+ promotions:
4
+ title: "Promotions"
2
5
  solidus_promotions:
3
6
  promotions:
4
7
  title: "Promotions"
data/config/routes.rb CHANGED
@@ -12,7 +12,7 @@ SolidusPromotions::Engine.routes.draw do
12
12
  }) do
13
13
  scope :admin do
14
14
  scope :solidus do
15
- admin_resources :promotion_categories, only: [:index, :destroy]
15
+ admin_resources :promotion_categories, except: [:show]
16
16
  admin_resources :promotions, only: [:index, :destroy]
17
17
  end
18
18
  end
@@ -0,0 +1,16 @@
1
+ <%= turbo_frame_tag :resource_modal, target: "_top" do %>
2
+ <%= render component("ui/modal").new(title: t(".title")) do |modal| %>
3
+ <%= form_for @promotion_category, url: form_url, html: { id: form_id } do |f| %>
4
+ <div class="flex flex-col gap-6 pb-4">
5
+ <%= render component("ui/forms/field").text_field(f, :name, class: "required") %>
6
+ <%= render component("ui/forms/field").text_field(f, :code, class: "required") %>
7
+ </div>
8
+ <% modal.with_actions do %>
9
+ <form method="dialog">
10
+ <%= render component("ui/button").new(scheme: :secondary, text: t('.cancel')) %>
11
+ </form>
12
+ <%= render component("ui/button").new(form: form_id, type: :submit, text: t('.submit')) %>
13
+ <% end %>
14
+ <% end %>
15
+ <% end %>
16
+ <% end %>
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SolidusPromotions::PromotionCategories::Edit::Component < SolidusAdmin::BaseComponent
4
+ def initialize(record)
5
+ super
6
+ @promotion_category = record
7
+ end
8
+
9
+ def form_id
10
+ dom_id(@promotion_category, "#{stimulus_id}_edit_promotion_category_form")
11
+ end
12
+
13
+ def form_url
14
+ solidus_promotions.promotion_category_path(@promotion_category, **search_filter_params)
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ en:
2
+ title: "Edit Promotion Category"
3
+ cancel: "Cancel"
4
+ submit: "Update Promotion Category"
@@ -5,15 +5,24 @@ class SolidusPromotions::PromotionCategories::Index::Component < SolidusAdmin::U
5
5
  SolidusPromotions::PromotionCategory
6
6
  end
7
7
 
8
- def row_url(promotion_category)
9
- solidus_promotions.edit_admin_promotion_category_path(promotion_category)
8
+ def title
9
+ t('solidus_promotions.promotion_categories.title')
10
+ end
11
+
12
+ def edit_path(record)
13
+ solidus_promotions.edit_promotion_category_path(record, **search_filter_params)
14
+ end
15
+
16
+ def turbo_frames
17
+ %w[resource_modal]
10
18
  end
11
19
 
12
20
  def page_actions
13
21
  render component("ui/button").new(
14
22
  tag: :a,
15
23
  text: t(".add"),
16
- href: solidus_promotions.new_admin_promotion_category_path,
24
+ href: solidus_promotions.new_promotion_category_path(**search_filter_params),
25
+ data: { turbo_frame: :resource_modal },
17
26
  icon: "add-line"
18
27
  )
19
28
  end
@@ -22,7 +31,7 @@ class SolidusPromotions::PromotionCategories::Index::Component < SolidusAdmin::U
22
31
  [
23
32
  {
24
33
  label: t(".batch_actions.delete"),
25
- action: solidus_promotions.promotion_categories_path,
34
+ action: solidus_promotions.promotion_categories_path(**search_filter_params),
26
35
  method: :delete,
27
36
  icon: "delete-bin-7-line"
28
37
  }
@@ -39,8 +48,10 @@ class SolidusPromotions::PromotionCategories::Index::Component < SolidusAdmin::U
39
48
  def name_column
40
49
  {
41
50
  header: :name,
42
- data: ->(promotion_category) do
43
- content_tag :div, promotion_category.name
51
+ data: ->(record) do
52
+ link_to record.name, edit_path(record),
53
+ data: { turbo_frame: :resource_modal },
54
+ class: 'body-link'
44
55
  end
45
56
  }
46
57
  end
@@ -48,8 +59,10 @@ class SolidusPromotions::PromotionCategories::Index::Component < SolidusAdmin::U
48
59
  def code_column
49
60
  {
50
61
  header: :code,
51
- data: ->(promotion_category) do
52
- content_tag :div, promotion_category.code
62
+ data: ->(record) do
63
+ link_to record.code, edit_path(record),
64
+ data: { turbo_frame: :resource_modal },
65
+ class: 'body-link'
53
66
  end
54
67
  }
55
68
  end
@@ -0,0 +1,16 @@
1
+ <%= turbo_frame_tag :resource_modal, target: "_top" do %>
2
+ <%= render component("ui/modal").new(title: t(".title")) do |modal| %>
3
+ <%= form_for @promotion_category, url: form_url, html: { id: form_id } do |f| %>
4
+ <div class="flex flex-col gap-6 pb-4">
5
+ <%= render component("ui/forms/field").text_field(f, :name, class: "required") %>
6
+ <%= render component("ui/forms/field").text_field(f, :code, class: "required") %>
7
+ </div>
8
+ <% modal.with_actions do %>
9
+ <form method="dialog">
10
+ <%= render component("ui/button").new(scheme: :secondary, text: t('.cancel')) %>
11
+ </form>
12
+ <%= render component("ui/button").new(form: form_id, type: :submit, text: t('.submit')) %>
13
+ <% end %>
14
+ <% end %>
15
+ <% end %>
16
+ <% end %>
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SolidusPromotions::PromotionCategories::New::Component < SolidusAdmin::BaseComponent
4
+ def initialize(record)
5
+ super
6
+ @promotion_category = record
7
+ end
8
+
9
+ def form_id
10
+ dom_id(@promotion_category, "#{stimulus_id}_new_promotion_category_form")
11
+ end
12
+
13
+ def form_url
14
+ solidus_promotions.promotion_categories_path(**search_filter_params)
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ en:
2
+ title: "New Promotion Category"
3
+ cancel: "Cancel"
4
+ submit: "Add Promotion Category"
@@ -14,7 +14,7 @@ class SolidusPromotions::Promotions::Index::Component < SolidusAdmin::UI::Pages:
14
14
  end
15
15
 
16
16
  def row_url(promotion)
17
- solidus_promotions.admin_promotion_path(promotion)
17
+ solidus_promotions.edit_admin_promotion_path(promotion)
18
18
  end
19
19
 
20
20
  def page_actions
@@ -63,14 +63,16 @@ class SolidusPromotions::Promotions::Index::Component < SolidusAdmin::UI::Pages:
63
63
  {
64
64
  header: :name,
65
65
  data: ->(promotion) do
66
- content_tag :div, promotion.name
66
+ link_to promotion.name, row_url(promotion)
67
67
  end
68
68
  },
69
69
  {
70
70
  header: :code,
71
71
  data: ->(promotion) do
72
- count = promotion.codes.count
73
- (count == 1) ? promotion.codes.pick(:value) : t("spree.number_of_codes", count: count)
72
+ link_to solidus_promotions.admin_promotion_promotion_codes_path(promotion), title: t(".codes") do
73
+ count = promotion.codes.count
74
+ (count == 1) ? promotion.codes.pick(:value) : t("spree.number_of_codes", count: count)
75
+ end
74
76
  end
75
77
  },
76
78
  {
@@ -8,3 +8,4 @@ en:
8
8
  status:
9
9
  active: Active
10
10
  inactive: Inactive
11
+ codes: Codes
@@ -1,29 +1,43 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidusPromotions
4
- class PromotionCategoriesController < SolidusAdmin::BaseController
5
- include SolidusAdmin::ControllerHelpers::Search
4
+ class PromotionCategoriesController < SolidusAdmin::ResourcesController
5
+ private
6
6
 
7
- def index
8
- promotion_categories = apply_search_to(
9
- SolidusPromotions::PromotionCategory.all,
10
- param: :q
11
- )
7
+ def resource_class = SolidusPromotions::PromotionCategory
12
8
 
13
- set_page_and_extract_portion_from(promotion_categories)
9
+ def permitted_resource_params
10
+ params.require(:promotion_category).permit(:name, :code)
11
+ end
12
+
13
+ def resources_collection = SolidusPromotions::PromotionCategory.unscoped
14
+
15
+ def index_component
16
+ component("solidus_promotions/categories/index")
17
+ end
18
+
19
+ def new_component
20
+ component("solidus_promotions/categories/new")
21
+ end
14
22
 
15
- respond_to do |format|
16
- format.html { render component("solidus_promotions/categories/index").new(page: @page) }
17
- end
23
+ def edit_component
24
+ component("solidus_promotions/categories/edit")
18
25
  end
19
26
 
20
- def destroy
21
- @promotion_categories = SolidusPromotions::PromotionCategory.where(id: params[:id])
27
+ def after_create_path
28
+ solidus_promotions.promotion_categories_path(**search_filter_params)
29
+ end
22
30
 
23
- SolidusPromotions::PromotionCategory.transaction { @promotion_categories.destroy_all }
31
+ def after_update_path
32
+ solidus_promotions.promotion_categories_path(**search_filter_params)
33
+ end
34
+
35
+ def after_destroy_path
36
+ solidus_promotions.promotion_categories_path(**search_filter_params)
37
+ end
24
38
 
25
- flash[:notice] = t(".success")
26
- redirect_back_or_to solidus_promotions.promotion_categories_path, status: :see_other
39
+ def authorization_subject
40
+ SolidusPromotions::PromotionCategory
27
41
  end
28
42
  end
29
43
  end
@@ -42,5 +42,9 @@ module SolidusPromotions
42
42
  def promotion_params
43
43
  params.require(:promotion).permit(:user_id, permitted_promotion_attributes)
44
44
  end
45
+
46
+ def authorization_subject
47
+ SolidusPromotions::Promotion
48
+ end
45
49
  end
46
50
  end
@@ -14,12 +14,12 @@ module SolidusPromotions
14
14
  def create
15
15
  @benefit = @benefit_type.new(benefit_params)
16
16
  @benefit.promotion = @promotion
17
- if @benefit.save(validate: false)
17
+ if @benefit.save
18
18
  flash[:success] =
19
19
  t("spree.successfully_created", resource: SolidusPromotions::Benefit.model_name.human)
20
20
  redirect_to location_after_save, format: :html
21
21
  else
22
- render :new, layout: false
22
+ render :new, layout: false, status: :unprocessable_entity
23
23
  end
24
24
  end
25
25
 
@@ -39,7 +39,7 @@ module SolidusPromotions
39
39
  t("spree.successfully_updated", resource: SolidusPromotions::Benefit.model_name.human)
40
40
  redirect_to location_after_save, format: :html
41
41
  else
42
- render :edit
42
+ render :edit, status: :unprocessable_entity
43
43
  end
44
44
  end
45
45
 
@@ -48,6 +48,10 @@ module SolidusPromotions
48
48
 
49
49
  private
50
50
 
51
+ def model_class
52
+ SolidusPromotions::PromotionCode
53
+ end
54
+
51
55
  def load_promotion
52
56
  @promotion = SolidusPromotions::Promotion
53
57
  .accessible_by(current_ability, :show)
@@ -6,6 +6,7 @@ require "solidus_support"
6
6
  module SolidusPromotions
7
7
  class Engine < Rails::Engine
8
8
  include SolidusSupport::EngineExtensions
9
+ Flickwerk.aliases["Spree::Config.order_recalculator_class"] = Spree::Config.order_recalculator_class_name
9
10
 
10
11
  isolate_namespace ::SolidusPromotions
11
12
 
@@ -40,10 +41,7 @@ module SolidusPromotions
40
41
 
41
42
  initializer "solidus_promotions.spree_config", after: "spree.load_config_initializers" do
42
43
  Spree::Config.adjustment_promotion_source_types << "SolidusPromotions::Benefit"
43
-
44
- Rails.application.config.to_prepare do
45
- Spree::Order.line_item_comparison_hooks << :free_from_order_benefit?
46
- end
44
+ Spree::Config.line_item_comparison_hooks << :free_from_order_benefit?
47
45
  end
48
46
 
49
47
  initializer "solidus_promotions.core.pub_sub", after: "spree.core.pub_sub" do |app|
@@ -60,6 +58,8 @@ module SolidusPromotions
60
58
 
61
59
  SolidusAdmin::Config.components["solidus_promotions/promotions/index"] = "SolidusPromotions::Promotions::Index::Component"
62
60
  SolidusAdmin::Config.components["solidus_promotions/categories/index"] = "SolidusPromotions::PromotionCategories::Index::Component"
61
+ SolidusAdmin::Config.components["solidus_promotions/categories/new"] = "SolidusPromotions::PromotionCategories::New::Component"
62
+ SolidusAdmin::Config.components["solidus_promotions/categories/edit"] = "SolidusPromotions::PromotionCategories::Edit::Component"
63
63
  end
64
64
  end
65
65
 
@@ -24,10 +24,11 @@ Gem::Specification.new do |spec|
24
24
  files = Dir.chdir(__dir__) { `git ls-files -z`.split("\x0") }
25
25
  spec.files = files.grep_v(%r{^(spec|bin)/})
26
26
 
27
+ spec.add_dependency "csv", "~> 3.0"
27
28
  spec.add_dependency "importmap-rails", "~> 1.2"
28
29
  spec.add_dependency "ransack-enum", "~> 1.0"
29
30
  spec.add_dependency "solidus_core", [">= 4.0.0", "< 5"]
30
- spec.add_dependency "solidus_support", "~> 0.5"
31
+ spec.add_dependency "solidus_support", ">= 0.12.0"
31
32
  spec.add_dependency "stimulus-rails", "~> 1.2"
32
33
  spec.add_dependency "turbo-rails", ">= 1.4"
33
34
  end
metadata CHANGED
@@ -1,16 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solidus_promotions
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.4.1
4
+ version: 4.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Meyerhoff
8
8
  - Solidus Team
9
- autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2024-11-18 00:00:00.000000000 Z
11
+ date: 2025-02-20 00:00:00.000000000 Z
13
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: csv
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
14
27
  - !ruby/object:Gem::Dependency
15
28
  name: importmap-rails
16
29
  requirement: !ruby/object:Gem::Requirement
@@ -63,16 +76,16 @@ dependencies:
63
76
  name: solidus_support
64
77
  requirement: !ruby/object:Gem::Requirement
65
78
  requirements:
66
- - - "~>"
79
+ - - ">="
67
80
  - !ruby/object:Gem::Version
68
- version: '0.5'
81
+ version: 0.12.0
69
82
  type: :runtime
70
83
  prerelease: false
71
84
  version_requirements: !ruby/object:Gem::Requirement
72
85
  requirements:
73
- - - "~>"
86
+ - - ">="
74
87
  - !ruby/object:Gem::Version
75
- version: '0.5'
88
+ version: 0.12.0
76
89
  - !ruby/object:Gem::Dependency
77
90
  name: stimulus-rails
78
91
  requirement: !ruby/object:Gem::Requirement
@@ -113,12 +126,6 @@ files:
113
126
  - README.md
114
127
  - Rakefile
115
128
  - app/assets/config/solidus_promotions/manifest.js
116
- - app/decorators/models/solidus_promotions/adjustment_decorator.rb
117
- - app/decorators/models/solidus_promotions/line_item_decorator.rb
118
- - app/decorators/models/solidus_promotions/order_decorator.rb
119
- - app/decorators/models/solidus_promotions/order_recalculator_decorator.rb
120
- - app/decorators/models/solidus_promotions/shipment_decorator.rb
121
- - app/decorators/models/solidus_promotions/shipping_rate_decorator.rb
122
129
  - app/helpers/solidus_promotions/admin/benefits_helper.rb
123
130
  - app/helpers/solidus_promotions/admin/conditions_helper.rb
124
131
  - app/helpers/solidus_promotions/admin/promotions_helper.rb
@@ -203,6 +210,12 @@ files:
203
210
  - app/models/solidus_promotions/promotion_handler/coupon.rb
204
211
  - app/models/solidus_promotions/promotion_handler/page.rb
205
212
  - app/models/solidus_promotions/shipping_rate_discount.rb
213
+ - app/patches/models/solidus_promotions/adjustment_patch.rb
214
+ - app/patches/models/solidus_promotions/line_item_patch.rb
215
+ - app/patches/models/solidus_promotions/order_patch.rb
216
+ - app/patches/models/solidus_promotions/order_recalculator_patch.rb
217
+ - app/patches/models/solidus_promotions/shipment_patch.rb
218
+ - app/patches/models/solidus_promotions/shipping_rate_patch.rb
206
219
  - app/subscribers/solidus_promotions/order_promotion_subscriber.rb
207
220
  - config/importmap.rb
208
221
  - config/locales/en.yml
@@ -233,7 +246,13 @@ files:
233
246
  - lib/components/admin/solidus_admin/orders/show/adjustments/index/source/solidus_promotions_benefit/component.rb
234
247
  - lib/components/admin/solidus_promotions/orders/index/component.rb
235
248
  - lib/components/admin/solidus_promotions/orders/index/component.yml
249
+ - lib/components/admin/solidus_promotions/promotion_categories/edit/component.html.erb
250
+ - lib/components/admin/solidus_promotions/promotion_categories/edit/component.rb
251
+ - lib/components/admin/solidus_promotions/promotion_categories/edit/component.yml
236
252
  - lib/components/admin/solidus_promotions/promotion_categories/index/component.rb
253
+ - lib/components/admin/solidus_promotions/promotion_categories/new/component.html.erb
254
+ - lib/components/admin/solidus_promotions/promotion_categories/new/component.rb
255
+ - lib/components/admin/solidus_promotions/promotion_categories/new/component.yml
237
256
  - lib/components/admin/solidus_promotions/promotions/index/component.rb
238
257
  - lib/components/admin/solidus_promotions/promotions/index/component.yml
239
258
  - lib/controllers/admin/solidus_promotions/promotion_categories_controller.rb
@@ -343,7 +362,6 @@ licenses:
343
362
  - BSD-3-Clause
344
363
  metadata:
345
364
  homepage_uri: https://github.com/solidusio/solidus/blob/main/promotions/README.md
346
- post_install_message:
347
365
  rdoc_options: []
348
366
  require_paths:
349
367
  - lib
@@ -358,8 +376,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
358
376
  - !ruby/object:Gem::Version
359
377
  version: '0'
360
378
  requirements: []
361
- rubygems_version: 3.5.22
362
- signing_key:
379
+ rubygems_version: 3.6.3
363
380
  specification_version: 4
364
381
  summary: New promotion system for Solidus
365
382
  test_files: []