solidus_core 3.2.5 → 3.3.0

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 (91) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +6 -2
  3. data/app/controllers/spree/base_controller.rb +1 -1
  4. data/app/models/concerns/spree/active_storage_adapter/attachment.rb +4 -0
  5. data/app/models/concerns/spree/ransackable_attributes.rb +24 -4
  6. data/app/models/concerns/spree/user_methods.rb +2 -2
  7. data/app/models/spree/address.rb +1 -1
  8. data/app/models/spree/calculator/flat_fee.rb +21 -0
  9. data/app/models/spree/country.rb +1 -1
  10. data/app/models/spree/credit_card.rb +1 -1
  11. data/app/models/spree/customer_return.rb +1 -1
  12. data/app/models/spree/line_item.rb +2 -2
  13. data/app/models/spree/option_type.rb +1 -1
  14. data/app/models/spree/option_value.rb +1 -1
  15. data/app/models/spree/order/number_generator.rb +7 -1
  16. data/app/models/spree/order.rb +4 -3
  17. data/app/models/spree/order_promotion.rb +1 -1
  18. data/app/models/spree/order_updater.rb +11 -2
  19. data/app/models/spree/payment/processing.rb +58 -55
  20. data/app/models/spree/payment_method/bogus_credit_card.rb +6 -7
  21. data/app/models/spree/payment_method/simple_bogus_credit_card.rb +8 -0
  22. data/app/models/spree/payment_method.rb +16 -10
  23. data/app/models/spree/price.rb +1 -1
  24. data/app/models/spree/product.rb +3 -3
  25. data/app/models/spree/product_property.rb +1 -1
  26. data/app/models/spree/promotion/actions/free_shipping.rb +1 -0
  27. data/app/models/spree/promotion/order_adjustments_recalculator.rb +92 -0
  28. data/app/models/spree/promotion.rb +2 -2
  29. data/app/models/spree/promotion_code.rb +1 -1
  30. data/app/models/spree/property.rb +1 -1
  31. data/app/models/spree/return_authorization.rb +1 -1
  32. data/app/models/spree/shipment.rb +2 -2
  33. data/app/models/spree/state.rb +1 -1
  34. data/app/models/spree/stock_item.rb +1 -1
  35. data/app/models/spree/stock_location.rb +1 -1
  36. data/app/models/spree/stock_movement.rb +2 -2
  37. data/app/models/spree/store_credit_prioritizer.rb +17 -0
  38. data/app/models/spree/tax/tax_helpers.rb +2 -2
  39. data/app/models/spree/tax_calculator/default.rb +31 -0
  40. data/app/models/spree/tax_rate.rb +9 -3
  41. data/app/models/spree/taxon.rb +1 -1
  42. data/app/models/spree/taxonomy.rb +1 -1
  43. data/app/models/spree/user_last_url_storer/rules/authentication_rule.rb +1 -1
  44. data/app/models/spree/variant.rb +25 -5
  45. data/app/models/spree/zone.rb +1 -1
  46. data/config/locales/en.yml +17 -2
  47. data/db/migrate/20220805202442_add_level_to_spree_tax_rates.rb +5 -0
  48. data/db/migrate/20221123152807_add_shipping_category_to_spree_variants.rb +5 -0
  49. data/db/seeds.rb +4 -1
  50. data/lib/generators/solidus/install/app_templates/authentication/custom.rb +21 -0
  51. data/lib/generators/solidus/install/app_templates/authentication/devise.rb +16 -0
  52. data/lib/generators/solidus/install/app_templates/authentication/existing.rb +10 -0
  53. data/lib/generators/solidus/install/app_templates/authentication/none.rb +1 -0
  54. data/lib/generators/solidus/install/app_templates/frontend/break_down_solidus_gem.rb +54 -0
  55. data/lib/generators/solidus/install/app_templates/frontend/classic.rb +16 -0
  56. data/lib/generators/solidus/install/app_templates/frontend/none.rb +2 -0
  57. data/lib/generators/solidus/install/app_templates/frontend/starter.rb +3 -0
  58. data/lib/generators/solidus/install/app_templates/payment_method/bolt.rb +11 -9
  59. data/lib/generators/solidus/install/app_templates/payment_method/paypal.rb +8 -9
  60. data/lib/generators/solidus/install/install_generator.rb +213 -190
  61. data/lib/generators/solidus/install/templates/config/initializers/spree.rb.tt +3 -4
  62. data/lib/generators/spree/custom_user/custom_user_generator.rb +6 -4
  63. data/lib/generators/spree/custom_user/templates/authentication_helpers.rb.tt +2 -6
  64. data/lib/generators/spree/custom_user/templates/migration.rb.tt +7 -3
  65. data/lib/generators/spree/dummy/dummy_generator.rb +10 -8
  66. data/lib/generators/spree/dummy/templates/rails/database.yml +6 -12
  67. data/lib/spree/app_configuration.rb +23 -0
  68. data/lib/spree/core/controller_helpers/current_host.rb +5 -1
  69. data/lib/spree/core/engine.rb +1 -0
  70. data/lib/spree/core/search/base.rb +17 -8
  71. data/lib/spree/core/version.rb +2 -2
  72. data/lib/spree/core.rb +1 -20
  73. data/lib/spree/migrations.rb +12 -10
  74. data/lib/spree/permitted_attributes.rb +4 -1
  75. data/lib/spree/preferences/static_model_preferences.rb +25 -8
  76. data/lib/spree/rails_compatibility.rb +0 -17
  77. data/lib/spree/testing_support/common_rake.rb +7 -6
  78. data/lib/spree/testing_support/dummy_app.rb +2 -2
  79. data/lib/spree/testing_support/factories/address_factory.rb +9 -11
  80. data/lib/spree/testing_support/factories/calculator_factory.rb +3 -0
  81. data/lib/spree/testing_support/factories/country_factory.rb +1 -2
  82. data/lib/spree/testing_support/factories/promotion_factory.rb +28 -14
  83. data/lib/spree/testing_support/factories/state_factory.rb +8 -2
  84. data/lib/spree/testing_support/factory_bot.rb +1 -1
  85. data/lib/spree/testing_support/order_walkthrough.rb +1 -1
  86. data/lib/tasks/colorado_delivery_fee.rake +28 -0
  87. data/solidus_core.gemspec +2 -2
  88. metadata +33 -22
  89. data/lib/generators/solidus/install/install_generator/bundler_context.rb +0 -105
  90. data/lib/generators/solidus/install/install_generator/install_frontend.rb +0 -61
  91. data/lib/generators/solidus/install/install_generator/support_solidus_frontend_extraction.rb +0 -48
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ class Promotion < Spree::Base
5
+
6
+ # This class encapsulates all the things the promotion system does to
7
+ # an order. It is called from the `Spree::OrderUpdater` before taxes are
8
+ # calculated, such that taxes always respect promotions.
9
+
10
+ # This class iterates over all existing promotion adjustments and recalculates
11
+ # their amount and eligibility using their adjustment source.
12
+ class OrderAdjustmentsRecalculator
13
+ def initialize(order)
14
+ @order = order
15
+ end
16
+
17
+ def call
18
+ all_items = line_items + shipments
19
+ all_items.each do |item|
20
+ promotion_adjustments = item.adjustments.select(&:promotion?)
21
+
22
+ promotion_adjustments.each { |adjustment| recalculate(adjustment) }
23
+ Spree::Config.promotion_chooser_class.new(promotion_adjustments).update
24
+
25
+ item.promo_total = promotion_adjustments.select(&:eligible?).sum(&:amount)
26
+ end
27
+ # Update and select the best promotion adjustment for the order.
28
+ # We don't update the order.promo_total yet. Order totals are updated later
29
+ # in #update_adjustment_total since they include the totals from the order's
30
+ # line items and/or shipments.
31
+ order_promotion_adjustments = order.adjustments.select(&:promotion?)
32
+ order_promotion_adjustments.each { |adjustment| recalculate(adjustment) }
33
+ Spree::Config.promotion_chooser_class.new(order_promotion_adjustments).update
34
+
35
+ order.promo_total = all_items.sum(&:promo_total) +
36
+ order_promotion_adjustments.
37
+ select(&:eligible?).
38
+ select(&:promotion?).
39
+ sum(&:amount)
40
+ order
41
+ end
42
+
43
+ private
44
+
45
+ attr_reader :order
46
+ delegate :line_items, :shipments, to: :order
47
+
48
+ # Recalculate and persist the amount from this adjustment's source based on
49
+ # the adjustable ({Order}, {Shipment}, or {LineItem})
50
+ #
51
+ # If the adjustment has no source (such as when created manually from the
52
+ # admin) or is closed, this is a noop.
53
+ #
54
+ # @return [BigDecimal] New amount of this adjustment
55
+ def recalculate(adjustment)
56
+ if adjustment.finalized?
57
+ return adjustment.amount
58
+ end
59
+
60
+ # If the adjustment has no source, do not attempt to re-calculate the
61
+ # amount.
62
+ # Some scenarios where this happens:
63
+ # - Adjustments that are manually created via the admin backend
64
+ # - PromotionAction adjustments where the PromotionAction was deleted
65
+ # after the order was completed.
66
+ if adjustment.source.present?
67
+ adjustment.amount = adjustment.source.compute_amount(adjustment.adjustable)
68
+
69
+ adjustment.eligible = calculate_eligibility(adjustment)
70
+
71
+ # Persist only if changed
72
+ # This is only not a save! to avoid the extra queries to load the order
73
+ # (for validations) and to touch the adjustment.
74
+ adjustment.update_columns(eligible: adjustment.eligible, amount: adjustment.amount, updated_at: Time.current) if adjustment.changed?
75
+ end
76
+ adjustment.amount
77
+ end
78
+
79
+ # Calculates based on attached promotion (if this is a promotion
80
+ # adjustment) whether this promotion is still eligible.
81
+ # @api private
82
+ # @return [true,false] Whether this adjustment is eligible
83
+ def calculate_eligibility(adjustment)
84
+ if !adjustment.finalized? && adjustment.source
85
+ adjustment.source.promotion.eligible?(adjustment.adjustable, promotion_code: adjustment.promotion_code)
86
+ else
87
+ adjustment.eligible?
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -52,8 +52,8 @@ module Spree
52
52
  end
53
53
  scope :applied, -> { joins(:order_promotions).distinct }
54
54
 
55
- self.whitelisted_ransackable_associations = ['codes']
56
- self.whitelisted_ransackable_attributes = %w[name path promotion_category_id]
55
+ self.allowed_ransackable_associations = ['codes']
56
+ self.allowed_ransackable_attributes = %w[name path promotion_category_id]
57
57
  def self.ransackable_scopes(*)
58
58
  %i(active)
59
59
  end
@@ -11,7 +11,7 @@ class Spree::PromotionCode < Spree::Base
11
11
  validates :promotion, presence: true
12
12
  validate :promotion_not_apply_automatically, on: :create
13
13
 
14
- self.whitelisted_ransackable_attributes = ['value']
14
+ self.allowed_ransackable_attributes = ['value']
15
15
 
16
16
  # Whether the promotion code has exceeded its usage restrictions
17
17
  #
@@ -11,7 +11,7 @@ module Spree
11
11
 
12
12
  after_touch :touch_all_products
13
13
 
14
- self.whitelisted_ransackable_attributes = %w[name]
14
+ self.allowed_ransackable_attributes = %w[name]
15
15
 
16
16
  private
17
17
 
@@ -27,7 +27,7 @@ module Spree
27
27
  extend DisplayMoney
28
28
  money_methods :amount, :total_excluding_vat
29
29
 
30
- self.whitelisted_ransackable_attributes = ['memo']
30
+ self.allowed_ransackable_attributes = ['memo']
31
31
 
32
32
  def total_excluding_vat
33
33
  return_items.sum(&:total_excluding_vat)
@@ -41,8 +41,8 @@ module Spree
41
41
 
42
42
  include ::Spree::Config.state_machines.shipment
43
43
 
44
- self.whitelisted_ransackable_associations = ['order']
45
- self.whitelisted_ransackable_attributes = ['number']
44
+ self.allowed_ransackable_associations = ['order']
45
+ self.allowed_ransackable_attributes = ['number']
46
46
 
47
47
  delegate :tax_category, :tax_category_id, to: :selected_shipping_rate, allow_nil: true
48
48
 
@@ -15,7 +15,7 @@ module Spree
15
15
  )
16
16
  end
17
17
 
18
- self.whitelisted_ransackable_attributes = %w[name]
18
+ self.allowed_ransackable_attributes = %w[name]
19
19
 
20
20
  # table of { country.id => [ state.id , state.name ] }, arrays sorted by name
21
21
  # blank is added elsewhere, if needed
@@ -20,7 +20,7 @@ module Spree
20
20
  after_save :conditional_variant_touch, if: :saved_changes?
21
21
  after_touch { variant.touch }
22
22
 
23
- self.whitelisted_ransackable_attributes = ['count_on_hand', 'stock_location_id']
23
+ self.allowed_ransackable_attributes = ['count_on_hand', 'stock_location_id']
24
24
 
25
25
  # @return [Array<Spree::InventoryUnit>] the backordered inventory units
26
26
  # associated with this stock item
@@ -31,7 +31,7 @@ module Spree
31
31
  after_create :create_stock_items, if: :propagate_all_variants?
32
32
  after_save :ensure_one_default
33
33
 
34
- self.whitelisted_ransackable_attributes = %w[name]
34
+ self.allowed_ransackable_attributes = %w[name]
35
35
 
36
36
  def state_text
37
37
  state.try(:abbr) || state.try(:name) || state_name
@@ -13,8 +13,8 @@ module Spree
13
13
 
14
14
  scope :recent, -> { order(created_at: :desc) }
15
15
 
16
- self.whitelisted_ransackable_associations = %w[variant]
17
- self.whitelisted_ransackable_attributes = ['quantity']
16
+ self.allowed_ransackable_associations = %w[variant]
17
+ self.allowed_ransackable_attributes = ['quantity']
18
18
 
19
19
  def readonly?
20
20
  !new_record?
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ class StoreCreditPrioritizer
5
+ def initialize(credits, _order)
6
+ @credits = credits
7
+ end
8
+
9
+ def call
10
+ credits.order_by_priority
11
+ end
12
+
13
+ private
14
+
15
+ attr_reader :credits
16
+ end
17
+ end
@@ -6,9 +6,9 @@ module Spree
6
6
  private
7
7
 
8
8
  def rates_for_item(item)
9
- @rates_for_order ||= Spree::TaxRate.for_address(item.order.tax_address)
9
+ @rates_for_item ||= Spree::TaxRate.item_level.for_address(item.order.tax_address)
10
10
 
11
- @rates_for_order.select do |rate|
11
+ @rates_for_item.select do |rate|
12
12
  rate.active? && rate.tax_categories.map(&:id).include?(item.tax_category_id)
13
13
  end
14
14
  end
@@ -25,6 +25,7 @@ module Spree
25
25
  def calculate
26
26
  Spree::Tax::OrderTax.new(
27
27
  order_id: order.id,
28
+ order_taxes: order_rates,
28
29
  line_item_taxes: line_item_rates,
29
30
  shipment_taxes: shipment_rates
30
31
  )
@@ -34,6 +35,23 @@ module Spree
34
35
 
35
36
  attr_reader :order
36
37
 
38
+ # Calculate the order-level taxes.
39
+ #
40
+ # @private
41
+ # @return [Array<Spree::Tax::ItemTax>] calculated taxes for the order
42
+ def order_rates
43
+ rates_for_order.map do |rate|
44
+ amount = rate.compute_amount(order)
45
+
46
+ Spree::Tax::ItemTax.new(
47
+ label: rate.adjustment_label(amount),
48
+ tax_rate: rate,
49
+ amount: amount,
50
+ included_in_price: rate.included_in_price
51
+ )
52
+ end
53
+ end
54
+
37
55
  # Calculate the taxes for line items.
38
56
  #
39
57
  # @private
@@ -76,6 +94,19 @@ module Spree
76
94
  )
77
95
  end
78
96
  end
97
+
98
+ # @private
99
+ # @return [Array<Spree::TaxRate>] rates that apply to an order
100
+ def rates_for_order
101
+ tax_category_ids = Set[
102
+ *@order.line_items.map(&:tax_category_id),
103
+ *@order.shipments.map(&:tax_category_id)
104
+ ]
105
+ rates = Spree::TaxRate.active.order_level.for_address(@order.tax_address)
106
+ rates.select do |rate|
107
+ tax_category_ids.intersect?(rate.tax_category_ids.to_set)
108
+ end
109
+ end
79
110
  end
80
111
  end
81
112
  end
@@ -11,6 +11,11 @@ module Spree
11
11
  include Spree::CalculatedAdjustments
12
12
  include Spree::AdjustmentSource
13
13
 
14
+ enum level: {
15
+ item: 0,
16
+ order: 1
17
+ }, _suffix: true
18
+
14
19
  belongs_to :zone, class_name: "Spree::Zone", inverse_of: :tax_rates, optional: true
15
20
 
16
21
  has_many :tax_rate_tax_categories,
@@ -27,7 +32,7 @@ module Spree
27
32
 
28
33
  validates :amount, presence: true, numericality: true
29
34
 
30
- self.whitelisted_ransackable_associations = %w[tax_categories zone]
35
+ self.allowed_ransackable_associations = %w[tax_categories zone]
31
36
 
32
37
  # Finds all tax rates whose zones match a given address
33
38
  scope :for_address, ->(address) { joins(:zone).merge(Spree::Zone.for_address(address)) }
@@ -113,12 +118,13 @@ module Spree
113
118
  def amount_for_adjustment_label
114
119
  ActiveSupport::NumberHelper::NumberToPercentageConverter.convert(
115
120
  amount * 100,
116
- locale: I18n.locale,
117
- precision: nil
121
+ locale: I18n.locale
118
122
  )
119
123
  end
120
124
 
121
125
  def translation_key(_amount)
126
+ return "flat_fee" if calculator.is_a?(Spree::Calculator::FlatFee)
127
+
122
128
  key = included_in_price? ? "vat" : "sales_tax"
123
129
  key += "_with_rate" if show_rate_in_label?
124
130
  key.to_sym
@@ -27,7 +27,7 @@ module Spree
27
27
 
28
28
  include ::Spree::Config.taxon_attachment_module
29
29
 
30
- self.whitelisted_ransackable_attributes = %w[name]
30
+ self.allowed_ransackable_attributes = %w[name]
31
31
 
32
32
  # @return [String] meta_title if set otherwise a string containing the
33
33
  # root name and taxon name
@@ -13,7 +13,7 @@ module Spree
13
13
 
14
14
  default_scope -> { order(position: :asc) }
15
15
 
16
- self.whitelisted_ransackable_attributes = %w[name]
16
+ self.allowed_ransackable_attributes = %w[name]
17
17
 
18
18
  private
19
19
 
@@ -4,7 +4,7 @@ module Spree
4
4
  class UserLastUrlStorer
5
5
  module Rules
6
6
  # This is the basic rule that ships with Solidus that avoids storing in
7
- # session the current path for login/loout/signup routes, avoiding possibly
7
+ # session the current path for login/logout/signup routes, avoiding possibly
8
8
  # infinte redirects.
9
9
  module AuthenticationRule
10
10
  AUTHENTICATION_ROUTES = %w[spree_signup_path spree_login_path spree_logout_path]
@@ -30,11 +30,14 @@ module Spree
30
30
 
31
31
  belongs_to :product, -> { with_discarded }, touch: true, class_name: 'Spree::Product', inverse_of: :variants_including_master, optional: false
32
32
  belongs_to :tax_category, class_name: 'Spree::TaxCategory', optional: true
33
+ belongs_to :shipping_category, class_name: "Spree::ShippingCategory", optional: true
33
34
 
34
35
  delegate :name, :description, :slug, :available_on, :discontinue_on, :discontinued?,
35
- :shipping_category_id, :meta_description, :meta_keywords, :shipping_category,
36
+ :meta_description, :meta_keywords,
36
37
  to: :product
37
38
  delegate :tax_category, to: :product, prefix: true
39
+ delegate :shipping_category, :shipping_category_id,
40
+ to: :product, prefix: true
38
41
  delegate :tax_rates, to: :tax_category
39
42
 
40
43
  has_many :inventory_units, inverse_of: :variant
@@ -110,8 +113,8 @@ module Spree
110
113
  joins(:stock_items).where(arel_conditions.inject(:or)).distinct
111
114
  end
112
115
 
113
- self.whitelisted_ransackable_associations = %w[option_values product prices default_price]
114
- self.whitelisted_ransackable_attributes = %w[weight sku]
116
+ self.allowed_ransackable_associations = %w[option_values product prices default_price]
117
+ self.allowed_ransackable_attributes = %w[weight sku]
115
118
 
116
119
  # Returns variants that have a price for the given pricing options
117
120
  # If you have modified the pricing options class, you might want to modify this scope too.
@@ -142,6 +145,23 @@ module Spree
142
145
  super || product_tax_category
143
146
  end
144
147
 
148
+ # @return [Spree::ShippingCategory] the variant's shipping category
149
+ #
150
+ # This returns the product's shipping category if the shipping category ID on the variant is nil. It looks
151
+ # like an association, but really is an override.
152
+ #
153
+ def shipping_category
154
+ super || product_shipping_category
155
+ end
156
+
157
+ # @return [Integer] the variant's shipping category id
158
+ #
159
+ # This returns the product's shipping category if if the shipping category ID on the variant is nil.
160
+ #
161
+ def shipping_category_id
162
+ super || product_shipping_category_id
163
+ end
164
+
145
165
  # Sets the cost_price for the variant.
146
166
  #
147
167
  # @param price [Any] the price to set
@@ -210,8 +230,8 @@ module Spree
210
230
 
211
231
  # Assign given options hash to option values.
212
232
  #
213
- # @param options [Array] array of hashes with a name and value.
214
- def options=(options = {})
233
+ # @param options [Array<Hash{name: String, value: String}>] array of hashes with a name and value.
234
+ def options=(options = [])
215
235
  options.each do |option|
216
236
  set_option_value(option[:name], option[:value])
217
237
  end
@@ -42,7 +42,7 @@ module Spree
42
42
  alias :members :zone_members
43
43
  accepts_nested_attributes_for :zone_members, allow_destroy: true, reject_if: proc { |member| member['zoneable_id'].blank? }
44
44
 
45
- self.whitelisted_ransackable_attributes = %w[name description]
45
+ self.allowed_ransackable_attributes = %w[name description]
46
46
 
47
47
  # Returns all zones that contain any of the zone members of the zone passed
48
48
  # in. This also includes any country zones that contain the state of the
@@ -415,6 +415,7 @@ en:
415
415
  depth: Depth
416
416
  height: Height
417
417
  price: Price
418
+ shipping_category: Variant Shipping Category
418
419
  sku: SKU
419
420
  tax_category: Variant Tax Category
420
421
  weight: Weight
@@ -527,6 +528,9 @@ en:
527
528
  spree/calculator/distributed_amount:
528
529
  one: Distributed Amount
529
530
  other: Distributed Amount
531
+ spree/calculator/flat_fee:
532
+ one: Flat Fee
533
+ other: Flat Fee
530
534
  spree/calculator/flat_percent_item_total:
531
535
  one: Flat Percent
532
536
  other: Flat Percent
@@ -751,6 +755,10 @@ en:
751
755
  not_saved:
752
756
  one: '1 error prohibited this %{resource} from being saved:'
753
757
  other: "%{count} errors prohibited this %{resource} from being saved:"
758
+ number:
759
+ percentage:
760
+ format:
761
+ precision: 1
754
762
  spree:
755
763
  abbreviation: Abbreviation
756
764
  accept: Accept
@@ -813,6 +821,7 @@ en:
813
821
  line_item: "%{promotion} (%{promotion_name})"
814
822
  order: "%{promotion} (%{promotion_name})"
815
823
  tax_rates:
824
+ flat_fee: "%{name}"
816
825
  sales_tax: "%{name}"
817
826
  sales_tax_with_rate: "%{name} %{amount}"
818
827
  vat: "%{name} (Included in Price)"
@@ -989,6 +998,7 @@ en:
989
998
  pricing: Pricing
990
999
  pricing_hint: These values are populated from the product details page and can be overridden below
991
1000
  properties: Properties
1001
+ use_product_shipping_category: Use Product Shipping Category
992
1002
  use_product_tax_category: Use Product Tax Category
993
1003
  new:
994
1004
  new_variant: New Variant
@@ -1600,7 +1610,7 @@ en:
1600
1610
  spree/calculator:
1601
1611
  promotions: This is used to determine the promotional discount to be applied to an order, an item, or shipping charges.
1602
1612
  shipping_methods: This is used to calculate the shipping rates on a per order or per package rate.
1603
- tax_rates: This is used to calculate both sales tax (United States-style taxes) and value-added tax (VAT). Typically this calculator should be the only tax calculator required by your store.
1613
+ tax_rates: The "Default Tax" calculator is used for both sales tax (United States-style taxes) and value-added tax (VAT). Typically this calculator should be the only tax calculator required by your store. "Flat Fee" can be used for any taxes that require a flat fee be charged to the customer.
1604
1614
  spree/price:
1605
1615
  country: 'This determines in what country the price is valid.<br/>Default: Any Country'
1606
1616
  master_variant: Changing master variant prices will not change variant prices below, but will be used to populate all new variants
@@ -1631,11 +1641,13 @@ en:
1631
1641
  spree/tax_category:
1632
1642
  is_default: When checked, this tax category will be selected by default when creating new products or variants.
1633
1643
  spree/tax_rate:
1644
+ tax_rate_level: Item-level taxes will be applied as adjustments on line items and shipments. Order-level taxes will create an adjustment on the order. Care should be taken when chosing order-level adjustments as they aren't considered in refunds or in discounts. The default is item-level.
1634
1645
  validity_period: This determines the validity period within which the tax rate is valid and will be applied to eligible items. <br /> If no start date value is specified, the tax rate will be immediately available. <br /> If no expiration date value is specified, the tax rate will never expire
1635
1646
  spree/variant:
1636
1647
  deleted: Deleted Variant
1637
1648
  deleted_explanation: This variant was deleted on %{date}.
1638
1649
  deleted_explanation_with_replacement: This variant was deleted on %{date}. It has since been replaced by another with the same SKU.
1650
+ shipping_category: 'This determines what kind of shipping this variant requires.<br/> Default: Use shipping category of the product associated with this variant'
1639
1651
  tax_category: 'This determines what kind of taxation is applied to this variant.<br/> Default: Use tax category of the product associated with this variant'
1640
1652
  home: Home
1641
1653
  i18n:
@@ -1694,6 +1706,7 @@ en:
1694
1706
  iso_name: Iso Name
1695
1707
  item: Item
1696
1708
  item_description: Item Description
1709
+ item_level: Item-level
1697
1710
  item_total: Item Total
1698
1711
  item_total_rule:
1699
1712
  operators:
@@ -1872,6 +1885,7 @@ en:
1872
1885
  order_details: Order Details
1873
1886
  order_email_resent: Order Email Resent
1874
1887
  order_information: Order Information
1888
+ order_level: Order-level
1875
1889
  order_mailer:
1876
1890
  cancel_email:
1877
1891
  dear_customer: Dear Customer,
@@ -2288,7 +2302,8 @@ en:
2288
2302
  tax_category: Tax Category
2289
2303
  tax_code: Tax Code
2290
2304
  tax_included: Tax (incl.)
2291
- tax_rate_amount_explanation: Tax rates are a decimal amount to aid in calculations, (i.e. if the tax rate is 5% then enter 0.05)
2305
+ tax_rate_amount_explanation: When using the "Default Tax" calculator, the amount is treated as a decimal amount to aid in calculations. (i.e. If the tax rate is 5% then enter 0.05) If using the "Flat Fee" calculator, the amount is used for the static fee.
2306
+ tax_rate_level: Tax Rate Level
2292
2307
  tax_rates: Tax Rates
2293
2308
  taxon: Taxon
2294
2309
  taxon_attachment_removal_error: There was an error removing the attachment
@@ -0,0 +1,5 @@
1
+ class AddLevelToSpreeTaxRates < ActiveRecord::Migration[5.2]
2
+ def change
3
+ add_column :spree_tax_rates, :level, :integer, default: 0, null: false
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddShippingCategoryToSpreeVariants < ActiveRecord::Migration[5.2]
2
+ def change
3
+ add_reference :spree_variants, :shipping_category, index: true
4
+ end
5
+ end
data/db/seeds.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'thor'
4
+ shell = Thor::Base.shell.new
5
+
3
6
  %w(
4
7
  stores
5
8
  store_credit
@@ -12,6 +15,6 @@
12
15
  roles
13
16
  shipping_categories
14
17
  ).each do |seed|
15
- puts "Loading seed file: #{seed}"
18
+ shell.say_status :seed, seed
16
19
  require_relative "default/spree/#{seed}"
17
20
  end
@@ -0,0 +1,21 @@
1
+ initializer 'spree_authentication.rb', <<~RUBY
2
+ # Please replace this module with your own implementation of
3
+ # ApplicationController#spree_current_user.
4
+ #
5
+ # The current setup will allow doing guest checkouts.
6
+ ActiveSupport.on_load(:action_controller) do
7
+ def spree_current_user
8
+ # Define here your custom logic for retrieving the current user
9
+ nil
10
+ end
11
+ end
12
+
13
+ # Re-raise the original authorization error on anauthorized access
14
+ Rails.application.config.to_prepare do
15
+ Spree::BaseController.unauthorized_redirect = -> { raise "Define the behavior for unauthorized access in \#{__FILE__}." }
16
+ end
17
+ RUBY
18
+
19
+ create_file 'app/views/spree/admin/shared/_navigation_footer.html.erb', <<~ERB
20
+ <!-- Add here your login/logout links in 'app/views/spree/admin/shared/_navigation_footer.html.erb'. -->
21
+ ERB
@@ -0,0 +1,16 @@
1
+ # Skip if already in the gemfile
2
+ if Bundler.locked_gems.dependencies['solidus_auth_devise']
3
+ say_status :skipping, 'solidus_auth_devise is already in the gemfile'
4
+ else
5
+ bundle_command("add solidus_auth_devise")
6
+ end
7
+
8
+ if options[:auto_accept]
9
+ migrations_flag = options[:migrate] ? '--auto-run-migrations' : '--skip-migrations'
10
+ end
11
+
12
+ generate "solidus:auth:install #{migrations_flag}"
13
+
14
+ append_file "db/seeds.rb", <<~RUBY
15
+ Spree::Auth::Engine.load_seed
16
+ RUBY
@@ -0,0 +1,10 @@
1
+ user_class = options[:user_class] || 'Spree::User'
2
+
3
+ begin
4
+ user_class.classify.constantize
5
+ rescue NameError
6
+ say_status :error, "Can't find an existing user class named #{user_class.classify}, plese set up one before using this authentication option.", :red
7
+ abort
8
+ end
9
+
10
+ generate "spree:custom_user #{user_class.shellescape}"
@@ -0,0 +1,54 @@
1
+ # # This will unpack the solidus gem into its components without calling `bundle install`.
2
+ #
3
+ # # Nothing to do if the `solidus` gem is not there.
4
+ solidus = Bundler.locked_gems.dependencies['solidus'] or return
5
+
6
+ # Write and remove into and from a Gemfile
7
+ #
8
+ # This custom injector fixes support for path, git and custom sources,
9
+ # which is missing in bundler's upstream injector for a dependency fetched
10
+ # with `Bundler.locked_gems.dependencies`.
11
+ bundler_injector = Class.new(Bundler::Injector) do
12
+ def build_gem_lines(conservative_versioning)
13
+ @deps.map do |d|
14
+ name = d.name.dump
15
+ is_local = d.source.instance_of?(Bundler::Source::Path)
16
+ is_git = d.source.instance_of?(Bundler::Source::Git)
17
+
18
+ requirement = if is_local
19
+ ", path: \"#{d.source.path}\""
20
+ elsif is_git
21
+ ", git: \"#{d.git}\"".then { |g| d.ref ? g + ", ref: \"#{d.ref}\"" : g }
22
+ elsif conservative_versioning
23
+ ", \"#{conservative_version(@definition.specs[d.name][0])}\""
24
+ else
25
+ ", #{d.requirement.as_list.map(&:dump).join(", ")}"
26
+ end
27
+
28
+ source = ", source: \"#{d.source.remotes.join(",")}\"" unless is_local || is_git || d.source.nil?
29
+
30
+ %(gem #{name}#{requirement}#{source})
31
+ end.join("\n")
32
+ end
33
+ end
34
+
35
+ to_dependency = ->(component) do
36
+ Bundler::Dependency.new(
37
+ component,
38
+ solidus.requirement,
39
+ "source" => solidus.source,
40
+ "git" => solidus.source.try(:uri),
41
+ "ref" => solidus.source.try(:ref),
42
+ )
43
+ end
44
+
45
+ bundler_injector.inject(%w[
46
+ solidus_core
47
+ solidus_backend
48
+ solidus_api
49
+ solidus_sample
50
+ ].map(&to_dependency))
51
+
52
+ bundler_injector.remove(%w[
53
+ solidus
54
+ ])
@@ -0,0 +1,16 @@
1
+ solidus = Bundler.locked_gems.dependencies['solidus']
2
+
3
+ if Bundler.locked_gems.dependencies['solidus_frontend']
4
+ say_status :skipping, "solidus_frontend is already in the bundle", :blue
5
+ else
6
+ # `solidus_frontend` is not sourced from rubygems if the solidus gem was not.
7
+ github_solidus_frontend = '--github solidusio/solidus_frontend' unless solidus.nil? || solidus.source.is_a?(Bundler::Source::Rubygems)
8
+
9
+ bundle_command("add solidus_frontend #{github_solidus_frontend}")
10
+ end
11
+
12
+ # Disable solidus_bolt installation from solidus_frontend as it can be
13
+ # explicitly selected directly from the solidus installer.
14
+ with_env('SKIP_SOLIDUS_BOLT' => 'true') do
15
+ generate 'solidus_frontend:install'
16
+ end