solidus_promotions 4.4.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 (234) hide show
  1. checksums.yaml +7 -0
  2. data/.eslintrc.json +10 -0
  3. data/.github/stale.yml +1 -0
  4. data/MIGRATING.md +184 -0
  5. data/README.md +122 -0
  6. data/Rakefile +20 -0
  7. data/app/assets/config/solidus_promotions/manifest.js +13 -0
  8. data/app/decorators/models/solidus_promotions/adjustment_decorator.rb +11 -0
  9. data/app/decorators/models/solidus_promotions/line_item_decorator.rb +27 -0
  10. data/app/decorators/models/solidus_promotions/order_decorator.rb +42 -0
  11. data/app/decorators/models/solidus_promotions/order_recalculator_decorator.rb +15 -0
  12. data/app/decorators/models/solidus_promotions/shipment_decorator.rb +14 -0
  13. data/app/decorators/models/solidus_promotions/shipping_rate_decorator.rb +29 -0
  14. data/app/helpers/solidus_promotions/admin/benefits_helper.rb +19 -0
  15. data/app/helpers/solidus_promotions/admin/conditions_helper.rb +14 -0
  16. data/app/helpers/solidus_promotions/admin/promotions_helper.rb +15 -0
  17. data/app/javascript/backend/solidus_promotions/controllers/application.js +9 -0
  18. data/app/javascript/backend/solidus_promotions/controllers/calculator_tiers_controller.js +37 -0
  19. data/app/javascript/backend/solidus_promotions/controllers/flash_controller.js +10 -0
  20. data/app/javascript/backend/solidus_promotions/controllers/index.js +8 -0
  21. data/app/javascript/backend/solidus_promotions/controllers/product_option_values_controller.js +62 -0
  22. data/app/javascript/backend/solidus_promotions/web_components/number_with_currency.js +35 -0
  23. data/app/javascript/backend/solidus_promotions/web_components/option_value_picker.js +52 -0
  24. data/app/javascript/backend/solidus_promotions/web_components/product_picker.js +7 -0
  25. data/app/javascript/backend/solidus_promotions/web_components/select_two.js +11 -0
  26. data/app/javascript/backend/solidus_promotions/web_components/taxon_picker.js +7 -0
  27. data/app/javascript/backend/solidus_promotions/web_components/user_picker.js +7 -0
  28. data/app/javascript/backend/solidus_promotions/web_components/variant_picker.js +7 -0
  29. data/app/javascript/backend/solidus_promotions.js +11 -0
  30. data/app/jobs/solidus_promotions/promotion_code_batch_job.rb +26 -0
  31. data/app/mailers/solidus_promotions/promotion_code_batch_mailer.rb +15 -0
  32. data/app/models/concerns/solidus_promotions/benefits/line_item_benefit.rb +15 -0
  33. data/app/models/concerns/solidus_promotions/benefits/order_benefit.rb +15 -0
  34. data/app/models/concerns/solidus_promotions/benefits/shipment_benefit.rb +15 -0
  35. data/app/models/concerns/solidus_promotions/calculators/promotion_calculator.rb +11 -0
  36. data/app/models/concerns/solidus_promotions/conditions/line_item_applicable_order_level_condition.rb +23 -0
  37. data/app/models/concerns/solidus_promotions/conditions/line_item_level_condition.rb +15 -0
  38. data/app/models/concerns/solidus_promotions/conditions/order_level_condition.rb +15 -0
  39. data/app/models/concerns/solidus_promotions/conditions/shipment_level_condition.rb +15 -0
  40. data/app/models/concerns/solidus_promotions/discountable_amount.rb +21 -0
  41. data/app/models/solidus_promotions/benefit.rb +123 -0
  42. data/app/models/solidus_promotions/benefits/adjust_line_item.rb +13 -0
  43. data/app/models/solidus_promotions/benefits/adjust_line_item_quantity_groups.rb +107 -0
  44. data/app/models/solidus_promotions/benefits/adjust_shipment.rb +13 -0
  45. data/app/models/solidus_promotions/benefits/create_discounted_item.rb +49 -0
  46. data/app/models/solidus_promotions/calculators/distributed_amount.rb +31 -0
  47. data/app/models/solidus_promotions/calculators/flat_rate.rb +23 -0
  48. data/app/models/solidus_promotions/calculators/flexi_rate.rb +26 -0
  49. data/app/models/solidus_promotions/calculators/percent.rb +19 -0
  50. data/app/models/solidus_promotions/calculators/tiered_flat_rate.rb +58 -0
  51. data/app/models/solidus_promotions/calculators/tiered_percent.rb +68 -0
  52. data/app/models/solidus_promotions/calculators/tiered_percent_on_eligible_item_quantity.rb +40 -0
  53. data/app/models/solidus_promotions/condition.rb +61 -0
  54. data/app/models/solidus_promotions/condition_product.rb +8 -0
  55. data/app/models/solidus_promotions/condition_store.rb +8 -0
  56. data/app/models/solidus_promotions/condition_taxon.rb +8 -0
  57. data/app/models/solidus_promotions/condition_user.rb +8 -0
  58. data/app/models/solidus_promotions/conditions/discounted_item_total.rb +22 -0
  59. data/app/models/solidus_promotions/conditions/first_order.rb +31 -0
  60. data/app/models/solidus_promotions/conditions/first_repeat_purchase_since.rb +31 -0
  61. data/app/models/solidus_promotions/conditions/item_total.rb +75 -0
  62. data/app/models/solidus_promotions/conditions/line_item_option_value.rb +37 -0
  63. data/app/models/solidus_promotions/conditions/line_item_product.rb +56 -0
  64. data/app/models/solidus_promotions/conditions/line_item_taxon.rb +59 -0
  65. data/app/models/solidus_promotions/conditions/minimum_quantity.rb +42 -0
  66. data/app/models/solidus_promotions/conditions/nth_order.rb +40 -0
  67. data/app/models/solidus_promotions/conditions/one_use_per_user.rb +25 -0
  68. data/app/models/solidus_promotions/conditions/option_value.rb +28 -0
  69. data/app/models/solidus_promotions/conditions/product.rb +85 -0
  70. data/app/models/solidus_promotions/conditions/shipping_method.rb +19 -0
  71. data/app/models/solidus_promotions/conditions/store.rb +26 -0
  72. data/app/models/solidus_promotions/conditions/taxon.rb +98 -0
  73. data/app/models/solidus_promotions/conditions/user.rb +35 -0
  74. data/app/models/solidus_promotions/conditions/user_logged_in.rb +16 -0
  75. data/app/models/solidus_promotions/conditions/user_role.rb +42 -0
  76. data/app/models/solidus_promotions/distributed_amounts_handler.rb +39 -0
  77. data/app/models/solidus_promotions/eligibility_result.rb +5 -0
  78. data/app/models/solidus_promotions/eligibility_results.rb +47 -0
  79. data/app/models/solidus_promotions/item_discount.rb +21 -0
  80. data/app/models/solidus_promotions/migration_support/order_promotion_syncer.rb +54 -0
  81. data/app/models/solidus_promotions/order_adjuster/choose_discounts.rb +21 -0
  82. data/app/models/solidus_promotions/order_adjuster/discount_order.rb +93 -0
  83. data/app/models/solidus_promotions/order_adjuster/load_promotions.rb +53 -0
  84. data/app/models/solidus_promotions/order_adjuster/persist_discounted_order.rb +79 -0
  85. data/app/models/solidus_promotions/order_adjuster.rb +33 -0
  86. data/app/models/solidus_promotions/order_promotion.rb +23 -0
  87. data/app/models/solidus_promotions/permission_sets/solidus_promotion_management.rb +15 -0
  88. data/app/models/solidus_promotions/promotion.rb +163 -0
  89. data/app/models/solidus_promotions/promotion_advertiser.rb +10 -0
  90. data/app/models/solidus_promotions/promotion_category.rb +9 -0
  91. data/app/models/solidus_promotions/promotion_code/batch_builder.rb +73 -0
  92. data/app/models/solidus_promotions/promotion_code.rb +56 -0
  93. data/app/models/solidus_promotions/promotion_code_batch.rb +25 -0
  94. data/app/models/solidus_promotions/promotion_finder.rb +10 -0
  95. data/app/models/solidus_promotions/promotion_handler/coupon.rb +113 -0
  96. data/app/models/solidus_promotions/promotion_handler/page.rb +30 -0
  97. data/app/models/solidus_promotions/shipping_rate_discount.rb +11 -0
  98. data/app/subscribers/solidus_promotions/order_promotion_subscriber.rb +20 -0
  99. data/bin/rails +13 -0
  100. data/config/importmap.rb +14 -0
  101. data/config/locales/en.yml +376 -0
  102. data/config/locales/promotion_categories.en.yml +6 -0
  103. data/config/locales/promotions.en.yml +6 -0
  104. data/config/routes.rb +38 -0
  105. data/db/migrate/20230703101637_create_promotions.rb +25 -0
  106. data/db/migrate/20230703113625_create_promotion_benefits.rb +15 -0
  107. data/db/migrate/20230703141116_create_promotion_categories.rb +14 -0
  108. data/db/migrate/20230703143943_create_promotion_conditions.rb +12 -0
  109. data/db/migrate/20230704083830_add_condition_join_tables.rb +31 -0
  110. data/db/migrate/20230704102444_create_promotion_codes.rb +11 -0
  111. data/db/migrate/20230704102656_create_promotion_code_batches.rb +34 -0
  112. data/db/migrate/20230705171556_create_order_promotions.rb +11 -0
  113. data/db/migrate/20230725074235_create_shipping_rate_discounts.rb +12 -0
  114. data/db/migrate/20231011100059_add_db_comments_to_order_promotions.rb +61 -0
  115. data/db/migrate/20231011120928_add_db_comments_to_condition_taxons.rb +54 -0
  116. data/db/migrate/20231011131324_add_db_comments_to_conditions.rb +60 -0
  117. data/db/migrate/20231011142040_add_db_comments_to_condition_users.rb +53 -0
  118. data/db/migrate/20231011155822_add_db_comments_to_promotions.rb +123 -0
  119. data/db/migrate/20231011163030_add_db_comments_to_promotion_codes.rb +60 -0
  120. data/db/migrate/20231011173312_add_db_comments_to_promotion_code_batches.rb +91 -0
  121. data/db/migrate/20231011184205_add_db_comments_to_condition_stores.rb +53 -0
  122. data/db/migrate/20231011190222_add_db_comments_to_benefits.rb +61 -0
  123. data/db/migrate/20231012020928_add_db_comments_to_condition_products.rb +52 -0
  124. data/db/migrate/20231012120928_add_db_comments_to_promotion_categories.rb +52 -0
  125. data/db/migrate/20231104135812_add_managed_by_order_benefit_to_line_items.rb +5 -0
  126. data/lib/components/admin/solidus_admin/orders/show/adjustments/index/source/solidus_promotions_benefit/component.rb +17 -0
  127. data/lib/components/admin/solidus_promotions/orders/index/component.rb +15 -0
  128. data/lib/components/admin/solidus_promotions/orders/index/component.yml +3 -0
  129. data/lib/components/admin/solidus_promotions/promotion_categories/index/component.rb +60 -0
  130. data/lib/components/admin/solidus_promotions/promotions/index/component.rb +108 -0
  131. data/lib/components/admin/solidus_promotions/promotions/index/component.yml +10 -0
  132. data/lib/controllers/admin/solidus_promotions/promotion_categories_controller.rb +29 -0
  133. data/lib/controllers/admin/solidus_promotions/promotions_controller.rb +46 -0
  134. data/lib/controllers/backend/solidus_promotions/admin/base_controller.rb +15 -0
  135. data/lib/controllers/backend/solidus_promotions/admin/benefits_controller.rb +85 -0
  136. data/lib/controllers/backend/solidus_promotions/admin/conditions_controller.rb +69 -0
  137. data/lib/controllers/backend/solidus_promotions/admin/promotion_categories_controller.rb +13 -0
  138. data/lib/controllers/backend/solidus_promotions/admin/promotion_code_batches_controller.rb +42 -0
  139. data/lib/controllers/backend/solidus_promotions/admin/promotion_codes_controller.rb +58 -0
  140. data/lib/controllers/backend/solidus_promotions/admin/promotions_controller.rb +65 -0
  141. data/lib/generators/solidus_promotions/install/install_generator.rb +56 -0
  142. data/lib/generators/solidus_promotions/install/templates/initializer.rb +6 -0
  143. data/lib/solidus_promotions/configuration.rb +125 -0
  144. data/lib/solidus_promotions/engine.rb +115 -0
  145. data/lib/solidus_promotions/migrate_adjustments.rb +62 -0
  146. data/lib/solidus_promotions/migrate_order_promotions.rb +73 -0
  147. data/lib/solidus_promotions/promotion_map.rb +126 -0
  148. data/lib/solidus_promotions/promotion_migrator.rb +103 -0
  149. data/lib/solidus_promotions/testing_support/factories/completed_order_with_solidus_promotion_factory.rb +20 -0
  150. data/lib/solidus_promotions/testing_support/factories/solidus_order_promotion_factory.rb +8 -0
  151. data/lib/solidus_promotions/testing_support/factories/solidus_promotion_category_factory.rb +7 -0
  152. data/lib/solidus_promotions/testing_support/factories/solidus_promotion_code_factory.rb +8 -0
  153. data/lib/solidus_promotions/testing_support/factories/solidus_promotion_factory.rb +65 -0
  154. data/lib/solidus_promotions/testing_support/factories/solidus_shipping_rate_discount_factory.rb +14 -0
  155. data/lib/solidus_promotions/testing_support/factory_bot.rb +30 -0
  156. data/lib/solidus_promotions.rb +37 -0
  157. data/lib/tasks/solidus_promotions/migrate_adjustments.rake +17 -0
  158. data/lib/tasks/solidus_promotions/migrate_existing_promotions.rake +12 -0
  159. data/lib/tasks/solidus_promotions/migrate_order_promotions.rake +17 -0
  160. data/lib/views/backend/solidus_promotions/admin/benefit_fields/_adjust_line_item.html.erb +6 -0
  161. data/lib/views/backend/solidus_promotions/admin/benefit_fields/_adjust_line_item_quantity_groups.html.erb +13 -0
  162. data/lib/views/backend/solidus_promotions/admin/benefit_fields/_adjust_shipment.html.erb +6 -0
  163. data/lib/views/backend/solidus_promotions/admin/benefit_fields/_calculator_fields.erb +11 -0
  164. data/lib/views/backend/solidus_promotions/admin/benefit_fields/_create_discounted_item.html.erb +21 -0
  165. data/lib/views/backend/solidus_promotions/admin/benefits/_benefit.html.erb +50 -0
  166. data/lib/views/backend/solidus_promotions/admin/benefits/_calculator_select.html.erb +16 -0
  167. data/lib/views/backend/solidus_promotions/admin/benefits/_form.html.erb +3 -0
  168. data/lib/views/backend/solidus_promotions/admin/benefits/_new_benefit.html.erb +33 -0
  169. data/lib/views/backend/solidus_promotions/admin/benefits/_type_select.html.erb +16 -0
  170. data/lib/views/backend/solidus_promotions/admin/benefits/edit.html.erb +19 -0
  171. data/lib/views/backend/solidus_promotions/admin/benefits/new.html.erb +1 -0
  172. data/lib/views/backend/solidus_promotions/admin/calculator_fields/_default_fields.html.erb +6 -0
  173. data/lib/views/backend/solidus_promotions/admin/calculator_fields/distributed_amount/_fields.html.erb +18 -0
  174. data/lib/views/backend/solidus_promotions/admin/calculator_fields/flat_rate/_fields.html.erb +6 -0
  175. data/lib/views/backend/solidus_promotions/admin/calculator_fields/flexi_rate/_fields.html.erb +24 -0
  176. data/lib/views/backend/solidus_promotions/admin/calculator_fields/percent/_fields.html.erb +6 -0
  177. data/lib/views/backend/solidus_promotions/admin/calculator_fields/tiered_flat_rate/_fields.html.erb +32 -0
  178. data/lib/views/backend/solidus_promotions/admin/calculator_fields/tiered_flat_rate/_tier_fields.html.erb +31 -0
  179. data/lib/views/backend/solidus_promotions/admin/calculator_fields/tiered_percent/_fields.html.erb +47 -0
  180. data/lib/views/backend/solidus_promotions/admin/calculator_fields/tiered_percent/_tier_fields.html.erb +33 -0
  181. data/lib/views/backend/solidus_promotions/admin/calculator_fields/tiered_percent_on_eligible_item_quantity/_fields.html.erb +36 -0
  182. data/lib/views/backend/solidus_promotions/admin/calculator_fields/tiered_percent_on_eligible_item_quantity/_tier_fields.html.erb +35 -0
  183. data/lib/views/backend/solidus_promotions/admin/condition_fields/_first_order.html.erb +3 -0
  184. data/lib/views/backend/solidus_promotions/admin/condition_fields/_first_repeat_purchase_since.html.erb +7 -0
  185. data/lib/views/backend/solidus_promotions/admin/condition_fields/_item_total.html.erb +15 -0
  186. data/lib/views/backend/solidus_promotions/admin/condition_fields/_line_item_option_value.html.erb +25 -0
  187. data/lib/views/backend/solidus_promotions/admin/condition_fields/_line_item_product.html.erb +21 -0
  188. data/lib/views/backend/solidus_promotions/admin/condition_fields/_line_item_taxon.html.erb +17 -0
  189. data/lib/views/backend/solidus_promotions/admin/condition_fields/_minimum_quantity.html.erb +5 -0
  190. data/lib/views/backend/solidus_promotions/admin/condition_fields/_nth_order.html.erb +15 -0
  191. data/lib/views/backend/solidus_promotions/admin/condition_fields/_one_use_per_user.html.erb +3 -0
  192. data/lib/views/backend/solidus_promotions/admin/condition_fields/_option_value.html.erb +63 -0
  193. data/lib/views/backend/solidus_promotions/admin/condition_fields/_product.html.erb +27 -0
  194. data/lib/views/backend/solidus_promotions/admin/condition_fields/_shipping_method.html.erb +10 -0
  195. data/lib/views/backend/solidus_promotions/admin/condition_fields/_store.html.erb +9 -0
  196. data/lib/views/backend/solidus_promotions/admin/condition_fields/_taxon.html.erb +27 -0
  197. data/lib/views/backend/solidus_promotions/admin/condition_fields/_user.html.erb +7 -0
  198. data/lib/views/backend/solidus_promotions/admin/condition_fields/_user_logged_in.html.erb +3 -0
  199. data/lib/views/backend/solidus_promotions/admin/condition_fields/_user_role.html.erb +15 -0
  200. data/lib/views/backend/solidus_promotions/admin/condition_fields/line_item_option_value/_option_value_fields.html.erb +21 -0
  201. data/lib/views/backend/solidus_promotions/admin/conditions/_condition.html.erb +26 -0
  202. data/lib/views/backend/solidus_promotions/admin/conditions/_new_condition.html.erb +26 -0
  203. data/lib/views/backend/solidus_promotions/admin/conditions/_type_select.html.erb +20 -0
  204. data/lib/views/backend/solidus_promotions/admin/conditions/new.html.erb +1 -0
  205. data/lib/views/backend/solidus_promotions/admin/promotion_categories/_form.html.erb +14 -0
  206. data/lib/views/backend/solidus_promotions/admin/promotion_categories/edit.html.erb +10 -0
  207. data/lib/views/backend/solidus_promotions/admin/promotion_categories/index.html.erb +47 -0
  208. data/lib/views/backend/solidus_promotions/admin/promotion_categories/new.html.erb +10 -0
  209. data/lib/views/backend/solidus_promotions/admin/promotion_code_batches/_form_fields.html.erb +22 -0
  210. data/lib/views/backend/solidus_promotions/admin/promotion_code_batches/download.csv.ruby +8 -0
  211. data/lib/views/backend/solidus_promotions/admin/promotion_code_batches/index.html.erb +65 -0
  212. data/lib/views/backend/solidus_promotions/admin/promotion_code_batches/new.html.erb +8 -0
  213. data/lib/views/backend/solidus_promotions/admin/promotion_codes/index.csv.ruby +8 -0
  214. data/lib/views/backend/solidus_promotions/admin/promotion_codes/index.html.erb +32 -0
  215. data/lib/views/backend/solidus_promotions/admin/promotion_codes/new.html.erb +31 -0
  216. data/lib/views/backend/solidus_promotions/admin/promotions/_form.html.erb +124 -0
  217. data/lib/views/backend/solidus_promotions/admin/promotions/_table.html.erb +57 -0
  218. data/lib/views/backend/solidus_promotions/admin/promotions/_table_filter.html.erb +78 -0
  219. data/lib/views/backend/solidus_promotions/admin/promotions/edit.html.erb +41 -0
  220. data/lib/views/backend/solidus_promotions/admin/promotions/index.html.erb +23 -0
  221. data/lib/views/backend/solidus_promotions/admin/promotions/new.html.erb +9 -0
  222. data/lib/views/backend/solidus_promotions/admin/shared/_number_with_currency.html.erb +20 -0
  223. data/lib/views/backend/solidus_promotions/admin/shared/_promotion_sub_menu.html.erb +14 -0
  224. data/lib/views/backend/solidus_promotions/admin/shared/preference_fields/_boolean.html.erb +14 -0
  225. data/lib/views/backend/solidus_promotions/admin/shared/preference_fields/_decimal.html.erb +12 -0
  226. data/lib/views/backend/solidus_promotions/admin/shared/preference_fields/_encrypted_string.html.erb +12 -0
  227. data/lib/views/backend/solidus_promotions/admin/shared/preference_fields/_integer.html.erb +12 -0
  228. data/lib/views/backend/solidus_promotions/admin/shared/preference_fields/_password.html.erb +12 -0
  229. data/lib/views/backend/solidus_promotions/admin/shared/preference_fields/_string.html.erb +12 -0
  230. data/lib/views/backend/solidus_promotions/admin/shared/preference_fields/_text.html.erb +12 -0
  231. data/lib/views/backend/solidus_promotions/promotion_code_batch_mailer/promotion_code_batch_errored.text.erb +2 -0
  232. data/lib/views/backend/solidus_promotions/promotion_code_batch_mailer/promotion_code_batch_finished.text.erb +2 -0
  233. data/solidus_promotions.gemspec +33 -0
  234. metadata +366 -0
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddDbCommentsToConditionStores < ActiveRecord::Migration[6.1]
4
+ def up
5
+ if connection.supports_comments?
6
+ change_table_comment(:solidus_promotions_condition_stores, solidus_promotions_condition_stores_table_comment)
7
+ change_column_comment(:solidus_promotions_condition_stores, :id, id_comment)
8
+ change_column_comment(:solidus_promotions_condition_stores, :store_id, store_id_comment)
9
+ change_column_comment(:solidus_promotions_condition_stores, :condition_id, condition_id_comment)
10
+ change_column_comment(:solidus_promotions_condition_stores, :created_at, created_at_comment)
11
+ change_column_comment(:solidus_promotions_condition_stores, :updated_at, updated_at_comment)
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def solidus_promotions_condition_stores_table_comment
18
+ <<~COMMENT
19
+ Join table between conditions and stores. Only used with the condition "Store", which checks that an order
20
+ has been placed in a particular Spree::Store instance.
21
+ COMMENT
22
+ end
23
+
24
+ def id_comment
25
+ <<~COMMENT
26
+ Primary key of this table.
27
+ COMMENT
28
+ end
29
+
30
+ def store_id_comment
31
+ <<~COMMENT
32
+ Foreign key to the spree_stores table.
33
+ COMMENT
34
+ end
35
+
36
+ def condition_id_comment
37
+ <<~COMMENT
38
+ Foreign key to the solidus_promotions_promotion_rules table.
39
+ COMMENT
40
+ end
41
+
42
+ def created_at_comment
43
+ <<~COMMENT
44
+ Timestamp indicating when this record was created.
45
+ COMMENT
46
+ end
47
+
48
+ def updated_at_comment
49
+ <<~COMMENT
50
+ Timestamp indicating when this record was last updated.
51
+ COMMENT
52
+ end
53
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddDbCommentsToBenefits < ActiveRecord::Migration[6.1]
4
+ def up
5
+ if connection.supports_comments?
6
+ change_table_comment(:solidus_promotions_benefits, solidus_promotions_benefits_table_comment)
7
+ change_column_comment(:solidus_promotions_benefits, :id, id_comment)
8
+ change_column_comment(:solidus_promotions_benefits, :promotion_id, promotion_id_comment)
9
+ change_column_comment(:solidus_promotions_benefits, :type, type_comment)
10
+ change_column_comment(:solidus_promotions_benefits, :preferences, preferences_comment)
11
+ change_column_comment(:solidus_promotions_benefits, :created_at, created_at_comment)
12
+ change_column_comment(:solidus_promotions_benefits, :updated_at, updated_at_comment)
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def solidus_promotions_benefits_table_comment
19
+ <<~COMMENT
20
+ Single Table inheritance table. Represents what to do to an order when the linked promotion is eligible.
21
+ Promotions can have many benefits.
22
+ COMMENT
23
+ end
24
+
25
+ def id_comment
26
+ <<~COMMENT
27
+ Primary key of this table.
28
+ COMMENT
29
+ end
30
+
31
+ def promotion_id_comment
32
+ <<~COMMENT
33
+ Foreign key to the solidus_promotions_promotions table.
34
+ COMMENT
35
+ end
36
+
37
+ def type_comment
38
+ <<~COMMENT
39
+ A class name representing which benefit this represents.
40
+ Usually SolidusPromotions::PromotionAction::Adjust{LineItem,Shipment}.
41
+ COMMENT
42
+ end
43
+
44
+ def preferences_comment
45
+ <<~COMMENT
46
+ Preferences for this benefit. Serialized YAML.
47
+ COMMENT
48
+ end
49
+
50
+ def created_at_comment
51
+ <<~COMMENT
52
+ Timestamp indicating when this record was created.
53
+ COMMENT
54
+ end
55
+
56
+ def updated_at_comment
57
+ <<~COMMENT
58
+ Timestamp indicating when this record was last updated.
59
+ COMMENT
60
+ end
61
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddDbCommentsToConditionProducts < ActiveRecord::Migration[6.1]
4
+ def up
5
+ if connection.supports_comments?
6
+ change_table_comment(:solidus_promotions_condition_products, solidus_promotions_condition_products_table_comment)
7
+ change_column_comment(:solidus_promotions_condition_products, :id, id_comment)
8
+ change_column_comment(:solidus_promotions_condition_products, :product_id, product_id_comment)
9
+ change_column_comment(:solidus_promotions_condition_products, :condition_id, condition_id_comment)
10
+ change_column_comment(:solidus_promotions_condition_products, :created_at, created_at_comment)
11
+ change_column_comment(:solidus_promotions_condition_products, :updated_at, updated_at_comment)
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def solidus_promotions_condition_products_table_comment
18
+ <<~COMMENT
19
+ Join table between conditions and products.
20
+ COMMENT
21
+ end
22
+
23
+ def id_comment
24
+ <<~COMMENT
25
+ Primary key of this table.
26
+ COMMENT
27
+ end
28
+
29
+ def product_id_comment
30
+ <<~COMMENT
31
+ Foreign key to the spree_products table.
32
+ COMMENT
33
+ end
34
+
35
+ def condition_id_comment
36
+ <<~COMMENT
37
+ Foreign key to the solidus_promotions_conditions table.
38
+ COMMENT
39
+ end
40
+
41
+ def created_at_comment
42
+ <<~COMMENT
43
+ Timestamp indicating when this record was created.
44
+ COMMENT
45
+ end
46
+
47
+ def updated_at_comment
48
+ <<~COMMENT
49
+ Timestamp indicating when this record was last updated.
50
+ COMMENT
51
+ end
52
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddDbCommentsToPromotionCategories < ActiveRecord::Migration[6.1]
4
+ def up
5
+ if connection.supports_comments?
6
+ change_table_comment(:solidus_promotions_promotion_categories, solidus_promotions_promotion_categories_table_comment)
7
+ change_column_comment(:solidus_promotions_promotion_categories, :id, id_comment)
8
+ change_column_comment(:solidus_promotions_promotion_categories, :name, name_comment)
9
+ change_column_comment(:solidus_promotions_promotion_categories, :code, code_comment)
10
+ change_column_comment(:solidus_promotions_promotion_categories, :created_at, created_at_comment)
11
+ change_column_comment(:solidus_promotions_promotion_categories, :updated_at, updated_at_comment)
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def solidus_promotions_promotion_categories_table_comment
18
+ <<~COMMENT
19
+ Category that helps admins index promotions.
20
+ COMMENT
21
+ end
22
+
23
+ def id_comment
24
+ <<~COMMENT
25
+ Primary key of this table.
26
+ COMMENT
27
+ end
28
+
29
+ def name_comment
30
+ <<~COMMENT
31
+ Name of this promotion category.
32
+ COMMENT
33
+ end
34
+
35
+ def code_comment
36
+ <<~COMMENT
37
+ Code of this promotion category.
38
+ COMMENT
39
+ end
40
+
41
+ def created_at_comment
42
+ <<~COMMENT
43
+ Timestamp indicating when this record was created.
44
+ COMMENT
45
+ end
46
+
47
+ def updated_at_comment
48
+ <<~COMMENT
49
+ Timestamp indicating when this record was last updated.
50
+ COMMENT
51
+ end
52
+ end
@@ -0,0 +1,5 @@
1
+ class AddManagedByOrderBenefitToLineItems < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_reference :spree_line_items, :managed_by_order_benefit, foreign_key: { to_table: :solidus_promotions_benefits, null: true }
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SolidusAdmin::Orders::Show::Adjustments::Index::Source::SolidusPromotionsBenefit::Component < SolidusAdmin::Orders::Show::Adjustments::Index::Source::Component
4
+ def detail
5
+ link_to("#{model_name}: #{promotion_name}", solidus_promotions.edit_admin_promotion_path(adjustment.source_id), class: "body-link")
6
+ end
7
+
8
+ private
9
+
10
+ def promotion_name
11
+ source.promotion.name
12
+ end
13
+
14
+ def solidus_promotions
15
+ @solidus_promotions ||= SolidusPromotions::Engine.routes.url_helpers
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SolidusPromotions::Orders::Index::Component < SolidusAdmin::Orders::Index::Component
4
+ def filters
5
+ super + [
6
+ {
7
+ label: t(".filters.promotions"),
8
+ combinator: "or",
9
+ attribute: "solidus_promotions_id",
10
+ predicate: "in",
11
+ options: SolidusPromotions::Promotion.all.pluck(:name, :id)
12
+ }
13
+ ]
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ en:
2
+ filters:
3
+ promotions: Promotions
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SolidusPromotions::PromotionCategories::Index::Component < SolidusAdmin::UI::Pages::Index::Component
4
+ def model_class
5
+ SolidusPromotions::PromotionCategory
6
+ end
7
+
8
+ def row_url(promotion_category)
9
+ solidus_promotions.edit_admin_promotion_category_path(promotion_category)
10
+ end
11
+
12
+ def page_actions
13
+ render component("ui/button").new(
14
+ tag: :a,
15
+ text: t(".add"),
16
+ href: solidus_promotions.new_admin_promotion_category_path,
17
+ icon: "add-line"
18
+ )
19
+ end
20
+
21
+ def batch_actions
22
+ [
23
+ {
24
+ label: t(".batch_actions.delete"),
25
+ action: solidus_promotions.promotion_categories_path,
26
+ method: :delete,
27
+ icon: "delete-bin-7-line"
28
+ }
29
+ ]
30
+ end
31
+
32
+ def columns
33
+ [
34
+ name_column,
35
+ code_column
36
+ ]
37
+ end
38
+
39
+ def name_column
40
+ {
41
+ header: :name,
42
+ data: ->(promotion_category) do
43
+ content_tag :div, promotion_category.name
44
+ end
45
+ }
46
+ end
47
+
48
+ def code_column
49
+ {
50
+ header: :code,
51
+ data: ->(promotion_category) do
52
+ content_tag :div, promotion_category.code
53
+ end
54
+ }
55
+ end
56
+
57
+ def solidus_promotions
58
+ @solidus_promotions ||= SolidusPromotions::Engine.routes.url_helpers
59
+ end
60
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SolidusPromotions::Promotions::Index::Component < SolidusAdmin::UI::Pages::Index::Component
4
+ def model_class
5
+ SolidusPromotions::Promotion
6
+ end
7
+
8
+ def search_key
9
+ :name_or_codes_value_or_path_or_description_cont
10
+ end
11
+
12
+ def search_url
13
+ solidus_promotions.promotions_path
14
+ end
15
+
16
+ def row_url(promotion)
17
+ solidus_promotions.admin_promotion_path(promotion)
18
+ end
19
+
20
+ def page_actions
21
+ render component("ui/button").new(
22
+ tag: :a,
23
+ text: t(".add"),
24
+ href: solidus_promotions.new_admin_promotion_path,
25
+ icon: "add-line"
26
+ )
27
+ end
28
+
29
+ def batch_actions
30
+ [
31
+ {
32
+ label: t(".batch_actions.delete"),
33
+ action: solidus_promotions.promotions_path,
34
+ method: :delete,
35
+ icon: "delete-bin-7-line"
36
+ }
37
+ ]
38
+ end
39
+
40
+ def scopes
41
+ [
42
+ { name: :active, label: t(".scopes.active"), default: true },
43
+ { name: :draft, label: t(".scopes.draft") },
44
+ { name: :future, label: t(".scopes.future") },
45
+ { name: :expired, label: t(".scopes.expired") },
46
+ { name: :all, label: t(".scopes.all") }
47
+ ]
48
+ end
49
+
50
+ def filters
51
+ [
52
+ {
53
+ label: SolidusPromotions::PromotionCategory.model_name.human.pluralize,
54
+ attribute: "promotion_category_id",
55
+ predicate: "in",
56
+ options: SolidusPromotions::PromotionCategory.pluck(:name, :id)
57
+ }
58
+ ]
59
+ end
60
+
61
+ def columns
62
+ [
63
+ {
64
+ header: :name,
65
+ data: ->(promotion) do
66
+ content_tag :div, promotion.name
67
+ end
68
+ },
69
+ {
70
+ header: :code,
71
+ data: ->(promotion) do
72
+ count = promotion.codes.count
73
+ (count == 1) ? promotion.codes.pick(:value) : t("spree.number_of_codes", count: count)
74
+ end
75
+ },
76
+ {
77
+ header: :status,
78
+ data: ->(promotion) do
79
+ if promotion.active?
80
+ render component("ui/badge").new(name: t(".status.active"), color: :green)
81
+ else
82
+ render component("ui/badge").new(name: t(".status.inactive"), color: :graphite_light)
83
+ end
84
+ end
85
+ },
86
+ {
87
+ header: :usage_limit,
88
+ data: ->(promotion) { promotion.usage_limit || icon_tag("infinity-line") }
89
+ },
90
+ {
91
+ header: :uses,
92
+ data: ->(promotion) { promotion.usage_count }
93
+ },
94
+ {
95
+ header: :starts_at,
96
+ data: ->(promotion) { promotion.starts_at ? l(promotion.starts_at, format: :long) : icon_tag("infinity-line") }
97
+ },
98
+ {
99
+ header: :expires_at,
100
+ data: ->(promotion) { promotion.expires_at ? l(promotion.expires_at, format: :long) : icon_tag("infinity-line") }
101
+ }
102
+ ]
103
+ end
104
+
105
+ def solidus_promotions
106
+ @solidus_promotions ||= SolidusPromotions::Engine.routes.url_helpers
107
+ end
108
+ end
@@ -0,0 +1,10 @@
1
+ en:
2
+ scopes:
3
+ active: Active
4
+ draft: Draft
5
+ future: Future
6
+ expired: Expired
7
+ all: All
8
+ status:
9
+ active: Active
10
+ inactive: Inactive
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusPromotions
4
+ class PromotionCategoriesController < SolidusAdmin::BaseController
5
+ include SolidusAdmin::ControllerHelpers::Search
6
+
7
+ def index
8
+ promotion_categories = apply_search_to(
9
+ SolidusPromotions::PromotionCategory.all,
10
+ param: :q
11
+ )
12
+
13
+ set_page_and_extract_portion_from(promotion_categories)
14
+
15
+ respond_to do |format|
16
+ format.html { render component("promotion_categories/index").new(page: @page) }
17
+ end
18
+ end
19
+
20
+ def destroy
21
+ @promotion_categories = SolidusPromotions::PromotionCategory.where(id: params[:id])
22
+
23
+ SolidusPromotions::PromotionCategory.transaction { @promotion_categories.destroy_all }
24
+
25
+ flash[:notice] = t(".success")
26
+ redirect_back_or_to solidus_promotions.promotion_categories_path, status: :see_other
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusPromotions
4
+ class PromotionsController < SolidusAdmin::BaseController
5
+ include SolidusAdmin::ControllerHelpers::Search
6
+
7
+ search_scope(:active, default: true, &:active)
8
+ search_scope(:draft) { _1.where.not(id: _1.has_benefits.select(:id)) }
9
+ search_scope(:future) { _1.has_benefits.where(starts_at: Time.current..) }
10
+ search_scope(:expired) { _1.has_benefits.where(expires_at: ..Time.current) }
11
+ search_scope(:all)
12
+
13
+ def index
14
+ promotions = apply_search_to(
15
+ SolidusPromotions::Promotion.order(id: :desc),
16
+ param: :q
17
+ )
18
+
19
+ set_page_and_extract_portion_from(promotions)
20
+
21
+ respond_to do |format|
22
+ format.html { render component("promotions/index").new(page: @page) }
23
+ end
24
+ end
25
+
26
+ def destroy
27
+ @promotions = SolidusPromotions::Promotion.where(id: params[:id])
28
+
29
+ SolidusPromotions::Promotion.transaction { @promotions.destroy_all }
30
+
31
+ flash[:notice] = t(".success")
32
+ redirect_back_or_to promotions_path, status: :see_other
33
+ end
34
+
35
+ private
36
+
37
+ def load_promotion
38
+ @promotion = SolidusPromotions::Promotion.find_by!(number: params[:id])
39
+ authorize! action_name, @promotion
40
+ end
41
+
42
+ def promotion_params
43
+ params.require(:promotion).permit(:user_id, permitted_promotion_attributes)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusPromotions
4
+ module Admin
5
+ class BaseController < Spree::Admin::ResourceController
6
+ def routes_proxy
7
+ solidus_promotions
8
+ end
9
+
10
+ def parent_model_name
11
+ self.class.parent_data[:model_name].gsub("solidus_promotions/", "")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusPromotions
4
+ module Admin
5
+ class BenefitsController < Spree::Admin::BaseController
6
+ before_action :load_promotion, only: [:create, :destroy, :new, :update, :edit]
7
+ before_action :validate_benefit_type, only: [:create, :edit]
8
+
9
+ def new
10
+ @benefit = @promotion.benefits.build(benefit_params)
11
+ render layout: false
12
+ end
13
+
14
+ def create
15
+ @benefit = @benefit_type.new(benefit_params)
16
+ @benefit.promotion = @promotion
17
+ if @benefit.save(validate: false)
18
+ flash[:success] =
19
+ t("spree.successfully_created", resource: SolidusPromotions::Benefit.model_name.human)
20
+ redirect_to location_after_save, format: :html
21
+ else
22
+ render :new, layout: false
23
+ end
24
+ end
25
+
26
+ def edit
27
+ @benefit = @promotion.benefits.find(params[:id])
28
+ if params.dig(:benefit, :calculator_type)
29
+ @benefit.calculator_type = params[:benefit][:calculator_type]
30
+ end
31
+ render layout: false
32
+ end
33
+
34
+ def update
35
+ @benefit = @promotion.benefits.find(params[:id])
36
+ @benefit.assign_attributes(benefit_params)
37
+ if @benefit.save
38
+ flash[:success] =
39
+ t("spree.successfully_updated", resource: SolidusPromotions::Benefit.model_name.human)
40
+ redirect_to location_after_save, format: :html
41
+ else
42
+ render :edit
43
+ end
44
+ end
45
+
46
+ def destroy
47
+ @benefit = @promotion.benefits.find(params[:id])
48
+ if @benefit.destroy
49
+ flash[:success] =
50
+ t("spree.successfully_removed", resource: SolidusPromotions::Benefit.model_name.human)
51
+ end
52
+ redirect_to location_after_save, format: :html
53
+ end
54
+
55
+ private
56
+
57
+ def location_after_save
58
+ solidus_promotions.edit_admin_promotion_path(@promotion)
59
+ end
60
+
61
+ def load_promotion
62
+ @promotion = SolidusPromotions::Promotion.find(params[:promotion_id])
63
+ end
64
+
65
+ def benefit_params
66
+ params[:benefit].try(:permit!) || {}
67
+ end
68
+
69
+ def validate_benefit_type
70
+ requested_type = params[:benefit].delete(:type)
71
+ benefit_types = SolidusPromotions.config.benefits
72
+ @benefit_type = benefit_types.detect do |klass|
73
+ klass.name == requested_type
74
+ end
75
+ return if @benefit_type
76
+
77
+ flash[:error] = t("solidus_promotions.invalid_benefit")
78
+ respond_to do |format|
79
+ format.html { redirect_to solidus_promotions.edit_admin_promotion_path(@promotion) }
80
+ format.js { render layout: false }
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusPromotions
4
+ module Admin
5
+ class ConditionsController < Spree::Admin::BaseController
6
+ helper "solidus_promotions/admin/conditions"
7
+
8
+ before_action :load_benefit, only: [:create, :destroy, :update, :new]
9
+ rescue_from ActiveRecord::SubclassNotFound, with: :invalid_condition_error
10
+
11
+ def new
12
+ @condition = @benefit.conditions.build(condition_params)
13
+ render layout: false
14
+ end
15
+
16
+ def create
17
+ @condition = @benefit.conditions.build(condition_params)
18
+ if @condition.save
19
+ flash[:success] =
20
+ t("spree.successfully_created", resource: model_class.model_name.human)
21
+ end
22
+ redirect_to location_after_save
23
+ end
24
+
25
+ def update
26
+ @condition = @benefit.conditions.find(params[:id])
27
+ @condition.assign_attributes(condition_params)
28
+ if @condition.save
29
+ flash[:success] =
30
+ t("spree.successfully_updated", resource: model_class.model_name.human)
31
+ end
32
+ redirect_to location_after_save
33
+ end
34
+
35
+ def destroy
36
+ @condition = @benefit.conditions.find(params[:id])
37
+ if @condition.destroy
38
+ flash[:success] =
39
+ t("spree.successfully_removed", resource: model_class.model_name.human)
40
+ end
41
+ redirect_to location_after_save
42
+ end
43
+
44
+ private
45
+
46
+ def invalid_condition_error
47
+ flash[:error] = t("solidus_promotions.invalid_condition")
48
+ redirect_to location_after_save
49
+ end
50
+
51
+ def location_after_save
52
+ solidus_promotions.edit_admin_promotion_path(@promotion)
53
+ end
54
+
55
+ def load_benefit
56
+ @promotion = SolidusPromotions::Promotion.find(params[:promotion_id])
57
+ @benefit = @promotion.benefits.find(params[:benefit_id])
58
+ end
59
+
60
+ def model_class
61
+ SolidusPromotions::Condition
62
+ end
63
+
64
+ def condition_params
65
+ params[:condition].try(:permit!) || {}
66
+ end
67
+ end
68
+ end
69
+ end