spree_core 6.0.0.beta3 → 6.0.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/README.md +2 -2
- 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/seller_payouts/sweep_seller_job.rb +2 -0
- data/app/mailers/spree/admin_user_mailer.rb +4 -19
- data/app/mailers/spree/base_mailer.rb +96 -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 +13 -1
- data/app/models/concerns/spree/api_typed.rb +91 -0
- data/app/models/concerns/spree/calculator/tiers.rb +76 -0
- data/app/models/concerns/spree/customer_methods.rb +15 -14
- 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.rb +4 -12
- data/app/models/concerns/spree/product_scopes.rb +11 -1
- 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 +7 -3
- data/app/models/concerns/spree/purchase/purchase_order.rb +2 -2
- data/app/models/concerns/spree/purchase/totals.rb +49 -1
- 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/single_store_resource.rb +1 -1
- data/app/models/concerns/spree/stores/email_branding.rb +31 -0
- data/app/models/concerns/spree/type_labels.rb +38 -0
- data/app/models/concerns/spree/typed_adjustment_line.rb +1 -1
- data/app/models/concerns/spree/typed_associations.rb +6 -0
- data/app/models/spree/address.rb +11 -1
- data/app/models/spree/adjusters/promotion.rb +1 -15
- data/app/models/spree/allowed_origin.rb +0 -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 +70 -22
- data/app/models/spree/calculator/flat_percent_item_total.rb +1 -3
- data/app/models/spree/calculator/flat_rate.rb +1 -3
- data/app/models/spree/calculator/flexi_rate.rb +1 -3
- data/app/models/spree/calculator/percent_on_line_item.rb +1 -1
- data/app/models/spree/calculator/price_sack.rb +1 -3
- data/app/models/spree/calculator/shipping/digital_delivery.rb +1 -3
- data/app/models/spree/calculator/shipping/flat_percent_item_total.rb +1 -3
- data/app/models/spree/calculator/shipping/flat_rate.rb +1 -3
- data/app/models/spree/calculator/shipping/flexi_rate.rb +1 -3
- data/app/models/spree/calculator/shipping/per_item.rb +1 -3
- data/app/models/spree/calculator/shipping/price_sack.rb +1 -3
- data/app/models/spree/calculator/tiered_flat_rate.rb +6 -23
- data/app/models/spree/calculator/tiered_percent.rb +7 -25
- data/app/models/spree/cart.rb +78 -18
- data/app/models/spree/channel/gating.rb +1 -1
- data/app/models/spree/channel.rb +4 -4
- data/app/models/spree/claim.rb +21 -1
- data/app/models/spree/claim_line_item.rb +41 -6
- data/app/models/spree/collection.rb +0 -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 +2 -3
- 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/product_rule.rb +1 -1
- 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 +9 -23
- data/app/models/spree/custom_fields/boolean.rb +1 -1
- data/app/models/spree/custom_fields/json.rb +1 -1
- data/app/models/spree/data_feed/google.rb +0 -2
- data/app/models/spree/data_request.rb +1 -1
- data/app/models/spree/delivery_method.rb +30 -13
- data/app/models/spree/delivery_method_rule.rb +4 -11
- data/app/models/spree/delivery_rate.rb +4 -5
- data/app/models/spree/delivery_rate_provider/base.rb +1 -0
- data/app/models/spree/delivery_zone.rb +0 -1
- 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 +15 -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 +1 -1
- data/app/models/spree/fee.rb +4 -2
- data/app/models/spree/fulfillment.rb +53 -27
- data/app/models/spree/fulfillment_changer.rb +2 -2
- 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 +4 -0
- data/app/models/spree/gateway/custom_payment_source_method.rb +5 -0
- data/app/models/spree/gateway.rb +5 -1
- data/app/models/spree/gift_card.rb +12 -1
- data/app/models/spree/gift_card_batch.rb +0 -1
- data/app/models/spree/import.rb +2 -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 +8 -18
- data/app/models/spree/invitation.rb +5 -5
- data/app/models/spree/line_item.rb +13 -2
- data/app/models/spree/locale.rb +11 -8
- data/app/models/spree/market.rb +1 -0
- data/app/models/spree/newsletter_subscriber.rb +3 -0
- data/app/models/spree/order.rb +56 -138
- data/app/models/spree/order_group.rb +11 -2
- 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 +1 -2
- data/app/models/spree/payment/gateway_options.rb +14 -52
- data/app/models/spree/payment/processing.rb +2 -4
- data/app/models/spree/payment.rb +20 -5
- data/app/models/spree/payment_method/session_instrumentation.rb +1 -0
- data/app/models/spree/payment_method/store_credit.rb +4 -4
- data/app/models/spree/payment_method.rb +36 -4
- 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/price_list.rb +1 -2
- data/app/models/spree/price_rules/channel_rule.rb +1 -1
- data/app/models/spree/price_rules/customer_group_rule.rb +1 -1
- data/app/models/spree/product.rb +31 -7
- data/app/models/spree/product_submission.rb +0 -12
- data/app/models/spree/product_type.rb +0 -1
- data/app/models/spree/promotion/actions/create_line_items.rb +27 -17
- data/app/models/spree/promotion/rules/category.rb +0 -4
- data/app/models/spree/promotion/rules/channel.rb +0 -4
- data/app/models/spree/promotion/rules/country.rb +0 -4
- data/app/models/spree/promotion/rules/currency.rb +0 -4
- data/app/models/spree/promotion/rules/customer_group.rb +0 -4
- data/app/models/spree/promotion/rules/first_order.rb +0 -4
- data/app/models/spree/promotion/rules/item_total.rb +4 -8
- data/app/models/spree/promotion/rules/market.rb +0 -4
- data/app/models/spree/promotion/rules/one_use_per_user.rb +0 -4
- data/app/models/spree/promotion/rules/option_value.rb +0 -3
- data/app/models/spree/promotion/rules/product.rb +0 -4
- 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 +35 -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 +1 -0
- data/app/models/spree/quantity_rule.rb +1 -1
- data/app/models/spree/refund.rb +28 -3
- data/app/models/spree/return.rb +30 -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 +1 -1
- data/app/models/spree/seller.rb +2 -1
- data/app/models/spree/seller_payout.rb +7 -0
- data/app/models/spree/seller_requirement.rb +4 -12
- data/app/models/spree/seller_requirement_custom_field.rb +1 -2
- data/app/models/spree/seller_requirement_submission.rb +2 -2
- data/app/models/spree/seller_requirements/accept_terms.rb +2 -3
- data/app/models/spree/seller_transfer.rb +5 -0
- data/app/models/spree/shipping_label.rb +1 -0
- data/app/models/spree/stock/availability_validator.rb +2 -2
- 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 +1 -1
- 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 +4 -2
- data/app/models/spree/store.rb +33 -7
- data/app/models/spree/store_credit.rb +8 -9
- data/app/models/spree/store_credit_event.rb +5 -5
- data/app/models/spree/tax_exemption_certificate.rb +2 -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 +59 -33
- data/app/models/spree/tax_provider/recorded_share.rb +114 -0
- data/app/models/spree/tax_rate.rb +1 -2
- data/app/models/spree/taxonomy.rb +0 -1
- data/app/models/spree/variant.rb +4 -3
- data/app/models/spree/variant_media.rb +1 -1
- data/app/models/spree/webhook_endpoint.rb +10 -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 +1 -1
- data/app/presenters/spree/csv/product_variant_presenter.rb +42 -12
- 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 +19 -5
- 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 +65 -34
- data/app/services/spree/imports/row_processors/purchase_order.rb +13 -13
- data/app/services/spree/locales.rb +4 -5
- 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 +2 -1
- data/app/services/spree/orders/discounts/create.rb +7 -4
- 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/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/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 +15 -14
- data/app/subscribers/spree/seller_onboarding_subscriber.rb +1 -1
- 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 +51 -47
- 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/process.rb +2 -2
- 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/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/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 +5 -5
- 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/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/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/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 +37 -503
- 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/lib/generators/spree/dummy/dummy_generator.rb +0 -9
- data/lib/generators/spree/dummy/templates/rails/test.rb +7 -0
- data/lib/spree/checkout/default_requirements.rb +37 -13
- data/lib/spree/core/configuration.rb +1 -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 +48 -167
- data/lib/spree/core/permissions/default_catalog.rb +5 -0
- data/lib/spree/core/preferences/json_conversion.rb +182 -0
- data/lib/spree/core/preferences/masking.rb +4 -1
- data/lib/spree/core/preferences/preferable.rb +137 -83
- data/lib/spree/core/preferences/preferable_class_methods.rb +81 -146
- data/lib/spree/core/previews/import_preview.rb +10 -0
- data/lib/spree/core/tax/provider_error.rb +37 -0
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/core.rb +85 -370
- 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/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/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/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 +45 -0
- data/lib/tasks/categories_and_collections.rake +3 -3
- data/lib/tasks/core.rake +6 -4
- data/lib/tasks/media.rake +3 -3
- data/lib/tasks/package_types.rake +1 -1
- data/lib/tasks/preferences_json.rake +101 -0
- data/spec/fixtures/mailer_views/custom_views_probe_mailer/welcome_email.html.erb +4 -0
- metadata +188 -44
- 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
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
class AddPostSaleTax < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
change_table :spree_tax_lines, bulk: true do |t|
|
|
4
|
+
t.references :return_line_item, index: true
|
|
5
|
+
t.references :claim_line_item, index: true
|
|
6
|
+
t.references :exchange_line_item, index: true
|
|
7
|
+
t.references :original_tax_line, index: true
|
|
8
|
+
t.boolean :credit, default: false, null: false
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
change_table :spree_return_line_items, bulk: true do |t|
|
|
12
|
+
t.decimal :included_tax_total, precision: 10, scale: 2, default: 0, null: false
|
|
13
|
+
t.decimal :additional_tax_total, precision: 10, scale: 2, default: 0, null: false
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
change_table :spree_claim_line_items, bulk: true do |t|
|
|
17
|
+
t.decimal :included_tax_total, precision: 10, scale: 2, default: 0, null: false
|
|
18
|
+
t.decimal :additional_tax_total, precision: 10, scale: 2, default: 0, null: false
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
change_table :spree_exchange_line_items, bulk: true do |t|
|
|
22
|
+
t.decimal :original_included_tax_total, precision: 10, scale: 2, default: 0, null: false
|
|
23
|
+
t.decimal :original_additional_tax_total, precision: 10, scale: 2, default: 0, null: false
|
|
24
|
+
t.decimal :new_included_tax_total, precision: 10, scale: 2, default: 0, null: false
|
|
25
|
+
t.decimal :new_additional_tax_total, precision: 10, scale: 2, default: 0, null: false
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
add_column :spree_refunds, :tax_amount, :decimal, precision: 10, scale: 2, default: 0, null: false
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
class ConvertPreferencesToJson < ActiveRecord::Migration[8.1]
|
|
2
|
+
# The tables whose classes declare `:password` preferences. Their secrets move
|
|
3
|
+
# to an encrypted `secret_preferences` column (see Spree::SecretPreferences).
|
|
4
|
+
SECRET_TABLES = %i[spree_payment_methods spree_integrations].freeze
|
|
5
|
+
|
|
6
|
+
# Records which tables had their `text` column replaced, so `down` restores
|
|
7
|
+
# `text` only there — a table whose column was already JSON (delivery method
|
|
8
|
+
# rules, commission rules) keeps it. Dropped on the way back down.
|
|
9
|
+
CONVERTED_TABLES_REGISTRY = :spree_converted_preference_tables
|
|
10
|
+
|
|
11
|
+
# The conversion lives here rather than in the upgrade rake task because the
|
|
12
|
+
# manifest runs AFTER db:migrate — a task scheduled there would find the YAML
|
|
13
|
+
# column already replaced. Secrets are moved in plain text, so this needs no
|
|
14
|
+
# encryption keys; they stay readable and `spree:upgrade:encrypt_secret_preferences`
|
|
15
|
+
# encrypts them.
|
|
16
|
+
def up
|
|
17
|
+
SECRET_TABLES.each do |table|
|
|
18
|
+
next unless table_exists?(table)
|
|
19
|
+
|
|
20
|
+
add_column table, :secret_preferences, :text unless column_exists?(table, :secret_preferences)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
create_table CONVERTED_TABLES_REGISTRY, if_not_exists: true do |t|
|
|
24
|
+
t.string :table_name, null: false
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
conversion.preference_tables.each do |table|
|
|
28
|
+
if conversion.text_column?(table)
|
|
29
|
+
conversion.convert_text_table(table)
|
|
30
|
+
execute(Arel::InsertManager.new.tap do |insert|
|
|
31
|
+
registry = Arel::Table.new(CONVERTED_TABLES_REGISTRY)
|
|
32
|
+
insert.into(registry).insert([[registry[:table_name], table]])
|
|
33
|
+
end.to_sql)
|
|
34
|
+
else
|
|
35
|
+
conversion.convert_table(table)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
drop_table :spree_preferences, if_exists: true
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Restores YAML: a `text` column where `up` replaced one, and a YAML document
|
|
43
|
+
# inside a JSON string where the column was already JSON, as before the
|
|
44
|
+
# upgrade. Secrets go back into `preferences` — decrypted, so rolling back an
|
|
45
|
+
# encrypted secret needs the encryption keys — tiers become a hash keyed by
|
|
46
|
+
# threshold again, and decimals return as BigDecimal for every row whose class
|
|
47
|
+
# can be resolved; anything else comes back as the string JSON held.
|
|
48
|
+
def down
|
|
49
|
+
restore = Restore.new(connection, conversion)
|
|
50
|
+
create_table :spree_preferences, if_not_exists: true do |t|
|
|
51
|
+
t.text :value
|
|
52
|
+
t.string :key
|
|
53
|
+
t.timestamps
|
|
54
|
+
t.index :key, unique: true
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
converted = converted_tables
|
|
58
|
+
conversion.preference_tables.each do |table|
|
|
59
|
+
if converted.include?(table)
|
|
60
|
+
add_column table, :preferences_yaml, :text
|
|
61
|
+
restore.table(table, target: 'preferences_yaml')
|
|
62
|
+
remove_column table, :preferences
|
|
63
|
+
rename_column table, :preferences_yaml, :preferences
|
|
64
|
+
else
|
|
65
|
+
restore.table(table, target: 'preferences', inside_json: true)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
drop_table CONVERTED_TABLES_REGISTRY, if_exists: true
|
|
70
|
+
|
|
71
|
+
SECRET_TABLES.each do |table|
|
|
72
|
+
remove_column table, :secret_preferences if table_exists?(table) && column_exists?(table, :secret_preferences)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def converted_tables
|
|
79
|
+
return [] unless table_exists?(CONVERTED_TABLES_REGISTRY)
|
|
80
|
+
|
|
81
|
+
registry = Arel::Table.new(CONVERTED_TABLES_REGISTRY)
|
|
82
|
+
connection.select_values(registry.project(registry[:table_name]))
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def conversion
|
|
86
|
+
@conversion ||= Spree::Preferences::JsonConversion.new(connection, log: ->(message) { say(message, true) })
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
class Restore
|
|
90
|
+
def initialize(connection, conversion)
|
|
91
|
+
@connection = connection
|
|
92
|
+
@conversion = conversion
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def table(table, target:, inside_json: false)
|
|
96
|
+
typed = connection.column_exists?(table, :type)
|
|
97
|
+
secrets = connection.column_exists?(table, :secret_preferences)
|
|
98
|
+
columns = ['id', 'preferences', ('type' if typed), ('secret_preferences' if secrets)].compact
|
|
99
|
+
|
|
100
|
+
arel_table = Arel::Table.new(table)
|
|
101
|
+
connection.select_all(arel_table.project(*columns.map { |column| arel_table[column] })).each do |row|
|
|
102
|
+
next if row['preferences'].nil? && row['secret_preferences'].nil?
|
|
103
|
+
|
|
104
|
+
preferences = decode(row['preferences']) || {}
|
|
105
|
+
preferences.merge!(decode(decrypt(row['secret_preferences'])) || {}) if secrets
|
|
106
|
+
model = typed ? conversion.model_for(row['type']) : nil
|
|
107
|
+
restore_tiers(preferences, model)
|
|
108
|
+
restore_typed_values(preferences, model)
|
|
109
|
+
|
|
110
|
+
yaml = YAML.dump(preferences.transform_keys(&:to_sym))
|
|
111
|
+
conversion.write(table, row['id'], target => inside_json ? JSON.generate(yaml) : yaml)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
private
|
|
116
|
+
|
|
117
|
+
attr_reader :connection, :conversion
|
|
118
|
+
|
|
119
|
+
def decode(raw)
|
|
120
|
+
raw.is_a?(String) ? JSON.parse(raw) : raw
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# A value written before encryption was enabled is plain JSON and comes
|
|
124
|
+
# back as it is. An encrypted one that cannot be decrypted stops the
|
|
125
|
+
# rollback: writing its ciphertext into `preferences` would replace a
|
|
126
|
+
# gateway's keys with garbage.
|
|
127
|
+
def decrypt(raw)
|
|
128
|
+
return raw if raw.nil? || !encrypted?(raw)
|
|
129
|
+
|
|
130
|
+
unless ActiveRecord::Encryption.config.has_primary_key?
|
|
131
|
+
raise ActiveRecord::IrreversibleMigration, 'Encrypted secret_preferences cannot be rolled back without the Active Record encryption keys. Configure them and run the rollback again.'
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
ActiveRecord::Encryption.encryptor.decrypt(raw)
|
|
135
|
+
rescue ActiveRecord::Encryption::Errors::Decryption
|
|
136
|
+
raise ActiveRecord::IrreversibleMigration, 'An encrypted secret_preferences value could not be decrypted with the configured keys. Restore the keys it was encrypted with and run the rollback again.'
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def encrypted?(raw)
|
|
140
|
+
parsed = JSON.parse(raw)
|
|
141
|
+
parsed.is_a?(Hash) && parsed.key?('p') && parsed.key?('h')
|
|
142
|
+
rescue JSON::ParserError
|
|
143
|
+
false
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def restore_tiers(preferences, model)
|
|
147
|
+
tiers = preferences['tiers']
|
|
148
|
+
return unless tiers.is_a?(Array) && Spree::Preferences::JsonConversion.tiered_calculator?(model)
|
|
149
|
+
|
|
150
|
+
# A value that is not a number is kept as written, so two such tiers
|
|
151
|
+
# cannot collapse into one nil key.
|
|
152
|
+
preferences['tiers'] = tiers.to_h do |tier|
|
|
153
|
+
[Spree::Calculator::Tiers.decimal(tier['threshold']) || tier['threshold'],
|
|
154
|
+
Spree::Calculator::Tiers.decimal(tier['value']) || tier['value']]
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def restore_typed_values(preferences, model)
|
|
159
|
+
return unless model.respond_to?(:declared_preference_types)
|
|
160
|
+
|
|
161
|
+
model.declared_preference_types.each do |name, type|
|
|
162
|
+
preferences[name.to_s] = Spree::Preferences::Preferable.restore_value(preferences[name.to_s], type) if preferences.key?(name.to_s)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
class CreateSpreeEmailTemplates < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :spree_email_templates do |t|
|
|
4
|
+
t.references :store, null: false, index: false
|
|
5
|
+
t.string :key, null: false
|
|
6
|
+
t.string :locale, null: false
|
|
7
|
+
t.string :status, null: false
|
|
8
|
+
t.text :subject
|
|
9
|
+
t.text :body, null: false
|
|
10
|
+
t.text :base_subject
|
|
11
|
+
t.text :base_body, null: false
|
|
12
|
+
t.datetime :published_at, null: false
|
|
13
|
+
t.references :published_by, polymorphic: true, index: true
|
|
14
|
+
t.datetime :reverted_at
|
|
15
|
+
t.references :reverted_by, polymorphic: true, index: true
|
|
16
|
+
|
|
17
|
+
t.timestamps
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
add_index :spree_email_templates, [:store_id, :key, :locale], unique: true,
|
|
21
|
+
name: 'index_spree_email_templates_on_store_key_locale'
|
|
22
|
+
add_index :spree_email_templates, :status
|
|
23
|
+
|
|
24
|
+
create_table :spree_email_template_drafts do |t|
|
|
25
|
+
t.references :store, null: false, index: false
|
|
26
|
+
t.string :key, null: false
|
|
27
|
+
t.string :locale, null: false
|
|
28
|
+
t.text :subject
|
|
29
|
+
t.text :body, null: false
|
|
30
|
+
t.text :base_subject
|
|
31
|
+
t.text :base_body, null: false
|
|
32
|
+
t.integer :lock_version, null: false, default: 0
|
|
33
|
+
t.references :updated_by, polymorphic: true, index: true
|
|
34
|
+
|
|
35
|
+
t.timestamps
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
add_index :spree_email_template_drafts, [:store_id, :key, :locale], unique: true,
|
|
39
|
+
name: 'index_spree_email_template_drafts_on_store_key_locale'
|
|
40
|
+
|
|
41
|
+
create_table :spree_email_template_revisions do |t|
|
|
42
|
+
t.references :email_template, null: false, index: false
|
|
43
|
+
t.text :subject
|
|
44
|
+
t.text :body, null: false
|
|
45
|
+
t.references :published_by, polymorphic: true, index: true
|
|
46
|
+
t.datetime :created_at, null: false
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
add_index :spree_email_template_revisions, [:email_template_id, :created_at],
|
|
50
|
+
name: 'index_spree_email_template_revisions_on_template_and_created'
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -63,7 +63,6 @@ module Spree
|
|
|
63
63
|
|
|
64
64
|
puts "Rails app generator args: #{args.inspect}"
|
|
65
65
|
Rails::Generators.invoke('app', args)
|
|
66
|
-
inject_yaml_permitted_classes
|
|
67
66
|
end
|
|
68
67
|
|
|
69
68
|
def test_dummy_config
|
|
@@ -96,14 +95,6 @@ module Spree
|
|
|
96
95
|
|
|
97
96
|
protected
|
|
98
97
|
|
|
99
|
-
def inject_yaml_permitted_classes
|
|
100
|
-
inside dummy_path do
|
|
101
|
-
inject_into_file 'config/application.rb', %Q[
|
|
102
|
-
config.active_record.yaml_column_permitted_classes = [Symbol, BigDecimal, ActiveSupport::HashWithIndifferentAccess, ActiveSupport::TimeWithZone, ActiveSupport::TimeZone, Time]
|
|
103
|
-
], after: /config\.load_defaults.*$/, verbose: true
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
98
|
def dummy_path
|
|
108
99
|
ENV['DUMMY_PATH'] || 'spec/dummy'
|
|
109
100
|
end
|
|
@@ -28,6 +28,9 @@ Dummy::Application.configure do
|
|
|
28
28
|
# the suite sees it, as every real Spree app does.
|
|
29
29
|
config.action_controller.raise_on_missing_callback_actions = true
|
|
30
30
|
|
|
31
|
+
# Fail a spec that looks up a translation key that does not exist.
|
|
32
|
+
config.i18n.raise_on_missing_translations = true
|
|
33
|
+
|
|
31
34
|
# Tell Action Mailer not to deliver emails to the real world.
|
|
32
35
|
# The :test delivery method accumulates sent emails in the
|
|
33
36
|
# ActionMailer::Base.deliveries array.
|
|
@@ -39,6 +42,10 @@ Dummy::Application.configure do
|
|
|
39
42
|
# Print deprecation notices to the stderr
|
|
40
43
|
config.active_support.deprecation = :stderr
|
|
41
44
|
|
|
45
|
+
# Spree's own code must not call the deprecated Spree.t.
|
|
46
|
+
config.active_support.disallowed_deprecation = :raise
|
|
47
|
+
config.active_support.disallowed_deprecation_warnings = [/Spree\.t is deprecated/]
|
|
48
|
+
|
|
42
49
|
config.active_job.queue_adapter = :test
|
|
43
50
|
|
|
44
51
|
config.cache_store = :null_store
|
|
@@ -29,19 +29,19 @@ module Spree
|
|
|
29
29
|
|
|
30
30
|
def advisory_requirements
|
|
31
31
|
[].tap do |r|
|
|
32
|
-
r << req('cart', 'line_items',
|
|
33
|
-
r << req('address', 'email',
|
|
34
|
-
r << req('address', 'ship_address',
|
|
35
|
-
r << req('delivery', 'delivery_method',
|
|
36
|
-
r << req('payment', 'payment',
|
|
37
|
-
r << req('address', 'po_number',
|
|
32
|
+
r << req('cart', 'line_items', I18n.t('spree.checkout_requirements.line_items_required')) unless @cart.line_items.any?
|
|
33
|
+
r << req('address', 'email', I18n.t('spree.checkout_requirements.email_required')) unless @cart.email.present?
|
|
34
|
+
r << req('address', 'ship_address', I18n.t('spree.checkout_requirements.ship_address_required')) if @cart.shipping_address_required? && @cart.ship_address.blank?
|
|
35
|
+
r << req('delivery', 'delivery_method', I18n.t('spree.checkout_requirements.delivery_method_required')) if delivery_step_required? && !delivery_method_selected?
|
|
36
|
+
r << req('payment', 'payment', I18n.t('spree.checkout_requirements.payment_required')) if payment_required? && !payment_satisfied?
|
|
37
|
+
r << req('address', 'po_number', I18n.t('spree.checkout_requirements.po_number_required')) if po_number_missing?
|
|
38
38
|
r << order_minimum_requirement if below_order_minimum?
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def completion_requirements
|
|
43
|
-
errors = stock_errors + quantity_rule_errors
|
|
44
|
-
errors << req('address', 'email',
|
|
43
|
+
errors = stock_errors + quantity_rule_errors + assortment_errors
|
|
44
|
+
errors << req('address', 'email', I18n.t('spree.guest_checkout_not_allowed'), code: 'guest_checkout_not_allowed') if @cart.guest_checkout_disallowed?
|
|
45
45
|
errors
|
|
46
46
|
end
|
|
47
47
|
|
|
@@ -55,6 +55,22 @@ module Spree
|
|
|
55
55
|
end
|
|
56
56
|
end
|
|
57
57
|
|
|
58
|
+
# Re-checked at completion because a line can outlive the add that
|
|
59
|
+
# admitted it: a guest cart claimed after sign-in, a cart moved to
|
|
60
|
+
# another company, an assortment edited since. An order arriving here is
|
|
61
|
+
# staff's draft, which may sell outside the buyer's catalogs. A
|
|
62
|
+
# discontinued line already has its own requirement.
|
|
63
|
+
def assortment_errors
|
|
64
|
+
return [] unless @cart.is_a?(Spree::Cart)
|
|
65
|
+
|
|
66
|
+
line_items = completion_line_items.reject { |line_item| discontinued?(line_item) }
|
|
67
|
+
orderable_ids = @cart.orderable_variants.where(id: line_items.map(&:variant_id)).pluck(:id).to_set
|
|
68
|
+
|
|
69
|
+
line_items.reject { |line_item| orderable_ids.include?(line_item.variant_id) }.map do |line_item|
|
|
70
|
+
req('cart', 'line_items', I18n.t('spree.cart_line_item.not_orderable', li_name: line_item.name), code: 'not_orderable')
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
58
74
|
# Advisory rather than completion-only: a buyer has to be able to build
|
|
59
75
|
# the order below the threshold and read how far off they are while
|
|
60
76
|
# they can still add to it. Completion refuses it because the advisory
|
|
@@ -68,7 +84,7 @@ module Spree
|
|
|
68
84
|
shortfall = Spree::Money.new(@cart.order_minimum_shortfall, currency: minimum.currency)
|
|
69
85
|
|
|
70
86
|
req('cart', 'order_minimum',
|
|
71
|
-
|
|
87
|
+
I18n.t('spree.checkout_requirements.order_minimum_not_met',
|
|
72
88
|
minimum: minimum.display_amount.to_s, shortfall: shortfall.to_s),
|
|
73
89
|
code: 'order_minimum_not_met')
|
|
74
90
|
end
|
|
@@ -77,15 +93,23 @@ module Spree
|
|
|
77
93
|
# while an individual variant hit its discontinue_on date after it
|
|
78
94
|
# entered the cart.
|
|
79
95
|
def stock_errors
|
|
80
|
-
|
|
81
|
-
if
|
|
82
|
-
req('cart', 'line_items',
|
|
96
|
+
completion_line_items.filter_map do |line_item|
|
|
97
|
+
if discontinued?(line_item)
|
|
98
|
+
req('cart', 'line_items', I18n.t('spree.cart_line_item.discontinued', li_name: line_item.name), code: 'discontinued')
|
|
83
99
|
elsif !line_item.sufficient_stock?
|
|
84
|
-
req('cart', 'line_items',
|
|
100
|
+
req('cart', 'line_items', I18n.t('spree.cart_line_item.out_of_stock', li_name: line_item.name), code: 'out_of_stock')
|
|
85
101
|
end
|
|
86
102
|
end
|
|
87
103
|
end
|
|
88
104
|
|
|
105
|
+
def discontinued?(line_item)
|
|
106
|
+
line_item.variant.nil? || line_item.variant.discontinued? || line_item.variant.product.discontinued?
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def completion_line_items
|
|
110
|
+
@completion_line_items ||= @cart.line_items.includes(variant: :product).to_a
|
|
111
|
+
end
|
|
112
|
+
|
|
89
113
|
def delivery_step_required?
|
|
90
114
|
@cart.delivery_step_required?
|
|
91
115
|
end
|
|
@@ -60,7 +60,7 @@ module Spree
|
|
|
60
60
|
|
|
61
61
|
# Preprocessed product image variant sizes at 2x retina resolution.
|
|
62
62
|
# These variants are generated on upload to reduce runtime processing.
|
|
63
|
-
#
|
|
63
|
+
# Pass the variant to spree_image_url instead of a width and height.
|
|
64
64
|
#
|
|
65
65
|
# Default sizes:
|
|
66
66
|
# mini (128x128) - admin thumbnails, checkout line items
|
|
@@ -26,7 +26,7 @@ module Spree
|
|
|
26
26
|
|
|
27
27
|
if object.has_attribute?(:store_id)
|
|
28
28
|
if object.store.present? && object.store != current_store
|
|
29
|
-
raise
|
|
29
|
+
raise I18n.t('spree.errors.messages.store_is_already_set')
|
|
30
30
|
else
|
|
31
31
|
object.store = current_store
|
|
32
32
|
end
|
|
@@ -37,7 +37,6 @@ module Spree
|
|
|
37
37
|
order_update_item_service: 'Spree::Orders::UpdateItem',
|
|
38
38
|
order_remove_line_item_service: 'Spree::Orders::RemoveLineItem',
|
|
39
39
|
order_remove_item_service: 'Spree::Orders::RemoveItem',
|
|
40
|
-
cart_empty_service: 'Spree::Carts::Empty',
|
|
41
40
|
cart_destroy_service: 'Spree::Carts::Destroy',
|
|
42
41
|
cart_associate_service: 'Spree::Carts::Associate',
|
|
43
42
|
cart_remove_out_of_stock_items_service: 'Spree::Carts::RemoveOutOfStockItems',
|
|
@@ -83,7 +82,6 @@ module Spree
|
|
|
83
82
|
fulfillment_fulfill_workflow: 'Spree::Fulfillments::Fulfill',
|
|
84
83
|
fulfillment_cancel_workflow: 'Spree::Fulfillments::Cancel',
|
|
85
84
|
fulfillment_mark_delivered_workflow: 'Spree::Fulfillments::MarkDelivered',
|
|
86
|
-
fulfillment_purchase_label_workflow: 'Spree::Fulfillments::PurchaseLabel',
|
|
87
85
|
|
|
88
86
|
# shipping labels + deliveries
|
|
89
87
|
shipping_label_purchase_workflow: 'Spree::ShippingLabels::Purchase',
|
|
@@ -97,7 +95,6 @@ module Spree
|
|
|
97
95
|
fulfillment_stand_down_service: 'Spree::Fulfillments::StandDownProvider',
|
|
98
96
|
fulfillment_recalculate_delivery_service: 'Spree::Fulfillments::RecalculateDelivery',
|
|
99
97
|
delivery_destroy_service: 'Spree::Deliveries::Destroy',
|
|
100
|
-
return_purchase_label_workflow: 'Spree::Returns::PurchaseLabel',
|
|
101
98
|
|
|
102
99
|
# inventory operations
|
|
103
100
|
stock_level_correct_service: 'Spree::StockLevels::Correct',
|
|
@@ -242,7 +239,6 @@ module Spree
|
|
|
242
239
|
# payment is arranged (deposits, net terms).
|
|
243
240
|
purchase_amount_due_at_checkout_service: 'Spree::Purchases::AmountDueAtCheckout',
|
|
244
241
|
|
|
245
|
-
payment_create_service: 'Spree::Payments::Create',
|
|
246
242
|
payment_process_workflow: 'Spree::Payments::Process',
|
|
247
243
|
payment_capture_workflow: 'Spree::Payments::Capture',
|
|
248
244
|
payment_void_workflow: 'Spree::Payments::Void',
|
|
@@ -253,6 +249,11 @@ module Spree
|
|
|
253
249
|
seller_payout_complete_workflow: 'Spree::SellerPayouts::Complete',
|
|
254
250
|
payments_handle_webhook_workflow: 'Spree::Payments::HandleWebhook',
|
|
255
251
|
payment_session_complete_workflow: 'Spree::PaymentSessions::Complete',
|
|
252
|
+
email_template_save_draft_workflow: 'Spree::EmailTemplates::SaveDraft',
|
|
253
|
+
email_template_publish_workflow: 'Spree::EmailTemplates::Publish',
|
|
254
|
+
email_template_revert_workflow: 'Spree::EmailTemplates::Revert',
|
|
255
|
+
email_template_discard_draft_workflow: 'Spree::EmailTemplates::DiscardDraft',
|
|
256
|
+
email_template_restore_revision_workflow: 'Spree::EmailTemplates::RestoreRevision',
|
|
256
257
|
|
|
257
258
|
# finders
|
|
258
259
|
current_store_finder: 'Spree::Stores::FindDefault',
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Core
|
|
3
|
+
module Emails
|
|
4
|
+
# HTML-escapes what a Liquid email template prints, unless the value was
|
|
5
|
+
# marked `| raw`. Applied where output is written rather than through
|
|
6
|
+
# Liquid's global filter, which `{% assign %}` also runs through — that
|
|
7
|
+
# would escape a value once when assigned and again when printed, and
|
|
8
|
+
# turn assigned numbers and lists into strings.
|
|
9
|
+
#
|
|
10
|
+
# Switched on by the `escape_output` register, which Liquid hands down to
|
|
11
|
+
# every partial, so any other Liquid the host app runs is untouched.
|
|
12
|
+
module EscapedOutput
|
|
13
|
+
def self.active?(context)
|
|
14
|
+
context.registers[:escape_output]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# `{{ value }}` and `{% echo value %}`. Variables are not tags, so this
|
|
18
|
+
# is the one place Liquid itself has to be extended.
|
|
19
|
+
module Variable
|
|
20
|
+
def render_to_output_buffer(context, output)
|
|
21
|
+
return super unless EscapedOutput.active?(context)
|
|
22
|
+
|
|
23
|
+
write_escaped(render(context), output)
|
|
24
|
+
output
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def write_escaped(value, output)
|
|
30
|
+
case value
|
|
31
|
+
when nil then nil
|
|
32
|
+
when Array then value.each { |item| write_escaped(item, output) }
|
|
33
|
+
else output << ERB::Util.html_escape(Liquid::Utils.to_s(value))
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# A captured block was escaped as it rendered, so it is kept as safe
|
|
39
|
+
# HTML rather than escaped a second time when printed.
|
|
40
|
+
class Capture < Liquid::Capture
|
|
41
|
+
def render(context)
|
|
42
|
+
output = super
|
|
43
|
+
EscapedOutput.active?(context) ? output.html_safe : output
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# `{% cycle %}` writes its values straight to the output.
|
|
48
|
+
class Cycle < Liquid::Cycle
|
|
49
|
+
def render_to_output_buffer(context, output)
|
|
50
|
+
return super unless EscapedOutput.active?(context)
|
|
51
|
+
|
|
52
|
+
output << ERB::Util.html_escape(super(context, +''))
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
Liquid::Variable.prepend(Spree::Core::Emails::EscapedOutput::Variable)
|