solidus_legacy_promotions 4.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +345 -0
  3. data/Rakefile +43 -0
  4. data/app/assets/config/solidus_legacy_promotions/manifest.js +2 -0
  5. data/app/assets/javascripts/spree/backend/edit_promotion.js +7 -0
  6. data/app/assets/javascripts/spree/backend/promotions/activation.js +26 -0
  7. data/app/assets/javascripts/spree/backend/promotions.js +35 -0
  8. data/app/assets/javascripts/spree/backend/templates/promotions/calculators/fields/tiered_flat_rate.hbs +23 -0
  9. data/app/assets/javascripts/spree/backend/templates/promotions/calculators/fields/tiered_percent.hbs +23 -0
  10. data/app/assets/javascripts/spree/backend/templates/promotions/rules/option_values.hbs +12 -0
  11. data/app/assets/javascripts/spree/backend/views/calculators/tiered.js +54 -0
  12. data/app/assets/javascripts/spree/backend/views/order/details_adjustments.js +43 -0
  13. data/app/assets/javascripts/spree/backend/views/promotions/option_values_rule.js +79 -0
  14. data/app/assets/javascripts/spree/backend/views/promotions.js +3 -0
  15. data/app/assets/stylesheets/solidus_legacy_promotions/promotions/_edit.scss +138 -0
  16. data/app/assets/stylesheets/solidus_legacy_promotions/promotions.scss +3 -0
  17. data/app/assets/stylesheets/spree/backend/sections/_adjustments.scss +3 -0
  18. data/app/decorators/solidus_legacy_promotions/controllers/solidus_admin/solidus_admin_adjustments_controller_decorator.rb +20 -0
  19. data/app/decorators/solidus_legacy_promotions/lib/spree_order_state_machine_decorator.rb +18 -0
  20. data/app/decorators/solidus_legacy_promotions/models/spree_adjustment_decorator.rb +76 -0
  21. data/app/decorators/solidus_legacy_promotions/models/spree_calculator_returns_default_refund_amount_decorator.rb +13 -0
  22. data/app/decorators/solidus_legacy_promotions/models/spree_line_item_decorator.rb +11 -0
  23. data/app/decorators/solidus_legacy_promotions/models/spree_order_decorator.rb +28 -0
  24. data/app/decorators/solidus_legacy_promotions/models/spree_order_updater_decorator.rb +40 -0
  25. data/app/decorators/solidus_legacy_promotions/models/spree_product_decorator.rb +16 -0
  26. data/app/decorators/solidus_legacy_promotions/models/spree_promotion_code_batch_decorator.rb +16 -0
  27. data/app/decorators/solidus_legacy_promotions/models/spree_shipment_decorator.rb +13 -0
  28. data/app/helpers/spree/admin/promotions_helper.rb +15 -0
  29. data/app/helpers/spree/promotion_rules_helper.rb +12 -0
  30. data/app/jobs/spree/promotion_code_batch_job.rb +26 -0
  31. data/app/mailers/spree/promotion_code_batch_mailer.rb +15 -0
  32. data/app/models/spree/calculator/distributed_amount.rb +33 -0
  33. data/app/models/spree/calculator/flat_percent_item_total.rb +23 -0
  34. data/app/models/spree/calculator/flexi_rate.rb +22 -0
  35. data/app/models/spree/calculator/percent_on_line_item.rb +13 -0
  36. data/app/models/spree/calculator/tiered_flat_rate.rb +52 -0
  37. data/app/models/spree/calculator/tiered_percent.rb +62 -0
  38. data/app/models/spree/order_contents.rb +36 -0
  39. data/app/models/spree/order_promotion.rb +27 -0
  40. data/app/models/spree/permission_sets/promotion_display.rb +25 -0
  41. data/app/models/spree/permission_sets/promotion_management.rb +25 -0
  42. data/app/models/spree/promotion/actions/create_adjustment.rb +81 -0
  43. data/app/models/spree/promotion/actions/create_item_adjustments.rb +98 -0
  44. data/app/models/spree/promotion/actions/create_quantity_adjustments.rb +139 -0
  45. data/app/models/spree/promotion/actions/free_shipping.rb +59 -0
  46. data/app/models/spree/promotion/order_adjustments_recalculator.rb +92 -0
  47. data/app/models/spree/promotion/rules/first_order.rb +36 -0
  48. data/app/models/spree/promotion/rules/first_repeat_purchase_since.rb +36 -0
  49. data/app/models/spree/promotion/rules/item_total.rb +86 -0
  50. data/app/models/spree/promotion/rules/minimum_quantity.rb +59 -0
  51. data/app/models/spree/promotion/rules/nth_order.rb +45 -0
  52. data/app/models/spree/promotion/rules/one_use_per_user.rb +25 -0
  53. data/app/models/spree/promotion/rules/option_value.rb +50 -0
  54. data/app/models/spree/promotion/rules/product.rb +86 -0
  55. data/app/models/spree/promotion/rules/store.rb +26 -0
  56. data/app/models/spree/promotion/rules/taxon.rb +91 -0
  57. data/app/models/spree/promotion/rules/user.rb +34 -0
  58. data/app/models/spree/promotion/rules/user_logged_in.rb +20 -0
  59. data/app/models/spree/promotion/rules/user_role.rb +45 -0
  60. data/app/models/spree/promotion.rb +271 -0
  61. data/app/models/spree/promotion_action.rb +51 -0
  62. data/app/models/spree/promotion_advertiser.rb +10 -0
  63. data/app/models/spree/promotion_category.rb +8 -0
  64. data/app/models/spree/promotion_chooser.rb +34 -0
  65. data/app/models/spree/promotion_code/batch_builder.rb +68 -0
  66. data/app/models/spree/promotion_code.rb +54 -0
  67. data/app/models/spree/promotion_code_batch.rb +18 -0
  68. data/app/models/spree/promotion_finder.rb +9 -0
  69. data/app/models/spree/promotion_handler/cart.rb +75 -0
  70. data/app/models/spree/promotion_handler/coupon.rb +125 -0
  71. data/app/models/spree/promotion_handler/page.rb +26 -0
  72. data/app/models/spree/promotion_handler/shipping.rb +61 -0
  73. data/app/models/spree/promotion_rule.rb +55 -0
  74. data/app/models/spree/promotion_rule_store.rb +10 -0
  75. data/app/models/spree/promotion_rule_taxon.rb +8 -0
  76. data/app/models/spree/promotion_rule_user.rb +10 -0
  77. data/app/subscribers/spree/order_promotion_subscriber.rb +20 -0
  78. data/app/views/spree/order_mailer/cancel_email.html.erb +45 -0
  79. data/app/views/spree/order_mailer/cancel_email.text.erb +16 -0
  80. data/app/views/spree/order_mailer/confirm_email.html.erb +84 -0
  81. data/app/views/spree/order_mailer/confirm_email.text.erb +38 -0
  82. data/app/views/spree/promotion_code_batch_mailer/promotion_code_batch_errored.text.erb +2 -0
  83. data/app/views/spree/promotion_code_batch_mailer/promotion_code_batch_finished.text.erb +2 -0
  84. data/bin/rails +13 -0
  85. data/config/locales/en.yml +101 -0
  86. data/config/locales/promotion_categories.en.yml +6 -0
  87. data/config/locales/promotions.en.yml +6 -0
  88. data/config/routes.rb +28 -0
  89. data/db/migrate/20160101010001_solidus_one_four_promotions.rb +126 -0
  90. data/db/migrate/20161017102621_create_spree_promotion_code_batch.rb +48 -0
  91. data/db/migrate/20180202190713_create_promotion_rule_stores.rb +14 -0
  92. data/db/migrate/20180328172631_add_join_characters_to_promotion_code_batch.rb +15 -0
  93. data/db/migrate/20190106184413_remove_code_from_spree_promotions.rb +46 -0
  94. data/db/migrate/20220317165036_set_promotions_with_any_policy_to_all_if_possible.rb +20 -0
  95. data/db/migrate/20230322085416_remove_match_policy_from_spree_promotion.rb +7 -0
  96. data/db/migrate/20230325132905_remove_unused_columns_from_promotion_rules.rb +10 -0
  97. data/db/migrate/20231027084517_add_order_promotions_foreign_key.rb +14 -0
  98. data/db/migrate/20240621100123_add_promotion_code_id_to_spree_adjustments.rb +10 -0
  99. data/db/migrate/20240622113334_move_adjustment_eligible_to_legacy_promotions.rb +11 -0
  100. data/lib/components/admin/solidus_admin/orders/show/adjustments/index/source/spree_promotion_action/component.rb +17 -0
  101. data/lib/components/admin/solidus_admin/promotion_categories/index/component.rb +56 -0
  102. data/lib/components/admin/solidus_admin/promotions/index/component.rb +104 -0
  103. data/lib/components/admin/solidus_admin/promotions/index/component.yml +10 -0
  104. data/lib/components/admin/solidus_legacy_promotions/orders/index/component.rb +15 -0
  105. data/lib/components/admin/solidus_legacy_promotions/orders/index/component.yml +20 -0
  106. data/lib/controllers/admin/solidus_admin/promotion_categories_controller.rb +29 -0
  107. data/lib/controllers/admin/solidus_admin/promotions_controller.rb +46 -0
  108. data/lib/controllers/backend/spree/admin/promotion_actions_controller.rb +51 -0
  109. data/lib/controllers/backend/spree/admin/promotion_categories_controller.rb +8 -0
  110. data/lib/controllers/backend/spree/admin/promotion_code_batches_controller.rb +30 -0
  111. data/lib/controllers/backend/spree/admin/promotion_codes_controller.rb +48 -0
  112. data/lib/controllers/backend/spree/admin/promotion_rules_controller.rb +60 -0
  113. data/lib/controllers/backend/spree/admin/promotions_controller.rb +66 -0
  114. data/lib/solidus_legacy_promotions/configuration.rb +115 -0
  115. data/lib/solidus_legacy_promotions/engine.rb +97 -0
  116. data/lib/solidus_legacy_promotions/migrations/promotions_with_code_handlers.rb +68 -0
  117. data/lib/solidus_legacy_promotions/testing_support/factories/calculator_factory.rb +7 -0
  118. data/lib/solidus_legacy_promotions/testing_support/factories/order_factory.rb +22 -0
  119. data/lib/solidus_legacy_promotions/testing_support/factories/order_promotion_factory.rb +8 -0
  120. data/lib/solidus_legacy_promotions/testing_support/factories/promotion_category_factory.rb +7 -0
  121. data/lib/solidus_legacy_promotions/testing_support/factories/promotion_code_factory.rb +8 -0
  122. data/lib/solidus_legacy_promotions/testing_support/factories/promotion_factory.rb +98 -0
  123. data/lib/solidus_legacy_promotions/testing_support/factory_bot.rb +28 -0
  124. data/lib/solidus_legacy_promotions.rb +28 -0
  125. data/lib/tasks/solidus_legacy_promotions/delete_ineligible_adjustments.rake +8 -0
  126. data/lib/views/backend/spree/admin/adjustments/_adjustment.html.erb +24 -0
  127. data/lib/views/backend/spree/admin/orders/_adjustments.html.erb +19 -0
  128. data/lib/views/backend/spree/admin/orders/_order_details.html.erb +32 -0
  129. data/lib/views/backend/spree/admin/orders/confirm.html.erb +59 -0
  130. data/lib/views/backend/spree/admin/promotion_actions/create.js.erb +10 -0
  131. data/lib/views/backend/spree/admin/promotion_actions/destroy.js.erb +1 -0
  132. data/lib/views/backend/spree/admin/promotion_categories/_form.html.erb +14 -0
  133. data/lib/views/backend/spree/admin/promotion_categories/edit.html.erb +10 -0
  134. data/lib/views/backend/spree/admin/promotion_categories/index.html.erb +47 -0
  135. data/lib/views/backend/spree/admin/promotion_categories/new.html.erb +10 -0
  136. data/lib/views/backend/spree/admin/promotion_code_batches/_form_fields.html.erb +22 -0
  137. data/lib/views/backend/spree/admin/promotion_code_batches/download.csv.ruby +8 -0
  138. data/lib/views/backend/spree/admin/promotion_code_batches/index.html.erb +65 -0
  139. data/lib/views/backend/spree/admin/promotion_code_batches/new.html.erb +8 -0
  140. data/lib/views/backend/spree/admin/promotion_codes/index.csv.ruby +8 -0
  141. data/lib/views/backend/spree/admin/promotion_codes/index.html.erb +32 -0
  142. data/lib/views/backend/spree/admin/promotion_codes/new.html.erb +31 -0
  143. data/lib/views/backend/spree/admin/promotion_rules/create.js.erb +8 -0
  144. data/lib/views/backend/spree/admin/promotion_rules/destroy.js.erb +3 -0
  145. data/lib/views/backend/spree/admin/promotions/_actions.html.erb +37 -0
  146. data/lib/views/backend/spree/admin/promotions/_activations_edit.html.erb +22 -0
  147. data/lib/views/backend/spree/admin/promotions/_activations_new.html.erb +43 -0
  148. data/lib/views/backend/spree/admin/promotions/_form.html.erb +67 -0
  149. data/lib/views/backend/spree/admin/promotions/_promotion_action.html.erb +13 -0
  150. data/lib/views/backend/spree/admin/promotions/_promotion_rule.html.erb +12 -0
  151. data/lib/views/backend/spree/admin/promotions/_rules.html.erb +42 -0
  152. data/lib/views/backend/spree/admin/promotions/actions/_create_adjustment.html.erb +2 -0
  153. data/lib/views/backend/spree/admin/promotions/actions/_create_item_adjustments.html.erb +6 -0
  154. data/lib/views/backend/spree/admin/promotions/actions/_create_quantity_adjustments.html.erb +10 -0
  155. data/lib/views/backend/spree/admin/promotions/actions/_free_shipping.html.erb +0 -0
  156. data/lib/views/backend/spree/admin/promotions/actions/_promotion_calculators_with_custom_fields.html.erb +29 -0
  157. data/lib/views/backend/spree/admin/promotions/calculators/_default_fields.html.erb +6 -0
  158. data/lib/views/backend/spree/admin/promotions/calculators/distributed_amount/_fields.html.erb +56 -0
  159. data/lib/views/backend/spree/admin/promotions/calculators/flat_rate/_fields.html.erb +6 -0
  160. data/lib/views/backend/spree/admin/promotions/calculators/tiered_flat_rate/_fields.html.erb +30 -0
  161. data/lib/views/backend/spree/admin/promotions/calculators/tiered_percent/_fields.html.erb +30 -0
  162. data/lib/views/backend/spree/admin/promotions/edit.html.erb +40 -0
  163. data/lib/views/backend/spree/admin/promotions/index.html.erb +124 -0
  164. data/lib/views/backend/spree/admin/promotions/new.html.erb +14 -0
  165. data/lib/views/backend/spree/admin/promotions/rules/_first_order.html.erb +0 -0
  166. data/lib/views/backend/spree/admin/promotions/rules/_first_repeat_purchase_since.html.erb +13 -0
  167. data/lib/views/backend/spree/admin/promotions/rules/_item_total.html.erb +14 -0
  168. data/lib/views/backend/spree/admin/promotions/rules/_minimum_quantity.html.erb +5 -0
  169. data/lib/views/backend/spree/admin/promotions/rules/_nth_order.html.erb +12 -0
  170. data/lib/views/backend/spree/admin/promotions/rules/_one_use_per_user.html.erb +0 -0
  171. data/lib/views/backend/spree/admin/promotions/rules/_option_value.html.erb +13 -0
  172. data/lib/views/backend/spree/admin/promotions/rules/_product.html.erb +15 -0
  173. data/lib/views/backend/spree/admin/promotions/rules/_store.html.erb +6 -0
  174. data/lib/views/backend/spree/admin/promotions/rules/_taxon.html.erb +9 -0
  175. data/lib/views/backend/spree/admin/promotions/rules/_user.html.erb +4 -0
  176. data/lib/views/backend/spree/admin/promotions/rules/_user_logged_in.html.erb +0 -0
  177. data/lib/views/backend/spree/admin/promotions/rules/_user_role.html.erb +12 -0
  178. data/solidus_legacy_promotions.gemspec +29 -0
  179. metadata +262 -0
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SolidusOneFourPromotions < ActiveRecord::Migration[5.0]
4
+ def up
5
+ unless table_exists?(:spree_orders_promotions)
6
+ create_table "spree_orders_promotions", force: :cascade do |t|
7
+ t.integer "order_id"
8
+ t.integer "promotion_id"
9
+ t.integer "promotion_code_id"
10
+ t.datetime "created_at", precision: 6
11
+ t.datetime "updated_at", precision: 6
12
+ t.index ["order_id", "promotion_id"], name: "index_spree_orders_promotions_on_order_id_and_promotion_id"
13
+ t.index ["promotion_code_id"], name: "index_spree_orders_promotions_on_promotion_code_id"
14
+ end
15
+ end
16
+
17
+ unless table_exists?(:spree_product_promotion_rules)
18
+ create_table "spree_product_promotion_rules", force: :cascade do |t|
19
+ t.integer "product_id"
20
+ t.integer "promotion_rule_id"
21
+ t.datetime "created_at", precision: 6
22
+ t.datetime "updated_at", precision: 6
23
+ t.index ["product_id"], name: "index_products_promotion_rules_on_product_id"
24
+ t.index ["promotion_rule_id"], name: "index_products_promotion_rules_on_promotion_rule_id"
25
+ end
26
+ end
27
+
28
+ unless table_exists?(:spree_promotion_actions)
29
+ create_table "spree_promotion_actions", force: :cascade do |t|
30
+ t.integer "promotion_id"
31
+ t.integer "position"
32
+ t.string "type"
33
+ t.datetime "deleted_at"
34
+ t.text "preferences"
35
+ t.datetime "created_at", precision: 6
36
+ t.datetime "updated_at", precision: 6
37
+ t.index ["deleted_at"], name: "index_spree_promotion_actions_on_deleted_at"
38
+ t.index ["id", "type"], name: "index_spree_promotion_actions_on_id_and_type"
39
+ t.index ["promotion_id"], name: "index_spree_promotion_actions_on_promotion_id"
40
+ end
41
+ end
42
+
43
+ unless table_exists?(:spree_promotion_categories)
44
+ create_table "spree_promotion_categories", force: :cascade do |t|
45
+ t.string "name"
46
+ t.datetime "created_at", precision: 6
47
+ t.datetime "updated_at", precision: 6
48
+ t.string "code"
49
+ end
50
+ end
51
+
52
+ unless table_exists?(:spree_promotion_codes)
53
+ create_table "spree_promotion_codes", force: :cascade do |t|
54
+ t.integer "promotion_id", null: false
55
+ t.string "value", null: false
56
+ t.datetime "created_at", precision: 6
57
+ t.datetime "updated_at", precision: 6
58
+ t.index ["promotion_id"], name: "index_spree_promotion_codes_on_promotion_id"
59
+ t.index ["value"], name: "index_spree_promotion_codes_on_value", unique: true
60
+ end
61
+ end
62
+
63
+ unless table_exists?(:spree_promotion_rule_taxons)
64
+ create_table "spree_promotion_rule_taxons", force: :cascade do |t|
65
+ t.integer "taxon_id"
66
+ t.integer "promotion_rule_id"
67
+ t.datetime "created_at", precision: 6
68
+ t.datetime "updated_at", precision: 6
69
+ t.index ["promotion_rule_id"], name: "index_spree_promotion_rule_taxons_on_promotion_rule_id"
70
+ t.index ["taxon_id"], name: "index_spree_promotion_rule_taxons_on_taxon_id"
71
+ end
72
+ end
73
+
74
+ unless table_exists?(:spree_promotion_rules)
75
+ create_table "spree_promotion_rules", force: :cascade do |t|
76
+ t.integer "promotion_id"
77
+ t.integer "product_group_id"
78
+ t.string "type"
79
+ t.datetime "created_at", precision: 6
80
+ t.datetime "updated_at", precision: 6
81
+ t.string "code"
82
+ t.text "preferences"
83
+ t.index ["product_group_id"], name: "index_promotion_rules_on_product_group_id"
84
+ t.index ["promotion_id"], name: "index_spree_promotion_rules_on_promotion_id"
85
+ end
86
+ end
87
+
88
+ unless table_exists?(:spree_promotion_rules_users)
89
+ create_table "spree_promotion_rules_users", force: :cascade do |t|
90
+ t.integer "user_id"
91
+ t.integer "promotion_rule_id"
92
+ t.datetime "created_at", precision: 6
93
+ t.datetime "updated_at", precision: 6
94
+ t.index ["promotion_rule_id"], name: "index_promotion_rules_users_on_promotion_rule_id"
95
+ t.index ["user_id"], name: "index_promotion_rules_users_on_user_id"
96
+ end
97
+ end
98
+
99
+ unless table_exists?(:spree_promotions)
100
+ create_table "spree_promotions", force: :cascade do |t|
101
+ t.string "description"
102
+ t.datetime "expires_at"
103
+ t.datetime "starts_at"
104
+ t.string "name"
105
+ t.string "type"
106
+ t.integer "usage_limit"
107
+ t.string "match_policy", default: "all"
108
+ t.string "code"
109
+ t.boolean "advertise", default: false
110
+ t.string "path"
111
+ t.datetime "created_at", precision: 6
112
+ t.datetime "updated_at", precision: 6
113
+ t.integer "promotion_category_id"
114
+ t.integer "per_code_usage_limit"
115
+ t.boolean "apply_automatically", default: false
116
+ t.index ["advertise"], name: "index_spree_promotions_on_advertise"
117
+ t.index ["apply_automatically"], name: "index_spree_promotions_on_apply_automatically"
118
+ t.index ["code"], name: "index_spree_promotions_on_code"
119
+ t.index ["expires_at"], name: "index_spree_promotions_on_expires_at"
120
+ t.index ["id", "type"], name: "index_spree_promotions_on_id_and_type"
121
+ t.index ["promotion_category_id"], name: "index_spree_promotions_on_promotion_category_id"
122
+ t.index ["starts_at"], name: "index_spree_promotions_on_starts_at"
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateSpreePromotionCodeBatch < ActiveRecord::Migration[5.0]
4
+ def change
5
+ unless table_exists?(:spree_promotion_code_batches)
6
+ create_table :spree_promotion_code_batches do |t|
7
+ t.references :promotion, null: false, index: true, type: :integer
8
+ t.string :base_code, null: false
9
+ t.integer :number_of_codes, null: false
10
+ t.string :email
11
+ t.string :error
12
+ t.string :state, default: "pending"
13
+ t.timestamps precision: 6
14
+ end
15
+ end
16
+
17
+ unless foreign_key_exists?(:spree_promotion_code_batches, :spree_promotions)
18
+ add_foreign_key(
19
+ :spree_promotion_code_batches,
20
+ :spree_promotions,
21
+ column: :promotion_id
22
+ )
23
+ end
24
+
25
+ unless column_exists?(:spree_promotion_codes, :promotion_code_batch_id)
26
+ add_column(
27
+ :spree_promotion_codes,
28
+ :promotion_code_batch_id,
29
+ :integer,
30
+ )
31
+ end
32
+
33
+ unless foreign_key_exists?(:spree_promotion_codes, :spree_promotion_code_batches)
34
+ add_foreign_key(
35
+ :spree_promotion_codes,
36
+ :spree_promotion_code_batches,
37
+ column: :promotion_code_batch_id,
38
+ )
39
+ end
40
+
41
+ unless index_exists?(:spree_promotion_codes, :promotion_code_batch_id)
42
+ add_index(
43
+ :spree_promotion_codes,
44
+ :promotion_code_batch_id,
45
+ )
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreatePromotionRuleStores < ActiveRecord::Migration[5.1]
4
+ def change
5
+ unless table_exists?(:spree_promotion_rules_stores)
6
+ create_table :spree_promotion_rules_stores do |t|
7
+ t.references :store, null: false
8
+ t.references :promotion_rule, null: false
9
+
10
+ t.timestamps
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddJoinCharactersToPromotionCodeBatch < ActiveRecord::Migration[5.1]
4
+ def change
5
+ unless column_exists?(:spree_promotion_code_batches, :join_characters)
6
+ add_column(
7
+ :spree_promotion_code_batches,
8
+ :join_characters,
9
+ :string,
10
+ null: false,
11
+ default: "_"
12
+ )
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'solidus_legacy_promotions/migrations/promotions_with_code_handlers'
4
+
5
+ class RemoveCodeFromSpreePromotions < ActiveRecord::Migration[5.1]
6
+ class Promotion < ActiveRecord::Base
7
+ self.table_name = "spree_promotions"
8
+ self.ignored_columns = %w(type)
9
+ end
10
+
11
+ def up
12
+ if column_exists?(:spree_promotions, :code)
13
+ promotions_with_code = Promotion.where.not(code: [nil, ''])
14
+
15
+ if promotions_with_code.any?
16
+ # You have some promotions with "code" field present! This is not good
17
+ # since we are going to remove that column.
18
+ #
19
+ self.class.promotions_with_code_handler.new(self, promotions_with_code).call
20
+ end
21
+
22
+ remove_index :spree_promotions, name: :index_spree_promotions_on_code
23
+ remove_column :spree_promotions, :code
24
+ end
25
+ end
26
+
27
+ def down
28
+ unless column_exists?(:spree_promotions, :code)
29
+ add_column :spree_promotions, :code, :string
30
+ add_index :spree_promotions, :code, name: :index_spree_promotions_on_code
31
+ end
32
+ end
33
+
34
+ def self.promotions_with_code_handler
35
+ # We propose different approaches, just pick the one that you prefer or
36
+ # write your custom one.
37
+ #
38
+ # The fist one (raising an exception) is the default but you can
39
+ # comment/uncomment the one then better fits you needs or use a
40
+ # custom class or callable object.
41
+ #
42
+ SolidusLegacyPromotions::Migrations::PromotionWithCodeHandlers::RaiseException
43
+ # SolidusLegacyPromotions::Migrations::PromotionWithCodeHandlers::MoveToSpreePromotionCode
44
+ # SolidusLegacyPromotions::Migrations::PromotionWithCodeHandlers::DoNothing
45
+ end
46
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SetPromotionsWithAnyPolicyToAllIfPossible < ActiveRecord::Migration[5.2]
4
+ def up
5
+ Spree::Promotion.where(match_policy: :any).includes(:promotion_rules).all.find_each do |promotion|
6
+ if promotion.promotion_rules.length <= 1
7
+ promotion.update!(match_policy: :all)
8
+ else
9
+ raise StandardError, <<~MSG
10
+ You have promotions with a match policy of any and more than one rule. Please
11
+ run `bundle exec rake solidus:split_promotions_with_any_match_policy`.
12
+ MSG
13
+ end
14
+ end
15
+ end
16
+
17
+ def down
18
+ # No-Op
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ class RemoveMatchPolicyFromSpreePromotion < ActiveRecord::Migration[5.2]
2
+ def change
3
+ if column_exists?(:spree_promotions, :match_policy)
4
+ remove_column :spree_promotions, :match_policy, :string, default: "all"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ class RemoveUnusedColumnsFromPromotionRules < ActiveRecord::Migration[5.2]
2
+ def change
3
+ if column_exists?(:spree_promotion_rules, :code)
4
+ remove_column :spree_promotion_rules, :code, :string
5
+ end
6
+ if column_exists?(:spree_promotion_rules, :product_group_id)
7
+ remove_column :spree_promotion_rules, :product_group_id, :integer
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ class AddOrderPromotionsForeignKey < ActiveRecord::Migration[7.0]
2
+ def up
3
+ Spree::OrderPromotion.left_joins(:order).where(spree_orders: { id: nil }).delete_all
4
+ unless foreign_key_exists?(:spree_orders_promotions, :spree_orders, column: :order_id)
5
+ add_foreign_key :spree_orders_promotions, :spree_orders, column: :order_id, validate: false, on_delete: :cascade
6
+ end
7
+ end
8
+
9
+ def down
10
+ if foreign_key_exists?(:spree_orders_promotions, :spree_orders, column: :order_id)
11
+ remove_foreign_key :spree_orders_promotions, :spree_orders_promotions
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ class AddPromotionCodeIdToSpreeAdjustments < ActiveRecord::Migration[5.0]
2
+ def up
3
+ unless column_exists?(:spree_adjustments, :promotion_code_id)
4
+ add_column :spree_adjustments, :promotion_code_id, :integer
5
+ end
6
+ unless index_exists?(:spree_adjustments, :promotion_code_id)
7
+ add_index :spree_adjustments, :promotion_code_id, name: "index_spree_adjustments_on_promotion_code_id"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ class MoveAdjustmentEligibleToLegacyPromotions < ActiveRecord::Migration[7.0]
2
+ def up
3
+ unless column_exists?(:spree_adjustments, :eligible)
4
+ add_column(:spree_adjustments, :eligible, :boolean, default: true)
5
+ end
6
+
7
+ unless index_exists?(:spree_adjustments, :eligible)
8
+ add_index :spree_adjustments, :eligible, name: "index_spree_adjustments_on_eligible"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SolidusAdmin::Orders::Show::Adjustments::Index::Source::SpreePromotionAction::Component < SolidusAdmin::Orders::Show::Adjustments::Index::Source::Component
4
+ def icon
5
+ "megaphone-line"
6
+ end
7
+
8
+ def detail
9
+ link_to("#{model_name}: #{promotion_name}", spree.edit_admin_promotion_path(adjustment.source_id), class: "body-link")
10
+ end
11
+
12
+ private
13
+
14
+ def promotion_name
15
+ source.promotion.name
16
+ end
17
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SolidusAdmin::PromotionCategories::Index::Component < SolidusAdmin::UI::Pages::Index::Component
4
+ def model_class
5
+ Spree::PromotionCategory
6
+ end
7
+
8
+ def row_url(promotion_category)
9
+ spree.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: spree.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_admin.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
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SolidusAdmin::Promotions::Index::Component < SolidusAdmin::UI::Pages::Index::Component
4
+ def model_class
5
+ Spree::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_admin.promotions_path
14
+ end
15
+
16
+ def row_url(promotion)
17
+ spree.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: spree.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_admin.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: Spree::PromotionCategory.model_name.human.pluralize,
54
+ attribute: "promotion_category_id",
55
+ predicate: "in",
56
+ options: Spree::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:)
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
+ 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,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SolidusLegacyPromotions::Orders::Index::Component < SolidusAdmin::Orders::Index::Component
4
+ def filters
5
+ super + [
6
+ {
7
+ label: t('.filters.promotions'),
8
+ combinator: 'or',
9
+ attribute: "promotions_id",
10
+ predicate: "in",
11
+ options: Spree::Promotion.all.pluck(:name, :id),
12
+ }
13
+ ]
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ en:
2
+ columns:
3
+ items:
4
+ one: 1 Item
5
+ other: '%{count} Items'
6
+ filters:
7
+ status: Status
8
+ shipment_state: Shipment State
9
+ payment_state: Payment State
10
+ promotions: Promotions
11
+ date:
12
+ formats:
13
+ short: '%d %b %y'
14
+ scopes:
15
+ all_orders: All
16
+ canceled: Canceled
17
+ complete: Complete
18
+ returned: Returned
19
+ in_progress: In Progress
20
+ promotions: Promotions
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusAdmin
4
+ class PromotionCategoriesController < SolidusAdmin::BaseController
5
+ include SolidusAdmin::ControllerHelpers::Search
6
+
7
+ def index
8
+ promotion_categories = apply_search_to(
9
+ Spree::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 = Spree::PromotionCategory.where(id: params[:id])
22
+
23
+ Spree::PromotionCategory.transaction { @promotion_categories.destroy_all }
24
+
25
+ flash[:notice] = t('.success')
26
+ redirect_back_or_to promotion_categories_path, status: :see_other
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusAdmin
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_actions.select(:id)) }
9
+ search_scope(:future) { _1.has_actions.where(starts_at: Time.current..) }
10
+ search_scope(:expired) { _1.has_actions.where(expires_at: ..Time.current) }
11
+ search_scope(:all)
12
+
13
+ def index
14
+ promotions = apply_search_to(
15
+ Spree::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 = Spree::Promotion.where(id: params[:id])
28
+
29
+ Spree::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 = Spree::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