solidus_promotions 4.4.1 → 4.5.0

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.
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: []