spree_core 4.4.0 → 4.6.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.
- checksums.yaml +4 -4
- data/app/finders/spree/option_values/find_available.rb +1 -1
- data/app/finders/spree/product_properties/find_available.rb +1 -1
- data/app/finders/spree/products/find.rb +21 -15
- data/app/finders/spree/taxons/find.rb +11 -8
- data/app/helpers/spree/base_helper.rb +14 -11
- data/app/helpers/spree/locale_helper.rb +6 -2
- data/app/helpers/spree/products_helper.rb +9 -4
- data/app/jobs/spree/variants/remove_from_incomplete_orders_job.rb +9 -0
- data/app/jobs/spree/variants/remove_line_item_job.rb +9 -0
- data/app/models/concerns/spree/calculated_adjustments.rb +1 -1
- data/app/models/concerns/spree/display_link.rb +17 -29
- data/app/models/concerns/spree/image_methods.rb +21 -9
- data/app/models/concerns/spree/metadata.rb +2 -2
- data/app/models/concerns/spree/product_scopes.rb +34 -28
- data/app/models/concerns/spree/translatable_resource.rb +25 -0
- data/app/models/concerns/spree/translatable_resource_scopes.rb +24 -0
- data/app/models/concerns/spree/translatable_resource_slug.rb +17 -0
- data/app/models/spree/address.rb +7 -1
- data/app/models/spree/asset/support/active_storage.rb +3 -2
- data/app/models/spree/asset.rb +3 -0
- data/app/models/spree/base.rb +1 -0
- data/app/models/spree/cms_page.rb +4 -0
- data/app/models/spree/cms_section.rb +12 -12
- data/app/models/spree/cms_section_image.rb +15 -0
- data/app/models/spree/cms_section_image_one.rb +4 -0
- data/app/models/spree/cms_section_image_three.rb +4 -0
- data/app/models/spree/cms_section_image_two.rb +4 -0
- data/app/models/spree/credit_card.rb +10 -4
- data/app/models/spree/customer_return.rb +3 -0
- data/app/models/spree/data_feed/google.rb +15 -0
- data/app/models/spree/data_feed.rb +40 -0
- data/app/models/spree/digital.rb +4 -0
- data/app/models/spree/digital_link.rb +7 -0
- data/app/models/spree/fulfilment_changer.rb +1 -1
- data/app/models/spree/gateway/bogus.rb +1 -1
- data/app/models/spree/icon.rb +5 -1
- data/app/models/spree/image/configuration/active_storage.rb +5 -1
- data/app/models/spree/image.rb +3 -3
- data/app/models/spree/inventory_unit.rb +5 -2
- data/app/models/spree/legacy_user.rb +1 -2
- data/app/models/spree/line_item.rb +4 -1
- data/app/models/spree/linkable/homepage.rb +3 -0
- data/app/models/spree/linkable/uri.rb +3 -0
- data/app/models/spree/log_entry.rb +9 -1
- data/app/models/spree/menu.rb +3 -0
- data/app/models/spree/menu_item.rb +7 -11
- data/app/models/spree/option_type.rb +8 -0
- data/app/models/spree/option_value.rb +9 -0
- data/app/models/spree/order/address_book.rb +1 -0
- data/app/models/spree/order.rb +12 -3
- data/app/models/spree/order_merger.rb +1 -1
- data/app/models/spree/payment/processing.rb +1 -1
- data/app/models/spree/payment.rb +7 -1
- data/app/models/spree/payment_capture_event.rb +4 -0
- data/app/models/spree/payment_method/store_credit.rb +1 -1
- data/app/models/spree/payment_method.rb +3 -0
- data/app/models/spree/payment_source.rb +10 -0
- data/app/models/spree/preference.rb +4 -0
- data/app/models/spree/price.rb +3 -0
- data/app/models/spree/product.rb +97 -24
- data/app/models/spree/product_property.rb +13 -3
- data/app/models/spree/promotion/rules/option_value.rb +2 -2
- data/app/models/spree/promotion.rb +6 -0
- data/app/models/spree/promotion_rule.rb +1 -1
- data/app/models/spree/promotion_rule_user.rb +1 -1
- data/app/models/spree/property.rb +10 -1
- data/app/models/spree/prototype.rb +3 -0
- data/app/models/spree/refund.rb +8 -0
- data/app/models/spree/reimbursement.rb +3 -0
- data/app/models/spree/return_authorization.rb +3 -0
- data/app/models/spree/return_item.rb +4 -0
- data/app/models/spree/role.rb +1 -1
- data/app/models/spree/role_user.rb +1 -1
- data/app/models/spree/shipment.rb +8 -1
- data/app/models/spree/shipping_category.rb +3 -0
- data/app/models/spree/shipping_method.rb +6 -0
- data/app/models/spree/state_change.rb +1 -1
- data/app/models/spree/stock/availability_validator.rb +9 -3
- data/app/models/spree/stock/content_item.rb +1 -1
- data/app/models/spree/stock/quantifier.rb +1 -1
- data/app/models/spree/stock_item.rb +5 -0
- data/app/models/spree/stock_location.rb +19 -5
- data/app/models/spree/stock_movement.rb +4 -0
- data/app/models/spree/stock_transfer.rb +3 -0
- data/app/models/spree/store.rb +39 -15
- data/app/models/spree/store_credit.rb +4 -1
- data/app/models/spree/store_favicon_image.rb +17 -0
- data/app/models/spree/store_logo.rb +9 -0
- data/app/models/spree/store_mailer_logo.rb +13 -0
- data/app/models/spree/tax_category.rb +6 -0
- data/app/models/spree/tax_rate.rb +6 -1
- data/app/models/spree/taxon.rb +26 -7
- data/app/models/spree/taxon_image/configuration/active_storage.rb +5 -1
- data/app/models/spree/taxon_image.rb +3 -2
- data/app/models/spree/taxonomy.rb +8 -1
- data/app/models/spree/variant.rb +47 -21
- data/app/models/spree/wished_item.rb +4 -0
- data/app/models/spree/wishlist.rb +4 -1
- data/app/models/spree/zone.rb +3 -0
- data/app/services/spree/addresses/create.rb +1 -1
- data/app/services/spree/addresses/update.rb +7 -2
- data/app/services/spree/cart/remove_line_item.rb +1 -0
- data/app/services/spree/data_feeds/google/optional_attributes.rb +23 -0
- data/app/services/spree/data_feeds/google/optional_sub_attributes.rb +21 -0
- data/app/services/spree/data_feeds/google/products_list.rb +14 -0
- data/app/services/spree/data_feeds/google/required_attributes.rb +67 -0
- data/app/services/spree/data_feeds/google/rss.rb +107 -0
- data/app/services/spree/variants/remove_line_items.rb +15 -0
- data/app/sorters/spree/products/sort.rb +23 -0
- data/brakeman.ignore +326 -18
- data/config/initializers/friendly_id.rb +2 -0
- data/config/initializers/mobility.rb +18 -0
- data/config/locales/en.yml +6 -2
- data/config/routes.rb +43 -0
- data/db/migrate/20211201202851_update_linkable_resource_types.rb +10 -0
- data/db/migrate/20211203082008_add_settings_to_payment_methods.rb +11 -0
- data/db/migrate/20211229162122_disable_propagate_all_variants_by_default.rb +5 -0
- data/db/migrate/20220103082046_add_status_and_make_active_at_to_spree_products.rb +7 -0
- data/db/migrate/20220106230929_add_internal_note_to_spree_orders.rb +5 -0
- data/db/migrate/20220113052823_create_payment_sources.rb +22 -0
- data/db/migrate/20220117100333_add_make_active_at_to_spree_products.rb +17 -0
- data/db/migrate/20220120092821_add_metadata_to_spree_tax_rates.rb +13 -0
- data/db/migrate/20220201103922_add_first_name_and_last_name_to_spree_users.rb +9 -0
- data/db/migrate/20220222083546_add_barcode_to_spree_variants.rb +6 -0
- data/db/migrate/20220329113557_fix_cms_pages_unique_indexes.rb +8 -0
- data/db/migrate/20220613133029_add_metadata_to_spree_stock_items.rb +13 -0
- data/db/migrate/20220706112554_create_product_name_and_description_translations_for_mobility_table_backend.rb +27 -0
- data/db/migrate/20220715083542_create_spree_product_translations_for_mobility.rb +7 -0
- data/db/migrate/20220715120222_change_product_name_null_to_true.rb +5 -0
- data/db/migrate/20220718100743_create_spree_taxon_name_and_description_translations_for_mobility_table_backend.rb +27 -0
- data/db/migrate/20220718100948_change_taxon_name_null_to_true.rb +5 -0
- data/db/migrate/20220802070609_add_locale_to_friendly_id_slugs.rb +11 -0
- data/db/migrate/20220802073225_create_spree_product_slug_translations_for_mobility_table_backend.rb +5 -0
- data/db/migrate/20220804073928_transfer_data_to_translatable_tables.rb +66 -0
- data/db/migrate/20221215151408_add_selected_locale_to_spree_users.rb +8 -0
- data/db/migrate/20221219123957_add_deleted_at_to_product_translations.rb +6 -0
- data/db/migrate/20221220133432_add_uniqueness_constraint_to_product_translations.rb +5 -0
- data/db/migrate/20221229132350_create_spree_data_feed_settings.rb +14 -0
- data/db/migrate/20230103144439_create_option_type_translations.rb +26 -0
- data/db/migrate/20230103151034_create_option_value_translations.rb +26 -0
- data/db/migrate/20230109084253_create_product_property_translations.rb +25 -0
- data/db/migrate/20230109094907_transfer_options_data_to_translatable_tables.rb +58 -0
- data/db/migrate/20230109105943_create_property_translations.rb +26 -0
- data/db/migrate/20230109110840_transfer_property_data_to_translatable_tables.rb +59 -0
- data/db/migrate/20230110142344_backfill_friendly_id_slug_locale.rb +15 -0
- data/db/migrate/20230111121534_add_additional_taxon_translation_fields.rb +8 -0
- data/db/migrate/20230111122511_transfer_product_and_taxon_data_to_translatable_tables.rb +82 -0
- data/db/migrate/20230117115531_create_taxonomy_translations.rb +24 -0
- data/db/migrate/20230117120430_allow_null_taxonomy_name.rb +5 -0
- data/db/migrate/20230117121303_transfer_taxonomy_data_to_translatable_tables.rb +11 -0
- data/db/migrate/20230210142732_create_store_translations.rb +50 -0
- data/db/migrate/20230210142849_transfer_store_data_to_translatable_tables.rb +11 -0
- data/db/migrate/20230210230434_add_deleted_at_to_store_translations.rb +6 -0
- data/db/migrate/20230415155958_rename_data_feed_settings_table.rb +5 -0
- data/db/migrate/20230415160828_rename_data_feed_table_columns.rb +7 -0
- data/db/migrate/20230415161226_add_indexes_to_data_feeds_table.rb +5 -0
- data/db/migrate/20230512094803_rename_data_feeds_column_provider_to_type.rb +5 -0
- data/db/migrate/20230514162157_add_index_on_locale_and_permalink_to_spree_taxons.rb +5 -0
- data/lib/friendly_id/paranoia.rb +4 -0
- data/lib/generators/spree/dummy/dummy_generator.rb +13 -2
- data/lib/generators/spree/dummy/templates/package.json +12 -0
- data/lib/generators/spree/dummy/templates/rails/test.rb +2 -0
- data/lib/spree/core/configuration.rb +91 -0
- data/lib/spree/core/controller_helpers/auth.rb +3 -1
- data/lib/spree/core/controller_helpers/currency.rb +7 -5
- data/lib/spree/core/controller_helpers/locale.rb +34 -8
- data/lib/spree/core/controller_helpers/order.rb +4 -2
- data/lib/spree/core/controller_helpers/search.rb +1 -1
- data/lib/spree/core/controller_helpers/store.rb +5 -3
- data/lib/spree/core/dependencies.rb +106 -0
- data/lib/spree/core/dependencies_helper.rb +19 -0
- data/lib/spree/core/engine.rb +53 -38
- data/{app/models/spree → lib/spree/core}/preferences/configuration.rb +3 -0
- data/{app/models/spree → lib/spree/core}/preferences/preferable.rb +3 -0
- data/lib/spree/core/product_duplicator.rb +1 -1
- data/lib/spree/core/product_filters.rb +7 -4
- data/lib/spree/core/search/base.rb +10 -6
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/core.rb +27 -5
- data/lib/spree/permitted_attributes.rb +9 -7
- data/lib/spree/testing_support/common_rake.rb +1 -0
- data/lib/spree/testing_support/factories/favicon_image_factory.rb +9 -0
- data/lib/spree/testing_support/factories/google_data_feed_factory.rb +8 -0
- data/lib/spree/testing_support/factories/icon_factory.rb +3 -1
- data/lib/spree/testing_support/factories/image_factory.rb +3 -1
- data/lib/spree/testing_support/factories/menu_item_factory.rb +1 -1
- data/lib/spree/testing_support/factories/order_factory.rb +2 -1
- data/lib/spree/testing_support/factories/product_factory.rb +12 -1
- data/lib/spree/testing_support/factories/product_property_factory.rb +1 -0
- data/lib/spree/testing_support/factories/product_translation_factory.rb +6 -0
- data/lib/spree/testing_support/factories/refund_factory.rb +1 -1
- data/lib/spree/testing_support/factories/return_authorization_factory.rb +1 -1
- data/lib/spree/testing_support/factories/role_factory.rb +1 -1
- data/lib/spree/testing_support/factories/shipping_category_factory.rb +1 -1
- data/lib/spree/testing_support/factories/stock_location_factory.rb +3 -2
- data/lib/spree/testing_support/factories/store_factory.rb +2 -1
- data/lib/spree/testing_support/factories/taxon_image_factory.rb +3 -1
- data/lib/spree/testing_support/factories/user_factory.rb +4 -0
- data/lib/spree/testing_support/factories/variant_factory.rb +8 -0
- data/lib/spree/translation_migrations.rb +40 -0
- data/lib/spree_core.rb +2 -1
- data/lib/tasks/core.rake +12 -0
- data/spree_core.gemspec +5 -3
- metadata +152 -52
- data/app/models/friendly_id/slug_decorator.rb +0 -9
- data/app/models/spree/app_configuration.rb +0 -86
- data/lib/friendly_id/slug_rails5_patch.rb +0 -11
- data/lib/spree/core/app_dependencies.rb +0 -126
- /data/{app/models/spree → lib/spree/core}/preferences/preferable_class_methods.rb +0 -0
- /data/{app/models/spree → lib/spree/core}/preferences/scoped_store.rb +0 -0
- /data/{app/models/spree → lib/spree/core}/preferences/store.rb +0 -0
data/app/models/spree/price.rb
CHANGED
data/app/models/spree/product.rb
CHANGED
|
@@ -23,20 +23,37 @@ module Spree
|
|
|
23
23
|
extend FriendlyId
|
|
24
24
|
include ProductScopes
|
|
25
25
|
include MultiStoreResource
|
|
26
|
+
include TranslatableResource
|
|
27
|
+
include TranslatableResourceSlug
|
|
26
28
|
include MemoizedData
|
|
27
29
|
include Metadata
|
|
30
|
+
if defined?(Spree::Webhooks)
|
|
31
|
+
include Spree::Webhooks::HasWebhooks
|
|
32
|
+
end
|
|
33
|
+
if defined?(Spree::VendorConcern)
|
|
34
|
+
include Spree::VendorConcern
|
|
35
|
+
end
|
|
28
36
|
|
|
29
|
-
MEMOIZED_METHODS = %w
|
|
37
|
+
MEMOIZED_METHODS = %w[total_on_hand taxonomy_ids taxon_and_ancestors category
|
|
30
38
|
default_variant_id tax_category default_variant
|
|
31
|
-
purchasable? in_stock? backorderable?
|
|
39
|
+
purchasable? in_stock? backorderable?]
|
|
40
|
+
|
|
41
|
+
TRANSLATABLE_FIELDS = %i[name description slug meta_description meta_keywords meta_title].freeze
|
|
42
|
+
translates(*TRANSLATABLE_FIELDS)
|
|
32
43
|
|
|
33
|
-
|
|
44
|
+
self::Translation.class_eval do
|
|
45
|
+
acts_as_paranoid
|
|
46
|
+
# deleted translation values also need to be accessible for index views listing deleted resources
|
|
47
|
+
default_scope { unscope(where: :deleted_at) }
|
|
48
|
+
end
|
|
34
49
|
|
|
50
|
+
friendly_id :slug_candidates, use: [:history, :mobility]
|
|
35
51
|
acts_as_paranoid
|
|
52
|
+
auto_strip_attributes :name
|
|
36
53
|
|
|
37
54
|
# we need to have this callback before any dependent: :destroy associations
|
|
38
55
|
# https://github.com/rails/rails/issues/3458
|
|
39
|
-
before_destroy :
|
|
56
|
+
before_destroy :ensure_not_in_complete_orders
|
|
40
57
|
|
|
41
58
|
has_many :product_option_types, dependent: :destroy, inverse_of: :product
|
|
42
59
|
has_many :option_types, through: :product_option_types
|
|
@@ -118,7 +135,7 @@ module Spree
|
|
|
118
135
|
end
|
|
119
136
|
|
|
120
137
|
validates :slug, presence: true, uniqueness: { allow_blank: true, case_sensitive: true, scope: spree_base_uniqueness_scope }
|
|
121
|
-
validate :
|
|
138
|
+
validate :discontinue_on_must_be_later_than_make_active_at, if: -> { make_active_at && discontinue_on }
|
|
122
139
|
|
|
123
140
|
scope :for_store, ->(store) { joins(:store_products).where(StoreProduct.table_name => { store_id: store.id }) }
|
|
124
141
|
|
|
@@ -129,11 +146,11 @@ module Spree
|
|
|
129
146
|
alias options product_option_types
|
|
130
147
|
|
|
131
148
|
self.whitelisted_ransackable_associations = %w[taxons stores variants_including_master master variants]
|
|
132
|
-
self.whitelisted_ransackable_attributes = %w[description name slug discontinue_on]
|
|
149
|
+
self.whitelisted_ransackable_attributes = %w[description name slug discontinue_on status]
|
|
133
150
|
self.whitelisted_ransackable_scopes = %w[not_discontinued search_by_name in_taxon price_between]
|
|
134
151
|
|
|
135
152
|
[
|
|
136
|
-
:sku, :price, :currency, :weight, :height, :width, :depth, :is_master,
|
|
153
|
+
:sku, :barcode, :price, :currency, :weight, :height, :width, :depth, :is_master,
|
|
137
154
|
:cost_currency, :price_in, :amount_in, :cost_price, :compare_at_price, :compare_at_amount_in
|
|
138
155
|
].each do |method_name|
|
|
139
156
|
delegate method_name, :"#{method_name}=", to: :find_or_build_master
|
|
@@ -144,6 +161,23 @@ module Spree
|
|
|
144
161
|
|
|
145
162
|
alias master_images images
|
|
146
163
|
|
|
164
|
+
state_machine :status, initial: :draft do
|
|
165
|
+
event :activate do
|
|
166
|
+
transition to: :active
|
|
167
|
+
end
|
|
168
|
+
after_transition to: :active, do: :after_activate
|
|
169
|
+
|
|
170
|
+
event :archive do
|
|
171
|
+
transition to: :archived
|
|
172
|
+
end
|
|
173
|
+
after_transition to: :archived, do: :after_archive
|
|
174
|
+
|
|
175
|
+
event :draft do
|
|
176
|
+
transition to: :draft
|
|
177
|
+
end
|
|
178
|
+
after_transition to: :draft, do: :after_draft
|
|
179
|
+
end
|
|
180
|
+
|
|
147
181
|
# Can't use short form block syntax due to https://github.com/Netflix/fast_jsonapi/issues/259
|
|
148
182
|
def purchasable?
|
|
149
183
|
default_variant.purchasable? || variants.any?(&:purchasable?)
|
|
@@ -225,14 +259,16 @@ module Spree
|
|
|
225
259
|
end
|
|
226
260
|
|
|
227
261
|
# determine if product is available.
|
|
228
|
-
# deleted products and products with
|
|
262
|
+
# deleted products and products with status different than active
|
|
229
263
|
# are not available
|
|
230
264
|
def available?
|
|
231
|
-
|
|
265
|
+
active? && !deleted?
|
|
232
266
|
end
|
|
233
267
|
|
|
234
268
|
def discontinue!
|
|
235
|
-
|
|
269
|
+
self.discontinue_on = Time.current
|
|
270
|
+
self.status = 'archived'
|
|
271
|
+
save(validate: false)
|
|
236
272
|
end
|
|
237
273
|
|
|
238
274
|
def discontinued?
|
|
@@ -280,14 +316,26 @@ module Spree
|
|
|
280
316
|
end
|
|
281
317
|
|
|
282
318
|
def property(property_name)
|
|
283
|
-
product_properties.joins(:property).
|
|
319
|
+
product_properties.joins(:property).
|
|
320
|
+
join_translation_table(Property).
|
|
321
|
+
find_by(Property.translation_table_alias => { name: property_name }).try(:value)
|
|
284
322
|
end
|
|
285
323
|
|
|
286
324
|
def set_property(property_name, property_value, property_presentation = property_name)
|
|
287
325
|
ApplicationRecord.transaction do
|
|
288
|
-
#
|
|
289
|
-
property = Property.
|
|
290
|
-
|
|
326
|
+
# Manual first_or_create to work around Mobility bug
|
|
327
|
+
property = if Property.where(name: property_name).exists?
|
|
328
|
+
Property.where(name: property_name).first
|
|
329
|
+
else
|
|
330
|
+
Property.create(name: property_name, presentation: property_presentation)
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
product_property = if ProductProperty.where(product: self, property: property).exists?
|
|
334
|
+
ProductProperty.where(product: self, property: property).first
|
|
335
|
+
else
|
|
336
|
+
ProductProperty.create(product: self, property: property)
|
|
337
|
+
end
|
|
338
|
+
|
|
291
339
|
product_property.value = property_value
|
|
292
340
|
product_property.save!
|
|
293
341
|
end
|
|
@@ -296,7 +344,7 @@ module Spree
|
|
|
296
344
|
def total_on_hand
|
|
297
345
|
@total_on_hand ||= Rails.cache.fetch(['product-total-on-hand', cache_key_with_version]) do
|
|
298
346
|
if any_variants_not_track_inventory?
|
|
299
|
-
|
|
347
|
+
BigDecimal::INFINITY
|
|
300
348
|
else
|
|
301
349
|
stock_items.sum(:count_on_hand)
|
|
302
350
|
end
|
|
@@ -311,11 +359,16 @@ module Spree
|
|
|
311
359
|
end
|
|
312
360
|
|
|
313
361
|
def brand
|
|
314
|
-
@brand ||= taxons.joins(:taxonomy).
|
|
362
|
+
@brand ||= taxons.joins(:taxonomy).
|
|
363
|
+
join_translation_table(Taxonomy).
|
|
364
|
+
find_by(Taxonomy.translation_table_alias => { name: Spree.t(:taxonomy_brands_name) })
|
|
315
365
|
end
|
|
316
366
|
|
|
317
367
|
def category
|
|
318
|
-
@category ||= taxons.joins(:taxonomy).
|
|
368
|
+
@category ||= taxons.joins(:taxonomy).
|
|
369
|
+
join_translation_table(Taxonomy).
|
|
370
|
+
order(depth: :desc).
|
|
371
|
+
find_by(Taxonomy.translation_table_alias => { name: Spree.t(:taxonomy_categories_name) })
|
|
319
372
|
end
|
|
320
373
|
|
|
321
374
|
def taxons_for_store(store)
|
|
@@ -327,17 +380,21 @@ module Spree
|
|
|
327
380
|
def any_variant_in_stock_or_backorderable?
|
|
328
381
|
if variants.any?
|
|
329
382
|
variants_including_master.in_stock_or_backorderable.exists?
|
|
330
|
-
else
|
|
383
|
+
else
|
|
331
384
|
master.in_stock_or_backorderable?
|
|
332
385
|
end
|
|
333
386
|
end
|
|
334
387
|
|
|
388
|
+
def digital?
|
|
389
|
+
shipping_category&.name == I18n.t('spree.seed.shipping.categories.digital')
|
|
390
|
+
end
|
|
391
|
+
|
|
335
392
|
private
|
|
336
393
|
|
|
337
394
|
def add_associations_from_prototype
|
|
338
395
|
if prototype_id && prototype = Spree::Prototype.find_by(id: prototype_id)
|
|
339
396
|
prototype.properties.each do |property|
|
|
340
|
-
product_properties.create(property: property)
|
|
397
|
+
product_properties.create(property: property, value: 'Placeholder')
|
|
341
398
|
end
|
|
342
399
|
self.option_types = prototype.option_types
|
|
343
400
|
self.taxons = prototype.taxons
|
|
@@ -385,7 +442,11 @@ module Spree
|
|
|
385
442
|
|
|
386
443
|
def punch_slug
|
|
387
444
|
# punch slug with date prefix to allow reuse of original
|
|
388
|
-
|
|
445
|
+
return if frozen?
|
|
446
|
+
|
|
447
|
+
translations.with_deleted.each do |t|
|
|
448
|
+
t.update_column :slug, "#{Time.current.to_i}_#{t.slug}"[0..254]
|
|
449
|
+
end
|
|
389
450
|
end
|
|
390
451
|
|
|
391
452
|
def update_slug_history
|
|
@@ -473,8 +534,8 @@ module Spree
|
|
|
473
534
|
Spree::Taxonomy.where(id: taxonomy_ids).update_all(updated_at: Time.current)
|
|
474
535
|
end
|
|
475
536
|
|
|
476
|
-
def
|
|
477
|
-
if
|
|
537
|
+
def ensure_not_in_complete_orders
|
|
538
|
+
if orders.complete.any?
|
|
478
539
|
errors.add(:base, :cannot_destroy_if_attached_to_line_items)
|
|
479
540
|
throw(:abort)
|
|
480
541
|
end
|
|
@@ -485,8 +546,8 @@ module Spree
|
|
|
485
546
|
removed_classifications.each &:remove_from_list
|
|
486
547
|
end
|
|
487
548
|
|
|
488
|
-
def
|
|
489
|
-
if discontinue_on <
|
|
549
|
+
def discontinue_on_must_be_later_than_make_active_at
|
|
550
|
+
if discontinue_on < make_active_at
|
|
490
551
|
errors.add(:discontinue_on, :invalid_date_range)
|
|
491
552
|
end
|
|
492
553
|
end
|
|
@@ -502,5 +563,17 @@ module Spree
|
|
|
502
563
|
def downcase_slug
|
|
503
564
|
slug&.downcase!
|
|
504
565
|
end
|
|
566
|
+
|
|
567
|
+
def after_activate
|
|
568
|
+
# this method is prepended in api/ to queue Webhooks requests
|
|
569
|
+
end
|
|
570
|
+
|
|
571
|
+
def after_archive
|
|
572
|
+
# this method is prepended in api/ to queue Webhooks requests
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
def after_draft
|
|
576
|
+
# this method is prepended in api/ to queue Webhooks requests
|
|
577
|
+
end
|
|
505
578
|
end
|
|
506
579
|
end
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class ProductProperty < Spree::Base
|
|
3
3
|
include Spree::FilterParam
|
|
4
|
+
include TranslatableResource
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
TRANSLATABLE_FIELDS = %i[value filter_param].freeze
|
|
7
|
+
translates(*TRANSLATABLE_FIELDS)
|
|
8
|
+
|
|
9
|
+
self::Translation.class_eval do
|
|
10
|
+
auto_strip_attributes :value
|
|
11
|
+
end
|
|
6
12
|
|
|
7
13
|
acts_as_list scope: :product
|
|
8
14
|
|
|
@@ -13,6 +19,7 @@ module Spree
|
|
|
13
19
|
|
|
14
20
|
validates :property, presence: true
|
|
15
21
|
validates :property_id, uniqueness: { scope: :product_id }
|
|
22
|
+
validates :value, presence: true
|
|
16
23
|
|
|
17
24
|
default_scope { order(:position) }
|
|
18
25
|
|
|
@@ -30,8 +37,11 @@ module Spree
|
|
|
30
37
|
`ProductProperty#property_name=` is deprecated and will be removed in Spree 5.0.
|
|
31
38
|
DEPRECATION
|
|
32
39
|
if name.present?
|
|
33
|
-
|
|
34
|
-
|
|
40
|
+
self.property = if Property.where(name: name).exists?
|
|
41
|
+
Property.where(name: name).first
|
|
42
|
+
else
|
|
43
|
+
Property.create(name: name, presentation: name)
|
|
44
|
+
end
|
|
35
45
|
end
|
|
36
46
|
end
|
|
37
47
|
|
|
@@ -4,9 +4,9 @@ module Spree
|
|
|
4
4
|
module OptionValueWithNumerificationSupport
|
|
5
5
|
def preferred_eligible_values
|
|
6
6
|
values = super || {}
|
|
7
|
-
Hash[values.keys.
|
|
7
|
+
Hash[values.keys.zip(
|
|
8
8
|
values.values.map do |v|
|
|
9
|
-
(v.is_a?(Array) ? v : v.split(','))
|
|
9
|
+
(v.is_a?(Array) ? v : v.split(','))
|
|
10
10
|
end
|
|
11
11
|
)]
|
|
12
12
|
end
|
|
@@ -2,6 +2,12 @@ module Spree
|
|
|
2
2
|
class Promotion < Spree::Base
|
|
3
3
|
include MultiStoreResource
|
|
4
4
|
include Metadata
|
|
5
|
+
if defined?(Spree::Webhooks)
|
|
6
|
+
include Spree::Webhooks::HasWebhooks
|
|
7
|
+
end
|
|
8
|
+
if defined?(Spree::Security::Promotions)
|
|
9
|
+
include Spree::Security::Promotions
|
|
10
|
+
end
|
|
5
11
|
|
|
6
12
|
MATCH_POLICIES = %w(all any)
|
|
7
13
|
UNACTIVATABLE_ORDER_STATES = ['complete', 'awaiting_return', 'returned']
|
|
@@ -35,7 +35,7 @@ module Spree
|
|
|
35
35
|
|
|
36
36
|
def unique_per_promotion
|
|
37
37
|
if Spree::PromotionRule.exists?(promotion_id: promotion_id, type: self.class.name)
|
|
38
|
-
errors
|
|
38
|
+
errors.add(:base, 'Promotion already contains this rule type')
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class PromotionRuleUser < Spree::Base
|
|
3
3
|
belongs_to :promotion_rule, class_name: 'Spree::PromotionRule'
|
|
4
|
-
belongs_to :user, class_name: Spree.user_class
|
|
4
|
+
belongs_to :user, class_name: "::#{Spree.user_class}"
|
|
5
5
|
|
|
6
6
|
validates :user, :promotion_rule, presence: true
|
|
7
7
|
validates :user_id, uniqueness: { scope: :promotion_rule_id }, allow_nil: true
|
|
@@ -2,8 +2,17 @@ module Spree
|
|
|
2
2
|
class Property < Spree::Base
|
|
3
3
|
include Spree::FilterParam
|
|
4
4
|
include Metadata
|
|
5
|
+
include TranslatableResource
|
|
6
|
+
if defined?(Spree::Webhooks)
|
|
7
|
+
include Spree::Webhooks::HasWebhooks
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
TRANSLATABLE_FIELDS = %i[name presentation filter_param].freeze
|
|
11
|
+
translates(*TRANSLATABLE_FIELDS)
|
|
5
12
|
|
|
6
|
-
|
|
13
|
+
self::Translation.class_eval do
|
|
14
|
+
auto_strip_attributes :name, :presentation
|
|
15
|
+
end
|
|
7
16
|
|
|
8
17
|
has_many :property_prototypes, class_name: 'Spree::PropertyPrototype'
|
|
9
18
|
has_many :prototypes, through: :property_prototypes, class_name: 'Spree::Prototype'
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class Prototype < Spree::Base
|
|
3
3
|
include Metadata
|
|
4
|
+
if defined?(Spree::Webhooks)
|
|
5
|
+
include Spree::Webhooks::HasWebhooks
|
|
6
|
+
end
|
|
4
7
|
|
|
5
8
|
has_many :property_prototypes, class_name: 'Spree::PropertyPrototype'
|
|
6
9
|
has_many :properties, through: :property_prototypes, class_name: 'Spree::Property'
|
data/app/models/spree/refund.rb
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class Refund < Spree::Base
|
|
3
3
|
include Metadata
|
|
4
|
+
if defined?(Spree::Webhooks)
|
|
5
|
+
include Spree::Webhooks::HasWebhooks
|
|
6
|
+
end
|
|
7
|
+
if defined?(Spree::Security::Refunds)
|
|
8
|
+
include Spree::Security::Refunds
|
|
9
|
+
end
|
|
4
10
|
|
|
5
11
|
with_options inverse_of: :refunds do
|
|
6
12
|
belongs_to :payment
|
|
@@ -23,6 +29,8 @@ module Spree
|
|
|
23
29
|
|
|
24
30
|
scope :non_reimbursement, -> { where(reimbursement_id: nil) }
|
|
25
31
|
|
|
32
|
+
attr_reader :response
|
|
33
|
+
|
|
26
34
|
def money
|
|
27
35
|
Spree::Money.new(amount, currency: payment.currency)
|
|
28
36
|
end
|
|
@@ -2,6 +2,9 @@ module Spree
|
|
|
2
2
|
class Reimbursement < Spree::Base
|
|
3
3
|
include Spree::Core::NumberGenerator.new(prefix: 'RI', length: 9)
|
|
4
4
|
include NumberIdentifier
|
|
5
|
+
if defined?(Spree::Webhooks)
|
|
6
|
+
include Spree::Webhooks::HasWebhooks
|
|
7
|
+
end
|
|
5
8
|
|
|
6
9
|
class IncompleteReimbursementError < StandardError; end
|
|
7
10
|
|
|
@@ -2,6 +2,9 @@ module Spree
|
|
|
2
2
|
class ReturnAuthorization < Spree::Base
|
|
3
3
|
include Spree::Core::NumberGenerator.new(prefix: 'RA', length: 9)
|
|
4
4
|
include NumberIdentifier
|
|
5
|
+
if defined?(Spree::Webhooks)
|
|
6
|
+
include Spree::Webhooks::HasWebhooks
|
|
7
|
+
end
|
|
5
8
|
|
|
6
9
|
belongs_to :order, class_name: 'Spree::Order', inverse_of: :return_authorizations
|
|
7
10
|
|
|
@@ -2,6 +2,10 @@ module Spree
|
|
|
2
2
|
class ReturnItem < Spree::Base
|
|
3
3
|
COMPLETED_RECEPTION_STATUSES = %w(received given_to_customer)
|
|
4
4
|
|
|
5
|
+
if defined?(Spree::Webhooks)
|
|
6
|
+
include Spree::Webhooks::HasWebhooks
|
|
7
|
+
end
|
|
8
|
+
|
|
5
9
|
class_attribute :return_eligibility_validator
|
|
6
10
|
self.return_eligibility_validator = ReturnItem::EligibilityValidator::Default
|
|
7
11
|
|
data/app/models/spree/role.rb
CHANGED
|
@@ -3,6 +3,6 @@ module Spree
|
|
|
3
3
|
include UniqueName
|
|
4
4
|
|
|
5
5
|
has_many :role_users, class_name: 'Spree::RoleUser', dependent: :destroy
|
|
6
|
-
has_many :users, through: :role_users, class_name: Spree.user_class
|
|
6
|
+
has_many :users, through: :role_users, class_name: "::#{Spree.user_class}"
|
|
7
7
|
end
|
|
8
8
|
end
|
|
@@ -6,6 +6,12 @@ module Spree
|
|
|
6
6
|
include NumberIdentifier
|
|
7
7
|
include NumberAsParam
|
|
8
8
|
include Metadata
|
|
9
|
+
if defined?(Spree::Webhooks)
|
|
10
|
+
include Spree::Webhooks::HasWebhooks
|
|
11
|
+
end
|
|
12
|
+
if defined?(Spree::Security::Shipments)
|
|
13
|
+
include Spree::Security::Shipments
|
|
14
|
+
end
|
|
9
15
|
|
|
10
16
|
with_options inverse_of: :shipments do
|
|
11
17
|
belongs_to :address, class_name: 'Spree::Address'
|
|
@@ -243,7 +249,8 @@ module Spree
|
|
|
243
249
|
end
|
|
244
250
|
|
|
245
251
|
def selected_shipping_rate_id=(id)
|
|
246
|
-
|
|
252
|
+
# Explicitly updates the timestamp in order to bust cache dependent on "updated_at"
|
|
253
|
+
shipping_rates.update_all(selected: false, updated_at: Time.current)
|
|
247
254
|
shipping_rates.update(id, selected: true)
|
|
248
255
|
save!
|
|
249
256
|
end
|
|
@@ -3,6 +3,12 @@ module Spree
|
|
|
3
3
|
acts_as_paranoid
|
|
4
4
|
include Spree::CalculatedAdjustments
|
|
5
5
|
include Metadata
|
|
6
|
+
if defined?(Spree::Webhooks)
|
|
7
|
+
include Spree::Webhooks::HasWebhooks
|
|
8
|
+
end
|
|
9
|
+
if defined?(Spree::VendorConcern)
|
|
10
|
+
include Spree::VendorConcern
|
|
11
|
+
end
|
|
6
12
|
|
|
7
13
|
DISPLAY = [:both, :front_end, :back_end]
|
|
8
14
|
|
|
@@ -14,9 +14,15 @@ module Spree
|
|
|
14
14
|
display_name = variant.name.to_s
|
|
15
15
|
display_name += " (#{variant.options_text})" unless variant.options_text.blank?
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
if variant.available?
|
|
18
|
+
line_item.errors.add(:quantity,
|
|
19
|
+
:selected_quantity_not_available,
|
|
20
|
+
message: Spree.t(:selected_quantity_not_available, item: display_name.inspect))
|
|
21
|
+
else
|
|
22
|
+
line_item.errors.add(:base,
|
|
23
|
+
:only_active_products_can_be_added_to_cart,
|
|
24
|
+
message: Spree.t(:only_active_products_can_be_added_to_cart))
|
|
25
|
+
end
|
|
20
26
|
end
|
|
21
27
|
|
|
22
28
|
private
|
|
@@ -2,6 +2,11 @@ module Spree
|
|
|
2
2
|
class StockItem < Spree::Base
|
|
3
3
|
acts_as_paranoid
|
|
4
4
|
|
|
5
|
+
include Metadata
|
|
6
|
+
if defined?(Spree::Webhooks)
|
|
7
|
+
include Spree::Webhooks::HasWebhooks
|
|
8
|
+
end
|
|
9
|
+
|
|
5
10
|
with_options inverse_of: :stock_items do
|
|
6
11
|
belongs_to :stock_location, class_name: 'Spree::StockLocation'
|
|
7
12
|
belongs_to :variant, -> { with_deleted }, class_name: 'Spree::Variant'
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class StockLocation < Spree::Base
|
|
3
3
|
include UniqueName
|
|
4
|
+
if defined?(Spree::Webhooks)
|
|
5
|
+
include Spree::Webhooks::HasWebhooks
|
|
6
|
+
end
|
|
7
|
+
if defined?(Spree::Security::StockLocations)
|
|
8
|
+
include Spree::Security::StockLocations
|
|
9
|
+
end
|
|
10
|
+
if defined?(Spree::VendorConcern)
|
|
11
|
+
include Spree::VendorConcern
|
|
12
|
+
end
|
|
4
13
|
|
|
5
14
|
has_many :shipments
|
|
6
15
|
has_many :stock_items, dependent: :delete_all, inverse_of: :stock_location
|
|
@@ -51,9 +60,15 @@ module Spree
|
|
|
51
60
|
# @param variant Variant instance or Variant ID
|
|
52
61
|
#
|
|
53
62
|
# @return [StockItem] Corresponding StockItem for the StockLocation's variant.
|
|
54
|
-
def stock_item_or_create(
|
|
55
|
-
|
|
56
|
-
|
|
63
|
+
def stock_item_or_create(variant_or_variant_id)
|
|
64
|
+
if variant_or_variant_id.is_a?(Spree::Variant)
|
|
65
|
+
variant_id = variant_or_variant_id.id
|
|
66
|
+
variant = variant_or_variant_id
|
|
67
|
+
else
|
|
68
|
+
variant_id = variant_or_variant_id
|
|
69
|
+
variant = Spree::Variant.find(variant_or_variant_id)
|
|
70
|
+
end
|
|
71
|
+
stock_item(variant_id) || propagate_variant(variant)
|
|
57
72
|
end
|
|
58
73
|
|
|
59
74
|
def count_on_hand(variant)
|
|
@@ -86,8 +101,7 @@ module Spree
|
|
|
86
101
|
end
|
|
87
102
|
|
|
88
103
|
def fill_status(variant, quantity)
|
|
89
|
-
if item =
|
|
90
|
-
|
|
104
|
+
if item = stock_item_or_create(variant)
|
|
91
105
|
if item.count_on_hand >= quantity
|
|
92
106
|
on_hand = quantity
|
|
93
107
|
backordered = 0
|