solidus_promotions 4.4.0

Sign up to get free protection for your applications and to get access to all the features.
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