solidus_core 3.2.7 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) 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/default_price.rb +0 -6
  6. data/app/models/concerns/spree/ransackable_attributes.rb +24 -4
  7. data/app/models/concerns/spree/user_methods.rb +2 -2
  8. data/app/models/spree/address.rb +1 -1
  9. data/app/models/spree/calculator/flat_fee.rb +21 -0
  10. data/app/models/spree/country.rb +1 -1
  11. data/app/models/spree/credit_card.rb +1 -1
  12. data/app/models/spree/customer_return.rb +1 -1
  13. data/app/models/spree/line_item.rb +2 -2
  14. data/app/models/spree/option_type.rb +1 -1
  15. data/app/models/spree/option_value.rb +1 -1
  16. data/app/models/spree/order/number_generator.rb +7 -1
  17. data/app/models/spree/order.rb +4 -3
  18. data/app/models/spree/order_promotion.rb +1 -1
  19. data/app/models/spree/order_updater.rb +11 -2
  20. data/app/models/spree/payment/processing.rb +58 -55
  21. data/app/models/spree/payment_method/bogus_credit_card.rb +6 -7
  22. data/app/models/spree/payment_method/simple_bogus_credit_card.rb +8 -0
  23. data/app/models/spree/payment_method.rb +16 -10
  24. data/app/models/spree/price.rb +1 -1
  25. data/app/models/spree/product.rb +3 -4
  26. data/app/models/spree/product_property.rb +1 -1
  27. data/app/models/spree/promotion/actions/free_shipping.rb +1 -0
  28. data/app/models/spree/promotion/order_adjustments_recalculator.rb +92 -0
  29. data/app/models/spree/promotion.rb +2 -2
  30. data/app/models/spree/promotion_code.rb +1 -1
  31. data/app/models/spree/property.rb +1 -1
  32. data/app/models/spree/return_authorization.rb +1 -1
  33. data/app/models/spree/shipment.rb +2 -2
  34. data/app/models/spree/state.rb +1 -1
  35. data/app/models/spree/stock_item.rb +1 -1
  36. data/app/models/spree/stock_location.rb +1 -1
  37. data/app/models/spree/stock_movement.rb +2 -2
  38. data/app/models/spree/store_credit_prioritizer.rb +17 -0
  39. data/app/models/spree/tax/tax_helpers.rb +2 -2
  40. data/app/models/spree/tax_calculator/default.rb +31 -0
  41. data/app/models/spree/tax_rate.rb +8 -1
  42. data/app/models/spree/taxon.rb +1 -1
  43. data/app/models/spree/taxonomy.rb +1 -1
  44. data/app/models/spree/user_last_url_storer/rules/authentication_rule.rb +1 -1
  45. data/app/models/spree/variant.rb +25 -5
  46. data/app/models/spree/zone.rb +1 -1
  47. data/config/locales/en.yml +13 -2
  48. data/db/migrate/20220805202442_add_level_to_spree_tax_rates.rb +5 -0
  49. data/db/migrate/20221123152807_add_shipping_category_to_spree_variants.rb +5 -0
  50. data/db/seeds.rb +4 -1
  51. data/lib/generators/solidus/install/app_templates/authentication/custom.rb +21 -0
  52. data/lib/generators/solidus/install/app_templates/authentication/devise.rb +16 -0
  53. data/lib/generators/solidus/install/app_templates/authentication/existing.rb +10 -0
  54. data/lib/generators/solidus/install/app_templates/authentication/none.rb +1 -0
  55. data/lib/generators/solidus/install/app_templates/frontend/break_down_solidus_gem.rb +54 -0
  56. data/lib/generators/solidus/install/app_templates/frontend/classic.rb +16 -0
  57. data/lib/generators/solidus/install/app_templates/frontend/none.rb +2 -0
  58. data/lib/generators/solidus/install/app_templates/frontend/starter.rb +3 -0
  59. data/lib/generators/solidus/install/app_templates/payment_method/bolt.rb +11 -9
  60. data/lib/generators/solidus/install/app_templates/payment_method/paypal.rb +8 -9
  61. data/lib/generators/solidus/install/install_generator.rb +213 -190
  62. data/lib/generators/solidus/install/templates/config/initializers/spree.rb.tt +3 -4
  63. data/lib/generators/solidus/update/update_generator.rb +2 -14
  64. data/lib/generators/spree/custom_user/custom_user_generator.rb +6 -4
  65. data/lib/generators/spree/custom_user/templates/authentication_helpers.rb.tt +2 -6
  66. data/lib/generators/spree/custom_user/templates/migration.rb.tt +7 -3
  67. data/lib/generators/spree/dummy/dummy_generator.rb +10 -8
  68. data/lib/generators/spree/dummy/templates/rails/database.yml +6 -12
  69. data/lib/spree/app_configuration.rb +23 -0
  70. data/lib/spree/bus.rb +3 -3
  71. data/lib/spree/core/controller_helpers/current_host.rb +5 -1
  72. data/lib/spree/core/product_duplicator.rb +1 -1
  73. data/lib/spree/core/search/base.rb +17 -8
  74. data/lib/spree/core/version.rb +2 -2
  75. data/lib/spree/core.rb +1 -20
  76. data/lib/spree/migrations.rb +12 -10
  77. data/lib/spree/permitted_attributes.rb +4 -1
  78. data/lib/spree/rails_compatibility.rb +0 -17
  79. data/lib/spree/testing_support/common_rake.rb +7 -6
  80. data/lib/spree/testing_support/dummy_app.rb +5 -5
  81. data/lib/spree/testing_support/factories/address_factory.rb +9 -11
  82. data/lib/spree/testing_support/factories/calculator_factory.rb +3 -0
  83. data/lib/spree/testing_support/factories/country_factory.rb +1 -2
  84. data/lib/spree/testing_support/factories/promotion_factory.rb +28 -14
  85. data/lib/spree/testing_support/factories/state_factory.rb +8 -2
  86. data/lib/spree/testing_support/factory_bot.rb +1 -1
  87. data/lib/spree/testing_support/order_walkthrough.rb +1 -1
  88. data/lib/tasks/colorado_delivery_fee.rake +28 -0
  89. data/solidus_core.gemspec +2 -2
  90. metadata +34 -23
  91. data/lib/generators/solidus/install/install_generator/bundler_context.rb +0 -105
  92. data/lib/generators/solidus/install/install_generator/install_frontend.rb +0 -61
  93. 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)) }
@@ -118,6 +123,8 @@ module Spree
118
123
  end
119
124
 
120
125
  def translation_key(_amount)
126
+ return "flat_fee" if calculator.is_a?(Spree::Calculator::FlatFee)
127
+
121
128
  key = included_in_price? ? "vat" : "sales_tax"
122
129
  key += "_with_rate" if show_rate_in_label?
123
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
@@ -817,6 +821,7 @@ en:
817
821
  line_item: "%{promotion} (%{promotion_name})"
818
822
  order: "%{promotion} (%{promotion_name})"
819
823
  tax_rates:
824
+ flat_fee: "%{name}"
820
825
  sales_tax: "%{name}"
821
826
  sales_tax_with_rate: "%{name} %{amount}"
822
827
  vat: "%{name} (Included in Price)"
@@ -993,6 +998,7 @@ en:
993
998
  pricing: Pricing
994
999
  pricing_hint: These values are populated from the product details page and can be overridden below
995
1000
  properties: Properties
1001
+ use_product_shipping_category: Use Product Shipping Category
996
1002
  use_product_tax_category: Use Product Tax Category
997
1003
  new:
998
1004
  new_variant: New Variant
@@ -1604,7 +1610,7 @@ en:
1604
1610
  spree/calculator:
1605
1611
  promotions: This is used to determine the promotional discount to be applied to an order, an item, or shipping charges.
1606
1612
  shipping_methods: This is used to calculate the shipping rates on a per order or per package rate.
1607
- 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.
1608
1614
  spree/price:
1609
1615
  country: 'This determines in what country the price is valid.<br/>Default: Any Country'
1610
1616
  master_variant: Changing master variant prices will not change variant prices below, but will be used to populate all new variants
@@ -1635,11 +1641,13 @@ en:
1635
1641
  spree/tax_category:
1636
1642
  is_default: When checked, this tax category will be selected by default when creating new products or variants.
1637
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.
1638
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
1639
1646
  spree/variant:
1640
1647
  deleted: Deleted Variant
1641
1648
  deleted_explanation: This variant was deleted on %{date}.
1642
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'
1643
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'
1644
1652
  home: Home
1645
1653
  i18n:
@@ -1698,6 +1706,7 @@ en:
1698
1706
  iso_name: Iso Name
1699
1707
  item: Item
1700
1708
  item_description: Item Description
1709
+ item_level: Item-level
1701
1710
  item_total: Item Total
1702
1711
  item_total_rule:
1703
1712
  operators:
@@ -1876,6 +1885,7 @@ en:
1876
1885
  order_details: Order Details
1877
1886
  order_email_resent: Order Email Resent
1878
1887
  order_information: Order Information
1888
+ order_level: Order-level
1879
1889
  order_mailer:
1880
1890
  cancel_email:
1881
1891
  dear_customer: Dear Customer,
@@ -2292,7 +2302,8 @@ en:
2292
2302
  tax_category: Tax Category
2293
2303
  tax_code: Tax Code
2294
2304
  tax_included: Tax (incl.)
2295
- 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
2296
2307
  tax_rates: Tax Rates
2297
2308
  taxon: Taxon
2298
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
@@ -0,0 +1,2 @@
1
+ apply "#{__dir__}/break_down_solidus_gem.rb"
2
+ run_bundle
@@ -0,0 +1,3 @@
1
+ apply "#{__dir__}/break_down_solidus_gem.rb"
2
+ run_bundle
3
+ apply 'https://github.com/solidusio/solidus_starter_frontend/raw/main/template.rb'