spree_core 5.2.6 → 5.3.0.rc1
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/helpers/spree/addresses_helper.rb +1 -23
- data/app/helpers/spree/base_helper.rb +25 -77
- data/app/helpers/spree/currency_helper.rb +2 -2
- data/app/helpers/spree/images_helper.rb +5 -0
- data/app/helpers/spree/mail_helper.rb +1 -1
- data/app/helpers/spree/products_helper.rb +1 -1
- data/app/jobs/spree/events/subscriber_job.rb +58 -0
- data/app/jobs/spree/products/refresh_metrics_job.rb +14 -0
- data/app/jobs/spree/products/touch_taxons_job.rb +0 -1
- data/app/jobs/spree/variants/touch_job.rb +9 -0
- data/app/models/concerns/spree/adjustment_source.rb +8 -0
- data/app/models/concerns/spree/parameterizable_name.rb +1 -1
- data/app/models/concerns/spree/product_scopes.rb +54 -8
- data/app/models/concerns/spree/publishable.rb +253 -0
- data/app/models/concerns/spree/unique_name.rb +1 -1
- data/app/models/concerns/spree/user_methods.rb +21 -1
- data/app/models/spree/ability.rb +3 -3
- data/app/models/spree/address.rb +0 -3
- data/app/models/spree/adjustable/promotion_accumulator.rb +1 -1
- data/app/models/spree/adjustment.rb +32 -6
- data/app/models/spree/asset.rb +6 -3
- data/app/models/spree/base.rb +3 -1
- data/app/models/spree/classification.rb +2 -2
- data/app/models/spree/credit_card.rb +0 -3
- data/app/models/spree/current.rb +24 -3
- data/app/models/spree/custom_domain.rb +1 -1
- data/app/models/spree/customer_group.rb +94 -0
- data/app/models/spree/customer_group_user.rb +16 -0
- data/app/models/spree/customer_return.rb +2 -3
- data/app/models/spree/digital.rb +2 -4
- data/app/models/spree/digital_link.rb +2 -3
- data/app/models/spree/event.rb +104 -0
- data/app/models/spree/export.rb +7 -1
- data/app/models/spree/gift_card.rb +13 -1
- data/app/models/spree/gift_card_batch.rb +3 -1
- data/app/models/spree/image.rb +20 -5
- data/app/models/spree/import.rb +17 -12
- data/app/models/spree/import_row.rb +13 -26
- data/app/models/spree/inventory_unit.rb +0 -3
- data/app/models/spree/invitation.rb +12 -6
- data/app/models/spree/line_item.rb +57 -4
- data/app/models/spree/newsletter_subscriber.rb +2 -0
- data/app/models/spree/option_type.rb +2 -5
- data/app/models/spree/option_value.rb +1 -4
- data/app/models/spree/order/checkout.rb +7 -2
- data/app/models/spree/order/emails.rb +3 -11
- data/app/models/spree/order/store_credit.rb +5 -1
- data/app/models/spree/order.rb +80 -31
- data/app/models/spree/order_updater.rb +28 -9
- data/app/models/spree/payment/custom_events.rb +37 -0
- data/app/models/spree/payment.rb +13 -4
- data/app/models/spree/payment_capture_event.rb +0 -4
- data/app/models/spree/payment_method.rb +1 -1
- data/app/models/spree/permission_sets/default_customer.rb +3 -3
- data/app/models/spree/policy.rb +1 -8
- data/app/models/spree/post.rb +2 -7
- data/app/models/spree/post_category.rb +2 -0
- data/app/models/spree/price.rb +8 -6
- data/app/models/spree/price_list.rb +263 -0
- data/app/models/spree/price_rule.rb +26 -0
- data/app/models/spree/price_rules/customer_group_rule.rb +21 -0
- data/app/models/spree/price_rules/user_rule.rb +19 -0
- data/app/models/spree/price_rules/volume_rule.rb +21 -0
- data/app/models/spree/price_rules/zone_rule.rb +19 -0
- data/app/models/spree/product.rb +117 -76
- data/app/models/spree/product_property.rb +2 -2
- data/app/models/spree/promotion/rules/customer_group.rb +22 -0
- data/app/models/spree/promotion/rules/user.rb +2 -2
- data/app/models/spree/promotion.rb +3 -4
- data/app/models/spree/promotion_handler/coupon.rb +3 -3
- data/app/models/spree/property.rb +3 -6
- data/app/models/spree/prototype.rb +0 -3
- data/app/models/spree/refund.rb +2 -3
- data/app/models/spree/reimbursement.rb +5 -3
- data/app/models/spree/report.rb +7 -1
- data/app/models/spree/reports/products_performance.rb +1 -1
- data/app/models/spree/reports/sales_total.rb +1 -1
- data/app/models/spree/return_authorization.rb +7 -3
- data/app/models/spree/return_item.rb +15 -4
- data/app/models/spree/shipment/custom_events.rb +47 -0
- data/app/models/spree/shipment.rb +12 -5
- data/app/models/spree/shipping_category.rb +0 -3
- data/app/models/spree/shipping_method.rb +0 -3
- data/app/models/spree/stock/quantifier.rb +1 -1
- data/app/models/spree/stock_item.rb +2 -0
- data/app/models/spree/stock_location.rb +0 -3
- data/app/models/spree/stock_movement/custom_events.rb +44 -0
- data/app/models/spree/stock_movement.rb +3 -0
- data/app/models/spree/stock_transfer.rb +2 -3
- data/app/models/spree/store.rb +64 -92
- data/app/models/spree/store_credit.rb +3 -4
- data/app/models/spree/store_product.rb +14 -0
- data/app/models/spree/subscriber.rb +186 -0
- data/app/models/spree/tax_category.rb +0 -4
- data/app/models/spree/tax_rate.rb +0 -3
- data/app/models/spree/taxon.rb +3 -36
- data/app/models/spree/taxonomy.rb +0 -3
- data/app/models/spree/variant.rb +114 -21
- data/app/models/spree/webhook_delivery.rb +60 -0
- data/app/models/spree/webhook_endpoint.rb +53 -0
- data/app/models/spree/wished_item.rb +2 -4
- data/app/models/spree/wishlist.rb +2 -3
- data/app/models/spree/zone.rb +0 -9
- data/app/paginators/spree/shared/paginate.rb +4 -0
- data/app/serializers/spree/events/asset_serializer.rb +22 -0
- data/app/serializers/spree/events/base_serializer.rb +61 -0
- data/app/serializers/spree/events/customer_return_serializer.rb +20 -0
- data/app/serializers/spree/events/digital_link_serializer.rb +20 -0
- data/app/serializers/spree/events/digital_serializer.rb +18 -0
- data/app/serializers/spree/events/export_serializer.rb +22 -0
- data/app/serializers/spree/events/gift_card_batch_serializer.rb +24 -0
- data/app/serializers/spree/events/gift_card_serializer.rb +29 -0
- data/app/serializers/spree/events/image_serializer.rb +9 -0
- data/app/serializers/spree/events/import_row_serializer.rb +23 -0
- data/app/serializers/spree/events/import_serializer.rb +24 -0
- data/app/serializers/spree/events/invitation_serializer.rb +28 -0
- data/app/serializers/spree/events/line_item_serializer.rb +31 -0
- data/app/serializers/spree/events/newsletter_subscriber_serializer.rb +21 -0
- data/app/serializers/spree/events/order_serializer.rb +39 -0
- data/app/serializers/spree/events/payment_serializer.rb +24 -0
- data/app/serializers/spree/events/post_category_serializer.rb +20 -0
- data/app/serializers/spree/events/post_serializer.rb +26 -0
- data/app/serializers/spree/events/price_serializer.rb +22 -0
- data/app/serializers/spree/events/product_serializer.rb +24 -0
- data/app/serializers/spree/events/promotion_serializer.rb +32 -0
- data/app/serializers/spree/events/refund_serializer.rb +23 -0
- data/app/serializers/spree/events/reimbursement_serializer.rb +22 -0
- data/app/serializers/spree/events/report_serializer.rb +23 -0
- data/app/serializers/spree/events/return_authorization_serializer.rb +22 -0
- data/app/serializers/spree/events/return_item_serializer.rb +27 -0
- data/app/serializers/spree/events/shipment_serializer.rb +24 -0
- data/app/serializers/spree/events/stock_item_serializer.rb +22 -0
- data/app/serializers/spree/events/stock_movement_serializer.rb +22 -0
- data/app/serializers/spree/events/stock_transfer_serializer.rb +22 -0
- data/app/serializers/spree/events/store_credit_serializer.rb +30 -0
- data/app/serializers/spree/events/user_serializer.rb +18 -0
- data/app/serializers/spree/events/variant_serializer.rb +34 -0
- data/app/serializers/spree/events/wished_item_serializer.rb +20 -0
- data/app/serializers/spree/events/wishlist_serializer.rb +22 -0
- data/app/services/spree/addresses/update.rb +1 -1
- data/app/services/spree/cart/add_item.rb +1 -1
- data/app/services/spree/coupon_codes/coupon_codes_handler.rb +2 -1
- data/app/services/spree/data_feeds/google/required_attributes.rb +4 -4
- data/app/services/spree/newsletter/verify.rb +5 -0
- data/app/services/spree/products/auto_match_taxons.rb +1 -1
- data/app/services/spree/seeds/all.rb +1 -1
- data/app/services/spree/taxons/add_products.rb +8 -4
- data/app/services/spree/taxons/regenerate_products.rb +8 -0
- data/app/services/spree/taxons/remove_products.rb +12 -7
- data/app/subscribers/spree/event_log_subscriber.rb +64 -0
- data/app/subscribers/spree/export_subscriber.rb +26 -0
- data/app/subscribers/spree/invitation_email_subscriber.rb +40 -0
- data/app/subscribers/spree/product_metrics_subscriber.rb +29 -0
- data/app/subscribers/spree/report_subscriber.rb +26 -0
- data/config/locales/en.yml +126 -0
- data/db/migrate/20251110120000_create_spree_price_lists.rb +22 -0
- data/db/migrate/20251110120001_create_spree_price_rules.rb +13 -0
- data/db/migrate/20251110120002_add_price_list_id_to_spree_prices.rb +6 -0
- data/db/migrate/20251110120003_add_price_list_id_to_spree_line_items.rb +5 -0
- data/db/migrate/20251201172118_fix_indexes_on_friendly_id_slugs.rb +8 -0
- data/db/migrate/20251214000001_create_spree_webhook_endpoints.rb +19 -0
- data/db/migrate/20251214000002_create_spree_webhook_deliveries.rb +23 -0
- data/db/migrate/20251222000000_add_performance_indexes_to_spree_adjustments.rb +25 -0
- data/db/migrate/20260112000000_fix_spree_prices_unique_indexes.rb +33 -0
- data/db/migrate/20260115120000_create_spree_customer_groups.rb +14 -0
- data/db/migrate/20260115120001_create_spree_customer_group_users.rb +14 -0
- data/db/migrate/20260117140831_remove_not_null_constraint_from_policy_name.rb +5 -0
- data/db/migrate/20260118120000_add_statistics_to_store_products.rb +11 -0
- data/db/migrate/20260119120000_add_counter_caches_to_spree_products.rb +9 -0
- data/db/migrate/20260119170000_add_counter_caches_to_spree_taxons.rb +9 -0
- data/db/migrate/20260120120000_add_image_count_to_spree_variants.rb +9 -0
- data/lib/generators/spree/dummy/dummy_generator.rb +14 -2
- data/lib/spree/core/configuration.rb +1 -0
- data/lib/spree/core/controller_helpers/auth.rb +0 -15
- data/lib/spree/core/controller_helpers/currency.rb +13 -9
- data/lib/spree/core/controller_helpers/search.rb +1 -1
- data/lib/spree/core/controller_helpers/store.rb +5 -1
- data/lib/spree/core/engine.rb +61 -78
- data/lib/spree/core/importer/order.rb +1 -1
- data/lib/spree/core/importer/product.rb +1 -1
- data/lib/spree/core/preferences/preferable.rb +14 -1
- data/lib/spree/core/pricing/context.rb +63 -0
- data/lib/spree/core/pricing/resolver.rb +129 -0
- data/lib/spree/core/search/base.rb +1 -1
- data/lib/spree/core/token_generator.rb +1 -1
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/core.rb +42 -47
- data/lib/spree/events/adapters/active_support_notifications.rb +112 -0
- data/lib/spree/events/adapters/base.rb +193 -0
- data/lib/spree/events/registry.rb +99 -0
- data/lib/spree/events.rb +240 -0
- data/lib/spree/permitted_attributes.rb +13 -2
- data/lib/spree/testing_support/common_rake.rb +68 -35
- data/lib/spree/testing_support/factories/customer_group_factory.rb +6 -0
- data/lib/spree/testing_support/factories/customer_group_user_factory.rb +6 -0
- data/lib/spree/testing_support/factories/price_factory.rb +4 -0
- data/lib/spree/testing_support/factories/price_list_factory.rb +34 -0
- data/lib/spree/testing_support/factories/price_rule_factory.rb +49 -0
- data/lib/spree/testing_support/factories/promotion_rule_factory.rb +12 -0
- data/lib/spree/testing_support/factories/stock_item_factory.rb +6 -4
- data/lib/spree/testing_support/factories/store_product_factory.rb +6 -0
- data/lib/spree/testing_support/factories/taxon_factory.rb +0 -1
- data/lib/spree/testing_support/factories/webhook_delivery_factory.rb +48 -0
- data/lib/spree/testing_support/factories/webhook_endpoint_factory.rb +22 -0
- data/lib/spree/testing_support/lifecycle_events.rb +38 -0
- data/lib/spree/testing_support/store.rb +4 -2
- data/lib/spree/webhooks.rb +22 -0
- data/lib/tasks/products.rake +40 -0
- data/lib/tasks/taxons.rake +19 -0
- data/lib/tasks/variants.rake +18 -0
- metadata +112 -114
- data/app/jobs/spree/themes/duplicate_components_job.rb +0 -59
- data/app/jobs/spree/themes/screenshot_job.rb +0 -81
- data/app/models/concerns/spree/has_page_links.rb +0 -53
- data/app/models/spree/page.rb +0 -188
- data/app/models/spree/page_block.rb +0 -73
- data/app/models/spree/page_blocks/buttons.rb +0 -29
- data/app/models/spree/page_blocks/heading.rb +0 -18
- data/app/models/spree/page_blocks/image.rb +0 -20
- data/app/models/spree/page_blocks/link.rb +0 -21
- data/app/models/spree/page_blocks/mega_nav.rb +0 -33
- data/app/models/spree/page_blocks/mega_nav_with_subcategories.rb +0 -32
- data/app/models/spree/page_blocks/metafields.rb +0 -18
- data/app/models/spree/page_blocks/nav.rb +0 -15
- data/app/models/spree/page_blocks/newsletter_form.rb +0 -18
- data/app/models/spree/page_blocks/products/brand.rb +0 -15
- data/app/models/spree/page_blocks/products/buy_buttons.rb +0 -24
- data/app/models/spree/page_blocks/products/description.rb +0 -18
- data/app/models/spree/page_blocks/products/price.rb +0 -18
- data/app/models/spree/page_blocks/products/quantity_selector.rb +0 -20
- data/app/models/spree/page_blocks/products/share.rb +0 -8
- data/app/models/spree/page_blocks/products/title.rb +0 -19
- data/app/models/spree/page_blocks/products/variant_picker.rb +0 -13
- data/app/models/spree/page_blocks/subheading.rb +0 -17
- data/app/models/spree/page_blocks/text.rb +0 -16
- data/app/models/spree/page_link.rb +0 -60
- data/app/models/spree/page_section.rb +0 -222
- data/app/models/spree/page_sections/announcement_bar.rb +0 -28
- data/app/models/spree/page_sections/breadcrumbs.rb +0 -12
- data/app/models/spree/page_sections/collection_banner.rb +0 -18
- data/app/models/spree/page_sections/custom_code.rb +0 -11
- data/app/models/spree/page_sections/featured_posts.rb +0 -45
- data/app/models/spree/page_sections/featured_product.rb +0 -50
- data/app/models/spree/page_sections/featured_taxon.rb +0 -90
- data/app/models/spree/page_sections/featured_taxons.rb +0 -45
- data/app/models/spree/page_sections/footer.rb +0 -101
- data/app/models/spree/page_sections/header.rb +0 -62
- data/app/models/spree/page_sections/image_banner.rb +0 -55
- data/app/models/spree/page_sections/image_with_text.rb +0 -65
- data/app/models/spree/page_sections/main_password_footer.rb +0 -18
- data/app/models/spree/page_sections/main_password_header.rb +0 -20
- data/app/models/spree/page_sections/newsletter.rb +0 -54
- data/app/models/spree/page_sections/page_title.rb +0 -19
- data/app/models/spree/page_sections/post_details.rb +0 -19
- data/app/models/spree/page_sections/post_grid.rb +0 -19
- data/app/models/spree/page_sections/product_details.rb +0 -53
- data/app/models/spree/page_sections/product_grid.rb +0 -13
- data/app/models/spree/page_sections/related_products.rb +0 -58
- data/app/models/spree/page_sections/rich_text.rb +0 -31
- data/app/models/spree/page_sections/taxon_banner.rb +0 -18
- data/app/models/spree/page_sections/taxon_grid.rb +0 -17
- data/app/models/spree/page_sections/video.rb +0 -107
- data/app/models/spree/pages/account.rb +0 -19
- data/app/models/spree/pages/cart.rb +0 -19
- data/app/models/spree/pages/checkout.rb +0 -15
- data/app/models/spree/pages/custom.rb +0 -38
- data/app/models/spree/pages/homepage.rb +0 -72
- data/app/models/spree/pages/login.rb +0 -19
- data/app/models/spree/pages/password.rb +0 -59
- data/app/models/spree/pages/post.rb +0 -27
- data/app/models/spree/pages/post_list.rb +0 -36
- data/app/models/spree/pages/product_details.rb +0 -30
- data/app/models/spree/pages/search_results.rb +0 -43
- data/app/models/spree/pages/shop_all.rb +0 -40
- data/app/models/spree/pages/taxon.rb +0 -29
- data/app/models/spree/pages/taxon_list.rb +0 -41
- data/app/models/spree/pages/wishlist.rb +0 -15
- data/app/models/spree/theme.rb +0 -233
- data/app/models/spree/themes/default.rb +0 -97
- data/app/services/spree/taxons/touch_featured_sections.rb +0 -21
- data/db/migrate/20250120094216_create_page_builder_models.rb +0 -78
- data/db/migrate/20250305121352_remove_page_builder_indices.rb +0 -11
- data/db/migrate/20250825175217_add_missing_page_builder_indexes.rb +0 -7
- data/db/migrate/20250913130044_add_page_links_counter_cache_to_spree_stores.rb +0 -10
- data/lib/generators/spree/dummy/templates/initializers/devise.rb +0 -3
- data/lib/generators/spree/install/install_generator.rb +0 -219
- data/lib/generators/spree/install/templates/config/initializers/spree.rb +0 -126
- data/lib/spree/core/webhooks.rb +0 -21
- data/lib/spree/testing_support/factories/page_block_factory.rb +0 -22
- data/lib/spree/testing_support/factories/page_factory.rb +0 -33
- data/lib/spree/testing_support/factories/page_link_factory.rb +0 -7
- data/lib/spree/testing_support/factories/page_section_factory.rb +0 -27
- data/lib/spree/testing_support/factories/theme_factory.rb +0 -14
data/app/models/spree/product.rb
CHANGED
|
@@ -22,7 +22,7 @@ module Spree
|
|
|
22
22
|
class Product < Spree.base_class
|
|
23
23
|
acts_as_paranoid
|
|
24
24
|
acts_as_taggable_on :tags, :labels
|
|
25
|
-
|
|
25
|
+
normalizes :name, with: ->(value) { value&.to_s&.squish&.presence }
|
|
26
26
|
|
|
27
27
|
include Spree::ProductScopes
|
|
28
28
|
include Spree::MultiStoreResource
|
|
@@ -30,17 +30,20 @@ module Spree
|
|
|
30
30
|
include Spree::MemoizedData
|
|
31
31
|
include Spree::Metafields
|
|
32
32
|
include Spree::Metadata
|
|
33
|
-
include Spree::Linkable
|
|
34
33
|
include Spree::Product::Webhooks
|
|
35
34
|
include Spree::Product::Slugs
|
|
36
35
|
if defined?(Spree::VendorConcern)
|
|
37
36
|
include Spree::VendorConcern
|
|
38
37
|
end
|
|
39
38
|
|
|
39
|
+
publishes_lifecycle_events
|
|
40
|
+
|
|
40
41
|
MEMOIZED_METHODS = %w[total_on_hand taxonomy_ids taxon_and_ancestors category
|
|
41
|
-
default_variant_id tax_category default_variant
|
|
42
|
-
|
|
43
|
-
purchasable? in_stock? backorderable?
|
|
42
|
+
default_variant_id tax_category default_variant variant_for_images
|
|
43
|
+
category_taxon brand_taxon main_taxon
|
|
44
|
+
purchasable? in_stock? backorderable? digital?]
|
|
45
|
+
|
|
46
|
+
STATUSES = %w[draft active archived].freeze
|
|
44
47
|
|
|
45
48
|
STATUS_TO_WEBHOOK_EVENT = {
|
|
46
49
|
'active' => 'activated',
|
|
@@ -52,6 +55,8 @@ module Spree
|
|
|
52
55
|
translates(*TRANSLATABLE_FIELDS, column_fallback: !Spree.always_use_translations?)
|
|
53
56
|
|
|
54
57
|
self::Translation.class_eval do
|
|
58
|
+
normalizes :name, :meta_title, with: ->(value) { value&.to_s&.squish&.presence }
|
|
59
|
+
|
|
55
60
|
if defined?(PgSearch)
|
|
56
61
|
include PgSearch::Model
|
|
57
62
|
|
|
@@ -107,6 +112,7 @@ module Spree
|
|
|
107
112
|
|
|
108
113
|
has_many :line_items, through: :variants_including_master
|
|
109
114
|
has_many :orders, through: :line_items
|
|
115
|
+
has_many :completed_orders, -> { reorder(nil).distinct.complete }, through: :line_items, source: :order
|
|
110
116
|
|
|
111
117
|
has_many :variant_images, -> { order(:position) }, source: :images, through: :variants_including_master
|
|
112
118
|
has_many :variant_images_without_master, -> { order(:position) }, source: :images, through: :variants
|
|
@@ -203,17 +209,6 @@ module Spree
|
|
|
203
209
|
joins(:stock_items).where("#{Spree::Variant.table_name}.track_inventory = ? OR #{Spree::StockItem.table_name}.count_on_hand <= ?", false, 0)
|
|
204
210
|
}
|
|
205
211
|
|
|
206
|
-
scope :by_best_selling, lambda { |order_direction = :desc|
|
|
207
|
-
left_joins(variants_including_master: { line_items: :order }).
|
|
208
|
-
select(
|
|
209
|
-
"#{Spree::Product.table_name}.*",
|
|
210
|
-
"COUNT(DISTINCT CASE WHEN #{Spree::Order.table_name}.completed_at IS NOT NULL THEN #{Spree::Order.table_name}.id END) AS completed_orders_count",
|
|
211
|
-
"COALESCE(SUM(CASE WHEN #{Spree::Order.table_name}.completed_at IS NOT NULL THEN (#{Spree::LineItem.table_name}.price * #{Spree::LineItem.table_name}.quantity) END), 0) AS completed_orders_total"
|
|
212
|
-
).
|
|
213
|
-
group("#{Spree::Product.table_name}.id").
|
|
214
|
-
order(completed_orders_count: order_direction, completed_orders_total: order_direction)
|
|
215
|
-
}
|
|
216
|
-
|
|
217
212
|
attr_accessor :option_values_hash
|
|
218
213
|
|
|
219
214
|
accepts_nested_attributes_for :product_properties, allow_destroy: true, reject_if: lambda { |pp|
|
|
@@ -263,12 +258,12 @@ module Spree
|
|
|
263
258
|
event :activate do
|
|
264
259
|
transition to: :active
|
|
265
260
|
end
|
|
266
|
-
after_transition to: :active, do: [:after_activate, :send_product_activated_webhook]
|
|
261
|
+
after_transition to: :active, do: [:after_activate, :send_product_activated_webhook, :publish_product_activated_event]
|
|
267
262
|
|
|
268
263
|
event :archive do
|
|
269
264
|
transition to: :archived
|
|
270
265
|
end
|
|
271
|
-
after_transition to: :archived, do: [:after_archive, :send_product_archived_webhook]
|
|
266
|
+
after_transition to: :archived, do: [:after_archive, :send_product_archived_webhook, :publish_product_archived_event]
|
|
272
267
|
|
|
273
268
|
event :draft do
|
|
274
269
|
transition to: :draft
|
|
@@ -316,9 +311,13 @@ module Spree
|
|
|
316
311
|
master || build_master
|
|
317
312
|
end
|
|
318
313
|
|
|
319
|
-
#
|
|
314
|
+
# Checks if product has variants (non-master variants)
|
|
315
|
+
# Uses variant_count counter cache for performance
|
|
316
|
+
# @return [Boolean]
|
|
320
317
|
def has_variants?
|
|
321
|
-
|
|
318
|
+
return variants.size.positive? if variants.loaded?
|
|
319
|
+
|
|
320
|
+
variant_count.positive?
|
|
322
321
|
end
|
|
323
322
|
|
|
324
323
|
# Returns default Variant for Product
|
|
@@ -330,7 +329,7 @@ module Spree
|
|
|
330
329
|
#
|
|
331
330
|
# @return [Spree::Variant]
|
|
332
331
|
def default_variant
|
|
333
|
-
@default_variant ||= if Spree::Config[:track_inventory_levels] && available_variant = variants.detect(&:purchasable?)
|
|
332
|
+
@default_variant ||= if Spree::Config[:track_inventory_levels] && has_variants? && available_variant = variants.detect(&:purchasable?)
|
|
334
333
|
available_variant
|
|
335
334
|
else
|
|
336
335
|
has_variants? ? variants.first : find_or_build_master
|
|
@@ -343,31 +342,52 @@ module Spree
|
|
|
343
342
|
@default_variant_id ||= default_variant.id
|
|
344
343
|
end
|
|
345
344
|
|
|
346
|
-
# Returns
|
|
347
|
-
#
|
|
345
|
+
# Returns true if any variant (including master) has images.
|
|
346
|
+
# Uses loaded association when available, otherwise falls back to counter cache.
|
|
347
|
+
# @return [Boolean]
|
|
348
|
+
def has_variant_images?
|
|
349
|
+
return variant_images.any? if association(:variant_images).loaded?
|
|
350
|
+
|
|
351
|
+
total_image_count.positive?
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
# Alias for has_variant_images? for consistency with Variant#has_images?
|
|
355
|
+
alias has_images? has_variant_images?
|
|
356
|
+
|
|
357
|
+
# Returns the variant that should be used for displaying images.
|
|
358
|
+
# Priority: master > default_variant > first variant with images
|
|
359
|
+
# @return [Spree::Variant, nil]
|
|
360
|
+
def variant_for_images
|
|
361
|
+
@variant_for_images ||= find_variant_for_images
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
# Returns default Image for Product.
|
|
365
|
+
# @return [Spree::Image, nil]
|
|
348
366
|
def default_image
|
|
349
|
-
|
|
350
|
-
images.first
|
|
351
|
-
elsif default_variant.images.any?
|
|
352
|
-
default_variant.default_image
|
|
353
|
-
elsif variant_images.any?
|
|
354
|
-
variant_images.first
|
|
355
|
-
end
|
|
367
|
+
variant_for_images&.primary_image
|
|
356
368
|
end
|
|
357
|
-
alias featured_image default_image
|
|
358
369
|
|
|
359
|
-
# Returns secondary Image for Product
|
|
360
|
-
# @return [Spree::Image]
|
|
370
|
+
# Returns secondary Image for Product (for hover effects).
|
|
371
|
+
# @return [Spree::Image, nil]
|
|
361
372
|
def secondary_image
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
373
|
+
variant_for_images&.secondary_image
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
# Alias for default_image for consistency.
|
|
377
|
+
alias primary_image default_image
|
|
378
|
+
|
|
379
|
+
# Returns the image count from the variant used for displaying images.
|
|
380
|
+
# @return [Integer]
|
|
381
|
+
def image_count
|
|
382
|
+
variant_for_images&.image_count || 0
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
# Finds first variant with images using preloaded data when available.
|
|
386
|
+
# @return [Spree::Variant, nil]
|
|
387
|
+
def find_variant_with_images
|
|
388
|
+
return variants.find(&:has_images?) if variants.loaded?
|
|
389
|
+
|
|
390
|
+
variants.joins(:images).first
|
|
371
391
|
end
|
|
372
392
|
|
|
373
393
|
# Returns the short description for the product
|
|
@@ -558,7 +578,7 @@ module Spree
|
|
|
558
578
|
if self.class.reflect_on_association(:brand)
|
|
559
579
|
super
|
|
560
580
|
else
|
|
561
|
-
Spree::Deprecation.warn('Spree::Product#brand is deprecated and will be removed in Spree
|
|
581
|
+
Spree::Deprecation.warn('Spree::Product#brand is deprecated and will be removed in Spree 5.5. Please use Spree::Product#brand_taxon instead.')
|
|
562
582
|
brand_taxon
|
|
563
583
|
end
|
|
564
584
|
end
|
|
@@ -566,17 +586,19 @@ module Spree
|
|
|
566
586
|
# Returns the brand taxon for the product
|
|
567
587
|
# @return [Spree::Taxon]
|
|
568
588
|
def brand_taxon
|
|
569
|
-
@
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
589
|
+
@brand_taxon ||= if classification_count.zero?
|
|
590
|
+
nil
|
|
591
|
+
elsif Spree.use_translations?
|
|
592
|
+
taxons.joins(:taxonomy).
|
|
593
|
+
join_translation_table(Taxonomy).
|
|
594
|
+
find_by(Taxonomy.translation_table_alias => { name: Spree.t(:taxonomy_brands_name) })
|
|
595
|
+
else
|
|
596
|
+
if taxons.loaded?
|
|
597
|
+
taxons.find { |taxon| taxon.taxonomy.name == Spree.t(:taxonomy_brands_name) }
|
|
598
|
+
else
|
|
599
|
+
taxons.joins(:taxonomy).find_by(Taxonomy.table_name => { name: Spree.t(:taxonomy_brands_name) })
|
|
600
|
+
end
|
|
601
|
+
end
|
|
580
602
|
end
|
|
581
603
|
|
|
582
604
|
# Returns the brand name for the product
|
|
@@ -593,7 +615,7 @@ module Spree
|
|
|
593
615
|
if self.class.reflect_on_association(:category)
|
|
594
616
|
super
|
|
595
617
|
else
|
|
596
|
-
Spree::Deprecation.warn('Spree::Product#category is deprecated and will be removed in Spree
|
|
618
|
+
Spree::Deprecation.warn('Spree::Product#category is deprecated and will be removed in Spree 5.5. Please use Spree::Product#category_taxon instead.')
|
|
597
619
|
category_taxon
|
|
598
620
|
end
|
|
599
621
|
end
|
|
@@ -601,27 +623,33 @@ module Spree
|
|
|
601
623
|
# Returns the category taxon for the product
|
|
602
624
|
# @return [Spree::Taxon]
|
|
603
625
|
def category_taxon
|
|
604
|
-
@
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
626
|
+
@category_taxon ||= if classification_count.zero?
|
|
627
|
+
nil
|
|
628
|
+
elsif Spree.use_translations?
|
|
629
|
+
taxons.joins(:taxonomy).
|
|
630
|
+
join_translation_table(Taxonomy).
|
|
631
|
+
order(depth: :desc).
|
|
632
|
+
find_by(Taxonomy.translation_table_alias => { name: Spree.t(:taxonomy_categories_name) })
|
|
633
|
+
else
|
|
634
|
+
if taxons.loaded?
|
|
635
|
+
taxons.find { |taxon| taxon.taxonomy.name == Spree.t(:taxonomy_categories_name) }
|
|
636
|
+
else
|
|
637
|
+
taxons.joins(:taxonomy).order(depth: :desc).find_by(Taxonomy.table_name => { name: Spree.t(:taxonomy_categories_name) })
|
|
638
|
+
end
|
|
639
|
+
end
|
|
616
640
|
end
|
|
617
641
|
|
|
618
642
|
def main_taxon
|
|
619
|
-
|
|
643
|
+
return if classification_count.zero?
|
|
644
|
+
|
|
645
|
+
@main_taxon ||= category_taxon || taxons.first
|
|
620
646
|
end
|
|
621
647
|
|
|
622
648
|
def taxons_for_store(store)
|
|
649
|
+
return if classification_count.zero?
|
|
650
|
+
|
|
623
651
|
Rails.cache.fetch("#{cache_key_with_version}/taxons-per-store/#{store.id}") do
|
|
624
|
-
taxons.for_store(store)
|
|
652
|
+
taxons.loaded? ? taxons.find_all { |taxon| taxon.taxonomy.store_id == store.id } : taxons.for_store(store)
|
|
625
653
|
end
|
|
626
654
|
end
|
|
627
655
|
|
|
@@ -674,7 +702,8 @@ module Spree
|
|
|
674
702
|
|
|
675
703
|
if has_variants?
|
|
676
704
|
variants_including_master.each_with_index do |variant, index|
|
|
677
|
-
csv_lines << Spree::CSV::ProductVariantPresenter.new(self, variant, index, properties_for_csv, taxons_for_csv, store,
|
|
705
|
+
csv_lines << Spree::CSV::ProductVariantPresenter.new(self, variant, index, properties_for_csv, taxons_for_csv, store,
|
|
706
|
+
metafields_for_csv).call
|
|
678
707
|
end
|
|
679
708
|
else
|
|
680
709
|
csv_lines << Spree::CSV::ProductVariantPresenter.new(self, master, 0, properties_for_csv, taxons_for_csv, store, metafields_for_csv).call
|
|
@@ -683,13 +712,17 @@ module Spree
|
|
|
683
712
|
csv_lines
|
|
684
713
|
end
|
|
685
714
|
|
|
686
|
-
|
|
687
|
-
return unless Spree::Core::Engine.routes.url_helpers.respond_to?(:product_path)
|
|
715
|
+
private
|
|
688
716
|
|
|
689
|
-
|
|
690
|
-
|
|
717
|
+
# Determines which variant should be used for displaying images.
|
|
718
|
+
# Priority: master > default_variant > first variant with images
|
|
719
|
+
def find_variant_for_images
|
|
720
|
+
return master if master.has_images?
|
|
721
|
+
return default_variant if has_variants? && default_variant.has_images?
|
|
722
|
+
return find_variant_with_images if has_variant_images?
|
|
691
723
|
|
|
692
|
-
|
|
724
|
+
nil
|
|
725
|
+
end
|
|
693
726
|
|
|
694
727
|
def add_associations_from_prototype
|
|
695
728
|
if prototype_id && prototype = Spree::Prototype.find_by(id: prototype_id)
|
|
@@ -727,7 +760,7 @@ module Spree
|
|
|
727
760
|
end
|
|
728
761
|
|
|
729
762
|
def default_variant_cache_key
|
|
730
|
-
Spree::Deprecation.warn('Spree::Product#default_variant_cache_key is deprecated and will be removed in Spree
|
|
763
|
+
Spree::Deprecation.warn('Spree::Product#default_variant_cache_key is deprecated and will be removed in Spree 5.5. Please remove any occurrences of it.')
|
|
731
764
|
|
|
732
765
|
"spree/default-variant/#{cache_key_with_version}/#{Spree::Config[:track_inventory_levels]}"
|
|
733
766
|
end
|
|
@@ -855,5 +888,13 @@ module Spree
|
|
|
855
888
|
def after_draft
|
|
856
889
|
# Implement your logic here
|
|
857
890
|
end
|
|
891
|
+
|
|
892
|
+
def publish_product_activated_event
|
|
893
|
+
publish_event('product.activated')
|
|
894
|
+
end
|
|
895
|
+
|
|
896
|
+
def publish_product_archived_event
|
|
897
|
+
publish_event('product.archived')
|
|
898
|
+
end
|
|
858
899
|
end
|
|
859
900
|
end
|
|
@@ -12,10 +12,10 @@ module Spree
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
self::Translation.class_eval do
|
|
15
|
-
|
|
15
|
+
normalizes :value, with: ->(value) { value&.to_s&.squish&.presence }
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
normalizes :value, with: ->(value) { value&.to_s&.squish&.presence }
|
|
19
19
|
|
|
20
20
|
acts_as_list scope: :product
|
|
21
21
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
class Promotion
|
|
3
|
+
module Rules
|
|
4
|
+
class CustomerGroup < PromotionRule
|
|
5
|
+
preference :customer_group_ids, :array, default: []
|
|
6
|
+
|
|
7
|
+
def applicable?(promotable)
|
|
8
|
+
promotable.is_a?(Spree::Order)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def eligible?(order, _options = {})
|
|
12
|
+
return false unless order.user_id.present?
|
|
13
|
+
return false if preferred_customer_group_ids.empty?
|
|
14
|
+
|
|
15
|
+
user_customer_group_ids = Spree::CustomerGroupUser.where(user_id: order.user_id).pluck(:customer_group_id).map(&:to_s)
|
|
16
|
+
|
|
17
|
+
(preferred_customer_group_ids.map(&:to_s) & user_customer_group_ids).any?
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -34,7 +34,7 @@ module Spree
|
|
|
34
34
|
|
|
35
35
|
def user_ids_string
|
|
36
36
|
ActiveSupport::Deprecation.warn(
|
|
37
|
-
'Spree::Promotion::Rules::User#user_ids_string is deprecated and will be removed in Spree
|
|
37
|
+
'Spree::Promotion::Rules::User#user_ids_string is deprecated and will be removed in Spree 5.5. ' \
|
|
38
38
|
'Please use `user_ids` instead.'
|
|
39
39
|
)
|
|
40
40
|
user_ids.join(',')
|
|
@@ -42,7 +42,7 @@ module Spree
|
|
|
42
42
|
|
|
43
43
|
def user_ids_string=(s)
|
|
44
44
|
ActiveSupport::Deprecation.warn(
|
|
45
|
-
'Spree::Promotion::Rules::User#user_ids_string= is deprecated and will be removed in Spree
|
|
45
|
+
'Spree::Promotion::Rules::User#user_ids_string= is deprecated and will be removed in Spree 5.5. ' \
|
|
46
46
|
'Please use `user_ids=` instead.'
|
|
47
47
|
)
|
|
48
48
|
self.user_ids = s
|
|
@@ -3,13 +3,12 @@ module Spree
|
|
|
3
3
|
include Spree::MultiStoreResource
|
|
4
4
|
include Spree::Metafields
|
|
5
5
|
include Spree::Metadata
|
|
6
|
-
if defined?(Spree::Webhooks::HasWebhooks)
|
|
7
|
-
include Spree::Webhooks::HasWebhooks
|
|
8
|
-
end
|
|
9
6
|
if defined?(Spree::Security::Promotions)
|
|
10
7
|
include Spree::Security::Promotions
|
|
11
8
|
end
|
|
12
9
|
|
|
10
|
+
publishes_lifecycle_events
|
|
11
|
+
|
|
13
12
|
MATCH_POLICIES = %w(all any)
|
|
14
13
|
UNACTIVATABLE_ORDER_STATES = ['complete', 'awaiting_return', 'returned']
|
|
15
14
|
|
|
@@ -18,7 +17,7 @@ module Spree
|
|
|
18
17
|
#
|
|
19
18
|
# Magic methods
|
|
20
19
|
#
|
|
21
|
-
|
|
20
|
+
normalizes :code, :path, :name, with: ->(value) { value&.to_s&.squish&.presence }
|
|
22
21
|
|
|
23
22
|
#
|
|
24
23
|
# Enums
|
|
@@ -177,8 +177,8 @@ module Spree
|
|
|
177
177
|
|
|
178
178
|
# Check for applied adjustments.
|
|
179
179
|
discount = order.all_adjustments.promotion.eligible.detect do |p|
|
|
180
|
-
p.
|
|
181
|
-
|
|
180
|
+
p.cached_source.promotion.code.try(:downcase) == coupon_code ||
|
|
181
|
+
Spree::CouponCode.unused.where(promotion_id: p.cached_source.promotion_id, code: coupon_code).exists?
|
|
182
182
|
end
|
|
183
183
|
|
|
184
184
|
# Check for applied line items.
|
|
@@ -209,7 +209,7 @@ module Spree
|
|
|
209
209
|
end
|
|
210
210
|
|
|
211
211
|
def handle_coupon_code(discount, coupon_code)
|
|
212
|
-
|
|
212
|
+
Spree::CouponCode.unused.find_by(promotion_id: discount.cached_source.promotion_id, code: coupon_code)&.apply_order!(order)
|
|
213
213
|
end
|
|
214
214
|
|
|
215
215
|
def load_gift_card_code
|
|
@@ -6,15 +6,12 @@ module Spree
|
|
|
6
6
|
include Spree::UniqueName
|
|
7
7
|
include Spree::DisplayOn
|
|
8
8
|
include Spree::TranslatableResource
|
|
9
|
-
if defined?(Spree::Webhooks::HasWebhooks)
|
|
10
|
-
include Spree::Webhooks::HasWebhooks
|
|
11
|
-
end
|
|
12
9
|
|
|
13
10
|
TRANSLATABLE_FIELDS = %i[presentation].freeze
|
|
14
11
|
translates(*TRANSLATABLE_FIELDS, column_fallback: !Spree.always_use_translations?)
|
|
15
12
|
|
|
16
13
|
self::Translation.class_eval do
|
|
17
|
-
|
|
14
|
+
normalizes :presentation, with: ->(value) { value&.to_s&.squish&.presence }
|
|
18
15
|
end
|
|
19
16
|
|
|
20
17
|
acts_as_list
|
|
@@ -46,7 +43,7 @@ module Spree
|
|
|
46
43
|
with_uniq_values_cache_key(product_properties_scope) do
|
|
47
44
|
properties = product_properties
|
|
48
45
|
properties = properties.where(id: product_properties_scope) if product_properties_scope.present?
|
|
49
|
-
properties.where
|
|
46
|
+
properties.where('value IS NOT NULL AND value != ?', '').pluck(:filter_param, :value).uniq
|
|
50
47
|
end
|
|
51
48
|
end
|
|
52
49
|
|
|
@@ -83,7 +80,7 @@ module Spree
|
|
|
83
80
|
def ensure_product_properties_have_filter_params
|
|
84
81
|
return unless filterable?
|
|
85
82
|
|
|
86
|
-
product_properties.where(filter_param: [nil, '']).where
|
|
83
|
+
product_properties.where(filter_param: [nil, '']).where('value IS NOT NULL AND value != ?', '').find_each(&:save)
|
|
87
84
|
end
|
|
88
85
|
end
|
|
89
86
|
end
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class Prototype < Spree.base_class
|
|
3
3
|
include Spree::Metadata
|
|
4
|
-
if defined?(Spree::Webhooks::HasWebhooks)
|
|
5
|
-
include Spree::Webhooks::HasWebhooks
|
|
6
|
-
end
|
|
7
4
|
|
|
8
5
|
has_many :property_prototypes, class_name: 'Spree::PropertyPrototype'
|
|
9
6
|
has_many :properties, through: :property_prototypes, class_name: 'Spree::Property'
|
data/app/models/spree/refund.rb
CHANGED
|
@@ -2,13 +2,12 @@ module Spree
|
|
|
2
2
|
class Refund < Spree.base_class
|
|
3
3
|
include Spree::Metafields
|
|
4
4
|
include Spree::Metadata
|
|
5
|
-
if defined?(Spree::Webhooks::HasWebhooks)
|
|
6
|
-
include Spree::Webhooks::HasWebhooks
|
|
7
|
-
end
|
|
8
5
|
if defined?(Spree::Security::Refunds)
|
|
9
6
|
include Spree::Security::Refunds
|
|
10
7
|
end
|
|
11
8
|
|
|
9
|
+
publishes_lifecycle_events
|
|
10
|
+
|
|
12
11
|
with_options inverse_of: :refunds do
|
|
13
12
|
belongs_to :payment
|
|
14
13
|
belongs_to :reimbursement, optional: true
|
|
@@ -2,9 +2,6 @@ module Spree
|
|
|
2
2
|
class Reimbursement < Spree.base_class
|
|
3
3
|
include Spree::Core::NumberGenerator.new(prefix: 'RI', length: 9)
|
|
4
4
|
include Spree::NumberIdentifier
|
|
5
|
-
if defined?(Spree::Webhooks::HasWebhooks)
|
|
6
|
-
include Spree::Webhooks::HasWebhooks
|
|
7
|
-
end
|
|
8
5
|
include Spree::Reimbursement::Emails
|
|
9
6
|
|
|
10
7
|
class IncompleteReimbursementError < StandardError; end
|
|
@@ -76,6 +73,7 @@ module Spree
|
|
|
76
73
|
event :reimbursed do
|
|
77
74
|
transition to: :reimbursed, from: [:pending, :errored]
|
|
78
75
|
end
|
|
76
|
+
after_transition to: :reimbursed, do: :publish_reimbursement_reimbursed_event
|
|
79
77
|
end
|
|
80
78
|
|
|
81
79
|
class << self
|
|
@@ -138,6 +136,10 @@ module Spree
|
|
|
138
136
|
|
|
139
137
|
private
|
|
140
138
|
|
|
139
|
+
def publish_reimbursement_reimbursed_event
|
|
140
|
+
publish_event('reimbursement.reimbursed')
|
|
141
|
+
end
|
|
142
|
+
|
|
141
143
|
def validate_return_items_belong_to_same_order
|
|
142
144
|
if return_items.any? { |ri| ri.inventory_unit.order_id != order_id }
|
|
143
145
|
errors.add(:base, :return_items_order_id_does_not_match)
|
data/app/models/spree/report.rb
CHANGED
|
@@ -3,6 +3,12 @@ module Spree
|
|
|
3
3
|
include Spree::SingleStoreResource
|
|
4
4
|
include Spree::VendorConcern if defined?(Spree::VendorConcern)
|
|
5
5
|
|
|
6
|
+
publishes_lifecycle_events
|
|
7
|
+
|
|
8
|
+
# Set event prefix for all Report subclasses
|
|
9
|
+
# This ensures Spree::Reports::SalesTotal publishes 'report.create' not 'sales_total.create'
|
|
10
|
+
self.event_prefix = 'report'
|
|
11
|
+
|
|
6
12
|
#
|
|
7
13
|
# Associations
|
|
8
14
|
#
|
|
@@ -13,7 +19,7 @@ module Spree
|
|
|
13
19
|
# Callbacks
|
|
14
20
|
#
|
|
15
21
|
after_initialize :set_default_values
|
|
16
|
-
|
|
22
|
+
# NOTE: generate_async is now handled by Spree::ReportSubscriber listening to 'report.create' event
|
|
17
23
|
|
|
18
24
|
#
|
|
19
25
|
# Validations
|
|
@@ -5,7 +5,7 @@ module Spree
|
|
|
5
5
|
scope = store.line_items.where(
|
|
6
6
|
order: Spree::Order.complete.where(
|
|
7
7
|
currency: currency,
|
|
8
|
-
completed_at:
|
|
8
|
+
completed_at: date_from..date_to
|
|
9
9
|
)
|
|
10
10
|
).includes(:order, shipments: :inventory_units, variant: :product)
|
|
11
11
|
|
|
@@ -2,9 +2,8 @@ module Spree
|
|
|
2
2
|
class ReturnAuthorization < Spree.base_class
|
|
3
3
|
include Spree::Core::NumberGenerator.new(prefix: 'RA', length: 9)
|
|
4
4
|
include Spree::NumberIdentifier
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
end
|
|
5
|
+
|
|
6
|
+
publishes_lifecycle_events
|
|
8
7
|
|
|
9
8
|
belongs_to :order, class_name: 'Spree::Order', inverse_of: :return_authorizations
|
|
10
9
|
|
|
@@ -34,6 +33,7 @@ module Spree
|
|
|
34
33
|
|
|
35
34
|
state_machine initial: :authorized do
|
|
36
35
|
before_transition to: :canceled, do: :cancel_return_items
|
|
36
|
+
after_transition to: :canceled, do: :publish_return_authorization_canceled_event
|
|
37
37
|
|
|
38
38
|
event :cancel do
|
|
39
39
|
transition to: :canceled, from: :authorized, if: ->(return_authorization) { return_authorization.can_cancel_return_items? }
|
|
@@ -79,6 +79,10 @@ module Spree
|
|
|
79
79
|
return_items.each { |item| item.cancel! if item.can_cancel? }
|
|
80
80
|
end
|
|
81
81
|
|
|
82
|
+
def publish_return_authorization_canceled_event
|
|
83
|
+
publish_event('return_authorization.canceled')
|
|
84
|
+
end
|
|
85
|
+
|
|
82
86
|
def generate_expedited_exchange_reimbursements
|
|
83
87
|
return unless Spree::Config[:expedited_exchanges]
|
|
84
88
|
|
|
@@ -2,10 +2,6 @@ module Spree
|
|
|
2
2
|
class ReturnItem < Spree.base_class
|
|
3
3
|
COMPLETED_RECEPTION_STATUSES = %w(received given_to_customer)
|
|
4
4
|
|
|
5
|
-
if defined?(Spree::Webhooks::HasWebhooks)
|
|
6
|
-
include Spree::Webhooks::HasWebhooks
|
|
7
|
-
end
|
|
8
|
-
|
|
9
5
|
class_attribute :return_eligibility_validator
|
|
10
6
|
self.return_eligibility_validator = ReturnItem::EligibilityValidator::Default
|
|
11
7
|
|
|
@@ -85,6 +81,7 @@ module Spree
|
|
|
85
81
|
state_machine :reception_status, initial: :awaiting do
|
|
86
82
|
after_transition to: :received, do: :attempt_accept
|
|
87
83
|
after_transition to: :received, do: :process_inventory_unit!
|
|
84
|
+
after_transition to: :received, do: :publish_return_item_received_event
|
|
88
85
|
|
|
89
86
|
event :receive do
|
|
90
87
|
transition to: :received, from: :awaiting
|
|
@@ -93,10 +90,12 @@ module Spree
|
|
|
93
90
|
event :cancel do
|
|
94
91
|
transition to: :cancelled, from: :awaiting
|
|
95
92
|
end
|
|
93
|
+
after_transition to: :cancelled, do: :publish_return_item_canceled_event
|
|
96
94
|
|
|
97
95
|
event :give do
|
|
98
96
|
transition to: :given_to_customer, from: :awaiting
|
|
99
97
|
end
|
|
98
|
+
after_transition to: :given_to_customer, do: :publish_return_item_given_event
|
|
100
99
|
end
|
|
101
100
|
|
|
102
101
|
extend DisplayMoney
|
|
@@ -270,5 +269,17 @@ module Spree
|
|
|
270
269
|
def should_restock?
|
|
271
270
|
resellable? && variant.should_track_inventory? && stock_item && Spree::Config[:restock_inventory]
|
|
272
271
|
end
|
|
272
|
+
|
|
273
|
+
def publish_return_item_received_event
|
|
274
|
+
publish_event('return_item.received')
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def publish_return_item_canceled_event
|
|
278
|
+
publish_event('return_item.canceled')
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def publish_return_item_given_event
|
|
282
|
+
publish_event('return_item.given')
|
|
283
|
+
end
|
|
273
284
|
end
|
|
274
285
|
end
|