spree_core 4.2.0.rc3 → 4.2.2
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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/spree.js +19 -0
- data/app/controllers/spree/base_controller.rb +2 -1
- data/app/controllers/spree/errors_controller.rb +11 -0
- data/app/finders/spree/orders/find_current.rb +1 -1
- data/app/finders/spree/products/find.rb +14 -3
- data/app/helpers/spree/base_helper.rb +2 -1
- data/app/helpers/spree/currency_helper.rb +34 -0
- data/app/helpers/spree/locale_helper.rb +31 -0
- data/app/helpers/spree/products_helper.rb +37 -12
- data/app/models/concerns/spree/product_scopes.rb +1 -1
- data/app/models/concerns/spree/user_payment_source.rb +1 -1
- data/app/models/spree/ability.rb +45 -30
- data/app/models/spree/app_configuration.rb +2 -2
- data/app/models/spree/app_dependencies.rb +3 -1
- data/app/models/spree/credit_card.rb +4 -0
- data/app/models/spree/image.rb +14 -14
- data/app/models/spree/line_item.rb +6 -9
- data/app/models/spree/price.rb +1 -1
- data/app/models/spree/product.rb +29 -15
- data/app/models/spree/promotion/rules/option_value.rb +1 -1
- data/app/models/spree/store.rb +38 -9
- data/app/models/spree/variant.rb +8 -8
- data/app/paginators/spree/shared/paginate.rb +8 -1
- data/app/presenters/spree/variant_presenter.rb +2 -5
- data/app/services/spree/build_localized_redirect_url.rb +101 -0
- data/app/services/spree/cart/estimate_shipping_rates.rb +1 -1
- data/app/views/spree/errors/forbidden.html.erb +0 -0
- data/app/views/spree/errors/unauthorized.html.erb +0 -0
- data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +13 -2
- data/app/views/spree/shared/_purchased_items_table.html.erb +15 -6
- data/app/views/spree/shared/purchased_items_table/_adjustment.html.erb +2 -2
- data/app/views/spree/shared/purchased_items_table/_line_item.html.erb +2 -2
- data/config/locales/en.yml +8 -54
- data/config/routes.rb +2 -1
- data/db/default/spree/stores.rb +1 -0
- data/db/default/spree/zones.rb +4 -1
- data/db/migrate/20191017121054_add_supported_currencies_to_store.rb +1 -0
- data/db/migrate/20201012091259_add_filterable_column_to_spree_option_types.rb +6 -2
- data/db/migrate/20210120142527_ensure_default_locale_in_spree_stores.rb +5 -0
- data/db/migrate/20210205211040_add_supported_locales_to_spree_stores.rb +11 -0
- data/db/migrate/20210215202602_migrate_spree_i18n_globalize_config.rb +22 -0
- data/lib/generators/spree/install/install_generator.rb +9 -6
- data/lib/spree/core.rb +2 -1
- data/lib/spree/core/controller_helpers/auth.rb +3 -1
- data/lib/spree/core/controller_helpers/common.rb +6 -8
- data/lib/spree/core/controller_helpers/currency.rb +54 -0
- data/lib/spree/core/controller_helpers/locale.rb +58 -0
- data/lib/spree/core/controller_helpers/search.rb +1 -1
- data/lib/spree/core/controller_helpers/store.rb +4 -16
- data/lib/spree/core/version.rb +3 -1
- data/lib/spree/i18n.rb +12 -0
- data/lib/spree/permitted_attributes.rb +1 -1
- data/lib/spree/service_module.rb +2 -2
- data/lib/spree/testing_support/common_rake.rb +1 -1
- data/lib/spree/testing_support/controller_requests.rb +10 -10
- data/lib/spree/testing_support/factories/stock_location_factory.rb +2 -2
- data/lib/spree/testing_support/factories/store_factory.rb +1 -0
- data/lib/spree/testing_support/flatpickr_capybara.rb +101 -0
- data/lib/spree/testing_support/locale_helpers.rb +78 -0
- data/lib/spree/testing_support/next_instance_of.rb +38 -0
- data/spree_core.gemspec +1 -1
- metadata +20 -9
- data/lib/generators/spree/install/templates/config/initializers/spree_storefront.rb +0 -1
- data/lib/generators/spree/install/templates/config/spree_storefront.yml +0 -67
- data/lib/spree/core/controller_helpers/currency_helpers.rb +0 -15
@@ -57,16 +57,13 @@ module Spree
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def update_price
|
60
|
-
|
61
|
-
currency_price = Spree::Price.where(
|
62
|
-
currency: order.currency,
|
63
|
-
variant_id: variant_id
|
64
|
-
).first
|
60
|
+
currency_price = variant.price_in(order.currency)
|
65
61
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
62
|
+
self.price = if currency_price.amount.present?
|
63
|
+
currency_price.price_including_vat_for(tax_zone: tax_zone)
|
64
|
+
else
|
65
|
+
0
|
66
|
+
end
|
70
67
|
end
|
71
68
|
|
72
69
|
def copy_tax_category
|
data/app/models/spree/price.rb
CHANGED
data/app/models/spree/product.rb
CHANGED
@@ -90,6 +90,10 @@ module Spree
|
|
90
90
|
after_save :reset_nested_changes
|
91
91
|
after_touch :touch_taxons
|
92
92
|
|
93
|
+
# reset cache on save inside trasaction and transaction commit
|
94
|
+
after_save :reset_memoized_data
|
95
|
+
after_commit :reset_memoized_data
|
96
|
+
|
93
97
|
before_validation :normalize_slug, on: :update
|
94
98
|
before_validation :validate_master
|
95
99
|
|
@@ -127,6 +131,13 @@ module Spree
|
|
127
131
|
|
128
132
|
alias master_images images
|
129
133
|
|
134
|
+
def reload
|
135
|
+
%w(total_on_hand taxonomy_ids taxon_and_ancestors category category default_variant_id tax_category default_variant).each do |v|
|
136
|
+
instance_variable_set(:"@#{v}", nil)
|
137
|
+
end
|
138
|
+
super
|
139
|
+
end
|
140
|
+
|
130
141
|
# Cant use short form block syntax due to https://github.com/Netflix/fast_jsonapi/issues/259
|
131
142
|
def purchasable?
|
132
143
|
variants_including_master.any?(&:purchasable?)
|
@@ -160,7 +171,7 @@ module Spree
|
|
160
171
|
#
|
161
172
|
# @return [Spree::Variant]
|
162
173
|
def default_variant
|
163
|
-
Rails.cache.fetch(default_variant_cache_key) do
|
174
|
+
@default_variant ||= Rails.cache.fetch(default_variant_cache_key) do
|
164
175
|
if Spree::Config[:track_inventory_levels] && variants.in_stock_or_backorderable.any?
|
165
176
|
variants.in_stock_or_backorderable.first
|
166
177
|
else
|
@@ -172,11 +183,11 @@ module Spree
|
|
172
183
|
# Returns default Variant ID for Product
|
173
184
|
# @return [Integer]
|
174
185
|
def default_variant_id
|
175
|
-
default_variant.id
|
186
|
+
@default_variant_id ||= default_variant.id
|
176
187
|
end
|
177
188
|
|
178
189
|
def tax_category
|
179
|
-
super || TaxCategory.find_by(is_default: true)
|
190
|
+
@tax_category ||= super || TaxCategory.find_by(is_default: true)
|
180
191
|
end
|
181
192
|
|
182
193
|
# Adding properties and option types on creation based on a chosen prototype
|
@@ -288,11 +299,11 @@ module Spree
|
|
288
299
|
end
|
289
300
|
|
290
301
|
def total_on_hand
|
291
|
-
if any_variants_not_track_inventory?
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
302
|
+
@total_on_hand ||= if any_variants_not_track_inventory?
|
303
|
+
Float::INFINITY
|
304
|
+
else
|
305
|
+
stock_items.sum(:count_on_hand)
|
306
|
+
end
|
296
307
|
end
|
297
308
|
|
298
309
|
# Master variant may be deleted (i.e. when the product is deleted)
|
@@ -303,14 +314,11 @@ module Spree
|
|
303
314
|
end
|
304
315
|
|
305
316
|
def brand
|
306
|
-
taxons.joins(:taxonomy).find_by(spree_taxonomies: { name: Spree.t(:taxonomy_brands_name) })
|
317
|
+
@brand ||= taxons.joins(:taxonomy).find_by(spree_taxonomies: { name: Spree.t(:taxonomy_brands_name) })
|
307
318
|
end
|
308
319
|
|
309
320
|
def category
|
310
|
-
taxons.joins(:taxonomy).
|
311
|
-
where(spree_taxonomies: { name: Spree.t(:taxonomy_categories_name) }).
|
312
|
-
order(depth: :desc).
|
313
|
-
first
|
321
|
+
@category ||= taxons.joins(:taxonomy).order(depth: :desc).find_by(spree_taxonomies: { name: Spree.t(:taxonomy_categories_name) })
|
314
322
|
end
|
315
323
|
|
316
324
|
private
|
@@ -440,12 +448,12 @@ module Spree
|
|
440
448
|
end
|
441
449
|
|
442
450
|
def taxon_and_ancestors
|
443
|
-
taxons.map(&:self_and_ancestors).flatten.uniq
|
451
|
+
@taxon_and_ancestors ||= taxons.map(&:self_and_ancestors).flatten.uniq
|
444
452
|
end
|
445
453
|
|
446
454
|
# Get the taxonomy ids of all taxons assigned to this product and their ancestors.
|
447
455
|
def taxonomy_ids
|
448
|
-
taxon_and_ancestors.map(&:taxonomy_id).flatten.uniq
|
456
|
+
@taxonomy_ids ||= taxon_and_ancestors.map(&:taxonomy_id).flatten.uniq
|
449
457
|
end
|
450
458
|
|
451
459
|
# Iterate through this products taxons and taxonomies and touch their timestamps in a batch
|
@@ -471,5 +479,11 @@ module Spree
|
|
471
479
|
errors.add(:discontinue_on, :invalid_date_range)
|
472
480
|
end
|
473
481
|
end
|
482
|
+
|
483
|
+
def reset_memoized_data
|
484
|
+
%w(total_on_hand taxonomy_ids taxon_and_ancestors category default_variant_id tax_category default_variant).each do |v|
|
485
|
+
instance_variable_set(:"@#{v}", nil)
|
486
|
+
end
|
487
|
+
end
|
474
488
|
end
|
475
489
|
end
|
@@ -31,7 +31,7 @@ module Spree
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def actionable?(line_item)
|
34
|
-
product_id = line_item.
|
34
|
+
product_id = line_item.product_id
|
35
35
|
option_values_ids = line_item.variant.option_value_ids
|
36
36
|
eligible_product_ids = preferred_eligible_values.keys
|
37
37
|
eligible_value_ids = preferred_eligible_values[product_id]
|
data/app/models/spree/store.rb
CHANGED
@@ -24,6 +24,7 @@ module Spree
|
|
24
24
|
validates :mailer_logo, content_type: ['image/png', 'image/jpg', 'image/jpeg']
|
25
25
|
|
26
26
|
before_save :ensure_default_exists_and_is_unique
|
27
|
+
before_save :ensure_supported_currencies, :ensure_supported_locales
|
27
28
|
before_destroy :validate_not_default
|
28
29
|
|
29
30
|
scope :by_url, ->(url) { where('url like ?', "%#{url}%") }
|
@@ -43,28 +44,39 @@ module Spree
|
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|
47
|
+
def self.available_locales
|
48
|
+
Rails.cache.fetch('stores_available_locales') do
|
49
|
+
Spree::Store.all.map(&:supported_locales_list).flatten.uniq
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
46
53
|
def supported_currencies_list
|
47
|
-
(read_attribute(:supported_currencies).to_s.split(',') << default_currency).map(&:to_s).map do |code|
|
54
|
+
@supported_currencies_list ||= (read_attribute(:supported_currencies).to_s.split(',') << default_currency).sort.map(&:to_s).map do |code|
|
48
55
|
::Money::Currency.find(code.strip)
|
49
56
|
end.uniq.compact
|
50
57
|
end
|
51
58
|
|
59
|
+
def supported_locales_list
|
60
|
+
# TODO: add support of multiple supported languages to a single Store
|
61
|
+
@supported_locales_list ||= (read_attribute(:supported_locales).to_s.split(',') << default_locale).compact.uniq.sort
|
62
|
+
end
|
63
|
+
|
52
64
|
def unique_name
|
53
|
-
"#{name} (#{code})"
|
65
|
+
@unique_name ||= "#{name} (#{code})"
|
54
66
|
end
|
55
67
|
|
56
68
|
def formatted_url
|
57
69
|
return if url.blank?
|
58
70
|
|
59
|
-
if url.match(/http:\/\/|https:\/\//)
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
71
|
+
@formatted_url ||= if url.match(/http:\/\/|https:\/\//)
|
72
|
+
url
|
73
|
+
else
|
74
|
+
Rails.env.development? ? "http://#{url}" : "https://#{url}"
|
75
|
+
end
|
64
76
|
end
|
65
77
|
|
66
78
|
def countries_available_for_checkout
|
67
|
-
checkout_zone_or_default.try(:country_list) || Spree::Country.all
|
79
|
+
@countries_available_for_checkout ||= checkout_zone_or_default.try(:country_list) || Spree::Country.all
|
68
80
|
end
|
69
81
|
|
70
82
|
def states_available_for_checkout(country)
|
@@ -72,7 +84,7 @@ module Spree
|
|
72
84
|
end
|
73
85
|
|
74
86
|
def checkout_zone_or_default
|
75
|
-
checkout_zone || Spree::Zone.default_checkout_zone
|
87
|
+
@checkout_zone_or_default ||= checkout_zone || Spree::Zone.default_checkout_zone
|
76
88
|
end
|
77
89
|
|
78
90
|
private
|
@@ -85,6 +97,22 @@ module Spree
|
|
85
97
|
end
|
86
98
|
end
|
87
99
|
|
100
|
+
def ensure_supported_locales
|
101
|
+
return unless attributes.keys.include?('supported_locales')
|
102
|
+
return if supported_locales.present?
|
103
|
+
return if default_locale.blank?
|
104
|
+
|
105
|
+
self.supported_locales = default_locale
|
106
|
+
end
|
107
|
+
|
108
|
+
def ensure_supported_currencies
|
109
|
+
return unless attributes.keys.include?('supported_currencies')
|
110
|
+
return if supported_currencies.present?
|
111
|
+
return if default_currency.blank?
|
112
|
+
|
113
|
+
self.supported_currencies = default_currency
|
114
|
+
end
|
115
|
+
|
88
116
|
def validate_not_default
|
89
117
|
if default
|
90
118
|
errors.add(:base, :cannot_destroy_default_store)
|
@@ -94,6 +122,7 @@ module Spree
|
|
94
122
|
|
95
123
|
def clear_cache
|
96
124
|
Rails.cache.delete('default_store')
|
125
|
+
Rails.cache.delete('stores_available_locales')
|
97
126
|
end
|
98
127
|
end
|
99
128
|
end
|
data/app/models/spree/variant.rb
CHANGED
@@ -123,15 +123,15 @@ module Spree
|
|
123
123
|
end
|
124
124
|
|
125
125
|
def tax_category
|
126
|
-
if self[:tax_category_id].nil?
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
126
|
+
@tax_category ||= if self[:tax_category_id].nil?
|
127
|
+
product.tax_category
|
128
|
+
else
|
129
|
+
Spree::TaxCategory.find(self[:tax_category_id])
|
130
|
+
end
|
131
131
|
end
|
132
132
|
|
133
133
|
def options_text
|
134
|
-
Spree::Variants::OptionsPresenter.new(self).to_sentence
|
134
|
+
@options_text ||= Spree::Variants::OptionsPresenter.new(self).to_sentence
|
135
135
|
end
|
136
136
|
|
137
137
|
# Default to master name
|
@@ -192,7 +192,7 @@ module Spree
|
|
192
192
|
end
|
193
193
|
|
194
194
|
def price_in(currency)
|
195
|
-
prices.detect { |price| price.currency == currency } || prices.build(currency: currency)
|
195
|
+
prices.detect { |price| price.currency == currency&.upcase } || prices.build(currency: currency&.upcase)
|
196
196
|
end
|
197
197
|
|
198
198
|
def amount_in(currency)
|
@@ -226,7 +226,7 @@ module Spree
|
|
226
226
|
end
|
227
227
|
|
228
228
|
def compare_at_price
|
229
|
-
price_in(cost_currency).try(:compare_at_amount)
|
229
|
+
@compare_at_price ||= price_in(cost_currency).try(:compare_at_amount)
|
230
230
|
end
|
231
231
|
|
232
232
|
def name_and_sku
|
@@ -4,7 +4,14 @@ module Spree
|
|
4
4
|
def initialize(collection, params)
|
5
5
|
@collection = collection
|
6
6
|
@page = params[:page]
|
7
|
-
|
7
|
+
|
8
|
+
per_page_limit = Spree::Api::Config[:api_v2_per_page_limit]
|
9
|
+
|
10
|
+
@per_page = if params[:per_page].to_i.between?(1, per_page_limit)
|
11
|
+
params[:per_page]
|
12
|
+
else
|
13
|
+
Kaminari.config.default_per_page
|
14
|
+
end
|
8
15
|
end
|
9
16
|
|
10
17
|
def call
|
@@ -2,6 +2,7 @@ module Spree
|
|
2
2
|
class VariantPresenter
|
3
3
|
include Rails.application.routes.url_helpers
|
4
4
|
include Spree::BaseHelper
|
5
|
+
include Spree::ProductsHelper
|
5
6
|
|
6
7
|
attr_reader :current_currency, :current_price_options, :current_store
|
7
8
|
|
@@ -19,7 +20,7 @@ module Spree
|
|
19
20
|
display_price: display_price(variant),
|
20
21
|
price: variant.price_in(current_currency),
|
21
22
|
display_compare_at_price: display_compare_at_price(variant),
|
22
|
-
should_display_compare_at_price: should_display_compare_at_price(variant),
|
23
|
+
should_display_compare_at_price: should_display_compare_at_price?(variant),
|
23
24
|
is_product_available_in_currency: @is_product_available_in_currency,
|
24
25
|
backorderable: backorderable?(variant),
|
25
26
|
in_stock: in_stock?(variant),
|
@@ -75,9 +76,5 @@ module Spree
|
|
75
76
|
purchasable: variant.purchasable?
|
76
77
|
}
|
77
78
|
end
|
78
|
-
|
79
|
-
def should_display_compare_at_price(variant)
|
80
|
-
variant.compare_at_price.present? && variant.compare_at_price > variant.price
|
81
|
-
end
|
82
79
|
end
|
83
80
|
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
class BuildLocalizedRedirectUrl
|
5
|
+
prepend Spree::ServiceModule::Base
|
6
|
+
|
7
|
+
LOCALE_REGEX = /^\/[A-Za-z]{2}\/|^\/[A-Za-z]{2}-[A-Za-z]{2}\/|^\/[A-Za-z]{2}$|^\/[A-Za-z]{2}-[A-Za-z]{2}$/.freeze
|
8
|
+
|
9
|
+
SUPPORTED_PATHS_REGEX = /\/(products|t\/|cart|checkout|addresses|content)/.freeze
|
10
|
+
|
11
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
12
|
+
def call(url:, locale:, default_locale: nil)
|
13
|
+
run :initialize_url_object
|
14
|
+
run :generate_new_path
|
15
|
+
run :append_locale_param
|
16
|
+
run :build_url
|
17
|
+
end
|
18
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def initialize_url_object(url:, locale:, default_locale:)
|
23
|
+
success(
|
24
|
+
url: URI(url),
|
25
|
+
locale: locale,
|
26
|
+
default_locale_supplied: default_locale_supplied?(locale, default_locale)
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def generate_new_path(url:, locale:, default_locale_supplied:)
|
31
|
+
unless supported_path?(url.path)
|
32
|
+
return success(
|
33
|
+
url: url,
|
34
|
+
locale: locale,
|
35
|
+
path: cleanup_path(url.path),
|
36
|
+
default_locale_supplied: default_locale_supplied,
|
37
|
+
locale_added_to_path: false
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
new_path = if default_locale_supplied
|
42
|
+
maches_locale_regex?(url.path) ? url.path.gsub(LOCALE_REGEX, '/') : url.path
|
43
|
+
else
|
44
|
+
maches_locale_regex?(url.path) ? url.path.gsub(LOCALE_REGEX, "/#{locale}/") : "/#{locale}#{url.path}"
|
45
|
+
end
|
46
|
+
|
47
|
+
success(
|
48
|
+
url: url,
|
49
|
+
locale: locale,
|
50
|
+
path: cleanup_path(new_path),
|
51
|
+
default_locale_supplied: default_locale_supplied,
|
52
|
+
locale_added_to_path: true
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
def append_locale_param(url:, locale:, path:, default_locale_supplied:, locale_added_to_path:)
|
57
|
+
return success(url: url, path: path, query: url.query) if locale_added_to_path
|
58
|
+
|
59
|
+
query_params = Rack::Utils.parse_nested_query(url.query)
|
60
|
+
|
61
|
+
if default_locale_supplied
|
62
|
+
query_params.delete('locale')
|
63
|
+
else
|
64
|
+
query_params.merge!('locale' => locale)
|
65
|
+
end
|
66
|
+
|
67
|
+
query_string = query_params.any? ? query_params.to_query : nil
|
68
|
+
|
69
|
+
success(url: url, path: path, query: query_string)
|
70
|
+
end
|
71
|
+
|
72
|
+
def build_url(url:, path:, query:)
|
73
|
+
localized_url = builder_class(url).build(host: url.host, port: url.port, path: path, query: query).to_s
|
74
|
+
success(localized_url)
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def supported_path?(path)
|
80
|
+
return true if path.blank? || path == '/' || maches_locale_regex?(path)
|
81
|
+
|
82
|
+
path.match(SUPPORTED_PATHS_REGEX)
|
83
|
+
end
|
84
|
+
|
85
|
+
def maches_locale_regex?(path)
|
86
|
+
path.match(LOCALE_REGEX)[0].gsub('/', '') if path.match(LOCALE_REGEX)
|
87
|
+
end
|
88
|
+
|
89
|
+
def default_locale_supplied?(locale, default_locale)
|
90
|
+
default_locale.present? && default_locale.to_s == locale.to_s
|
91
|
+
end
|
92
|
+
|
93
|
+
def cleanup_path(path)
|
94
|
+
path.chomp('/').gsub('//', '/')
|
95
|
+
end
|
96
|
+
|
97
|
+
def builder_class(url)
|
98
|
+
url.scheme == 'http' ? URI::HTTP : URI::HTTPS
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
File without changes
|
File without changes
|
@@ -249,11 +249,9 @@
|
|
249
249
|
color: #51545E;
|
250
250
|
font-size: 15px;
|
251
251
|
line-height: 18px;
|
252
|
-
width: 62%;
|
253
252
|
}
|
254
253
|
|
255
254
|
.purchase_image {
|
256
|
-
width: 18%;
|
257
255
|
padding: 5px;
|
258
256
|
}
|
259
257
|
|
@@ -289,10 +287,20 @@
|
|
289
287
|
color: #333333;
|
290
288
|
}
|
291
289
|
|
290
|
+
.purchase_total--name {
|
291
|
+
margin: 0;
|
292
|
+
text-align: right;
|
293
|
+
color: #333333;
|
294
|
+
}
|
295
|
+
|
292
296
|
.purchase_total--label {
|
293
297
|
padding: 0 15px 0 0;
|
294
298
|
}
|
295
299
|
|
300
|
+
.purchase_total-col {
|
301
|
+
vertical-align: bottom;
|
302
|
+
}
|
303
|
+
|
296
304
|
body {
|
297
305
|
background-color: #F2F4F6;
|
298
306
|
color: #51545E;
|
@@ -402,6 +410,9 @@
|
|
402
410
|
.email-footer {
|
403
411
|
width: 100% !important;
|
404
412
|
}
|
413
|
+
.content-cell {
|
414
|
+
padding: 40px 15px !important;
|
415
|
+
}
|
405
416
|
}
|
406
417
|
|
407
418
|
@media (prefers-color-scheme: dark) {
|