solidus_friendly_promotions 1.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (214) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +61 -0
  3. data/.gem_release.yml +5 -0
  4. data/.github/stale.yml +1 -0
  5. data/.github_changelog_generator +2 -0
  6. data/.gitignore +21 -0
  7. data/.rspec +2 -0
  8. data/.rubocop.yml +29 -0
  9. data/.rubocop_todo.yml +157 -0
  10. data/.standard.yml +4 -0
  11. data/CHANGELOG.md +1 -0
  12. data/Gemfile +42 -0
  13. data/LICENSE +26 -0
  14. data/MIGRATING.md +134 -0
  15. data/README.md +144 -0
  16. data/Rakefile +7 -0
  17. data/app/assets/config/solidus_friendly_promotions/manifest.js +7 -0
  18. data/app/controllers/solidus_friendly_promotions/admin/base_controller.rb +54 -0
  19. data/app/controllers/solidus_friendly_promotions/admin/promotion_actions_controller.rb +103 -0
  20. data/app/controllers/solidus_friendly_promotions/admin/promotion_categories_controller.rb +13 -0
  21. data/app/controllers/solidus_friendly_promotions/admin/promotion_code_batches_controller.rb +30 -0
  22. data/app/controllers/solidus_friendly_promotions/admin/promotion_codes_controller.rb +58 -0
  23. data/app/controllers/solidus_friendly_promotions/admin/promotion_rules_controller.rb +105 -0
  24. data/app/controllers/solidus_friendly_promotions/admin/promotions_controller.rb +64 -0
  25. data/app/decorators/models/solidus_friendly_promotions/adjustment_decorator.rb +26 -0
  26. data/app/decorators/models/solidus_friendly_promotions/line_item_decorator.rb +7 -0
  27. data/app/decorators/models/solidus_friendly_promotions/order_decorator.rb +42 -0
  28. data/app/decorators/models/solidus_friendly_promotions/order_recalculator_decorator.rb +13 -0
  29. data/app/decorators/models/solidus_friendly_promotions/shipment_decorator.rb +14 -0
  30. data/app/decorators/models/solidus_friendly_promotions/shipping_rate_decorator.rb +29 -0
  31. data/app/helpers/solidus_friendly_promotions/admin/promotion_actions_helper.rb +23 -0
  32. data/app/helpers/solidus_friendly_promotions/admin/promotion_rules_helper.rb +25 -0
  33. data/app/javascript/solidus_friendly_promotions/controllers/application.js +9 -0
  34. data/app/javascript/solidus_friendly_promotions/controllers/calculator_tiers_controller.js +37 -0
  35. data/app/javascript/solidus_friendly_promotions/controllers/flash_controller.js +10 -0
  36. data/app/javascript/solidus_friendly_promotions/controllers/index.js +8 -0
  37. data/app/javascript/solidus_friendly_promotions/controllers/product_option_values_controller.js +62 -0
  38. data/app/javascript/solidus_friendly_promotions/jquery/option_value_picker.js +44 -0
  39. data/app/javascript/solidus_friendly_promotions.js +12 -0
  40. data/app/jobs/solidus_friendly_promotions/promotion_code_batch_job.rb +26 -0
  41. data/app/mailers/solidus_friendly_promotions/promotion_code_batch_mailer.rb +15 -0
  42. data/app/models/concerns/solidus_friendly_promotions/discountable_amount.rb +21 -0
  43. data/app/models/concerns/solidus_friendly_promotions/rules/line_item_applicable_order_rule.rb +23 -0
  44. data/app/models/concerns/solidus_friendly_promotions/rules/line_item_level_rule.rb +15 -0
  45. data/app/models/concerns/solidus_friendly_promotions/rules/order_level_rule.rb +15 -0
  46. data/app/models/concerns/solidus_friendly_promotions/rules/shipment_level_rule.rb +15 -0
  47. data/app/models/solidus_friendly_promotions/actions/adjust_line_item.rb +15 -0
  48. data/app/models/solidus_friendly_promotions/actions/adjust_line_item_quantity_groups.rb +116 -0
  49. data/app/models/solidus_friendly_promotions/actions/adjust_shipment.rb +15 -0
  50. data/app/models/solidus_friendly_promotions/calculators/distributed_amount.rb +37 -0
  51. data/app/models/solidus_friendly_promotions/calculators/flat_rate.rb +21 -0
  52. data/app/models/solidus_friendly_promotions/calculators/flexi_rate.rb +24 -0
  53. data/app/models/solidus_friendly_promotions/calculators/percent.rb +17 -0
  54. data/app/models/solidus_friendly_promotions/calculators/tiered_flat_rate.rb +56 -0
  55. data/app/models/solidus_friendly_promotions/calculators/tiered_percent.rb +66 -0
  56. data/app/models/solidus_friendly_promotions/distributed_amounts_handler.rb +43 -0
  57. data/app/models/solidus_friendly_promotions/eligibility_result.rb +5 -0
  58. data/app/models/solidus_friendly_promotions/eligibility_results.rb +48 -0
  59. data/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/choose_discounts.rb +21 -0
  60. data/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/discount_order.rb +76 -0
  61. data/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/load_promotions.rb +54 -0
  62. data/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/persist_discounted_order.rb +81 -0
  63. data/app/models/solidus_friendly_promotions/friendly_promotion_adjuster.rb +25 -0
  64. data/app/models/solidus_friendly_promotions/item_discount.rb +21 -0
  65. data/app/models/solidus_friendly_promotions/migration_support/order_promotion_syncer.rb +54 -0
  66. data/app/models/solidus_friendly_promotions/order_promotion.rb +23 -0
  67. data/app/models/solidus_friendly_promotions/permission_sets/friendly_promotion_management.rb +15 -0
  68. data/app/models/solidus_friendly_promotions/products_promotion_rule.rb +8 -0
  69. data/app/models/solidus_friendly_promotions/promotion.rb +166 -0
  70. data/app/models/solidus_friendly_promotions/promotion_action.rb +73 -0
  71. data/app/models/solidus_friendly_promotions/promotion_category.rb +9 -0
  72. data/app/models/solidus_friendly_promotions/promotion_code/batch_builder.rb +72 -0
  73. data/app/models/solidus_friendly_promotions/promotion_code.rb +55 -0
  74. data/app/models/solidus_friendly_promotions/promotion_code_batch.rb +25 -0
  75. data/app/models/solidus_friendly_promotions/promotion_handler/coupon.rb +113 -0
  76. data/app/models/solidus_friendly_promotions/promotion_handler/page.rb +30 -0
  77. data/app/models/solidus_friendly_promotions/promotion_rule.rb +55 -0
  78. data/app/models/solidus_friendly_promotions/promotion_rules_store.rb +8 -0
  79. data/app/models/solidus_friendly_promotions/promotion_rules_taxon.rb +8 -0
  80. data/app/models/solidus_friendly_promotions/promotion_rules_user.rb +8 -0
  81. data/app/models/solidus_friendly_promotions/rules/discounted_item_total.rb +22 -0
  82. data/app/models/solidus_friendly_promotions/rules/first_order.rb +31 -0
  83. data/app/models/solidus_friendly_promotions/rules/first_repeat_purchase_since.rb +31 -0
  84. data/app/models/solidus_friendly_promotions/rules/item_total.rb +86 -0
  85. data/app/models/solidus_friendly_promotions/rules/line_item_option_value.rb +37 -0
  86. data/app/models/solidus_friendly_promotions/rules/line_item_product.rb +52 -0
  87. data/app/models/solidus_friendly_promotions/rules/line_item_taxon.rb +55 -0
  88. data/app/models/solidus_friendly_promotions/rules/minimum_quantity.rb +48 -0
  89. data/app/models/solidus_friendly_promotions/rules/nth_order.rb +40 -0
  90. data/app/models/solidus_friendly_promotions/rules/one_use_per_user.rb +25 -0
  91. data/app/models/solidus_friendly_promotions/rules/option_value.rb +28 -0
  92. data/app/models/solidus_friendly_promotions/rules/product.rb +85 -0
  93. data/app/models/solidus_friendly_promotions/rules/shipping_method.rb +19 -0
  94. data/app/models/solidus_friendly_promotions/rules/store.rb +26 -0
  95. data/app/models/solidus_friendly_promotions/rules/taxon.rb +98 -0
  96. data/app/models/solidus_friendly_promotions/rules/user.rb +35 -0
  97. data/app/models/solidus_friendly_promotions/rules/user_logged_in.rb +16 -0
  98. data/app/models/solidus_friendly_promotions/rules/user_role.rb +42 -0
  99. data/app/models/solidus_friendly_promotions/shipping_rate_discount.rb +11 -0
  100. data/app/models/solidus_friendly_promotions/simple_order_contents.rb +27 -0
  101. data/app/models/solidus_friendly_promotions.rb +7 -0
  102. data/app/views/solidus_friendly_promotions/admin/promotion_actions/_calculator_select.html.erb +16 -0
  103. data/app/views/solidus_friendly_promotions/admin/promotion_actions/_form.html.erb +3 -0
  104. data/app/views/solidus_friendly_promotions/admin/promotion_actions/_promotion_action.html.erb +29 -0
  105. data/app/views/solidus_friendly_promotions/admin/promotion_actions/_type_select.html.erb +14 -0
  106. data/app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_adjust_line_item.html.erb +6 -0
  107. data/app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_adjust_line_item_quantity_groups.html.erb +13 -0
  108. data/app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_adjust_shipment.html.erb +6 -0
  109. data/app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_calculator_fields.erb +8 -0
  110. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/_default_fields.html.erb +6 -0
  111. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/distributed_amount/_fields.html.erb +56 -0
  112. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/flat_rate/_fields.html.erb +6 -0
  113. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_flat_rate/_fields.html.erb +34 -0
  114. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_flat_rate/_tier_fields.html.erb +32 -0
  115. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_percent/_fields.html.erb +34 -0
  116. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_percent/_tier_fields.html.erb +32 -0
  117. data/app/views/solidus_friendly_promotions/admin/promotion_actions/edit.html.erb +23 -0
  118. data/app/views/solidus_friendly_promotions/admin/promotion_actions/new.html.erb +26 -0
  119. data/app/views/solidus_friendly_promotions/admin/promotion_categories/_form.html.erb +14 -0
  120. data/app/views/solidus_friendly_promotions/admin/promotion_categories/edit.html.erb +10 -0
  121. data/app/views/solidus_friendly_promotions/admin/promotion_categories/index.html.erb +47 -0
  122. data/app/views/solidus_friendly_promotions/admin/promotion_categories/new.html.erb +10 -0
  123. data/app/views/solidus_friendly_promotions/admin/promotion_codes/index.csv.ruby +8 -0
  124. data/app/views/solidus_friendly_promotions/admin/promotion_codes/index.html.erb +32 -0
  125. data/app/views/solidus_friendly_promotions/admin/promotion_codes/new.html.erb +31 -0
  126. data/app/views/solidus_friendly_promotions/admin/promotion_rules/_promotion_rule.html.erb +22 -0
  127. data/app/views/solidus_friendly_promotions/admin/promotion_rules/_type_select.html.erb +20 -0
  128. data/app/views/solidus_friendly_promotions/admin/promotion_rules/new.html.erb +24 -0
  129. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_first_order.html.erb +3 -0
  130. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_first_repeat_purchase_since.html.erb +6 -0
  131. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_item_total.html.erb +17 -0
  132. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_line_item_option_value.html.erb +25 -0
  133. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_line_item_product.html.erb +21 -0
  134. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_line_item_taxon.html.erb +17 -0
  135. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_minimum_quantity.html.erb +5 -0
  136. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_nth_order.html.erb +15 -0
  137. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_one_use_per_user.html.erb +3 -0
  138. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_option_value.html.erb +63 -0
  139. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_product.html.erb +44 -0
  140. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_shipping_method.html.erb +10 -0
  141. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_store.html.erb +9 -0
  142. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_taxon.html.erb +44 -0
  143. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_user.html.erb +7 -0
  144. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_user_logged_in.html.erb +3 -0
  145. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_user_role.html.erb +15 -0
  146. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/line_item_option_value/_option_value_fields.html.erb +17 -0
  147. data/app/views/solidus_friendly_promotions/admin/promotions/_activations_edit.html.erb +22 -0
  148. data/app/views/solidus_friendly_promotions/admin/promotions/_activations_new.html.erb +43 -0
  149. data/app/views/solidus_friendly_promotions/admin/promotions/_form.html.erb +96 -0
  150. data/app/views/solidus_friendly_promotions/admin/promotions/edit.html.erb +73 -0
  151. data/app/views/solidus_friendly_promotions/admin/promotions/index.html.erb +124 -0
  152. data/app/views/solidus_friendly_promotions/admin/promotions/new.html.erb +9 -0
  153. data/app/views/solidus_friendly_promotions/admin/shared/_promotion_sub_menu.html.erb +14 -0
  154. data/app/views/solidus_friendly_promotions/promotion_code_batch_mailer/promotion_code_batch_errored.text.erb +2 -0
  155. data/app/views/solidus_friendly_promotions/promotion_code_batch_mailer/promotion_code_batch_finished.text.erb +2 -0
  156. data/bin/console +17 -0
  157. data/bin/importmap +4 -0
  158. data/bin/rails +7 -0
  159. data/bin/rails-engine +13 -0
  160. data/bin/rails-sandbox +16 -0
  161. data/bin/rake +7 -0
  162. data/bin/sandbox +75 -0
  163. data/bin/setup +8 -0
  164. data/config/importmap.rb +12 -0
  165. data/config/initializers/solidus_friendly_promotions.rb +3 -0
  166. data/config/locales/en.yml +255 -0
  167. data/config/routes.rb +18 -0
  168. data/db/migrate/20230703101637_create_promotions.rb +16 -0
  169. data/db/migrate/20230703141116_create_promotion_categories.rb +14 -0
  170. data/db/migrate/20230703143943_create_promotion_rules.rb +12 -0
  171. data/db/migrate/20230704083830_add_rule_tables.rb +31 -0
  172. data/db/migrate/20230704093625_create_promotion_actions.rb +14 -0
  173. data/db/migrate/20230704102444_create_promotion_codes.rb +11 -0
  174. data/db/migrate/20230704102656_create_promotion_code_batches.rb +33 -0
  175. data/db/migrate/20230705171556_create_friendly_order_promotions.rb +11 -0
  176. data/db/migrate/20230725074235_create_shipping_rate_discounts.rb +12 -0
  177. data/db/migrate/20230928093138_add_lane_to_solidus_friendly_promotions_promotions.rb +5 -0
  178. data/db/migrate/20231006134042_add_customer_label_to_promotions.rb +7 -0
  179. data/db/migrate/20231011100059_add_db_comments_to_friendly_order_promotions.rb +61 -0
  180. data/db/migrate/20231011120928_add_db_comments_to_friendly_promotion_rules_taxons.rb +54 -0
  181. data/db/migrate/20231011131324_add_db_comments_to_friendly_promotion_rules.rb +60 -0
  182. data/db/migrate/20231011142040_add_db_comments_to_friendly_promotion_rules_users.rb +53 -0
  183. data/db/migrate/20231011154553_allow_null_promotion_ids.rb +9 -0
  184. data/db/migrate/20231011155822_add_db_comments_to_friendly_promotions.rb +123 -0
  185. data/db/migrate/20231011163030_add_db_comments_to_friendly_promotion_codes.rb +60 -0
  186. data/db/migrate/20231011173312_add_db_comments_to_friendly_promotion_code_batches.rb +91 -0
  187. data/db/migrate/20231011184205_add_db_comments_to_friendly_promotion_rules_stores.rb +53 -0
  188. data/db/migrate/20231011190222_add_db_comments_to_friendly_promotion_actions.rb +68 -0
  189. data/db/migrate/20231012020928_add_db_comments_to_friendly_products_promotion_rules.rb +52 -0
  190. data/db/migrate/20231012120928_add_db_comments_to_friendly_promotion_categories.rb +52 -0
  191. data/db/migrate/20231013181921_add_original_promotion_ids.rb +6 -0
  192. data/lib/generators/solidus_friendly_promotions/install/install_generator.rb +38 -0
  193. data/lib/generators/solidus_friendly_promotions/install/templates/initializer.rb +118 -0
  194. data/lib/solidus_friendly_promotions/configuration.rb +52 -0
  195. data/lib/solidus_friendly_promotions/engine.rb +37 -0
  196. data/lib/solidus_friendly_promotions/migrate_adjustments.rb +62 -0
  197. data/lib/solidus_friendly_promotions/migrate_order_promotions.rb +73 -0
  198. data/lib/solidus_friendly_promotions/nested_class_set.rb +24 -0
  199. data/lib/solidus_friendly_promotions/promotion_map.rb +96 -0
  200. data/lib/solidus_friendly_promotions/promotion_migrator.rb +103 -0
  201. data/lib/solidus_friendly_promotions/testing_support/factories/friendly_order_factory.rb +20 -0
  202. data/lib/solidus_friendly_promotions/testing_support/factories/friendly_order_promotion_factory.rb +8 -0
  203. data/lib/solidus_friendly_promotions/testing_support/factories/friendly_promotion_category_factory.rb +7 -0
  204. data/lib/solidus_friendly_promotions/testing_support/factories/friendly_promotion_code_factory.rb +8 -0
  205. data/lib/solidus_friendly_promotions/testing_support/factories/friendly_promotion_factory.rb +91 -0
  206. data/lib/solidus_friendly_promotions/testing_support/factories/friendly_shipping_rate_discount_factory.rb +14 -0
  207. data/lib/solidus_friendly_promotions/testing_support.rb +9 -0
  208. data/lib/solidus_friendly_promotions/version.rb +5 -0
  209. data/lib/solidus_friendly_promotions.rb +18 -0
  210. data/lib/tasks/solidus_friendly_promotions/migrate_adjustments.rake +17 -0
  211. data/lib/tasks/solidus_friendly_promotions/migrate_existing_promotions.rake +12 -0
  212. data/lib/tasks/solidus_friendly_promotions/migrate_order_promotions.rake +17 -0
  213. data/solidus_friendly_promotions.gemspec +40 -0
  214. metadata +392 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: '042911d4cf39c2bddcce9c5826f8c8f790e2ca8396cc32d339c7f5c2dea0a834'
4
+ data.tar.gz: cf2a4ee16b1d40a6d89771de93b37b145bfce413aab7114a0660cdf0c5798d27
5
+ SHA512:
6
+ metadata.gz: 5ffa465ffa65e01a30adae44873edabe2fa25594b7c3c09beda6e0e2946ed4e8fdbec547dafc4d22974bbeddb0a978a96c65c5c83f3b300d4e9b0473dc809f23
7
+ data.tar.gz: 601306df6e5de918612d12ed6084d2a6ea2b690d15ef13ff36d826a541dc19dabaf84b62ea74c0065f106baf256089df544e9814fe3ddcc4da5635ffc8e74c60
@@ -0,0 +1,61 @@
1
+ version: '2.1'
2
+ orbs:
3
+ browser-tools: circleci/browser-tools@1.1
4
+ solidusio_extensions: solidusio/extensions@volatile
5
+ jobs:
6
+ lint:
7
+ executor:
8
+ name: solidusio_extensions/sqlite-memory
9
+ ruby_version: '3.0'
10
+ steps:
11
+ - checkout
12
+ - solidusio_extensions/test-branch:
13
+ command: bundle exec standardrb
14
+ command_verb: Check code style
15
+ run-specs-with-mysql:
16
+ executor:
17
+ name: solidusio_extensions/mysql
18
+ ruby_version: '3.1'
19
+ steps:
20
+ - browser-tools/install-chrome
21
+ - checkout
22
+ - solidusio_extensions/dependencies
23
+ - solidusio_extensions/run-tests-solidus-current
24
+ - solidusio_extensions/run-tests-solidus-main
25
+ run-specs-with-postgres:
26
+ executor:
27
+ name: solidusio_extensions/postgres
28
+ ruby_version: '3.2'
29
+ steps:
30
+ - browser-tools/install-chrome
31
+ - checkout
32
+ - solidusio_extensions/dependencies
33
+ - solidusio_extensions/run-tests-solidus-current
34
+ - solidusio_extensions/run-tests-solidus-main
35
+ run-specs-with-sqlite:
36
+ executor:
37
+ name: solidusio_extensions/sqlite
38
+ ruby_version: '3.0'
39
+ steps:
40
+ - browser-tools/install-chrome
41
+ - checkout
42
+ - solidusio_extensions/dependencies
43
+ - solidusio_extensions/run-tests-solidus-current
44
+ - solidusio_extensions/run-tests-solidus-main
45
+ workflows:
46
+ Run specs on supported Solidus versions:
47
+ jobs:
48
+ - lint
49
+ - run-specs-with-postgres
50
+ - run-specs-with-mysql
51
+ - run-specs-with-sqlite
52
+ Weekly run specs against main:
53
+ jobs:
54
+ - run-specs-with-sqlite
55
+ triggers:
56
+ - schedule:
57
+ cron: 0 0 * * 4
58
+ filters:
59
+ branches:
60
+ only:
61
+ - main
data/.gem_release.yml ADDED
@@ -0,0 +1,5 @@
1
+ bump:
2
+ recurse: false
3
+ file: 'lib/solidus_friendly_promotions/version.rb'
4
+ message: Bump SolidusFriendlyPromotions to %{version}
5
+ tag: true
data/.github/stale.yml ADDED
@@ -0,0 +1 @@
1
+ _extends: .github
@@ -0,0 +1,2 @@
1
+ issues=false
2
+ exclude-labels=infrastructure
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ \#*
3
+ *~
4
+ .#*
5
+ .DS_Store
6
+ .idea
7
+ .project
8
+ .sass-cache
9
+ coverage
10
+ Gemfile.lock
11
+ Gemfile-local
12
+ tmp
13
+ nbproject
14
+ pkg
15
+ *.swp
16
+ spec/dummy
17
+ spec/examples.txt
18
+ /sandbox
19
+ .rvmrc
20
+ .ruby-version
21
+ .ruby-gemset
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,29 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ require:
4
+ - solidus_dev_support/rubocop
5
+
6
+ AllCops:
7
+ NewCops: disable
8
+
9
+
10
+ RSpec/MultipleExpectations:
11
+ Max: 10
12
+
13
+ RSpec/MultipleMemoizedHelpers:
14
+ Max: 12
15
+
16
+ RSpec/NamedSubject:
17
+ Enabled: false
18
+
19
+ RSpec/MessageSpies:
20
+ Enabled: false
21
+
22
+ RSpec/ContextWording:
23
+ Enabled: false
24
+
25
+ RSpec/NestedGroups:
26
+ Max: 5
27
+
28
+ RSpec/LetSetup:
29
+ Enabled: false
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,157 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config --exclude-limit 10000`
3
+ # on 2023-07-25 15:26:43 UTC using RuboCop version 1.54.1.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 2
10
+ # Configuration parameters: AllowedMethods.
11
+ # AllowedMethods: enums
12
+ Lint/ConstantDefinitionInBlock:
13
+ Exclude:
14
+ - 'spec/models/solidus_friendly_promotions/promotion_rule_spec.rb'
15
+
16
+ # Offense count: 1
17
+ Lint/DuplicateMethods:
18
+ Exclude:
19
+ - 'app/models/solidus_friendly_promotions/promotion.rb'
20
+
21
+ # Offense count: 1
22
+ # This cop supports safe autocorrection (--autocorrect).
23
+ Lint/RedundantCopDisableDirective:
24
+ Exclude:
25
+ - 'lib/generators/solidus_friendly_promotions/install/install_generator.rb'
26
+
27
+ # Offense count: 8
28
+ # Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
29
+ # SupportedStyles: snake_case, normalcase, non_integer
30
+ # AllowedIdentifiers: capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64
31
+ Naming/VariableNumber:
32
+ Exclude:
33
+ - 'spec/models/solidus_friendly_promotions/rules/first_repeat_purchase_since_spec.rb'
34
+
35
+ # Offense count: 1
36
+ RSpec/AnyInstance:
37
+ Exclude:
38
+ - 'spec/jobs/solidus_friendly_promotions/promotion_code_batch_job_spec.rb'
39
+
40
+ # Offense count: 2
41
+ # Configuration parameters: IgnoredMetadata.
42
+ RSpec/DescribeClass:
43
+ Exclude:
44
+ - 'spec/lib/solidus_friendly_promotions/testing_support/factories_spec.rb'
45
+ - 'spec/models/promotion/integration_spec.rb'
46
+
47
+ # Offense count: 2
48
+ RSpec/ExpectInHook:
49
+ Exclude:
50
+ - 'spec/jobs/solidus_friendly_promotions/promotion_code_batch_job_spec.rb'
51
+ - 'spec/models/solidus_friendly_promotions/promotion_code/batch_builder_spec.rb'
52
+
53
+ # Offense count: 7
54
+ # Configuration parameters: AssignmentOnly.
55
+ RSpec/InstanceVariable:
56
+ Exclude:
57
+ - 'spec/models/solidus_friendly_promotions/promotion_spec.rb'
58
+
59
+ # Offense count: 2
60
+ RSpec/IteratedExpectation:
61
+ Exclude:
62
+ - 'spec/jobs/solidus_friendly_promotions/promotion_code_batch_job_spec.rb'
63
+
64
+ # Offense count: 2
65
+ RSpec/LeakyConstantDeclaration:
66
+ Exclude:
67
+ - 'spec/models/solidus_friendly_promotions/promotion_rule_spec.rb'
68
+
69
+ # Offense count: 3
70
+ RSpec/MessageChain:
71
+ Exclude:
72
+ - 'spec/models/solidus_friendly_promotions/rules/first_order_spec.rb'
73
+
74
+ # Offense count: 4
75
+ # Configuration parameters: AllowSubject.
76
+ RSpec/MultipleMemoizedHelpers:
77
+ Max: 12
78
+
79
+ # Offense count: 1
80
+ RSpec/OverwritingSetup:
81
+ Exclude:
82
+ - 'spec/models/solidus_friendly_promotions/calculators/flexi_rate_spec.rb'
83
+
84
+ # Offense count: 2
85
+ RSpec/RepeatedExampleGroupBody:
86
+ Exclude:
87
+ - 'spec/lib/solidus_friendly_promotions/configuration_spec.rb'
88
+
89
+ # Offense count: 2
90
+ RSpec/RepeatedExampleGroupDescription:
91
+ Exclude:
92
+ - 'spec/models/solidus_friendly_promotions/calculators/flat_rate_spec.rb'
93
+
94
+ # Offense count: 1
95
+ RSpec/SubjectStub:
96
+ Exclude:
97
+ - 'spec/models/solidus_friendly_promotions/promotion_code/batch_builder_spec.rb'
98
+
99
+ # Offense count: 2
100
+ # Configuration parameters: IgnoreNameless, IgnoreSymbolicNames.
101
+ RSpec/VerifiedDoubles:
102
+ Exclude:
103
+ - 'spec/models/solidus_friendly_promotions/calculators/percent_spec.rb'
104
+
105
+ # Offense count: 1
106
+ # Configuration parameters: Include.
107
+ # Include: db/**/*.rb
108
+ Rails/CreateTableWithTimestamps:
109
+ Exclude:
110
+ - 'db/migrate/20230725074235_create_shipping_rate_discounts.rb'
111
+
112
+ # Offense count: 7
113
+ # Configuration parameters: Include.
114
+ # Include: app/models/**/*.rb
115
+ Rails/HasManyOrHasOneDependent:
116
+ Exclude:
117
+ - 'app/models/solidus_friendly_promotions/promotion.rb'
118
+ - 'app/models/solidus_friendly_promotions/promotion_action.rb'
119
+ - 'app/models/solidus_friendly_promotions/promotion_category.rb'
120
+ - 'app/models/solidus_friendly_promotions/promotion_code.rb'
121
+
122
+ # Offense count: 7
123
+ # Configuration parameters: IgnoreScopes, Include.
124
+ # Include: app/models/**/*.rb
125
+ Rails/InverseOf:
126
+ Exclude:
127
+ - 'app/models/solidus_friendly_promotions/promotion.rb'
128
+ - 'app/models/solidus_friendly_promotions/rules/line_item_product.rb'
129
+ - 'app/models/solidus_friendly_promotions/rules/line_item_taxon.rb'
130
+ - 'app/models/solidus_friendly_promotions/rules/product.rb'
131
+ - 'app/models/solidus_friendly_promotions/rules/store.rb'
132
+ - 'app/models/solidus_friendly_promotions/rules/taxon.rb'
133
+ - 'app/models/solidus_friendly_promotions/rules/user.rb'
134
+
135
+ # Offense count: 2
136
+ # This cop supports unsafe autocorrection (--autocorrect-all).
137
+ Rails/ReflectionClassName:
138
+ Exclude:
139
+ - 'app/models/solidus_friendly_promotions/promotion_rules_user.rb'
140
+ - 'app/models/solidus_friendly_promotions/rules/user.rb'
141
+
142
+ # Offense count: 9
143
+ # Configuration parameters: ForbiddenMethods, AllowedMethods.
144
+ # ForbiddenMethods: decrement!, decrement_counter, increment!, increment_counter, insert, insert!, insert_all, insert_all!, toggle!, touch, touch_all, update_all, update_attribute, update_column, update_columns, update_counters, upsert, upsert_all
145
+ Rails/SkipsModelValidations:
146
+ Exclude:
147
+ - 'lib/solidus_friendly_promotions/testing_support/friendly_order_factory.rb'
148
+ - 'spec/models/solidus_friendly_promotions/promotion_code_batch_spec.rb'
149
+ - 'spec/models/solidus_friendly_promotions/promotion_code_spec.rb'
150
+ - 'spec/models/solidus_friendly_promotions/promotion_spec.rb'
151
+
152
+ # Offense count: 5
153
+ # This cop supports safe autocorrection (--autocorrect).
154
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
155
+ # URISchemes: http, https
156
+ Layout/LineLength:
157
+ Max: 148
data/.standard.yml ADDED
@@ -0,0 +1,4 @@
1
+ ruby_version: 3.0
2
+ ignore:
3
+ - 'sandbox/**/*'
4
+ - 'spec/dummy/**/*'
data/CHANGELOG.md ADDED
@@ -0,0 +1 @@
1
+ # Changelog
data/Gemfile ADDED
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
5
+
6
+ branch = ENV.fetch("SOLIDUS_BRANCH", "main")
7
+ gem "solidus", github: "solidusio/solidus", branch: branch
8
+
9
+ # The solidus_frontend gem has been pulled out since v3.2
10
+ gem "solidus_frontend", github: "solidusio/solidus_frontend" if branch == "master"
11
+ gem "solidus_frontend" if branch >= "v3.2" # rubocop:disable Bundler/DuplicatedGem
12
+
13
+ # Needed to help Bundler figure out how to resolve dependencies,
14
+ # otherwise it takes forever to resolve them.
15
+ # See https://github.com/bundler/bundler/issues/6677
16
+ gem "rails", ">0.a"
17
+
18
+ # Provides basic authentication functionality for testing parts of your engine
19
+ gem "solidus_auth_devise"
20
+
21
+ case ENV.fetch("DB", nil)
22
+ when "mysql"
23
+ gem "mysql2"
24
+ when "postgresql"
25
+ gem "pg"
26
+ else
27
+ gem "sqlite3"
28
+ end
29
+
30
+ # While we still support Ruby < 3 we need to workaround a limitation in
31
+ # the 'async' gem that relies on the latest ruby, since RubyGems doesn't
32
+ # resolve gems based on the required ruby version.
33
+ gem "async", "< 3" if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3")
34
+
35
+ gemspec
36
+
37
+ # Use a local Gemfile to include development dependencies that might not be
38
+ # relevant for the project or for other contributors, e.g. pry-byebug.
39
+ #
40
+ # We use `send` instead of calling `eval_gemfile` to work around an issue with
41
+ # how Dependabot parses projects: https://github.com/dependabot/dependabot-core/issues/1658.
42
+ send(:eval_gemfile, "Gemfile-local") if File.exist? "Gemfile-local"
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2023 Martin Meyerhoff
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ * Neither the name Solidus nor the names of its contributors may be used to
13
+ endorse or promote products derived from this software without specific
14
+ prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/MIGRATING.md ADDED
@@ -0,0 +1,134 @@
1
+ # Migrating from Solidus' promotion system to SolidusFriendlyPromotions
2
+
3
+ The system is designed to completely replace the Solidus promotion system. Follow these steps to migrate your store to the gem:
4
+
5
+ ## Install solidus_friendly_promotions
6
+
7
+ Add the following line to your `Gemfile`:
8
+
9
+ ```rb
10
+ gem "solidus_friendly_promotions"
11
+ ```
12
+
13
+ Then run
14
+
15
+ ```sh
16
+ bundle install
17
+ bundle exec rails generate solidus_friendly_promotions:install
18
+ ```
19
+
20
+ This will install the extension. It will add new tables, and new routes. It will also generate an initializer in `config/initializers/solidus_friendly_promotions.rb`.
21
+
22
+ For the time being, comment out the following lines:
23
+
24
+ ```rb
25
+ # Spree::Config.order_contents_class = "SolidusFriendlyPromotions::SimpleOrderContents"
26
+ # Spree::Config.promotion_adjuster_class = "SolidusFriendlyPromotions::OrderDiscounter"
27
+ ```
28
+
29
+ This makes sure that the behavior of the current promotion system does not change - yet.
30
+
31
+ ## Migrate existing promotions
32
+
33
+ Now, run the promotion migrator:
34
+
35
+ ```sh
36
+ bundle exec rails solidus_friendly_promotions:migrate_existing_promotions
37
+ ```
38
+
39
+ This will create equivalents of the legacy promotion configuration in SolidusFriendlyPromotions.
40
+
41
+ Now, change `config/initializers/solidus_friendly_promotions.rb` to use your new promotion configuration:
42
+
43
+ ## Change store behavior to use SolidusFriendlyPromotions
44
+
45
+ ```rb
46
+ # Stops running the stock `Spree::PromotionHandler::Cart`
47
+ Spree::Config.order_contents_class = "SolidusFriendlyPromotions::SimpleOrderContents"
48
+ # Adjusts all items in an order according to the currently eligible promotions
49
+ Spree::Config.promotion_adjuster_class = "SolidusFriendlyPromotions::OrderDiscounter"
50
+ ```
51
+
52
+ From a user's perspective, your promotions should work as before.
53
+
54
+ Before you create new promotions, migrate the adjustments and order promotions in your database:
55
+
56
+ ```rb
57
+ bundle exec rails solidus_friendly_promotions:migrate_adjustments:up
58
+ bundle exec rails solidus_friendly_promotions:migrate_order_promotions:up
59
+
60
+ ```
61
+
62
+ Check your `spree_adjustments` table for correctness. If things went wrong, you should be able to roll back with
63
+
64
+ ```rb
65
+ bundle exec rails solidus_friendly_promotions:migrate_adjustments:down
66
+ bundle exec rails solidus_friendly_promotions:migrate_order_promotions:down
67
+ ```
68
+
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
+
71
+ ## Migrating custom rules and actions
72
+
73
+ If you have custom promotion rules or actions, you need to create new promotion rules and actions.
74
+
75
+ > [!IMPORTANT]
76
+ > SolidusFriendlyPromotions currently only supports actions that discount line items and shipments. If you have actions that add line items, or create order-level adjustments, we currently have no support for that.
77
+
78
+ In our experience, using the two actions can do almost all the things necessary, since they are customizable using calculators.
79
+
80
+ Rules share a lot of the previous API. If you make use of `#actionable?`, you might want to migrate your rule to be a line-item level rule:
81
+
82
+ ```rb
83
+ class MyRule < Spree::PromotionRule
84
+ def actionable?(promotable)
85
+ promotable.quantity > 3
86
+ end
87
+ end
88
+ ```
89
+
90
+ would become:
91
+
92
+ ```rb
93
+ class MyNewRule < SolidusFriendlyShipping::PromotionRule
94
+ include LineItemLevelRule
95
+ def eligible?(promotable)
96
+ promotable.quantity > 3
97
+ end
98
+ end
99
+ ```
100
+
101
+ Now, create your own Promotion conversion map:
102
+
103
+ ```rb
104
+ require 'solidus_friendly_promotions/promotion_map'
105
+
106
+ MY_PROMOTION_MAP = SolidusFriendlyPromotions::PROMOTION_MAP.deep_merge(
107
+ rules: {
108
+ MyRule => MyNewRule
109
+ }
110
+ )
111
+ ```
112
+
113
+ The value of the conversion map can also be a callable that takes the original promotion rule and should return a new promotion rule.
114
+
115
+ ```rb
116
+ require 'solidus_friendly_promotions/promotion_map'
117
+
118
+ MY_PROMOTION_MAP = SolidusFriendlyPromotions::PROMOTION_MAP.deep_merge(
119
+ rules: {
120
+ MyRule => ->(old_promotion_rule) {
121
+ MyNewRule.new(preferred_quantity: old_promotion_rule.preferred_count)
122
+ }
123
+ }
124
+ )
125
+ ```
126
+
127
+ You can now run our migrator with your map:
128
+
129
+ ```rb
130
+ require 'solidus_friendly_promotions/promotion_migrator'
131
+ require 'my_promotion_map'
132
+
133
+ SolidusFriendlyPromotions::PromotionMigrator.new(MY_PROMOTION_MAP).call
134
+ ```
data/README.md ADDED
@@ -0,0 +1,144 @@
1
+ # Solidus Friendly Promotions
2
+
3
+ [![CircleCI](https://circleci.com/gh/friendlycart/solidus_friendly_promotions.svg?style=shield)](https://circleci.com/gh/friendlycart/solidus_friendly_promotions)
4
+
5
+ This extension replaces Solidus core's promotion system. It is intended as both a research project and a working alternative to how promotions work in core.
6
+
7
+ The basic architecture is very similar to the one in core Solidus, but with a few decisive tweaks, which I'll explain in the coming sections.
8
+
9
+ ## Architecture
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.
12
+
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
+
15
+ The design decision here is to make the code path easier to follow, and consequently to make it more performant ("Make it easy, then make it fast").
16
+
17
+ `SolidusFriendlyPromotions::Promotion` objects have rules and actions, just like `Spree::Promotion`. However, both rules and actions work slightly differently.
18
+
19
+ ### Promotion lanes
20
+
21
+ 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 SolidusFriendlyPromotions initializer:
22
+
23
+ ```rb
24
+ SolidusFriendlyPromotions.configure do |config|
25
+ config.preferred_lanes = {
26
+ pre: 0,
27
+ default: 1,
28
+ grogu: 2,
29
+ post: 3
30
+ }
31
+ end
32
+ ```
33
+
34
+ ### Promotion Rules
35
+
36
+ Promotion rules can be applicable to either `Spree::Order`, `Spree::LineItem`, or `Spree::Shipment` objects. If they are applicable, they will be asked for eligibility. Rules applicable to orders are processed first. If a promotion has a rule that makes it ineligible for an order, line items and shipments will not be adjusted. If there are no rules that are applicable, the promotion will be considered eligible.
37
+
38
+ ### Promotion Actions
39
+
40
+ There are only two actions by default that should cover most use cases: `AdjustLineItem` and `AdjustShipment`. Ther is no action that creates order-level adjustments, as this feature of core Solidus 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` action with the `DistributedAmount` calculator.
41
+
42
+ Both actions are calculable. By setting their `calculator` to one of the classes provided, a great range of discount possibilities is maintained.
43
+
44
+ ### Connecting promotions to orders
45
+
46
+ When there is a join record `SolidusFriendlyPromotions::OrderPromotion`, the promotion and the order will be "connected", and the promotion will be applied even if it does not `apply_automatically` (see below). There's a difference to Solidus' system here in that promotions are not automatically connected to orders when they apply.
47
+
48
+ One way of connecting orders to promotions is via a promotion code.
49
+
50
+ ### Promotion categories
51
+
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
+
54
+
55
+ ## Installation
56
+
57
+ Add solidus_friendly_promotions to your Gemfile:
58
+
59
+ ```ruby
60
+ gem 'solidus_friendly_promotions', github: 'friendlycart/solidus_friendly_promotion', branch: 'main'
61
+ ```
62
+
63
+ Once this project is out of the research phase, a proper gem release will follow.
64
+
65
+ Bundle your dependencies and run the installation generator:
66
+
67
+ ```shell
68
+ bin/rails generate solidus_friendly_promotions:install
69
+ ```
70
+
71
+ This will create the tables for this extension. It will also replace the promotion administration system under
72
+ `/admin/promotions` with a new one that needs `turbo-rails`.
73
+
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!
75
+
76
+ ## Usage
77
+
78
+ Add a promotion using the admin. Add rules and actions, and observe promotions getting applied how you'd expect them to.
79
+
80
+ In the admin screen, you can set a number of attributes on your promotion:
81
+ - Name: The name of the promotion. The `name` attribute will also be used to generate adjustment labels. In multi-lingual stores, you probably want different promotions per language for this reason.
82
+
83
+ - Description: This is purely informative. Some stores use `description` in order display information about this promotion to customers, but there is nothing in core Solidus that does it.
84
+
85
+ - Start and End: Outside of the time range between `starts_at` and `expires_at`, the promotion will not be eligible to any order.
86
+
87
+ - Usage Limit: `usage_limit` controls to how many orders this promotion can be applied, independent of promotion code or user. This is most commonly used to limit the risk of losing too much revenue with a particular promotion.
88
+
89
+ - Path: `path` is a URL path that connects the promotion to the order upon visitation. Not currently implemented in either Solidus core or this extension.
90
+
91
+ - Per Code Usage Limit: How often each code can be used. Useful for limiting how many orders can be placed with a single promotion code.
92
+
93
+ - Apply Automatically: Whether this promotion should apply automatically. This means that the promotion is checked for eligibility every time the customer's order is recalculated. Promotion Codes and automatic applications are incompatible.
94
+
95
+ - Promotion Category: Used to group promotions in the admin view.
96
+
97
+ ## Development
98
+
99
+ ### Testing the extension
100
+
101
+ First bundle your dependencies, then run `bin/rake`. `bin/rake` will default to building the dummy
102
+ app if it does not exist, then it will run specs. The dummy app can be regenerated by using
103
+ `bin/rake extension:test_app`.
104
+
105
+ ```shell
106
+ bin/rake
107
+ ```
108
+
109
+ To run [Rubocop](https://github.com/bbatsov/rubocop) static code analysis run
110
+
111
+ ```shell
112
+ bundle exec rubocop
113
+ ```
114
+
115
+ When testing your application's integration with this extension you may use its factories.
116
+ You can load Solidus core factories along with this extension's factories using this statement:
117
+
118
+ ```ruby
119
+ SolidusDevSupport::TestingSupport::Factories.load_for(SolidusFriendlyPromotions::Engine)
120
+ ```
121
+
122
+ ### Running the sandbox
123
+
124
+ To run this extension in a sandboxed Solidus application, you can run `bin/sandbox`. The path for
125
+ the sandbox app is `./sandbox` and `bin/rails` will forward any Rails commands to
126
+ `sandbox/bin/rails`.
127
+
128
+ Here's an example:
129
+
130
+ ```
131
+ $ bin/rails server
132
+ => Booting Puma
133
+ => Rails 6.0.2.1 application starting in development
134
+ * Listening on tcp://127.0.0.1:3000
135
+ Use Ctrl-C to stop
136
+ ```
137
+
138
+ ### Releasing new versions
139
+
140
+ Please refer to the [dedicated page](https://github.com/solidusio/solidus/wiki/How-to-release-extensions) in the Solidus wiki.
141
+
142
+ ## License
143
+
144
+ Copyright (c) 2023 Martin Meyerhoff, released under the New BSD License.
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "solidus_dev_support/rake_tasks"
5
+ SolidusDevSupport::RakeTasks.install
6
+
7
+ task default: "extension:specs"
@@ -0,0 +1,7 @@
1
+ //= link solidus_friendly_promotions.js
2
+ //= link solidus_friendly_promotions/controllers/application.js
3
+ //= link solidus_friendly_promotions/controllers/index.js
4
+ //= link solidus_friendly_promotions/controllers/calculator_tiers_controller.js
5
+ //= link solidus_friendly_promotions/controllers/flash_controller.js
6
+ //= link solidus_friendly_promotions/controllers/product_option_values_controller.js
7
+ //= link solidus_friendly_promotions/jquery/option_value_picker.js