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
|
@@ -1,43 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
<head>
|
|
4
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
5
|
-
<meta name="x-apple-disable-message-reformatting"/>
|
|
6
|
-
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
|
7
|
-
<meta name="color-scheme" content="light"/>
|
|
8
|
-
<meta name="supported-color-schemes" content="light"/>
|
|
9
|
-
|
|
10
|
-
<%= render partial: 'spree/shared/base_mailer_stylesheets' %>
|
|
11
|
-
<%# Per-email styles — templates add their own via `content_for :head` %>
|
|
12
|
-
<%= yield :head %>
|
|
13
|
-
</head>
|
|
14
|
-
<body class="email-bg" style="margin: 0; padding: 0; -webkit-text-size-adjust: none;" bgcolor="#FFFFFF">
|
|
15
|
-
<table class="email-wrapper" width="100%" cellpadding="0" cellspacing="0" role="presentation" bgcolor="#FFFFFF">
|
|
16
|
-
<tr>
|
|
17
|
-
<td align="center">
|
|
18
|
-
<table class="email-content" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
|
19
|
-
<!-- Email Body -->
|
|
20
|
-
<tr>
|
|
21
|
-
<td class="email-card" bgcolor="#F6F6F6">
|
|
22
|
-
<%= render partial: 'spree/shared/base_mailer_header' %>
|
|
23
|
-
<table width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
|
24
|
-
<tr>
|
|
25
|
-
<td class="content-cell f-fallback" align="left">
|
|
26
|
-
<%= yield %>
|
|
27
|
-
</td>
|
|
28
|
-
</tr>
|
|
29
|
-
</table>
|
|
30
|
-
</td>
|
|
31
|
-
</tr>
|
|
32
|
-
<!-- Email Footer -->
|
|
33
|
-
<tr>
|
|
34
|
-
<td class="email-footer" align="center">
|
|
35
|
-
<%= render partial: 'spree/shared/base_mailer_footer' %>
|
|
36
|
-
</td>
|
|
37
|
-
</tr>
|
|
38
|
-
</table>
|
|
39
|
-
</td>
|
|
40
|
-
</tr>
|
|
41
|
-
</table>
|
|
42
|
-
</body>
|
|
43
|
-
</html>
|
|
1
|
+
<%# Mailers that render their own ERB views get Spree's Liquid email layout around them. %>
|
|
2
|
+
<%= render_in_email_layout(yield) %>
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{% assign brand = store.branding %}<mjml lang="{{ locale }}">
|
|
2
|
+
<mj-head>
|
|
3
|
+
<mj-title>{{ subject }}</mj-title>
|
|
4
|
+
{% if brand.font_url %}<mj-font name="{{ brand.font_family | split: ',' | first }}" href="{{ brand.font_url }}" />{% endif %}
|
|
5
|
+
<mj-attributes>
|
|
6
|
+
<mj-all font-family="{{ brand.font_family }}" />
|
|
7
|
+
<mj-section padding="0" />
|
|
8
|
+
<mj-column padding="0" />
|
|
9
|
+
<mj-text padding="0" color="{{ brand.text_color }}" font-size="14px" line-height="1.6" align="center" />
|
|
10
|
+
<mj-button background-color="{{ brand.button_color }}" border="{{ brand.button_border }}" border-radius="8px" color="{{ brand.button_text_color }}" font-size="15px" font-weight="500" line-height="1.6" inner-padding="12px 20px" padding="32px 0 0" />
|
|
11
|
+
<mj-table padding="0" color="{{ brand.text_color }}" font-size="14px" line-height="1.6" />
|
|
12
|
+
<mj-class name="heading" font-family="{{ brand.heading_font_family }}" font-size="40px" font-weight="700" line-height="1.2" letter-spacing="-0.8px" color="{{ brand.heading_color }}" css-class="heading" />
|
|
13
|
+
<mj-class name="greeting" padding="24px 0 0" font-size="15px" font-weight="500" color="{{ brand.heading_color }}" />
|
|
14
|
+
<mj-class name="lead" padding="12px 0 0" />
|
|
15
|
+
<mj-class name="note" padding="24px 0 0" font-size="13px" css-class="note" />
|
|
16
|
+
<mj-class name="section-heading" padding="48px 0 16px" font-family="{{ brand.heading_font_family }}" font-size="16px" font-weight="500" letter-spacing="-0.16px" align="left" />
|
|
17
|
+
<mj-class name="body" padding="16px 0 0" align="left" />
|
|
18
|
+
<mj-class name="footer" padding="12px 0 0" font-size="11px" line-height="1.5" />
|
|
19
|
+
</mj-attributes>
|
|
20
|
+
<mj-style>
|
|
21
|
+
{% if brand.font == 'inter' %}
|
|
22
|
+
@font-face { font-family: "Geist"; font-style: normal; font-weight: 500 700; src: url("https://fonts.gstatic.com/s/geist/v4/gyByhwUxId8gMEwcGFU.woff2") format("woff2"); }
|
|
23
|
+
@font-face { font-family: "Inter"; font-style: normal; font-weight: 400 450; src: url("https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuOKfMZg.ttf") format("truetype"); }
|
|
24
|
+
@font-face { font-family: "Inter"; font-style: normal; font-weight: 500; src: url("https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuI6fMZg.ttf") format("truetype"); }
|
|
25
|
+
@font-face { font-family: "Inter"; font-style: normal; font-weight: 600; src: url("https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuGKYMZg.ttf") format("truetype"); }
|
|
26
|
+
{% endif %}
|
|
27
|
+
a { color: {{ brand.link_color }}; }
|
|
28
|
+
.hero > table { max-width: 420px; margin: 0 auto; }
|
|
29
|
+
.note a { color: {{ brand.text_color }}; word-break: break-all; }
|
|
30
|
+
.footer a { color: {{ brand.text_color }}; }
|
|
31
|
+
.item { width: 100%; background-color: #F0F0F0; border-radius: 16px; margin: 0 0 8px; }
|
|
32
|
+
.item_image { padding: 8px; width: 96px; }
|
|
33
|
+
.item_thumb { display: block; width: 80px; height: auto; border-radius: 12px; }
|
|
34
|
+
.item_thumb_placeholder { width: 80px; height: 80px; background-color: #E4E4E4; border-radius: 12px; }
|
|
35
|
+
.item_info { padding: 8px 16px 8px 8px; }
|
|
36
|
+
.item_name { font-size: 15px; line-height: 1.5; font-weight: 500; color: {{ brand.heading_color }}; text-decoration: none; }
|
|
37
|
+
.item_meta { margin: 2px 0 0; font-size: 13px; line-height: 1.5; color: {{ brand.text_color }}; }
|
|
38
|
+
.item_amount { padding: 8px 16px 8px 8px; text-align: right; white-space: nowrap; }
|
|
39
|
+
.item_qty { margin: 0; font-size: 13px; line-height: 1.5; color: {{ brand.text_color }}; }
|
|
40
|
+
.item_price { margin: 2px 0 0; font-size: 15px; line-height: 1.5; font-weight: 500; color: {{ brand.heading_color }}; }
|
|
41
|
+
.summary td { padding: 6px 0; font-size: 14px; line-height: 1.6; color: {{ brand.text_color }}; }
|
|
42
|
+
.summary_value { font-size: 15px; font-weight: 500; text-align: right; white-space: nowrap; color: {{ brand.heading_color }}; }
|
|
43
|
+
.summary_sub { display: block; font-size: 13px; line-height: 1.5; }
|
|
44
|
+
.summary_total td { padding: 14px 0 0; border-top: 1px solid #E8E9E9; font-weight: 500; color: {{ brand.heading_color }}; }
|
|
45
|
+
.summary_total .summary_value { font-weight: 600; }
|
|
46
|
+
.mailer_hero h1 { margin: 0; font-family: {{ brand.heading_font_family }}; font-size: 40px; line-height: 1.2; letter-spacing: -0.8px; font-weight: 700; color: {{ brand.heading_color }}; }
|
|
47
|
+
.mailer_hero p { margin: 12px 0 0; }
|
|
48
|
+
.mailer_hero .greeting { margin-top: 24px; font-size: 15px; font-weight: 500; color: {{ brand.heading_color }}; }
|
|
49
|
+
.mailer_hero .sub { margin-top: 24px; font-size: 13px; }
|
|
50
|
+
@media only screen and (max-width: 600px) {
|
|
51
|
+
.heading div { font-size: 32px !important; letter-spacing: -0.64px !important; }
|
|
52
|
+
}
|
|
53
|
+
</mj-style>
|
|
54
|
+
</mj-head>
|
|
55
|
+
<mj-body background-color="{{ brand.background_color }}" width="640px">
|
|
56
|
+
<mj-wrapper background-color="{{ brand.card_color }}" padding="56px 24px">
|
|
57
|
+
<mj-section padding="0 0 32px">
|
|
58
|
+
<mj-column>
|
|
59
|
+
{% if store.logo_url and store.logo_width %}
|
|
60
|
+
<mj-image src="{{ store.logo_url }}" href="{{ store.url }}" alt="{{ store.name }}" width="{{ store.logo_width }}px" height="32px" padding="0" />
|
|
61
|
+
{% elsif store.logo_url %}
|
|
62
|
+
<mj-text><a href="{{ store.url }}"><img src="{{ store.logo_url }}" alt="{{ store.name }}" height="32" style="height: 32px; width: auto; border: 0;" /></a></mj-text>
|
|
63
|
+
{% else %}
|
|
64
|
+
<mj-text font-size="22px" font-weight="700" color="{{ brand.heading_color }}" text-transform="uppercase"><a href="{{ store.url }}" style="color: {{ brand.heading_color }}; text-decoration: none;">{{ store.name }}</a></mj-text>
|
|
65
|
+
{% endif %}
|
|
66
|
+
</mj-column>
|
|
67
|
+
</mj-section>
|
|
68
|
+
{{ content_for_layout }}
|
|
69
|
+
</mj-wrapper>
|
|
70
|
+
<mj-section padding="64px 24px">
|
|
71
|
+
<mj-column>
|
|
72
|
+
<mj-text font-size="13px" line-height="1.5" css-class="footer"><a href="{{ store.url }}" style="font-weight: 500; text-decoration: none;">{{ store.name }}</a></mj-text>
|
|
73
|
+
{% if store.address != blank %}<mj-text mj-class="footer">{{ store.address }}</mj-text>{% endif %}
|
|
74
|
+
{% if store.support_email != blank %}<mj-text mj-class="footer" css-class="footer"><a href="mailto:{{ store.support_email }}">{{ store.support_email }}</a></mj-text>{% endif %}
|
|
75
|
+
<mj-text mj-class="footer" padding="20px 0 0">© {{ 'now' | date: '%Y' }} {{ store.name }}</mj-text>
|
|
76
|
+
</mj-column>
|
|
77
|
+
</mj-section>
|
|
78
|
+
</mj-body>
|
|
79
|
+
</mjml>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
subject: "{{ store.name }} {{ 'admin_user_mailer.password_reset_email.subject' | t }}"
|
|
3
|
+
---
|
|
4
|
+
{% assign name = user.first_name | default: user.email %}
|
|
5
|
+
<mj-section>
|
|
6
|
+
<mj-column css-class="hero">
|
|
7
|
+
<mj-text mj-class="heading">{{ 'admin_user_mailer.password_reset_email.action' | t }}</mj-text>
|
|
8
|
+
<mj-text mj-class="greeting">{{ 'admin_user_mailer.password_reset_email.greeting' | t: name: name }}</mj-text>
|
|
9
|
+
<mj-text mj-class="lead">{{ 'admin_user_mailer.password_reset_email.instructions' | t: store_name: store.name }}</mj-text>
|
|
10
|
+
<mj-button href="{{ reset_url }}">{{ 'admin_user_mailer.password_reset_email.action' | t }}</mj-button>
|
|
11
|
+
<mj-text mj-class="note">{{ 'admin_user_mailer.password_reset_email.expiry_notice' | t }}</mj-text>
|
|
12
|
+
<mj-text mj-class="note" padding="16px 0 0">{{ 'admin_user_mailer.password_reset_email.ignore_notice' | t }}</mj-text>
|
|
13
|
+
</mj-column>
|
|
14
|
+
</mj-section>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
subject: "{{ 'export_mailer.export_done.subject' | t: export_number: export.number }}"
|
|
3
|
+
---
|
|
4
|
+
<mj-section>
|
|
5
|
+
<mj-column css-class="hero">
|
|
6
|
+
<mj-text mj-class="heading">{{ 'export_mailer.greeting' | t: user_name: export.user.first_name }}</mj-text>
|
|
7
|
+
<mj-text mj-class="lead">{{ 'export_mailer.export_done.message' | t }}</mj-text>
|
|
8
|
+
{% if export.results_url != blank %}
|
|
9
|
+
<mj-button href="{{ export.results_url }}">{{ export.filename }}</mj-button>
|
|
10
|
+
{% endif %}
|
|
11
|
+
</mj-column>
|
|
12
|
+
</mj-section>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
subject: "{{ 'import_mailer.import_done.subject' | t: import_number: import.number }}"
|
|
3
|
+
---
|
|
4
|
+
<mj-section>
|
|
5
|
+
<mj-column css-class="hero">
|
|
6
|
+
<mj-text mj-class="heading">{{ 'import_mailer.greeting' | t: user_name: import.user.first_name }}</mj-text>
|
|
7
|
+
<mj-text mj-class="lead">{{ 'import_mailer.import_done.message' | t: completed_count: import.completed_count }}</mj-text>
|
|
8
|
+
{% if import.failed_count > 0 %}
|
|
9
|
+
<mj-text mj-class="lead"><strong>{{ 'import_mailer.import_done.failed_message' | t: failed_count: import.failed_count }}</strong></mj-text>
|
|
10
|
+
{% endif %}
|
|
11
|
+
{% if import.results_url != blank %}
|
|
12
|
+
<mj-button href="{{ import.results_url }}">{{ 'import_mailer.import_done.view_results' | t }}</mj-button>
|
|
13
|
+
{% endif %}
|
|
14
|
+
</mj-column>
|
|
15
|
+
</mj-section>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
subject: "{{ 'invitation_mailer.invitation_accepted.subject' | t: invitee_name: invitation.invitee_name, resource_name: invitation.resource_name }}"
|
|
3
|
+
---
|
|
4
|
+
<mj-section>
|
|
5
|
+
<mj-column css-class="hero">
|
|
6
|
+
<mj-text mj-class="heading">{{ 'invitation_mailer.greeting' | t: user_name: invitation.inviter_first_name }}</mj-text>
|
|
7
|
+
<mj-text mj-class="lead">{{ 'invitation_mailer.invitation_accepted.body' | t: invitee_name: invitation.invitee_name, resource_name: invitation.resource_name }}</mj-text>
|
|
8
|
+
</mj-column>
|
|
9
|
+
</mj-section>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
subject: "{{ 'invitation_mailer.invitation_email.subject' | t: resource_name: invitation.resource_name }}"
|
|
3
|
+
---
|
|
4
|
+
{% assign name = invitation.invitee_first_name | default: invitation.email %}
|
|
5
|
+
<mj-section>
|
|
6
|
+
<mj-column css-class="hero">
|
|
7
|
+
<mj-text mj-class="heading">{{ 'invitation_mailer.invitation_email.subject' | t: resource_name: invitation.resource_name }}</mj-text>
|
|
8
|
+
<mj-text mj-class="greeting">{{ 'invitation_mailer.greeting' | t: user_name: name }}</mj-text>
|
|
9
|
+
<mj-text mj-class="lead">{{ 'invitation_mailer.invitation_email.body' | t: inviter_name: invitation.inviter_name, resource_name: invitation.resource_name }}</mj-text>
|
|
10
|
+
<mj-text mj-class="lead">{{ 'invitation_mailer.invitation_email.link_description' | t }}</mj-text>
|
|
11
|
+
<mj-button href="{{ accept_url }}">{{ 'accept' | t }}</mj-button>
|
|
12
|
+
</mj-column>
|
|
13
|
+
</mj-section>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
subject: "{{ store.name }} {{ 'seller_user_mailer.password_reset_email.subject' | t }}"
|
|
3
|
+
---
|
|
4
|
+
{% assign name = user.first_name | default: user.email %}
|
|
5
|
+
<mj-section>
|
|
6
|
+
<mj-column css-class="hero">
|
|
7
|
+
<mj-text mj-class="heading">{{ 'seller_user_mailer.password_reset_email.action' | t }}</mj-text>
|
|
8
|
+
<mj-text mj-class="greeting">{{ 'seller_user_mailer.password_reset_email.greeting' | t: name: name }}</mj-text>
|
|
9
|
+
<mj-text mj-class="lead">{{ 'seller_user_mailer.password_reset_email.instructions' | t: store_name: store.name }}</mj-text>
|
|
10
|
+
<mj-button href="{{ reset_url }}">{{ 'seller_user_mailer.password_reset_email.action' | t }}</mj-button>
|
|
11
|
+
<mj-text mj-class="note">{{ 'seller_user_mailer.password_reset_email.expiry_notice' | t }}</mj-text>
|
|
12
|
+
<mj-text mj-class="note" padding="16px 0 0">{{ 'seller_user_mailer.password_reset_email.ignore_notice' | t }}</mj-text>
|
|
13
|
+
</mj-column>
|
|
14
|
+
</mj-section>
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
<table
|
|
1
|
+
<%# A call-to-action button for a custom mailer's ERB view. Locals: url, label. %>
|
|
2
|
+
<table align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation" style="margin: 32px auto 0;">
|
|
3
3
|
<tr>
|
|
4
4
|
<td align="center">
|
|
5
|
-
<a href="<%= url %>"
|
|
6
|
-
|
|
7
|
-
</a>
|
|
5
|
+
<a href="<%= url %>" target="_blank"
|
|
6
|
+
style="display: inline-block; background-color: #FFFFFF; border: 1px solid #E8E9E9; border-radius: 8px; padding: 12px 20px; font-size: 15px; line-height: 1.6; font-weight: 500; color: #1F2222; text-decoration: none;"><%= label %></a>
|
|
8
7
|
</td>
|
|
9
8
|
</tr>
|
|
10
9
|
</table>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
<%# Centered hero block
|
|
2
|
-
|
|
3
|
-
render layout: 'spree/shared/mailer_hero' do ... end
|
|
4
|
-
|
|
1
|
+
<%# Centered hero block for a custom mailer's ERB view. Render it as a layout so
|
|
2
|
+
the view's heading and copy fill it:
|
|
3
|
+
render layout: 'spree/shared/mailer_hero' do ... end
|
|
4
|
+
Style its contents with h1, p.greeting and p.sub. %>
|
|
5
|
+
<table class="mailer_hero" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
|
5
6
|
<tr>
|
|
6
7
|
<td align="center">
|
|
7
|
-
<div
|
|
8
|
+
<div style="max-width: 420px; margin: 0 auto; text-align: center;">
|
|
8
9
|
<%= yield %>
|
|
9
10
|
</div>
|
|
10
11
|
</td>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
One label/value row inside an <mj-table css-class="summary">.
|
|
3
|
+
Arguments: label (translation key when translate is true), value, optional sub (a second line under the label), optional total (the emphasized final row).
|
|
4
|
+
{%- endcomment -%}
|
|
5
|
+
<tr{% if total %} class="summary_total"{% endif %}>
|
|
6
|
+
<td valign="top">{% if translate %}{{ label | t }}{% else %}{{ label }}{% endif %}{% if sub != blank %} <span class="summary_sub">{{ sub }}</span>{% endif %}</td>
|
|
7
|
+
<td class="summary_value" align="right" valign="top">{{ value }}</td>
|
|
8
|
+
</tr>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
subject: "{{ 'webhook_mailer.endpoint_disabled.subject' | t: endpoint_name: endpoint.display_name }}"
|
|
3
|
+
---
|
|
4
|
+
{% assign disabled_at = endpoint.disabled_at | date: '%Y-%m-%d %H:%M %Z' %}
|
|
5
|
+
<mj-section>
|
|
6
|
+
<mj-column css-class="hero">
|
|
7
|
+
<mj-text mj-class="heading">{{ 'webhook_mailer.endpoint_disabled.heading' | t }}</mj-text>
|
|
8
|
+
<mj-text mj-class="lead">{{ 'webhook_mailer.endpoint_disabled.message' | t: endpoint_name: endpoint.display_name }}</mj-text>
|
|
9
|
+
</mj-column>
|
|
10
|
+
</mj-section>
|
|
11
|
+
<mj-section padding="48px 0 0">
|
|
12
|
+
<mj-column>
|
|
13
|
+
<mj-table css-class="summary">
|
|
14
|
+
{% render 'spree/shared/summary_row', label: 'webhook_mailer.endpoint_disabled.url_label', value: endpoint.url, translate: true %}
|
|
15
|
+
{% if endpoint.name != blank %}{% render 'spree/shared/summary_row', label: 'webhook_mailer.endpoint_disabled.name_label', value: endpoint.name, translate: true %}{% endif %}
|
|
16
|
+
{% render 'spree/shared/summary_row', label: 'webhook_mailer.endpoint_disabled.reason_label', value: endpoint.disabled_reason, translate: true %}
|
|
17
|
+
{% render 'spree/shared/summary_row', label: 'webhook_mailer.endpoint_disabled.disabled_at_label', value: disabled_at, translate: true %}
|
|
18
|
+
</mj-table>
|
|
19
|
+
<mj-text mj-class="body" padding="48px 0 0">{{ 'webhook_mailer.endpoint_disabled.instructions' | t }}</mj-text>
|
|
20
|
+
</mj-column>
|
|
21
|
+
</mj-section>
|
|
@@ -61,17 +61,17 @@ module Spree
|
|
|
61
61
|
# @return [Spree::ServiceModule::Result, nil] failure when the price is refused
|
|
62
62
|
def parse_manual_price
|
|
63
63
|
if cart.completed?
|
|
64
|
-
errors.add(:base, :price_override_not_allowed, message:
|
|
64
|
+
errors.add(:base, :price_override_not_allowed, message: I18n.t('spree.cart_line_item.price_override_not_allowed'))
|
|
65
65
|
return failure(cart, errors)
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
@manual_price = BigDecimal(price.to_s)
|
|
69
69
|
if @manual_price.negative? || !@manual_price.finite?
|
|
70
|
-
errors.add(:base, :invalid_price, message:
|
|
70
|
+
errors.add(:base, :invalid_price, message: I18n.t('spree.cart_line_item.invalid_price'))
|
|
71
71
|
return failure(cart, errors)
|
|
72
72
|
end
|
|
73
73
|
rescue ArgumentError
|
|
74
|
-
errors.add(:base, :invalid_price, message:
|
|
74
|
+
errors.add(:base, :invalid_price, message: I18n.t('spree.cart_line_item.invalid_price'))
|
|
75
75
|
failure(cart, errors)
|
|
76
76
|
end
|
|
77
77
|
|
|
@@ -158,7 +158,7 @@ module Spree
|
|
|
158
158
|
|
|
159
159
|
return if result.value.blank?
|
|
160
160
|
|
|
161
|
-
failure(variant,
|
|
161
|
+
failure(variant, I18n.t('spree.selected_quantity_not_available', item: variant.name.inspect))
|
|
162
162
|
end
|
|
163
163
|
|
|
164
164
|
# Asked before the item exists, so the context carries the quantity the
|
|
@@ -47,6 +47,7 @@ module Spree
|
|
|
47
47
|
|
|
48
48
|
cart.with_lock do
|
|
49
49
|
step :guard_concurrent_completion
|
|
50
|
+
step :guard_coupon_code
|
|
50
51
|
step :recalculate_in_lock
|
|
51
52
|
step :verify_expected_total
|
|
52
53
|
step :validate_cart
|
|
@@ -92,7 +93,7 @@ module Spree
|
|
|
92
93
|
halt!(result) if result.canceled?
|
|
93
94
|
|
|
94
95
|
if !result.placed? && result.payment_required? && !payment_covered?(result)
|
|
95
|
-
failure(cart, code: 'payment_failed', message:
|
|
96
|
+
failure(cart, code: 'payment_failed', message: I18n.t('spree.payment_processing_failed'))
|
|
96
97
|
end
|
|
97
98
|
|
|
98
99
|
finalize!(cart, result)
|
|
@@ -113,6 +114,15 @@ module Spree
|
|
|
113
114
|
failure(cart, code: 'completion_in_progress') if cart.completion_claimed?
|
|
114
115
|
end
|
|
115
116
|
|
|
117
|
+
# A batch code this cart no longer holds no longer discounts it, so the
|
|
118
|
+
# shopper would be charged more than the total they last saw, and the
|
|
119
|
+
# order would name a code it never used.
|
|
120
|
+
def guard_coupon_code
|
|
121
|
+
return unless cart.coupon_code_unavailable?
|
|
122
|
+
|
|
123
|
+
failure(cart, code: 'coupon_code_unavailable', message: I18n.t('spree.coupon_code_unavailable'))
|
|
124
|
+
end
|
|
125
|
+
|
|
116
126
|
# In-lock recalculation — the totals about to be charged are computed
|
|
117
127
|
# here, not trusted from earlier requests.
|
|
118
128
|
# Only external pricing is re-confirmed: Spree's own catalog is read
|
|
@@ -165,7 +175,7 @@ module Spree
|
|
|
165
175
|
return if payment_covered?(order)
|
|
166
176
|
|
|
167
177
|
failure(cart, code: 'payment_failed',
|
|
168
|
-
message: order.errors.full_messages.to_sentence.presence ||
|
|
178
|
+
message: order.errors.full_messages.to_sentence.presence || I18n.t('spree.payment_processing_failed'))
|
|
169
179
|
rescue Spree::Core::GatewayError => e
|
|
170
180
|
failure(cart, code: 'payment_failed', message: e.message)
|
|
171
181
|
end
|
|
@@ -328,7 +338,7 @@ module Spree
|
|
|
328
338
|
line_item_id_map = line_item_map.transform_keys(&:id).transform_values(&:id)
|
|
329
339
|
|
|
330
340
|
cart.fulfillments.reload.each_with_object({}) do |cart_fulfillment, map|
|
|
331
|
-
attributes = cart_fulfillment.attributes.except('id', 'cart_id', 'number', 'created_at', 'updated_at')
|
|
341
|
+
attributes = cart_fulfillment.attributes.except('id', 'cart_id', 'number', 'tracking', 'created_at', 'updated_at')
|
|
332
342
|
fulfillment = order.fulfillments.create!(attributes.merge('order_id' => order.id, 'address_id' => order.ship_address_id))
|
|
333
343
|
|
|
334
344
|
if (selected = cart_fulfillment.selected_delivery_rate)
|
|
@@ -42,7 +42,7 @@ module Spree
|
|
|
42
42
|
def ensure_matching_currency
|
|
43
43
|
return if other_cart.currency == cart.currency
|
|
44
44
|
|
|
45
|
-
failure(cart,
|
|
45
|
+
failure(cart, I18n.t('spree.errors.messages.cart_currency_mismatch'))
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
# A matching item absorbs the quantity; everything else is re-pointed
|
|
@@ -40,6 +40,7 @@ module Spree
|
|
|
40
40
|
step :fold_typed_rows
|
|
41
41
|
step :refresh_grand_total
|
|
42
42
|
step :persist_totals
|
|
43
|
+
step :resize_gift_card_payment unless money_frozen?
|
|
43
44
|
|
|
44
45
|
success(cart)
|
|
45
46
|
end
|
|
@@ -175,6 +176,10 @@ module Spree
|
|
|
175
176
|
cart.update_columns(columns)
|
|
176
177
|
end
|
|
177
178
|
|
|
179
|
+
def resize_gift_card_payment
|
|
180
|
+
cart.recalculate_gift_card
|
|
181
|
+
end
|
|
182
|
+
|
|
178
183
|
def money_frozen?
|
|
179
184
|
resum_only || (cart.is_a?(Spree::Order) && cart.completed?)
|
|
180
185
|
end
|
|
@@ -33,8 +33,10 @@ module Spree
|
|
|
33
33
|
# amount negotiates the line (+price_source: 'manual'+), an explicit
|
|
34
34
|
# nil reverts a negotiated line to catalog pricing. Admin surface
|
|
35
35
|
# only (draft orders); refused once the order is placed.
|
|
36
|
+
# @param orderable_variants [ActiveRecord::Relation<Spree::Variant>, nil]
|
|
37
|
+
# what an add may name; the store's variants when nil
|
|
36
38
|
# @return [Spree::ServiceModule::Result] value is the cart
|
|
37
|
-
def perform(cart:, items:)
|
|
39
|
+
def perform(cart:, items:, orderable_variants: nil)
|
|
38
40
|
super
|
|
39
41
|
@warnings = []
|
|
40
42
|
|
|
@@ -107,7 +109,7 @@ module Spree
|
|
|
107
109
|
# Price overrides are pre-placement only. reject! rather than
|
|
108
110
|
# failure(cart, message), which would drop the message.
|
|
109
111
|
if cart.completed? && @resolved_items.any?(&:price_provided)
|
|
110
|
-
errors.add(:base, :price_override_not_allowed, message:
|
|
112
|
+
errors.add(:base, :price_override_not_allowed, message: I18n.t('spree.cart_line_item.price_override_not_allowed'))
|
|
111
113
|
reject!(nil, cart)
|
|
112
114
|
end
|
|
113
115
|
end
|
|
@@ -121,19 +123,19 @@ module Spree
|
|
|
121
123
|
return nil if value.nil?
|
|
122
124
|
|
|
123
125
|
if cart.completed?
|
|
124
|
-
errors.add(:base, :price_override_not_allowed, message:
|
|
126
|
+
errors.add(:base, :price_override_not_allowed, message: I18n.t('spree.cart_line_item.price_override_not_allowed'))
|
|
125
127
|
reject!(nil, cart)
|
|
126
128
|
end
|
|
127
129
|
|
|
128
130
|
parsed = BigDecimal(value.to_s)
|
|
129
131
|
if parsed.negative? || !parsed.finite?
|
|
130
|
-
errors.add(:base, :invalid_price, message:
|
|
132
|
+
errors.add(:base, :invalid_price, message: I18n.t('spree.cart_line_item.invalid_price'))
|
|
131
133
|
reject!(nil, cart)
|
|
132
134
|
end
|
|
133
135
|
|
|
134
136
|
parsed
|
|
135
137
|
rescue ArgumentError
|
|
136
|
-
errors.add(:base, :invalid_price, message:
|
|
138
|
+
errors.add(:base, :invalid_price, message: I18n.t('spree.cart_line_item.invalid_price'))
|
|
137
139
|
reject!(nil, cart)
|
|
138
140
|
end
|
|
139
141
|
|
|
@@ -230,7 +232,7 @@ module Spree
|
|
|
230
232
|
# external system can be the only source for a currency. A
|
|
231
233
|
# negotiated price is a quote too, made by the merchant.
|
|
232
234
|
if !item.manual_price? && resolved_prices[item.variant.id]&.at(1)&.amount.nil? && item.variant.amount_in(cart.currency).nil?
|
|
233
|
-
message =
|
|
235
|
+
message = I18n.t('spree.cart_line_item.currency_unavailable', li_name: item.variant.name, currency: cart.currency)
|
|
234
236
|
failure(item.variant, message) unless partial_success?
|
|
235
237
|
|
|
236
238
|
warn(index, item, :currency_unavailable, message)
|
|
@@ -238,7 +240,7 @@ module Spree
|
|
|
238
240
|
end
|
|
239
241
|
|
|
240
242
|
if unsupplyable?(item)
|
|
241
|
-
message =
|
|
243
|
+
message = I18n.t('spree.selected_quantity_not_available', item: item.variant.name.inspect)
|
|
242
244
|
failure(item.variant, message) unless partial_success?
|
|
243
245
|
|
|
244
246
|
warn(index, item, :selected_quantity_not_available, message)
|
|
@@ -355,8 +357,15 @@ module Spree
|
|
|
355
357
|
cart.line_items.detect { |line_item| line_item.variant_id.to_s == variant_id.to_s }&.variant ||
|
|
356
358
|
Spree::Variant.with_deleted.find_by_param(variant_id)
|
|
357
359
|
else
|
|
358
|
-
store.variants.find_by_param(variant_id)
|
|
359
|
-
|
|
360
|
+
variant = store.variants.find_by_param(variant_id)
|
|
361
|
+
# +orderable_variants+ narrows what a request may add. A line already
|
|
362
|
+
# in the cart is a quantity edit and resolves as before — checkout
|
|
363
|
+
# judges it — so one stale line cannot fail a whole cart's update.
|
|
364
|
+
if variant && orderable_variants && cart.line_items.none? { |line_item| line_item.variant_id == variant.id }
|
|
365
|
+
variant = orderable_variants.find_by(id: variant.id)
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
variant || raise(ActiveRecord::RecordNotFound.new("Variant '#{variant_id}' not found in this store", 'Spree::Variant', 'id', variant_id))
|
|
360
369
|
end
|
|
361
370
|
end
|
|
362
371
|
|
|
@@ -1,38 +1,21 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
module Claims
|
|
3
3
|
class Approve < Spree::Workflow
|
|
4
|
+
include Spree::PostSale::Approval
|
|
5
|
+
|
|
4
6
|
hooks :validate, :after_approve
|
|
5
7
|
|
|
6
8
|
# @param claim [Spree::Claim]
|
|
7
9
|
# @param approver [Object, nil]
|
|
8
10
|
def perform(claim:, approver: nil)
|
|
9
11
|
super
|
|
10
|
-
|
|
11
|
-
step :ensure_approvable
|
|
12
|
-
run_hooks :validate
|
|
13
|
-
|
|
14
|
-
ApplicationRecord.transaction do
|
|
15
|
-
step :mark_approved
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
run_hooks :after_approve
|
|
19
|
-
claim.publish_event('claim.approved')
|
|
20
|
-
success(claim.reload)
|
|
12
|
+
approve
|
|
21
13
|
end
|
|
22
14
|
|
|
23
15
|
private
|
|
24
16
|
|
|
25
|
-
def
|
|
26
|
-
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def mark_approved
|
|
30
|
-
claim.update!(
|
|
31
|
-
status: 'approved',
|
|
32
|
-
approved_at: Time.current,
|
|
33
|
-
created_by: claim.created_by || approver
|
|
34
|
-
)
|
|
35
|
-
end
|
|
17
|
+
def post_sale_record = claim
|
|
18
|
+
def approvable_status = 'open'
|
|
36
19
|
end
|
|
37
20
|
end
|
|
38
21
|
end
|
|
@@ -1,37 +1,21 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
module Claims
|
|
3
3
|
class Cancel < Spree::Workflow
|
|
4
|
+
include Spree::PostSale::Cancellation
|
|
5
|
+
|
|
4
6
|
hooks :validate, :after_cancel
|
|
5
7
|
|
|
6
8
|
# @param claim [Spree::Claim]
|
|
7
9
|
# @param reason [String, nil]
|
|
8
10
|
def perform(claim:, reason: nil)
|
|
9
11
|
super
|
|
10
|
-
|
|
11
|
-
step :ensure_cancellable
|
|
12
|
-
run_hooks :validate
|
|
13
|
-
|
|
14
|
-
ApplicationRecord.transaction do
|
|
15
|
-
step :mark_canceled
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
run_hooks :after_cancel
|
|
19
|
-
claim.publish_event('claim.canceled')
|
|
20
|
-
success(claim.reload)
|
|
12
|
+
cancel
|
|
21
13
|
end
|
|
22
14
|
|
|
23
15
|
private
|
|
24
16
|
|
|
25
|
-
def
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
failure(claim, :not_cancellable)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def mark_canceled
|
|
32
|
-
memo = [claim.memo, reason].compact_blank.join("\n")
|
|
33
|
-
claim.update!(status: 'canceled', canceled_at: Time.current, memo: memo.presence)
|
|
34
|
-
end
|
|
17
|
+
def post_sale_record = claim
|
|
18
|
+
def cancellable_statuses = %w[open approved]
|
|
35
19
|
end
|
|
36
20
|
end
|
|
37
21
|
end
|
|
@@ -5,6 +5,8 @@ module Spree
|
|
|
5
5
|
# No goods come back — that is the point of a claim — so there is nothing
|
|
6
6
|
# to receive and nothing to restock.
|
|
7
7
|
class Create < Spree::Workflow
|
|
8
|
+
include Spree::Refunds::TaxCredit
|
|
9
|
+
|
|
8
10
|
hooks :validate, :after_create
|
|
9
11
|
|
|
10
12
|
attr_reader :claim
|
|
@@ -24,6 +26,8 @@ module Spree
|
|
|
24
26
|
|
|
25
27
|
ApplicationRecord.transaction do
|
|
26
28
|
step :build_claim
|
|
29
|
+
step :calculate_tax
|
|
30
|
+
step :ensure_refunds_within_paid
|
|
27
31
|
end
|
|
28
32
|
|
|
29
33
|
run_hooks :after_create
|
|
@@ -107,6 +111,17 @@ module Spree
|
|
|
107
111
|
|
|
108
112
|
failure(@claim) unless @claim.save
|
|
109
113
|
end
|
|
114
|
+
|
|
115
|
+
def calculate_tax
|
|
116
|
+
with_tax_provider(claim) { claim.calculate_tax! }
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Checked once the tax is known, because a line's refund is entered tax
|
|
120
|
+
# included and what it may not exceed includes the tax charged on it.
|
|
121
|
+
def ensure_refunds_within_paid
|
|
122
|
+
over = claim.claim_line_items.any? { |line| line.refund_amount.to_d > line.paid_amount }
|
|
123
|
+
failure(claim, :refund_exceeds_paid) if over
|
|
124
|
+
end
|
|
110
125
|
end
|
|
111
126
|
end
|
|
112
127
|
end
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
module Claims
|
|
3
3
|
class Deny < Spree::Workflow
|
|
4
|
+
include Spree::Refunds::TaxCredit
|
|
5
|
+
|
|
4
6
|
hooks :validate, :after_deny
|
|
5
7
|
|
|
6
8
|
# @param claim [Spree::Claim]
|
|
@@ -13,6 +15,7 @@ module Spree
|
|
|
13
15
|
|
|
14
16
|
ApplicationRecord.transaction do
|
|
15
17
|
step :mark_denied
|
|
18
|
+
step :clear_tax
|
|
16
19
|
end
|
|
17
20
|
|
|
18
21
|
run_hooks :after_deny
|
|
@@ -30,6 +33,10 @@ module Spree
|
|
|
30
33
|
memo = [claim.memo, reason].compact_blank.join("\n")
|
|
31
34
|
claim.update!(status: 'denied', denied_at: Time.current, memo: memo.presence)
|
|
32
35
|
end
|
|
36
|
+
|
|
37
|
+
def clear_tax
|
|
38
|
+
clear_tax_credit(claim)
|
|
39
|
+
end
|
|
33
40
|
end
|
|
34
41
|
end
|
|
35
42
|
end
|