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/lib/spree/events.rb
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'events/registry'
|
|
4
|
+
require_relative 'events/adapters/base'
|
|
5
|
+
require_relative 'events/adapters/active_support_notifications'
|
|
6
|
+
|
|
7
|
+
module Spree
|
|
8
|
+
# Main entry point for the Spree event system.
|
|
9
|
+
#
|
|
10
|
+
# This module provides a clean API for publishing events and subscribing
|
|
11
|
+
# to them. It abstracts the underlying implementation (ActiveSupport::Notifications)
|
|
12
|
+
# allowing for future changes without affecting subscriber code.
|
|
13
|
+
#
|
|
14
|
+
# @example Publishing an event
|
|
15
|
+
# Spree::Events.publish('order.completed', order.serializable_hash)
|
|
16
|
+
#
|
|
17
|
+
# @example Subscribing with a class
|
|
18
|
+
# Spree::Events.subscribe('order.completed', OrderCompletedHandler)
|
|
19
|
+
#
|
|
20
|
+
# @example Subscribing with a block
|
|
21
|
+
# Spree::Events.subscribe('order.completed') do |event|
|
|
22
|
+
# puts "Order completed: #{event.payload['number']}"
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
25
|
+
# @example Pattern matching
|
|
26
|
+
# Spree::Events.subscribe('order.*', OrderAuditLogger) # All order events
|
|
27
|
+
# Spree::Events.subscribe('*', GlobalEventLogger) # All events
|
|
28
|
+
#
|
|
29
|
+
module Events
|
|
30
|
+
class << self
|
|
31
|
+
# Publish an event to all matching subscribers
|
|
32
|
+
#
|
|
33
|
+
# @param name [String] The event name (e.g., 'order.complete')
|
|
34
|
+
# @param payload [Hash] The event payload (should be serializable)
|
|
35
|
+
# @param metadata [Hash] Additional metadata for the event
|
|
36
|
+
# @return [Spree::Event] The published event
|
|
37
|
+
#
|
|
38
|
+
# @example
|
|
39
|
+
# Spree::Events.publish('product.created', product.serializable_hash)
|
|
40
|
+
# Spree::Events.publish('order.completed', order.serializable_hash, { user_id: current_user.id })
|
|
41
|
+
#
|
|
42
|
+
def publish(name, payload = {}, metadata = {})
|
|
43
|
+
adapter.publish(name, payload, metadata)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Subscribe to an event pattern
|
|
47
|
+
#
|
|
48
|
+
# @param pattern [String] Event pattern (supports wildcards like 'order.*' or '*')
|
|
49
|
+
# @param subscriber [Class, Proc, nil] The subscriber class or callable
|
|
50
|
+
# @param options [Hash] Subscription options
|
|
51
|
+
# @option options [Boolean] :async (true) Whether to run async via ActiveJob
|
|
52
|
+
# @yield [event] Block to execute when event occurs (alternative to subscriber param)
|
|
53
|
+
# @yieldparam event [Spree::Event] The event object
|
|
54
|
+
# @return [void]
|
|
55
|
+
#
|
|
56
|
+
# @example With a subscriber class
|
|
57
|
+
# Spree::Events.subscribe('order.completed', SendConfirmationEmail)
|
|
58
|
+
#
|
|
59
|
+
# @example With a block
|
|
60
|
+
# Spree::Events.subscribe('order.completed') { |event| puts event.name }
|
|
61
|
+
#
|
|
62
|
+
# @example With pattern matching
|
|
63
|
+
# Spree::Events.subscribe('order.*', OrderAuditLogger)
|
|
64
|
+
#
|
|
65
|
+
# @example Synchronous execution
|
|
66
|
+
# Spree::Events.subscribe('order.completed', MyHandler, async: false)
|
|
67
|
+
#
|
|
68
|
+
def subscribe(pattern, subscriber = nil, options = {}, &block)
|
|
69
|
+
subscriber = block if block_given?
|
|
70
|
+
raise ArgumentError, 'Must provide a subscriber class, callable, or block' unless subscriber
|
|
71
|
+
|
|
72
|
+
adapter.subscribe(pattern, subscriber, options)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Unsubscribe from an event pattern
|
|
76
|
+
#
|
|
77
|
+
# @param pattern [String] Event pattern
|
|
78
|
+
# @param subscriber [Class, Proc] The subscriber to remove
|
|
79
|
+
# @return [Boolean] true if removed, false if not found
|
|
80
|
+
def unsubscribe(pattern, subscriber)
|
|
81
|
+
adapter.unsubscribe(pattern, subscriber)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Get the event registry
|
|
85
|
+
#
|
|
86
|
+
# @return [Spree::Events::Registry]
|
|
87
|
+
def registry
|
|
88
|
+
@registry ||= Registry.new
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Get the adapter instance
|
|
92
|
+
#
|
|
93
|
+
# The adapter class can be configured via Spree.events_adapter_class
|
|
94
|
+
# Default: Spree::Events::Adapters::ActiveSupportNotifications
|
|
95
|
+
#
|
|
96
|
+
# @return [Object] the configured adapter instance
|
|
97
|
+
def adapter
|
|
98
|
+
@adapter ||= Spree.events_adapter_class.new(registry)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Activate the event system (called during Rails initialization)
|
|
102
|
+
# Also registers all subscribers from Spree.subscribers
|
|
103
|
+
# This method is idempotent - calling it multiple times has no effect
|
|
104
|
+
def activate!
|
|
105
|
+
return if registry.size > 0
|
|
106
|
+
|
|
107
|
+
register_subscribers!
|
|
108
|
+
adapter.activate!
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Reset the event system (useful for testing)
|
|
112
|
+
def reset!
|
|
113
|
+
adapter.deactivate! if @adapter
|
|
114
|
+
@registry = nil
|
|
115
|
+
@adapter = nil
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Register all subscribers from Spree.subscribers
|
|
119
|
+
#
|
|
120
|
+
# This is called automatically during Rails initialization.
|
|
121
|
+
# Can also be called in tests after reset! to re-register subscribers.
|
|
122
|
+
#
|
|
123
|
+
# In development, class objects in Spree.subscribers may become stale after
|
|
124
|
+
# code reload (Zeitwerk creates new class objects). We resolve the constant
|
|
125
|
+
# fresh from the class name to ensure we're using the reloaded class.
|
|
126
|
+
#
|
|
127
|
+
# @return [void]
|
|
128
|
+
def register_subscribers!
|
|
129
|
+
return unless defined?(Spree) && Spree.respond_to?(:subscribers)
|
|
130
|
+
|
|
131
|
+
Spree.subscribers&.each do |subscriber|
|
|
132
|
+
# Resolve the subscriber constant fresh to handle code reload in development
|
|
133
|
+
# The array may contain stale class objects after Zeitwerk reload
|
|
134
|
+
resolved_subscriber = resolve_subscriber(subscriber)
|
|
135
|
+
next unless resolved_subscriber
|
|
136
|
+
|
|
137
|
+
resolved_subscriber.subscription_patterns.each do |pattern|
|
|
138
|
+
subscribe(pattern, resolved_subscriber, resolved_subscriber.subscription_options)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Resolve a subscriber to its current class object
|
|
144
|
+
#
|
|
145
|
+
# In development, Zeitwerk may have reloaded the class, creating a new
|
|
146
|
+
# class object while the old one is still referenced in Spree.subscribers.
|
|
147
|
+
# This method resolves the constant fresh to get the current class.
|
|
148
|
+
#
|
|
149
|
+
# @param subscriber [Class, String] The subscriber class or class name
|
|
150
|
+
# @return [Class, nil] The resolved class or nil if not found
|
|
151
|
+
def resolve_subscriber(subscriber)
|
|
152
|
+
return subscriber unless Rails.env.development? || Rails.env.test?
|
|
153
|
+
|
|
154
|
+
class_name = subscriber.is_a?(String) ? subscriber : subscriber.name
|
|
155
|
+
return nil unless class_name
|
|
156
|
+
|
|
157
|
+
class_name.constantize
|
|
158
|
+
rescue NameError => e
|
|
159
|
+
Rails.logger.warn "[Spree Events] Could not resolve subscriber #{class_name}: #{e.message}"
|
|
160
|
+
nil
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# List all registered subscriber patterns
|
|
164
|
+
#
|
|
165
|
+
# @return [Array<String>]
|
|
166
|
+
def patterns
|
|
167
|
+
registry.patterns
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# List all subscriptions
|
|
171
|
+
#
|
|
172
|
+
# @return [Array<Spree::Events::Registry::Subscription>]
|
|
173
|
+
def subscriptions
|
|
174
|
+
registry.all_subscriptions
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Check if events are enabled
|
|
178
|
+
#
|
|
179
|
+
# Events can be temporarily disabled using Spree::Events.disable { ... }
|
|
180
|
+
#
|
|
181
|
+
# @return [Boolean]
|
|
182
|
+
def enabled?
|
|
183
|
+
!RequestStore.store[:spree_events_disabled]
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Temporarily disable events within a block
|
|
187
|
+
#
|
|
188
|
+
# @yield Block during which events are disabled
|
|
189
|
+
# @return [Object] Return value of the block
|
|
190
|
+
#
|
|
191
|
+
# @example
|
|
192
|
+
# Spree::Events.disable do
|
|
193
|
+
# # Events published here won't trigger subscribers
|
|
194
|
+
# order.complete!
|
|
195
|
+
# end
|
|
196
|
+
#
|
|
197
|
+
def disable
|
|
198
|
+
previous = RequestStore.store[:spree_events_disabled]
|
|
199
|
+
RequestStore.store[:spree_events_disabled] = true
|
|
200
|
+
yield
|
|
201
|
+
ensure
|
|
202
|
+
RequestStore.store[:spree_events_disabled] = previous
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Globally disable events
|
|
206
|
+
# Useful for testing to disable events for the entire test suite
|
|
207
|
+
# @return [void]
|
|
208
|
+
def disable!
|
|
209
|
+
RequestStore.store[:spree_events_disabled] = true
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# Temporarily enable events within a block
|
|
213
|
+
# Useful for testing when events are globally disabled
|
|
214
|
+
#
|
|
215
|
+
# @yield Block during which events are enabled
|
|
216
|
+
# @return [Object] Return value of the block
|
|
217
|
+
#
|
|
218
|
+
# @example
|
|
219
|
+
# Spree::Events.enable do
|
|
220
|
+
# # Events published here will trigger subscribers
|
|
221
|
+
# order.complete!
|
|
222
|
+
# end
|
|
223
|
+
#
|
|
224
|
+
def enable
|
|
225
|
+
previous = RequestStore.store[:spree_events_disabled]
|
|
226
|
+
RequestStore.store[:spree_events_disabled] = false
|
|
227
|
+
yield
|
|
228
|
+
ensure
|
|
229
|
+
RequestStore.store[:spree_events_disabled] = previous
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Globally enable events
|
|
233
|
+
# Useful for testing
|
|
234
|
+
# @return [void]
|
|
235
|
+
def enable!
|
|
236
|
+
RequestStore.store[:spree_events_disabled] = false
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
end
|
|
@@ -8,6 +8,7 @@ module Spree
|
|
|
8
8
|
:cms_page_attributes,
|
|
9
9
|
:cms_section_attributes,
|
|
10
10
|
:custom_domain_attributes,
|
|
11
|
+
:customer_group_attributes,
|
|
11
12
|
:customer_return_attributes,
|
|
12
13
|
:digital_attributes,
|
|
13
14
|
:digital_link_attributes,
|
|
@@ -36,6 +37,7 @@ module Spree
|
|
|
36
37
|
:policy_attributes,
|
|
37
38
|
:post_attributes,
|
|
38
39
|
:post_category_attributes,
|
|
40
|
+
:price_list_attributes,
|
|
39
41
|
:product_attributes,
|
|
40
42
|
:promotion_attributes,
|
|
41
43
|
:promotion_rule_attributes,
|
|
@@ -68,6 +70,7 @@ module Spree
|
|
|
68
70
|
:theme_attributes,
|
|
69
71
|
:user_attributes,
|
|
70
72
|
:variant_attributes,
|
|
73
|
+
:webhook_endpoint_attributes,
|
|
71
74
|
:wishlist_attributes,
|
|
72
75
|
:wished_item_attributes,
|
|
73
76
|
:zone_attributes
|
|
@@ -88,7 +91,8 @@ module Spree
|
|
|
88
91
|
|
|
89
92
|
@@checkout_attributes = [
|
|
90
93
|
:coupon_code, :email, :shipping_method_id, :special_instructions, :use_billing, :use_shipping,
|
|
91
|
-
:user_id, :bill_address_id, :ship_address_id, :accept_marketing, :signup_for_an_account, :currency
|
|
94
|
+
:user_id, :bill_address_id, :ship_address_id, :accept_marketing, :signup_for_an_account, :currency,
|
|
95
|
+
:internal_note
|
|
92
96
|
]
|
|
93
97
|
|
|
94
98
|
@@classification_attributes = [
|
|
@@ -101,6 +105,8 @@ module Spree
|
|
|
101
105
|
|
|
102
106
|
@@custom_domain_attributes = [:url, :default]
|
|
103
107
|
|
|
108
|
+
@@customer_group_attributes = [:name, :description]
|
|
109
|
+
|
|
104
110
|
@@customer_return_attributes = [:stock_location_id, {
|
|
105
111
|
return_items_attributes: [:id, :inventory_unit_id, :return_authorization_id, :returned, :pre_tax_amount,
|
|
106
112
|
:acceptance_status, :exchange_variant_id, :resellable]
|
|
@@ -162,6 +168,8 @@ module Spree
|
|
|
162
168
|
|
|
163
169
|
@@post_category_attributes = [:title, :slug, :description]
|
|
164
170
|
|
|
171
|
+
@@price_list_attributes = [:name, :description, :match_policy, :starts_at, :ends_at, :status, :position]
|
|
172
|
+
|
|
165
173
|
@@product_properties_attributes = [:property_name, :property_id, :value, :position, :_destroy]
|
|
166
174
|
|
|
167
175
|
@@product_attributes = [
|
|
@@ -290,7 +298,8 @@ module Spree
|
|
|
290
298
|
|
|
291
299
|
@@user_attributes = [:email, :bill_address_id, :ship_address_id, :password, :first_name, :last_name,
|
|
292
300
|
:password_confirmation, :selected_locale, :avatar, :accepts_email_marketing, :phone,
|
|
293
|
-
|
|
301
|
+
:internal_note,
|
|
302
|
+
{ public_metadata: {}, private_metadata: {}, tag_list: [], customer_group_ids: [] }]
|
|
294
303
|
|
|
295
304
|
@@variant_attributes = [
|
|
296
305
|
:name, :presentation, :cost_price, :discontinue_on, :lock_version,
|
|
@@ -308,6 +317,8 @@ module Spree
|
|
|
308
317
|
}
|
|
309
318
|
]
|
|
310
319
|
|
|
320
|
+
@@webhook_endpoint_attributes = [:url, :secret, :active, subscriptions: []]
|
|
321
|
+
|
|
311
322
|
@@wishlist_attributes = [:name, :is_default, :is_private]
|
|
312
323
|
|
|
313
324
|
@@wished_item_attributes = [:variant_id, :quantity]
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
unless defined?(Spree::InstallGenerator)
|
|
2
|
-
require 'generators/spree/install/install_generator'
|
|
3
|
-
end
|
|
4
|
-
|
|
5
1
|
require 'generators/spree/dummy/dummy_generator'
|
|
6
2
|
require 'generators/spree/dummy_model/dummy_model_generator'
|
|
7
3
|
|
|
@@ -9,56 +5,85 @@ desc 'Generates a dummy app for testing'
|
|
|
9
5
|
namespace :common do
|
|
10
6
|
task :test_app, :user_class do |_t, args|
|
|
11
7
|
args.with_defaults(
|
|
8
|
+
authentication: 'dummy',
|
|
12
9
|
user_class: 'Spree::LegacyUser',
|
|
13
|
-
install_storefront:
|
|
14
|
-
install_admin:
|
|
15
|
-
|
|
10
|
+
install_storefront: false,
|
|
11
|
+
install_admin: false,
|
|
12
|
+
javascript: false,
|
|
13
|
+
css: false
|
|
16
14
|
)
|
|
17
15
|
require ENV['LIB_NAME'].to_s
|
|
18
16
|
|
|
17
|
+
# Convert to booleans (supports both string and boolean values for backwards compatibility)
|
|
18
|
+
install_admin = args[:install_admin].to_b
|
|
19
|
+
install_storefront = args[:install_storefront].to_b
|
|
20
|
+
javascript_enabled = args[:javascript].to_b
|
|
21
|
+
css_enabled = args[:css].to_b
|
|
22
|
+
|
|
23
|
+
# Admin and Storefront require JavaScript and CSS (Tailwind) to function properly
|
|
24
|
+
javascript_enabled ||= install_admin || install_storefront
|
|
25
|
+
css_enabled ||= install_admin || install_storefront
|
|
26
|
+
|
|
27
|
+
puts args
|
|
28
|
+
|
|
19
29
|
ENV['RAILS_ENV'] = 'test'
|
|
20
30
|
Rails.env = 'test'
|
|
21
31
|
|
|
22
|
-
api_only = ['spree/api', 'spree/core', 'spree/sample'].include?(ENV['LIB_NAME'])
|
|
23
|
-
skip_javascript = api_only || ENV['LIB_NAME'] == 'spree/emails'
|
|
24
|
-
|
|
25
32
|
dummy_app_args = [
|
|
26
33
|
"--lib_name=#{ENV['LIB_NAME']}"
|
|
27
34
|
]
|
|
28
|
-
if
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
# Use API mode only if no frontend components are needed
|
|
36
|
+
use_api_mode = !install_storefront && !install_admin && !javascript_enabled && !css_enabled
|
|
37
|
+
dummy_app_args << '--api' if use_api_mode
|
|
38
|
+
dummy_app_args << '--javascript' if javascript_enabled
|
|
39
|
+
dummy_app_args << '--css=tailwind' if css_enabled
|
|
40
|
+
|
|
41
|
+
puts dummy_app_args
|
|
42
|
+
|
|
33
43
|
Spree::DummyGenerator.start dummy_app_args
|
|
34
44
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
45
|
+
# Install JavaScript dependencies (importmap, turbo, stimulus) if JavaScript is enabled
|
|
46
|
+
# Rails includes the gems but doesn't run the installers automatically
|
|
47
|
+
if javascript_enabled
|
|
48
|
+
puts 'Installing JavaScript dependencies...'
|
|
49
|
+
system('yes | bundle exec rails importmap:install turbo:install stimulus:install')
|
|
38
50
|
end
|
|
39
51
|
|
|
40
52
|
# install devise if it's not the legacy user, useful for testing storefront
|
|
41
53
|
if args[:authentication] == 'devise' && args[:user_class] != 'Spree::LegacyUser'
|
|
42
54
|
system('bundle exec rails g devise:install --force --auto-accept')
|
|
43
55
|
system("bundle exec rails g devise #{args[:user_class]} --force --auto-accept")
|
|
56
|
+
system("bundle exec rails g devise #{args[:admin_user_class]} --force --auto-accept") if args[:admin_user_class].present? && args[:admin_user_class] != args[:user_class]
|
|
44
57
|
system('rm -rf spec') # we need to cleanup factories created by devise to avoid naming conflict
|
|
45
58
|
end
|
|
46
59
|
|
|
47
|
-
Spree
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
'--migrate=false',
|
|
51
|
-
'--seed=false',
|
|
52
|
-
'--sample=false',
|
|
53
|
-
"--install_storefront=#{args[:install_storefront]}",
|
|
54
|
-
"--install_admin=#{args[:install_admin]}",
|
|
55
|
-
"--user_class=#{args[:user_class]}",
|
|
56
|
-
"--authentication=#{args[:authentication]}"
|
|
57
|
-
]
|
|
60
|
+
# Run core Spree install generator
|
|
61
|
+
puts 'Running Spree install generator...'
|
|
62
|
+
system("bundle exec rails g spree:install --force --auto-accept --migrate=false --seed=false --sample=false --user_class=#{args[:user_class]} --admin_user_class=#{args[:admin_user_class]} --authentication=#{args[:authentication]}")
|
|
58
63
|
|
|
59
|
-
if
|
|
60
|
-
|
|
61
|
-
|
|
64
|
+
# Determine if we need to install admin/storefront
|
|
65
|
+
# Either via explicit flag or because we're testing that gem itself
|
|
66
|
+
needs_admin = install_admin || ENV['LIB_NAME'] == 'spree/admin'
|
|
67
|
+
needs_storefront = install_storefront || ENV['LIB_NAME'] == 'spree/storefront'
|
|
68
|
+
|
|
69
|
+
# Run admin install generator if requested or testing admin gem
|
|
70
|
+
if needs_admin
|
|
71
|
+
# Only run install if explicitly requested (not when testing admin gem itself)
|
|
72
|
+
if install_admin
|
|
73
|
+
puts 'Running Spree Admin install generator...'
|
|
74
|
+
system('bundle exec rails g spree:admin:install --force')
|
|
75
|
+
end
|
|
76
|
+
system('bundle exec rails g spree:admin:devise --force') if args[:authentication] == 'devise'
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Run storefront install generator if requested or testing storefront gem
|
|
80
|
+
if needs_storefront
|
|
81
|
+
# Only run install if explicitly requested (not when testing storefront gem itself)
|
|
82
|
+
if install_storefront
|
|
83
|
+
puts 'Running Spree Storefront install generator...'
|
|
84
|
+
system('bundle exec rails g spree:storefront:install --force --migrate=false')
|
|
85
|
+
end
|
|
86
|
+
system('bundle exec rails g spree:storefront:devise --force') if args[:authentication] == 'devise'
|
|
62
87
|
end
|
|
63
88
|
|
|
64
89
|
unless ENV['NO_MIGRATE']
|
|
@@ -74,13 +99,21 @@ namespace :common do
|
|
|
74
99
|
puts 'Running extension installation generator...'
|
|
75
100
|
|
|
76
101
|
if ENV['NO_MIGRATE']
|
|
77
|
-
"#{ENV['LIB_NAME'].camelize}::Generators::InstallGenerator".constantize.start([])
|
|
102
|
+
"#{ENV['LIB_NAME'].camelize}::Generators::InstallGenerator".constantize.start(['--force'])
|
|
78
103
|
else
|
|
79
|
-
"#{ENV['LIB_NAME'].camelize}::Generators::InstallGenerator".constantize.start(['--auto-run-migrations'])
|
|
104
|
+
"#{ENV['LIB_NAME'].camelize}::Generators::InstallGenerator".constantize.start(['--force', '--auto-run-migrations'])
|
|
80
105
|
end
|
|
81
|
-
rescue LoadError
|
|
106
|
+
rescue LoadError => e
|
|
107
|
+
puts "Error loading generator: #{e.message}"
|
|
82
108
|
puts 'Skipping installation no generator to run...'
|
|
83
109
|
end
|
|
110
|
+
|
|
111
|
+
# Precompile assets after all generators have run
|
|
112
|
+
# This ensures CSS entry points (like Spree Admin's Tailwind CSS) are created first
|
|
113
|
+
if javascript_enabled || css_enabled
|
|
114
|
+
puts 'Precompiling assets...'
|
|
115
|
+
system('bundle exec rake assets:precompile')
|
|
116
|
+
end
|
|
84
117
|
end
|
|
85
118
|
|
|
86
119
|
task :db_setup do |_t|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
FactoryBot.define do
|
|
2
|
+
factory :price_list, class: Spree::PriceList do
|
|
3
|
+
sequence(:name) { |n| "Price List #{n}" }
|
|
4
|
+
store { Spree::Store.default || create(:store) }
|
|
5
|
+
match_policy { 'all' }
|
|
6
|
+
|
|
7
|
+
trait :draft do
|
|
8
|
+
status { 'draft' }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
trait :active do
|
|
12
|
+
status { 'active' }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
trait :inactive do
|
|
16
|
+
status { 'inactive' }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
trait :scheduled do
|
|
20
|
+
status { 'scheduled' }
|
|
21
|
+
starts_at { 1.hour.from_now }
|
|
22
|
+
ends_at { 1.week.from_now }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
trait :with_date_range do
|
|
26
|
+
starts_at { 1.day.ago }
|
|
27
|
+
ends_at { 1.day.from_now }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
trait :any_match do
|
|
31
|
+
match_policy { 'any' }
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
FactoryBot.define do
|
|
2
|
+
factory :price_rule, class: Spree::PriceRule do
|
|
3
|
+
price_list
|
|
4
|
+
|
|
5
|
+
factory :zone_price_rule, class: Spree::PriceRules::ZoneRule do
|
|
6
|
+
after(:build) do |rule, evaluator|
|
|
7
|
+
rule.preferred_zone_ids = evaluator.zone_ids if evaluator.respond_to?(:zone_ids)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
transient do
|
|
11
|
+
zone_ids { [] }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
factory :volume_price_rule, class: Spree::PriceRules::VolumeRule do
|
|
16
|
+
after(:build) do |rule, evaluator|
|
|
17
|
+
rule.preferred_min_quantity = evaluator.min_quantity if evaluator.min_quantity.present?
|
|
18
|
+
rule.preferred_max_quantity = evaluator.max_quantity if evaluator.max_quantity.present?
|
|
19
|
+
rule.preferred_apply_to = evaluator.apply_to if evaluator.apply_to.present?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
transient do
|
|
23
|
+
min_quantity { nil }
|
|
24
|
+
max_quantity { nil }
|
|
25
|
+
apply_to { nil }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
factory :user_price_rule, class: Spree::PriceRules::UserRule do
|
|
30
|
+
after(:build) do |rule, evaluator|
|
|
31
|
+
rule.preferred_user_ids = evaluator.user_ids if evaluator.respond_to?(:user_ids)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
transient do
|
|
35
|
+
user_ids { [] }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
factory :customer_group_price_rule, class: Spree::PriceRules::CustomerGroupRule do
|
|
40
|
+
after(:build) do |rule, evaluator|
|
|
41
|
+
rule.preferred_customer_group_ids = evaluator.customer_group_ids if evaluator.respond_to?(:customer_group_ids)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
transient do
|
|
45
|
+
customer_group_ids { [] }
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -18,4 +18,16 @@ FactoryBot.define do
|
|
|
18
18
|
factory :promotion_rule_option_value, class: Spree::Promotion::Rules::OptionValue do
|
|
19
19
|
association :promotion
|
|
20
20
|
end
|
|
21
|
+
|
|
22
|
+
factory :promotion_rule_customer_group, class: Spree::Promotion::Rules::CustomerGroup do
|
|
23
|
+
association :promotion
|
|
24
|
+
|
|
25
|
+
after(:build) do |rule, evaluator|
|
|
26
|
+
rule.preferred_customer_group_ids = evaluator.customer_group_ids if evaluator.respond_to?(:customer_group_ids)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
transient do
|
|
30
|
+
customer_group_ids { [] }
|
|
31
|
+
end
|
|
32
|
+
end
|
|
21
33
|
end
|
|
@@ -5,10 +5,12 @@ FactoryBot.define do
|
|
|
5
5
|
variant
|
|
6
6
|
|
|
7
7
|
before(:create) do |stock_item|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
# Use really_destroy! (hard delete) to avoid unique index conflicts
|
|
9
|
+
# with deleted_at timestamps in MySQL when tests run quickly
|
|
10
|
+
Spree::StockItem.where(
|
|
11
|
+
variant_id: stock_item.variant_id,
|
|
12
|
+
stock_location_id: stock_item.stock_location_id
|
|
13
|
+
).delete_all
|
|
12
14
|
end
|
|
13
15
|
|
|
14
16
|
transient do
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
FactoryBot.define do
|
|
4
|
+
factory :webhook_delivery, class: Spree::WebhookDelivery do
|
|
5
|
+
webhook_endpoint
|
|
6
|
+
event_name { 'order.created' }
|
|
7
|
+
payload { { event: 'order.created', data: { id: 1 } } }
|
|
8
|
+
|
|
9
|
+
trait :pending do
|
|
10
|
+
response_code { nil }
|
|
11
|
+
execution_time { nil }
|
|
12
|
+
success { nil }
|
|
13
|
+
delivered_at { nil }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
trait :successful do
|
|
17
|
+
response_code { 200 }
|
|
18
|
+
execution_time { 150 }
|
|
19
|
+
success { true }
|
|
20
|
+
delivered_at { Time.current }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
trait :failed do
|
|
24
|
+
response_code { 500 }
|
|
25
|
+
execution_time { 200 }
|
|
26
|
+
success { false }
|
|
27
|
+
delivered_at { Time.current }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
trait :timeout do
|
|
31
|
+
response_code { nil }
|
|
32
|
+
error_type { 'timeout' }
|
|
33
|
+
execution_time { 30_000 }
|
|
34
|
+
success { false }
|
|
35
|
+
request_errors { 'execution expired' }
|
|
36
|
+
delivered_at { Time.current }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
trait :connection_error do
|
|
40
|
+
response_code { nil }
|
|
41
|
+
error_type { 'connection_error' }
|
|
42
|
+
execution_time { 100 }
|
|
43
|
+
success { false }
|
|
44
|
+
request_errors { 'Connection refused' }
|
|
45
|
+
delivered_at { Time.current }
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|