solidus_core 2.2.2 → 2.3.0.beta1

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 (175) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -7
  3. data/app/assets/javascripts/spree.js.erb +2 -2
  4. data/app/helpers/spree/base_helper.rb +3 -4
  5. data/app/models/spree/address.rb +1 -1
  6. data/app/models/spree/adjustment.rb +3 -1
  7. data/app/models/spree/app_configuration.rb +43 -0
  8. data/app/models/spree/billing_integration.rb +2 -2
  9. data/app/models/spree/calculator/default_tax.rb +3 -1
  10. data/app/models/spree/calculator/distributed_amount.rb +24 -0
  11. data/app/models/spree/calculator/free_shipping.rb +0 -1
  12. data/app/models/spree/calculator/tiered_flat_rate.rb +17 -3
  13. data/app/models/spree/calculator/tiered_percent.rb +18 -3
  14. data/app/models/spree/distributed_amounts_handler.rb +43 -0
  15. data/app/models/spree/gateway/bogus.rb +7 -83
  16. data/app/models/spree/gateway/bogus_simple.rb +7 -20
  17. data/app/models/spree/gateway.rb +8 -58
  18. data/app/models/spree/image.rb +1 -1
  19. data/app/models/spree/line_item.rb +1 -1
  20. data/app/models/spree/option_value.rb +1 -1
  21. data/app/models/spree/order/checkout.rb +1 -4
  22. data/app/models/spree/order/number_generator.rb +43 -0
  23. data/app/models/spree/order.rb +33 -38
  24. data/app/models/spree/order_contents.rb +1 -1
  25. data/app/models/spree/order_taxation.rb +79 -0
  26. data/app/models/spree/order_update_attributes.rb +0 -2
  27. data/app/models/spree/order_updater.rb +55 -33
  28. data/app/models/spree/payment.rb +0 -1
  29. data/app/models/spree/payment_method/bogus_credit_card.rb +87 -0
  30. data/app/models/spree/payment_method/check.rb +14 -6
  31. data/app/models/spree/payment_method/credit_card.rb +41 -0
  32. data/app/models/spree/payment_method/simple_bogus_credit_card.rb +24 -0
  33. data/app/models/spree/payment_method/store_credit.rb +5 -13
  34. data/app/models/spree/payment_method.rb +126 -40
  35. data/app/models/spree/preferences/preferable.rb +5 -1
  36. data/app/models/spree/preferences/store.rb +2 -2
  37. data/app/models/spree/product/scopes.rb +14 -1
  38. data/app/models/spree/product.rb +10 -4
  39. data/app/models/spree/promotion_action.rb +4 -0
  40. data/app/models/spree/promotion_code/batch_builder.rb +3 -2
  41. data/app/models/spree/promotion_rule.rb +4 -0
  42. data/app/models/spree/role.rb +2 -0
  43. data/app/models/spree/role_user.rb +2 -0
  44. data/app/models/spree/shipment.rb +4 -2
  45. data/app/models/spree/shipping_method.rb +3 -1
  46. data/app/models/spree/shipping_rate.rb +1 -1
  47. data/app/models/spree/state.rb +10 -2
  48. data/app/models/spree/stock_item.rb +3 -3
  49. data/app/models/spree/store.rb +5 -0
  50. data/app/models/spree/store_credit.rb +2 -2
  51. data/app/models/spree/store_credit_event.rb +1 -1
  52. data/app/models/spree/store_selector/by_server_name.rb +30 -0
  53. data/app/models/spree/store_selector/legacy.rb +48 -0
  54. data/app/models/spree/tax/item_tax.rb +20 -0
  55. data/app/models/spree/tax/order_adjuster.rb +2 -14
  56. data/app/models/spree/tax/order_tax.rb +18 -0
  57. data/app/models/spree/tax/shipping_rate_taxer.rb +4 -13
  58. data/app/models/spree/tax/tax_helpers.rb +5 -3
  59. data/app/models/spree/tax_calculator/default.rb +83 -0
  60. data/app/models/spree/tax_calculator/shipping_rate.rb +46 -0
  61. data/app/models/spree/tax_category.rb +9 -1
  62. data/app/models/spree/tax_rate.rb +31 -7
  63. data/app/models/spree/tax_rate_tax_category.rb +6 -0
  64. data/app/models/spree/taxon.rb +1 -1
  65. data/app/models/spree/variant.rb +1 -1
  66. data/app/views/spree/{shipment_mailer → carton_mailer}/shipped_email.html.erb +3 -3
  67. data/app/views/spree/order_mailer/cancel_email.html.erb +3 -3
  68. data/app/views/spree/order_mailer/confirm_email.html.erb +2 -2
  69. data/app/views/spree/order_mailer/inventory_cancellation_email.html.erb +26 -0
  70. data/app/views/spree/reimbursement_mailer/reimbursement_email.html.erb +2 -2
  71. data/app/views/spree/test_mailer/test_email.html.erb +2 -2
  72. data/config/locales/en.yml +66 -57
  73. data/db/default/spree/refund_reasons.rb +1 -0
  74. data/db/default/spree/shipping_categories.rb +1 -0
  75. data/db/default/spree/stock_locations.rb +2 -0
  76. data/db/default/spree/stores.rb +3 -4
  77. data/db/migrate/20170412103617_transform_tax_rate_category_relation.rb +48 -0
  78. data/db/migrate/20170422134804_add_roles_unique_constraints.rb +6 -0
  79. data/db/migrate/20170522143442_add_time_range_to_tax_rate.rb +6 -0
  80. data/db/migrate/20170608074534_rename_bogus_gateways.rb +13 -0
  81. data/lib/generators/spree/custom_user/custom_user_generator.rb +1 -1
  82. data/lib/generators/spree/dummy/dummy_generator.rb +10 -4
  83. data/lib/generators/spree/dummy/templates/rails/database.yml +12 -12
  84. data/lib/generators/spree/install/install_generator.rb +5 -5
  85. data/lib/generators/spree/install/templates/config/initializers/{spree.rb → solidus.rb} +0 -0
  86. data/lib/solidus/migrations/rename_gateways.rb +39 -0
  87. data/lib/spree/core/controller_helpers/auth.rb +1 -1
  88. data/lib/spree/core/controller_helpers/order.rb +10 -5
  89. data/lib/spree/core/controller_helpers/store.rb +1 -9
  90. data/lib/spree/core/current_store.rb +6 -14
  91. data/lib/spree/core/engine.rb +4 -3
  92. data/lib/spree/core/importer/order.rb +4 -4
  93. data/lib/spree/core/version.rb +1 -1
  94. data/lib/spree/core.rb +0 -1
  95. data/lib/spree/localized_number.rb +2 -1
  96. data/lib/spree/permitted_attributes.rb +12 -6
  97. data/lib/spree/testing_support/capybara_ext.rb +0 -1
  98. data/lib/spree/testing_support/factories/adjustment_factory.rb +5 -1
  99. data/lib/spree/testing_support/factories/order_factory.rb +26 -24
  100. data/lib/spree/testing_support/factories/payment_factory.rb +4 -0
  101. data/lib/spree/testing_support/factories/payment_method_factory.rb +3 -3
  102. data/lib/spree/testing_support/factories/shipment_factory.rb +7 -3
  103. data/lib/spree/testing_support/factories/tax_rate_factory.rb +1 -1
  104. data/lib/spree/testing_support/factories/variant_factory.rb +3 -1
  105. data/lib/tasks/migrations/copy_order_bill_address_to_credit_card.rake +0 -4
  106. data/lib/tasks/migrations/migrate_user_addresses.rake +2 -2
  107. data/lib/tasks/migrations/rename_gateways.rake +19 -0
  108. data/solidus_core.gemspec +2 -3
  109. data/spec/lib/spree/core/controller_helpers/order_spec.rb +32 -6
  110. data/spec/lib/spree/core/controller_helpers/payment_parameters_spec.rb +0 -1
  111. data/spec/lib/spree/core/current_store_spec.rb +6 -11
  112. data/spec/lib/spree/core/price_migrator_spec.rb +4 -4
  113. data/spec/lib/spree/core/testing_support/factories/order_factory_spec.rb +199 -91
  114. data/spec/lib/spree/core/testing_support/factories/variant_factory_spec.rb +18 -0
  115. data/spec/lib/spree/localized_number_spec.rb +6 -0
  116. data/spec/mailers/carton_mailer_spec.rb +3 -3
  117. data/spec/models/spree/address_spec.rb +3 -3
  118. data/spec/models/spree/adjustment_spec.rb +71 -27
  119. data/spec/models/spree/calculator/default_tax_spec.rb +72 -1
  120. data/spec/models/spree/calculator/distributed_amount_spec.rb +32 -0
  121. data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +20 -1
  122. data/spec/models/spree/calculator/tiered_percent_spec.rb +20 -1
  123. data/spec/models/spree/distributed_amounts_handler_spec.rb +79 -0
  124. data/spec/models/spree/gateway/bogus_simple.rb +7 -13
  125. data/spec/models/spree/gateway/bogus_spec.rb +8 -4
  126. data/spec/models/spree/gateway_spec.rb +6 -105
  127. data/spec/models/spree/image_spec.rb +23 -0
  128. data/spec/models/spree/order/checkout_spec.rb +3 -18
  129. data/spec/models/spree/order/number_generator_spec.rb +45 -0
  130. data/spec/models/spree/order/outstanding_balance_integration_spec.rb +135 -0
  131. data/spec/models/spree/order/payment_spec.rb +7 -2
  132. data/spec/models/spree/order/state_machine_spec.rb +4 -2
  133. data/spec/models/spree/order_capturing_spec.rb +8 -8
  134. data/spec/models/spree/order_contents_spec.rb +8 -1
  135. data/spec/models/spree/order_shipping_spec.rb +5 -1
  136. data/spec/models/spree/order_spec.rb +156 -83
  137. data/spec/models/spree/order_taxation_spec.rb +126 -0
  138. data/spec/models/spree/order_update_attributes_spec.rb +1 -5
  139. data/spec/models/spree/order_updater_spec.rb +20 -21
  140. data/spec/models/spree/payment_create_spec.rb +14 -6
  141. data/spec/models/spree/payment_method/bogus_credit_card_spec.rb +8 -0
  142. data/spec/models/spree/payment_method/check_spec.rb +78 -0
  143. data/spec/models/spree/payment_method/credit_card_spec.rb +66 -0
  144. data/spec/models/spree/payment_method/simple_bogus_credit_card_spec.rb +18 -0
  145. data/spec/models/spree/payment_method_spec.rb +47 -2
  146. data/spec/models/spree/payment_spec.rb +6 -8
  147. data/spec/models/spree/preference_spec.rb +1 -1
  148. data/spec/models/spree/price_spec.rb +1 -1
  149. data/spec/models/spree/product/scopes_spec.rb +46 -0
  150. data/spec/models/spree/promotion_action_spec.rb +4 -0
  151. data/spec/models/spree/promotion_code/batch_builder_spec.rb +25 -3
  152. data/spec/models/spree/promotion_code_batch_spec.rb +0 -6
  153. data/spec/models/spree/promotion_handler/coupon_spec.rb +1 -1
  154. data/spec/models/spree/promotion_rule_spec.rb +5 -0
  155. data/spec/models/spree/reimbursement_type/original_payment_spec.rb +1 -1
  156. data/spec/models/spree/shipment_spec.rb +24 -3
  157. data/spec/models/spree/shipping_rate_spec.rb +5 -5
  158. data/spec/models/spree/state_spec.rb +31 -4
  159. data/spec/models/spree/stock/coordinator_spec.rb +24 -0
  160. data/spec/models/spree/stock/estimator_spec.rb +1 -1
  161. data/spec/models/spree/store_selector/by_server_name_spec.rb +26 -0
  162. data/spec/models/spree/store_selector/legacy_spec.rb +44 -0
  163. data/spec/models/spree/store_spec.rb +10 -2
  164. data/spec/models/spree/tax/order_adjuster_spec.rb +11 -21
  165. data/spec/models/spree/tax/shipping_rate_taxer_spec.rb +10 -3
  166. data/spec/models/spree/tax/taxation_integration_spec.rb +43 -8
  167. data/spec/models/spree/tax_calculator/default_spec.rb +54 -0
  168. data/spec/models/spree/tax_rate_spec.rb +92 -0
  169. data/spec/models/spree/variant/vat_price_generator_spec.rb +4 -4
  170. data/spec/models/spree/variant_spec.rb +8 -2
  171. data/spec/spec_helper.rb +2 -1
  172. data/spec/support/test_gateway.rb +1 -1
  173. metadata +45 -24
  174. data/app/models/spree/tax/item_adjuster.rb +0 -51
  175. data/spec/models/spree/tax/item_adjuster_spec.rb +0 -82
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2a2dec32c7e551a4cccda16f58059e05cbb507ea
4
- data.tar.gz: 0f1687d7691c96cb0a0aae2b13cc53c1e4f90692
3
+ metadata.gz: 9d015fdadf3dd41148e17b69ff2432090071c998
4
+ data.tar.gz: cf60f2cdfa6b33eccb82886b942a23b3253a5557
5
5
  SHA512:
6
- metadata.gz: 9215d5df94bc2bb98df3f74e33b670af7fa9a7f00edec4ee4367e9f28da1d386cde1982f3f770c6eba3676e29253dd7c3b1c2c2d1640dec5fd6fd9a4eff31242
7
- data.tar.gz: d2b86bb28e9673ddf3f32d98a67d274bf580f057f812e662d4c4f43e7f9cb6cd67dbe0628d58fc839e78ba15636f8528c4b416caeeece6dd5ca98a9046e677e6
6
+ metadata.gz: dbd5d9fc8a47b9470a406e28e8f7427ab0c005893c6179e908d50e6310f375216a2c933a4d56a26b5695beb8a5a46ed2e2996ec34caeccceb9c8d41eb44affc9
7
+ data.tar.gz: 2d86cd376c2341b82ca020ed126c4633151d99918775863c2223bcb4e6da88259f9e5dcf80d5ed8a18cb02fcc50949e8bb4a0800c0929d0d34b441e3457bbe95
data/README.md CHANGED
@@ -38,13 +38,10 @@ integration.
38
38
  * `Spree::Payment` - Manage and process a payment for an order, from a specific
39
39
  source (e.g. `Spree::CreditCard`) using a specific payment method (e.g
40
40
  `Solidus::Gateway::Braintree`).
41
- * `Spree::PaymentMethod` - An abstract class which is implemented most commonly
42
- as a `Spree::Gateway`.
43
- * `Spree::Gateway` - A concrete implementation of `Spree::PaymentMethod`
44
- intended to provide a base for extension. See
45
- https://github.com/solidusio/solidus_gateway/ for offically supported payment
46
- gateway implementations.
47
- * `Spree::CreditCard` - The default `source` of a `Spree::Payment`.
41
+ * `Spree::PaymentMethod` - A base class which is used for implementing payment methods.
42
+ * `Spree::PaymentMethod::CreditCard` - An implementation of a `Spree::PaymentMethod` for credit card payments.
43
+ See https://github.com/solidusio/solidus_gateway/ for officially supported payment method implementations.
44
+ * `Spree::CreditCard` - The `source` of a `Spree::Payment` using `Spree::PaymentMethod::CreditCard` as payment method.
48
45
 
49
46
  ## The Inventory Sub-System
50
47
  * `Spree::ReturnAuthorization` - Models the return of Inventory Units to
@@ -23,8 +23,8 @@ Spree.pathFor = function(path) {
23
23
  };
24
24
 
25
25
  Spree.url = function(uri, query) {
26
- if (Spree.env === 'development' || Spree.env === 'test') {
27
- console.warn('Spree.url is deprecated, please use Spree.ajax for your request instead.');
26
+ if (console && console.warn) {
27
+ console.warn('Spree.url is deprecated, and will be removed from a future Solidus version.');
28
28
  }
29
29
  if (uri.path === undefined) {
30
30
  uri = new Uri(uri);
@@ -4,11 +4,11 @@ module Spree
4
4
  text = text ? h(text) : Spree.t(:cart)
5
5
  css_class = nil
6
6
 
7
- if simple_current_order.nil? || simple_current_order.item_count.zero?
7
+ if current_order.nil? || current_order.item_count.zero?
8
8
  text = "#{text}: (#{Spree.t(:empty)})"
9
9
  css_class = 'empty'
10
10
  else
11
- text = "#{text}: (#{simple_current_order.item_count}) <span class='amount'>#{simple_current_order.display_total.to_html}</span>"
11
+ text = "#{text}: (#{current_order.item_count}) <span class='amount'>#{current_order.display_total.to_html}</span>"
12
12
  css_class = 'full'
13
13
  end
14
14
 
@@ -84,7 +84,7 @@ module Spree
84
84
  items = crumbs.each_with_index.collect do |crumb, i|
85
85
  content_tag(:li, itemprop: 'itemListElement', itemscope: '', itemtype: 'https://schema.org/ListItem') do
86
86
  link_to(crumb.last, itemprop: 'item') do
87
- content_tag(:span, crumb.first, itemprop: 'name') + tag('meta', { itemprop: 'position', content: (i+1).to_s }, false, false)
87
+ content_tag(:span, crumb.first, itemprop: 'name') + tag('meta', { itemprop: 'position', content: (i + 1).to_s }, false, false)
88
88
  end + (crumb == crumbs.last ? '' : separator)
89
89
  end
90
90
  end
@@ -147,6 +147,5 @@ module Spree
147
147
  def plural_resource_name(resource_class)
148
148
  resource_class.model_name.human(count: Spree::I18N_GENERIC_PLURAL)
149
149
  end
150
-
151
150
  end
152
151
  end
@@ -193,7 +193,7 @@ module Spree
193
193
  # ensure state_name belongs to country without states, or that it matches a predefined state name/abbr
194
194
  if state_name.present?
195
195
  if country.states.present?
196
- states = country.states.find_all_by_name_or_abbr(state_name)
196
+ states = country.states.with_name_or_abbr(state_name)
197
197
 
198
198
  if states.size == 1
199
199
  self.state = states.first
@@ -97,7 +97,9 @@ module Spree
97
97
  #
98
98
  # @return [BigDecimal] New amount of this adjustment
99
99
  def update!
100
- return amount if finalized?
100
+ if finalized? && !tax?
101
+ return amount
102
+ end
101
103
 
102
104
  # If the adjustment has no source, do not attempt to re-calculate the amount.
103
105
  # Chances are likely that this was a manually created adjustment in the admin backend.
@@ -309,6 +309,17 @@ module Spree
309
309
  @shipping_rate_taxer_class ||= Spree::Tax::ShippingRateTaxer
310
310
  end
311
311
 
312
+ # Allows providing your own class for calculating taxes on a shipping rate.
313
+ #
314
+ # @!attribute [rw] shipping_rate_tax_calculator_class
315
+ # @return [Class] a class with the same public interfaces as
316
+ # Spree::TaxCalculator::ShippingRate
317
+ # @api experimental
318
+ attr_writer :shipping_rate_tax_calculator_class
319
+ def shipping_rate_tax_calculator_class
320
+ @shipping_rate_tax_calculator_class ||= Spree::TaxCalculator::ShippingRate
321
+ end
322
+
312
323
  # Allows providing your own Mailer for shipped cartons.
313
324
  #
314
325
  # @!attribute [rw] carton_shipped_email_class
@@ -365,6 +376,38 @@ module Spree
365
376
  @tax_adjuster_class ||= Spree::Tax::OrderAdjuster
366
377
  end
367
378
 
379
+ # Allows providing your own class for calculating taxes on an order.
380
+ #
381
+ # @!attribute [rw] tax_calculator_class
382
+ # @return [Class] a class with the same public interfaces as
383
+ # Spree::TaxCalculator::Default
384
+ # @api experimental
385
+ attr_writer :tax_calculator_class
386
+ def tax_calculator_class
387
+ @tax_calculator_class ||= Spree::TaxCalculator::Default
388
+ end
389
+
390
+ # Allows providing your own class for choosing which store to use.
391
+ #
392
+ # @!attribute [rw] current_store_selector_class
393
+ # @return [Class] a class with the same public interfaces as
394
+ # Spree::CurrentStoreSelector
395
+ attr_writer :current_store_selector_class
396
+ def current_store_selector_class
397
+ @current_store_selector_class ||= Spree::StoreSelector::ByServerName
398
+ end
399
+
400
+ # Allows providing your own class instance for generating order numbers.
401
+ #
402
+ # @!attribute [rw] order_number_generator
403
+ # @return [Class] a class instance with the same public interfaces as
404
+ # Spree::Order::NumberGenerator
405
+ # @api experimental
406
+ attr_writer :order_number_generator
407
+ def order_number_generator
408
+ @order_number_generator ||= Spree::Order::NumberGenerator.new
409
+ end
410
+
368
411
  def static_model_preferences
369
412
  @static_model_preferences ||= Spree::Preferences::StaticModelPreferences.new
370
413
  end
@@ -5,11 +5,11 @@ module Spree
5
5
  preference :server, :string, default: 'test'
6
6
  preference :test_mode, :boolean, default: true
7
7
 
8
- def provider
8
+ def gateway
9
9
  integration_options = options
10
10
  ActiveMerchant::Billing::Base.integration_mode = integration_options[:server].to_sym
11
11
  integration_options[:test] = true if integration_options[:test_mode]
12
- @provider ||= provider_class.new(integration_options)
12
+ @gateway ||= gateway_class.new(integration_options)
13
13
  end
14
14
 
15
15
  def options
@@ -8,8 +8,9 @@ module Spree
8
8
  # Orders created before Spree 2.1 had tax adjustments applied to the order, as a whole.
9
9
  # Orders created with Spree 2.2 and after, have them applied to the line items individually.
10
10
  def compute_order(order)
11
+ return 0 unless rate.active?
11
12
  matched_line_items = order.line_items.select do |line_item|
12
- line_item.tax_category == rate.tax_category
13
+ rate.tax_categories.include?(line_item.tax_category)
13
14
  end
14
15
 
15
16
  line_items_total = matched_line_items.sum(&:discounted_amount)
@@ -23,6 +24,7 @@ module Spree
23
24
 
24
25
  # When it comes to computing shipments or line items: same same.
25
26
  def compute_item(item)
27
+ return 0 unless rate.active?
26
28
  if rate.included_in_price
27
29
  deduced_total_by_rate(item, rate)
28
30
  else
@@ -0,0 +1,24 @@
1
+ require_dependency 'spree/calculator'
2
+
3
+ # This is a calculator for line item adjustment actions. It accepts a line item
4
+ # and calculates its weighted adjustment amount based on the value of the
5
+ # preferred amount and the price of the other line items. More expensive line
6
+ # items will receive a greater share of the preferred amount.
7
+
8
+ module Spree
9
+ class Calculator::DistributedAmount < Calculator
10
+ preference :amount, :decimal, default: 0
11
+ preference :currency, :string, default: -> { Spree::Config[:currency] }
12
+
13
+ def compute_line_item(line_item)
14
+ if line_item && preferred_currency.casecmp(line_item.currency).zero?
15
+ Spree::DistributedAmountsHandler.new(
16
+ line_item,
17
+ preferred_amount
18
+ ).amount
19
+ else
20
+ 0
21
+ end
22
+ end
23
+ end
24
+ end
@@ -3,7 +3,6 @@ module Spree
3
3
  # The only case where it was used was for Free Shipping Promotions. There is
4
4
  # now a Promotion Action which deals with these types of promotions instead.
5
5
  class Calculator::FreeShipping < Calculator
6
-
7
6
  def compute(object)
8
7
  if object.is_a?(Array)
9
8
  return if object.empty?
@@ -4,12 +4,13 @@ module Spree
4
4
  class Calculator::TieredFlatRate < Calculator
5
5
  preference :base_amount, :decimal, default: 0
6
6
  preference :tiers, :hash, default: {}
7
+ preference :currency, :string, default: -> { Spree::Config[:currency] }
7
8
 
8
9
  before_validation do
9
10
  # Convert tier values to decimals. Strings don't do us much good.
10
11
  if preferred_tiers.is_a?(Hash)
11
12
  self.preferred_tiers = preferred_tiers.map do |k, v|
12
- [BigDecimal.new(k.to_s), BigDecimal.new(v.to_s)]
13
+ [cast_to_d(k.to_s), cast_to_d(v.to_s)]
13
14
  end.to_h
14
15
  end
15
16
  end
@@ -17,12 +18,25 @@ module Spree
17
18
  validate :preferred_tiers_content
18
19
 
19
20
  def compute(object)
20
- _base, amount = preferred_tiers.sort.reverse.detect{ |b, _| object.amount >= b }
21
- amount || preferred_base_amount
21
+ _base, amount = preferred_tiers.sort.reverse.detect do |b, _|
22
+ object.amount >= b
23
+ end
24
+
25
+ if preferred_currency.casecmp(object.currency).zero?
26
+ amount || preferred_base_amount
27
+ else
28
+ 0
29
+ end
22
30
  end
23
31
 
24
32
  private
25
33
 
34
+ def cast_to_d(value)
35
+ value.to_s.to_d
36
+ rescue ArgumentError
37
+ BigDecimal.new(0)
38
+ end
39
+
26
40
  def preferred_tiers_content
27
41
  if preferred_tiers.is_a? Hash
28
42
  unless preferred_tiers.keys.all?{ |k| k.is_a?(Numeric) && k > 0 }
@@ -4,12 +4,13 @@ module Spree
4
4
  class Calculator::TieredPercent < Calculator
5
5
  preference :base_percent, :decimal, default: 0
6
6
  preference :tiers, :hash, default: {}
7
+ preference :currency, :string, default: -> { Spree::Config[:currency] }
7
8
 
8
9
  before_validation do
9
10
  # Convert tier values to decimals. Strings don't do us much good.
10
11
  if preferred_tiers.is_a?(Hash)
11
12
  self.preferred_tiers = preferred_tiers.map do |k, v|
12
- [BigDecimal.new(k.to_s), BigDecimal.new(v.to_s)]
13
+ [cast_to_d(k.to_s), cast_to_d(v.to_s)]
13
14
  end.to_h
14
15
  end
15
16
  end
@@ -22,12 +23,26 @@ module Spree
22
23
 
23
24
  def compute(object)
24
25
  order = object.is_a?(Order) ? object : object.order
25
- _base, percent = preferred_tiers.sort.reverse.detect{ |b, _| order.item_total >= b }
26
- (object.amount * (percent || preferred_base_percent) / 100).round(2)
26
+
27
+ _base, percent = preferred_tiers.sort.reverse.detect do |b, _|
28
+ order.item_total >= b
29
+ end
30
+
31
+ if preferred_currency.casecmp(order.currency).zero?
32
+ (object.amount * (percent || preferred_base_percent) / 100).round(2)
33
+ else
34
+ 0
35
+ end
27
36
  end
28
37
 
29
38
  private
30
39
 
40
+ def cast_to_d(value)
41
+ value.to_s.to_d
42
+ rescue ArgumentError
43
+ BigDecimal.new(0)
44
+ end
45
+
31
46
  def preferred_tiers_content
32
47
  if preferred_tiers.is_a? Hash
33
48
  unless preferred_tiers.keys.all?{ |k| k.is_a?(Numeric) && k > 0 }
@@ -0,0 +1,43 @@
1
+ module Spree
2
+ class DistributedAmountsHandler
3
+ attr_reader :line_item, :order, :total_amount
4
+
5
+ def initialize(line_item, total_amount)
6
+ @line_item = line_item
7
+ @order = line_item.order
8
+ @total_amount = total_amount
9
+ end
10
+
11
+ # @return [Float] the weighted adjustment for the initialized line item
12
+ def amount
13
+ distributed_amounts[@line_item.id].to_f
14
+ end
15
+
16
+ private
17
+
18
+ # @private
19
+ # @return [Hash<Integer, BigDecimal>] a hash of line item IDs and their
20
+ # corresponding weighted adjustments
21
+ def distributed_amounts
22
+ remaining_amount = @total_amount
23
+
24
+ @order.line_items.each_with_index.map do |line_item, i|
25
+ if i == @order.line_items.length - 1
26
+ # If this is the last line item on the order we want to use the
27
+ # remaining preferred amount to ensure our total adjustment is what
28
+ # has been set as the preferred amount.
29
+ [line_item.id, remaining_amount]
30
+ else
31
+ # Calculate the weighted amount by getting this line item's share of
32
+ # the order's total and multiplying it with the preferred amount.
33
+ weighted_amount = ((line_item.amount / @order.item_total) * total_amount).round(2)
34
+
35
+ # Subtract this line item's weighted amount from the total.
36
+ remaining_amount -= weighted_amount
37
+
38
+ [line_item.id, weighted_amount]
39
+ end
40
+ end.to_h
41
+ end
42
+ end
43
+ end
@@ -1,87 +1,11 @@
1
1
  module Spree
2
- class Gateway::Bogus < Gateway
3
- TEST_VISA = ['4111111111111111', '4012888888881881', '4222222222222']
4
- TEST_MC = ['5500000000000004', '5555555555554444', '5105105105105100']
5
- TEST_AMEX = ['378282246310005', '371449635398431', '378734493671000', '340000000000009']
6
- TEST_DISC = ['6011000000000004', '6011111111111117', '6011000990139424']
7
-
8
- VALID_CCS = ['1', TEST_VISA, TEST_MC, TEST_AMEX, TEST_DISC].flatten
9
-
10
- attr_accessor :test
11
-
12
- def provider_class
13
- self.class
14
- end
15
-
16
- def create_profile(payment)
17
- return if payment.source.has_payment_profile?
18
- # simulate the storage of credit card profile using remote service
19
- if success = VALID_CCS.include?(payment.source.number)
20
- payment.source.update_attributes(gateway_customer_profile_id: generate_profile_id(success))
21
- end
22
- end
23
-
24
- def authorize(_money, credit_card, _options = {})
25
- profile_id = credit_card.gateway_customer_profile_id
26
- if VALID_CCS.include?(credit_card.number) || (profile_id && profile_id.starts_with?('BGS-'))
27
- ActiveMerchant::Billing::Response.new(true, 'Bogus Gateway: Forced success', {}, test: true, authorization: '12345', avs_result: { code: 'D' })
28
- else
29
- ActiveMerchant::Billing::Response.new(false, 'Bogus Gateway: Forced failure', { message: 'Bogus Gateway: Forced failure' }, test: true)
30
- end
31
- end
32
-
33
- def purchase(_money, credit_card, _options = {})
34
- profile_id = credit_card.gateway_customer_profile_id
35
- if VALID_CCS.include?(credit_card.number) || (profile_id && profile_id.starts_with?('BGS-'))
36
- ActiveMerchant::Billing::Response.new(true, 'Bogus Gateway: Forced success', {}, test: true, authorization: '12345', avs_result: { code: 'M' })
37
- else
38
- ActiveMerchant::Billing::Response.new(false, 'Bogus Gateway: Forced failure', message: 'Bogus Gateway: Forced failure', test: true)
39
- end
40
- end
41
-
42
- def credit(_money, _credit_card, _response_code, _options = {})
43
- ActiveMerchant::Billing::Response.new(true, 'Bogus Gateway: Forced success', {}, test: true, authorization: '12345')
44
- end
45
-
46
- def capture(_money, authorization, _gateway_options)
47
- if authorization == '12345'
48
- ActiveMerchant::Billing::Response.new(true, 'Bogus Gateway: Forced success', {}, test: true)
49
- else
50
- ActiveMerchant::Billing::Response.new(false, 'Bogus Gateway: Forced failure', error: 'Bogus Gateway: Forced failure', test: true)
51
- end
52
- end
53
-
54
- def void(_response_code, _credit_card, _options = {})
55
- ActiveMerchant::Billing::Response.new(true, 'Bogus Gateway: Forced success', {}, test: true, authorization: '12345')
56
- end
57
-
58
- def cancel(_response_code)
59
- ActiveMerchant::Billing::Response.new(true, 'Bogus Gateway: Forced success', {}, test: true, authorization: '12345')
60
- end
61
-
62
- def test?
63
- # Test mode is not really relevant with bogus gateway (no such thing as live server)
64
- true
65
- end
66
-
67
- def payment_profiles_supported?
68
- true
69
- end
70
-
71
- def actions
72
- %w(capture void credit)
73
- end
74
-
75
- private
76
-
77
- def generate_profile_id(success)
78
- record = true
79
- prefix = success ? 'BGS' : 'FAIL'
80
- while record
81
- random = "#{prefix}-#{Array.new(6){ rand(6) }.join}"
82
- record = Spree::CreditCard.where(gateway_customer_profile_id: random).first
83
- end
84
- random
2
+ # @deprecated Use Spree::PaymentMethod::BogusCreditCard instead
3
+ class Gateway::Bogus < PaymentMethod::BogusCreditCard
4
+ def initialize(*args)
5
+ Spree::Deprecation.warn \
6
+ 'Spree::Gateway::Bogus is deprecated. ' \
7
+ 'Please use Spree::PaymentMethod::BogusCreditCard instead'
8
+ super
85
9
  end
86
10
  end
87
11
  end
@@ -1,24 +1,11 @@
1
1
  module Spree
2
- # Bogus Gateway that doesn't support payment profiles.
3
- class Gateway::BogusSimple < Gateway::Bogus
4
- def payment_profiles_supported?
5
- false
6
- end
7
-
8
- def authorize(_money, credit_card, _options = {})
9
- if VALID_CCS.include? credit_card.number
10
- ActiveMerchant::Billing::Response.new(true, 'Bogus Gateway: Forced success', {}, test: true, authorization: '12345', avs_result: { code: 'A' })
11
- else
12
- ActiveMerchant::Billing::Response.new(false, 'Bogus Gateway: Forced failure', { message: 'Bogus Gateway: Forced failure' }, test: true)
13
- end
14
- end
15
-
16
- def purchase(_money, credit_card, _options = {})
17
- if VALID_CCS.include? credit_card.number
18
- ActiveMerchant::Billing::Response.new(true, 'Bogus Gateway: Forced success', {}, test: true, authorization: '12345', avs_result: { code: 'A' })
19
- else
20
- ActiveMerchant::Billing::Response.new(false, 'Bogus Gateway: Forced failure', message: 'Bogus Gateway: Forced failure', test: true)
21
- end
2
+ # @deprecated Use Spree::PaymentMethod::SimpleBogusCreditCard instead
3
+ class Gateway::BogusSimple < Spree::PaymentMethod::SimpleBogusCreditCard
4
+ def initialize(*args)
5
+ Spree::Deprecation.warn \
6
+ 'Spree::Gateway::BogusSimple is deprecated. ' \
7
+ 'Please use Spree::PaymentMethod::SimpleBogusCreditCard instead'
8
+ super
22
9
  end
23
10
  end
24
11
  end
@@ -1,62 +1,12 @@
1
1
  module Spree
2
- # A concrete implementation of `Spree::PaymentMethod` intended to provide a
3
- # base for extension. See https://github.com/solidusio/solidus_gateway/ for
4
- # offically supported payment gateway implementations.
5
- #
6
- class Gateway < PaymentMethod
7
- delegate :authorize, :purchase, :capture, :void, :credit, to: :provider
8
-
9
- validates :name, :type, presence: true
10
-
11
- preference :server, :string, default: 'test'
12
- preference :test_mode, :boolean, default: true
13
-
14
- def payment_source_class
15
- CreditCard
16
- end
17
-
18
- def provider
19
- gateway_options = options
20
- gateway_options.delete :login if gateway_options.key?(:login) && gateway_options[:login].nil?
21
- if gateway_options[:server]
22
- ActiveMerchant::Billing::Base.mode = gateway_options[:server].to_sym
23
- end
24
- @provider ||= provider_class.new(gateway_options)
25
- end
26
-
27
- def options
28
- preferences.to_hash
29
- end
30
-
31
- def payment_profiles_supported?
32
- false
33
- end
34
-
35
- def method_type
36
- 'gateway'
37
- end
38
-
39
- def supports?(source)
40
- return true unless provider_class.respond_to? :supports?
41
- return true if source.brand && provider_class.supports?(source.brand)
42
- source.has_payment_profile?
43
- end
44
-
45
- def reusable_sources_by_order(order)
46
- source_ids = order.payments.where(payment_method_id: id).pluck(:source_id).uniq
47
- payment_source_class.where(id: source_ids).select(&:reusable?)
48
- end
49
- alias_method :sources_by_order, :reusable_sources_by_order
50
- deprecate sources_by_order: :reusable_sources_by_order, deprecator: Spree::Deprecation
51
-
52
- def reusable_sources(order)
53
- if order.completed?
54
- reusable_sources_by_order(order)
55
- elsif order.user_id
56
- order.user.wallet.wallet_payment_sources.map(&:payment_source).select(&:reusable?)
57
- else
58
- []
59
- end
2
+ # @deprecated Use Spree::PaymentMethod::CreditCard or Spree::PaymentMethod instead
3
+ class Gateway < PaymentMethod::CreditCard
4
+ def initialize(*args)
5
+ Spree::Deprecation.warn \
6
+ "Using Spree::Gateway as parent class of payment methods is deprecated. " \
7
+ "Please use Spree::PaymentMethod::CreditCard for credit card based payment methods " \
8
+ "or Spree::PaymentMethod for non credit card payment methods instead."
9
+ super
60
10
  end
61
11
  end
62
12
  end
@@ -15,7 +15,7 @@ module Spree
15
15
 
16
16
  # save the w,h of the original image (from which others can be calculated)
17
17
  # we need to look at the write-queue for images which have not been saved yet
18
- after_post_process :find_dimensions
18
+ after_post_process :find_dimensions, if: :valid?
19
19
 
20
20
  # used by admin products autocomplete
21
21
  def mini_url
@@ -175,7 +175,7 @@ module Spree
175
175
  end
176
176
 
177
177
  def update_inventory
178
- if (changed? || target_shipment.present?) && order.has_checkout_step?("delivery")
178
+ if (saved_changes? || target_shipment.present?) && order.has_checkout_step?("delivery")
179
179
  Spree::OrderInventory.new(order, self).verify(target_shipment)
180
180
  end
181
181
  end
@@ -9,7 +9,7 @@ module Spree
9
9
  validates :name, presence: true, uniqueness: { scope: :option_type_id, allow_blank: true }
10
10
  validates :presentation, presence: true
11
11
 
12
- after_save :touch, if: :changed?
12
+ after_save :touch, if: :saved_changes?
13
13
  after_touch :touch_all_variants
14
14
 
15
15
  delegate :name, :presentation, to: :option_type, prefix: :option_type
@@ -90,7 +90,7 @@ module Spree
90
90
  before_transition from: :cart, do: :ensure_line_items_present
91
91
 
92
92
  if states[:address]
93
- before_transition to: :address, do: :assign_default_addresses!
93
+ before_transition to: :address, do: :assign_default_user_addresses
94
94
  before_transition from: :address, do: :persist_user_address!
95
95
  end
96
96
 
@@ -108,9 +108,6 @@ module Spree
108
108
  # calls matter so that we do not process payments
109
109
  # until validations have passed
110
110
  before_transition to: :complete, do: :validate_line_item_availability
111
- if states[:delivery]
112
- before_transition to: :complete, do: :ensure_available_shipping_rates
113
- end
114
111
  before_transition to: :complete, do: :ensure_promotions_eligible
115
112
  before_transition to: :complete, do: :ensure_line_item_variants_are_not_deleted
116
113
  before_transition to: :complete, do: :ensure_inventory_units
@@ -0,0 +1,43 @@
1
+ module Spree
2
+ # Generates order numbers
3
+ #
4
+ # In order to change the way your order numbers get generated you can either
5
+ # set your own instance of this class in your stores configuration with different options:
6
+ #
7
+ # Spree::Config.order_number_generator = Spree::Order::NumberGenerator.new(
8
+ # prefix: 'B',
9
+ # lenght: 8,
10
+ # letters: false
11
+ # )
12
+ #
13
+ # or create your own class:
14
+ #
15
+ # Spree::Config.order_number_generator = My::OrderNumberGenerator.new
16
+ #
17
+ class Order::NumberGenerator
18
+ attr_reader :letters, :prefix
19
+
20
+ def initialize(options = {})
21
+ @length = options[:length] || Spree::Order::ORDER_NUMBER_LENGTH
22
+ @letters = options[:letters] || Spree::Order::ORDER_NUMBER_LETTERS
23
+ @prefix = options[:prefix] || Spree::Order::ORDER_NUMBER_PREFIX
24
+ end
25
+
26
+ def generate
27
+ possible = (0..9).to_a
28
+ possible += ('A'..'Z').to_a if letters
29
+
30
+ loop do
31
+ # Make a random number.
32
+ random = "#{prefix}#{(0...@length).map { possible.sample }.join}"
33
+ # Use the random number if no other order exists with it.
34
+ if Spree::Order.exists?(number: random)
35
+ # If over half of all possible options are taken add another digit.
36
+ @length += 1 if Spree::Order.count > (10**@length / 2)
37
+ else
38
+ break random
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end