spree_core 6.0.0.beta4 → 6.0.0.rc2
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/README.md +5 -5
- data/app/helpers/spree/images_helper.rb +0 -57
- data/app/jobs/spree/base_job.rb +21 -0
- data/app/jobs/spree/carts/reap_expired_job.rb +2 -2
- data/app/jobs/spree/collections/regenerate_time_based_job.rb +6 -3
- data/app/jobs/spree/orders/finalize_stale_drafts_job.rb +8 -5
- data/app/jobs/spree/payments/cancel_unused_sessions_job.rb +61 -0
- data/app/jobs/spree/search_provider/index_job.rb +4 -0
- data/app/jobs/spree/seller_payouts/sweep_seller_job.rb +2 -0
- data/app/jobs/spree/uploads/purge_unattached_job.rb +49 -0
- data/app/mailers/spree/admin_user_mailer.rb +4 -19
- data/app/mailers/spree/base_mailer.rb +97 -13
- data/app/mailers/spree/email_template_mailer.rb +27 -0
- data/app/mailers/spree/export_mailer.rb +3 -4
- data/app/mailers/spree/import_mailer.rb +3 -4
- data/app/mailers/spree/invitation_mailer.rb +24 -7
- data/app/mailers/spree/seller_user_mailer.rb +4 -16
- data/app/mailers/spree/webhook_mailer.rb +2 -2
- data/app/models/concerns/spree/acted_by.rb +1 -1
- data/app/models/concerns/spree/admin_user_methods.rb +15 -1
- data/app/models/concerns/spree/api_typed.rb +91 -0
- data/app/models/concerns/spree/calculated_adjustments.rb +41 -13
- data/app/models/concerns/spree/calculator/currency_amounts.rb +1 -1
- data/app/models/concerns/spree/calculator/tiers.rb +63 -0
- data/app/models/concerns/spree/canonical_decimals.rb +61 -0
- data/app/models/concerns/spree/customer_methods.rb +23 -18
- data/app/models/concerns/spree/derived_number.rb +11 -13
- data/app/models/concerns/spree/email_template_identity.rb +52 -0
- data/app/models/concerns/spree/parameterizable_name.rb +2 -0
- data/app/models/concerns/spree/payment_session_transitions.rb +8 -2
- data/app/models/concerns/spree/post_sale/taxation.rb +54 -0
- data/app/models/concerns/spree/post_sale/taxed_line.rb +51 -0
- data/app/models/concerns/spree/preference_schema/json_schema.rb +139 -0
- data/app/models/concerns/spree/preference_schema.rb +62 -32
- data/app/models/concerns/spree/product_scopes.rb +16 -2
- data/app/models/concerns/spree/provider_listing.rb +41 -0
- data/app/models/concerns/spree/publishable.rb +82 -14
- data/app/models/concerns/spree/purchase/addresses.rb +23 -10
- data/app/models/concerns/spree/purchase/currency.rb +1 -1
- data/app/models/concerns/spree/purchase/deprecated_aliases.rb +87 -0
- data/app/models/concerns/spree/purchase/gift_cards.rb +10 -4
- data/app/models/concerns/spree/purchase/locale.rb +1 -1
- data/app/models/concerns/spree/purchase/payment_processing.rb +8 -4
- data/app/models/concerns/spree/purchase/purchase_order.rb +9 -4
- data/app/models/concerns/spree/purchase/store_credits.rb +36 -1
- data/app/models/concerns/spree/purchase/totals.rb +49 -8
- data/app/models/concerns/spree/ransackable_attributes.rb +46 -0
- data/app/models/concerns/spree/receivable.rb +1 -1
- data/app/models/concerns/spree/searchable.rb +0 -4
- data/app/models/concerns/spree/secret_preferences.rb +59 -0
- data/app/models/concerns/spree/signed_id_attachments.rb +54 -0
- data/app/models/concerns/spree/single_store_resource.rb +1 -1
- data/app/models/concerns/spree/stores/email_branding.rb +32 -0
- data/app/models/concerns/spree/stores/markets.rb +5 -2
- data/app/models/concerns/spree/type_labels.rb +38 -0
- data/app/models/concerns/spree/typed_adjustment_line.rb +5 -6
- data/app/models/concerns/spree/typed_associations.rb +12 -18
- data/app/models/concerns/spree/vat_price_calculation.rb +5 -6
- data/app/models/spree/address.rb +12 -2
- data/app/models/spree/adjusters/largest_remainder.rb +14 -1
- data/app/models/spree/adjusters/promotion.rb +4 -19
- data/app/models/spree/allowed_origin.rb +3 -1
- data/app/models/spree/api_key.rb +5 -6
- data/app/models/spree/authentication/strategies/oidc_strategy.rb +5 -5
- data/app/models/spree/base.rb +99 -22
- data/app/models/spree/calculator/flat_percent_item_total.rb +2 -4
- data/app/models/spree/calculator/flat_rate.rb +3 -5
- data/app/models/spree/calculator/flexi_rate.rb +4 -6
- data/app/models/spree/calculator/percent_on_line_item.rb +2 -2
- data/app/models/spree/calculator/price_sack.rb +5 -7
- data/app/models/spree/calculator/shipping/digital_delivery.rb +3 -5
- data/app/models/spree/calculator/shipping/flat_percent_item_total.rb +7 -7
- data/app/models/spree/calculator/shipping/flat_rate.rb +5 -7
- data/app/models/spree/calculator/shipping/flexi_rate.rb +4 -6
- data/app/models/spree/calculator/shipping/per_item.rb +3 -5
- data/app/models/spree/calculator/shipping/price_sack.rb +5 -7
- data/app/models/spree/calculator/tiered_flat_rate.rb +7 -24
- data/app/models/spree/calculator/tiered_percent.rb +7 -25
- data/app/models/spree/cart.rb +78 -18
- data/app/models/spree/catalog.rb +1 -0
- data/app/models/spree/catalog_price.rb +0 -7
- data/app/models/spree/catalog_price_tier.rb +0 -8
- data/app/models/spree/category.rb +3 -1
- data/app/models/spree/channel/gating.rb +3 -2
- data/app/models/spree/channel.rb +6 -4
- data/app/models/spree/claim.rb +22 -1
- data/app/models/spree/claim_line_item.rb +41 -6
- data/app/models/spree/collection.rb +2 -1
- data/app/models/spree/collection_rule.rb +5 -21
- data/app/models/spree/commission_line.rb +1 -1
- data/app/models/spree/commission_rate.rb +7 -4
- data/app/models/spree/commission_rate_value.rb +1 -1
- data/app/models/spree/commission_rule.rb +4 -11
- data/app/models/spree/commission_rules/category_rule.rb +2 -5
- data/app/models/spree/commission_rules/item_total_rule.rb +2 -2
- data/app/models/spree/commission_rules/product_rule.rb +1 -1
- data/app/models/spree/commission_rules/seller_rule.rb +2 -5
- data/app/models/spree/company.rb +1 -0
- data/app/models/spree/company_invitation.rb +1 -0
- data/app/models/spree/consent_record.rb +0 -1
- data/app/models/spree/credit_card.rb +1 -1
- data/app/models/spree/current.rb +23 -0
- data/app/models/spree/custom_field.rb +2 -2
- data/app/models/spree/custom_field_definition.rb +20 -35
- data/app/models/spree/custom_fields/boolean.rb +1 -1
- data/app/models/spree/custom_fields/json.rb +1 -1
- data/app/models/spree/customer_group.rb +1 -0
- data/app/models/spree/data_feed/google.rb +0 -2
- data/app/models/spree/data_request.rb +2 -1
- data/app/models/spree/delivery_method.rb +36 -14
- data/app/models/spree/delivery_method_rule.rb +4 -11
- data/app/models/spree/delivery_method_rules/channel_rule.rb +2 -5
- data/app/models/spree/delivery_method_rules/item_total_rule.rb +2 -2
- data/app/models/spree/delivery_profile.rb +1 -0
- data/app/models/spree/delivery_rate.rb +7 -8
- data/app/models/spree/delivery_rate_provider/base.rb +1 -0
- data/app/models/spree/delivery_zone.rb +1 -2
- data/app/models/spree/delivery_zone_member.rb +4 -4
- data/app/models/spree/digital_asset.rb +7 -0
- data/app/models/spree/digital_asset_provider/base.rb +2 -0
- data/app/models/spree/digital_link.rb +2 -5
- data/app/models/spree/discount.rb +1 -1
- data/app/models/spree/email_template.rb +25 -0
- data/app/models/spree/email_template_draft.rb +13 -0
- data/app/models/spree/email_template_revision.rb +17 -0
- data/app/models/spree/email_templates/entry.rb +118 -0
- data/app/models/spree/email_templates/sample_record.rb +16 -0
- data/app/models/spree/emails/branding.rb +80 -0
- data/app/models/spree/exchange.rb +16 -1
- data/app/models/spree/exchange_line_item.rb +121 -5
- data/app/models/spree/export.rb +0 -1
- data/app/models/spree/exports/products.rb +10 -1
- data/app/models/spree/exports/report.rb +3 -3
- data/app/models/spree/fee.rb +4 -2
- data/app/models/spree/file_upload.rb +155 -0
- data/app/models/spree/fulfillment.rb +66 -30
- data/app/models/spree/fulfillment_changer.rb +2 -2
- data/app/models/spree/fulfillment_group.rb +6 -1
- data/app/models/spree/fulfillment_item.rb +0 -4
- data/app/models/spree/fulfillment_provider/base.rb +1 -0
- data/app/models/spree/gateway/bogus.rb +6 -0
- data/app/models/spree/gateway/custom_payment_source_method.rb +5 -0
- data/app/models/spree/gateway.rb +6 -2
- data/app/models/spree/gift_card.rb +18 -8
- data/app/models/spree/gift_card_batch.rb +3 -5
- data/app/models/spree/import.rb +5 -7
- data/app/models/spree/import_mapping.rb +1 -2
- data/app/models/spree/import_row.rb +2 -2
- data/app/models/spree/import_schemas/products.rb +1 -0
- data/app/models/spree/integration.rb +9 -19
- data/app/models/spree/invitation.rb +5 -5
- data/app/models/spree/line_item.rb +15 -4
- data/app/models/spree/locale.rb +11 -8
- data/app/models/spree/market.rb +8 -2
- data/app/models/spree/media.rb +1 -9
- data/app/models/spree/newsletter_subscriber.rb +4 -0
- data/app/models/spree/option_type.rb +2 -1
- data/app/models/spree/option_value.rb +2 -1
- data/app/models/spree/order.rb +60 -142
- data/app/models/spree/order_group.rb +18 -4
- data/app/models/spree/order_inventory.rb +10 -5
- data/app/models/spree/order_promotion.rb +1 -1
- data/app/models/spree/order_routing/has_strategy_preference.rb +1 -1
- data/app/models/spree/order_routing/strategy/base.rb +4 -2
- data/app/models/spree/order_routing/strategy/rules.rb +1 -1
- data/app/models/spree/order_routing_rule.rb +6 -22
- data/app/models/spree/package_type.rb +2 -2
- data/app/models/spree/payment/gateway_options.rb +15 -53
- data/app/models/spree/payment/processing.rb +2 -4
- data/app/models/spree/payment.rb +21 -13
- data/app/models/spree/payment_method/check.rb +2 -0
- data/app/models/spree/payment_method/session_instrumentation.rb +1 -0
- data/app/models/spree/payment_method/store_credit.rb +15 -13
- data/app/models/spree/payment_method.rb +78 -6
- data/app/models/spree/payment_session.rb +5 -1
- data/app/models/spree/payment_setup_session.rb +1 -0
- data/app/models/spree/payout_provider/base.rb +3 -1
- data/app/models/spree/pickup_point_provider/base.rb +2 -0
- data/app/models/spree/policy.rb +1 -0
- data/app/models/spree/price.rb +17 -14
- data/app/models/spree/price_adjustment_tier.rb +4 -0
- data/app/models/spree/price_list.rb +14 -9
- data/app/models/spree/price_rules/channel_rule.rb +3 -6
- data/app/models/spree/price_rules/customer_group_rule.rb +3 -6
- data/app/models/spree/price_rules/market_rule.rb +2 -5
- data/app/models/spree/price_rules/user_rule.rb +1 -3
- data/app/models/spree/product/channels.rb +9 -2
- data/app/models/spree/product.rb +54 -30
- data/app/models/spree/product_submission.rb +0 -12
- data/app/models/spree/product_type.rb +1 -1
- data/app/models/spree/promotion/actions/create_line_items.rb +28 -18
- data/app/models/spree/promotion/rules/category.rb +1 -5
- data/app/models/spree/promotion/rules/channel.rb +2 -9
- data/app/models/spree/promotion/rules/country.rb +3 -8
- data/app/models/spree/promotion/rules/currency.rb +1 -5
- data/app/models/spree/promotion/rules/customer_group.rb +2 -9
- data/app/models/spree/promotion/rules/first_order.rb +0 -4
- data/app/models/spree/promotion/rules/item_total.rb +6 -10
- data/app/models/spree/promotion/rules/market.rb +2 -9
- data/app/models/spree/promotion/rules/one_use_per_user.rb +0 -4
- data/app/models/spree/promotion/rules/option_value.rb +2 -6
- data/app/models/spree/promotion/rules/product.rb +1 -5
- data/app/models/spree/promotion/rules/user.rb +0 -4
- data/app/models/spree/promotion/rules/user_logged_in.rb +0 -4
- data/app/models/spree/promotion.rb +36 -6
- data/app/models/spree/promotion_action.rb +7 -14
- data/app/models/spree/promotion_action_line_item.rb +1 -1
- data/app/models/spree/promotion_handler/coupon.rb +59 -27
- data/app/models/spree/promotion_rule.rb +7 -14
- data/app/models/spree/purchase_order.rb +3 -0
- data/app/models/spree/quantity_rule.rb +1 -1
- data/app/models/spree/refund.rb +41 -18
- data/app/models/spree/return.rb +31 -2
- data/app/models/spree/return_line_item.rb +65 -14
- data/app/models/spree/role.rb +7 -7
- data/app/models/spree/saved_report.rb +2 -1
- data/app/models/spree/search_provider/base.rb +4 -0
- data/app/models/spree/seller.rb +10 -2
- data/app/models/spree/seller_payout.rb +8 -0
- data/app/models/spree/seller_requirement.rb +5 -12
- data/app/models/spree/seller_requirement_custom_field.rb +1 -2
- data/app/models/spree/seller_requirement_submission.rb +3 -2
- data/app/models/spree/seller_requirements/accept_terms.rb +2 -3
- data/app/models/spree/seller_transfer.rb +6 -0
- data/app/models/spree/shipping_label.rb +2 -0
- data/app/models/spree/stock/availability_validator.rb +2 -2
- data/app/models/spree/stock/estimator.rb +1 -1
- data/app/models/spree/stock/inventory_unit_builder.rb +1 -1
- data/app/models/spree/stock/packer.rb +2 -2
- data/app/models/spree/stock/splitter/weight.rb +1 -1
- data/app/models/spree/stock_level/custom_events.rb +6 -0
- data/app/models/spree/stock_level.rb +3 -1
- data/app/models/spree/stock_location.rb +1 -0
- data/app/models/spree/stock_movement.rb +1 -1
- data/app/models/spree/stock_receipt_item.rb +1 -1
- data/app/models/spree/stock_reservation.rb +2 -2
- data/app/models/spree/stock_transfer.rb +6 -2
- data/app/models/spree/store.rb +70 -19
- data/app/models/spree/store_credit.rb +13 -13
- data/app/models/spree/store_credit_event.rb +5 -5
- data/app/models/spree/supplier.rb +1 -0
- data/app/models/spree/tax_category.rb +1 -0
- data/app/models/spree/tax_exemption_certificate.rb +3 -0
- data/app/models/spree/tax_identifier.rb +3 -1
- data/app/models/spree/tax_line.rb +53 -3
- data/app/models/spree/tax_provider/base.rb +71 -14
- data/app/models/spree/tax_provider/internal.rb +70 -41
- data/app/models/spree/tax_provider/recorded_share.rb +114 -0
- data/app/models/spree/tax_rate.rb +30 -8
- data/app/models/spree/taxon.rb +1 -1
- data/app/models/spree/taxonomy.rb +0 -1
- data/app/models/spree/update_status.rb +25 -0
- data/app/models/spree/variant.rb +10 -12
- data/app/models/spree/variant_media.rb +1 -1
- data/app/models/spree/webhook_delivery.rb +1 -0
- data/app/models/spree/webhook_endpoint.rb +46 -13
- data/app/models/spree/wishlist.rb +1 -6
- data/app/models/spree/wishlist_item/custom_events.rb +6 -0
- data/app/presenters/spree/csv/customer_presenter.rb +1 -1
- data/app/presenters/spree/csv/newsletter_subscriber_presenter.rb +1 -1
- data/app/presenters/spree/csv/order_line_item_presenter.rb +10 -6
- data/app/presenters/spree/csv/price_list_price_presenter.rb +3 -8
- data/app/presenters/spree/csv/product_variant_presenter.rb +59 -20
- data/app/presenters/spree/csv/purchase_order_item_presenter.rb +1 -3
- data/app/serializers/spree/emails/base_serializer.rb +14 -0
- data/app/serializers/spree/emails/export_serializer.rb +13 -0
- data/app/serializers/spree/emails/import_serializer.rb +19 -0
- data/app/serializers/spree/emails/invitation_serializer.rb +28 -0
- data/app/serializers/spree/emails/store_serializer.rb +31 -0
- data/app/serializers/spree/emails/user_serializer.rb +12 -0
- data/app/serializers/spree/emails/webhook_endpoint_serializer.rb +16 -0
- data/app/services/spree/carts/create.rb +8 -2
- data/app/services/spree/carts/destroy.rb +2 -2
- data/app/services/spree/carts/remove_out_of_stock_items.rb +2 -2
- data/app/services/spree/carts/split_by_seller.rb +1 -1
- data/app/services/spree/carts/update.rb +22 -8
- data/app/services/spree/catalogs/set_product_terms.rb +1 -1
- data/app/services/spree/categories/add_products.rb +13 -31
- data/app/services/spree/categories/remove_products.rb +12 -51
- data/app/services/spree/checkout/advance.rb +1 -4
- data/app/services/spree/collections/add_products.rb +10 -23
- data/app/services/spree/collections/remove_products.rb +7 -43
- data/app/services/spree/coupon_codes/bulk_generate.rb +8 -14
- data/app/services/spree/data_requests/create.rb +1 -1
- data/app/services/spree/deliveries/destroy.rb +2 -2
- data/app/services/spree/email_templates/check.rb +58 -0
- data/app/services/spree/email_templates/no_sample_record.rb +7 -0
- data/app/services/spree/email_templates/preview.rb +99 -0
- data/app/services/spree/emails/file_system.rb +23 -0
- data/app/services/spree/emails/filters.rb +84 -0
- data/app/services/spree/emails/liquid_context.rb +48 -0
- data/app/services/spree/emails/rendered_email.rb +14 -0
- data/app/services/spree/emails/renderer.rb +125 -0
- data/app/services/spree/emails/template.rb +51 -0
- data/app/services/spree/emails/template_data.rb +23 -0
- data/app/services/spree/emails/template_resolver.rb +109 -0
- data/app/services/spree/emails/text_converter.rb +72 -0
- data/app/services/spree/emails/translation_inliner.rb +134 -0
- data/app/services/spree/imports/row_processors/price_list_price.rb +10 -10
- data/app/services/spree/imports/row_processors/product_variant.rb +77 -34
- data/app/services/spree/imports/row_processors/purchase_order.rb +13 -13
- data/app/services/spree/locales.rb +43 -10
- data/app/services/spree/newsletter/subscribe.rb +8 -12
- data/app/services/spree/orders/build_fulfillments.rb +3 -2
- data/app/services/spree/orders/create.rb +5 -4
- data/app/services/spree/orders/discounts/create.rb +14 -11
- data/app/services/spree/orders/discounts/destroy.rb +1 -0
- data/app/services/spree/orders/discounts/update.rb +1 -0
- data/app/services/spree/orders/fees/create.rb +1 -0
- data/app/services/spree/orders/fees/destroy.rb +1 -0
- data/app/services/spree/orders/fees/update.rb +1 -0
- data/app/services/spree/orders/remove_line_item.rb +13 -3
- data/app/services/spree/orders/update.rb +10 -6
- data/app/services/spree/orders/update_item.rb +6 -3
- data/app/services/spree/orders/update_statuses.rb +3 -1
- data/app/services/spree/prices/bulk_upsert.rb +32 -25
- data/app/services/spree/product_memberships.rb +61 -0
- data/app/services/spree/returns/eligibility_validator.rb +1 -1
- data/app/services/spree/search_provider/custom_field_schema.rb +2 -2
- data/app/services/spree/seeds/commission_rates.rb +1 -1
- data/app/services/spree/seeds/digital_delivery.rb +1 -1
- data/app/services/spree/seeds/payment_methods.rb +2 -2
- data/app/services/spree/seeds/saved_reports.rb +3 -3
- data/app/services/spree/seeds/stores.rb +1 -1
- data/app/services/spree/sellers/requirements.rb +1 -2
- data/app/services/spree/shipping_labels/confirm_refund.rb +1 -1
- data/app/services/spree/shipping_labels/store_file.rb +3 -3
- data/app/services/spree/stock_levels/correct.rb +3 -3
- data/app/services/spree/stock_reservations/reserve.rb +2 -3
- data/app/services/spree/store_credits/apply.rb +15 -13
- data/app/services/spree/stores/provision_defaults.rb +23 -25
- data/app/services/spree/update_check.rb +160 -0
- data/app/services/spree/uploads/assign_stores.rb +92 -0
- data/app/subscribers/spree/seller_onboarding_subscriber.rb +1 -1
- data/app/validators/spree/attachment_content_type_validator.rb +19 -2
- data/app/validators/spree/locale_codes_validator.rb +22 -0
- data/app/views/layouts/spree/base_mailer.html.erb +2 -43
- data/app/views/layouts/spree/base_mailer.liquid +79 -0
- data/app/views/spree/admin_user_mailer/password_reset_email.liquid +14 -0
- data/app/views/spree/export_mailer/export_done.liquid +12 -0
- data/app/views/spree/import_mailer/import_done.liquid +15 -0
- data/app/views/spree/invitation_mailer/invitation_accepted.liquid +9 -0
- data/app/views/spree/invitation_mailer/invitation_email.liquid +13 -0
- data/app/views/spree/seller_user_mailer/password_reset_email.liquid +14 -0
- data/app/views/spree/shared/_mailer_button.html.erb +4 -5
- data/app/views/spree/shared/_mailer_hero.html.erb +6 -5
- data/app/views/spree/shared/_summary_row.liquid +8 -0
- data/app/views/spree/webhook_mailer/endpoint_disabled.liquid +21 -0
- data/app/workflows/spree/carts/add_item.rb +4 -4
- data/app/workflows/spree/carts/complete.rb +13 -3
- data/app/workflows/spree/carts/merge.rb +1 -1
- data/app/workflows/spree/carts/recalculate_totals.rb +5 -0
- data/app/workflows/spree/carts/upsert_items.rb +18 -9
- data/app/workflows/spree/claims/approve.rb +5 -22
- data/app/workflows/spree/claims/cancel.rb +5 -21
- data/app/workflows/spree/claims/create.rb +15 -0
- data/app/workflows/spree/claims/deny.rb +7 -0
- data/app/workflows/spree/claims/resolve.rb +34 -31
- data/app/workflows/spree/customers/anonymize.rb +3 -4
- data/app/workflows/spree/customers/create.rb +1 -1
- data/app/workflows/spree/data_requests/fulfill.rb +2 -2
- data/app/workflows/spree/deliveries/update_tracking.rb +1 -1
- data/app/workflows/spree/email_templates/discard_draft.rb +20 -0
- data/app/workflows/spree/email_templates/publish.rb +70 -0
- data/app/workflows/spree/email_templates/restore_revision.rb +33 -0
- data/app/workflows/spree/email_templates/revert.rb +29 -0
- data/app/workflows/spree/email_templates/save_draft.rb +85 -0
- data/app/workflows/spree/exchanges/approve.rb +5 -22
- data/app/workflows/spree/exchanges/cancel.rb +5 -21
- data/app/workflows/spree/exchanges/create.rb +6 -0
- data/app/workflows/spree/exchanges/fulfill.rb +75 -51
- data/app/workflows/spree/exchanges/receive.rb +6 -65
- data/app/workflows/spree/fulfillments/cancel.rb +1 -1
- data/app/workflows/spree/fulfillments/create.rb +53 -49
- data/app/workflows/spree/fulfillments/fulfill.rb +23 -27
- data/app/workflows/spree/fulfillments/mark_delivered.rb +1 -1
- data/app/workflows/spree/fulfillments/replacements.rb +59 -0
- data/app/workflows/spree/gift_cards/apply.rb +2 -2
- data/app/workflows/spree/orders/add_item.rb +5 -1
- data/app/workflows/spree/orders/cancel.rb +3 -3
- data/app/workflows/spree/orders/complete.rb +16 -8
- data/app/workflows/spree/payments/capture.rb +20 -5
- data/app/workflows/spree/payments/process.rb +5 -3
- data/app/workflows/spree/post_sale/approval.rb +35 -0
- data/app/workflows/spree/post_sale/cancellation.rb +44 -0
- data/app/workflows/spree/post_sale/receipt.rb +92 -0
- data/app/workflows/spree/price_lists/update.rb +4 -4
- data/app/workflows/spree/products/nested_attributes.rb +1 -1
- data/app/workflows/spree/purchase_orders/cancel.rb +1 -1
- data/app/workflows/spree/purchase_orders/close.rb +3 -31
- data/app/workflows/spree/purchase_orders/create.rb +3 -1
- data/app/workflows/spree/purchase_orders/mark_draft.rb +2 -2
- data/app/workflows/spree/purchase_orders/mark_ordered.rb +2 -2
- data/app/workflows/spree/purchase_orders/receive.rb +1 -1
- data/app/workflows/spree/purchase_orders/update.rb +5 -34
- data/app/workflows/spree/receivables/closing_short.rb +46 -0
- data/app/workflows/spree/receivables/draft_editing.rb +48 -0
- data/app/workflows/spree/refunds/create.rb +5 -2
- data/app/workflows/spree/refunds/order_payments.rb +14 -2
- data/app/workflows/spree/refunds/tax_credit.rb +67 -0
- data/app/workflows/spree/returns/approve.rb +5 -22
- data/app/workflows/spree/returns/cancel.rb +5 -22
- data/app/workflows/spree/returns/create.rb +8 -0
- data/app/workflows/spree/returns/receive.rb +5 -76
- data/app/workflows/spree/returns/refund.rb +31 -8
- data/app/workflows/spree/seller_requirement_submissions/create.rb +1 -2
- data/app/workflows/spree/seller_transfers/reverse.rb +28 -1
- data/app/workflows/spree/shipping_labels/purchase.rb +8 -8
- data/app/workflows/spree/shipping_labels/record.rb +7 -7
- data/app/workflows/spree/shipping_labels/refund.rb +2 -2
- data/app/workflows/spree/stock_receipts/recording.rb +4 -4
- data/app/workflows/spree/stock_transfers/cancel.rb +2 -2
- data/app/workflows/spree/stock_transfers/close.rb +3 -30
- data/app/workflows/spree/stock_transfers/create.rb +3 -1
- data/app/workflows/spree/stock_transfers/mark_draft.rb +1 -1
- data/app/workflows/spree/stock_transfers/mark_in_transit.rb +3 -3
- data/app/workflows/spree/stock_transfers/mark_ready.rb +2 -2
- data/app/workflows/spree/stock_transfers/receive.rb +1 -1
- data/app/workflows/spree/stock_transfers/update.rb +5 -33
- data/config/currency_exponents.json +180 -0
- data/config/i18n-tasks.yml +32 -18
- data/config/initializers/alba.rb +7 -0
- data/config/language_names.csv +264 -0
- data/config/locales/ar.yml +811 -0
- data/config/locales/be.yml +855 -0
- data/config/locales/bg.yml +723 -0
- data/config/locales/ca.yml +689 -0
- data/config/locales/content_locales.rb +9 -0
- data/config/locales/cs.yml +855 -0
- data/config/locales/da.yml +771 -0
- data/config/locales/de-CH.yml +248 -0
- data/config/locales/de.yml +835 -0
- data/config/locales/el.yml +769 -0
- data/config/locales/en.yml +47 -505
- data/config/locales/es-CL.yml +301 -0
- data/config/locales/es-EC.yml +186 -0
- data/config/locales/es-MX.yml +334 -0
- data/config/locales/es.yml +831 -0
- data/config/locales/et.yml +644 -0
- data/config/locales/fa.yml +709 -0
- data/config/locales/fi.yml +771 -0
- data/config/locales/fr.yml +830 -0
- data/config/locales/hu.yml +751 -0
- data/config/locales/id.yml +756 -0
- data/config/locales/it.yml +833 -0
- data/config/locales/ja.yml +726 -0
- data/config/locales/km.yml +759 -0
- data/config/locales/ko.yml +575 -0
- data/config/locales/ku.yml +753 -0
- data/config/locales/lt.yml +821 -0
- data/config/locales/lv.yml +685 -0
- data/config/locales/nb.yml +824 -0
- data/config/locales/ne.yml +823 -0
- data/config/locales/nl.yml +826 -0
- data/config/locales/pl.yml +835 -0
- data/config/locales/pt-BR.yml +547 -0
- data/config/locales/pt.yml +636 -0
- data/config/locales/ro.yml +750 -0
- data/config/locales/ru.yml +834 -0
- data/config/locales/sk.yml +680 -0
- data/config/locales/sl-SI.yml +600 -0
- data/config/locales/sv.yml +827 -0
- data/config/locales/th.yml +745 -0
- data/config/locales/tr.yml +777 -0
- data/config/locales/uk.yml +836 -0
- data/config/locales/vi.yml +768 -0
- data/config/locales/zh-CN.yml +786 -0
- data/config/locales/zh-TW.yml +834 -0
- data/db/migrate/20260925000001_add_replacement_to_spree_fulfillment_items.rb +5 -0
- data/db/migrate/20261001000001_add_post_sale_tax.rb +30 -0
- data/db/migrate/20261001000001_convert_preferences_to_json.rb +166 -0
- data/db/migrate/20261001000001_create_spree_email_templates.rb +52 -0
- data/db/migrate/20261009000001_change_money_columns_to_decimal_19_4.rb +116 -0
- data/db/migrate/20261010000001_add_store_id_to_active_storage_blobs.rb +12 -0
- data/lib/generators/spree/dummy/dummy_generator.rb +0 -9
- data/lib/generators/spree/dummy/templates/rails/test.rb +26 -0
- data/lib/spree/checkout/default_requirements.rb +37 -13
- data/lib/spree/core/configuration.rb +19 -1
- data/lib/spree/core/controller_helpers/store.rb +1 -1
- data/lib/spree/core/dependencies.rb +5 -4
- data/lib/spree/core/emails/escaped_output.rb +60 -0
- data/lib/spree/core/engine.rb +72 -165
- data/lib/spree/core/permissions/default_catalog.rb +5 -0
- data/lib/spree/core/preferences/invalid_preferences.rb +18 -0
- data/lib/spree/core/preferences/json_conversion.rb +186 -0
- data/lib/spree/core/preferences/masking.rb +55 -2
- data/lib/spree/core/preferences/preferable.rb +343 -103
- data/lib/spree/core/preferences/preferable_class_methods.rb +188 -136
- data/lib/spree/core/previews/import_preview.rb +10 -0
- data/lib/spree/core/ransack_configuration.rb +13 -2
- data/lib/spree/core/tax/provider_error.rb +37 -0
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/core.rb +91 -373
- data/lib/spree/emails/editable_templates.rb +82 -0
- data/lib/spree/events/catalog.rb +189 -0
- data/lib/spree/events.rb +21 -1
- data/lib/spree/hooks.rb +0 -17
- data/lib/spree/i18n.rb +32 -15
- data/lib/spree/iso_data.rb +7 -0
- data/lib/spree/localized_number.rb +6 -0
- data/lib/spree/migrations.rb +4 -1
- data/lib/spree/money.rb +196 -15
- data/lib/spree/reporting/adapters/base.rb +7 -6
- data/lib/spree/reporting/adapters/live.rb +6 -6
- data/lib/spree/reporting/default_vocabulary.rb +22 -10
- data/lib/spree/reporting/hydration.rb +1 -1
- data/lib/spree/reporting/query.rb +8 -0
- data/lib/spree/reporting/registry.rb +13 -0
- data/lib/spree/reporting/schema.rb +10 -10
- data/lib/spree/testing_support/editable_email_templates.rb +61 -0
- data/lib/spree/testing_support/emails.rb +22 -0
- data/lib/spree/testing_support/factories/cart_factory.rb +1 -1
- data/lib/spree/testing_support/factories/email_template_factory.rb +28 -0
- data/lib/spree/testing_support/factories/order_factory.rb +2 -2
- data/lib/spree/testing_support/factories/product_factory.rb +9 -0
- data/lib/spree/testing_support/factories/refund_factory.rb +1 -1
- data/lib/spree/testing_support/factories/stock_factory.rb +1 -1
- data/lib/spree/testing_support/factories/variant_factory.rb +1 -1
- data/lib/spree/testing_support/i18n.rb +3 -94
- data/lib/spree/testing_support/lifecycle_events.rb +1 -1
- data/lib/spree/testing_support/order_walkthrough.rb +1 -1
- data/lib/spree/testing_support/preferences.rb +0 -5
- data/lib/spree/testing_support/store.rb +9 -1
- data/lib/spree/upgrades/5_6_to_6_0/manifest.yml +67 -1
- data/lib/spree/uploads.rb +101 -0
- data/lib/tasks/categories_and_collections.rake +3 -3
- data/lib/tasks/core.rake +6 -4
- data/lib/tasks/markets.rake +2 -1
- data/lib/tasks/media.rake +3 -3
- data/lib/tasks/migrate_users_to_customers.rake +23 -18
- data/lib/tasks/money.rake +46 -0
- data/lib/tasks/package_types.rake +1 -1
- data/lib/tasks/preferences_json.rake +101 -0
- data/lib/tasks/seller_sample_data.rake +2 -2
- data/lib/tasks/store_settings.rake +13 -6
- data/lib/tasks/typed_adjustments_migration.rake +1 -1
- data/lib/tasks/uploads.rake +19 -0
- data/spec/fixtures/mailer_views/custom_views_probe_mailer/welcome_email.html.erb +4 -0
- metadata +219 -46
- data/app/jobs/spree/products/touch_categories_job.rb +0 -15
- data/app/jobs/spree/products/touch_taxons_job.rb +0 -13
- data/app/models/acts_as_taggable_on/tag_decorator.rb +0 -10
- data/app/models/concerns/spree/has_image_alt_text.rb +0 -18
- data/app/models/spree/base_analytics_event_handler.rb +0 -54
- data/app/models/spree/invitations/store.rb +0 -6
- data/app/models/spree/preference.rb +0 -14
- data/app/models/spree/promotion_handler/page.rb +0 -25
- data/app/models/spree/promotion_handler/promotion_duplicator.rb +0 -60
- data/app/models/spree/stock/differentiator.rb +0 -45
- data/app/presenters/spree/filters/options_presenter.rb +0 -47
- data/app/services/spree/carts/empty.rb +0 -42
- data/app/services/spree/country_to_timezone.rb +0 -273
- data/app/services/spree/payments/create.rb +0 -92
- data/app/validators/spree/url_validator.rb +0 -23
- data/app/views/active_storage/blobs/_blob.html.erb +0 -14
- data/app/views/spree/admin_user_mailer/password_reset_email.html.erb +0 -8
- data/app/views/spree/export_mailer/export_done.html.erb +0 -7
- data/app/views/spree/import_mailer/import_done.html.erb +0 -12
- data/app/views/spree/invitation_mailer/invitation_accepted.html.erb +0 -4
- data/app/views/spree/invitation_mailer/invitation_email.html.erb +0 -12
- data/app/views/spree/seller_user_mailer/password_reset_email.html.erb +0 -8
- data/app/views/spree/shared/_base_mailer_footer.html.erb +0 -19
- data/app/views/spree/shared/_base_mailer_header.html.erb +0 -8
- data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +0 -399
- data/app/views/spree/shared/_mailer_logo.html.erb +0 -41
- data/app/views/spree/shared/_purchased_items_styles.html.erb +0 -119
- data/app/views/spree/webhook_mailer/endpoint_disabled.html.erb +0 -51
- data/app/views/spree/webhook_mailer/endpoint_disabled.text.erb +0 -10
- data/app/workflows/spree/fulfillments/purchase_label.rb +0 -40
- data/app/workflows/spree/returns/purchase_label.rb +0 -32
- data/lib/spree/analytics.rb +0 -11
- data/lib/spree/core/preferences/scoped_store.rb +0 -34
- data/lib/spree/core/preferences/store.rb +0 -105
- data/lib/spree/translation_migrations.rb +0 -52
|
@@ -7,10 +7,12 @@ module Spree
|
|
|
7
7
|
|
|
8
8
|
include Spree::SingleStoreResource
|
|
9
9
|
include Spree::HasListPosition
|
|
10
|
+
include Spree::CanonicalDecimals
|
|
11
|
+
|
|
12
|
+
canonical_decimals :price_adjustment_percentage, places: 3
|
|
10
13
|
|
|
11
14
|
MATCH_POLICIES = %w[all any].freeze
|
|
12
15
|
|
|
13
|
-
belongs_to :store, class_name: 'Spree::Store'
|
|
14
16
|
# The owning agreement, or nil for a standalone list. An owned list is
|
|
15
17
|
# reached only through its catalog — generic rule matching skips it in
|
|
16
18
|
# SQL (see .for_context) — so a deactivated catalog's list goes dormant
|
|
@@ -95,6 +97,7 @@ module Spree
|
|
|
95
97
|
# `catalog_id` is queryable so a picker can offer the lists that are
|
|
96
98
|
# actually available — unowned, plus the one the catalog already holds.
|
|
97
99
|
self.whitelisted_ransackable_attributes = %w[status match_policy starts_at ends_at catalog_id]
|
|
100
|
+
search_by :name
|
|
98
101
|
|
|
99
102
|
scope :by_position, -> { ordered }
|
|
100
103
|
scope :for_store, ->(store) { where(store: store) }
|
|
@@ -155,7 +158,7 @@ module Spree
|
|
|
155
158
|
end
|
|
156
159
|
|
|
157
160
|
def self.match_policies
|
|
158
|
-
MATCH_POLICIES.map { |key| [
|
|
161
|
+
MATCH_POLICIES.map { |key| [I18n.t("spree.#{key}"), key] }
|
|
159
162
|
end
|
|
160
163
|
|
|
161
164
|
# Returns true if the price list is applicable to the context
|
|
@@ -334,9 +337,9 @@ module Spree
|
|
|
334
337
|
|
|
335
338
|
return if prices_to_insert.empty?
|
|
336
339
|
|
|
337
|
-
# Use upsert_all with on_duplicate: :skip to handle race conditions
|
|
340
|
+
# Use upsert_all with on_duplicate: :skip to handle race conditions.
|
|
341
|
+
# Placeholders charge nothing, so the variants are not touched.
|
|
338
342
|
Spree::Price.upsert_all(prices_to_insert, on_duplicate: :skip)
|
|
339
|
-
touch_variants(variant_ids)
|
|
340
343
|
touch
|
|
341
344
|
end
|
|
342
345
|
|
|
@@ -355,10 +358,13 @@ module Spree
|
|
|
355
358
|
variant_ids = Spree::Variant.where(product_id: product_ids).distinct.pluck(:id)
|
|
356
359
|
return if variant_ids.empty?
|
|
357
360
|
|
|
361
|
+
removed_prices = prices.where(variant_id: variant_ids)
|
|
362
|
+
priced_variant_ids = removed_prices.where.not(amount: nil).distinct.pluck(:variant_id)
|
|
363
|
+
|
|
358
364
|
# Use delete_all for hard delete - this bypasses acts_as_paranoid
|
|
359
365
|
# which is required for the unique index to work when re-adding products
|
|
360
|
-
|
|
361
|
-
touch_variants(
|
|
366
|
+
removed_prices.delete_all
|
|
367
|
+
touch_variants(priced_variant_ids)
|
|
362
368
|
touch
|
|
363
369
|
end
|
|
364
370
|
|
|
@@ -387,9 +393,8 @@ module Spree
|
|
|
387
393
|
|
|
388
394
|
current = current_values[price_id]
|
|
389
395
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
compare_at_amount = attrs[:compare_at_amount].present? ? Spree::LocalizedNumber.parse(attrs[:compare_at_amount]) : nil
|
|
396
|
+
amount = Spree::Money::Rounding.parse_decimal(attrs[:amount])
|
|
397
|
+
compare_at_amount = Spree::Money::Rounding.parse_decimal(attrs[:compare_at_amount])
|
|
393
398
|
|
|
394
399
|
# Clear compare_at_amount if it equals amount
|
|
395
400
|
compare_at_amount = nil if compare_at_amount == amount
|
|
@@ -9,11 +9,8 @@ module Spree
|
|
|
9
9
|
# against raw `channel_id` rows directly. Scope confines the
|
|
10
10
|
# existence check to the price-list's store so cross-store channel
|
|
11
11
|
# IDs can't sneak in.
|
|
12
|
-
preference :channel_ids, :array, default: [],
|
|
13
|
-
|
|
14
|
-
klass: Spree::Channel,
|
|
15
|
-
scope: ->(rule) { rule.store.channels }
|
|
16
|
-
)
|
|
12
|
+
preference :channel_ids, :array, of: :id, model: 'Spree::Channel', default: [],
|
|
13
|
+
scope: ->(rule) { rule.store.channels }
|
|
17
14
|
|
|
18
15
|
def channels
|
|
19
16
|
return [] if preferred_channel_ids.blank?
|
|
@@ -32,7 +29,7 @@ module Spree
|
|
|
32
29
|
end
|
|
33
30
|
|
|
34
31
|
def self.description
|
|
35
|
-
|
|
32
|
+
I18n.t('spree.price_rules.channel_rule.description')
|
|
36
33
|
end
|
|
37
34
|
end
|
|
38
35
|
end
|
|
@@ -10,11 +10,8 @@ module Spree
|
|
|
10
10
|
# callers and decodes them on write so eligibility checks compare
|
|
11
11
|
# against raw `customer_group_id` rows directly. Scope confines
|
|
12
12
|
# the existence check to the price-list's store.
|
|
13
|
-
preference :customer_group_ids, :array, default: [],
|
|
14
|
-
|
|
15
|
-
klass: Spree::CustomerGroup,
|
|
16
|
-
scope: ->(rule) { rule.store.customer_groups }
|
|
17
|
-
)
|
|
13
|
+
preference :customer_group_ids, :array, of: :id, model: 'Spree::CustomerGroup', default: [],
|
|
14
|
+
scope: ->(rule) { rule.store.customer_groups }
|
|
18
15
|
|
|
19
16
|
def customer_groups
|
|
20
17
|
return [] if preferred_customer_group_ids.blank?
|
|
@@ -33,7 +30,7 @@ module Spree
|
|
|
33
30
|
end
|
|
34
31
|
|
|
35
32
|
def self.description
|
|
36
|
-
|
|
33
|
+
I18n.t('spree.price_rules.customer_group_rule.description')
|
|
37
34
|
end
|
|
38
35
|
|
|
39
36
|
def self.superseded?
|
|
@@ -6,11 +6,8 @@ module Spree
|
|
|
6
6
|
# against raw `market_id` rows directly. Scope confines the
|
|
7
7
|
# existence check to the price-list's store so cross-store market
|
|
8
8
|
# IDs can't sneak in.
|
|
9
|
-
preference :market_ids, :array, default: [],
|
|
10
|
-
|
|
11
|
-
klass: Spree::Market,
|
|
12
|
-
scope: ->(rule) { rule.store.markets }
|
|
13
|
-
)
|
|
9
|
+
preference :market_ids, :array, of: :id, model: 'Spree::Market', default: [],
|
|
10
|
+
scope: ->(rule) { rule.store.markets }
|
|
14
11
|
|
|
15
12
|
def markets
|
|
16
13
|
return [] if preferred_market_ids.blank?
|
|
@@ -10,9 +10,7 @@ module Spree
|
|
|
10
10
|
# e.g. `usr_…`) from API callers and decodes them on write. Resolves
|
|
11
11
|
# `Spree.customer_class` lazily — the user class is configured at boot,
|
|
12
12
|
# and class-body evaluation runs before that on cold loads.
|
|
13
|
-
preference :user_ids, :array,
|
|
14
|
-
normalize_id_preference(klass: Spree.customer_class).call(values)
|
|
15
|
-
}
|
|
13
|
+
preference :user_ids, :array, of: :id, model: -> { Spree.customer_class }, default: []
|
|
16
14
|
|
|
17
15
|
def users
|
|
18
16
|
return [] if preferred_user_ids.blank?
|
|
@@ -43,8 +43,7 @@ module Spree
|
|
|
43
43
|
"Spree::Product##{legacy_attr}= is deprecated; set #{publication_attr} on " \
|
|
44
44
|
"ProductPublication instead (writes to every channel's publication). "
|
|
45
45
|
)
|
|
46
|
-
|
|
47
|
-
product_publications.each { |publication| publication.public_send("#{publication_attr}=", value) }
|
|
46
|
+
write_publication_date(legacy_attr, value)
|
|
48
47
|
end
|
|
49
48
|
|
|
50
49
|
# Reading +available_on+/+discontinue_on+ prefers the current-channel
|
|
@@ -92,6 +91,14 @@ module Spree
|
|
|
92
91
|
|
|
93
92
|
private
|
|
94
93
|
|
|
94
|
+
# Writes a legacy date column together with the matching date on every
|
|
95
|
+
# channel's publication, so the two never disagree.
|
|
96
|
+
def write_publication_date(legacy_attr, value)
|
|
97
|
+
write_attribute(legacy_attr, value)
|
|
98
|
+
publication_attr = DEPRECATED_DATE_TO_PUBLICATION_FIELD.fetch(legacy_attr.to_sym)
|
|
99
|
+
product_publications.each { |publication| publication.public_send("#{publication_attr}=", value) }
|
|
100
|
+
end
|
|
101
|
+
|
|
95
102
|
def assign_default_store
|
|
96
103
|
self.store ||= Spree::Current.store || Spree::Store.default
|
|
97
104
|
end
|
data/app/models/spree/product.rb
CHANGED
|
@@ -38,9 +38,9 @@ module Spree
|
|
|
38
38
|
include Spree::StorePreferences
|
|
39
39
|
|
|
40
40
|
publishes_lifecycle_events
|
|
41
|
+
publishes_events :activated, :approved, :archived, :back_in_stock, :drafted, :out_of_stock, :proposed, :rejected
|
|
41
42
|
|
|
42
|
-
MEMOIZED_METHODS = %w[total_on_hand
|
|
43
|
-
default_variant_id tax_category default_variant variant_for_images
|
|
43
|
+
MEMOIZED_METHODS = %w[total_on_hand default_variant_id tax_category default_variant variant_for_images
|
|
44
44
|
primary_category buy_box_variants resolved_delivery_profile
|
|
45
45
|
purchasable? in_stock? backorderable? digital?]
|
|
46
46
|
|
|
@@ -242,8 +242,6 @@ module Spree
|
|
|
242
242
|
after_create :set_default_variant
|
|
243
243
|
|
|
244
244
|
after_save :auto_promote_default_variant
|
|
245
|
-
after_save :run_touch_callbacks, if: :saved_changes?
|
|
246
|
-
after_touch :touch_categories
|
|
247
245
|
|
|
248
246
|
after_commit :auto_match_collections, if: :eligible_for_collection_matching?
|
|
249
247
|
|
|
@@ -302,9 +300,6 @@ module Spree
|
|
|
302
300
|
where(id: (product_ids + custom_field_ids).uniq.compact)
|
|
303
301
|
}
|
|
304
302
|
|
|
305
|
-
# Backward compatibility alias — remove in Spree 6.0
|
|
306
|
-
scope :multi_search, ->(*args) { search(*args) }
|
|
307
|
-
|
|
308
303
|
scope :archivable, -> { where(status: %w[active draft]) }
|
|
309
304
|
scope :by_source, ->(source) { send(source) }
|
|
310
305
|
scope :published, -> { where(status: 'active') }
|
|
@@ -366,7 +361,21 @@ module Spree
|
|
|
366
361
|
super(manual_ids | collections.automatic.ids)
|
|
367
362
|
end
|
|
368
363
|
|
|
369
|
-
self.whitelisted_ransackable_attributes = %w[description name slug discontinue_on status available_on created_at updated_at seller_id]
|
|
364
|
+
self.whitelisted_ransackable_attributes = %w[description name slug discontinue_on status available_on created_at updated_at seller_id price]
|
|
365
|
+
|
|
366
|
+
# The default variant's base price in the current currency — what the
|
|
367
|
+
# product lists show — so a list can filter on it like a column.
|
|
368
|
+
ransacker :price, type: :decimal do |parent|
|
|
369
|
+
prices = Spree::Price.arel_table
|
|
370
|
+
Arel::Nodes::Grouping.new(
|
|
371
|
+
prices.project(prices[:amount]).
|
|
372
|
+
where(prices[:variant_id].eq(parent.table[:default_variant_id])).
|
|
373
|
+
where(prices[:currency].eq(Spree::Current.currency)).
|
|
374
|
+
where(prices[:price_list_id].eq(nil)).
|
|
375
|
+
where(prices[:deleted_at].eq(nil)).
|
|
376
|
+
take(1)
|
|
377
|
+
)
|
|
378
|
+
end
|
|
370
379
|
self.whitelisted_ransackable_associations = %w[categories collections store channels variants default_variant tags labels
|
|
371
380
|
product_type product_categories option_types seller]
|
|
372
381
|
# The storefront filters by tag, category and collection; every other hop
|
|
@@ -375,9 +384,15 @@ module Spree
|
|
|
375
384
|
self.storefront_ransackable_associations = %w[tags categories collections]
|
|
376
385
|
self.whitelisted_ransackable_scopes = %w[not_discontinued search_by_name in_taxon in_category in_categories in_collection price_between
|
|
377
386
|
price_lte price_gte
|
|
378
|
-
search
|
|
387
|
+
search in_stock out_of_stock with_option_value_ids
|
|
379
388
|
|
|
380
389
|
ascend_by_price descend_by_price]
|
|
390
|
+
self.ransackable_scope_types = {
|
|
391
|
+
'in_taxon' => 'id', 'in_category' => 'id', 'in_collection' => 'id',
|
|
392
|
+
'in_categories' => { list: 'id' }, 'with_option_value_ids' => { list: 'id' },
|
|
393
|
+
'price_between' => %w[decimal decimal], 'price_lte' => 'decimal', 'price_gte' => 'decimal',
|
|
394
|
+
'ascend_by_price' => 'boolean', 'descend_by_price' => 'boolean'
|
|
395
|
+
}
|
|
381
396
|
|
|
382
397
|
# All product-level convenience attributes delegate to the default variant —
|
|
383
398
|
# one target, no branching. Reads resolve the existing default variant
|
|
@@ -693,12 +708,12 @@ module Spree
|
|
|
693
708
|
# variant), reading preloaded associations to avoid an N+1.
|
|
694
709
|
# @return [ActiveSupport::TimeWithZone, nil]
|
|
695
710
|
def preorder_ships_at
|
|
696
|
-
candidates = has_variants? ? variants : [
|
|
711
|
+
candidates = has_variants? ? variants : [default_variant]
|
|
697
712
|
candidates.select(&:preorder?).filter_map(&:preorder_ships_at).max
|
|
698
713
|
end
|
|
699
714
|
|
|
700
715
|
def discontinue!
|
|
701
|
-
|
|
716
|
+
write_publication_date(:discontinue_on, Time.current)
|
|
702
717
|
self.status = 'archived'
|
|
703
718
|
save(validate: false)
|
|
704
719
|
end
|
|
@@ -817,7 +832,13 @@ module Spree
|
|
|
817
832
|
Spree::Products::AutoMatchCollectionsJob.set(wait: 30.seconds).perform_later(id)
|
|
818
833
|
end
|
|
819
834
|
|
|
820
|
-
|
|
835
|
+
# @param seller [Spree::Seller, nil] the seller exporting their own
|
|
836
|
+
# products, whose rows cover only their own locations; nil for the
|
|
837
|
+
# operator, whose rows cover the marketplace's and the product's seller's
|
|
838
|
+
# @param default_stock_location [Spree::StockLocation, nil] the location
|
|
839
|
+
# the full rows carry; further locations get stock-only rows. The
|
|
840
|
+
# store's default when nil
|
|
841
|
+
def to_csv(store = nil, seller: nil, default_stock_location: nil)
|
|
821
842
|
store ||= self.store
|
|
822
843
|
properties_for_csv = if respond_to?(:product_properties) && Spree::Config.respond_to?(:product_properties_enabled) && Spree::Config[:product_properties_enabled]
|
|
823
844
|
Spree::Property.order(:position).flat_map do |property|
|
|
@@ -840,11 +861,12 @@ module Spree
|
|
|
840
861
|
all_variants = variants.to_a
|
|
841
862
|
default_currency = store.default_currency
|
|
842
863
|
additional_currencies = store.supported_currencies_list.map(&:iso_code) - [default_currency]
|
|
864
|
+
default_stock_location ||= store.default_stock_location
|
|
843
865
|
|
|
844
866
|
# Primary rows in the store's default currency
|
|
845
867
|
all_variants.each_with_index do |variant, index|
|
|
846
868
|
csv_lines << Spree::CSV::ProductVariantPresenter.new(self, variant, index, properties_for_csv, categories_for_csv, store,
|
|
847
|
-
custom_field_values).call
|
|
869
|
+
custom_field_values, default_stock_location: default_stock_location).call
|
|
848
870
|
end
|
|
849
871
|
|
|
850
872
|
# Price-only rows for each additional currency
|
|
@@ -857,6 +879,25 @@ module Spree
|
|
|
857
879
|
end
|
|
858
880
|
end
|
|
859
881
|
|
|
882
|
+
# Stock-only rows for every other location the importer can name back. A
|
|
883
|
+
# row the import cannot route to its variant is left out: with no SKU it
|
|
884
|
+
# would land on the default variant.
|
|
885
|
+
location_owner_ids = seller ? [seller.id] : [nil, seller_id].uniq
|
|
886
|
+
all_variants.each do |variant|
|
|
887
|
+
next unless variant.should_track_inventory?
|
|
888
|
+
next if variant.sku.blank? && variant != default_variant
|
|
889
|
+
|
|
890
|
+
variant.stock_levels.each do |stock_level|
|
|
891
|
+
location = stock_level.stock_location
|
|
892
|
+
next if location.nil? || location == default_stock_location
|
|
893
|
+
next unless location.store_id == store.id && location_owner_ids.include?(location.seller_id)
|
|
894
|
+
next if stock_level.count_on_hand.zero?
|
|
895
|
+
|
|
896
|
+
csv_lines << Spree::CSV::ProductVariantPresenter.new(self, variant, 0, [], [], store,
|
|
897
|
+
stock_level: stock_level).call
|
|
898
|
+
end
|
|
899
|
+
end
|
|
900
|
+
|
|
860
901
|
csv_lines
|
|
861
902
|
end
|
|
862
903
|
|
|
@@ -972,23 +1013,6 @@ module Spree
|
|
|
972
1013
|
errors.add(:seller, :invalid)
|
|
973
1014
|
end
|
|
974
1015
|
|
|
975
|
-
def run_touch_callbacks
|
|
976
|
-
run_callbacks(:touch)
|
|
977
|
-
end
|
|
978
|
-
|
|
979
|
-
def category_and_ancestors
|
|
980
|
-
@category_and_ancestors ||= categories.map(&:self_and_ancestors).flatten.uniq
|
|
981
|
-
end
|
|
982
|
-
|
|
983
|
-
# Iterate through this product's categories and touch their timestamps in a batch
|
|
984
|
-
def touch_categories
|
|
985
|
-
if categories.any?
|
|
986
|
-
Spree::Products::TouchCategoriesJob.
|
|
987
|
-
set(wait: 5.seconds).
|
|
988
|
-
perform_later(category_and_ancestors.map(&:id))
|
|
989
|
-
end
|
|
990
|
-
end
|
|
991
|
-
|
|
992
1016
|
def ensure_not_in_complete_orders
|
|
993
1017
|
if orders.complete.any?
|
|
994
1018
|
errors.add(:base, :cannot_destroy_if_attached_to_line_items)
|
|
@@ -56,17 +56,5 @@ module Spree
|
|
|
56
56
|
def store
|
|
57
57
|
product&.store
|
|
58
58
|
end
|
|
59
|
-
|
|
60
|
-
# Named explicitly rather than left to the `Spree::Api::V3::` convention:
|
|
61
|
-
# a serializer at that level is picked up by the Store API's generated
|
|
62
|
-
# types and OpenAPI document, and a review decision is not something the
|
|
63
|
-
# storefront has any business describing. The seller's own view is the
|
|
64
|
-
# right shape for an event — it already withholds who decided, which a
|
|
65
|
-
# webhook payload leaving the marketplace should not carry.
|
|
66
|
-
#
|
|
67
|
-
# @return [Class]
|
|
68
|
-
def event_serializer_class
|
|
69
|
-
Spree::Api::V3::Seller::ProductSubmissionSerializer
|
|
70
|
-
end
|
|
71
59
|
end
|
|
72
60
|
end
|
|
@@ -10,7 +10,6 @@ module Spree
|
|
|
10
10
|
TRANSLATABLE_FIELDS = %i[name].freeze
|
|
11
11
|
translates(*TRANSLATABLE_FIELDS, column_fallback: Spree.mobility_column_fallback)
|
|
12
12
|
|
|
13
|
-
belongs_to :store, class_name: 'Spree::Store'
|
|
14
13
|
# Creation-time template only: stamped onto the product when it is
|
|
15
14
|
# created with this type, never managed through it afterwards — the same
|
|
16
15
|
# doctrine as every other type-driven attribute. Nil means the store's
|
|
@@ -38,6 +37,7 @@ module Spree
|
|
|
38
37
|
validates :store, presence: true
|
|
39
38
|
|
|
40
39
|
self.whitelisted_ransackable_attributes = %w[name]
|
|
40
|
+
search_by :name
|
|
41
41
|
self.whitelisted_ransackable_associations = %w[option_types]
|
|
42
42
|
|
|
43
43
|
# Replace-set writer for the flat API payload. Each entry is
|
|
@@ -42,7 +42,7 @@ module Spree
|
|
|
42
42
|
# @param line_item [Spree::LineItem]
|
|
43
43
|
# @return [BigDecimal] never positive
|
|
44
44
|
def compute_amount(line_item)
|
|
45
|
-
line_item.price * gifted_quantity_of(line_item)
|
|
45
|
+
-Spree::Money::Rounding.to_currency(line_item.price * gifted_quantity_of(line_item), line_item.currency)
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
# Tops the order up to the promised quantity and discounts it.
|
|
@@ -104,6 +104,31 @@ module Spree
|
|
|
104
104
|
quantifier.can_supply? quantity
|
|
105
105
|
end
|
|
106
106
|
|
|
107
|
+
# Whether the promotion gives its gift on this order, judged with other
|
|
108
|
+
# promotions' gifts still counting toward its own rules — a single
|
|
109
|
+
# level, so two gift promotions measuring each other cannot loop.
|
|
110
|
+
#
|
|
111
|
+
# @param order [Spree::Order, Spree::Cart]
|
|
112
|
+
# @return [Boolean]
|
|
113
|
+
def gives_away?(order)
|
|
114
|
+
promotion.eligible?(order, own_gift_only: true) && qualifies_beyond_the_gift?(order, own_gift_only: true)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# How many units of this line the promotion pays for — never more than
|
|
118
|
+
# the line holds, so a shopper buying three of a variant gifted once
|
|
119
|
+
# still pays for two. `quantity` is nullable and written by `upsert_all`,
|
|
120
|
+
# which skips validation, so a missing or negative one gifts nothing
|
|
121
|
+
# rather than raising or turning the discount into a surcharge.
|
|
122
|
+
#
|
|
123
|
+
# @param line_item [Spree::LineItem]
|
|
124
|
+
# @return [Integer]
|
|
125
|
+
def gifted_quantity_of(line_item)
|
|
126
|
+
gifted = promotion_action_line_items.detect { |item| item.variant_id == line_item.variant_id }
|
|
127
|
+
return 0 if gifted.nil?
|
|
128
|
+
|
|
129
|
+
[[line_item.quantity, gifted.quantity.to_i].min, 0].max
|
|
130
|
+
end
|
|
131
|
+
|
|
107
132
|
private
|
|
108
133
|
|
|
109
134
|
# Whether this line holds a variant the promotion gives away.
|
|
@@ -117,30 +142,15 @@ module Spree
|
|
|
117
142
|
# to hold a line the rules count with units this action is not already
|
|
118
143
|
# covering. A promotion with no rules qualifies on anything, so there is
|
|
119
144
|
# nothing for the gift to stand in for.
|
|
120
|
-
def qualifies_beyond_the_gift?(order)
|
|
145
|
+
def qualifies_beyond_the_gift?(order, options = {})
|
|
121
146
|
return true if promotion.promotion_rules.empty?
|
|
122
147
|
|
|
123
148
|
order.line_items.any? do |line_item|
|
|
124
|
-
promotion.line_item_actionable?(order, line_item) &&
|
|
149
|
+
promotion.line_item_actionable?(order, line_item, options) &&
|
|
125
150
|
gifted_quantity_of(line_item) < line_item.quantity
|
|
126
151
|
end
|
|
127
152
|
end
|
|
128
153
|
|
|
129
|
-
# How many units of this line the promotion pays for — never more than
|
|
130
|
-
# the line holds, so a shopper buying three of a variant gifted once
|
|
131
|
-
# still pays for two. `quantity` is nullable and written by `upsert_all`,
|
|
132
|
-
# which skips validation, so a missing or negative one gifts nothing
|
|
133
|
-
# rather than raising or turning the discount into a surcharge.
|
|
134
|
-
#
|
|
135
|
-
# @param line_item [Spree::LineItem]
|
|
136
|
-
# @return [Integer]
|
|
137
|
-
def gifted_quantity_of(line_item)
|
|
138
|
-
gifted = promotion_action_line_items.detect { |item| item.variant_id == line_item.variant_id }
|
|
139
|
-
return 0 if gifted.nil?
|
|
140
|
-
|
|
141
|
-
[[line_item.quantity, gifted.quantity.to_i].min, 0].max
|
|
142
|
-
end
|
|
143
|
-
|
|
144
154
|
def add_missing_line_items(order)
|
|
145
155
|
added_results = promotion_action_line_items.map do |item|
|
|
146
156
|
missing = item.quantity.to_i - order.quantity_of(item.variant)
|
|
@@ -35,7 +35,7 @@ module Spree
|
|
|
35
35
|
# Preferences
|
|
36
36
|
#
|
|
37
37
|
MATCH_POLICIES = %w(any all)
|
|
38
|
-
preference :match_policy, :string, default: MATCH_POLICIES.first
|
|
38
|
+
preference :match_policy, :string, default: MATCH_POLICIES.first, choices: MATCH_POLICIES
|
|
39
39
|
|
|
40
40
|
#
|
|
41
41
|
# Attributes
|
|
@@ -47,10 +47,6 @@ module Spree
|
|
|
47
47
|
#
|
|
48
48
|
after_save :add_categories
|
|
49
49
|
|
|
50
|
-
def applicable?(promotable)
|
|
51
|
-
promotable.is_a?(Spree::Order) || promotable.is_a?(Spree::Cart)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
50
|
def eligible_category_ids
|
|
55
51
|
@eligible_category_ids ||= promotion_rule_categories.pluck(:category_id)
|
|
56
52
|
end
|
|
@@ -8,15 +8,8 @@ module Spree
|
|
|
8
8
|
# against the order's raw `channel_id` directly. Scope confines the
|
|
9
9
|
# existence check to the promotion's store so cross-store channel
|
|
10
10
|
# IDs can't sneak in.
|
|
11
|
-
preference :channel_ids, :array, default: [],
|
|
12
|
-
|
|
13
|
-
klass: Spree::Channel,
|
|
14
|
-
scope: ->(rule) { rule.promotion.store.channels }
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
def applicable?(promotable)
|
|
18
|
-
promotable.is_a?(Spree::Order) || promotable.is_a?(Spree::Cart)
|
|
19
|
-
end
|
|
11
|
+
preference :channel_ids, :array, of: :id, model: 'Spree::Channel', default: [],
|
|
12
|
+
scope: ->(rule) { rule.promotion.store.channels }
|
|
20
13
|
|
|
21
14
|
def channels
|
|
22
15
|
return Spree::Channel.none if preferred_channel_ids.blank?
|
|
@@ -9,15 +9,10 @@ module Spree
|
|
|
9
9
|
class Promotion
|
|
10
10
|
module Rules
|
|
11
11
|
class Country < Spree::PromotionRule
|
|
12
|
-
preference :country_codes, :array,
|
|
13
|
-
|
|
14
|
-
}
|
|
12
|
+
preference :country_codes, :array, of: :string, format: :iso_country, default: [],
|
|
13
|
+
parse_on_set: ->(values) { Array(values).flat_map { |value| value.to_s.split(',') }.map { |code| code.strip.upcase }.compact_blank }
|
|
15
14
|
preference :country_id, :integer # legacy single-country shortcut
|
|
16
|
-
preference :country_code, :string # legacy ISO-based shortcut
|
|
17
|
-
|
|
18
|
-
def applicable?(promotable)
|
|
19
|
-
promotable.is_a?(Spree::Order) || promotable.is_a?(Spree::Cart)
|
|
20
|
-
end
|
|
15
|
+
preference :country_code, :string, format: :iso_country # legacy ISO-based shortcut
|
|
21
16
|
|
|
22
17
|
def countries
|
|
23
18
|
isos = configured_country_codes.presence || [configured_country_code].compact_blank
|
|
@@ -3,11 +3,7 @@ module Spree
|
|
|
3
3
|
class Promotion
|
|
4
4
|
module Rules
|
|
5
5
|
class Currency < Spree::PromotionRule
|
|
6
|
-
preference :currency, :string
|
|
7
|
-
|
|
8
|
-
def applicable?(promotable)
|
|
9
|
-
promotable.is_a?(Spree::Order) || promotable.is_a?(Spree::Cart)
|
|
10
|
-
end
|
|
6
|
+
preference :currency, :string, format: :currency
|
|
11
7
|
|
|
12
8
|
def eligible?(order, options = {})
|
|
13
9
|
return true if order.currency == preferred_currency
|
|
@@ -9,15 +9,8 @@ module Spree
|
|
|
9
9
|
# Scoped to the promotion's own store: groups are store-owned, so an
|
|
10
10
|
# id from elsewhere must raise rather than link a promotion to an
|
|
11
11
|
# audience its store cannot see.
|
|
12
|
-
preference :customer_group_ids, :array, default: [],
|
|
13
|
-
|
|
14
|
-
klass: Spree::CustomerGroup,
|
|
15
|
-
scope: ->(rule) { rule.promotion.store.customer_groups }
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
def applicable?(promotable)
|
|
19
|
-
promotable.is_a?(Spree::Order) || promotable.is_a?(Spree::Cart)
|
|
20
|
-
end
|
|
12
|
+
preference :customer_group_ids, :array, of: :id, model: 'Spree::CustomerGroup', default: [],
|
|
13
|
+
scope: ->(rule) { rule.promotion.store.customer_groups }
|
|
21
14
|
|
|
22
15
|
def customer_groups
|
|
23
16
|
return Spree::CustomerGroup.none if preferred_customer_group_ids.blank?
|
|
@@ -4,10 +4,6 @@ module Spree
|
|
|
4
4
|
class FirstOrder < Spree::PromotionRule
|
|
5
5
|
attr_reader :user, :email, :store
|
|
6
6
|
|
|
7
|
-
def applicable?(promotable)
|
|
8
|
-
promotable.is_a?(Spree::Order) || promotable.is_a?(Spree::Cart)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
7
|
def eligible?(order, options = {})
|
|
12
8
|
@user = order.try(:customer) || options[:user]
|
|
13
9
|
@email = if options[:email].present?
|
|
@@ -1,23 +1,19 @@
|
|
|
1
1
|
# A rule to apply to an order greater than (or greater than or equal to)
|
|
2
|
-
# a specific amount
|
|
2
|
+
# a specific amount. Free gifts do not count toward it.
|
|
3
3
|
module Spree
|
|
4
4
|
class Promotion
|
|
5
5
|
module Rules
|
|
6
6
|
class ItemTotal < Spree::PromotionRule
|
|
7
|
-
preference :amount_min, :
|
|
7
|
+
preference :amount_min, :money, default: 100.00
|
|
8
8
|
preference :operator_min, :string, default: '>'
|
|
9
|
-
preference :amount_max, :
|
|
9
|
+
preference :amount_max, :money, default: nil, nullable: true
|
|
10
10
|
preference :operator_max, :string, default: '<'
|
|
11
11
|
|
|
12
12
|
OPERATORS_MIN = ['gt', 'gte']
|
|
13
13
|
OPERATORS_MAX = ['lt', 'lte']
|
|
14
14
|
|
|
15
|
-
def
|
|
16
|
-
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def eligible?(order, _options = {})
|
|
20
|
-
item_total = order.item_total
|
|
15
|
+
def eligible?(order, options = {})
|
|
16
|
+
item_total = order.item_total - order.gift_amount(promotion: promotion, own_gift_only: options.fetch(:own_gift_only, false))
|
|
21
17
|
|
|
22
18
|
lower_limit_condition = item_total.send(preferred_operator_min == 'gte' ? :>= : :>, BigDecimal(preferred_amount_min.to_s))
|
|
23
19
|
|
|
@@ -43,7 +39,7 @@ module Spree
|
|
|
43
39
|
if preferred_amount_max.present?
|
|
44
40
|
Spree::Money.new(preferred_amount_max, currency: order.currency).to_s
|
|
45
41
|
else
|
|
46
|
-
|
|
42
|
+
I18n.t('spree.no_maximum')
|
|
47
43
|
end
|
|
48
44
|
end
|
|
49
45
|
|
|
@@ -8,15 +8,8 @@ module Spree
|
|
|
8
8
|
# against the order's raw `market_id` directly. Scope confines the
|
|
9
9
|
# existence check to the promotion's store so cross-store market
|
|
10
10
|
# IDs can't sneak in.
|
|
11
|
-
preference :market_ids, :array, default: [],
|
|
12
|
-
|
|
13
|
-
klass: Spree::Market,
|
|
14
|
-
scope: ->(rule) { rule.promotion.store.markets }
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
def applicable?(promotable)
|
|
18
|
-
promotable.is_a?(Spree::Order) || promotable.is_a?(Spree::Cart)
|
|
19
|
-
end
|
|
11
|
+
preference :market_ids, :array, of: :id, model: 'Spree::Market', default: [],
|
|
12
|
+
scope: ->(rule) { rule.promotion.store.markets }
|
|
20
13
|
|
|
21
14
|
def markets
|
|
22
15
|
return Spree::Market.none if preferred_market_ids.blank?
|
|
@@ -2,10 +2,6 @@ module Spree
|
|
|
2
2
|
class Promotion
|
|
3
3
|
module Rules
|
|
4
4
|
class OneUsePerUser < Spree::PromotionRule
|
|
5
|
-
def applicable?(promotable)
|
|
6
|
-
promotable.is_a?(Spree::Order) || promotable.is_a?(Spree::Cart)
|
|
7
|
-
end
|
|
8
|
-
|
|
9
5
|
def eligible?(order, _options = {})
|
|
10
6
|
if order.customer.present?
|
|
11
7
|
if promotion.used_by?(order.customer, [order])
|
|
@@ -3,19 +3,15 @@ module Spree
|
|
|
3
3
|
module Rules
|
|
4
4
|
class OptionValue < Spree::PromotionRule
|
|
5
5
|
MATCH_POLICIES = %w(any)
|
|
6
|
-
preference :match_policy, :string, default: MATCH_POLICIES.first
|
|
6
|
+
preference :match_policy, :string, default: MATCH_POLICIES.first, choices: MATCH_POLICIES
|
|
7
7
|
# Stored as raw Spree::OptionValue ids. Accepts prefixed IDs (`optval_…`)
|
|
8
8
|
# from API callers and decodes them on write so eligibility checks compare
|
|
9
9
|
# against stable option-value rows, not join-table ids that shift when
|
|
10
10
|
# variants are reconfigured.
|
|
11
|
-
preference :eligible_values, :array, default: []
|
|
12
|
-
parse_on_set: normalize_id_preference(klass: Spree::OptionValue)
|
|
11
|
+
preference :eligible_values, :array, of: :id, model: 'Spree::OptionValue', default: []
|
|
13
12
|
|
|
14
13
|
# @param promotable [Object]
|
|
15
14
|
# @return [Boolean]
|
|
16
|
-
def applicable?(promotable)
|
|
17
|
-
promotable.is_a?(Spree::Order) || promotable.is_a?(Spree::Cart)
|
|
18
|
-
end
|
|
19
15
|
|
|
20
16
|
# @return [ActiveRecord::Relation<Spree::OptionValue>]
|
|
21
17
|
def option_values
|
|
@@ -28,7 +28,7 @@ module Spree
|
|
|
28
28
|
# Preferences
|
|
29
29
|
#
|
|
30
30
|
MATCH_POLICIES = %w(any all none)
|
|
31
|
-
preference :match_policy, :string, default: MATCH_POLICIES.first
|
|
31
|
+
preference :match_policy, :string, default: MATCH_POLICIES.first, choices: MATCH_POLICIES
|
|
32
32
|
|
|
33
33
|
#
|
|
34
34
|
# Attributes
|
|
@@ -49,10 +49,6 @@ module Spree
|
|
|
49
49
|
@eligible_product_ids ||= product_promotion_rules.pluck(:product_id)
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
def applicable?(promotable)
|
|
53
|
-
promotable.is_a?(Spree::Order) || promotable.is_a?(Spree::Cart)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
52
|
def eligible?(order, _options = {})
|
|
57
53
|
return true if eligible_product_ids.empty?
|
|
58
54
|
|