solidus_core 3.0.0 → 4.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (444) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -2
  3. data/Rakefile +7 -2
  4. data/app/assets/images/logo/solidus.svg +18 -1
  5. data/app/assets/images/logo/solidus_logo.png +0 -0
  6. data/app/controllers/spree/base_controller.rb +1 -3
  7. data/app/helpers/spree/base_helper.rb +3 -3
  8. data/app/helpers/spree/core/controller_helpers/auth.rb +66 -0
  9. data/app/helpers/spree/core/controller_helpers/common.rb +82 -0
  10. data/app/helpers/spree/core/controller_helpers/order.rb +86 -0
  11. data/app/helpers/spree/core/controller_helpers/payment_parameters.rb +165 -0
  12. data/{lib/spree/core/controller_helpers/current_host.rb → app/helpers/spree/core/controller_helpers/pricing.rb} +6 -4
  13. data/app/helpers/spree/core/controller_helpers/search.rb +16 -0
  14. data/app/helpers/spree/core/controller_helpers/store.rb +19 -0
  15. data/app/helpers/spree/core/controller_helpers/strong_parameters.rb +74 -0
  16. data/app/helpers/spree/products_helper.rb +2 -2
  17. data/app/mailers/spree/base_mailer.rb +1 -1
  18. data/app/mailers/spree/carton_mailer.rb +1 -1
  19. data/app/mailers/spree/order_mailer.rb +3 -3
  20. data/app/mailers/spree/reimbursement_mailer.rb +1 -1
  21. data/app/models/concerns/spree/active_storage_adapter/attachment.rb +30 -11
  22. data/app/models/concerns/spree/active_storage_adapter/normalization.rb +1 -1
  23. data/app/models/concerns/spree/active_storage_adapter.rb +1 -18
  24. data/app/models/concerns/spree/default_price.rb +30 -10
  25. data/app/models/concerns/spree/display_money.rb +1 -1
  26. data/app/models/concerns/spree/metadata.rb +64 -0
  27. data/app/models/concerns/spree/named_type.rb +2 -0
  28. data/app/models/concerns/spree/ordered_property_value_list.rb +2 -2
  29. data/app/models/concerns/spree/ransackable_attributes.rb +9 -5
  30. data/app/models/concerns/spree/user_address_book.rb +19 -10
  31. data/app/models/concerns/spree/user_methods.rb +40 -6
  32. data/app/models/spree/address.rb +11 -9
  33. data/app/models/spree/adjustment.rb +15 -76
  34. data/app/models/spree/adjustment_reason.rb +2 -0
  35. data/app/models/spree/calculator/flat_fee.rb +21 -0
  36. data/app/models/spree/calculator/returns/default_refund_amount.rb +1 -1
  37. data/app/models/spree/carton.rb +3 -3
  38. data/app/models/spree/core/state_machines/inventory_unit.rb +42 -0
  39. data/app/models/spree/core/state_machines/order/class_methods.rb +217 -0
  40. data/app/models/spree/core/state_machines/order.rb +42 -0
  41. data/app/models/spree/core/state_machines/payment.rb +61 -0
  42. data/app/models/spree/core/state_machines/reimbursement.rb +33 -0
  43. data/app/models/spree/core/state_machines/return_authorization.rb +32 -0
  44. data/app/models/spree/core/state_machines/return_item/acceptance_status.rb +51 -0
  45. data/app/models/spree/core/state_machines/return_item/reception_status.rb +42 -0
  46. data/app/models/spree/core/state_machines/shipment.rb +58 -0
  47. data/app/models/spree/country.rb +1 -1
  48. data/app/models/spree/credit_card.rb +13 -10
  49. data/app/models/spree/customer_return.rb +6 -3
  50. data/app/models/spree/deprecated_configurable_class.rb +40 -0
  51. data/app/models/spree/fulfilment_changer.rb +56 -29
  52. data/app/models/spree/image/active_storage_attachment.rb +2 -7
  53. data/app/models/spree/image/paperclip_attachment.rb +2 -2
  54. data/app/models/spree/inventory_unit.rb +2 -2
  55. data/app/models/spree/item_total.rb +28 -0
  56. data/app/models/spree/legacy_user.rb +1 -0
  57. data/app/models/spree/line_item.rb +26 -8
  58. data/app/models/spree/log_entry.rb +98 -1
  59. data/app/models/spree/money.rb +120 -0
  60. data/app/models/spree/null_promotion_adjuster.rb +13 -0
  61. data/app/models/spree/null_promotion_advertiser.rb +9 -0
  62. data/app/models/spree/null_promotion_finder.rb +9 -0
  63. data/app/models/spree/null_promotion_handler.rb +44 -0
  64. data/app/models/spree/option_type.rb +1 -1
  65. data/app/models/spree/option_value.rb +4 -3
  66. data/app/models/spree/order/number_generator.rb +7 -1
  67. data/app/models/spree/order.rb +143 -96
  68. data/app/models/spree/order_cancellations.rb +8 -8
  69. data/app/models/spree/order_inventory.rb +7 -5
  70. data/app/models/spree/order_merger.rb +5 -7
  71. data/app/models/spree/order_mutex.rb +2 -2
  72. data/app/models/spree/order_shipping.rb +15 -19
  73. data/app/models/spree/order_taxation.rb +7 -4
  74. data/app/models/spree/order_update_attributes.rb +3 -1
  75. data/app/models/spree/order_updater.rb +25 -63
  76. data/app/models/spree/payment/processing.rb +60 -57
  77. data/app/models/spree/payment.rb +14 -27
  78. data/app/models/spree/payment_create.rb +1 -1
  79. data/app/models/spree/payment_method/bogus_credit_card.rb +18 -14
  80. data/app/models/spree/payment_method/credit_card.rb +0 -4
  81. data/app/models/spree/payment_method/simple_bogus_credit_card.rb +18 -4
  82. data/app/models/spree/payment_method/store_credit.rb +1 -1
  83. data/app/models/spree/payment_method.rb +29 -10
  84. data/app/models/spree/payment_source.rb +5 -1
  85. data/app/models/spree/permission_set.rb +11 -0
  86. data/app/models/spree/permission_sets/base.rb +45 -0
  87. data/app/models/spree/permission_sets/configuration_display.rb +53 -0
  88. data/app/models/spree/permission_sets/configuration_management.rb +52 -0
  89. data/app/models/spree/permission_sets/dashboard_display.rb +28 -0
  90. data/app/models/spree/permission_sets/default_customer.rb +83 -0
  91. data/app/models/spree/permission_sets/order_display.rb +50 -0
  92. data/app/models/spree/permission_sets/order_management.rb +50 -0
  93. data/app/models/spree/permission_sets/product_display.rb +43 -0
  94. data/app/models/spree/permission_sets/product_management.rb +47 -0
  95. data/app/models/spree/permission_sets/restricted_stock_display.rb +33 -0
  96. data/app/models/spree/permission_sets/restricted_stock_management.rb +33 -0
  97. data/app/models/spree/permission_sets/stock_display.rb +26 -0
  98. data/app/models/spree/permission_sets/stock_management.rb +26 -0
  99. data/app/models/spree/permission_sets/super_user.rb +26 -0
  100. data/app/models/spree/permission_sets/user_display.rb +27 -0
  101. data/app/models/spree/permission_sets/user_management.rb +44 -0
  102. data/app/models/spree/preference.rb +1 -1
  103. data/app/models/spree/price.rb +3 -3
  104. data/app/models/spree/product/scopes.rb +23 -10
  105. data/app/models/spree/product.rb +30 -23
  106. data/app/models/spree/product_property.rb +1 -1
  107. data/app/models/spree/property.rb +1 -1
  108. data/app/models/spree/refund.rb +13 -3
  109. data/app/models/spree/refund_reason.rb +6 -1
  110. data/app/models/spree/reimbursement.rb +6 -6
  111. data/app/models/spree/reimbursement_performer.rb +3 -3
  112. data/app/models/spree/reimbursement_tax_calculator.rb +3 -3
  113. data/app/models/spree/reimbursement_type/credit.rb +1 -1
  114. data/app/models/spree/reimbursement_type/reimbursement_helpers.rb +6 -6
  115. data/app/models/spree/reimbursement_type/store_credit.rb +1 -1
  116. data/app/models/spree/reimbursement_type.rb +6 -1
  117. data/app/models/spree/return_authorization.rb +3 -1
  118. data/app/models/spree/return_item.rb +13 -15
  119. data/app/models/spree/return_reason.rb +6 -1
  120. data/app/models/spree/role.rb +3 -1
  121. data/app/models/spree/role_permission.rb +8 -0
  122. data/app/models/spree/shipment.rb +12 -10
  123. data/app/models/spree/shipping_category.rb +2 -0
  124. data/app/models/spree/shipping_rate.rb +2 -3
  125. data/app/models/spree/shipping_rate_tax.rb +1 -1
  126. data/app/models/spree/{order_contents.rb → simple_order_contents.rb} +10 -13
  127. data/app/models/spree/state.rb +1 -1
  128. data/app/models/spree/stock/allocator/on_hand_first.rb +2 -2
  129. data/app/models/spree/stock/availability.rb +11 -3
  130. data/app/models/spree/stock/estimator.rb +1 -1
  131. data/app/models/spree/stock/inventory_unit_builder.rb +1 -1
  132. data/app/models/spree/stock/package.rb +2 -2
  133. data/app/models/spree/stock/quantifier.rb +12 -8
  134. data/app/models/spree/stock/simple_coordinator.rb +38 -28
  135. data/app/models/spree/stock/splitter/shipping_category.rb +1 -1
  136. data/app/models/spree/stock_item.rb +2 -1
  137. data/app/models/spree/stock_location.rb +7 -7
  138. data/app/models/spree/stock_movement.rb +2 -2
  139. data/app/models/spree/store.rb +3 -1
  140. data/app/models/spree/store_credit.rb +31 -16
  141. data/app/models/spree/store_credit_event.rb +4 -3
  142. data/app/models/spree/store_credit_prioritizer.rb +17 -0
  143. data/app/models/spree/store_credit_reason.rb +6 -1
  144. data/app/models/spree/store_selector/by_server_name.rb +1 -1
  145. data/app/models/spree/tax/item_tax.rb +3 -2
  146. data/app/models/spree/tax/order_tax.rb +3 -1
  147. data/app/models/spree/tax/tax_helpers.rb +14 -3
  148. data/app/models/spree/tax/tax_location.rb +4 -7
  149. data/app/models/spree/tax_calculator/default.rb +32 -1
  150. data/app/models/spree/tax_calculator/shipping_rate.rb +2 -2
  151. data/app/models/spree/tax_category.rb +3 -1
  152. data/app/models/spree/tax_rate.rb +14 -1
  153. data/app/models/spree/taxon/active_storage_attachment.rb +2 -2
  154. data/app/models/spree/taxon/paperclip_attachment.rb +4 -4
  155. data/app/models/spree/taxon.rb +25 -3
  156. data/app/models/spree/taxon_brand_selector.rb +22 -0
  157. data/app/models/spree/taxonomy.rb +4 -3
  158. data/app/models/spree/unauthorized_redirect_handler.rb +24 -0
  159. data/app/models/spree/unit_cancel.rb +1 -2
  160. data/app/models/spree/user_address.rb +9 -3
  161. data/app/models/spree/user_last_url_storer/rules/authentication_rule.rb +1 -1
  162. data/app/models/spree/variant/price_selector.rb +25 -8
  163. data/app/models/spree/variant/scopes.rb +4 -0
  164. data/app/models/spree/variant/vat_price_generator.rb +1 -1
  165. data/app/models/spree/variant.rb +64 -37
  166. data/app/models/spree/wallet/add_payment_sources_to_wallet.rb +4 -4
  167. data/app/models/spree/wallet.rb +2 -2
  168. data/app/models/spree/zone.rb +1 -1
  169. data/app/subscribers/spree/order_mailer_subscriber.rb +35 -0
  170. data/app/views/layouts/spree/base_mailer.html.erb +2 -2
  171. data/app/views/spree/order_mailer/cancel_email.html.erb +1 -1
  172. data/app/views/spree/order_mailer/cancel_email.text.erb +1 -1
  173. data/app/views/spree/order_mailer/confirm_email.html.erb +5 -5
  174. data/app/views/spree/order_mailer/confirm_email.text.erb +5 -5
  175. data/app/views/spree/order_mailer/inventory_cancellation_email.html.erb +0 -1
  176. data/config/i18n-tasks.yml +134 -0
  177. data/config/locales/en.yml +439 -338
  178. data/db/default/spree/permission_sets.rb +10 -0
  179. data/db/default/spree/return_reasons.rb +3 -1
  180. data/db/default/spree/states.rb +2 -2
  181. data/db/migrate/20160101010000_solidus_one_four.rb +0 -127
  182. data/db/migrate/20180710170104_create_spree_store_credit_reasons_table.rb +2 -2
  183. data/db/migrate/20201127212108_add_type_before_removal_to_spree_payment_methods.rb +7 -0
  184. data/db/migrate/20210312061050_change_column_null_on_prices.rb +7 -0
  185. data/db/migrate/20210815004823_add_unique_index_to_option_values_variants.rb +16 -0
  186. data/db/migrate/20220419170826_remove_archived_user_addresses.rb +12 -0
  187. data/db/migrate/20220805202442_add_level_to_spree_tax_rates.rb +5 -0
  188. data/db/migrate/20221123152807_add_shipping_category_to_spree_variants.rb +5 -0
  189. data/db/migrate/20230321161854_change_column_null_option_values_option_type_id.rb +5 -0
  190. data/db/migrate/20230425103509_remove_taxon_position.rb +5 -0
  191. data/db/migrate/20230427095534_drop_deprecated_address_id_from_shipments.rb +11 -0
  192. data/db/migrate/20240821173254_create_spree_permission_sets_in_core.rb +9 -0
  193. data/db/migrate/20240821173341_create_spree_roles_permissions_in_core.rb +9 -0
  194. data/db/migrate/20240821173641_add_description_to_spree_roles.rb +5 -0
  195. data/db/migrate/20240904152041_add_privilege_and_category_to_spree_permission_sets.rb +6 -0
  196. data/db/migrate/20250129061658_add_metadata_to_spree_resources.rb +28 -0
  197. data/db/migrate/20250201172950_add_gtin_and_condition_to_spree_variant.rb +6 -0
  198. data/db/migrate/20250207104016_add_primary_taxon_to_products.rb +7 -0
  199. data/db/migrate/20250221152004_add_metadata_to_users.rb +13 -0
  200. data/db/seeds.rb +5 -1
  201. data/lib/generators/solidus/install/app_templates/authentication/custom.rb +16 -0
  202. data/lib/generators/solidus/install/app_templates/authentication/devise.rb +16 -0
  203. data/lib/generators/solidus/install/app_templates/authentication/existing.rb +10 -0
  204. data/lib/generators/solidus/install/app_templates/authentication/none.rb +1 -0
  205. data/lib/generators/solidus/install/app_templates/frontend/none.rb +1 -0
  206. data/lib/generators/solidus/install/app_templates/frontend/starter.rb +1 -0
  207. data/lib/generators/solidus/install/app_templates/payment_method/braintree.rb +5 -0
  208. data/lib/generators/solidus/install/app_templates/payment_method/none.rb +1 -0
  209. data/lib/generators/solidus/install/app_templates/payment_method/paypal.rb +5 -0
  210. data/lib/generators/solidus/install/app_templates/payment_method/stripe.rb +5 -0
  211. data/lib/generators/solidus/install/install_generator.rb +210 -156
  212. data/lib/generators/solidus/install/templates/config/initializers/spree.rb.tt +27 -33
  213. data/lib/generators/solidus/install/templates/vendor/assets/javascripts/spree/backend/all.js +2 -2
  214. data/lib/generators/solidus/update/templates/config/initializers/new_solidus_defaults.rb.tt +30 -0
  215. data/lib/generators/solidus/update/update_generator.rb +124 -0
  216. data/lib/generators/spree/custom_user/custom_user_generator.rb +6 -4
  217. data/lib/generators/spree/custom_user/templates/authentication_helpers.rb.tt +2 -6
  218. data/lib/generators/spree/custom_user/templates/migration.rb.tt +7 -3
  219. data/lib/generators/spree/dummy/dummy_generator.rb +12 -9
  220. data/lib/generators/spree/dummy/templates/rails/application.rb.tt +1 -2
  221. data/lib/generators/spree/dummy/templates/rails/database.yml +48 -63
  222. data/lib/generators/spree/dummy/templates/rails/manifest.js +3 -0
  223. data/lib/generators/spree/dummy/templates/rails/test.rb +7 -2
  224. data/lib/spree/app_configuration.rb +220 -71
  225. data/lib/spree/bus.rb +11 -0
  226. data/lib/spree/core/class_constantizer.rb +2 -2
  227. data/lib/spree/core/controller_helpers/auth.rb +5 -69
  228. data/lib/spree/core/controller_helpers/common.rb +5 -80
  229. data/lib/spree/core/controller_helpers/order.rb +5 -86
  230. data/lib/spree/core/controller_helpers/payment_parameters.rb +5 -165
  231. data/lib/spree/core/controller_helpers/pricing.rb +5 -17
  232. data/lib/spree/core/controller_helpers/search.rb +5 -14
  233. data/lib/spree/core/controller_helpers/store.rb +5 -17
  234. data/lib/spree/core/controller_helpers/strong_parameters.rb +5 -71
  235. data/lib/spree/core/engine.rb +49 -16
  236. data/lib/spree/core/environment/calculators.rb +35 -3
  237. data/lib/spree/core/environment/promotions.rb +25 -4
  238. data/lib/spree/core/environment_extension.rb +16 -2
  239. data/lib/spree/core/importer/order.rb +6 -6
  240. data/lib/spree/core/importer/product.rb +3 -3
  241. data/lib/spree/core/nested_class_set.rb +28 -0
  242. data/lib/spree/core/null_promotion_configuration.rb +84 -0
  243. data/lib/spree/core/product_duplicator.rb +1 -1
  244. data/lib/spree/core/product_filters.rb +2 -2
  245. data/lib/spree/core/search/base.rb +18 -9
  246. data/lib/spree/core/search/variant.rb +2 -2
  247. data/lib/spree/core/state_machines/inventory_unit.rb +5 -40
  248. data/lib/spree/core/state_machines/order.rb +5 -247
  249. data/lib/spree/core/state_machines/payment.rb +5 -59
  250. data/lib/spree/core/state_machines/reimbursement.rb +5 -31
  251. data/lib/spree/core/state_machines/return_authorization.rb +5 -30
  252. data/lib/spree/core/state_machines/return_item/acceptance_status.rb +5 -49
  253. data/lib/spree/core/state_machines/return_item/reception_status.rb +5 -40
  254. data/lib/spree/core/state_machines/shipment.rb +5 -56
  255. data/lib/spree/core/state_machines.rb +48 -81
  256. data/lib/spree/core/stock_configuration.rb +18 -0
  257. data/lib/spree/core/validators/email.rb +2 -4
  258. data/lib/spree/core/version.rb +5 -1
  259. data/lib/spree/core/versioned_value.rb +75 -0
  260. data/lib/spree/core.rb +40 -16
  261. data/lib/spree/deprecated_instance_variable_proxy.rb +57 -0
  262. data/lib/spree/deprecation.rb +3 -51
  263. data/lib/spree/deprecator.rb +9 -0
  264. data/lib/spree/i18n.rb +1 -1
  265. data/lib/spree/mailer_previews/carton_preview.rb +1 -1
  266. data/lib/spree/migration_helpers.rb +3 -3
  267. data/lib/spree/migrations.rb +13 -11
  268. data/lib/spree/money.rb +5 -118
  269. data/lib/spree/permission_sets/base.rb +5 -30
  270. data/lib/spree/permission_sets/configuration_display.rb +5 -23
  271. data/lib/spree/permission_sets/configuration_management.rb +5 -23
  272. data/lib/spree/permission_sets/dashboard_display.rb +5 -9
  273. data/lib/spree/permission_sets/default_customer.rb +5 -35
  274. data/lib/spree/permission_sets/order_display.rb +5 -19
  275. data/lib/spree/permission_sets/order_management.rb +5 -20
  276. data/lib/spree/permission_sets/product_display.rb +5 -17
  277. data/lib/spree/permission_sets/product_management.rb +5 -19
  278. data/lib/spree/permission_sets/restricted_stock_display.rb +5 -16
  279. data/lib/spree/permission_sets/restricted_stock_management.rb +5 -16
  280. data/lib/spree/permission_sets/stock_display.rb +5 -10
  281. data/lib/spree/permission_sets/stock_management.rb +5 -10
  282. data/lib/spree/permission_sets/super_user.rb +5 -9
  283. data/lib/spree/permission_sets/user_display.rb +5 -11
  284. data/lib/spree/permission_sets/user_management.rb +5 -23
  285. data/lib/spree/permission_sets.rb +5 -18
  286. data/lib/spree/permitted_attributes.rb +35 -14
  287. data/lib/spree/preferences/configuration.rb +88 -0
  288. data/lib/spree/preferences/persistable.rb +7 -1
  289. data/lib/spree/preferences/preferable.rb +13 -0
  290. data/lib/spree/preferences/preferable_class_methods.rb +12 -4
  291. data/lib/spree/preferences/preference_differentiator.rb +29 -0
  292. data/lib/spree/preferences/static_model_preferences.rb +25 -10
  293. data/lib/spree/preferences/store.rb +2 -2
  294. data/lib/spree/testing_support/blacklist_urls.rb +1 -1
  295. data/lib/spree/testing_support/bus_helpers.rb +101 -0
  296. data/lib/spree/testing_support/capybara_ext.rb +11 -1
  297. data/lib/spree/testing_support/common_rake.rb +76 -23
  298. data/lib/spree/testing_support/dummy_ability.rb +7 -0
  299. data/lib/spree/testing_support/dummy_app/assets/javascripts/spree/backend/all.js +1 -1
  300. data/lib/spree/testing_support/dummy_app/assets/stylesheets/solidus_admin/tailwind.css +1 -0
  301. data/lib/spree/testing_support/dummy_app/database.yml +39 -28
  302. data/lib/spree/testing_support/dummy_app/migrations.rb +8 -15
  303. data/lib/spree/testing_support/dummy_app/rake_tasks.rb +3 -10
  304. data/lib/spree/testing_support/dummy_app.rb +71 -42
  305. data/lib/spree/testing_support/extension_rake.rb +2 -2
  306. data/lib/spree/testing_support/factories/address_factory.rb +9 -13
  307. data/lib/spree/testing_support/factories/adjustment_factory.rb +1 -13
  308. data/lib/spree/testing_support/factories/adjustment_reason_factory.rb +0 -5
  309. data/lib/spree/testing_support/factories/calculator_factory.rb +4 -10
  310. data/lib/spree/testing_support/factories/carton_factory.rb +2 -10
  311. data/lib/spree/testing_support/factories/country_factory.rb +1 -7
  312. data/lib/spree/testing_support/factories/credit_card_factory.rb +0 -5
  313. data/lib/spree/testing_support/factories/customer_return_factory.rb +2 -11
  314. data/lib/spree/testing_support/factories/image_factory.rb +0 -5
  315. data/lib/spree/testing_support/factories/inventory_unit_factory.rb +4 -14
  316. data/lib/spree/testing_support/factories/line_item_factory.rb +0 -8
  317. data/lib/spree/testing_support/factories/option_type_factory.rb +0 -8
  318. data/lib/spree/testing_support/factories/option_value_factory.rb +0 -5
  319. data/lib/spree/testing_support/factories/order_factory.rb +19 -38
  320. data/lib/spree/testing_support/factories/payment_factory.rb +0 -10
  321. data/lib/spree/testing_support/factories/payment_method_factory.rb +0 -5
  322. data/lib/spree/testing_support/factories/price_factory.rb +0 -7
  323. data/lib/spree/testing_support/factories/product_factory.rb +5 -13
  324. data/lib/spree/testing_support/factories/product_option_type_factory.rb +0 -8
  325. data/lib/spree/testing_support/factories/product_property_factory.rb +0 -8
  326. data/lib/spree/testing_support/factories/property_factory.rb +0 -5
  327. data/lib/spree/testing_support/factories/refund_factory.rb +0 -8
  328. data/lib/spree/testing_support/factories/refund_reason_factory.rb +0 -5
  329. data/lib/spree/testing_support/factories/reimbursement_factory.rb +0 -7
  330. data/lib/spree/testing_support/factories/reimbursement_type_factory.rb +0 -5
  331. data/lib/spree/testing_support/factories/return_authorization_factory.rb +0 -9
  332. data/lib/spree/testing_support/factories/return_item_factory.rb +0 -9
  333. data/lib/spree/testing_support/factories/return_reason_factory.rb +0 -5
  334. data/lib/spree/testing_support/factories/role_factory.rb +0 -5
  335. data/lib/spree/testing_support/factories/shipment_factory.rb +1 -11
  336. data/lib/spree/testing_support/factories/shipping_category_factory.rb +0 -5
  337. data/lib/spree/testing_support/factories/shipping_method_factory.rb +0 -9
  338. data/lib/spree/testing_support/factories/shipping_rate_factory.rb +0 -8
  339. data/lib/spree/testing_support/factories/state_factory.rb +8 -10
  340. data/lib/spree/testing_support/factories/stock_item_factory.rb +5 -9
  341. data/lib/spree/testing_support/factories/stock_location_factory.rb +0 -9
  342. data/lib/spree/testing_support/factories/stock_movement_factory.rb +0 -7
  343. data/lib/spree/testing_support/factories/stock_package_factory.rb +1 -9
  344. data/lib/spree/testing_support/factories/store_credit_category_factory.rb +0 -5
  345. data/lib/spree/testing_support/factories/store_credit_event_factory.rb +0 -8
  346. data/lib/spree/testing_support/factories/store_credit_factory.rb +4 -13
  347. data/lib/spree/testing_support/factories/store_credit_reason_factory.rb +0 -5
  348. data/lib/spree/testing_support/factories/store_credit_type_factory.rb +0 -5
  349. data/lib/spree/testing_support/factories/store_factory.rb +0 -5
  350. data/lib/spree/testing_support/factories/tax_category_factory.rb +0 -8
  351. data/lib/spree/testing_support/factories/tax_rate_factory.rb +0 -9
  352. data/lib/spree/testing_support/factories/taxon_factory.rb +5 -10
  353. data/lib/spree/testing_support/factories/taxonomy_factory.rb +3 -6
  354. data/lib/spree/testing_support/factories/user_factory.rb +6 -9
  355. data/lib/spree/testing_support/factories/variant_factory.rb +0 -10
  356. data/lib/spree/testing_support/factories/variant_property_rule_condition_factory.rb +0 -8
  357. data/lib/spree/testing_support/factories/variant_property_rule_factory.rb +0 -9
  358. data/lib/spree/testing_support/factories/variant_property_rule_value_factory.rb +0 -8
  359. data/lib/spree/testing_support/factories/zone_factory.rb +1 -9
  360. data/lib/spree/testing_support/factory_bot.rb +6 -29
  361. data/lib/spree/testing_support/flaky.rb +22 -0
  362. data/lib/spree/testing_support/order_walkthrough.rb +7 -6
  363. data/lib/spree/testing_support/sequences.rb +0 -5
  364. data/lib/spree/testing_support/shared_examples/calculator.rb +10 -0
  365. data/lib/spree/testing_support/shared_examples/order_factory.rb +141 -0
  366. data/lib/spree/testing_support/shared_examples/working_factory.rb +15 -0
  367. data/lib/spree/testing_support/silence_deprecations.rb +9 -0
  368. data/lib/spree/user_class_handle.rb +2 -2
  369. data/lib/tasks/colorado_delivery_fee.rake +28 -0
  370. data/lib/tasks/payment_method.rake +29 -0
  371. data/lib/tasks/solidus/delete_prices_with_nil_amount.rake +8 -0
  372. data/solidus_core.gemspec +18 -8
  373. metadata +233 -117
  374. data/app/jobs/spree/promotion_code_batch_job.rb +0 -26
  375. data/app/mailers/spree/promotion_code_batch_mailer.rb +0 -15
  376. data/app/models/spree/calculator/distributed_amount.rb +0 -33
  377. data/app/models/spree/calculator/flat_percent_item_total.rb +0 -23
  378. data/app/models/spree/calculator/flexi_rate.rb +0 -22
  379. data/app/models/spree/calculator/percent_on_line_item.rb +0 -13
  380. data/app/models/spree/calculator/tiered_flat_rate.rb +0 -52
  381. data/app/models/spree/calculator/tiered_percent.rb +0 -62
  382. data/app/models/spree/line_item_action.rb +0 -8
  383. data/app/models/spree/order_promotion.rb +0 -27
  384. data/app/models/spree/promotion/actions/create_adjustment.rb +0 -77
  385. data/app/models/spree/promotion/actions/create_item_adjustments.rb +0 -99
  386. data/app/models/spree/promotion/actions/create_quantity_adjustments.rb +0 -139
  387. data/app/models/spree/promotion/actions/free_shipping.rb +0 -58
  388. data/app/models/spree/promotion/rules/first_order.rb +0 -38
  389. data/app/models/spree/promotion/rules/first_repeat_purchase_since.rb +0 -36
  390. data/app/models/spree/promotion/rules/item_total.rb +0 -53
  391. data/app/models/spree/promotion/rules/nth_order.rb +0 -45
  392. data/app/models/spree/promotion/rules/one_use_per_user.rb +0 -25
  393. data/app/models/spree/promotion/rules/option_value.rb +0 -50
  394. data/app/models/spree/promotion/rules/product.rb +0 -74
  395. data/app/models/spree/promotion/rules/store.rb +0 -22
  396. data/app/models/spree/promotion/rules/taxon.rb +0 -87
  397. data/app/models/spree/promotion/rules/user.rb +0 -30
  398. data/app/models/spree/promotion/rules/user_logged_in.rb +0 -20
  399. data/app/models/spree/promotion/rules/user_role.rb +0 -45
  400. data/app/models/spree/promotion.rb +0 -284
  401. data/app/models/spree/promotion_action.rb +0 -43
  402. data/app/models/spree/promotion_category.rb +0 -8
  403. data/app/models/spree/promotion_chooser.rb +0 -34
  404. data/app/models/spree/promotion_code/batch_builder.rb +0 -64
  405. data/app/models/spree/promotion_code.rb +0 -50
  406. data/app/models/spree/promotion_code_batch.rb +0 -27
  407. data/app/models/spree/promotion_handler/cart.rb +0 -55
  408. data/app/models/spree/promotion_handler/coupon.rb +0 -123
  409. data/app/models/spree/promotion_handler/page.rb +0 -26
  410. data/app/models/spree/promotion_handler/shipping.rb +0 -61
  411. data/app/models/spree/promotion_rule.rb +0 -55
  412. data/app/models/spree/promotion_rule_role.rb +0 -8
  413. data/app/models/spree/promotion_rule_store.rb +0 -10
  414. data/app/models/spree/promotion_rule_taxon.rb +0 -8
  415. data/app/models/spree/promotion_rule_user.rb +0 -10
  416. data/app/models/spree/tax/shipping_rate_taxer.rb +0 -24
  417. data/app/subscribers/spree/mailer_subscriber.rb +0 -25
  418. data/app/views/spree/promotion_code_batch_mailer/promotion_code_batch_errored.text.erb +0 -2
  419. data/app/views/spree/promotion_code_batch_mailer/promotion_code_batch_finished.text.erb +0 -2
  420. data/db/migrate/20161017102621_create_spree_promotion_code_batch.rb +0 -38
  421. data/db/migrate/20180202190713_create_promotion_rule_stores.rb +0 -12
  422. data/db/migrate/20180328172631_add_join_characters_to_promotion_code_batch.rb +0 -11
  423. data/db/migrate/20190106184413_remove_code_from_spree_promotions.rb +0 -42
  424. data/lib/generators/solidus/install/templates/vendor/assets/javascripts/spree/frontend/all.js +0 -10
  425. data/lib/generators/solidus/install/templates/vendor/assets/stylesheets/spree/frontend/all.css +0 -9
  426. data/lib/generators/spree/dummy/templates/rails/script/rails +0 -6
  427. data/lib/solidus/migrations/promotions_with_code_handlers.rb +0 -66
  428. data/lib/spree/event/adapters/active_support_notifications.rb +0 -67
  429. data/lib/spree/event/configuration.rb +0 -25
  430. data/lib/spree/event/subscriber.rb +0 -86
  431. data/lib/spree/event/subscriber_registry.rb +0 -94
  432. data/lib/spree/event.rb +0 -119
  433. data/lib/spree/permission_sets/promotion_display.rb +0 -15
  434. data/lib/spree/permission_sets/promotion_management.rb +0 -15
  435. data/lib/spree/testing_support/dummy_app/assets/javascripts/spree/frontend/all.js +0 -10
  436. data/lib/spree/testing_support/dummy_app/assets/stylesheets/spree/frontend/all.css +0 -9
  437. data/lib/spree/testing_support/dummy_app/views/layouts/application.html.erb +0 -1
  438. data/lib/spree/testing_support/factories/order_promotion_factory.rb +0 -16
  439. data/lib/spree/testing_support/factories/promotion_category_factory.rb +0 -12
  440. data/lib/spree/testing_support/factories/promotion_code_factory.rb +0 -16
  441. data/lib/spree/testing_support/factories/promotion_factory.rb +0 -92
  442. data/lib/spree/testing_support/factories.rb +0 -11
  443. data/lib/spree/testing_support.rb +0 -31
  444. data/lib/tasks/upgrade.rake +0 -15
@@ -30,7 +30,7 @@ module Spree
30
30
  self.refund_amount_calculator = Calculator::Returns::DefaultRefundAmount
31
31
 
32
32
  belongs_to :return_authorization, inverse_of: :return_items, optional: true
33
- belongs_to :inventory_unit, inverse_of: :return_items, optional: true
33
+ belongs_to :inventory_unit, inverse_of: :return_items
34
34
  belongs_to :exchange_variant, class_name: 'Spree::Variant', optional: true
35
35
  belongs_to :exchange_inventory_unit, class_name: 'Spree::InventoryUnit', inverse_of: :original_return_item, optional: true
36
36
  belongs_to :customer_return, inverse_of: :return_items, optional: true
@@ -42,7 +42,6 @@ module Spree
42
42
  validate :eligible_exchange_variant
43
43
  validate :belongs_to_same_customer_order
44
44
  validate :validate_acceptance_status_for_reimbursement
45
- validates :inventory_unit, presence: true
46
45
  validate :validate_no_other_completed_return_items
47
46
 
48
47
  after_create :cancel_others, unless: :cancelled?
@@ -54,7 +53,7 @@ module Spree
54
53
  scope :not_expired, -> { where.not(reception_status: 'expired') }
55
54
  scope :received, -> { where(reception_status: 'received') }
56
55
  INTERMEDIATE_RECEPTION_STATUSES.each do |reception_status|
57
- scope reception_status, -> { where(reception_status: reception_status) }
56
+ scope reception_status, -> { where(reception_status:) }
58
57
  end
59
58
  scope :pending, -> { where(acceptance_status: 'pending') }
60
59
  scope :accepted, -> { where(acceptance_status: 'accepted') }
@@ -68,7 +67,7 @@ module Spree
68
67
  scope :exchange_processed, -> { where.not(exchange_inventory_unit: nil) }
69
68
  scope :exchange_required, -> { exchange_requested.where(exchange_inventory_unit: nil) }
70
69
 
71
- serialize :acceptance_status_errors
70
+ serialize :acceptance_status_errors, coder: YAML
72
71
 
73
72
  delegate :eligible_for_return?, :requires_manual_intervention?, to: :validator
74
73
  delegate :variant, to: :inventory_unit
@@ -94,8 +93,8 @@ module Spree
94
93
  # @return [Spree::ReturnItem] a valid return item for the given inventory
95
94
  # unit if one exists, or a new one if one does not
96
95
  def self.from_inventory_unit(inventory_unit)
97
- valid.find_by(inventory_unit: inventory_unit) ||
98
- new(inventory_unit: inventory_unit).tap(&:set_default_amount)
96
+ valid.find_by(inventory_unit:) ||
97
+ new(inventory_unit:).tap(&:set_default_amount)
99
98
  end
100
99
 
101
100
  # @return [Boolean] true when an exchange has been requested on this return
@@ -131,7 +130,7 @@ module Spree
131
130
  # @return [ActiveRecord::Relation<Spree::Variant>] the variants eligible
132
131
  # for exchange for this return item
133
132
  def eligible_exchange_variants(stock_locations = nil)
134
- exchange_variant_engine.eligible_variants(variant, stock_locations: stock_locations)
133
+ exchange_variant_engine.eligible_variants(variant, stock_locations:)
135
134
  end
136
135
 
137
136
  # Builds the exchange inventory unit for this return item, only if an
@@ -249,21 +248,20 @@ module Spree
249
248
 
250
249
  def validate_no_other_completed_return_items
251
250
  other_return_item = Spree::ReturnItem.where({
252
- inventory_unit_id: inventory_unit_id,
251
+ inventory_unit_id:,
253
252
  reception_status: COMPLETED_RECEPTION_STATUSES
254
- }).where.not(id: id).first
253
+ }).where.not(id:).first
255
254
 
256
255
  if other_return_item && (new_record? || COMPLETED_RECEPTION_STATUSES.include?(reception_status.to_sym))
257
- errors.add(:inventory_unit, :other_completed_return_item_exists, {
258
- inventory_unit_id: inventory_unit_id,
259
- return_item_id: other_return_item.id
260
- })
256
+ errors.add(:inventory_unit, :other_completed_return_item_exists,
257
+ inventory_unit_id:,
258
+ return_item_id: other_return_item.id)
261
259
  end
262
260
  end
263
261
 
264
262
  def cancel_others
265
- Spree::ReturnItem.where(inventory_unit_id: inventory_unit_id)
266
- .where.not(id: id)
263
+ Spree::ReturnItem.where(inventory_unit_id:)
264
+ .where.not(id:)
267
265
  .valid
268
266
  .each(&:cancel!)
269
267
  end
@@ -2,10 +2,15 @@
2
2
 
3
3
  module Spree
4
4
  class ReturnReason < Spree::Base
5
- include Spree::NamedType
5
+ scope :active, -> { where(active: true) }
6
+ default_scope -> { order(arel_table[:name].lower) }
7
+
8
+ validates :name, presence: true, uniqueness: { case_sensitive: false, allow_blank: true }
6
9
 
7
10
  has_many :return_authorizations
8
11
 
12
+ self.allowed_ransackable_attributes = %w[name]
13
+
9
14
  def self.reasons_for_return_items(return_items)
10
15
  # Only allow an inactive reason if it's already associated to a return item
11
16
  active | return_items.map(&:return_reason).compact
@@ -4,8 +4,10 @@ module Spree
4
4
  class Role < Spree::Base
5
5
  has_many :role_users, class_name: "Spree::RoleUser", dependent: :destroy
6
6
  has_many :users, through: :role_users
7
+ has_many :role_permissions, dependent: :destroy
8
+ has_many :permission_sets, through: :role_permissions
7
9
 
8
- validates_uniqueness_of :name, case_sensitive: true
10
+ validates :name, presence: true, uniqueness: { case_sensitive: true, allow_blank: true }
9
11
 
10
12
  def admin?
11
13
  name == "admin"
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ class RolePermission < Spree::Base
5
+ belongs_to :role
6
+ belongs_to :permission_set
7
+ end
8
+ end
@@ -4,6 +4,8 @@ module Spree
4
4
  # An order's planned shipments including tracking and cost.
5
5
  #
6
6
  class Shipment < Spree::Base
7
+ include Metadata
8
+
7
9
  belongs_to :order, class_name: 'Spree::Order', touch: true, inverse_of: :shipments, optional: true
8
10
  belongs_to :stock_location, class_name: 'Spree::StockLocation', optional: true
9
11
 
@@ -31,7 +33,7 @@ module Spree
31
33
  scope :ready, -> { with_state('ready') }
32
34
  scope :shipped, -> { with_state('shipped') }
33
35
  scope :trackable, -> { where("tracking IS NOT NULL AND tracking != ''") }
34
- scope :with_state, ->(*state) { where(state: state) }
36
+ scope :with_state, ->(*state) { where(state:) }
35
37
  # sort by most recent shipped_at, falling back to created_at. add "id desc" to make specs that involve this scope more deterministic.
36
38
  scope :reverse_chronological, -> {
37
39
  order(Arel.sql("coalesce(#{Spree::Shipment.table_name}.shipped_at, #{Spree::Shipment.table_name}.created_at) desc"), id: :desc)
@@ -41,8 +43,8 @@ module Spree
41
43
 
42
44
  include ::Spree::Config.state_machines.shipment
43
45
 
44
- self.whitelisted_ransackable_associations = ['order']
45
- self.whitelisted_ransackable_attributes = ['number']
46
+ self.allowed_ransackable_associations = ['order']
47
+ self.allowed_ransackable_attributes = ['number']
46
48
 
47
49
  delegate :tax_category, :tax_category_id, to: :selected_shipping_rate, allow_nil: true
48
50
 
@@ -92,7 +94,7 @@ module Spree
92
94
  # @return [BigDecimal] the amount of this item, taking into consideration
93
95
  # all non-tax adjustments.
94
96
  def total_before_tax
95
- amount + adjustments.select { |adjustment| !adjustment.tax? && adjustment.eligible? }.sum(&:amount)
97
+ amount + adjustments.reject(&:tax?).sum(&:amount)
96
98
  end
97
99
 
98
100
  # @return [BigDecimal] the amount of this shipment before VAT tax
@@ -175,7 +177,7 @@ module Spree
175
177
  end
176
178
 
177
179
  def manifest
178
- @manifest ||= Spree::ShippingManifest.new(inventory_units: inventory_units).items
180
+ @manifest ||= Spree::ShippingManifest.new(inventory_units:).items
179
181
  end
180
182
 
181
183
  def selected_shipping_rate_id
@@ -217,7 +219,7 @@ module Spree
217
219
 
218
220
  def set_up_inventory(state, variant, _order, line_item)
219
221
  inventory_units.create(
220
- state: state,
222
+ state:,
221
223
  variant_id: variant.id,
222
224
  line_item_id: line_item.id
223
225
  )
@@ -263,7 +265,7 @@ module Spree
263
265
  self.cost = selected_shipping_rate.cost
264
266
  if changed?
265
267
  update_columns(
266
- cost: cost,
268
+ cost:,
267
269
  updated_at: Time.current
268
270
  )
269
271
  end
@@ -286,7 +288,7 @@ module Spree
286
288
 
287
289
  # Updates the state of the Shipment bypassing any callbacks.
288
290
  #
289
- # If this moves the shipmnent to the 'shipped' state, after_ship will be
291
+ # If this moves the shipment to the 'shipped' state, after_ship will be
290
292
  # called.
291
293
  def update_state
292
294
  old_state = state
@@ -312,7 +314,7 @@ module Spree
312
314
  end
313
315
 
314
316
  def after_ship
315
- order.shipping.ship_shipment(self, suppress_mailer: suppress_mailer)
317
+ order.shipping.ship_shipment(self, suppress_mailer:)
316
318
  end
317
319
 
318
320
  def can_get_rates?
@@ -339,7 +341,7 @@ module Spree
339
341
 
340
342
  def ensure_can_destroy
341
343
  if shipped? || canceled?
342
- errors.add(:state, :cannot_destroy, state: state)
344
+ errors.add(:state, :cannot_destroy, state:)
343
345
  throw :abort
344
346
  end
345
347
  end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Spree
4
4
  class ShippingCategory < Spree::Base
5
+ self.allowed_ransackable_attributes = %w[name]
6
+
5
7
  validates :name, presence: true
6
8
  has_many :products, inverse_of: :shipping_category
7
9
  has_many :shipping_method_categories, inverse_of: :shipping_category
@@ -18,8 +18,7 @@ module Spree
18
18
  delegate :name, :tax_category, :tax_category_id, to: :shipping_method
19
19
  delegate :code, to: :shipping_method, prefix: true
20
20
  alias_attribute :amount, :cost
21
-
22
- alias_method :total_before_tax, :amount
21
+ alias_attribute :total_before_tax, :cost
23
22
 
24
23
  extend DisplayMoney
25
24
  money_methods :amount
@@ -32,7 +31,7 @@ module Spree
32
31
  tax_explanations = taxes.map(&:label).join(tax_label_separator)
33
32
 
34
33
  I18n.t 'spree.shipping_rate.display_price.display_price_with_explanations',
35
- price: price,
34
+ price:,
36
35
  explanations: tax_explanations
37
36
  end
38
37
  alias_method :display_cost, :display_price
@@ -5,7 +5,7 @@ module Spree
5
5
  # @attr [Spree::ShippingRate] shipping_rate The shipping rate to be taxed
6
6
  # @attr [Spree::TaxRate] tax_rate The tax rate used to calculate the tax amount
7
7
  # @since 1.3.0
8
- # @see Spree::Tax::ShippingRateTaxer
8
+ # @see Spree::Stock::Estimator
9
9
  class ShippingRateTax < Spree::Base
10
10
  belongs_to :shipping_rate, class_name: "Spree::ShippingRate", optional: true
11
11
  belongs_to :tax_rate, class_name: "Spree::TaxRate", optional: true
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Spree
4
- class OrderContents
4
+ class SimpleOrderContents
5
5
  attr_accessor :order
6
6
 
7
7
  def initialize(order)
@@ -38,12 +38,7 @@ module Spree
38
38
  if order.update(params)
39
39
  unless order.completed?
40
40
  order.line_items = order.line_items.select { |li| li.quantity > 0 }
41
- # Update totals, then check if the order is eligible for any cart promotions.
42
- # If we do not update first, then the item total will be wrong and ItemTotal
43
- # promotion rules would not be triggered.
44
- reload_totals
45
- PromotionHandler::Cart.new(order).activate
46
- order.ensure_updated_shipments
41
+ order.check_shipments_and_restart_checkout
47
42
  end
48
43
  reload_totals
49
44
  true
@@ -71,10 +66,8 @@ module Spree
71
66
  private
72
67
 
73
68
  def after_add_or_remove(line_item, options = {})
74
- reload_totals
75
69
  shipment = options[:shipment]
76
- shipment.present? ? shipment.update_amounts : order.ensure_updated_shipments
77
- PromotionHandler::Cart.new(order, line_item).activate
70
+ shipment.present? ? shipment.update_amounts : order.check_shipments_and_restart_checkout
78
71
  reload_totals
79
72
  line_item
80
73
  end
@@ -88,11 +81,15 @@ module Spree
88
81
 
89
82
  line_item ||= order.line_items.new(
90
83
  quantity: 0,
91
- variant: variant,
84
+ variant:,
85
+ adjustments: []
92
86
  )
93
87
 
88
+ permitted_attributes = Spree::PermittedAttributes.line_item_attributes.dup
89
+ permitted_attributes << { admin_metadata: {} } if options[:admin_metadata].present?
90
+
94
91
  line_item.quantity += quantity.to_i
95
- line_item.options = ActionController::Parameters.new(options).permit(PermittedAttributes.line_item_attributes).to_h
92
+ line_item.options = ActionController::Parameters.new(options).permit(permitted_attributes).to_h
96
93
 
97
94
  line_item.target_shipment = options[:shipment]
98
95
  line_item.save!
@@ -116,7 +113,7 @@ module Spree
116
113
  def grab_line_item_by_variant(variant, raise_error = false, options = {})
117
114
  line_item = order.find_line_item_by_variant(variant, options)
118
115
 
119
- if !line_item.present? && raise_error
116
+ if line_item.blank? && raise_error
120
117
  raise ActiveRecord::RecordNotFound, "Line item not found for variant #{variant.sku}"
121
118
  end
122
119
 
@@ -15,7 +15,7 @@ module Spree
15
15
  )
16
16
  end
17
17
 
18
- self.whitelisted_ransackable_attributes = %w[name]
18
+ self.allowed_ransackable_attributes = %w[name]
19
19
 
20
20
  # table of { country.id => [ state.id , state.name ] }, arrays sorted by name
21
21
  # blank is added elsewhere, if needed
@@ -7,11 +7,11 @@ module Spree
7
7
  def allocate_inventory(desired)
8
8
  # Allocate any available on hand inventory
9
9
  on_hand = allocate_on_hand(desired)
10
- desired -= on_hand.values.sum if on_hand.present?
10
+ desired -= on_hand.values.reduce(&:+) if on_hand.present?
11
11
 
12
12
  # Allocate remaining desired inventory from backorders
13
13
  backordered = allocate_backordered(desired)
14
- desired -= backordered.values.sum if backordered.present?
14
+ desired -= backordered.values.reduce(&:+) if backordered.present?
15
15
 
16
16
  # If all works at this point desired must be empty
17
17
  [on_hand, backordered, desired]
@@ -19,7 +19,7 @@ module Spree
19
19
  # Get the on_hand stock quantities
20
20
  # @return [Hash<Integer=>Spree::StockQuantities>] A map of stock_location_ids to the stock quantities available in that location
21
21
  def on_hand_by_stock_location_id
22
- counts_on_hand.to_a.group_by do |(_, stock_location_id), _|
22
+ quantities_by_location_id = counts_on_hand.to_a.group_by do |(_, stock_location_id), _|
23
23
  stock_location_id
24
24
  end.transform_values do |values|
25
25
  Spree::StockQuantities.new(
@@ -31,12 +31,13 @@ module Spree
31
31
  end.to_h
32
32
  )
33
33
  end
34
+ restore_location_order(quantities_by_location_id)
34
35
  end
35
36
 
36
- # Get the on_hand stock quantities
37
+ # Get the backorderable stock quantities
37
38
  # @return [Hash<Integer=>Spree::StockQuantities>] A map of stock_location_ids to the stock quantities available in that location
38
39
  def backorderable_by_stock_location_id
39
- backorderables.group_by(&:second).transform_values do |variant_ids|
40
+ quantities_by_location_id = backorderables.group_by(&:second).transform_values do |variant_ids|
40
41
  Spree::StockQuantities.new(
41
42
  variant_ids.map do |variant_id, _|
42
43
  variant = @variant_map[variant_id]
@@ -44,6 +45,7 @@ module Spree
44
45
  end.to_h
45
46
  )
46
47
  end
48
+ restore_location_order(quantities_by_location_id)
47
49
  end
48
50
 
49
51
  private
@@ -67,6 +69,12 @@ module Spree
67
69
  where(variant_id: @variants).
68
70
  where(stock_location_id: @stock_locations)
69
71
  end
72
+
73
+ def restore_location_order(quantities_by_location_id)
74
+ sorted_location_ids = @stock_locations.map(&:id)
75
+
76
+ quantities_by_location_id.sort_by { |key, _value| sorted_location_ids.index(key) }.to_h
77
+ end
70
78
  end
71
79
  end
72
80
  end
@@ -39,7 +39,7 @@ module Spree
39
39
  cost = shipping_method.calculator.compute(package)
40
40
  if cost
41
41
  rate = shipping_method.shipping_rates.new(
42
- cost: cost,
42
+ cost:,
43
43
  shipment: package.shipment
44
44
  )
45
45
  tax_calculator.calculate(rate).each do |tax|
@@ -25,7 +25,7 @@ module Spree
25
25
  Spree::InventoryUnit.new(
26
26
  pending: true,
27
27
  variant: line_item.variant,
28
- line_item: line_item
28
+ line_item:
29
29
  )
30
30
  end
31
31
  end
@@ -124,8 +124,8 @@ module Spree
124
124
  contents.each { |content_item| content_item.inventory_unit.state = content_item.state.to_s }
125
125
 
126
126
  Spree::Shipment.new(
127
- order: order,
128
- stock_location: stock_location,
127
+ order:,
128
+ stock_location:,
129
129
  inventory_units: contents.map(&:inventory_unit)
130
130
  )
131
131
  end
@@ -6,14 +6,18 @@ module Spree
6
6
  attr_reader :stock_items
7
7
 
8
8
  # @param [Variant] variant The variant to check inventory for.
9
- # @param [StockLocation, Integer] stock_location The stock_location to check inventory in. If unspecified it will check inventory in all available StockLocations
10
- def initialize(variant, stock_location = nil)
9
+ # @param [StockLocation, Integer] stock_location_or_id
10
+ # The stock_location or stock location ID to check inventory in.
11
+ # If unspecified it will check inventory in all available StockLocations
12
+ def initialize(variant, stock_location_or_id = nil)
11
13
  @variant = variant
12
- @stock_items = Spree::StockItem.where(variant_id: variant)
13
- if stock_location
14
- @stock_items.where!(stock_location: stock_location)
15
- else
16
- @stock_items.joins!(:stock_location).merge!(Spree::StockLocation.active)
14
+ @stock_items = variant.stock_items.select do |stock_item|
15
+ if stock_location_or_id
16
+ stock_item.stock_location == stock_location_or_id ||
17
+ stock_item.stock_location_id == stock_location_or_id
18
+ else
19
+ stock_item.stock_location.active?
20
+ end
17
21
  end
18
22
  end
19
23
 
@@ -23,7 +27,7 @@ module Spree
23
27
  # inventory is not tracked on the variant.
24
28
  def total_on_hand
25
29
  if @variant.should_track_inventory?
26
- stock_items.sum(:count_on_hand)
30
+ stock_items.sum(&:count_on_hand)
27
31
  else
28
32
  Float::INFINITY
29
33
  end
@@ -22,38 +22,65 @@ module Spree
22
22
  class SimpleCoordinator
23
23
  attr_reader :order
24
24
 
25
+ # @api private
26
+ attr_reader :inventory_units, :splitters, :stock_locations,
27
+ :filtered_stock_locations, :inventory_units_by_variant, :desired,
28
+ :availability, :allocator, :packages
29
+
25
30
  def initialize(order, inventory_units = nil)
26
31
  @order = order
27
- @inventory_units = inventory_units || InventoryUnitBuilder.new(order).units
32
+ @inventory_units =
33
+ inventory_units || Spree::Config.stock.inventory_unit_builder_class.new(order).units
28
34
  @splitters = Spree::Config.environment.stock_splitters
29
35
 
30
- filtered_stock_locations = Spree::Config.stock.location_filter_class.new(Spree::StockLocation.all, @order).filter
36
+ @filtered_stock_locations = Spree::Config.stock.location_filter_class.new(load_stock_locations, order).filter
31
37
  sorted_stock_locations = Spree::Config.stock.location_sorter_class.new(filtered_stock_locations).sort
32
38
  @stock_locations = sorted_stock_locations
33
39
 
34
40
  @inventory_units_by_variant = @inventory_units.group_by(&:variant)
35
- @desired = Spree::StockQuantities.new(@inventory_units_by_variant.transform_values(&:count))
41
+ @desired = Spree::StockQuantities.new(inventory_units_by_variant.transform_values(&:count))
36
42
  @availability = Spree::Stock::Availability.new(
37
- variants: @desired.variants,
38
- stock_locations: @stock_locations
43
+ variants: desired.variants,
44
+ stock_locations:
39
45
  )
40
46
 
41
- @allocator = Spree::Config.stock.allocator_class.new(@availability)
47
+ @allocator = Spree::Config.stock.allocator_class.new(availability)
42
48
  end
43
49
 
44
50
  def shipments
45
- @shipments ||= build_shipments
51
+ @shipments ||= begin
52
+ @packages = build_packages
53
+ shipments = build_shipments
54
+
55
+ # Make sure we don't add the proposed shipments to the order
56
+ order.shipments = order.shipments - shipments
57
+
58
+ shipments
59
+ end
46
60
  end
47
61
 
48
62
  private
49
63
 
64
+ def load_stock_locations
65
+ Spree::StockLocation.all
66
+ end
67
+
50
68
  def build_shipments
69
+ # Turn the Stock::Packages into a Shipment with rates
70
+ packages.map do |package|
71
+ shipment = package.shipment = package.to_shipment
72
+ shipment.shipping_rates = Spree::Config.stock.estimator_class.new.shipping_rates(package)
73
+ shipment
74
+ end
75
+ end
76
+
77
+ def build_packages
51
78
  # Allocate any available on hand inventory and remaining desired inventory from backorders
52
- on_hand_packages, backordered_packages, leftover = @allocator.allocate_inventory(@desired)
79
+ on_hand_packages, backordered_packages, leftover = allocator.allocate_inventory(desired)
53
80
 
54
81
  raise Spree::Order::InsufficientStock.new(items: leftover.quantities) unless leftover.empty?
55
82
 
56
- packages = @stock_locations.map do |stock_location|
83
+ packages = stock_locations.map do |stock_location|
57
84
  # Combine on_hand and backorders into a single package per-location
58
85
  on_hand = on_hand_packages[stock_location.id] || Spree::StockQuantities.new
59
86
  backordered = backordered_packages[stock_location.id] || Spree::StockQuantities.new
@@ -70,14 +97,7 @@ module Spree
70
97
  end.compact
71
98
 
72
99
  # Split the packages
73
- packages = split_packages(packages)
74
-
75
- # Turn the Stock::Packages into a Shipment with rates
76
- packages.map do |package|
77
- shipment = package.shipment = package.to_shipment
78
- shipment.shipping_rates = Spree::Config.stock.estimator_class.new.shipping_rates(package)
79
- shipment
80
- end
100
+ split_packages(packages)
81
101
  end
82
102
 
83
103
  def split_packages(initial_packages)
@@ -87,20 +107,10 @@ module Spree
87
107
  end
88
108
  end
89
109
 
90
- def sort_availability(availability)
91
- sorted_availability = availability.sort_by do |stock_location_id, _|
92
- @stock_locations.find_index do |stock_location|
93
- stock_location.id == stock_location_id
94
- end
95
- end
96
-
97
- Hash[sorted_availability]
98
- end
99
-
100
110
  def get_units(quantities)
101
111
  # Change our raw quantities back into inventory units
102
112
  quantities.flat_map do |variant, quantity|
103
- @inventory_units_by_variant[variant].shift(quantity)
113
+ inventory_units_by_variant[variant].shift(quantity)
104
114
  end
105
115
  end
106
116
  end
@@ -24,7 +24,7 @@ module Spree
24
24
 
25
25
  def hash_to_packages(categories)
26
26
  packages = []
27
- categories.each do |_id, contents|
27
+ categories.each_value do |contents|
28
28
  packages << build_package(contents)
29
29
  end
30
30
  packages
@@ -20,7 +20,8 @@ module Spree
20
20
  after_save :conditional_variant_touch, if: :saved_changes?
21
21
  after_touch { variant.touch }
22
22
 
23
- self.whitelisted_ransackable_attributes = ['count_on_hand', 'stock_location_id']
23
+ self.allowed_ransackable_attributes = ['count_on_hand', 'stock_location_id']
24
+ self.allowed_ransackable_associations = %w[variant]
24
25
 
25
26
  # @return [Array<Spree::InventoryUnit>] the backordered inventory units
26
27
  # associated with this stock item
@@ -26,12 +26,12 @@ module Spree
26
26
  validates_uniqueness_of :code, allow_blank: true, case_sensitive: false
27
27
 
28
28
  scope :active, -> { where(active: true) }
29
- scope :order_default, -> { order(default: :desc, name: :asc) }
29
+ scope :order_default, -> { order(default: :desc, position: :asc) }
30
30
 
31
31
  after_create :create_stock_items, if: :propagate_all_variants?
32
32
  after_save :ensure_one_default
33
33
 
34
- self.whitelisted_ransackable_attributes = %w[name]
34
+ self.allowed_ransackable_attributes = %w[name]
35
35
 
36
36
  def state_text
37
37
  state.try(:abbr) || state.try(:name) || state_name
@@ -39,7 +39,7 @@ module Spree
39
39
 
40
40
  # Wrapper for creating a new stock item respecting the backorderable config
41
41
  def propagate_variant(variant)
42
- stock_items.create!(variant: variant, backorderable: backorderable_default)
42
+ stock_items.create!(variant:, backorderable: backorderable_default)
43
43
  end
44
44
 
45
45
  # Return either an existing stock item or create a new one. Useful in
@@ -55,7 +55,7 @@ module Spree
55
55
  #
56
56
  # @return [StockItem] Corresponding StockItem for the StockLocation's variant.
57
57
  def stock_item(variant_id)
58
- stock_items.where(variant_id: variant_id).order(:id).first
58
+ stock_items.where(variant_id:).order(:id).first
59
59
  end
60
60
 
61
61
  # Attempts to look up StockItem for the variant, and creates one if not found.
@@ -101,8 +101,8 @@ module Spree
101
101
  if quantity < 1 && !stock_item(variant)
102
102
  raise InvalidMovementError.new(I18n.t('spree.negative_movement_absent_item'))
103
103
  end
104
- stock_item_or_create(variant).stock_movements.create!(quantity: quantity,
105
- originator: originator)
104
+ stock_item_or_create(variant).stock_movements.create!(quantity:,
105
+ originator:)
106
106
  end
107
107
 
108
108
  def fill_status(variant, quantity)
@@ -121,7 +121,7 @@ module Spree
121
121
 
122
122
  def ensure_one_default
123
123
  if default
124
- Spree::StockLocation.where(default: true).where.not(id: id).each do |stock_location|
124
+ Spree::StockLocation.where(default: true).where.not(id:).find_each do |stock_location|
125
125
  stock_location.default = false
126
126
  stock_location.save!
127
127
  end
@@ -13,8 +13,8 @@ module Spree
13
13
 
14
14
  scope :recent, -> { order(created_at: :desc) }
15
15
 
16
- self.whitelisted_ransackable_associations = %w[variant]
17
- self.whitelisted_ransackable_attributes = ['quantity']
16
+ self.allowed_ransackable_associations = %w[variant]
17
+ self.allowed_ransackable_attributes = ['quantity']
18
18
 
19
19
  def readonly?
20
20
  !new_record?