solidus_core 4.4.1 → 4.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) 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_shipping.rb +0 -1
  29. data/app/models/spree/order_taxation.rb +1 -0
  30. data/app/models/spree/order_updater.rb +13 -30
  31. data/app/models/spree/payment.rb +1 -0
  32. data/app/models/spree/permission_sets/base.rb +45 -0
  33. data/app/models/spree/permission_sets/configuration_display.rb +53 -0
  34. data/app/models/spree/permission_sets/configuration_management.rb +52 -0
  35. data/app/models/spree/permission_sets/dashboard_display.rb +28 -0
  36. data/app/models/spree/permission_sets/default_customer.rb +83 -0
  37. data/app/models/spree/permission_sets/order_display.rb +50 -0
  38. data/app/models/spree/permission_sets/order_management.rb +50 -0
  39. data/app/models/spree/permission_sets/product_display.rb +43 -0
  40. data/app/models/spree/permission_sets/product_management.rb +47 -0
  41. data/app/models/spree/permission_sets/restricted_stock_display.rb +33 -0
  42. data/app/models/spree/permission_sets/restricted_stock_management.rb +33 -0
  43. data/app/models/spree/permission_sets/stock_display.rb +26 -0
  44. data/app/models/spree/permission_sets/stock_management.rb +26 -0
  45. data/app/models/spree/permission_sets/super_user.rb +26 -0
  46. data/app/models/spree/permission_sets/user_display.rb +27 -0
  47. data/app/models/spree/permission_sets/user_management.rb +44 -0
  48. data/app/models/spree/product.rb +7 -0
  49. data/app/models/spree/refund.rb +2 -0
  50. data/app/models/spree/return_authorization.rb +2 -0
  51. data/app/models/spree/shipment.rb +2 -0
  52. data/app/models/spree/simple_order_contents.rb +4 -1
  53. data/app/models/spree/store_credit_event.rb +1 -0
  54. data/app/models/spree/tax/tax_helpers.rb +12 -1
  55. data/app/models/spree/tax_calculator/default.rb +1 -1
  56. data/app/models/spree/taxon.rb +22 -2
  57. data/app/models/spree/taxon_brand_selector.rb +22 -0
  58. data/app/models/spree/unauthorized_redirect_handler.rb +24 -0
  59. data/app/models/spree/user_address.rb +9 -3
  60. data/app/models/spree/variant.rb +14 -1
  61. data/config/locales/en.yml +16 -0
  62. data/db/migrate/20220419170826_remove_archived_user_addresses.rb +12 -0
  63. data/db/migrate/20250129061658_add_metadata_to_spree_resources.rb +29 -0
  64. data/db/migrate/20250201172950_add_gtin_and_condition_to_spree_variant.rb +6 -0
  65. data/db/migrate/20250207104016_add_primary_taxon_to_products.rb +7 -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 +4 -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/extension_rake.rb +2 -2
  116. data/lib/spree/testing_support/factories/order_factory.rb +9 -1
  117. data/lib/spree/user_class_handle.rb +2 -2
  118. data/solidus_core.gemspec +1 -1
  119. metadata +64 -24
  120. 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.