solidus_friendly_promotions 1.0.0.rc.1 → 1.0.0.rc.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +3 -3
  3. data/CHANGELOG.md +112 -0
  4. data/MIGRATING.md +7 -3
  5. data/README.md +12 -3
  6. data/app/controllers/solidus_friendly_promotions/admin/base_controller.rb +1 -1
  7. data/app/controllers/solidus_friendly_promotions/admin/promotion_rules_controller.rb +1 -1
  8. data/app/controllers/solidus_friendly_promotions/admin/promotions_controller.rb +1 -1
  9. data/app/decorators/models/solidus_friendly_promotions/line_item_decorator.rb +7 -1
  10. data/app/helpers/solidus_friendly_promotions/admin/promotion_rules_helper.rb +1 -1
  11. data/app/models/concerns/solidus_friendly_promotions/calculators/promotion_calculator.rb +11 -0
  12. data/app/models/concerns/solidus_friendly_promotions/rules/line_item_applicable_order_rule.rb +1 -1
  13. data/app/models/solidus_friendly_promotions/actions/adjust_line_item_quantity_groups.rb +1 -9
  14. data/app/models/solidus_friendly_promotions/actions/create_discounted_item.rb +16 -1
  15. data/app/models/solidus_friendly_promotions/calculators/distributed_amount.rb +3 -9
  16. data/app/models/solidus_friendly_promotions/calculators/flat_rate.rb +2 -0
  17. data/app/models/solidus_friendly_promotions/calculators/flexi_rate.rb +2 -0
  18. data/app/models/solidus_friendly_promotions/calculators/percent.rb +2 -0
  19. data/app/models/solidus_friendly_promotions/calculators/tiered_flat_rate.rb +2 -0
  20. data/app/models/solidus_friendly_promotions/calculators/tiered_percent.rb +2 -0
  21. data/app/models/solidus_friendly_promotions/calculators/tiered_percent_on_eligible_item_quantity.rb +36 -0
  22. data/app/models/solidus_friendly_promotions/friendly_promotion_adjuster.rb +2 -1
  23. data/app/models/solidus_friendly_promotions/promotion.rb +7 -1
  24. data/app/models/solidus_friendly_promotions/promotion_rule.rb +1 -1
  25. data/app/models/solidus_friendly_promotions/rules/minimum_quantity.rb +1 -7
  26. data/app/views/solidus_friendly_promotions/admin/promotion_actions/_promotion_action.html.erb +1 -1
  27. data/app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_calculator_fields.erb +1 -0
  28. data/app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_create_discounted_item.html.erb +4 -0
  29. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/distributed_amount/_fields.html.erb +1 -39
  30. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_flat_rate/_fields.html.erb +1 -1
  31. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_percent/_fields.html.erb +1 -1
  32. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_percent_on_eligible_item_quantity/_fields.html.erb +34 -0
  33. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_percent_on_eligible_item_quantity/_tier_fields.html.erb +27 -0
  34. data/app/views/solidus_friendly_promotions/admin/promotion_actions/new.html.erb +1 -1
  35. data/app/views/solidus_friendly_promotions/admin/promotions/_table.html.erb +56 -0
  36. data/app/views/solidus_friendly_promotions/admin/promotions/_table_filter.html.erb +69 -0
  37. data/app/views/solidus_friendly_promotions/admin/promotions/index.html.erb +2 -103
  38. data/app/views/solidus_friendly_promotions/admin/shared/_promotion_sub_menu.html.erb +2 -2
  39. data/config/locales/en.yml +57 -2
  40. data/lib/generators/solidus_friendly_promotions/install/templates/initializer.rb +9 -5
  41. data/lib/solidus_friendly_promotions/configuration.rb +2 -0
  42. data/lib/solidus_friendly_promotions/promotion_migrator.rb +1 -1
  43. data/lib/solidus_friendly_promotions/version.rb +1 -1
  44. data/lib/solidus_friendly_promotions.rb +1 -0
  45. data/solidus_friendly_promotions.gemspec +1 -0
  46. metadata +22 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ac98e07030bf9f63775dafdffc94d3a6be02b8050664037469f57a32dc71da43
4
- data.tar.gz: fdd1d7e3fbbfc92cb347af92c28c5f518d91724a330408a576d47449c6e8f201
3
+ metadata.gz: bb47848b0ee568a1116d827ac87f0071afd5790eff84d501860c0ed68eb37ac1
4
+ data.tar.gz: fd5c9d4ac486641ab72f87129cfbf7a7a44ea5b3c1a18970c479794f410dcd9f
5
5
  SHA512:
6
- metadata.gz: c9eb24c1fabf89ee0b61731b8541e1459dfe9d508ffc2721f8f1384df382c1653b94f407c04438a2047ebf0fc868e4849fc5f88b821ab141eac44b21bde910b9
7
- data.tar.gz: 1e89490f9daf5ad6480b37bc47581bb7ba4a948bb1af7aa7b9539b3c094c6549db4055132b53155e3fc419f881b71d64c81577ba447d188e704eda176bd5b808
6
+ metadata.gz: 71269bc48e02192efa3d41c83fe461bed7b3b0c8b1d123cfa555671ee5baea159f7e49521d203124ec1c23e2bedecc641e2a6b44ff5b18ad013438c2255fee50
7
+ data.tar.gz: 91b12062bff9c7324c9efdce8398ce6eac5ffd50b353848b1249c9a4146411b137c8354fee594861d03f490db9e4a05d0556f5bade2160596d04c56a7e3c452b
data/.circleci/config.yml CHANGED
@@ -21,7 +21,7 @@ jobs:
21
21
  - checkout
22
22
  - solidusio_extensions/dependencies
23
23
  - solidusio_extensions/run-tests-solidus-current
24
- - solidusio_extensions/run-tests-solidus-main
24
+ # - solidusio_extensions/run-tests-solidus-main
25
25
  run-specs-with-postgres:
26
26
  executor:
27
27
  name: solidusio_extensions/postgres
@@ -31,7 +31,7 @@ jobs:
31
31
  - checkout
32
32
  - solidusio_extensions/dependencies
33
33
  - solidusio_extensions/run-tests-solidus-current
34
- - solidusio_extensions/run-tests-solidus-main
34
+ # - solidusio_extensions/run-tests-solidus-main
35
35
  run-specs-with-sqlite:
36
36
  executor:
37
37
  name: solidusio_extensions/sqlite
@@ -41,7 +41,7 @@ jobs:
41
41
  - checkout
42
42
  - solidusio_extensions/dependencies
43
43
  - solidusio_extensions/run-tests-solidus-current
44
- - solidusio_extensions/run-tests-solidus-main
44
+ # - solidusio_extensions/run-tests-solidus-main
45
45
  workflows:
46
46
  Run specs on supported Solidus versions:
47
47
  jobs:
data/CHANGELOG.md CHANGED
@@ -1 +1,113 @@
1
1
  # Changelog
2
+
3
+ ## [Unreleased](https://github.com/FriendlyCart/solidus_friendly_promotions/tree/HEAD)
4
+
5
+ ## [v1.0.0.rc.2](https://github.com/FriendlyCart/solidus_friendly_promotions/tree/v1.0.0.rc.3) (2024-01-16)
6
+
7
+ **Merged pull requests:**
8
+
9
+ - Add configuration option: `recalculate_complete_orders` [\#97](https://github.com/friendlycart/solidus_friendly_promotions/pull/97) ([mamhoff](https://github.com/mamhoff))
10
+ - Fix standardrb violations [\#96](https://github.com/friendlycart/solidus_friendly_promotions/pull/96) ([mamhoff](https://github.com/mamhoff))
11
+ - Fix admin sub menu entry visibility condition [\#92](https://github.com/friendlycart/solidus_friendly_promotions/pull/92) ([mickenorlen](https://github.com/mickenorlen))
12
+ - Documentation fixes [\#91](https://github.com/friendlycart/solidus_friendly_promotions/pull/91) ([mamhoff](https://github.com/mamhoff))
13
+ - Fix typo [\#89](https://github.com/friendlycart/solidus_friendly_promotions/pull/89) ([jarednorman](https://github.com/jarednorman))
14
+ - Pass untranslated strings through i18n [\#88](https://github.com/friendlycart/solidus_friendly_promotions/pull/88) ([mamhoff](https://github.com/mamhoff))
15
+
16
+ ## [v1.0.0.rc.2](https://github.com/FriendlyCart/solidus_friendly_promotions/tree/v1.0.0.rc.2) (2023-11-11)
17
+
18
+ [Full Changelog](https://github.com/FriendlyCart/solidus_friendly_promotions/compare/v1.0.0.rc.1...v1.0.0.rc.2)
19
+
20
+ **Merged pull requests:**
21
+
22
+ - Refactor: Extract `Promotion#applicable_line_items` [\#86](https://github.com/friendlycart/solidus_friendly_promotions/pull/86) ([mamhoff](https://github.com/mamhoff))
23
+ - Coupon Promo Handler: Fix flaky spec [\#84](https://github.com/friendlycart/solidus_friendly_promotions/pull/84) ([mamhoff](https://github.com/mamhoff))
24
+ - Use Remix icons if Solidus' admin\_updated\_navbar is enabled [\#83](https://github.com/friendlycart/solidus_friendly_promotions/pull/83) ([tvdeyen](https://github.com/tvdeyen))
25
+ - Tiered calculators [\#82](https://github.com/friendlycart/solidus_friendly_promotions/pull/82) ([mamhoff](https://github.com/mamhoff))
26
+ - Allow changing quantity for automatic line items [\#81](https://github.com/friendlycart/solidus_friendly_promotions/pull/81) ([mamhoff](https://github.com/mamhoff))
27
+ - Update MIGRATING.md [\#80](https://github.com/friendlycart/solidus_friendly_promotions/pull/80) ([tvdeyen](https://github.com/tvdeyen))
28
+ - Promotions index improvements [\#79](https://github.com/friendlycart/solidus_friendly_promotions/pull/79) ([mamhoff](https://github.com/mamhoff))
29
+ - Lint: Fix standardrb error [\#78](https://github.com/friendlycart/solidus_friendly_promotions/pull/78) ([mamhoff](https://github.com/mamhoff))
30
+
31
+ ## [v1.0.0.rc.1](https://github.com/FriendlyCart/solidus_friendly_promotions/tree/v1.0.0.rc.1) (2023-11-07)
32
+
33
+ [Full Changelog](https://github.com/FriendlyCart/solidus_friendly_promotions/compare/v1.0.0.pre...v1.0.0.rc.1)
34
+
35
+ **Merged pull requests:**
36
+
37
+ - Goodies! [\#75](https://github.com/friendlycart/solidus_friendly_promotions/pull/75) ([mamhoff](https://github.com/mamhoff))
38
+ - Add a null promotion handler [\#71](https://github.com/friendlycart/solidus_friendly_promotions/pull/71) ([mamhoff](https://github.com/mamhoff))
39
+
40
+ ## [v1.0.0.pre](https://github.com/FriendlyCart/solidus_friendly_promotions/tree/v1.0.0.pre) (2023-11-07)
41
+
42
+ [Full Changelog](https://github.com/FriendlyCart/solidus_friendly_promotions/compare/e14802957fdb55d7f4e2730341e4cbb118ebf993...v1.0.0.pre)
43
+
44
+ **Merged pull requests:**
45
+
46
+ - Use new NestedClassSet for configuring calculators [\#77](https://github.com/friendlycart/solidus_friendly_promotions/pull/77) ([mamhoff](https://github.com/mamhoff))
47
+ - Refactor to FriendlyPromotion::FriendlyPromotionAdjuster [\#76](https://github.com/friendlycart/solidus_friendly_promotions/pull/76) ([mamhoff](https://github.com/mamhoff))
48
+ - Add bundler/gem\_tasks [\#74](https://github.com/friendlycart/solidus_friendly_promotions/pull/74) ([mamhoff](https://github.com/mamhoff))
49
+ - Fix order discounter spec [\#73](https://github.com/friendlycart/solidus_friendly_promotions/pull/73) ([mamhoff](https://github.com/mamhoff))
50
+ - Quantity tiered calculator [\#72](https://github.com/friendlycart/solidus_friendly_promotions/pull/72) ([mamhoff](https://github.com/mamhoff))
51
+ - Add PromotionHandler::Page [\#70](https://github.com/friendlycart/solidus_friendly_promotions/pull/70) ([mamhoff](https://github.com/mamhoff))
52
+ - Never create adjustments with a zero amount [\#69](https://github.com/friendlycart/solidus_friendly_promotions/pull/69) ([mamhoff](https://github.com/mamhoff))
53
+ - Ignore shipping rates that have no cost [\#68](https://github.com/friendlycart/solidus_friendly_promotions/pull/68) ([davecandlescience](https://github.com/davecandlescience))
54
+ - Refactor promotions eligibility [\#67](https://github.com/friendlycart/solidus_friendly_promotions/pull/67) ([mamhoff](https://github.com/mamhoff))
55
+ - Refactor order promotions migrator [\#66](https://github.com/friendlycart/solidus_friendly_promotions/pull/66) ([mamhoff](https://github.com/mamhoff))
56
+ - Add migrate order promotions rake task [\#65](https://github.com/friendlycart/solidus_friendly_promotions/pull/65) ([davecandlescience](https://github.com/davecandlescience))
57
+ - Add missing relation: SolidusFriendlyPromotions\#order\_promotions [\#64](https://github.com/friendlycart/solidus_friendly_promotions/pull/64) ([mamhoff](https://github.com/mamhoff))
58
+ - Promo Migrator: Ignore missing rules and actions [\#63](https://github.com/friendlycart/solidus_friendly_promotions/pull/63) ([mamhoff](https://github.com/mamhoff))
59
+ - Improve spec for product rule [\#62](https://github.com/friendlycart/solidus_friendly_promotions/pull/62) ([mamhoff](https://github.com/mamhoff))
60
+ - Do not call Spree::PromotionHandler::Shipping when SFP is active [\#61](https://github.com/friendlycart/solidus_friendly_promotions/pull/61) ([mamhoff](https://github.com/mamhoff))
61
+ - Add a migration guide [\#60](https://github.com/friendlycart/solidus_friendly_promotions/pull/60) ([mamhoff](https://github.com/mamhoff))
62
+ - Add a PromotionHandler::Coupon [\#59](https://github.com/friendlycart/solidus_friendly_promotions/pull/59) ([mamhoff](https://github.com/mamhoff))
63
+ - Backports minimum quantity promotion rule from Solidus [\#58](https://github.com/friendlycart/solidus_friendly_promotions/pull/58) ([mamhoff](https://github.com/mamhoff))
64
+ - Backport promotion code batch fix from Solidus [\#57](https://github.com/friendlycart/solidus_friendly_promotions/pull/57) ([mamhoff](https://github.com/mamhoff))
65
+ - Add a rake task to migrate adjustments from legacy promotions [\#56](https://github.com/friendlycart/solidus_friendly_promotions/pull/56) ([mamhoff](https://github.com/mamhoff))
66
+ - Add missing shipping\_rate translation [\#55](https://github.com/friendlycart/solidus_friendly_promotions/pull/55) ([davecandlescience](https://github.com/davecandlescience))
67
+ - Fix shipping rate discount factory [\#54](https://github.com/friendlycart/solidus_friendly_promotions/pull/54) ([mamhoff](https://github.com/mamhoff))
68
+ - Order Discounter: Create valid shipping rate discounts [\#53](https://github.com/friendlycart/solidus_friendly_promotions/pull/53) ([mamhoff](https://github.com/mamhoff))
69
+ - FriendlyPromotionDiscounter: Always return @order [\#52](https://github.com/friendlycart/solidus_friendly_promotions/pull/52) ([mamhoff](https://github.com/mamhoff))
70
+ - Line Item Product Rule: Add error messaging [\#50](https://github.com/friendlycart/solidus_friendly_promotions/pull/50) ([mamhoff](https://github.com/mamhoff))
71
+ - Fix: SolidusFriendlyPromotions, not Shipping [\#49](https://github.com/friendlycart/solidus_friendly_promotions/pull/49) ([mamhoff](https://github.com/mamhoff))
72
+ - Import eligiblity error messages from Solidus [\#48](https://github.com/friendlycart/solidus_friendly_promotions/pull/48) ([mamhoff](https://github.com/mamhoff))
73
+ - Faster promotion code migration [\#47](https://github.com/friendlycart/solidus_friendly_promotions/pull/47) ([mamhoff](https://github.com/mamhoff))
74
+ - Migrator: Store original promotion and promotion action [\#46](https://github.com/friendlycart/solidus_friendly_promotions/pull/46) ([mamhoff](https://github.com/mamhoff))
75
+ - Lint with standardrb in CI [\#45](https://github.com/friendlycart/solidus_friendly_promotions/pull/45) ([mamhoff](https://github.com/mamhoff))
76
+ - Migrator: Migrate promotion codes and promotion code batches [\#44](https://github.com/friendlycart/solidus_friendly_promotions/pull/44) ([mamhoff](https://github.com/mamhoff))
77
+ - Migrate promotion categories and association [\#43](https://github.com/friendlycart/solidus_friendly_promotions/pull/43) ([davecandlescience](https://github.com/davecandlescience))
78
+ - On the fly order promotions [\#42](https://github.com/friendlycart/solidus_friendly_promotions/pull/42) ([mamhoff](https://github.com/mamhoff))
79
+ - Add back references to promotions and actions [\#41](https://github.com/friendlycart/solidus_friendly_promotions/pull/41) ([davecandlescience](https://github.com/davecandlescience))
80
+ - Fix spec warning in promotion rules spec [\#40](https://github.com/friendlycart/solidus_friendly_promotions/pull/40) ([mamhoff](https://github.com/mamhoff))
81
+ - Transparently replace promotion adjustments [\#39](https://github.com/friendlycart/solidus_friendly_promotions/pull/39) ([mamhoff](https://github.com/mamhoff))
82
+ - Add DB comments to tables [\#38](https://github.com/friendlycart/solidus_friendly_promotions/pull/38) ([mamhoff](https://github.com/mamhoff))
83
+ - Fix Promotion Map [\#36](https://github.com/friendlycart/solidus_friendly_promotions/pull/36) ([mamhoff](https://github.com/mamhoff))
84
+ - Fix specs [\#29](https://github.com/friendlycart/solidus_friendly_promotions/pull/29) ([mamhoff](https://github.com/mamhoff))
85
+ - Add Promotion Migrator [\#28](https://github.com/friendlycart/solidus_friendly_promotions/pull/28) ([mamhoff](https://github.com/mamhoff))
86
+ - Polyvalent rules [\#27](https://github.com/friendlycart/solidus_friendly_promotions/pull/27) ([mamhoff](https://github.com/mamhoff))
87
+ - Fix Turbo frame tags for Turbo 1.5 [\#26](https://github.com/friendlycart/solidus_friendly_promotions/pull/26) ([mamhoff](https://github.com/mamhoff))
88
+ - Allow destroying promotions [\#25](https://github.com/friendlycart/solidus_friendly_promotions/pull/25) ([mamhoff](https://github.com/mamhoff))
89
+ - Fix class name option in line item taxon association [\#24](https://github.com/friendlycart/solidus_friendly_promotions/pull/24) ([mamhoff](https://github.com/mamhoff))
90
+ - Move factories to factories folder [\#23](https://github.com/friendlycart/solidus_friendly_promotions/pull/23) ([mamhoff](https://github.com/mamhoff))
91
+ - Add links to legacy promotions in Solidus 4.1 [\#22](https://github.com/friendlycart/solidus_friendly_promotions/pull/22) ([mamhoff](https://github.com/mamhoff))
92
+ - Make lanes configurable [\#21](https://github.com/friendlycart/solidus_friendly_promotions/pull/21) ([mamhoff](https://github.com/mamhoff))
93
+ - Allow order rules per lane [\#20](https://github.com/friendlycart/solidus_friendly_promotions/pull/20) ([mamhoff](https://github.com/mamhoff))
94
+ - Add PermissionSet for Friendly Promotions [\#19](https://github.com/friendlycart/solidus_friendly_promotions/pull/19) ([mamhoff](https://github.com/mamhoff))
95
+ - Add "only" match policy to product rule [\#18](https://github.com/friendlycart/solidus_friendly_promotions/pull/18) ([mamhoff](https://github.com/mamhoff))
96
+ - Require solidus [\#17](https://github.com/friendlycart/solidus_friendly_promotions/pull/17) ([mamhoff](https://github.com/mamhoff))
97
+ - Customer label [\#16](https://github.com/friendlycart/solidus_friendly_promotions/pull/16) ([mamhoff](https://github.com/mamhoff))
98
+ - System specs with turbo [\#15](https://github.com/friendlycart/solidus_friendly_promotions/pull/15) ([mamhoff](https://github.com/mamhoff))
99
+ - Reference our own I18n namespace in views [\#14](https://github.com/friendlycart/solidus_friendly_promotions/pull/14) ([mamhoff](https://github.com/mamhoff))
100
+ - Use different path for friendly promotions [\#13](https://github.com/friendlycart/solidus_friendly_promotions/pull/13) ([mamhoff](https://github.com/mamhoff))
101
+ - Add dependent: :destroy to Spree::Order\#friendly\_promotions [\#12](https://github.com/friendlycart/solidus_friendly_promotions/pull/12) ([mamhoff](https://github.com/mamhoff))
102
+ - Extract promotion loading from promo discounter [\#11](https://github.com/friendlycart/solidus_friendly_promotions/pull/11) ([mamhoff](https://github.com/mamhoff))
103
+ - Remove delegators [\#10](https://github.com/friendlycart/solidus_friendly_promotions/pull/10) ([mamhoff](https://github.com/mamhoff))
104
+ - Fix standardrb error in promotion rule spec [\#8](https://github.com/friendlycart/solidus_friendly_promotions/pull/8) ([mamhoff](https://github.com/mamhoff))
105
+ - Stacking Promotions [\#7](https://github.com/friendlycart/solidus_friendly_promotions/pull/7) ([mamhoff](https://github.com/mamhoff))
106
+ - Add "Lane" enum to Promotion [\#6](https://github.com/friendlycart/solidus_friendly_promotions/pull/6) ([mamhoff](https://github.com/mamhoff))
107
+ - Lint using standardrb gem [\#5](https://github.com/friendlycart/solidus_friendly_promotions/pull/5) ([mamhoff](https://github.com/mamhoff))
108
+ - Promotion Actions: Implement "edit" action [\#4](https://github.com/friendlycart/solidus_friendly_promotions/pull/4) ([mamhoff](https://github.com/mamhoff))
109
+ - Initializer: Use new MenuItem API from Solidus 4.2 onwards [\#3](https://github.com/friendlycart/solidus_friendly_promotions/pull/3) ([mamhoff](https://github.com/mamhoff))
110
+
111
+
112
+
113
+ \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
data/MIGRATING.md CHANGED
@@ -23,7 +23,7 @@ For the time being, comment out the following lines:
23
23
 
24
24
  ```rb
25
25
  # Spree::Config.order_contents_class = "SolidusFriendlyPromotions::SimpleOrderContents"
26
- # Spree::Config.promotion_adjuster_class = "SolidusFriendlyPromotions::OrderDiscounter"
26
+ # Spree::Config.promotion_adjuster_class = "SolidusFriendlyPromotions::FriendlyPromotionAdjuster"
27
27
  ```
28
28
 
29
29
  This makes sure that the behavior of the current promotion system does not change - yet.
@@ -46,7 +46,7 @@ Now, change `config/initializers/solidus_friendly_promotions.rb` to use your new
46
46
  # Stops running the stock `Spree::PromotionHandler::Cart`
47
47
  Spree::Config.order_contents_class = "SolidusFriendlyPromotions::SimpleOrderContents"
48
48
  # Adjusts all items in an order according to the currently eligible promotions
49
- Spree::Config.promotion_adjuster_class = "SolidusFriendlyPromotions::OrderDiscounter"
49
+ Spree::Config.promotion_adjuster_class = "SolidusFriendlyPromotions::FriendlyPromotionAdjuster"
50
50
  ```
51
51
 
52
52
  From a user's perspective, your promotions should work as before.
@@ -68,6 +68,10 @@ bundle exec rails solidus_friendly_promotions:migrate_order_promotions:down
68
68
 
69
69
  Both of these tasks only work if every promotion and promotion action have an equivalent in SolidusFrienndlyPromotions. Promotion Actions are connected to their originals using the `SolidusFriendlyPromotions#original_promotion_action_id`, Promotions are connected to their originals using the `SolidusFriendlyPromotions#original_promotion_id`.
70
70
 
71
+ ## Solidus Starter Frontend (and other custom frontends)
72
+
73
+ Stores that have a custom coupon codes controller, such as Solidus' starter frontend, have to change the coupon promotion handler to the one from this gem. If you are on a very recent Solidus version, you can change any reference to `Spree::PromotionHandler::Coupon` to `Spree::Config.coupon_code_handler_class`. If your version of Solidus does not have that method yet, replace `Spree::PromotionHandler::Coupon` with `SolidusFriendlyPromotions::PromotionHandler::Coupon`
74
+
71
75
  ## Migrating custom rules and actions
72
76
 
73
77
  If you have custom promotion rules or actions, you need to create new promotion rules and actions.
@@ -90,7 +94,7 @@ end
90
94
  would become:
91
95
 
92
96
  ```rb
93
- class MyNewRule < SolidusFriendlyShipping::PromotionRule
97
+ class MyNewRule < SolidusFriendlyPromotions::PromotionRule
94
98
  include LineItemLevelRule
95
99
  def eligible?(promotable)
96
100
  promotable.quantity > 3
data/README.md CHANGED
@@ -8,7 +8,7 @@ The basic architecture is very similar to the one in core Solidus, but with a fe
8
8
 
9
9
  ## Architecture
10
10
 
11
- This extension centralizes promotion handling in the order updater. A service class, the `SolidusFriendlyPromotions::OrderDiscounter` applies the current promotion configuration to the order, adjusting or removing adjustments as necessary.
11
+ This extension centralizes promotion handling in the order updater. A service class, the `SolidusFriendlyPromotions::FriendlyPromotionAdjuster` applies the current promotion configuration to the order, adjusting or removing adjustments as necessary.
12
12
 
13
13
  In Solidus Core, Promotion adjustments get recalculated twice on every change to the cart; once in `Spree::OrderContents#after_add_or_remove` and in `Spree::OrderUpdater#update_promotions`. To make things more complicated, `Spree::OrderContents` leverages the `Spree::PromotionHandler#cart`, while the order updater goes through `Spree::Adjustment#recalculate`.
14
14
 
@@ -51,13 +51,22 @@ One way of connecting orders to promotions is via a promotion code.
51
51
 
52
52
  Promotion categories simply allow admins to group promotion actions. They have no further significance with regards to the functionality of the promotion system. This is the same behavior as in core.
53
53
 
54
+ ### Promotion recalculation
55
+
56
+ Solidus allows changing orders up until when they are shipped. SolidusFriendlyPromotions therefore will recalculate orders up until when they are shipped as well. If your admins change promotions rather than add new ones and carefully manage the start and end dates of promotions, you might want to disable this feature:
57
+
58
+ ```rb
59
+ SolidusFriendlyPromotions.configure do |config|
60
+ config.recalculate_complete_orders = false
61
+ end
62
+ ```
54
63
 
55
64
  ## Installation
56
65
 
57
66
  Add solidus_friendly_promotions to your Gemfile:
58
67
 
59
68
  ```ruby
60
- gem 'solidus_friendly_promotions', github: 'friendlycart/solidus_friendly_promotion', branch: 'main'
69
+ gem 'solidus_friendly_promotions'
61
70
  ```
62
71
 
63
72
  Once this project is out of the research phase, a proper gem release will follow.
@@ -71,7 +80,7 @@ bin/rails generate solidus_friendly_promotions:install
71
80
  This will create the tables for this extension. It will also replace the promotion administration system under
72
81
  `/admin/promotions` with a new one that needs `turbo-rails`.
73
82
 
74
- It will also create an initializer within which Solidus is configured to use this extension's `SimpleOrderContents` and `OrderDiscounter` classes. Feel free to override with your own implementations!
83
+ It will also create an initializer within which Solidus is configured to use this extension's `SimpleOrderContents` and `FriendlyPromotionAdjuster` classes. Feel free to override with your own implementations!
75
84
 
76
85
  ## Usage
77
86
 
@@ -7,7 +7,7 @@ module SolidusFriendlyPromotions
7
7
  @parent ||= self.class.parent_data[:model_class]
8
8
  .includes(self.class.parent_data[:includes])
9
9
  .find_by!(self.class.parent_data[:find_by] => params["#{parent_model_name}_id"])
10
- instance_variable_set("@#{parent_model_name}", @parent)
10
+ instance_variable_set(:"@#{parent_model_name}", @parent)
11
11
  rescue ActiveRecord::RecordNotFound => e
12
12
  resource_not_found(flash_class: e.model.constantize, redirect_url: routes_proxy.polymorphic_url([:admin, parent_model_name.pluralize.to_sym]))
13
13
  end
@@ -63,7 +63,7 @@ module SolidusFriendlyPromotions
63
63
 
64
64
  def validate_promotion_rule_type
65
65
  requested_type = params[:promotion_rule].delete(:type)
66
- promotion_rule_types = SolidusFriendlyPromotions.config.send("#{@level}_rules")
66
+ promotion_rule_types = SolidusFriendlyPromotions.config.send(:"#{@level}_rules")
67
67
  @promotion_rule_type = promotion_rule_types.detect do |klass|
68
68
  klass.name == requested_type
69
69
  end
@@ -32,7 +32,7 @@ module SolidusFriendlyPromotions
32
32
  return @collection if @collection
33
33
 
34
34
  params[:q] ||= HashWithIndifferentAccess.new
35
- params[:q][:s] ||= "id desc"
35
+ params[:q][:s] ||= "updated_at desc"
36
36
 
37
37
  @collection = super
38
38
  @search = @collection.ransack(params[:q])
@@ -3,18 +3,24 @@
3
3
  module SolidusFriendlyPromotions
4
4
  module LineItemDecorator
5
5
  def self.prepended(base)
6
+ base.attr_accessor :quantity_setter
6
7
  base.belongs_to :managed_by_order_action, class_name: "SolidusFriendlyPromotions::PromotionAction", optional: true
7
8
  base.validate :validate_managed_quantity_same, on: :update
9
+ base.after_save :reset_quantity_setter
8
10
  end
9
11
 
10
12
  private
11
13
 
12
14
  def validate_managed_quantity_same
13
- if managed_by_order_action && quantity_changed?
15
+ if managed_by_order_action && quantity_changed? && quantity_setter != managed_by_order_action
14
16
  errors.add(:quantity, :cannot_be_changed_for_automated_items)
15
17
  end
16
18
  end
17
19
 
20
+ def reset_quantity_setter
21
+ @quantity_setter = nil
22
+ end
23
+
18
24
  Spree::LineItem.prepend self
19
25
  Spree::LineItem.prepend SolidusFriendlyPromotions::DiscountableAmount
20
26
  end
@@ -5,7 +5,7 @@ module SolidusFriendlyPromotions
5
5
  module PromotionRulesHelper
6
6
  def options_for_promotion_rule_types(promotion_rule, level)
7
7
  existing = promotion_rule.promotion.rules.select(&:persisted?).map { |rule| rule.class.name }
8
- rules = SolidusFriendlyPromotions.config.send("#{level}_rules").reject { |rule| existing.include? rule.name }
8
+ rules = SolidusFriendlyPromotions.config.send(:"#{level}_rules").reject { |rule| existing.include? rule.name }
9
9
  options = rules.map { |rule| [rule.model_name.human, rule.name] }
10
10
  options_for_select(options, promotion_rule.type.to_s)
11
11
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusFriendlyPromotions
4
+ module Calculators
5
+ module PromotionCalculator
6
+ def description
7
+ self.class.human_attribute_name(:description)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -12,7 +12,7 @@ module SolidusFriendlyPromotions
12
12
  end
13
13
 
14
14
  def eligible?(promotable)
15
- send("#{promotable.class.name.demodulize.underscore}_eligible?", promotable)
15
+ send(:"#{promotable.class.name.demodulize.underscore}_eligible?", promotable)
16
16
  end
17
17
 
18
18
  def level
@@ -58,7 +58,7 @@ module SolidusFriendlyPromotions
58
58
  adjustment_amount = adjustment_amount.abs
59
59
 
60
60
  order = line_item.order
61
- line_items = actionable_line_items(order)
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.discountable_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
@@ -6,9 +6,11 @@ module SolidusFriendlyPromotions
6
6
  include OrderLevelAction
7
7
  preference :variant_id, :integer
8
8
  preference :quantity, :integer, default: 1
9
+ preference :necessary_quantity, :integer, default: 1
9
10
 
10
11
  def perform(order)
11
12
  line_item = find_item(order) || create_item(order)
13
+ set_quantity(line_item, determine_item_quantity(order))
12
14
  line_item.current_discounts << discount(line_item)
13
15
  end
14
16
 
@@ -24,7 +26,20 @@ module SolidusFriendlyPromotions
24
26
  end
25
27
 
26
28
  def create_item(order)
27
- order.line_items.create!(quantity: preferred_quantity, variant: variant, managed_by_order_action: self)
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
28
43
  end
29
44
 
30
45
  def variant
@@ -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 = eligible_line_items(line_item.order)
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.discountable_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 Percent < Spree::Calculator
8
+ include PromotionCalculator
9
+
8
10
  preference :percent, :decimal, default: 0
9
11
 
10
12
  def compute(object)
@@ -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] }
@@ -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
@@ -13,7 +13,8 @@ module SolidusFriendlyPromotions
13
13
  def call
14
14
  order.reset_current_discounts
15
15
 
16
- return order if order.shipped?
16
+ return order if (!SolidusFriendlyPromotions.config.recalculate_complete_orders && order.complete?) || order.shipped?
17
+
17
18
  discounted_order = DiscountOrder.new(order, promotions, dry_run: dry_run).call
18
19
 
19
20
  PersistDiscountedOrder.new(discounted_order).call unless dry_run
@@ -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
@@ -49,7 +49,7 @@ module SolidusFriendlyPromotions
49
49
  end
50
50
 
51
51
  def eligibility_error_message(key, options = {})
52
- I18n.t(key, **{scope: [:solidus_friendly_promotions, :eligibility_errors, self.class.name.underscore]}.merge(options))
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 = order.line_items.select do |line_item|
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),
@@ -21,7 +21,7 @@
21
21
  <%= render 'solidus_friendly_promotions/admin/promotion_actions/form', form: form %>
22
22
  <div class="row">
23
23
  <div class="col-12">
24
- <%= button_tag "Update", class: "btn btn-secondary float-right" %>
24
+ <%= button_tag t(:update, scope: [:solidus_friendly_promotions, :crud]), class: "btn btn-secondary float-right" %>
25
25
  </div>
26
26
  </div>
27
27
  <% end %>
@@ -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 %>
@@ -5,6 +5,10 @@
5
5
  <%= form.label :preferred_quantity %>
6
6
  <%= form.number_field :preferred_quantity, class: "fullwidth" %>
7
7
  </div>
8
+ <div class="field">
9
+ <%= form.label :preferred_necessary_quantity %>
10
+ <%= form.number_field :preferred_necessary_quantity, class: "fullwidth" %>
11
+ </div>
8
12
  <% end %>
9
13
 
10
14
  <%= render(