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
@@ -0,0 +1,217 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Core
5
+ class StateMachines
6
+ module Order
7
+ module ClassMethods
8
+ attr_accessor :previous_states
9
+ attr_writer :next_event_transitions, :checkout_steps, :removed_transitions
10
+
11
+ def checkout_flow(&block)
12
+ if block_given?
13
+ @checkout_flow = block
14
+ define_state_machine!
15
+ else
16
+ @checkout_flow
17
+ end
18
+ end
19
+
20
+ def define_state_machine!
21
+ self.checkout_steps = {}
22
+ self.next_event_transitions = []
23
+ self.previous_states = [:cart]
24
+ self.removed_transitions = []
25
+
26
+ # Build the checkout flow using the checkout_flow defined either
27
+ # within the Order class, or a decorator for that class.
28
+ #
29
+ # This method may be called multiple times depending on if the
30
+ # checkout_flow is re-defined in a decorator or not.
31
+ instance_eval(&checkout_flow)
32
+
33
+ klass = self
34
+
35
+ # To avoid multiple occurrences of the same transition being defined
36
+ # On first definition, state_machines will not be defined
37
+ state_machines.clear if respond_to?(:state_machines)
38
+ state_machine :state, initial: :cart, use_transactions: false do
39
+ klass.next_event_transitions.each { |state| transition(state.merge(on: :next)) }
40
+
41
+ # Persist the state on the order
42
+ after_transition do |order, transition|
43
+ # Hard to say if this is really necessary, it was introduced in this commit:
44
+ # https://github.com/mamhoff/solidus/commit/fa1d66c42e4c04ee7cd1c20d87e4cdb74a226d3d
45
+ # But it seems to be harmless, so we'll keep it for now.
46
+ order.state = order.state # rubocop:disable Lint/SelfAssignment
47
+
48
+ order.state_changes.create(
49
+ previous_state: transition.from,
50
+ next_state: transition.to,
51
+ name: 'order',
52
+ user_id: order.user_id
53
+ )
54
+ order.save
55
+ end
56
+
57
+ event :cancel do
58
+ transition to: :canceled, if: :allow_cancel?, from: :complete
59
+ end
60
+
61
+ event :return do
62
+ transition to: :returned, from: [:complete, :awaiting_return], if: :all_inventory_units_returned?
63
+ end
64
+
65
+ event :resume do
66
+ transition to: :resumed, from: :canceled, if: :canceled?
67
+ end
68
+
69
+ event :authorize_return do
70
+ transition to: :awaiting_return, from: :complete
71
+ end
72
+
73
+ event :complete do
74
+ transition to: :complete, from: klass.checkout_steps.keys.last
75
+ end
76
+
77
+ if states[:payment]
78
+ event :payment_failed do
79
+ transition to: :payment, from: :confirm
80
+ end
81
+
82
+ after_transition to: :complete, do: :add_payment_sources_to_wallet
83
+ before_transition to: :payment, do: :add_default_payment_from_wallet
84
+ before_transition to: :payment, do: :ensure_billing_address
85
+
86
+ before_transition to: :confirm, do: :add_store_credit_payments
87
+
88
+ # see also process_payments_before_complete below which needs to
89
+ # be added in the correct sequence.
90
+ end
91
+
92
+ before_transition from: :cart, do: :ensure_line_items_present
93
+
94
+ if states[:address]
95
+ before_transition to: :address, do: :assign_default_user_addresses
96
+ before_transition from: :address, do: :persist_user_address!
97
+ end
98
+
99
+ if states[:delivery]
100
+ before_transition to: :delivery, do: :ensure_shipping_address
101
+ before_transition to: :delivery, do: :create_proposed_shipments
102
+ before_transition to: :delivery, do: :ensure_available_shipping_rates
103
+ end
104
+
105
+ before_transition to: :resumed, do: :ensure_line_item_variants_are_not_deleted
106
+ before_transition to: :resumed, do: :validate_line_item_availability
107
+
108
+ # Sequence of before_transition to: :complete
109
+ # calls matter so that we do not process payments
110
+ # until validations have passed
111
+ before_transition to: :complete, do: :validate_line_item_availability
112
+ before_transition to: :complete, do: :ensure_promotions_eligible
113
+ before_transition to: :complete, do: :ensure_line_item_variants_are_not_deleted
114
+ before_transition to: :complete, do: :ensure_inventory_units
115
+ if states[:payment]
116
+ before_transition to: :complete, do: :process_payments_before_complete
117
+ end
118
+
119
+ after_transition to: :complete, do: :finalize
120
+ after_transition to: :resumed, do: :after_resume
121
+ after_transition to: :canceled, do: :after_cancel
122
+
123
+ after_transition from: any - :cart, to: any - [:confirm, :complete] do |order|
124
+ order.recalculate
125
+ end
126
+
127
+ after_transition do |order, transition|
128
+ order.logger.debug "Order #{order.number} transitioned from #{transition.from} to #{transition.to} via #{transition.event}"
129
+ end
130
+
131
+ after_failure do |order, transition|
132
+ order.logger.debug "Order #{order.number} halted transition on event #{transition.event} state #{transition.from}: #{order.errors.full_messages.join}"
133
+ end
134
+ end
135
+ end
136
+
137
+ def go_to_state(name, options = {})
138
+ checkout_steps[name] = options
139
+ previous_states.each do |state|
140
+ add_transition({ from: state, to: name }.merge(options))
141
+ end
142
+ if options[:if]
143
+ previous_states << name
144
+ else
145
+ self.previous_states = [name]
146
+ end
147
+ end
148
+
149
+ def insert_checkout_step(name, options = {})
150
+ before = options.delete(:before)
151
+ after = options.delete(:after) unless before
152
+ after = checkout_steps.keys.last unless before || after
153
+
154
+ cloned_steps = checkout_steps.clone
155
+ cloned_removed_transitions = removed_transitions.clone
156
+ checkout_flow do
157
+ cloned_steps.each_pair do |key, value|
158
+ go_to_state(name, options) if key == before
159
+ go_to_state(key, value)
160
+ go_to_state(name, options) if key == after
161
+ end
162
+ cloned_removed_transitions.each do |transition|
163
+ remove_transition(transition)
164
+ end
165
+ end
166
+ end
167
+
168
+ def remove_checkout_step(name)
169
+ cloned_steps = checkout_steps.clone
170
+ cloned_removed_transitions = removed_transitions.clone
171
+ checkout_flow do
172
+ cloned_steps.each_pair do |key, value|
173
+ go_to_state(key, value) unless key == name
174
+ end
175
+ cloned_removed_transitions.each do |transition|
176
+ remove_transition(transition)
177
+ end
178
+ end
179
+ end
180
+
181
+ def remove_transition(options = {})
182
+ removed_transitions << options
183
+ next_event_transitions.delete(find_transition(options))
184
+ end
185
+
186
+ def find_transition(options = {})
187
+ return nil if options.nil? || !options.include?(:from) || !options.include?(:to)
188
+
189
+ next_event_transitions.detect do |transition|
190
+ transition[options[:from].to_sym] == options[:to].to_sym
191
+ end
192
+ end
193
+
194
+ def next_event_transitions
195
+ @next_event_transitions ||= []
196
+ end
197
+
198
+ def checkout_steps
199
+ @checkout_steps ||= {}
200
+ end
201
+
202
+ def checkout_step_names
203
+ checkout_steps.keys
204
+ end
205
+
206
+ def add_transition(options)
207
+ next_event_transitions << { options.delete(:from) => options.delete(:to) }.merge(options)
208
+ end
209
+
210
+ def removed_transitions
211
+ @removed_transitions ||= []
212
+ end
213
+ end
214
+ end
215
+ end
216
+ end
217
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Core
5
+ class StateMachines
6
+ module Order
7
+ def self.included(klass)
8
+ klass.extend ClassMethods
9
+ end
10
+
11
+ def checkout_steps
12
+ steps = self.class.checkout_steps.each_with_object([]) { |(step, options), checkout_steps|
13
+ next if options.include?(:if) && !options[:if].call(self)
14
+
15
+ checkout_steps << step
16
+ }.map(&:to_s)
17
+ # Ensure there is always a complete step
18
+ steps << "complete" unless steps.include?("complete")
19
+ steps
20
+ end
21
+
22
+ def has_checkout_step?(step)
23
+ step.present? && checkout_steps.include?(step)
24
+ end
25
+
26
+ def passed_checkout_step?(step)
27
+ has_checkout_step?(step) && checkout_step_index(step) < checkout_step_index(state)
28
+ end
29
+
30
+ def checkout_step_index(step)
31
+ checkout_steps.index(step).to_i
32
+ end
33
+
34
+ def can_go_to_state?(state)
35
+ return false unless has_checkout_step?(self.state) && has_checkout_step?(state)
36
+
37
+ checkout_step_index(state) > checkout_step_index(self.state)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Core
5
+ class StateMachines
6
+ # Payments' 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 Payment
17
+ extend ActiveSupport::Concern
18
+
19
+ included do
20
+ state_machine initial: :checkout do
21
+ # With card payments, happens before purchase or authorization happens
22
+ #
23
+ # Setting it after creating a profile and authorizing a full amount will
24
+ # prevent the payment from being authorized again once Order transitions
25
+ # to complete
26
+ event :started_processing do
27
+ transition from: [:checkout, :pending, :completed, :processing], to: :processing
28
+ end
29
+ # When processing during checkout fails
30
+ event :failure do
31
+ transition from: [:pending, :processing], to: :failed
32
+ end
33
+ # With card payments this represents authorizing the payment
34
+ event :pend do
35
+ transition from: [:checkout, :processing], to: :pending
36
+ end
37
+ # With card payments this represents completing a purchase or capture transaction
38
+ event :complete do
39
+ transition from: [:processing, :pending, :checkout], to: :completed
40
+ end
41
+ event :void do
42
+ transition from: [:pending, :processing, :completed, :checkout], to: :void
43
+ end
44
+ # when the card brand isnt supported
45
+ event :invalidate do
46
+ transition from: [:checkout], to: :invalid
47
+ end
48
+
49
+ after_transition do |payment, transition|
50
+ payment.state_changes.create!(
51
+ previous_state: transition.from,
52
+ next_state: transition.to,
53
+ name: 'payment'
54
+ )
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Core
5
+ class StateMachines
6
+ # Reimbursement' 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 Reimbursement
17
+ extend ActiveSupport::Concern
18
+
19
+ included do
20
+ state_machine :reimbursement_status, initial: :pending do
21
+ event :errored do
22
+ transition to: :errored, from: [:pending, :errored]
23
+ end
24
+
25
+ event :reimbursed do
26
+ transition to: :reimbursed, from: [:pending, :errored]
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Core
5
+ class StateMachines
6
+ # Return Authorizations' 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 ReturnAuthorization
17
+ extend ActiveSupport::Concern
18
+
19
+ included do
20
+ state_machine initial: :authorized do
21
+ before_transition to: :canceled, do: :cancel_return_items
22
+
23
+ event :cancel do
24
+ transition to: :canceled, from: :authorized,
25
+ if: lambda { |return_authorization| return_authorization.can_cancel_return_items? }
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Core
5
+ class StateMachines
6
+ module ReturnItem
7
+ # Return Items' acceptance status state machine
8
+ #
9
+ # for each event the following instance methods are dynamically implemented:
10
+ # #<event_name>
11
+ # #<event_name>!
12
+ # #can_<event_name>?
13
+ #
14
+ # for each state the following instance methods are implemented:
15
+ # #<state_name>?
16
+ #
17
+ module AcceptanceStatus
18
+ extend ActiveSupport::Concern
19
+
20
+ included do
21
+ state_machine :acceptance_status, initial: :pending do
22
+ event :attempt_accept do
23
+ transition to: :accepted, from: :accepted
24
+ transition to: :accepted, from: :pending, if: ->(return_item) { return_item.eligible_for_return? }
25
+ transition to: :manual_intervention_required, from: :pending, if: ->(return_item) { return_item.requires_manual_intervention? }
26
+ transition to: :rejected, from: :pending
27
+ end
28
+
29
+ # bypasses eligibility checks
30
+ event :accept do
31
+ transition to: :accepted, from: [:accepted, :pending, :manual_intervention_required]
32
+ end
33
+
34
+ # bypasses eligibility checks
35
+ event :reject do
36
+ transition to: :rejected, from: [:accepted, :pending, :manual_intervention_required]
37
+ end
38
+
39
+ # bypasses eligibility checks
40
+ event :require_manual_intervention do
41
+ transition to: :manual_intervention_required, from: [:accepted, :pending, :manual_intervention_required]
42
+ end
43
+
44
+ after_transition any => any, do: :persist_acceptance_status_errors
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Core
5
+ class StateMachines
6
+ module ReturnItem
7
+ # Return Items' reception status state machine
8
+ #
9
+ # for each event the following instance methods are dynamically implemented:
10
+ # #<event_name>
11
+ # #<event_name>!
12
+ # #can_<event_name>?
13
+ #
14
+ # for each state the following instance methods are implemented:
15
+ # #<state_name>?
16
+ #
17
+ module ReceptionStatus
18
+ extend ActiveSupport::Concern
19
+
20
+ included do
21
+ state_machine :reception_status, initial: :awaiting do
22
+ after_transition to: ::Spree::ReturnItem::COMPLETED_RECEPTION_STATUSES, do: :attempt_accept, if: :can_attempt_accept?
23
+ after_transition to: ::Spree::ReturnItem::COMPLETED_RECEPTION_STATUSES, do: :check_unexchange
24
+ after_transition to: :received, do: :process_inventory_unit!
25
+
26
+ event(:cancel) { transition to: :cancelled, from: :awaiting }
27
+
28
+ event(:receive) { transition to: :received, from: ::Spree::ReturnItem::INTERMEDIATE_RECEPTION_STATUSES + [:awaiting] }
29
+ event(:unexchange) { transition to: :unexchanged, from: [:awaiting] }
30
+ event(:give) { transition to: :given_to_customer, from: :awaiting }
31
+ event(:lost) { transition to: :lost_in_transit, from: :awaiting }
32
+ event(:wrong_item_shipped) { transition to: :shipped_wrong_item, from: :awaiting }
33
+ event(:short_shipped) { transition to: :short_shipped, from: :awaiting }
34
+ event(:in_transit) { transition to: :in_transit, from: :awaiting }
35
+ event(:expired) { transition to: :expired, from: :awaiting }
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Core
5
+ class StateMachines
6
+ # Shipments' 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 Shipment
17
+ extend ActiveSupport::Concern
18
+
19
+ included do
20
+ state_machine initial: :pending, use_transactions: false do
21
+ event :ready do
22
+ transition from: :pending, to: :shipped, if: :can_transition_from_pending_to_shipped?
23
+ transition from: :pending, to: :ready, if: :can_transition_from_pending_to_ready?
24
+ end
25
+
26
+ event :pend do
27
+ transition from: :ready, to: :pending
28
+ end
29
+
30
+ event :ship do
31
+ transition from: [:ready, :canceled], to: :shipped
32
+ end
33
+ after_transition to: :shipped, do: :after_ship
34
+
35
+ event :cancel do
36
+ transition to: :canceled, from: [:pending, :ready]
37
+ end
38
+ after_transition to: :canceled, do: :after_cancel
39
+
40
+ event :resume do
41
+ transition from: :canceled, to: :ready, if: :can_transition_from_canceled_to_ready?
42
+ transition from: :canceled, to: :pending
43
+ end
44
+ after_transition from: :canceled, to: [:pending, :ready, :shipped], do: :after_resume
45
+
46
+ after_transition do |shipment, transition|
47
+ shipment.state_changes.create!(
48
+ previous_state: transition.from,
49
+ next_state: transition.to,
50
+ name: 'shipment'
51
+ )
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Spree
4
4
  class CustomerReturn < Spree::Base
5
+ include Metadata
6
+
5
7
  belongs_to :stock_location, optional: true
6
8
 
7
9
  has_many :return_items, inverse_of: :customer_return
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Spree::ItemTotal
4
+ def initialize(item)
5
+ @item = item
6
+ end
7
+
8
+ def recalculate!
9
+ tax_adjustments = item.adjustments.select do |adjustment|
10
+ adjustment.tax? && !adjustment.marked_for_destruction?
11
+ end
12
+
13
+ # Included tax adjustments are those which are included in the price.
14
+ # These ones should not affect the eventual total price.
15
+ #
16
+ # Additional tax adjustments are the opposite, affecting the final total.
17
+ item.included_tax_total = tax_adjustments.select(&:included?).sum(&:amount)
18
+ item.additional_tax_total = tax_adjustments.reject(&:included?).sum(&:amount)
19
+
20
+ item.adjustment_total = item.adjustments.reject { |adjustment|
21
+ adjustment.marked_for_destruction? || adjustment.included?
22
+ }.sum(&:amount)
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :item
28
+ end
@@ -7,6 +7,7 @@ module Spree
7
7
  # spree_auth_devise)
8
8
  class LegacyUser < Spree::Base
9
9
  include UserMethods
10
+ include Metadata
10
11
 
11
12
  self.table_name = 'spree_users'
12
13
 
@@ -10,6 +10,8 @@ module Spree
10
10
  # promotion system.
11
11
  #
12
12
  class LineItem < Spree::Base
13
+ include Metadata
14
+
13
15
  belongs_to :order, class_name: "Spree::Order", inverse_of: :line_items, touch: true, optional: true
14
16
  belongs_to :variant, -> { with_discarded }, class_name: "Spree::Variant", inverse_of: :line_items, optional: true
15
17
  belongs_to :tax_category, class_name: "Spree::TaxCategory", optional: true
@@ -36,6 +38,7 @@ module Spree
36
38
  before_destroy :destroy_inventory_units
37
39
 
38
40
  delegate :name, :description, :sku, :should_track_inventory?, to: :variant
41
+ delegate :tax_category, :tax_category_id, to: :variant, prefix: true
39
42
  delegate :currency, to: :order, allow_nil: true
40
43
 
41
44
  attr_accessor :target_shipment, :price_currency
@@ -128,6 +131,24 @@ module Spree
128
131
  Spree::Config.pricing_options_class.from_line_item(self)
129
132
  end
130
133
 
134
+ # @return [Spree::TaxCategory] the variant's tax category
135
+ #
136
+ # This returns the variant's tax category if the tax category ID on the line_item is nil. It looks
137
+ # like an association, but really is an override.
138
+ #
139
+ def tax_category
140
+ super || variant_tax_category
141
+ end
142
+
143
+ # @return [Integer] the variant's tax category ID
144
+ #
145
+ # This returns the variant's tax category ID if the tax category ID on the line_id is nil. It looks
146
+ # like an association, but really is an override.
147
+ #
148
+ def tax_category_id
149
+ super || variant_tax_category_id
150
+ end
151
+
131
152
  private
132
153
 
133
154
  # Sets the quantity to zero if it is nil or less than zero.