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
|
@@ -31,7 +31,7 @@ FactoryBot.define do
|
|
|
31
31
|
country = Spree::Country.by_iso('US')
|
|
32
32
|
|
|
33
33
|
if Spree::DeliveryMethod.none?
|
|
34
|
-
create(:
|
|
34
|
+
create(:delivery_method).tap do |delivery_method|
|
|
35
35
|
delivery_method.calculator.preferred_amount = evaluator.shipping_cost
|
|
36
36
|
delivery_method.calculator.preferred_currency = cart.store.default_currency
|
|
37
37
|
delivery_method.calculator.save!
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
FactoryBot.define do
|
|
2
|
+
factory :email_template, class: Spree::EmailTemplate do
|
|
3
|
+
store { Spree::Store.default || create(:store) }
|
|
4
|
+
key { 'spree/admin_user_mailer/password_reset_email' }
|
|
5
|
+
locale { 'any' }
|
|
6
|
+
subject { 'Reset {{ store.name }}' }
|
|
7
|
+
body { '<mj-section><mj-column><mj-text>Hello</mj-text></mj-column></mj-section>' }
|
|
8
|
+
base_subject { 'Reset {{ store.name }}' }
|
|
9
|
+
base_body { '<mj-section><mj-column><mj-text>Default</mj-text></mj-column></mj-section>' }
|
|
10
|
+
published_at { Time.current }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
factory :email_template_draft, class: Spree::EmailTemplateDraft do
|
|
14
|
+
store { Spree::Store.default || create(:store) }
|
|
15
|
+
key { 'spree/admin_user_mailer/password_reset_email' }
|
|
16
|
+
locale { 'any' }
|
|
17
|
+
subject { 'Reset {{ store.name }}' }
|
|
18
|
+
body { '<mj-section><mj-column><mj-text>Draft</mj-text></mj-column></mj-section>' }
|
|
19
|
+
base_subject { 'Reset {{ store.name }}' }
|
|
20
|
+
base_body { '<mj-section><mj-column><mj-text>Default</mj-text></mj-column></mj-section>' }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
factory :email_template_revision, class: Spree::EmailTemplateRevision do
|
|
24
|
+
email_template
|
|
25
|
+
subject { 'Reset {{ store.name }}' }
|
|
26
|
+
body { '<mj-section><mj-column><mj-text>Hello</mj-text></mj-column></mj-section>' }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -39,7 +39,7 @@ FactoryBot.define do
|
|
|
39
39
|
create(:line_item, order: order, price: evaluator.line_items_price)
|
|
40
40
|
order.line_items.reload # to ensure order.line_items is accessible after
|
|
41
41
|
|
|
42
|
-
order.update_column(:
|
|
42
|
+
order.update_column(:total_quantity, order.line_items.count)
|
|
43
43
|
order.reload
|
|
44
44
|
end
|
|
45
45
|
end
|
|
@@ -78,7 +78,7 @@ FactoryBot.define do
|
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
stock_location = order.line_items&.first&.variant&.stock_levels&.first&.stock_location || create(:stock_location)
|
|
81
|
-
create(:
|
|
81
|
+
create(:fulfillment, order: order, cost: evaluator.shipment_cost, stock_location: stock_location)
|
|
82
82
|
order.fulfillments.reload
|
|
83
83
|
|
|
84
84
|
order.recalculate_totals!
|
|
@@ -4,7 +4,7 @@ FactoryBot.define do
|
|
|
4
4
|
factory :refund, class: Spree::Refund do
|
|
5
5
|
amount { 100.00 }
|
|
6
6
|
transaction_id { generate(:refund_transaction_id) }
|
|
7
|
-
association(:payment,
|
|
7
|
+
association(:payment, status: 'completed')
|
|
8
8
|
association(:reason, factory: :refund_reason)
|
|
9
9
|
end
|
|
10
10
|
|
|
@@ -20,7 +20,7 @@ FactoryBot.define do
|
|
|
20
20
|
|
|
21
21
|
after(:build) do |package, evaluator|
|
|
22
22
|
evaluator.variants_contents.each do |variant, count|
|
|
23
|
-
package.add_multiple build_list(:
|
|
23
|
+
package.add_multiple build_list(:fulfillment_item, count, variant: variant)
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
|
|
@@ -1,94 +1,3 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
3
|
-
|
|
4
|
-
# If there is a translation referenced which has no corresponding key within the
|
|
5
|
-
# .yml file, then there will be a message output at the end of the suite showing
|
|
6
|
-
# that.
|
|
7
|
-
#
|
|
8
|
-
# If there is a translation within the locale file which *isn't* used in the
|
|
9
|
-
# test, this will also be shown at the end of the suite run.
|
|
10
|
-
module Spree
|
|
11
|
-
class << self
|
|
12
|
-
attr_accessor :used_translations, :missing_translation_messages,
|
|
13
|
-
:unused_translations, :unused_translation_messages
|
|
14
|
-
alias normal_t t
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def self.t(*args)
|
|
18
|
-
original_args = args.dup
|
|
19
|
-
options = args.extract_options!
|
|
20
|
-
self.used_translations ||= []
|
|
21
|
-
[*args.first].each do |translation_key|
|
|
22
|
-
key = ([*options[:scope]] << translation_key).join('.')
|
|
23
|
-
self.used_translations << key
|
|
24
|
-
end
|
|
25
|
-
normal_t(*original_args)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def self.check_missing_translations
|
|
29
|
-
self.missing_translation_messages = []
|
|
30
|
-
self.used_translations ||= []
|
|
31
|
-
used_translations.map { |a| a.split('.') }.each do |translation_keys|
|
|
32
|
-
root = translations
|
|
33
|
-
processed_keys = []
|
|
34
|
-
translation_keys.each do |key|
|
|
35
|
-
root = root.fetch(key.to_sym)
|
|
36
|
-
processed_keys << key.to_sym
|
|
37
|
-
rescue KeyError
|
|
38
|
-
error = "#{(processed_keys << key).join('.')} (#{I18n.locale})"
|
|
39
|
-
unless Spree.missing_translation_messages.include?(error)
|
|
40
|
-
Spree.missing_translation_messages << error
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def self.check_unused_translations
|
|
47
|
-
self.used_translations ||= []
|
|
48
|
-
self.unused_translation_messages = []
|
|
49
|
-
self.unused_translations = []
|
|
50
|
-
load_translations(translations)
|
|
51
|
-
translation_diff = unused_translations - used_translations
|
|
52
|
-
translation_diff.each do |translation|
|
|
53
|
-
Spree.unused_translation_messages << "#{translation} (#{I18n.locale})"
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
private
|
|
58
|
-
|
|
59
|
-
def self.load_translations(hash, root = [])
|
|
60
|
-
hash.each do |k, v|
|
|
61
|
-
if v.is_a?(Hash)
|
|
62
|
-
load_translations(v, root.dup << k)
|
|
63
|
-
else
|
|
64
|
-
key = (root + [k]).join('.')
|
|
65
|
-
unused_translations << key
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def self.translations
|
|
71
|
-
@translations ||= I18n.backend.send(:translations)[I18n.locale][:spree]
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
RSpec.configure do |config|
|
|
76
|
-
# Need to check here again because this is used in i18n_spec too.
|
|
77
|
-
if ENV['CHECK_TRANSLATIONS']
|
|
78
|
-
config.after :suite do
|
|
79
|
-
Spree.check_missing_translations
|
|
80
|
-
if Spree.missing_translation_messages.any?
|
|
81
|
-
puts "\nThere are missing translations within Spree:"
|
|
82
|
-
puts Spree.missing_translation_messages.sort
|
|
83
|
-
exit(1)
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
Spree.check_unused_translations
|
|
87
|
-
if Spree.unused_translation_messages.any?
|
|
88
|
-
puts "\nThere are unused translations within Spree:"
|
|
89
|
-
puts Spree.unused_translation_messages.sort
|
|
90
|
-
exit(1)
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
end
|
|
1
|
+
# Deprecated: Spree's specs now catch missing keys through Rails'
|
|
2
|
+
# config.i18n.raise_on_missing_translations. Removed in Spree 6.1.
|
|
3
|
+
Spree::Deprecation.warn("spree/testing_support/i18n is deprecated and does nothing; set config.i18n.raise_on_missing_translations = true in your test environment instead. It will be removed in Spree 6.1.") if defined?(Spree::Deprecation)
|
|
@@ -21,7 +21,7 @@ shared_examples_for 'lifecycle events' do |factory: nil, event_prefix: nil|
|
|
|
21
21
|
expect(record).to receive(:publish_event).with("#{lifecycle_event_prefix}.updated")
|
|
22
22
|
allow(record).to receive(:publish_event).with(anything)
|
|
23
23
|
|
|
24
|
-
# update_attribute, not update!: Spree::
|
|
24
|
+
# update_attribute, not update!: Spree::Fulfillment#update! shadows the
|
|
25
25
|
# Active Record method with the legacy state-recalculation API.
|
|
26
26
|
Timecop.travel(1.minute.from_now) do
|
|
27
27
|
record.update_attribute(:updated_at, Time.current)
|
|
@@ -21,7 +21,7 @@ class OrderWalkthrough
|
|
|
21
21
|
|
|
22
22
|
# A delivery method must exist for rates to be displayed on checkout page
|
|
23
23
|
unless Spree::DeliveryMethod.exists?
|
|
24
|
-
FactoryBot.create(:
|
|
24
|
+
FactoryBot.create(:delivery_method).tap do |delivery_method|
|
|
25
25
|
delivery_method.calculator.preferred_amount = 10
|
|
26
26
|
delivery_method.calculator.preferred_currency = store.default_currency
|
|
27
27
|
delivery_method.calculator.save
|
|
@@ -18,11 +18,6 @@ module Spree
|
|
|
18
18
|
yield(config) if block_given?
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
def assert_preference_unset(preference)
|
|
22
|
-
find("#preferences_#{preference}")['checked'].should be false
|
|
23
|
-
Spree::Config[preference].should be false
|
|
24
|
-
end
|
|
25
|
-
|
|
26
21
|
# Stubs store-scoped commerce settings for the duration of one example.
|
|
27
22
|
#
|
|
28
23
|
# stub_store_preferences(track_inventory_levels: false)
|
|
@@ -29,6 +29,15 @@ RSpec.configure do |config|
|
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
# Reloaded before each example rather than after: the after hooks run
|
|
33
|
+
# inside the example's transaction, so a reload there still sees the
|
|
34
|
+
# example's writes, and the next example would start from values the
|
|
35
|
+
# database no longer holds. Setting a preference to such a stale value is
|
|
36
|
+
# no change to Rails, so it would never be saved.
|
|
37
|
+
config.before(:each) do
|
|
38
|
+
@default_store&.reload unless self.class.metadata[:without_global_store]
|
|
39
|
+
end
|
|
40
|
+
|
|
32
41
|
config.after(:each) do
|
|
33
42
|
unless self.class.metadata[:without_global_store]
|
|
34
43
|
@default_store&.products = []
|
|
@@ -43,7 +52,6 @@ RSpec.configure do |config|
|
|
|
43
52
|
@default_store.association(:default_market).reset if @default_store.association_cached?(:default_market)
|
|
44
53
|
@default_store.association(:markets).reset if @default_store.association_cached?(:markets)
|
|
45
54
|
@default_store.remove_instance_variable(:@has_markets) if @default_store.instance_variable_defined?(:@has_markets)
|
|
46
|
-
@default_store.reload
|
|
47
55
|
end
|
|
48
56
|
end
|
|
49
57
|
end
|
|
@@ -35,6 +35,22 @@ steps:
|
|
|
35
35
|
|
|
36
36
|
Idempotent, and a no-op on an already-consolidated schema.
|
|
37
37
|
|
|
38
|
+
- id: preferences_json
|
|
39
|
+
name: "Check for preferences still stored as YAML"
|
|
40
|
+
task: "spree:upgrade:preferences_json"
|
|
41
|
+
notes: |
|
|
42
|
+
Spree 6.0 stores preferences as JSON instead of YAML, and keeps secrets
|
|
43
|
+
(preferences declared as passwords, such as gateway API keys) in a
|
|
44
|
+
separate secret_preferences column. The migration converts every row and
|
|
45
|
+
moves every secret itself, so a normal db:migrate needs nothing from this
|
|
46
|
+
step.
|
|
47
|
+
|
|
48
|
+
This is a safety net: it converts any row still holding YAML, and moves
|
|
49
|
+
the secrets of a class that was not loaded when the migration ran, such
|
|
50
|
+
as one from an extension gem installed afterwards.
|
|
51
|
+
|
|
52
|
+
Idempotent, and a no-op once everything is converted.
|
|
53
|
+
|
|
38
54
|
- id: migrate_media_class_names
|
|
39
55
|
name: "Rewrite stored Spree::Asset and Spree::Image class names"
|
|
40
56
|
task: "spree:migrate_media_class_names"
|
|
@@ -288,6 +304,20 @@ steps:
|
|
|
288
304
|
with one statement scoped to the rows still missing a code, so an
|
|
289
305
|
interrupted run picks up where it stopped.
|
|
290
306
|
|
|
307
|
+
- id: migrate_checkout_zones
|
|
308
|
+
name: "Convert checkout zones to markets"
|
|
309
|
+
task: "spree:markets:migrate_checkout_zones"
|
|
310
|
+
notes: |
|
|
311
|
+
Markets replace the store's checkout zone in Spree 6. Stores that have
|
|
312
|
+
no market yet get a default one covering their checkout zone's
|
|
313
|
+
countries, or their default country when no zone was set, and the
|
|
314
|
+
checkout zone is cleared.
|
|
315
|
+
|
|
316
|
+
Run before migrate_tax_zones, which matches zone price rules against a
|
|
317
|
+
store's markets, and before backfill_order_markets, which assigns each
|
|
318
|
+
store's default market to its orders. Idempotent: stores that already
|
|
319
|
+
have a market are skipped.
|
|
320
|
+
|
|
291
321
|
- id: migrate_promotion_option_value_rules
|
|
292
322
|
name: "Rewrite Option Value promotion rules to stable option value ids"
|
|
293
323
|
task: "spree:upgrade:migrate_promotion_option_value_rules"
|
|
@@ -715,3 +745,18 @@ steps:
|
|
|
715
745
|
predates the upgrade.
|
|
716
746
|
|
|
717
747
|
Idempotent, and safe to re-run at any time to repair drift.
|
|
748
|
+
|
|
749
|
+
- id: encrypt_secret_preferences
|
|
750
|
+
name: "Encrypt gateway and integration secrets"
|
|
751
|
+
task: "spree:upgrade:encrypt_secret_preferences"
|
|
752
|
+
notes: |
|
|
753
|
+
The 6.0 migration moves existing secrets into the secret_preferences
|
|
754
|
+
column in plain text, so it never needs encryption keys. They stay
|
|
755
|
+
readable and are encrypted the next time their record is saved. This step
|
|
756
|
+
encrypts them all now.
|
|
757
|
+
|
|
758
|
+
Skips with a note when Active Record encryption keys are not configured;
|
|
759
|
+
see the encryption section of the upgrade guide to add them, then run
|
|
760
|
+
this step again.
|
|
761
|
+
|
|
762
|
+
Idempotent.
|
|
@@ -80,7 +80,7 @@ namespace :spree do
|
|
|
80
80
|
# otherwise purge/destroy: ActionText description, images, custom fields, slugs.
|
|
81
81
|
move_polymorphic.call(ActionText::RichText, :record_type, :record_id, category, collection)
|
|
82
82
|
move_polymorphic.call(ActiveStorage::Attachment, :record_type, :record_id, category, collection, name: %w[image square_image])
|
|
83
|
-
move_polymorphic.call(Spree::
|
|
83
|
+
move_polymorphic.call(Spree::CustomField, :resource_type, :resource_id, category, collection)
|
|
84
84
|
move_polymorphic.call(FriendlyId::Slug, :sluggable_type, :sluggable_id, category, collection)
|
|
85
85
|
|
|
86
86
|
# Rules -> collection_rules (remap the STI type; insert_all bypasses the
|
|
@@ -169,8 +169,8 @@ namespace :spree do
|
|
|
169
169
|
# category rows that still hold the pre-6.0 names.
|
|
170
170
|
puts 'Backfilling renamed class-name strings...'
|
|
171
171
|
[
|
|
172
|
-
[Spree::
|
|
173
|
-
[Spree::
|
|
172
|
+
[Spree::CustomField, :resource_type, 'Spree::Taxon', 'Spree::Category'],
|
|
173
|
+
[Spree::CustomFieldDefinition, :resource_type, 'Spree::Taxon', 'Spree::Category'],
|
|
174
174
|
[ActiveStorage::Attachment, :record_type, 'Spree::Taxon', 'Spree::Category'],
|
|
175
175
|
# description is an ActionText field (translates :description, backend: :action_text);
|
|
176
176
|
# surviving categories keep their rich-text description without this.
|
data/lib/tasks/core.rake
CHANGED
|
@@ -26,14 +26,16 @@ namespace :core do
|
|
|
26
26
|
|
|
27
27
|
desc 'Migrate newsletter subscribers'
|
|
28
28
|
task migrate_newsletter_subscribers: :environment do |_t, _args|
|
|
29
|
-
Spree.
|
|
30
|
-
|
|
29
|
+
store_id = Spree::Store.default&.id
|
|
30
|
+
|
|
31
|
+
Spree.customer_class.where(accepts_email_marketing: true).in_batches(of: 500) do |customer_batch|
|
|
32
|
+
subscriber_attributes = customer_batch.pluck(:id, :email, :updated_at).map do |id, email, updated_at|
|
|
31
33
|
{
|
|
32
34
|
email: Spree::NewsletterSubscriber.new(email: email).email, # normalized email
|
|
33
|
-
|
|
35
|
+
customer_id: id,
|
|
34
36
|
verified_at: updated_at,
|
|
35
37
|
verification_token: nil,
|
|
36
|
-
store_id:
|
|
38
|
+
store_id: store_id,
|
|
37
39
|
updated_at: DateTime.current,
|
|
38
40
|
created_at: DateTime.current
|
|
39
41
|
}
|
data/lib/tasks/media.rake
CHANGED
|
@@ -31,9 +31,9 @@ namespace :spree do
|
|
|
31
31
|
# Subquery (not pluck) so the product set doesn't materialize in Ruby —
|
|
32
32
|
# important for catalogs with millions of products.
|
|
33
33
|
variant_product_ids = Spree::Variant
|
|
34
|
-
.joins("INNER JOIN #{Spree::
|
|
35
|
-
"#{Spree::
|
|
36
|
-
"AND #{Spree::
|
|
34
|
+
.joins("INNER JOIN #{Spree::Media.table_name} ON " \
|
|
35
|
+
"#{Spree::Media.table_name}.viewable_id = #{Spree::Variant.table_name}.id " \
|
|
36
|
+
"AND #{Spree::Media.table_name}.viewable_type = 'Spree::Variant'")
|
|
37
37
|
.select(:product_id)
|
|
38
38
|
|
|
39
39
|
relation = Spree::Product.where(id: variant_product_ids)
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# 5.6 → 6.0 follow-ups to the ConvertPreferencesToJson migration
|
|
4
|
+
# (docs/plans/6.0-json-preferences.md). Both are idempotent.
|
|
5
|
+
module Spree
|
|
6
|
+
module SecretPreferencesUpgrade
|
|
7
|
+
# The models keeping secrets in `secret_preferences`, one per table.
|
|
8
|
+
def self.models
|
|
9
|
+
Rails.application.eager_load!
|
|
10
|
+
Spree::Base.descendants.select do |model|
|
|
11
|
+
model.include?(Spree::SecretPreferences) && model.base_class == model && model.table_exists?
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Every row of the model, deleted ones included, except rows whose class
|
|
16
|
+
# is no longer installed — loading one of those raises, which would stop
|
|
17
|
+
# the task before it reached the rest. They are reported and left as
|
|
18
|
+
# they are; their secrets stay readable.
|
|
19
|
+
#
|
|
20
|
+
# @return [ActiveRecord::Relation]
|
|
21
|
+
def self.loadable_rows(model)
|
|
22
|
+
rows = model.unscoped
|
|
23
|
+
return rows unless model.column_names.include?(model.inheritance_column)
|
|
24
|
+
|
|
25
|
+
types = rows.distinct.pluck(model.inheritance_column)
|
|
26
|
+
missing = types.compact.reject(&:safe_constantize)
|
|
27
|
+
return rows if missing.empty?
|
|
28
|
+
|
|
29
|
+
missing.each { |type| puts " #{model.table_name}: skipped rows of #{type}, which is not installed" }
|
|
30
|
+
rows.where.not(model.inheritance_column => missing).or(rows.where(model.inheritance_column => nil))
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
namespace :spree do
|
|
36
|
+
namespace :upgrade do
|
|
37
|
+
desc <<~DESC
|
|
38
|
+
Converts any preferences row still holding YAML to JSON, and moves secrets
|
|
39
|
+
left in `preferences` to the encrypted `secret_preferences` column.
|
|
40
|
+
|
|
41
|
+
The 6.0 migration does both itself, so a normal `db:migrate` leaves nothing
|
|
42
|
+
for this task. It exists for schemas changed out of band, and for secrets of
|
|
43
|
+
a class that was not loaded when the migration ran (an extension gem added
|
|
44
|
+
afterwards).
|
|
45
|
+
DESC
|
|
46
|
+
task preferences_json: :environment do
|
|
47
|
+
conversion = Spree::Preferences::JsonConversion.new(ActiveRecord::Base.connection, log: ->(message) { puts " #{message}" })
|
|
48
|
+
|
|
49
|
+
conversion.preference_tables.each do |table|
|
|
50
|
+
converted = conversion.text_column?(table) ? conversion.convert_text_table(table) : conversion.convert_table(table)
|
|
51
|
+
puts " #{table}: #{converted} rows converted from YAML" if converted.positive?
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
Spree::SecretPreferencesUpgrade.models.each do |model|
|
|
55
|
+
moved = 0
|
|
56
|
+
|
|
57
|
+
Spree::SecretPreferencesUpgrade.loadable_rows(model).find_each do |record|
|
|
58
|
+
separated = record.separated_secret_preferences
|
|
59
|
+
next unless separated
|
|
60
|
+
|
|
61
|
+
# Written without callbacks: moving a secret is not a change to it, and
|
|
62
|
+
# must not look like one to a gateway that re-registers on key changes.
|
|
63
|
+
record.update_columns(separated)
|
|
64
|
+
moved += 1
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
puts " #{model.table_name}: moved secrets out of preferences for #{moved} rows" if moved.positive?
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
puts 'preferences_json done.'
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
desc <<~DESC
|
|
74
|
+
Encrypts every `secret_preferences` value still stored in plain text.
|
|
75
|
+
|
|
76
|
+
The 6.0 migration moves existing secrets into `secret_preferences` without
|
|
77
|
+
encrypting them, so it never depends on encryption keys. They stay readable
|
|
78
|
+
as they are and are encrypted on their next save; this task encrypts them
|
|
79
|
+
all at once. Skips with a note when Active Record encryption keys are not
|
|
80
|
+
configured.
|
|
81
|
+
DESC
|
|
82
|
+
task encrypt_secret_preferences: :environment do
|
|
83
|
+
unless ActiveRecord::Encryption.config.has_primary_key?
|
|
84
|
+
puts ' Active Record encryption keys are not configured, so secrets stay in plain text. ' \
|
|
85
|
+
'See https://spreecommerce.org/docs/developer/deployment/environment_variables'
|
|
86
|
+
next
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
Spree::SecretPreferencesUpgrade.models.each do |model|
|
|
90
|
+
count = 0
|
|
91
|
+
Spree::SecretPreferencesUpgrade.loadable_rows(model).where.not(secret_preferences: nil).find_each do |record|
|
|
92
|
+
record.encrypt
|
|
93
|
+
count += 1
|
|
94
|
+
end
|
|
95
|
+
puts " #{model.table_name}: encrypted secrets for #{count} rows"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
puts 'encrypt_secret_preferences done.'
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|