solidus_friendly_promotions 1.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (214) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +61 -0
  3. data/.gem_release.yml +5 -0
  4. data/.github/stale.yml +1 -0
  5. data/.github_changelog_generator +2 -0
  6. data/.gitignore +21 -0
  7. data/.rspec +2 -0
  8. data/.rubocop.yml +29 -0
  9. data/.rubocop_todo.yml +157 -0
  10. data/.standard.yml +4 -0
  11. data/CHANGELOG.md +1 -0
  12. data/Gemfile +42 -0
  13. data/LICENSE +26 -0
  14. data/MIGRATING.md +134 -0
  15. data/README.md +144 -0
  16. data/Rakefile +7 -0
  17. data/app/assets/config/solidus_friendly_promotions/manifest.js +7 -0
  18. data/app/controllers/solidus_friendly_promotions/admin/base_controller.rb +54 -0
  19. data/app/controllers/solidus_friendly_promotions/admin/promotion_actions_controller.rb +103 -0
  20. data/app/controllers/solidus_friendly_promotions/admin/promotion_categories_controller.rb +13 -0
  21. data/app/controllers/solidus_friendly_promotions/admin/promotion_code_batches_controller.rb +30 -0
  22. data/app/controllers/solidus_friendly_promotions/admin/promotion_codes_controller.rb +58 -0
  23. data/app/controllers/solidus_friendly_promotions/admin/promotion_rules_controller.rb +105 -0
  24. data/app/controllers/solidus_friendly_promotions/admin/promotions_controller.rb +64 -0
  25. data/app/decorators/models/solidus_friendly_promotions/adjustment_decorator.rb +26 -0
  26. data/app/decorators/models/solidus_friendly_promotions/line_item_decorator.rb +7 -0
  27. data/app/decorators/models/solidus_friendly_promotions/order_decorator.rb +42 -0
  28. data/app/decorators/models/solidus_friendly_promotions/order_recalculator_decorator.rb +13 -0
  29. data/app/decorators/models/solidus_friendly_promotions/shipment_decorator.rb +14 -0
  30. data/app/decorators/models/solidus_friendly_promotions/shipping_rate_decorator.rb +29 -0
  31. data/app/helpers/solidus_friendly_promotions/admin/promotion_actions_helper.rb +23 -0
  32. data/app/helpers/solidus_friendly_promotions/admin/promotion_rules_helper.rb +25 -0
  33. data/app/javascript/solidus_friendly_promotions/controllers/application.js +9 -0
  34. data/app/javascript/solidus_friendly_promotions/controllers/calculator_tiers_controller.js +37 -0
  35. data/app/javascript/solidus_friendly_promotions/controllers/flash_controller.js +10 -0
  36. data/app/javascript/solidus_friendly_promotions/controllers/index.js +8 -0
  37. data/app/javascript/solidus_friendly_promotions/controllers/product_option_values_controller.js +62 -0
  38. data/app/javascript/solidus_friendly_promotions/jquery/option_value_picker.js +44 -0
  39. data/app/javascript/solidus_friendly_promotions.js +12 -0
  40. data/app/jobs/solidus_friendly_promotions/promotion_code_batch_job.rb +26 -0
  41. data/app/mailers/solidus_friendly_promotions/promotion_code_batch_mailer.rb +15 -0
  42. data/app/models/concerns/solidus_friendly_promotions/discountable_amount.rb +21 -0
  43. data/app/models/concerns/solidus_friendly_promotions/rules/line_item_applicable_order_rule.rb +23 -0
  44. data/app/models/concerns/solidus_friendly_promotions/rules/line_item_level_rule.rb +15 -0
  45. data/app/models/concerns/solidus_friendly_promotions/rules/order_level_rule.rb +15 -0
  46. data/app/models/concerns/solidus_friendly_promotions/rules/shipment_level_rule.rb +15 -0
  47. data/app/models/solidus_friendly_promotions/actions/adjust_line_item.rb +15 -0
  48. data/app/models/solidus_friendly_promotions/actions/adjust_line_item_quantity_groups.rb +116 -0
  49. data/app/models/solidus_friendly_promotions/actions/adjust_shipment.rb +15 -0
  50. data/app/models/solidus_friendly_promotions/calculators/distributed_amount.rb +37 -0
  51. data/app/models/solidus_friendly_promotions/calculators/flat_rate.rb +21 -0
  52. data/app/models/solidus_friendly_promotions/calculators/flexi_rate.rb +24 -0
  53. data/app/models/solidus_friendly_promotions/calculators/percent.rb +17 -0
  54. data/app/models/solidus_friendly_promotions/calculators/tiered_flat_rate.rb +56 -0
  55. data/app/models/solidus_friendly_promotions/calculators/tiered_percent.rb +66 -0
  56. data/app/models/solidus_friendly_promotions/distributed_amounts_handler.rb +43 -0
  57. data/app/models/solidus_friendly_promotions/eligibility_result.rb +5 -0
  58. data/app/models/solidus_friendly_promotions/eligibility_results.rb +48 -0
  59. data/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/choose_discounts.rb +21 -0
  60. data/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/discount_order.rb +76 -0
  61. data/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/load_promotions.rb +54 -0
  62. data/app/models/solidus_friendly_promotions/friendly_promotion_adjuster/persist_discounted_order.rb +81 -0
  63. data/app/models/solidus_friendly_promotions/friendly_promotion_adjuster.rb +25 -0
  64. data/app/models/solidus_friendly_promotions/item_discount.rb +21 -0
  65. data/app/models/solidus_friendly_promotions/migration_support/order_promotion_syncer.rb +54 -0
  66. data/app/models/solidus_friendly_promotions/order_promotion.rb +23 -0
  67. data/app/models/solidus_friendly_promotions/permission_sets/friendly_promotion_management.rb +15 -0
  68. data/app/models/solidus_friendly_promotions/products_promotion_rule.rb +8 -0
  69. data/app/models/solidus_friendly_promotions/promotion.rb +166 -0
  70. data/app/models/solidus_friendly_promotions/promotion_action.rb +73 -0
  71. data/app/models/solidus_friendly_promotions/promotion_category.rb +9 -0
  72. data/app/models/solidus_friendly_promotions/promotion_code/batch_builder.rb +72 -0
  73. data/app/models/solidus_friendly_promotions/promotion_code.rb +55 -0
  74. data/app/models/solidus_friendly_promotions/promotion_code_batch.rb +25 -0
  75. data/app/models/solidus_friendly_promotions/promotion_handler/coupon.rb +113 -0
  76. data/app/models/solidus_friendly_promotions/promotion_handler/page.rb +30 -0
  77. data/app/models/solidus_friendly_promotions/promotion_rule.rb +55 -0
  78. data/app/models/solidus_friendly_promotions/promotion_rules_store.rb +8 -0
  79. data/app/models/solidus_friendly_promotions/promotion_rules_taxon.rb +8 -0
  80. data/app/models/solidus_friendly_promotions/promotion_rules_user.rb +8 -0
  81. data/app/models/solidus_friendly_promotions/rules/discounted_item_total.rb +22 -0
  82. data/app/models/solidus_friendly_promotions/rules/first_order.rb +31 -0
  83. data/app/models/solidus_friendly_promotions/rules/first_repeat_purchase_since.rb +31 -0
  84. data/app/models/solidus_friendly_promotions/rules/item_total.rb +86 -0
  85. data/app/models/solidus_friendly_promotions/rules/line_item_option_value.rb +37 -0
  86. data/app/models/solidus_friendly_promotions/rules/line_item_product.rb +52 -0
  87. data/app/models/solidus_friendly_promotions/rules/line_item_taxon.rb +55 -0
  88. data/app/models/solidus_friendly_promotions/rules/minimum_quantity.rb +48 -0
  89. data/app/models/solidus_friendly_promotions/rules/nth_order.rb +40 -0
  90. data/app/models/solidus_friendly_promotions/rules/one_use_per_user.rb +25 -0
  91. data/app/models/solidus_friendly_promotions/rules/option_value.rb +28 -0
  92. data/app/models/solidus_friendly_promotions/rules/product.rb +85 -0
  93. data/app/models/solidus_friendly_promotions/rules/shipping_method.rb +19 -0
  94. data/app/models/solidus_friendly_promotions/rules/store.rb +26 -0
  95. data/app/models/solidus_friendly_promotions/rules/taxon.rb +98 -0
  96. data/app/models/solidus_friendly_promotions/rules/user.rb +35 -0
  97. data/app/models/solidus_friendly_promotions/rules/user_logged_in.rb +16 -0
  98. data/app/models/solidus_friendly_promotions/rules/user_role.rb +42 -0
  99. data/app/models/solidus_friendly_promotions/shipping_rate_discount.rb +11 -0
  100. data/app/models/solidus_friendly_promotions/simple_order_contents.rb +27 -0
  101. data/app/models/solidus_friendly_promotions.rb +7 -0
  102. data/app/views/solidus_friendly_promotions/admin/promotion_actions/_calculator_select.html.erb +16 -0
  103. data/app/views/solidus_friendly_promotions/admin/promotion_actions/_form.html.erb +3 -0
  104. data/app/views/solidus_friendly_promotions/admin/promotion_actions/_promotion_action.html.erb +29 -0
  105. data/app/views/solidus_friendly_promotions/admin/promotion_actions/_type_select.html.erb +14 -0
  106. data/app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_adjust_line_item.html.erb +6 -0
  107. data/app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_adjust_line_item_quantity_groups.html.erb +13 -0
  108. data/app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_adjust_shipment.html.erb +6 -0
  109. data/app/views/solidus_friendly_promotions/admin/promotion_actions/actions/_calculator_fields.erb +8 -0
  110. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/_default_fields.html.erb +6 -0
  111. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/distributed_amount/_fields.html.erb +56 -0
  112. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/flat_rate/_fields.html.erb +6 -0
  113. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_flat_rate/_fields.html.erb +34 -0
  114. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_flat_rate/_tier_fields.html.erb +32 -0
  115. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_percent/_fields.html.erb +34 -0
  116. data/app/views/solidus_friendly_promotions/admin/promotion_actions/calculators/tiered_percent/_tier_fields.html.erb +32 -0
  117. data/app/views/solidus_friendly_promotions/admin/promotion_actions/edit.html.erb +23 -0
  118. data/app/views/solidus_friendly_promotions/admin/promotion_actions/new.html.erb +26 -0
  119. data/app/views/solidus_friendly_promotions/admin/promotion_categories/_form.html.erb +14 -0
  120. data/app/views/solidus_friendly_promotions/admin/promotion_categories/edit.html.erb +10 -0
  121. data/app/views/solidus_friendly_promotions/admin/promotion_categories/index.html.erb +47 -0
  122. data/app/views/solidus_friendly_promotions/admin/promotion_categories/new.html.erb +10 -0
  123. data/app/views/solidus_friendly_promotions/admin/promotion_codes/index.csv.ruby +8 -0
  124. data/app/views/solidus_friendly_promotions/admin/promotion_codes/index.html.erb +32 -0
  125. data/app/views/solidus_friendly_promotions/admin/promotion_codes/new.html.erb +31 -0
  126. data/app/views/solidus_friendly_promotions/admin/promotion_rules/_promotion_rule.html.erb +22 -0
  127. data/app/views/solidus_friendly_promotions/admin/promotion_rules/_type_select.html.erb +20 -0
  128. data/app/views/solidus_friendly_promotions/admin/promotion_rules/new.html.erb +24 -0
  129. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_first_order.html.erb +3 -0
  130. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_first_repeat_purchase_since.html.erb +6 -0
  131. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_item_total.html.erb +17 -0
  132. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_line_item_option_value.html.erb +25 -0
  133. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_line_item_product.html.erb +21 -0
  134. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_line_item_taxon.html.erb +17 -0
  135. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_minimum_quantity.html.erb +5 -0
  136. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_nth_order.html.erb +15 -0
  137. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_one_use_per_user.html.erb +3 -0
  138. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_option_value.html.erb +63 -0
  139. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_product.html.erb +44 -0
  140. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_shipping_method.html.erb +10 -0
  141. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_store.html.erb +9 -0
  142. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_taxon.html.erb +44 -0
  143. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_user.html.erb +7 -0
  144. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_user_logged_in.html.erb +3 -0
  145. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/_user_role.html.erb +15 -0
  146. data/app/views/solidus_friendly_promotions/admin/promotion_rules/rules/line_item_option_value/_option_value_fields.html.erb +17 -0
  147. data/app/views/solidus_friendly_promotions/admin/promotions/_activations_edit.html.erb +22 -0
  148. data/app/views/solidus_friendly_promotions/admin/promotions/_activations_new.html.erb +43 -0
  149. data/app/views/solidus_friendly_promotions/admin/promotions/_form.html.erb +96 -0
  150. data/app/views/solidus_friendly_promotions/admin/promotions/edit.html.erb +73 -0
  151. data/app/views/solidus_friendly_promotions/admin/promotions/index.html.erb +124 -0
  152. data/app/views/solidus_friendly_promotions/admin/promotions/new.html.erb +9 -0
  153. data/app/views/solidus_friendly_promotions/admin/shared/_promotion_sub_menu.html.erb +14 -0
  154. data/app/views/solidus_friendly_promotions/promotion_code_batch_mailer/promotion_code_batch_errored.text.erb +2 -0
  155. data/app/views/solidus_friendly_promotions/promotion_code_batch_mailer/promotion_code_batch_finished.text.erb +2 -0
  156. data/bin/console +17 -0
  157. data/bin/importmap +4 -0
  158. data/bin/rails +7 -0
  159. data/bin/rails-engine +13 -0
  160. data/bin/rails-sandbox +16 -0
  161. data/bin/rake +7 -0
  162. data/bin/sandbox +75 -0
  163. data/bin/setup +8 -0
  164. data/config/importmap.rb +12 -0
  165. data/config/initializers/solidus_friendly_promotions.rb +3 -0
  166. data/config/locales/en.yml +255 -0
  167. data/config/routes.rb +18 -0
  168. data/db/migrate/20230703101637_create_promotions.rb +16 -0
  169. data/db/migrate/20230703141116_create_promotion_categories.rb +14 -0
  170. data/db/migrate/20230703143943_create_promotion_rules.rb +12 -0
  171. data/db/migrate/20230704083830_add_rule_tables.rb +31 -0
  172. data/db/migrate/20230704093625_create_promotion_actions.rb +14 -0
  173. data/db/migrate/20230704102444_create_promotion_codes.rb +11 -0
  174. data/db/migrate/20230704102656_create_promotion_code_batches.rb +33 -0
  175. data/db/migrate/20230705171556_create_friendly_order_promotions.rb +11 -0
  176. data/db/migrate/20230725074235_create_shipping_rate_discounts.rb +12 -0
  177. data/db/migrate/20230928093138_add_lane_to_solidus_friendly_promotions_promotions.rb +5 -0
  178. data/db/migrate/20231006134042_add_customer_label_to_promotions.rb +7 -0
  179. data/db/migrate/20231011100059_add_db_comments_to_friendly_order_promotions.rb +61 -0
  180. data/db/migrate/20231011120928_add_db_comments_to_friendly_promotion_rules_taxons.rb +54 -0
  181. data/db/migrate/20231011131324_add_db_comments_to_friendly_promotion_rules.rb +60 -0
  182. data/db/migrate/20231011142040_add_db_comments_to_friendly_promotion_rules_users.rb +53 -0
  183. data/db/migrate/20231011154553_allow_null_promotion_ids.rb +9 -0
  184. data/db/migrate/20231011155822_add_db_comments_to_friendly_promotions.rb +123 -0
  185. data/db/migrate/20231011163030_add_db_comments_to_friendly_promotion_codes.rb +60 -0
  186. data/db/migrate/20231011173312_add_db_comments_to_friendly_promotion_code_batches.rb +91 -0
  187. data/db/migrate/20231011184205_add_db_comments_to_friendly_promotion_rules_stores.rb +53 -0
  188. data/db/migrate/20231011190222_add_db_comments_to_friendly_promotion_actions.rb +68 -0
  189. data/db/migrate/20231012020928_add_db_comments_to_friendly_products_promotion_rules.rb +52 -0
  190. data/db/migrate/20231012120928_add_db_comments_to_friendly_promotion_categories.rb +52 -0
  191. data/db/migrate/20231013181921_add_original_promotion_ids.rb +6 -0
  192. data/lib/generators/solidus_friendly_promotions/install/install_generator.rb +38 -0
  193. data/lib/generators/solidus_friendly_promotions/install/templates/initializer.rb +118 -0
  194. data/lib/solidus_friendly_promotions/configuration.rb +52 -0
  195. data/lib/solidus_friendly_promotions/engine.rb +37 -0
  196. data/lib/solidus_friendly_promotions/migrate_adjustments.rb +62 -0
  197. data/lib/solidus_friendly_promotions/migrate_order_promotions.rb +73 -0
  198. data/lib/solidus_friendly_promotions/nested_class_set.rb +24 -0
  199. data/lib/solidus_friendly_promotions/promotion_map.rb +96 -0
  200. data/lib/solidus_friendly_promotions/promotion_migrator.rb +103 -0
  201. data/lib/solidus_friendly_promotions/testing_support/factories/friendly_order_factory.rb +20 -0
  202. data/lib/solidus_friendly_promotions/testing_support/factories/friendly_order_promotion_factory.rb +8 -0
  203. data/lib/solidus_friendly_promotions/testing_support/factories/friendly_promotion_category_factory.rb +7 -0
  204. data/lib/solidus_friendly_promotions/testing_support/factories/friendly_promotion_code_factory.rb +8 -0
  205. data/lib/solidus_friendly_promotions/testing_support/factories/friendly_promotion_factory.rb +91 -0
  206. data/lib/solidus_friendly_promotions/testing_support/factories/friendly_shipping_rate_discount_factory.rb +14 -0
  207. data/lib/solidus_friendly_promotions/testing_support.rb +9 -0
  208. data/lib/solidus_friendly_promotions/version.rb +5 -0
  209. data/lib/solidus_friendly_promotions.rb +18 -0
  210. data/lib/tasks/solidus_friendly_promotions/migrate_adjustments.rake +17 -0
  211. data/lib/tasks/solidus_friendly_promotions/migrate_existing_promotions.rake +12 -0
  212. data/lib/tasks/solidus_friendly_promotions/migrate_order_promotions.rake +17 -0
  213. data/solidus_friendly_promotions.gemspec +40 -0
  214. metadata +392 -0
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddDbCommentsToFriendlyPromotionCategories < ActiveRecord::Migration[6.1]
4
+ def up
5
+ if connection.supports_comments?
6
+ change_table_comment(:friendly_promotion_categories, friendly_promotion_categories_table_comment)
7
+ change_column_comment(:friendly_promotion_categories, :id, id_comment)
8
+ change_column_comment(:friendly_promotion_categories, :name, name_comment)
9
+ change_column_comment(:friendly_promotion_categories, :code, code_comment)
10
+ change_column_comment(:friendly_promotion_categories, :created_at, created_at_comment)
11
+ change_column_comment(:friendly_promotion_categories, :updated_at, updated_at_comment)
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def friendly_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,6 @@
1
+ class AddOriginalPromotionIds < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_reference :friendly_promotions, :original_promotion, type: :integer, index: {name: :index_original_promotion_id}, foreign_key: {to_table: :spree_promotions}
4
+ add_reference :friendly_promotion_actions, :original_promotion_action, type: :integer, index: {name: :index_original_promotion_action_id}, foreign_key: {to_table: :spree_promotion_actions}
5
+ end
6
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusFriendlyPromotions
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ class_option :auto_run_migrations, type: :boolean, default: false
7
+ source_root File.expand_path("templates", __dir__)
8
+
9
+ def self.exit_on_failure?
10
+ true
11
+ end
12
+
13
+ def copy_initializer
14
+ template "initializer.rb", "config/initializers/solidus_friendly_promotions.rb"
15
+ end
16
+
17
+ def add_migrations
18
+ run "bin/rails railties:install:migrations FROM=solidus_friendly_promotions"
19
+ end
20
+
21
+ def mount_engine
22
+ inject_into_file "config/routes.rb",
23
+ " mount SolidusFriendlyPromotions::Engine => '/'\n",
24
+ before: / mount Spree::Core::Engine.*/,
25
+ verbose: true
26
+ end
27
+
28
+ def run_migrations
29
+ run_migrations = options[:auto_run_migrations] || ["", "y", "Y"].include?(ask("Would you like to run the migrations now? [Y/n]")) # rubocop:disable Layout/LineLength
30
+ if run_migrations
31
+ run "bin/rails db:migrate"
32
+ else
33
+ puts "Skipping bin/rails db:migrate, don't forget to run it!" # rubocop:disable Rails/Output
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Replace solidus core's order contents and promotion adjuster classes with ours.
4
+ Spree::Config.order_contents_class = "SolidusFriendlyPromotions::SimpleOrderContents"
5
+ Spree::Config.promotion_adjuster_class = "SolidusFriendlyPromotions::FriendlyPromotionAdjuster"
6
+
7
+ # Replace the promotions menu from core with ours
8
+ Spree::Backend::Config.configure do |config|
9
+ config.menu_items = config.menu_items.map do |item|
10
+ next item unless item.label.to_sym == :promotions
11
+
12
+ # The API of the MenuItem class changes in Solidus 4.2.0
13
+ if item.respond_to?(:children)
14
+ Spree::BackendConfiguration::MenuItem.new(
15
+ label: :promotions,
16
+ icon: "bullhorn",
17
+ condition: -> { can?(:admin, SolidusFriendlyPromotions::Promotion) },
18
+ url: -> { SolidusFriendlyPromotions::Engine.routes.url_helpers.admin_promotions_path },
19
+ data_hook: :admin_promotion_sub_tabs,
20
+ children: [
21
+ Spree::BackendConfiguration::MenuItem.new(
22
+ label: :promotions,
23
+ url: -> { SolidusFriendlyPromotions::Engine.routes.url_helpers.admin_promotions_path },
24
+ condition: -> { can?(:admin, SolidusFriendlyPromotions::Promotion) }
25
+ ),
26
+ Spree::BackendConfiguration::MenuItem.new(
27
+ label: :promotion_categories,
28
+ url: -> { SolidusFriendlyPromotions::Engine.routes.url_helpers.admin_promotion_categories_path },
29
+ condition: -> { can?(:admin, SolidusFriendlyPromotions::PromotionCategory) }
30
+ ),
31
+ Spree::BackendConfiguration::MenuItem.new(
32
+ label: :legacy_promotions,
33
+ condition: -> { can?(:admin, Spree::Promotion && Spree::Promotion.any?) },
34
+ url: -> { Spree::Core::Engine.routes.url_helpers.admin_promotions_path },
35
+ match_path: "/admin/promotions/"
36
+ ),
37
+ Spree::BackendConfiguration::MenuItem.new(
38
+ label: :legacy_promotion_categories,
39
+ condition: -> { can?(:admin, Spree::PromotionCategory && Spree::Promotion.any?) },
40
+ url: -> { Spree::Core::Engine.routes.url_helpers.admin_promotion_categories_path },
41
+ match_path: "/admin/promotion_categories/"
42
+ )
43
+ ]
44
+ )
45
+ else
46
+ Spree::BackendConfiguration::MenuItem.new(
47
+ [:promotions, :promotion_categories],
48
+ "bullhorn",
49
+ partial: "solidus_friendly_promotions/admin/shared/promotion_sub_menu",
50
+ condition: -> { can?(:admin, SolidusFriendlyPromotions::Promotion) },
51
+ url: -> { SolidusFriendlyPromotions::Engine.routes.url_helpers.admin_promotions_path },
52
+ position: 2
53
+ )
54
+ end
55
+ end
56
+ end
57
+
58
+ SolidusFriendlyPromotions.configure do |config|
59
+ # This class chooses which promotion should apply to a line item in case
60
+ # that more than one promotion is eligible.
61
+ config.discount_chooser_class = "SolidusFriendlyPromotions::FriendlyPromotionAdjuster::ChooseDiscounts"
62
+
63
+ # How many promotions should be displayed on the index page in the admin.
64
+ config.promotions_per_page = 25
65
+
66
+ config.promotion_calculators = SolidusFriendlyPromotions::NestedClassSet.new(
67
+ "SolidusFriendlyPromotions::Actions::AdjustShipment" => [
68
+ "SolidusFriendlyPromotions::Calculators::FlatRate",
69
+ "SolidusFriendlyPromotions::Calculators::FlexiRate",
70
+ "SolidusFriendlyPromotions::Calculators::Percent",
71
+ "SolidusFriendlyPromotions::Calculators::TieredFlatRate",
72
+ "SolidusFriendlyPromotions::Calculators::TieredPercent"
73
+ ],
74
+ "SolidusFriendlyPromotions::Actions::AdjustLineItem" => [
75
+ "SolidusFriendlyPromotions::Calculators::DistributedAmount",
76
+ "SolidusFriendlyPromotions::Calculators::FlatRate",
77
+ "SolidusFriendlyPromotions::Calculators::FlexiRate",
78
+ "SolidusFriendlyPromotions::Calculators::Percent",
79
+ "SolidusFriendlyPromotions::Calculators::TieredFlatRate",
80
+ "SolidusFriendlyPromotions::Calculators::TieredPercent"
81
+ ],
82
+ "SolidusFriendlyPromotions::Actions::AdjustLineItemQuantityGroups" => [
83
+ "SolidusFriendlyPromotions::Calculators::FlatRate",
84
+ "SolidusFriendlyPromotions::Calculators::Percent"
85
+ ]
86
+ )
87
+
88
+ config.order_rules = [
89
+ "SolidusFriendlyPromotions::Rules::FirstOrder",
90
+ "SolidusFriendlyPromotions::Rules::FirstRepeatPurchaseSince",
91
+ "SolidusFriendlyPromotions::Rules::ItemTotal",
92
+ "SolidusFriendlyPromotions::Rules::DiscountedItemTotal",
93
+ "SolidusFriendlyPromotions::Rules::MinimumQuantity",
94
+ "SolidusFriendlyPromotions::Rules::NthOrder",
95
+ "SolidusFriendlyPromotions::Rules::OneUsePerUser",
96
+ "SolidusFriendlyPromotions::Rules::OptionValue",
97
+ "SolidusFriendlyPromotions::Rules::Product",
98
+ "SolidusFriendlyPromotions::Rules::Store",
99
+ "SolidusFriendlyPromotions::Rules::Taxon",
100
+ "SolidusFriendlyPromotions::Rules::UserLoggedIn",
101
+ "SolidusFriendlyPromotions::Rules::UserRole",
102
+ "SolidusFriendlyPromotions::Rules::User"
103
+ ]
104
+ config.line_item_rules = [
105
+ "SolidusFriendlyPromotions::Rules::LineItemOptionValue",
106
+ "SolidusFriendlyPromotions::Rules::LineItemProduct",
107
+ "SolidusFriendlyPromotions::Rules::LineItemTaxon"
108
+ ]
109
+ config.shipment_rules = [
110
+ "SolidusFriendlyPromotions::Rules::ShippingMethod"
111
+ ]
112
+
113
+ config.actions = [
114
+ "SolidusFriendlyPromotions::Actions::AdjustLineItem",
115
+ "SolidusFriendlyPromotions::Actions::AdjustLineItemQuantityGroups",
116
+ "SolidusFriendlyPromotions::Actions::AdjustShipment"
117
+ ]
118
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spree/core/environment_extension"
4
+
5
+ module SolidusFriendlyPromotions
6
+ class Configuration < Spree::Preferences::Configuration
7
+ attr_accessor :sync_order_promotions
8
+ attr_accessor :promotion_calculators
9
+
10
+ def initialize
11
+ @sync_order_promotions = true
12
+ @promotion_calculators = NestedClassSet.new
13
+ end
14
+
15
+ include Spree::Core::EnvironmentExtension
16
+
17
+ add_class_set :line_item_discount_calculators
18
+ add_class_set :shipment_discount_calculators
19
+
20
+ add_class_set :order_rules
21
+ add_class_set :line_item_rules
22
+ add_class_set :shipment_rules
23
+
24
+ add_class_set :actions
25
+
26
+ class_name_attribute :discount_chooser_class, default: "SolidusFriendlyPromotions::DiscountChooser"
27
+ class_name_attribute :promotion_code_batch_mailer_class,
28
+ default: "SolidusFriendlyPromotions::PromotionCodeBatchMailer"
29
+
30
+ # @!attribute [rw] promotions_per_page
31
+ # @return [Integer] Promotions to show per-page in the admin (default: +25+)
32
+ preference :promotions_per_page, :integer, default: 25
33
+
34
+ preference :lanes, :hash, default: {
35
+ pre: 0,
36
+ default: 1,
37
+ post: 2
38
+ }
39
+ end
40
+
41
+ class << self
42
+ def configuration
43
+ @configuration ||= Configuration.new
44
+ end
45
+
46
+ alias_method :config, :configuration
47
+
48
+ def configure
49
+ yield configuration
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "solidus_core"
4
+ require "solidus_support"
5
+
6
+ module SolidusFriendlyPromotions
7
+ class Engine < Rails::Engine
8
+ include SolidusSupport::EngineExtensions
9
+
10
+ isolate_namespace ::SolidusFriendlyPromotions
11
+
12
+ engine_name "solidus_friendly_promotions"
13
+
14
+ # use rspec for tests
15
+ config.generators do |g|
16
+ g.test_framework :rspec
17
+ end
18
+
19
+ initializer "solidus_friendly_promotions.assets" do |app|
20
+ app.config.assets.precompile << "solidus_friendly_promotions/manifest.js"
21
+ end
22
+
23
+ initializer "solidus_friendly_promotions.importmap" do |app|
24
+ SolidusFriendlyPromotions.importmap.draw(Engine.root.join("config", "importmap.rb"))
25
+
26
+ package_path = Engine.root.join("app/javascript")
27
+ app.config.assets.paths << package_path
28
+
29
+ if app.config.importmap.sweep_cache
30
+ SolidusFriendlyPromotions.importmap.cache_sweeper(watches: package_path)
31
+ ActiveSupport.on_load(:action_controller_base) do
32
+ before_action { SolidusFriendlyPromotions.importmap.cache_sweeper.execute_if_updated }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusFriendlyPromotions
4
+ class MigrateAdjustments
5
+ class << self
6
+ def up
7
+ sql = if ActiveRecord::Base.connection_db_config.adapter == "mysql2"
8
+ <<~SQL
9
+ UPDATE spree_adjustments
10
+ INNER JOIN spree_promotion_actions ON spree_adjustments.source_id = spree_promotion_actions.id and spree_adjustments.source_type = 'Spree::PromotionAction'
11
+ INNER JOIN friendly_promotion_actions ON friendly_promotion_actions.original_promotion_action_id = spree_promotion_actions.id
12
+ SET source_id = friendly_promotion_actions.id,
13
+ source_type = 'SolidusFriendlyPromotions::PromotionAction'
14
+ SQL
15
+ else
16
+ <<~SQL
17
+ UPDATE spree_adjustments
18
+ SET source_id = friendly_promotion_actions.id,
19
+ source_type = 'SolidusFriendlyPromotions::PromotionAction'
20
+ FROM spree_promotion_actions
21
+ INNER JOIN friendly_promotion_actions ON friendly_promotion_actions.original_promotion_action_id = spree_promotion_actions.id
22
+ WHERE spree_adjustments.source_id = spree_promotion_actions.id and spree_adjustments.source_type = 'Spree::PromotionAction'
23
+ SQL
24
+ end
25
+
26
+ execute(sql)
27
+ end
28
+
29
+ def down
30
+ sql = if ActiveRecord::Base.connection_db_config.adapter == "mysql2"
31
+ <<~SQL
32
+ UPDATE spree_adjustments
33
+ INNER JOIN friendly_promotion_actions
34
+ INNER JOIN spree_promotion_actions ON spree_adjustments.source_id = friendly_promotion_actions.id and spree_adjustments.source_type = 'SolidusFriendlyPromotions::PromotionAction'
35
+ SET source_id = spree_promotion_actions.id,
36
+ source_type = 'Spree::PromotionAction'
37
+ WHERE friendly_promotion_actions.original_promotion_action_id = spree_promotion_actions.id
38
+ SQL
39
+ else
40
+ <<~SQL
41
+ UPDATE spree_adjustments
42
+ SET source_id = spree_promotion_actions.id,
43
+ source_type = 'Spree::PromotionAction'
44
+ FROM spree_promotion_actions
45
+ INNER JOIN friendly_promotion_actions ON friendly_promotion_actions.original_promotion_action_id = spree_promotion_actions.id
46
+ WHERE spree_adjustments.source_id = friendly_promotion_actions.id and spree_adjustments.source_type = 'SolidusFriendlyPromotions::PromotionAction'
47
+ SQL
48
+ end
49
+
50
+ execute(sql)
51
+ end
52
+
53
+ private
54
+
55
+ def execute(sql)
56
+ Spree::Adjustment.transaction do
57
+ ActiveRecord::Base.connection.execute(sql)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusFriendlyPromotions
4
+ class MigrateOrderPromotions
5
+ class << self
6
+ def up
7
+ sql = <<~SQL
8
+ INSERT INTO friendly_order_promotions (
9
+ order_id,
10
+ promotion_id,
11
+ promotion_code_id,
12
+ created_at,
13
+ updated_at
14
+ )
15
+ SELECT
16
+ spree_orders_promotions.order_id AS order_id,
17
+ friendly_promotions.id AS promotion_id,
18
+ friendly_promotion_codes.id AS promotion_code_id,
19
+ spree_orders_promotions.created_at,
20
+ spree_orders_promotions.updated_at
21
+ FROM spree_orders_promotions
22
+ INNER JOIN spree_promotions ON spree_orders_promotions.promotion_id = spree_promotions.id
23
+ INNER JOIN friendly_promotions ON spree_promotions.id = friendly_promotions.original_promotion_id
24
+ LEFT OUTER JOIN spree_promotion_codes ON spree_orders_promotions.promotion_code_id = spree_promotion_codes.id
25
+ LEFT OUTER JOIN friendly_promotion_codes ON spree_promotion_codes.value = friendly_promotion_codes.value
26
+ WHERE NOT EXISTS (
27
+ SELECT NULL
28
+ FROM friendly_order_promotions
29
+ WHERE friendly_order_promotions.order_id = order_id
30
+ AND (friendly_order_promotions.promotion_code_id = promotion_code_id OR promotion_code_id IS NULL)
31
+ AND friendly_order_promotions.promotion_id = promotion_id
32
+ );
33
+ SQL
34
+ ActiveRecord::Base.connection.execute(sql)
35
+
36
+ Spree::OrderPromotion.delete_all
37
+ end
38
+
39
+ def down
40
+ sql = <<~SQL
41
+ INSERT INTO spree_orders_promotions (
42
+ order_id,
43
+ promotion_id,
44
+ promotion_code_id,
45
+ created_at,
46
+ updated_at
47
+ )
48
+ SELECT
49
+ friendly_order_promotions.order_id AS order_id,
50
+ spree_promotions.id AS promotion_id,
51
+ spree_promotion_codes.id AS promotion_code_id,
52
+ friendly_order_promotions.created_at,
53
+ friendly_order_promotions.updated_at
54
+ FROM friendly_order_promotions
55
+ INNER JOIN friendly_promotions ON friendly_order_promotions.promotion_id = friendly_promotions.id
56
+ INNER JOIN spree_promotions ON spree_promotions.id = friendly_promotions.original_promotion_id
57
+ LEFT OUTER JOIN friendly_promotion_codes ON friendly_order_promotions.promotion_code_id = friendly_promotion_codes.id
58
+ LEFT OUTER JOIN spree_promotion_codes ON spree_promotion_codes.value = friendly_promotion_codes.value
59
+ WHERE NOT EXISTS (
60
+ SELECT NULL
61
+ FROM spree_orders_promotions
62
+ WHERE spree_orders_promotions.order_id = order_id
63
+ AND (spree_orders_promotions.promotion_code_id = promotion_code_id OR promotion_code_id IS NULL)
64
+ AND spree_orders_promotions.promotion_id = promotion_id
65
+ );
66
+ SQL
67
+ ActiveRecord::Base.connection.execute(sql)
68
+
69
+ SolidusFriendlyPromotions::OrderPromotion.delete_all
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spree/core/class_constantizer"
4
+
5
+ module SolidusFriendlyPromotions
6
+ class NestedClassSet
7
+ attr_reader :klass_sets
8
+
9
+ def initialize(hash = {})
10
+ @klass_sets = hash.map do |key, value|
11
+ [
12
+ key,
13
+ Spree::Core::ClassConstantizer::Set.new.tap do |set|
14
+ value.each { |klass_name| set << klass_name }
15
+ end
16
+ ]
17
+ end.to_h
18
+ end
19
+
20
+ def [](klass)
21
+ klass_sets[klass.name]
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusFriendlyPromotions
4
+ PROMOTION_MAP = {
5
+ rules: {
6
+ Spree::Promotion::Rules::ItemTotal =>
7
+ SolidusFriendlyPromotions::Rules::ItemTotal,
8
+ Spree::Promotion::Rules::Product =>
9
+ SolidusFriendlyPromotions::Rules::Product,
10
+ Spree::Promotion::Rules::User =>
11
+ SolidusFriendlyPromotions::Rules::User,
12
+ Spree::Promotion::Rules::FirstOrder =>
13
+ SolidusFriendlyPromotions::Rules::FirstOrder,
14
+ Spree::Promotion::Rules::UserLoggedIn =>
15
+ SolidusFriendlyPromotions::Rules::UserLoggedIn,
16
+ Spree::Promotion::Rules::OneUsePerUser =>
17
+ SolidusFriendlyPromotions::Rules::OneUsePerUser,
18
+ Spree::Promotion::Rules::Taxon =>
19
+ SolidusFriendlyPromotions::Rules::Taxon,
20
+ Spree::Promotion::Rules::NthOrder =>
21
+ SolidusFriendlyPromotions::Rules::NthOrder,
22
+ Spree::Promotion::Rules::OptionValue =>
23
+ SolidusFriendlyPromotions::Rules::OptionValue,
24
+ Spree::Promotion::Rules::FirstRepeatPurchaseSince =>
25
+ SolidusFriendlyPromotions::Rules::FirstRepeatPurchaseSince,
26
+ Spree::Promotion::Rules::UserRole =>
27
+ SolidusFriendlyPromotions::Rules::UserRole,
28
+ Spree::Promotion::Rules::Store =>
29
+ SolidusFriendlyPromotions::Rules::Store
30
+ },
31
+ actions: {
32
+ Spree::Promotion::Actions::CreateAdjustment => ->(old_action) {
33
+ calculator = case old_action.calculator
34
+ when Spree::Calculator::FlatRate
35
+ SolidusFriendlyPromotions::Calculators::DistributedAmount.new(preferences: old_action.calculator.preferences)
36
+ when Spree::Calculator::FlatPercentItemTotal
37
+ SolidusFriendlyPromotions::Calculators::Percent.new(preferred_percent: old_action.calculator.preferred_flat_percent)
38
+ end
39
+
40
+ SolidusFriendlyPromotions::Actions::AdjustLineItem.new(
41
+ calculator: calculator
42
+ )
43
+ },
44
+ Spree::Promotion::Actions::CreateItemAdjustments => ->(old_action) {
45
+ preferences = old_action.calculator.preferences
46
+ calculator = case old_action.calculator
47
+ when Spree::Calculator::FlatRate
48
+ SolidusFriendlyPromotions::Calculators::FlatRate.new(preferences: preferences)
49
+ when Spree::Calculator::PercentOnLineItem
50
+ SolidusFriendlyPromotions::Calculators::Percent.new(preferences: preferences)
51
+ when Spree::Calculator::FlexiRate
52
+ SolidusFriendlyPromotions::Calculators::FlexiRate.new(preferences: preferences)
53
+ when Spree::Calculator::DistributedAmount
54
+ SolidusFriendlyPromotions::Calculators::DistributedAmount.new(preferences: preferences)
55
+ when Spree::Calculator::TieredFlatRate
56
+ SolidusFriendlyPromotions::Calculators::TieredFlatRate.new(preferences: preferences)
57
+ when Spree::Calculator::TieredPercent
58
+ SolidusFriendlyPromotions::Calculators::TieredPercent.new(preferences: preferences)
59
+ end
60
+
61
+ SolidusFriendlyPromotions::Actions::AdjustLineItem.new(
62
+ calculator: calculator
63
+ )
64
+ },
65
+ Spree::Promotion::Actions::CreateQuantityAdjustments => ->(old_action) {
66
+ preferences = old_action.calculator.preferences
67
+ calculator = case old_action.calculator
68
+ when Spree::Calculator::FlatRate
69
+ SolidusFriendlyPromotions::Calculators::FlatRate.new(preferences: preferences)
70
+ when Spree::Calculator::PercentOnLineItem
71
+ SolidusFriendlyPromotions::Calculators::Percent.new(preferences: preferences)
72
+ when Spree::Calculator::FlexiRate
73
+ SolidusFriendlyPromotions::Calculators::FlexiRate.new(preferences: preferences)
74
+ when Spree::Calculator::DistributedAmount
75
+ SolidusFriendlyPromotions::Calculators::DistributedAmount.new(preferences: preferences)
76
+ when Spree::Calculator::TieredFlatRate
77
+ SolidusFriendlyPromotions::Calculators::TieredFlatRate.new(preferences: preferences)
78
+ when Spree::Calculator::TieredPercent
79
+ SolidusFriendlyPromotions::Calculators::TieredPercent.new(preferences: preferences)
80
+ end
81
+
82
+ SolidusFriendlyPromotions::Actions::AdjustLineItemQuantityGroups.new(
83
+ preferred_group_size: old_action.preferred_group_size,
84
+ calculator: calculator
85
+ )
86
+ },
87
+ Spree::Promotion::Actions::FreeShipping => ->(old_action) {
88
+ SolidusFriendlyPromotions::Actions::AdjustShipment.new(
89
+ calculator: SolidusFriendlyPromotions::Calculators::Percent.new(
90
+ preferred_percent: 100
91
+ )
92
+ )
93
+ }
94
+ }
95
+ }
96
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusFriendlyPromotions
4
+ class PromotionMigrator
5
+ PROMOTION_IGNORED_ATTRIBUTES = ["id", "type", "promotion_category_id"]
6
+
7
+ attr_reader :promotion_map
8
+
9
+ def initialize(promotion_map)
10
+ @promotion_map = promotion_map
11
+ end
12
+
13
+ def call
14
+ SolidusFriendlyPromotions::PromotionCategory.destroy_all
15
+ Spree::PromotionCategory.all.each do |promotion_category|
16
+ SolidusFriendlyPromotions::PromotionCategory.create!(promotion_category.attributes.except("id"))
17
+ end
18
+
19
+ SolidusFriendlyPromotions::Promotion.destroy_all
20
+ Spree::Promotion.all.each do |promotion|
21
+ new_promotion = copy_promotion(promotion)
22
+ if promotion.promotion_category&.name.present?
23
+ new_promotion.category = SolidusFriendlyPromotions::PromotionCategory.find_by(
24
+ name: promotion.promotion_category.name
25
+ )
26
+ end
27
+ new_promotion.rules = promotion.rules.flat_map do |old_promotion_rule|
28
+ generate_new_promotion_rules(old_promotion_rule)
29
+ end
30
+ new_promotion.actions = promotion.actions.flat_map do |old_promotion_action|
31
+ generate_new_promotion_actions(old_promotion_action)&.tap do |new_promotion_action|
32
+ new_promotion_action.original_promotion_action = old_promotion_action
33
+ end
34
+ end.compact
35
+ new_promotion.save!
36
+ copy_promotion_code_batches(new_promotion)
37
+ copy_promotion_codes(new_promotion)
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def copy_promotion_code_batches(new_promotion)
44
+ sql = <<~SQL
45
+ INSERT INTO friendly_promotion_code_batches (promotion_id, base_code, number_of_codes, email, error, state, created_at, updated_at, join_characters)
46
+ SELECT friendly_promotions.id AS promotion_id, base_code, number_of_codes, email, error, state, spree_promotion_code_batches.created_at, spree_promotion_code_batches.updated_at, join_characters
47
+ FROM spree_promotion_code_batches
48
+ INNER JOIN spree_promotions ON spree_promotion_code_batches.promotion_id = spree_promotions.id
49
+ INNER JOIN friendly_promotions ON spree_promotions.id = friendly_promotions.original_promotion_id
50
+ WHERE spree_promotion_code_batches.promotion_id = #{new_promotion.original_promotion_id};
51
+ SQL
52
+ SolidusFriendlyPromotions::PromotionCodeBatch.connection.execute(sql)
53
+ end
54
+
55
+ def copy_promotion_codes(new_promotion)
56
+ sql = <<~SQL
57
+ INSERT INTO friendly_promotion_codes (promotion_id, promotion_code_batch_id, value, created_at, updated_at)
58
+ SELECT friendly_promotions.id AS promotion_id, friendly_promotion_code_batches.id AS promotion_code_batch_id, value, spree_promotion_codes.created_at, spree_promotion_codes.updated_at
59
+ FROM spree_promotion_codes
60
+ LEFT OUTER JOIN spree_promotion_code_batches ON spree_promotion_code_batches.id = spree_promotion_codes.promotion_code_batch_id
61
+ LEFT OUTER JOIN friendly_promotion_code_batches ON friendly_promotion_code_batches.base_code = spree_promotion_code_batches.base_code
62
+ INNER JOIN spree_promotions ON spree_promotion_codes.promotion_id = spree_promotions.id
63
+ INNER JOIN friendly_promotions ON spree_promotions.id = friendly_promotions.original_promotion_id
64
+ WHERE spree_promotion_codes.promotion_id = #{new_promotion.original_promotion_id};
65
+ SQL
66
+ SolidusFriendlyPromotions::PromotionCode.connection.execute(sql)
67
+ end
68
+
69
+ def copy_promotion(old_promotion)
70
+ SolidusFriendlyPromotions::Promotion.new(
71
+ old_promotion.attributes.except(*PROMOTION_IGNORED_ATTRIBUTES).merge(
72
+ customer_label: old_promotion.name,
73
+ original_promotion: old_promotion
74
+ )
75
+ )
76
+ end
77
+
78
+ def generate_new_promotion_actions(old_promotion_action)
79
+ promo_action_config = promotion_map[:actions][old_promotion_action.class]
80
+ if promo_action_config.nil?
81
+ puts("#{old_promotion_action.class} is not supported")
82
+ return nil
83
+ end
84
+ promo_action_config.call(old_promotion_action)
85
+ end
86
+
87
+ def generate_new_promotion_rules(old_promotion_rule)
88
+ new_promo_rule_class = promotion_map[:rules][old_promotion_rule.class]
89
+ if new_promo_rule_class.nil?
90
+ puts("#{old_promotion_rule.class} is not supported")
91
+ []
92
+ elsif new_promo_rule_class.respond_to?(:call)
93
+ new_promo_rule_class.call(old_promotion_rule)
94
+ else
95
+ new_rule = new_promo_rule_class.new(old_promotion_rule.attributes.except(*PROMOTION_IGNORED_ATTRIBUTES))
96
+ new_rule.preload_relations.each do |relation|
97
+ new_rule.send("#{relation}=", old_promotion_rule.send(relation))
98
+ end
99
+ [new_rule]
100
+ end
101
+ end
102
+ end
103
+ end