solidus_core 4.4.2 → 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 (118) hide show
  1. checksums.yaml +4 -4
  2. data/app/helpers/spree/core/controller_helpers/auth.rb +66 -0
  3. data/app/helpers/spree/core/controller_helpers/common.rb +82 -0
  4. data/app/helpers/spree/core/controller_helpers/order.rb +86 -0
  5. data/app/helpers/spree/core/controller_helpers/payment_parameters.rb +165 -0
  6. data/app/helpers/spree/core/controller_helpers/pricing.rb +19 -0
  7. data/app/helpers/spree/core/controller_helpers/search.rb +16 -0
  8. data/app/helpers/spree/core/controller_helpers/store.rb +19 -0
  9. data/app/helpers/spree/core/controller_helpers/strong_parameters.rb +74 -0
  10. data/app/models/concerns/spree/metadata.rb +64 -0
  11. data/app/models/concerns/spree/user_address_book.rb +4 -5
  12. data/app/models/spree/core/state_machines/inventory_unit.rb +42 -0
  13. data/app/models/spree/core/state_machines/order/class_methods.rb +217 -0
  14. data/app/models/spree/core/state_machines/order.rb +42 -0
  15. data/app/models/spree/core/state_machines/payment.rb +61 -0
  16. data/app/models/spree/core/state_machines/reimbursement.rb +33 -0
  17. data/app/models/spree/core/state_machines/return_authorization.rb +32 -0
  18. data/app/models/spree/core/state_machines/return_item/acceptance_status.rb +51 -0
  19. data/app/models/spree/core/state_machines/return_item/reception_status.rb +42 -0
  20. data/app/models/spree/core/state_machines/shipment.rb +58 -0
  21. data/app/models/spree/customer_return.rb +2 -0
  22. data/app/models/spree/item_total.rb +28 -0
  23. data/app/models/spree/legacy_user.rb +1 -0
  24. data/app/models/spree/line_item.rb +21 -0
  25. data/app/models/spree/money.rb +120 -0
  26. data/app/models/spree/order.rb +20 -9
  27. data/app/models/spree/order_merger.rb +1 -1
  28. data/app/models/spree/order_taxation.rb +1 -0
  29. data/app/models/spree/order_updater.rb +13 -30
  30. data/app/models/spree/payment.rb +1 -0
  31. data/app/models/spree/permission_sets/base.rb +45 -0
  32. data/app/models/spree/permission_sets/configuration_display.rb +53 -0
  33. data/app/models/spree/permission_sets/configuration_management.rb +52 -0
  34. data/app/models/spree/permission_sets/dashboard_display.rb +28 -0
  35. data/app/models/spree/permission_sets/default_customer.rb +83 -0
  36. data/app/models/spree/permission_sets/order_display.rb +50 -0
  37. data/app/models/spree/permission_sets/order_management.rb +50 -0
  38. data/app/models/spree/permission_sets/product_display.rb +43 -0
  39. data/app/models/spree/permission_sets/product_management.rb +47 -0
  40. data/app/models/spree/permission_sets/restricted_stock_display.rb +33 -0
  41. data/app/models/spree/permission_sets/restricted_stock_management.rb +33 -0
  42. data/app/models/spree/permission_sets/stock_display.rb +26 -0
  43. data/app/models/spree/permission_sets/stock_management.rb +26 -0
  44. data/app/models/spree/permission_sets/super_user.rb +26 -0
  45. data/app/models/spree/permission_sets/user_display.rb +27 -0
  46. data/app/models/spree/permission_sets/user_management.rb +44 -0
  47. data/app/models/spree/product.rb +7 -0
  48. data/app/models/spree/refund.rb +2 -0
  49. data/app/models/spree/return_authorization.rb +2 -0
  50. data/app/models/spree/shipment.rb +2 -0
  51. data/app/models/spree/simple_order_contents.rb +4 -1
  52. data/app/models/spree/store_credit_event.rb +1 -0
  53. data/app/models/spree/tax/tax_helpers.rb +12 -1
  54. data/app/models/spree/tax_calculator/default.rb +1 -1
  55. data/app/models/spree/taxon.rb +22 -2
  56. data/app/models/spree/taxon_brand_selector.rb +22 -0
  57. data/app/models/spree/unauthorized_redirect_handler.rb +24 -0
  58. data/app/models/spree/user_address.rb +9 -3
  59. data/app/models/spree/variant.rb +14 -1
  60. data/config/locales/en.yml +14 -0
  61. data/db/migrate/20220419170826_remove_archived_user_addresses.rb +12 -0
  62. data/db/migrate/20250129061658_add_metadata_to_spree_resources.rb +28 -0
  63. data/db/migrate/20250201172950_add_gtin_and_condition_to_spree_variant.rb +6 -0
  64. data/db/migrate/20250207104016_add_primary_taxon_to_products.rb +7 -0
  65. data/db/migrate/20250221152004_add_metadata_to_users.rb +13 -0
  66. data/lib/generators/solidus/install/app_templates/authentication/custom.rb +0 -5
  67. data/lib/generators/solidus/install/app_templates/frontend/starter.rb +1 -1
  68. data/lib/generators/spree/dummy/dummy_generator.rb +1 -1
  69. data/lib/generators/spree/dummy/templates/rails/application.rb.tt +1 -1
  70. data/lib/generators/spree/dummy/templates/rails/manifest.js +3 -0
  71. data/lib/spree/app_configuration.rb +49 -0
  72. data/lib/spree/core/controller_helpers/auth.rb +5 -61
  73. data/lib/spree/core/controller_helpers/common.rb +5 -80
  74. data/lib/spree/core/controller_helpers/order.rb +5 -86
  75. data/lib/spree/core/controller_helpers/payment_parameters.rb +5 -163
  76. data/lib/spree/core/controller_helpers/pricing.rb +5 -17
  77. data/lib/spree/core/controller_helpers/search.rb +5 -14
  78. data/lib/spree/core/controller_helpers/store.rb +5 -17
  79. data/lib/spree/core/controller_helpers/strong_parameters.rb +5 -71
  80. data/lib/spree/core/engine.rb +5 -0
  81. data/lib/spree/core/state_machines/inventory_unit.rb +5 -40
  82. data/lib/spree/core/state_machines/order.rb +5 -250
  83. data/lib/spree/core/state_machines/payment.rb +5 -59
  84. data/lib/spree/core/state_machines/reimbursement.rb +5 -31
  85. data/lib/spree/core/state_machines/return_authorization.rb +5 -30
  86. data/lib/spree/core/state_machines/return_item/acceptance_status.rb +5 -49
  87. data/lib/spree/core/state_machines/return_item/reception_status.rb +5 -40
  88. data/lib/spree/core/state_machines/shipment.rb +5 -56
  89. data/lib/spree/core/state_machines.rb +48 -81
  90. data/lib/spree/core/version.rb +2 -2
  91. data/lib/spree/core.rb +0 -10
  92. data/lib/spree/money.rb +5 -118
  93. data/lib/spree/permission_sets/base.rb +5 -42
  94. data/lib/spree/permission_sets/configuration_display.rb +5 -51
  95. data/lib/spree/permission_sets/configuration_management.rb +5 -50
  96. data/lib/spree/permission_sets/dashboard_display.rb +5 -26
  97. data/lib/spree/permission_sets/default_customer.rb +5 -81
  98. data/lib/spree/permission_sets/order_display.rb +5 -48
  99. data/lib/spree/permission_sets/order_management.rb +5 -48
  100. data/lib/spree/permission_sets/product_display.rb +5 -41
  101. data/lib/spree/permission_sets/product_management.rb +5 -45
  102. data/lib/spree/permission_sets/restricted_stock_display.rb +5 -31
  103. data/lib/spree/permission_sets/restricted_stock_management.rb +5 -31
  104. data/lib/spree/permission_sets/stock_display.rb +5 -24
  105. data/lib/spree/permission_sets/stock_management.rb +5 -24
  106. data/lib/spree/permission_sets/super_user.rb +5 -24
  107. data/lib/spree/permission_sets/user_display.rb +5 -25
  108. data/lib/spree/permission_sets/user_management.rb +5 -42
  109. data/lib/spree/permission_sets.rb +5 -16
  110. data/lib/spree/permitted_attributes.rb +18 -7
  111. data/lib/spree/preferences/configuration.rb +4 -0
  112. data/lib/spree/preferences/persistable.rb +1 -1
  113. data/lib/spree/testing_support/capybara_ext.rb +10 -0
  114. data/lib/spree/testing_support/dummy_app.rb +1 -1
  115. data/lib/spree/testing_support/factories/order_factory.rb +9 -1
  116. data/solidus_core.gemspec +1 -1
  117. metadata +65 -24
  118. data/lib/generators/spree/dummy/templates/rails/script/rails +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9a77feaec973407e0036df672af2decbf5a3a0fcae38d4041dcbd5fea19bfbaf
4
- data.tar.gz: ed69345a425cef54bb72257aa687711c9379903866886035f54510dc076aedb4
3
+ metadata.gz: 995355f29d96abe41d7beb6b28cbe8bd8198d8c4ebee544dedc223f15b856548
4
+ data.tar.gz: 07b683686244717fc86fe1a83777e29845365dbed70c2117d1aacddf8c729717
5
5
  SHA512:
6
- metadata.gz: 47c13a634466741aa45278e9fd7007eed9621ac595ae9bcfd9c5f8bbeeeae932b2419e620ec574b00a68c4f90a8a8e866042744895cf71d5443dc42ff39577b8
7
- data.tar.gz: 3d8a8943ae006304d636ba1c54108a01d46b390bf10085c917002caaeb2b3b4c55986ba528efa8a6b18ce2b2f39d49b40d589cff4233a7c67977e634adeacf13
6
+ metadata.gz: '0963f51448492bca5190edb6641ea96206670f8ce17bea75e67c429838b5b98c041a936d64f57b994ca731df036995ef402eb24e723840a3b00efb109bf4e5c0'
7
+ data.tar.gz: 0fc6248571ff6027d618e4840d9c154bba8674fdbfd96805a58fbbc051b7c36d9c31d6e1d20b042bce38b8c5fc2b48d8b3201acb2ec264be2466c29704612c02
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cancan'
4
+
5
+ module Spree
6
+ module Core
7
+ module ControllerHelpers
8
+ module Auth
9
+ extend ActiveSupport::Concern
10
+
11
+ # @!attribute [rw] unauthorized_redirect
12
+ # @!scope class
13
+ # Extension point for overriding behaviour of access denied errors.
14
+ # Default behaviour is to redirect back or to "/unauthorized" with a flash
15
+ # message.
16
+ # @return [Proc] action to take when access denied error is raised.
17
+
18
+ included do
19
+ before_action :set_guest_token
20
+ helper_method :spree_current_user
21
+
22
+ class_attribute :unauthorized_redirect
23
+ deprecate :unauthorized_redirect= => "Use a custom Spree::Config.unauthorized_redirect_handler_class instead", :deprecator => Spree.deprecator
24
+
25
+ rescue_from CanCan::AccessDenied, with: :handle_unauthorized_access
26
+ end
27
+
28
+ # Needs to be overriden so that we use Spree's Ability rather than anyone else's.
29
+ def current_ability
30
+ @current_ability ||= Spree::Ability.new(spree_current_user)
31
+ end
32
+
33
+ def redirect_back_or_default(default)
34
+ redirect_to(session["spree_user_return_to"] || default)
35
+ session["spree_user_return_to"] = nil
36
+ end
37
+
38
+ def set_guest_token
39
+ if cookies.signed[:guest_token].blank?
40
+ cookies.permanent.signed[:guest_token] = Spree::Config[:guest_token_cookie_options].merge(
41
+ value: SecureRandom.urlsafe_base64(nil, false),
42
+ httponly: true
43
+ )
44
+ end
45
+ end
46
+
47
+ def store_location
48
+ Spree::UserLastUrlStorer.new(self).store_location
49
+ end
50
+
51
+ # Auth extensions are expected to define it, otherwise it's a no-op
52
+ def spree_current_user
53
+ defined?(super) ? super : nil
54
+ end
55
+
56
+ def handle_unauthorized_access
57
+ if unauthorized_redirect
58
+ instance_exec(&unauthorized_redirect)
59
+ else
60
+ Spree::Config.unauthorized_redirect_handler_class.new(self).call
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'carmen'
4
+
5
+ module Spree
6
+ module Core
7
+ module ControllerHelpers
8
+ module Common
9
+ extend ActiveSupport::Concern
10
+ included do
11
+ helper_method :title
12
+ helper_method :title=
13
+ helper_method :accurate_title
14
+
15
+ layout :get_layout
16
+
17
+ before_action :set_user_language
18
+ end
19
+
20
+ protected
21
+
22
+ # can be used in views as well as controllers.
23
+ # e.g. <% self.title = 'This is a custom title for this view' %>
24
+ attr_writer :title
25
+
26
+ def title
27
+ title_string = @title.presence || accurate_title
28
+ if title_string.present?
29
+ if Spree::Config[:always_put_site_name_in_title]
30
+ [title_string, default_title].join(' - ')
31
+ else
32
+ title_string
33
+ end
34
+ else
35
+ default_title
36
+ end
37
+ end
38
+
39
+ def default_title
40
+ current_store.name
41
+ end
42
+
43
+ # this is a hook for subclasses to provide title
44
+ def accurate_title
45
+ current_store.seo_title
46
+ end
47
+
48
+ private
49
+
50
+ def set_user_language_locale_key
51
+ :locale
52
+ end
53
+
54
+ def set_user_language
55
+ available_locales = Spree.i18n_available_locales
56
+ locale = [
57
+ params[:locale],
58
+ session[set_user_language_locale_key],
59
+ (config_locale if respond_to?(:config_locale, true)),
60
+ I18n.default_locale
61
+ ].detect do |candidate|
62
+ candidate &&
63
+ available_locales.include?(candidate.to_sym)
64
+ end
65
+ session[set_user_language_locale_key] = locale
66
+ I18n.locale = locale
67
+ Carmen.i18n_backend.locale = locale
68
+ end
69
+
70
+ # Returns which layout to render.
71
+ #
72
+ # You can set the layout you want to render inside your Spree configuration with the +:layout+ option.
73
+ #
74
+ # Default layout is: +app/views/spree/layouts/spree_application+
75
+ #
76
+ def get_layout
77
+ Spree::Config[:layout]
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Core
5
+ module ControllerHelpers
6
+ module Order
7
+ extend ActiveSupport::Concern
8
+ include ControllerHelpers::Pricing
9
+
10
+ included do
11
+ helper_method :current_order
12
+ end
13
+
14
+ # The current incomplete order from the guest_token for use in cart and during checkout
15
+ def current_order(options = {})
16
+ should_create = options[:create_order_if_necessary] || false
17
+ should_build = options[:build_order_if_necessary] || should_create
18
+
19
+ return @current_order if @current_order
20
+
21
+ @current_order = find_order_by_token_or_user(lock: options[:lock])
22
+
23
+ if should_build && (@current_order.nil? || @current_order.completed?)
24
+ @current_order = Spree::Order.new(new_order_params)
25
+ @current_order.user ||= spree_current_user
26
+ # See issue https://github.com/spree/spree/issues/3346 for reasons why this line is here
27
+ @current_order.created_by ||= spree_current_user
28
+ @current_order.save! if should_create
29
+ end
30
+
31
+ if @current_order
32
+ @current_order.record_ip_address(ip_address)
33
+ @current_order
34
+ end
35
+ end
36
+
37
+ def associate_user
38
+ @order ||= current_order
39
+ if spree_current_user && @order && (@order.user.blank? || @order.email.blank?)
40
+ @order.associate_user!(spree_current_user)
41
+ end
42
+ end
43
+
44
+ def set_current_order
45
+ if spree_current_user && current_order
46
+ spree_current_user.orders.by_store(current_store).incomplete.where('id != ?', current_order.id).find_each do |order|
47
+ current_order.merge!(order, spree_current_user)
48
+ end
49
+ end
50
+ end
51
+
52
+ def ip_address
53
+ request.remote_ip
54
+ end
55
+
56
+ private
57
+
58
+ def last_incomplete_order
59
+ @last_incomplete_order ||= spree_current_user.last_incomplete_spree_order(store: current_store)
60
+ end
61
+
62
+ def current_order_params
63
+ { currency: current_pricing_options.currency, guest_token: cookies.signed[:guest_token], store_id: current_store.id, user_id: spree_current_user.try(:id) }
64
+ end
65
+
66
+ def new_order_params
67
+ current_order_params.merge(last_ip_address: ip_address)
68
+ end
69
+
70
+ def find_order_by_token_or_user(options = {})
71
+ should_lock = options[:lock] || false
72
+
73
+ # Find any incomplete orders for the guest_token
74
+ order = Spree::Order.incomplete.lock(should_lock).find_by(current_order_params)
75
+
76
+ # Find any incomplete orders for the current user
77
+ if order.nil? && spree_current_user
78
+ order = last_incomplete_order
79
+ end
80
+
81
+ order
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Core::ControllerHelpers::PaymentParameters
5
+ # This method handles the awkwardness of how the html forms are currently
6
+ # set up for frontend.
7
+ #
8
+ # This method expects a params hash in the format of:
9
+ #
10
+ # {
11
+ # payment_source: {
12
+ # # The keys here are spree_payment_method.id's
13
+ # '1' => {...source attributes for payment method 1...},
14
+ # '2' => {...source attributes for payment method 2...},
15
+ # },
16
+ # order: {
17
+ # # Note that only a single entry is expected/handled in this array
18
+ # payments_attributes: [
19
+ # {
20
+ # payment_method_id: '1',
21
+ # },
22
+ # ],
23
+ # ...other params...
24
+ # },
25
+ # ...other params...
26
+ # }
27
+ #
28
+ # And this method modifies the params into the format of:
29
+ #
30
+ # {
31
+ # order: {
32
+ # payments_attributes: [
33
+ # {
34
+ # payment_method_id: '1',
35
+ # source_attributes: {...source attributes for payment method 1...}
36
+ # },
37
+ # ],
38
+ # ...other params...
39
+ # },
40
+ # ...other params...
41
+ # }
42
+ #
43
+ def move_payment_source_into_payments_attributes(params)
44
+ # Step 1: Gather all the information and ensure all the pieces are there.
45
+
46
+ return params if params[:payment_source].blank?
47
+
48
+ payment_params = params[:order] &&
49
+ params[:order][:payments_attributes] &&
50
+ params[:order][:payments_attributes].first
51
+ return params if payment_params.blank?
52
+
53
+ payment_method_id = payment_params[:payment_method_id]
54
+ return params if payment_method_id.blank?
55
+
56
+ source_params = params[:payment_source][payment_method_id]
57
+ return params if source_params.blank?
58
+
59
+ # Step 2: Perform the modifications.
60
+
61
+ payment_params[:source_attributes] = source_params
62
+ params.delete(:payment_source)
63
+
64
+ params
65
+ end
66
+
67
+ # This method handles the awkwardness of how the html forms are currently
68
+ # set up for frontend.
69
+ #
70
+ # This method expects a params hash in the format of:
71
+ #
72
+ # {
73
+ # order: {
74
+ # wallet_payment_source_id: '123',
75
+ # ...other params...
76
+ # },
77
+ # cvc_confirm: '456', # optional
78
+ # ...other params...
79
+ # }
80
+ #
81
+ # And this method modifies the params into the format of:
82
+ #
83
+ # {
84
+ # order: {
85
+ # payments_attributes: [
86
+ # {
87
+ # source_attributes: {
88
+ # wallet_payment_source_id: '123',
89
+ # verification_value: '456',
90
+ # },
91
+ # },
92
+ # ]
93
+ # ...other params...
94
+ # },
95
+ # ...other params...
96
+ # }
97
+ #
98
+ def move_wallet_payment_source_id_into_payments_attributes(params)
99
+ return params if params[:order].blank?
100
+
101
+ wallet_payment_source_id = params[:order][:wallet_payment_source_id].presence
102
+ cvc_confirm = params[:cvc_confirm].presence
103
+
104
+ return params if wallet_payment_source_id.nil?
105
+
106
+ params[:order][:payments_attributes] = [
107
+ {
108
+ source_attributes: {
109
+ wallet_payment_source_id:,
110
+ verification_value: cvc_confirm
111
+ }
112
+ }
113
+ ]
114
+
115
+ params[:order].delete(:wallet_payment_source_id)
116
+ params.delete(:cvc_confirm)
117
+
118
+ params
119
+ end
120
+
121
+ # This is a strange thing to do since an order can have multiple payments
122
+ # but we always assume that it only has a single payment and that its
123
+ # amount should be the current order total after store credit is applied.
124
+ # We should reconsider this method and its usage at some point.
125
+ #
126
+ # This method expects a params hash in the format of:
127
+ #
128
+ # {
129
+ # order: {
130
+ # # Note that only a single entry is expected/handled in this array
131
+ # payments_attributes: [
132
+ # {
133
+ # ...params...
134
+ # },
135
+ # ],
136
+ # ...other params...
137
+ # },
138
+ # ...other params...
139
+ # }
140
+ #
141
+ # And this method modifies the params into the format of:
142
+ #
143
+ # {
144
+ # order: {
145
+ # payments_attributes: [
146
+ # {
147
+ # ...params...
148
+ # amount: <the order total after store credit>,
149
+ # },
150
+ # ],
151
+ # ...other params...
152
+ # },
153
+ # ...other params...
154
+ # }
155
+ #
156
+ def set_payment_parameters_amount(params, order)
157
+ return params if params[:order].blank?
158
+ return params if params[:order][:payments_attributes].blank?
159
+
160
+ params[:order][:payments_attributes].first[:amount] = order.order_total_after_store_credit
161
+
162
+ params
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Core
5
+ module ControllerHelpers
6
+ module Pricing
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ helper_method :current_pricing_options
11
+ end
12
+
13
+ def current_pricing_options
14
+ Spree::Config.pricing_options_class.from_context(self)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Core
5
+ module ControllerHelpers
6
+ module Search
7
+ def build_searcher(params)
8
+ Spree::Config.searcher_class.new(params).tap do |searcher|
9
+ searcher.current_user = spree_current_user
10
+ searcher.pricing_options = current_pricing_options
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Core
5
+ module ControllerHelpers
6
+ module Store
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ helper_method :current_store
11
+ end
12
+
13
+ def current_store
14
+ @current_store ||= Spree::Config.current_store_selector_class.new(request).store
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Core
5
+ module ControllerHelpers
6
+ module StrongParameters
7
+ def permitted_attributes
8
+ Spree::PermittedAttributes
9
+ end
10
+
11
+ delegate(*Spree::PermittedAttributes::ATTRIBUTES,
12
+ to: :permitted_attributes,
13
+ prefix: :permitted)
14
+
15
+ def permitted_credit_card_update_attributes
16
+ permitted_attributes.credit_card_update_attributes + [
17
+ address_attributes: permitted_address_attributes
18
+ ]
19
+ end
20
+
21
+ def permitted_payment_attributes
22
+ permitted_attributes.payment_attributes + [
23
+ source_attributes: permitted_source_attributes
24
+ ]
25
+ end
26
+
27
+ def permitted_source_attributes
28
+ permitted_attributes.source_attributes + [
29
+ address_attributes: permitted_address_attributes
30
+ ]
31
+ end
32
+
33
+ def permitted_checkout_address_attributes
34
+ permitted_attributes.checkout_address_attributes
35
+ end
36
+
37
+ def permitted_checkout_delivery_attributes
38
+ permitted_attributes.checkout_delivery_attributes
39
+ end
40
+
41
+ def permitted_checkout_payment_attributes
42
+ permitted_attributes.checkout_payment_attributes
43
+ end
44
+
45
+ def permitted_checkout_confirm_attributes
46
+ permitted_attributes.checkout_confirm_attributes
47
+ end
48
+
49
+ def permitted_order_attributes
50
+ permitted_checkout_address_attributes +
51
+ permitted_checkout_delivery_attributes +
52
+ permitted_checkout_payment_attributes +
53
+ permitted_attributes.customer_metadata_attributes +
54
+ permitted_checkout_confirm_attributes + [
55
+ line_items_attributes: permitted_line_item_attributes
56
+ ]
57
+ end
58
+
59
+ def permitted_product_attributes
60
+ permitted_attributes.product_attributes + [
61
+ product_properties_attributes: permitted_product_properties_attributes
62
+ ]
63
+ end
64
+
65
+ def permitted_user_attributes
66
+ permitted_attributes.user_attributes + [
67
+ bill_address_attributes: permitted_address_attributes,
68
+ ship_address_attributes: permitted_address_attributes
69
+ ]
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Metadata
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ attribute :customer_metadata, :json, default: {}
9
+ attribute :admin_metadata, :json, default: {}
10
+
11
+ validate :validate_metadata_limits, if: :validate_metadata_enabled?
12
+ end
13
+
14
+ class_methods do
15
+ def meta_data_columns
16
+ %i[customer_metadata admin_metadata]
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def validate_metadata_enabled?
23
+ Spree::Config.meta_data_validation_enabled
24
+ end
25
+
26
+ def validate_metadata_limits
27
+ self.class.meta_data_columns.each { |column| validate_metadata_column(column) }
28
+ end
29
+
30
+ def validate_metadata_column(column)
31
+ config = Spree::Config
32
+ metadata = send(column)
33
+
34
+ return if metadata.nil?
35
+
36
+ # Check for maximum number of keys
37
+ validate_metadata_keys_count(metadata, column, config.meta_data_max_keys)
38
+
39
+ # Check for maximum key and value size
40
+ metadata.each do |key, value|
41
+ validate_metadata_key(key, column, config.meta_data_max_key_length)
42
+ validate_metadata_value(key, value, column, config.meta_data_max_value_length)
43
+ end
44
+ end
45
+
46
+ def validate_metadata_keys_count(metadata, column, max_keys)
47
+ return unless metadata.keys.count > max_keys
48
+
49
+ errors.add(column, "must not have more than #{max_keys} keys")
50
+ end
51
+
52
+ def validate_metadata_key(key, column, max_key_length)
53
+ return unless key.to_s.length > max_key_length
54
+
55
+ errors.add(column, "key '#{key}' exceeds #{max_key_length} characters")
56
+ end
57
+
58
+ def validate_metadata_value(key, value, column, max_value_length)
59
+ return unless value.to_s.length > max_value_length
60
+
61
+ errors.add(column, "value for key '#{key}' exceeds #{max_value_length} characters")
62
+ end
63
+ end
64
+ end
@@ -5,7 +5,7 @@ module Spree
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
8
- has_many :user_addresses, -> { active }, foreign_key: "user_id", class_name: "Spree::UserAddress" do
8
+ has_many :user_addresses, foreign_key: "user_id", class_name: "Spree::UserAddress" do
9
9
  def find_first_by_address_values(address_attrs)
10
10
  detect { |ua| ua.address == Spree::Address.new(address_attrs) }
11
11
  end
@@ -22,7 +22,7 @@ module Spree
22
22
  end
23
23
 
24
24
  if user_address.persisted?
25
- user_address.update!(column_for_default => true, archived: false)
25
+ user_address.update!(column_for_default => true)
26
26
  else
27
27
  user_address.write_attribute(column_for_default, true)
28
28
  end
@@ -151,7 +151,7 @@ module Spree
151
151
  user_address = user_addresses.find_by(address_id:)
152
152
  if user_address
153
153
  remove_user_address_reference(address_id)
154
- user_address.update(archived: true, default: false)
154
+ user_address.destroy!
155
155
  else
156
156
  false
157
157
  end
@@ -160,10 +160,9 @@ module Spree
160
160
  private
161
161
 
162
162
  def prepare_user_address(new_address)
163
- user_address = user_addresses.all_historical.find_first_by_address_values(new_address.attributes)
163
+ user_address = user_addresses.find_first_by_address_values(new_address.attributes)
164
164
  user_address ||= user_addresses.build
165
165
  user_address.address = new_address
166
- user_address.archived = false
167
166
  user_address
168
167
  end
169
168
 
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Core
5
+ class StateMachines
6
+ # Inventory Units' state machine
7
+ #
8
+ # for each event the following instance methods are dynamically implemented:
9
+ # #<event_name>
10
+ # #<event_name>!
11
+ # #can_<event_name>?
12
+ #
13
+ # for each state the following instance methods are implemented:
14
+ # #<state_name>?
15
+ #
16
+ module InventoryUnit
17
+ extend ActiveSupport::Concern
18
+
19
+ included do
20
+ state_machine initial: :on_hand do
21
+ event :fill_backorder do
22
+ transition to: :on_hand, from: :backordered
23
+ end
24
+ after_transition on: :fill_backorder, do: :fulfill_order
25
+
26
+ event :ship do
27
+ transition to: :shipped, if: :allow_ship?
28
+ end
29
+
30
+ event :return do
31
+ transition to: :returned, from: :shipped
32
+ end
33
+
34
+ event :cancel do
35
+ transition to: :canceled, from: ::Spree::InventoryUnit::CANCELABLE_STATES.map(&:to_sym)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end