spree_core 3.7.14.1 → 4.0.0.beta
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/Gemfile +1 -1
- data/app/controllers/spree/base_controller.rb +0 -1
- data/app/finders/spree/taxons/find.rb +6 -5
- data/app/helpers/spree/base_helper.rb +0 -9
- data/app/helpers/spree/products_helper.rb +1 -1
- data/app/models/concerns/spree/product_scopes.rb +254 -0
- data/app/models/concerns/spree/user_address.rb +5 -2
- data/app/models/friendly_id/slug_decorator.rb +8 -2
- data/app/models/spree/ability.rb +21 -22
- data/app/models/spree/address.rb +37 -24
- data/app/models/spree/adjustment.rb +0 -10
- data/app/models/spree/app_dependencies.rb +2 -2
- data/app/models/spree/asset.rb +1 -12
- data/app/models/spree/country.rb +2 -2
- data/app/models/spree/credit_card.rb +4 -5
- data/app/models/spree/gateway/bogus.rb +1 -1
- data/app/models/spree/image.rb +8 -1
- data/app/models/spree/image/configuration/active_storage.rb +0 -2
- data/app/models/spree/order.rb +13 -78
- data/app/models/spree/order/address_book.rb +86 -0
- data/app/models/spree/order/checkout.rb +4 -22
- data/app/models/spree/order/currency_updater.rb +1 -1
- data/app/models/spree/order/store_credit.rb +0 -18
- data/app/models/spree/order_merger.rb +1 -0
- data/app/models/spree/payment.rb +4 -2
- data/app/models/spree/payment/gateway_options.rb +1 -1
- data/app/models/spree/payment/processing.rb +2 -0
- data/app/models/spree/preferences/configuration.rb +1 -1
- data/app/models/spree/preferences/preferable.rb +1 -1
- data/app/models/spree/product.rb +2 -3
- data/app/models/spree/promotion_handler/coupon.rb +2 -1
- data/app/models/spree/reimbursement_tax_calculator.rb +1 -1
- data/app/models/spree/return_item.rb +1 -1
- data/app/models/spree/return_item/eligibility_validator/default.rb +2 -0
- data/app/models/spree/return_item/eligibility_validator/{rma_required.rb → r_m_a_required.rb} +0 -0
- data/app/models/spree/shipment.rb +1 -1
- data/app/models/spree/store_credit.rb +4 -5
- data/app/models/spree/taxon_image.rb +1 -1
- data/app/models/spree/taxonomy.rb +1 -1
- data/app/services/spree/cart/add_item.rb +3 -1
- data/app/services/spree/cart/update.rb +1 -1
- data/config/locales/en.yml +15 -0
- data/db/default/spree/stores.rb +1 -0
- data/db/default/spree/zones.rb +16 -0
- data/db/migrate/20140806144901_add_type_to_reimbursement_type.rb +1 -1
- data/db/migrate/20141101231208_fix_adjustment_order_presence.rb +2 -2
- data/db/migrate/20170323151450_add_missing_unique_indexes_for_unique_attributes.rb +1 -1
- data/db/migrate/20190305121659_add_iso_and_iso3_validation_on_presence_and_uniqueness.rb +18 -0
- data/db/migrate/20190523092729_add_user_id_and_deleted_at_to_spree_addresses.rb +12 -0
- data/lib/generators/spree/dummy/dummy_generator.rb +3 -1
- data/lib/spree/core.rb +0 -2
- data/lib/spree/core/importer/order.rb +64 -103
- data/lib/spree/core/importer/product.rb +2 -2
- data/lib/spree/core/product_duplicator.rb +1 -5
- data/lib/spree/core/version.rb +1 -3
- data/lib/spree/permitted_attributes.rb +3 -1
- data/lib/spree/testing_support/ability_helpers.rb +3 -11
- data/lib/spree/testing_support/capybara_config.rb +4 -1
- data/lib/spree/testing_support/capybara_ext.rb +22 -98
- data/lib/spree/testing_support/controller_requests.rb +36 -26
- data/lib/spree/testing_support/factories/image_factory.rb +2 -6
- data/lib/spree/testing_support/factories/return_item_factory.rb +2 -2
- data/lib/spree/testing_support/factories/taxon_factory.rb +1 -1
- data/lib/spree/testing_support/i18n.rb +6 -8
- data/lib/spree/testing_support/image_helpers.rb +5 -11
- data/lib/tasks/exchanges.rake +35 -37
- data/spree_core.gemspec +11 -14
- metadata +63 -103
- data/app/models/concerns/spree/acts_as_taggable.rb +0 -11
- data/app/models/spree/image/configuration/paperclip.rb +0 -64
- data/app/models/spree/order_contents.rb +0 -54
- data/app/models/spree/product/scopes.rb +0 -250
- data/app/models/spree/tag.rb +0 -4
- data/app/models/spree/taxon_image/configuration/paperclip.rb +0 -27
- data/config/initializers/acts_as_taggable_on.rb +0 -9
- data/config/initializers/use_paperclip.rb +0 -3
- data/db/migrate/20160511071954_acts_as_taggable_on_spree_migration.rb +0 -40
- data/db/migrate/20160511072249_change_collation_for_spree_tag_names.rb +0 -9
- data/db/migrate/20160511072335_add_missing_indexes_to_spree_taggings.rb +0 -14
- data/lib/spree/core/controller_helpers/respond_with.rb +0 -67
- data/lib/spree/responder.rb +0 -44
- data/lib/spree/testing_support/factories/tag_factory.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5064fe41cb92fc49b65d326a8104d304e34e53b14cd8ad841207bef116b35464
|
4
|
+
data.tar.gz: c5288fc5c3b503961af981fe4c374e4bafcb93cb117dcd6e9be983d2c06f96e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b70df4383270e04fc466c704e7d97ca152793bb74eec3ca7f66cbe901700671255eb2d94016b66031f43f57fa40ab9817f3498a272624a383a392d998ff675ed
|
7
|
+
data.tar.gz: 2eaf71128b93b12a4502d4bdb0ef0719ab39c480968a8436b422a723d6c7c43e97c323df636259fe03891fbf924c3043fafab4dc1e505fafa13317717a4c6fbf
|
data/Gemfile
CHANGED
@@ -3,7 +3,6 @@ require_dependency 'spree/core/controller_helpers/strong_parameters'
|
|
3
3
|
|
4
4
|
class Spree::BaseController < ApplicationController
|
5
5
|
include Spree::Core::ControllerHelpers::Auth
|
6
|
-
include Spree::Core::ControllerHelpers::RespondWith
|
7
6
|
include Spree::Core::ControllerHelpers::Common
|
8
7
|
include Spree::Core::ControllerHelpers::Search
|
9
8
|
include Spree::Core::ControllerHelpers::Store
|
@@ -3,11 +3,12 @@ module Spree
|
|
3
3
|
class Find
|
4
4
|
def initialize(scope:, params:)
|
5
5
|
@scope = scope
|
6
|
-
|
7
|
-
@
|
8
|
-
@
|
9
|
-
@
|
10
|
-
@
|
6
|
+
|
7
|
+
@ids = String(params[:ids]).split(',')
|
8
|
+
@parent = params[:parent_id]
|
9
|
+
@taxonomy = params[:taxonomy_id]
|
10
|
+
@name = params[:name]
|
11
|
+
@roots = params[:roots]
|
11
12
|
end
|
12
13
|
|
13
14
|
def execute
|
@@ -79,15 +79,6 @@ module Spree
|
|
79
79
|
spree.nested_taxons_path(taxon.permalink)
|
80
80
|
end
|
81
81
|
|
82
|
-
# human readable list of variant options
|
83
|
-
def variant_options(variant, _options = {})
|
84
|
-
ActiveSupport::Deprecation.warn(<<-DEPRECATION, caller)
|
85
|
-
BaseHelper#variant_options is deprecated and will be removed in Spree 4.0.
|
86
|
-
Please use Variant#options_text or LineItem#options_text
|
87
|
-
DEPRECATION
|
88
|
-
variant.options_text
|
89
|
-
end
|
90
|
-
|
91
82
|
def frontend_available?
|
92
83
|
Spree::Core::Engine.frontend_available?
|
93
84
|
end
|
@@ -36,7 +36,7 @@ module Spree
|
|
36
36
|
else
|
37
37
|
product.description.to_s.gsub(/(.*?)\r?\n\r?\n/m, '<p>\1</p>')
|
38
38
|
end
|
39
|
-
description.blank? ? Spree.t(:product_has_no_description) :
|
39
|
+
description.blank? ? Spree.t(:product_has_no_description) : description
|
40
40
|
end
|
41
41
|
|
42
42
|
def line_item_description_text(description_text)
|
@@ -0,0 +1,254 @@
|
|
1
|
+
module Spree
|
2
|
+
module ProductScopes
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
cattr_accessor :search_scopes do
|
7
|
+
[]
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.add_search_scope(name, &block)
|
11
|
+
singleton_class.send(:define_method, name.to_sym, &block)
|
12
|
+
search_scopes << name.to_sym
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.simple_scopes
|
16
|
+
[
|
17
|
+
:ascend_by_updated_at,
|
18
|
+
:descend_by_updated_at,
|
19
|
+
:ascend_by_name,
|
20
|
+
:descend_by_name
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.add_simple_scopes(scopes)
|
25
|
+
scopes.each do |name|
|
26
|
+
# We should not define price scopes here, as they require something slightly different
|
27
|
+
next if name.to_s.include?('master_price')
|
28
|
+
|
29
|
+
parts = name.to_s.match(/(.*)_by_(.*)/)
|
30
|
+
scope(name.to_s, -> { order(Arel.sql("#{Product.quoted_table_name}.#{parts[2]} #{parts[1] == 'ascend' ? 'ASC' : 'DESC'}")) })
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.property_conditions(property)
|
35
|
+
properties = Property.table_name
|
36
|
+
case property
|
37
|
+
when String then { "#{properties}.name" => property }
|
38
|
+
when Property then { "#{properties}.id" => property.id }
|
39
|
+
else { "#{properties}.id" => property.to_i }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
add_simple_scopes simple_scopes
|
44
|
+
|
45
|
+
add_search_scope :ascend_by_master_price do
|
46
|
+
joins(master: :default_price).order("#{price_table_name}.amount ASC")
|
47
|
+
end
|
48
|
+
|
49
|
+
add_search_scope :descend_by_master_price do
|
50
|
+
joins(master: :default_price).order("#{price_table_name}.amount DESC")
|
51
|
+
end
|
52
|
+
|
53
|
+
add_search_scope :price_between do |low, high|
|
54
|
+
joins(master: :default_price).where(Price.table_name => { amount: low..high })
|
55
|
+
end
|
56
|
+
|
57
|
+
add_search_scope :master_price_lte do |price|
|
58
|
+
joins(master: :default_price).where("#{price_table_name}.amount <= ?", price)
|
59
|
+
end
|
60
|
+
|
61
|
+
add_search_scope :master_price_gte do |price|
|
62
|
+
joins(master: :default_price).where("#{price_table_name}.amount >= ?", price)
|
63
|
+
end
|
64
|
+
|
65
|
+
# This scope selects products in taxon AND all its descendants
|
66
|
+
# If you need products only within one taxon use
|
67
|
+
#
|
68
|
+
# Spree::Product.joins(:taxons).where(Taxon.table_name => { id: taxon.id })
|
69
|
+
#
|
70
|
+
# If you're using count on the result of this scope, you must use the
|
71
|
+
# `:distinct` option as well:
|
72
|
+
#
|
73
|
+
# Spree::Product.in_taxon(taxon).count(distinct: true)
|
74
|
+
#
|
75
|
+
# This is so that the count query is distinct'd:
|
76
|
+
#
|
77
|
+
# SELECT COUNT(DISTINCT "spree_products"."id") ...
|
78
|
+
#
|
79
|
+
# vs.
|
80
|
+
#
|
81
|
+
# SELECT COUNT(*) ...
|
82
|
+
add_search_scope :in_taxon do |taxon|
|
83
|
+
includes(:classifications).
|
84
|
+
where('spree_products_taxons.taxon_id' => taxon.self_and_descendants.pluck(:id)).
|
85
|
+
order('spree_products_taxons.position ASC')
|
86
|
+
end
|
87
|
+
|
88
|
+
# This scope selects products in all taxons AND all its descendants
|
89
|
+
# If you need products only within one taxon use
|
90
|
+
#
|
91
|
+
# Spree::Product.taxons_id_eq([x,y])
|
92
|
+
add_search_scope :in_taxons do |*taxons|
|
93
|
+
taxons = get_taxons(taxons)
|
94
|
+
taxons.first ? prepare_taxon_conditions(taxons) : where(nil)
|
95
|
+
end
|
96
|
+
|
97
|
+
# a scope that finds all products having property specified by name, object or id
|
98
|
+
add_search_scope :with_property do |property|
|
99
|
+
joins(:properties).where(property_conditions(property))
|
100
|
+
end
|
101
|
+
|
102
|
+
# a simple test for product with a certain property-value pairing
|
103
|
+
# note that it can test for properties with NULL values, but not for absent values
|
104
|
+
add_search_scope :with_property_value do |property, value|
|
105
|
+
joins(:properties).
|
106
|
+
where("#{ProductProperty.table_name}.value = ?", value).
|
107
|
+
where(property_conditions(property))
|
108
|
+
end
|
109
|
+
|
110
|
+
add_search_scope :with_option do |option|
|
111
|
+
option_types = OptionType.table_name
|
112
|
+
conditions = case option
|
113
|
+
when String then { "#{option_types}.name" => option }
|
114
|
+
when OptionType then { "#{option_types}.id" => option.id }
|
115
|
+
else { "#{option_types}.id" => option.to_i }
|
116
|
+
end
|
117
|
+
|
118
|
+
joins(:option_types).where(conditions)
|
119
|
+
end
|
120
|
+
|
121
|
+
add_search_scope :with_option_value do |option, value|
|
122
|
+
option_values = OptionValue.table_name
|
123
|
+
option_type_id = case option
|
124
|
+
when String then OptionType.find_by(name: option) || option.to_i
|
125
|
+
when OptionType then option.id
|
126
|
+
else option.to_i
|
127
|
+
end
|
128
|
+
|
129
|
+
conditions = "#{option_values}.name = ? AND #{option_values}.option_type_id = ?", value, option_type_id
|
130
|
+
group('spree_products.id').joins(variants_including_master: :option_values).where(conditions)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Finds all products which have either:
|
134
|
+
# 1) have an option value with the name matching the one given
|
135
|
+
# 2) have a product property with a value matching the one given
|
136
|
+
add_search_scope :with do |value|
|
137
|
+
includes(variants_including_master: :option_values).
|
138
|
+
includes(:product_properties).
|
139
|
+
where("#{OptionValue.table_name}.name = ? OR #{ProductProperty.table_name}.value = ?", value, value)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Finds all products that have a name containing the given words.
|
143
|
+
add_search_scope :in_name do |words|
|
144
|
+
like_any([:name], prepare_words(words))
|
145
|
+
end
|
146
|
+
|
147
|
+
# Finds all products that have a name or meta_keywords containing the given words.
|
148
|
+
add_search_scope :in_name_or_keywords do |words|
|
149
|
+
like_any([:name, :meta_keywords], prepare_words(words))
|
150
|
+
end
|
151
|
+
|
152
|
+
# Finds all products that have a name, description, meta_description or meta_keywords containing the given keywords.
|
153
|
+
add_search_scope :in_name_or_description do |words|
|
154
|
+
like_any([:name, :description, :meta_description, :meta_keywords], prepare_words(words))
|
155
|
+
end
|
156
|
+
|
157
|
+
# Finds all products that have the ids matching the given collection of ids.
|
158
|
+
# Alternatively, you could use find(collection_of_ids), but that would raise an exception if one product couldn't be found
|
159
|
+
add_search_scope :with_ids do |*ids|
|
160
|
+
where(id: ids)
|
161
|
+
end
|
162
|
+
|
163
|
+
# Sorts products from most popular (popularity is extracted from how many
|
164
|
+
# times use has put product in cart, not completed orders)
|
165
|
+
#
|
166
|
+
# there is alternative faster and more elegant solution, it has small drawback though,
|
167
|
+
# it doesn stack with other scopes :/
|
168
|
+
#
|
169
|
+
# joins: "LEFT OUTER JOIN (SELECT line_items.variant_id as vid, COUNT(*) as cnt FROM line_items GROUP BY line_items.variant_id) AS popularity_count ON variants.id = vid",
|
170
|
+
# order: 'COALESCE(cnt, 0) DESC'
|
171
|
+
add_search_scope :descend_by_popularity do
|
172
|
+
joins(:master).
|
173
|
+
order(%Q{
|
174
|
+
COALESCE((
|
175
|
+
SELECT
|
176
|
+
COUNT(#{LineItem.quoted_table_name}.id)
|
177
|
+
FROM
|
178
|
+
#{LineItem.quoted_table_name}
|
179
|
+
JOIN
|
180
|
+
#{Variant.quoted_table_name} AS popular_variants
|
181
|
+
ON
|
182
|
+
popular_variants.id = #{LineItem.quoted_table_name}.variant_id
|
183
|
+
WHERE
|
184
|
+
popular_variants.product_id = #{Product.quoted_table_name}.id
|
185
|
+
), 0) DESC
|
186
|
+
})
|
187
|
+
end
|
188
|
+
|
189
|
+
add_search_scope :not_deleted do
|
190
|
+
where("#{Product.quoted_table_name}.deleted_at IS NULL or #{Product.quoted_table_name}.deleted_at >= ?", Time.zone.now)
|
191
|
+
end
|
192
|
+
|
193
|
+
def self.not_discontinued(only_not_discontinued = true)
|
194
|
+
if only_not_discontinued != '0' && only_not_discontinued
|
195
|
+
where("#{Product.quoted_table_name}.discontinue_on IS NULL or #{Product.quoted_table_name}.discontinue_on >= ?", Time.zone.now)
|
196
|
+
else
|
197
|
+
all
|
198
|
+
end
|
199
|
+
end
|
200
|
+
search_scopes << :not_discontinued
|
201
|
+
# Can't use add_search_scope for this as it needs a default argument
|
202
|
+
def self.available(available_on = nil, _currency = nil)
|
203
|
+
available_on ||= Time.current
|
204
|
+
not_discontinued.joins(master: :prices).where("#{Product.quoted_table_name}.available_on <= ?", available_on)
|
205
|
+
end
|
206
|
+
search_scopes << :available
|
207
|
+
|
208
|
+
def self.active(currency = nil)
|
209
|
+
available(nil, currency)
|
210
|
+
end
|
211
|
+
search_scopes << :active
|
212
|
+
|
213
|
+
add_search_scope :taxons_name_eq do |name|
|
214
|
+
group('spree_products.id').joins(:taxons).where(Taxon.arel_table[:name].eq(name))
|
215
|
+
end
|
216
|
+
|
217
|
+
def self.price_table_name
|
218
|
+
Price.quoted_table_name
|
219
|
+
end
|
220
|
+
private_class_method :price_table_name
|
221
|
+
|
222
|
+
# specifically avoid having an order for taxon search (conflicts with main order)
|
223
|
+
def self.prepare_taxon_conditions(taxons)
|
224
|
+
ids = taxons.map { |taxon| taxon.self_and_descendants.pluck(:id) }.flatten.uniq
|
225
|
+
joins(:classifications).where(Classification.table_name => { taxon_id: ids })
|
226
|
+
end
|
227
|
+
private_class_method :prepare_taxon_conditions
|
228
|
+
|
229
|
+
# Produce an array of keywords for use in scopes.
|
230
|
+
# Always return array with at least an empty string to avoid SQL errors
|
231
|
+
def self.prepare_words(words)
|
232
|
+
return [''] if words.blank?
|
233
|
+
|
234
|
+
a = words.split(/[,\s]/).map(&:strip)
|
235
|
+
a.any? ? a : ['']
|
236
|
+
end
|
237
|
+
private_class_method :prepare_words
|
238
|
+
|
239
|
+
def self.get_taxons(*ids_or_records_or_names)
|
240
|
+
taxons = Taxon.table_name
|
241
|
+
ids_or_records_or_names.flatten.map do |t|
|
242
|
+
case t
|
243
|
+
when Integer then Taxon.find_by(id: t)
|
244
|
+
when ApplicationRecord then t
|
245
|
+
when String
|
246
|
+
Taxon.find_by(name: t) ||
|
247
|
+
Taxon.where("#{taxons}.permalink LIKE ? OR #{taxons}.permalink = ?", "%/#{t}/", "#{t}/").first
|
248
|
+
end
|
249
|
+
end.compact.flatten.uniq
|
250
|
+
end
|
251
|
+
private_class_method :get_taxons
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
@@ -13,18 +13,21 @@ module Spree
|
|
13
13
|
|
14
14
|
accepts_nested_attributes_for :ship_address, :bill_address
|
15
15
|
|
16
|
+
has_many :addresses, -> { where(deleted_at: nil).order('updated_at DESC') },
|
17
|
+
class_name: 'Spree::Address', foreign_key: :user_id
|
18
|
+
|
16
19
|
def persist_order_address(order)
|
17
20
|
b_address = bill_address || build_bill_address
|
18
21
|
b_address.attributes = order.bill_address.value_attributes
|
19
22
|
b_address.save
|
20
|
-
|
23
|
+
update(bill_address_id: b_address.id)
|
21
24
|
|
22
25
|
# May not be present if delivery step has been removed
|
23
26
|
if order.ship_address
|
24
27
|
s_address = ship_address || build_ship_address
|
25
28
|
s_address.attributes = order.ship_address.value_attributes
|
26
29
|
s_address.save
|
27
|
-
|
30
|
+
update(ship_address_id: s_address.id)
|
28
31
|
end
|
29
32
|
end
|
30
33
|
end
|
data/app/models/spree/ability.rb
CHANGED
@@ -23,15 +23,8 @@ module Spree
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def initialize(user)
|
26
|
-
|
27
|
-
|
28
|
-
# override cancan default aliasing (we don't want to differentiate between read and index)
|
26
|
+
# add cancancan aliasing
|
29
27
|
alias_action :delete, to: :destroy
|
30
|
-
alias_action :edit, to: :update
|
31
|
-
alias_action :new, to: :create
|
32
|
-
alias_action :new_action, to: :create
|
33
|
-
alias_action :show, to: :read
|
34
|
-
alias_action :index, :read, to: :display
|
35
28
|
alias_action :create, :update, :destroy, to: :modify
|
36
29
|
|
37
30
|
user ||= Spree.user_class.new
|
@@ -39,27 +32,33 @@ module Spree
|
|
39
32
|
if user.respond_to?(:has_spree_role?) && user.has_spree_role?('admin')
|
40
33
|
can :manage, :all
|
41
34
|
else
|
42
|
-
can :
|
43
|
-
can :
|
44
|
-
can :
|
35
|
+
can :read, Country
|
36
|
+
can :read, OptionType
|
37
|
+
can :read, OptionValue
|
45
38
|
can :create, Order
|
46
|
-
can :
|
39
|
+
can :show, Order do |order, token|
|
47
40
|
order.user == user || order.token && token == order.token
|
48
41
|
end
|
49
42
|
can :update, Order do |order, token|
|
50
43
|
!order.completed? && (order.user == user || order.token && token == order.token)
|
51
44
|
end
|
52
|
-
can :
|
53
|
-
|
54
|
-
|
55
|
-
can :
|
45
|
+
can :manage, Spree::Address do |address|
|
46
|
+
address.user == user
|
47
|
+
end
|
48
|
+
can :create, Spree::Address do |_address|
|
49
|
+
user.id.present?
|
50
|
+
end
|
51
|
+
can :read, CreditCard, user_id: user.id
|
52
|
+
can :read, Product
|
53
|
+
can :read, ProductProperty
|
54
|
+
can :read, Property
|
56
55
|
can :create, Spree.user_class
|
57
|
-
can [:
|
58
|
-
can :
|
59
|
-
can :
|
60
|
-
can :
|
61
|
-
can :
|
62
|
-
can :
|
56
|
+
can [:show, :update, :destroy], Spree.user_class, id: user.id
|
57
|
+
can :read, State
|
58
|
+
can :read, Taxon
|
59
|
+
can :read, Taxonomy
|
60
|
+
can :read, Variant
|
61
|
+
can :read, Zone
|
63
62
|
end
|
64
63
|
|
65
64
|
# Include any abilities registered by extensions, etc.
|
data/app/models/spree/address.rb
CHANGED
@@ -12,10 +12,12 @@ module Spree
|
|
12
12
|
|
13
13
|
# we're not freezing this on purpose so developers can extend and manage
|
14
14
|
# those attributes depending of the logic of their applications
|
15
|
-
|
15
|
+
ADDRESS_FIELDS = %w(firstname lastname company address1 address2 city state zipcode country phone)
|
16
|
+
EXCLUDED_KEYS_FOR_COMPARISION = %w(id updated_at created_at deleted_at user_id)
|
16
17
|
|
17
18
|
belongs_to :country, class_name: 'Spree::Country'
|
18
19
|
belongs_to :state, class_name: 'Spree::State', optional: true
|
20
|
+
belongs_to :user, class_name: Spree.user_class.name, optional: true
|
19
21
|
|
20
22
|
has_many :shipments, inverse_of: :address
|
21
23
|
|
@@ -49,12 +51,10 @@ module Spree
|
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
DEPRECATION
|
57
|
-
country_iso_name
|
54
|
+
def self.required_fields
|
55
|
+
Spree::Address.validators.map do |v|
|
56
|
+
v.is_a?(ActiveModel::Validations::PresenceValidator) ? v.attributes : []
|
57
|
+
end.flatten
|
58
58
|
end
|
59
59
|
|
60
60
|
def full_name
|
@@ -69,24 +69,15 @@ module Spree
|
|
69
69
|
state_name.present? ? state_name : state&.name
|
70
70
|
end
|
71
71
|
|
72
|
-
def same_as?(other)
|
73
|
-
ActiveSupport::Deprecation.warn(<<-EOS, caller)
|
74
|
-
Address#same_as? is deprecated and will be removed in Spree 4.0. Please use Address#== instead"
|
75
|
-
EOS
|
76
|
-
|
77
|
-
self == other
|
78
|
-
end
|
79
|
-
|
80
|
-
def same_as(other)
|
81
|
-
ActiveSupport::Deprecation.warn(<<-EOS, caller)
|
82
|
-
Address#same_as is deprecated and will be removed in Spree 4.0. Please use Address#== instead"
|
83
|
-
EOS
|
84
|
-
|
85
|
-
self == other
|
86
|
-
end
|
87
|
-
|
88
72
|
def to_s
|
89
|
-
|
73
|
+
[
|
74
|
+
full_name,
|
75
|
+
company,
|
76
|
+
address1,
|
77
|
+
address2,
|
78
|
+
"#{city}, #{state_text} #{zipcode}",
|
79
|
+
country.to_s
|
80
|
+
].reject(&:blank?).map { |attribute| ERB::Util.html_escape(attribute) }.join('<br/>')
|
90
81
|
end
|
91
82
|
|
92
83
|
def clone
|
@@ -129,6 +120,28 @@ module Spree
|
|
129
120
|
country ? country.zipcode_required? : true
|
130
121
|
end
|
131
122
|
|
123
|
+
def editable?
|
124
|
+
new_record? || (shipments.empty? && !Order.complete.where('bill_address_id = ? OR ship_address_id = ?', id, id).exists?)
|
125
|
+
end
|
126
|
+
|
127
|
+
def can_be_deleted?
|
128
|
+
shipments.empty? && !Order.where('bill_address_id = ? OR ship_address_id = ?', id, id).exists?
|
129
|
+
end
|
130
|
+
|
131
|
+
def check
|
132
|
+
attrs = attributes.except('id', 'updated_at', 'created_at')
|
133
|
+
the_same_address = user&.addresses&.find_by(attrs)
|
134
|
+
the_same_address || self
|
135
|
+
end
|
136
|
+
|
137
|
+
def destroy
|
138
|
+
if can_be_deleted?
|
139
|
+
super
|
140
|
+
else
|
141
|
+
update_column :deleted_at, Time.current
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
132
145
|
private
|
133
146
|
|
134
147
|
def clear_state
|