spree_core 6.0.0.beta4 → 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
|
@@ -3,7 +3,11 @@ module Spree
|
|
|
3
3
|
#
|
|
4
4
|
# Named for {Spree::LineItem}, which it mirrors: `quantity` is what the
|
|
5
5
|
# customer said was coming, `received_quantity` what the warehouse counted.
|
|
6
|
+
# Like a line item it carries its worth before tax in `pre_tax_amount` and
|
|
7
|
+
# the tax on it beside that, both for the announced quantity.
|
|
6
8
|
class ReturnLineItem < Spree.base_class
|
|
9
|
+
include Spree::PostSale::TaxedLine
|
|
10
|
+
|
|
7
11
|
has_prefix_id :rli
|
|
8
12
|
|
|
9
13
|
belongs_to :return, class_name: 'Spree::Return', inverse_of: :return_line_items
|
|
@@ -19,31 +23,80 @@ module Spree
|
|
|
19
23
|
|
|
20
24
|
delegate :order, :currency, to: :return
|
|
21
25
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
extend Spree::DisplayMoney
|
|
27
|
+
money_methods :pre_tax_amount, :included_tax_total, :additional_tax_total, :tax_total,
|
|
28
|
+
:refund_amount, :refund_tax_amount
|
|
29
|
+
|
|
30
|
+
# What this line refunds, tax included. Once the warehouse has counted,
|
|
31
|
+
# only the units that arrived are paid for — a customer who announced
|
|
32
|
+
# three and sent two is owed two — and before the count there is nothing
|
|
33
|
+
# to go on but the announced quantity.
|
|
26
34
|
#
|
|
27
35
|
# Rounded to the currency, because this is the ceiling a refund is checked
|
|
28
36
|
# against as well as the figure the dialog offers: a third of $29.99 taken
|
|
29
37
|
# three times is not $29.99 until it is.
|
|
30
38
|
#
|
|
39
|
+
# A line opened before returns carried tax holds the price it was opened
|
|
40
|
+
# with in `pre_tax_amount` and no tax, so it refunds exactly what it did.
|
|
41
|
+
#
|
|
31
42
|
# @return [BigDecimal]
|
|
32
43
|
def refund_amount
|
|
33
|
-
|
|
34
|
-
|
|
44
|
+
counted_share(total)
|
|
45
|
+
end
|
|
35
46
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
)
|
|
47
|
+
# @return [BigDecimal] the tax inside {#refund_amount}
|
|
48
|
+
def refund_tax_amount
|
|
49
|
+
counted_share(tax_total)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @return [BigDecimal] the announced units, tax included
|
|
53
|
+
def total
|
|
54
|
+
pre_tax_amount + tax_total
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def tax_total
|
|
58
|
+
included_tax_total + additional_tax_total
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# The units this line gives back: none once the return is canceled, what
|
|
62
|
+
# arrived once the warehouse has counted, what was announced before.
|
|
63
|
+
#
|
|
64
|
+
# @return [Integer]
|
|
65
|
+
def credited_quantity
|
|
66
|
+
return 0 if self.return.canceled?
|
|
67
|
+
|
|
68
|
+
self.return.counted? ? received_quantity.to_i : quantity.to_i
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# @return [BigDecimal] what the credited units are worth, tax included
|
|
72
|
+
def credited_worth
|
|
73
|
+
refund_amount
|
|
39
74
|
end
|
|
40
75
|
|
|
41
|
-
|
|
42
|
-
|
|
76
|
+
# Copies the credit rows written at opening onto the line. The before-tax
|
|
77
|
+
# figure is what was paid after discounts less the tax inside it, so the
|
|
78
|
+
# three columns add up to the cent.
|
|
79
|
+
#
|
|
80
|
+
# @return [void]
|
|
81
|
+
def fold_tax_lines!
|
|
82
|
+
included, additional = tax_totals_from(tax_lines.credits.reload)
|
|
83
|
+
|
|
84
|
+
update_columns(
|
|
85
|
+
pre_tax_amount: default_pre_tax_amount - included,
|
|
86
|
+
included_tax_total: included,
|
|
87
|
+
additional_tax_total: additional
|
|
88
|
+
)
|
|
43
89
|
end
|
|
44
90
|
|
|
45
91
|
private
|
|
46
92
|
|
|
93
|
+
def counted_share(value)
|
|
94
|
+
return value unless self.return.counted?
|
|
95
|
+
return 0.to_d if quantity.to_i.zero?
|
|
96
|
+
|
|
97
|
+
Spree::Money::Rounding.to_currency((value / quantity) * received_quantity.to_i, currency)
|
|
98
|
+
end
|
|
99
|
+
|
|
47
100
|
# The refundable amount defaults to this item's share of what the
|
|
48
101
|
# customer actually paid for the line, after discounts — refunding the
|
|
49
102
|
# list price would give back more than was taken.
|
|
@@ -53,9 +106,7 @@ module Spree
|
|
|
53
106
|
end
|
|
54
107
|
|
|
55
108
|
def default_pre_tax_amount
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
(line_item.amount / line_item.quantity) * quantity.to_i
|
|
109
|
+
line_item&.discounted_amount_for(quantity) || 0
|
|
59
110
|
end
|
|
60
111
|
end
|
|
61
112
|
end
|
data/app/models/spree/role.rb
CHANGED
|
@@ -150,7 +150,7 @@ module Spree
|
|
|
150
150
|
|
|
151
151
|
def permissions_must_be_known
|
|
152
152
|
unknown = permissions - Spree.permissions.catalog_keys
|
|
153
|
-
errors.add(:permissions, :role_permissions_unknown, message:
|
|
153
|
+
errors.add(:permissions, :role_permissions_unknown, message: I18n.t('spree.role_permissions_unknown', keys: unknown.join(', '))) if unknown.any?
|
|
154
154
|
end
|
|
155
155
|
|
|
156
156
|
# Every role is bounded by the catalog: only resources registered as
|
|
@@ -164,26 +164,26 @@ module Spree
|
|
|
164
164
|
return if ungrantable.none?
|
|
165
165
|
|
|
166
166
|
errors.add(
|
|
167
|
-
:permissions, :role_permissions_not_grantable_for_audience, message:
|
|
167
|
+
:permissions, :role_permissions_not_grantable_for_audience, message: I18n.t('spree.role_permissions_not_grantable_for_audience', audience: audience, keys: ungrantable.join(', '))
|
|
168
168
|
)
|
|
169
169
|
end
|
|
170
170
|
|
|
171
171
|
# Re-pointing the resource would move every existing assignment to another
|
|
172
172
|
# panel — and, for a store, to another tenant.
|
|
173
173
|
def resource_immutable
|
|
174
|
-
errors.add(:resource, :role_resource_immutable, message:
|
|
174
|
+
errors.add(:resource, :role_resource_immutable, message: I18n.t('spree.role_resource_immutable'))
|
|
175
175
|
end
|
|
176
176
|
|
|
177
177
|
def name_immutable
|
|
178
|
-
errors.add(:name, :role_immutable, message:
|
|
178
|
+
errors.add(:name, :role_immutable, message: I18n.t('spree.role_immutable')) unless mutable_was_and_not_admin?
|
|
179
179
|
end
|
|
180
180
|
|
|
181
181
|
def permissions_immutable
|
|
182
|
-
errors.add(:permissions, :role_immutable, message:
|
|
182
|
+
errors.add(:permissions, :role_immutable, message: I18n.t('spree.role_immutable')) unless mutable_was_and_not_admin?
|
|
183
183
|
end
|
|
184
184
|
|
|
185
185
|
def description_immutable
|
|
186
|
-
errors.add(:description, :role_immutable, message:
|
|
186
|
+
errors.add(:description, :role_immutable, message: I18n.t('spree.role_immutable')) unless mutable_was_and_not_admin?
|
|
187
187
|
end
|
|
188
188
|
|
|
189
189
|
# Guards compare against the persisted `mutable` so flipping it in the same
|
|
@@ -197,7 +197,7 @@ module Spree
|
|
|
197
197
|
def ensure_can_be_deleted
|
|
198
198
|
return true if can_be_deleted?
|
|
199
199
|
|
|
200
|
-
errors.add(:base, :role_cannot_be_deleted, message:
|
|
200
|
+
errors.add(:base, :role_cannot_be_deleted, message: I18n.t('spree.role_cannot_be_deleted'))
|
|
201
201
|
throw :abort
|
|
202
202
|
end
|
|
203
203
|
end
|
|
@@ -25,7 +25,7 @@ module Spree
|
|
|
25
25
|
self.whitelisted_ransackable_attributes = %w[name seeded created_at updated_at]
|
|
26
26
|
|
|
27
27
|
def event_serializer_class
|
|
28
|
-
'Spree::Api::V3::
|
|
28
|
+
'Spree::Api::V3::SavedReportEventSerializer'.safe_constantize
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
# The stored query, normalized against the registry.
|
data/app/models/spree/seller.rb
CHANGED
|
@@ -25,6 +25,8 @@ module Spree
|
|
|
25
25
|
MEMOIZED_METHODS = %w[onboarding_requirements onboarding_progress products_count returns_location].freeze
|
|
26
26
|
|
|
27
27
|
publishes_lifecycle_events
|
|
28
|
+
publishes_events :approved, :invited, :onboarding_reopened, :onboarding_started, :rejected,
|
|
29
|
+
:submitted_for_review, :suspended
|
|
28
30
|
|
|
29
31
|
# Where a seller is in its life on the marketplace. Transitions belong to
|
|
30
32
|
# workflows (Spree::Sellers::Approve and friends) rather than a state
|
|
@@ -62,7 +64,6 @@ module Spree
|
|
|
62
64
|
#
|
|
63
65
|
# Associations
|
|
64
66
|
#
|
|
65
|
-
belongs_to :store, class_name: 'Spree::Store'
|
|
66
67
|
# The address knows it is a seller's from its owner, so it is read back
|
|
67
68
|
# with the business rules — no personal name insisted on, the company line
|
|
68
69
|
# required. Not `dependent: :destroy`: a seller is paranoid, so destroy is
|
|
@@ -16,6 +16,8 @@ module Spree
|
|
|
16
16
|
# and leaves the operator to pay by bank, while a provider like Stripe
|
|
17
17
|
# Connect performs the transfer itself.
|
|
18
18
|
class SellerPayout < Spree.base_class
|
|
19
|
+
publishes_event :completed
|
|
20
|
+
|
|
19
21
|
has_prefix_id :vpo
|
|
20
22
|
|
|
21
23
|
include Spree::Metadata
|
|
@@ -58,6 +60,11 @@ module Spree
|
|
|
58
60
|
scope :owed, -> { where(status: %w[pending processing]) }
|
|
59
61
|
|
|
60
62
|
self.whitelisted_ransackable_attributes = %w[amount currency status provider reference period_start period_end created_at seller_id]
|
|
63
|
+
# Filtered by the provider's API shorthand (`system`); the column holds
|
|
64
|
+
# its class name.
|
|
65
|
+
ransacker :provider, formatter: ->(value) { Spree::ApiTyped.class_name_for(Spree.payout_providers, value) } do |parent|
|
|
66
|
+
parent.table[:provider]
|
|
67
|
+
end
|
|
61
68
|
# No `transfers`: they lead on to the order and its buyer, which a
|
|
62
69
|
# payouts-only caller may not read.
|
|
63
70
|
self.whitelisted_ransackable_associations = %w[seller]
|
|
@@ -16,6 +16,9 @@ module Spree
|
|
|
16
16
|
include Spree::HasListPosition
|
|
17
17
|
include Spree::PreferenceSchema
|
|
18
18
|
include Spree::Metadata
|
|
19
|
+
include Spree::TypeLabels
|
|
20
|
+
|
|
21
|
+
self.type_labels_scope = 'spree.seller_requirement_types'
|
|
19
22
|
|
|
20
23
|
has_prefix_id :selreq
|
|
21
24
|
|
|
@@ -87,16 +90,6 @@ module Spree
|
|
|
87
90
|
end
|
|
88
91
|
end
|
|
89
92
|
|
|
90
|
-
# @return [String] the localized name of the kind, used by operator pickers
|
|
91
|
-
def self.human_name
|
|
92
|
-
Spree.t("seller_requirement_types.#{api_type}.name", default: api_type.titleize)
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
# @return [String] the localized description of the kind
|
|
96
|
-
def self.human_description
|
|
97
|
-
Spree.t("seller_requirement_types.#{api_type}.description", default: '')
|
|
98
|
-
end
|
|
99
|
-
|
|
100
93
|
# Whether the operator may configure this kind more than once per store.
|
|
101
94
|
# True for the kinds whose meaning comes from the operator's own copy.
|
|
102
95
|
#
|
|
@@ -266,8 +259,7 @@ module Spree
|
|
|
266
259
|
return if Spree.seller_requirements.any? { |kind| kind.to_s == type }
|
|
267
260
|
|
|
268
261
|
errors.add(
|
|
269
|
-
:type, :invalid_seller_requirement, message:
|
|
270
|
-
default: 'is not a registered seller requirement')
|
|
262
|
+
:type, :invalid_seller_requirement, message: I18n.t('spree.errors.messages.invalid_seller_requirement')
|
|
271
263
|
)
|
|
272
264
|
end
|
|
273
265
|
end
|
|
@@ -22,8 +22,7 @@ module Spree
|
|
|
22
22
|
return if custom_field_definition.resource_type == Spree::Seller.to_s
|
|
23
23
|
|
|
24
24
|
errors.add(:custom_field_definition, :invalid,
|
|
25
|
-
message:
|
|
26
|
-
default: 'must be a custom field defined for sellers'))
|
|
25
|
+
message: I18n.t('spree.seller_requirements.custom_field_not_for_sellers'))
|
|
27
26
|
end
|
|
28
27
|
|
|
29
28
|
# Both sides are store-owned, so a marketplace can only ask its sellers
|
|
@@ -16,6 +16,7 @@ module Spree
|
|
|
16
16
|
has_prefix_id :selsub
|
|
17
17
|
|
|
18
18
|
publishes_lifecycle_events
|
|
19
|
+
publishes_events :accepted, :created, :rejected, :waived
|
|
19
20
|
|
|
20
21
|
# `waived` is the operator excusing one seller from something the store
|
|
21
22
|
# asks of everyone — a requirement they have already satisfied off the
|
|
@@ -84,8 +85,7 @@ module Spree
|
|
|
84
85
|
return if seller.nil? || requirement.nil?
|
|
85
86
|
return if seller.store_id == requirement.store_id
|
|
86
87
|
|
|
87
|
-
errors.add(:requirement, :seller_requirement_store_mismatch, message:
|
|
88
|
-
default: 'must belong to the same store as the seller'))
|
|
88
|
+
errors.add(:requirement, :seller_requirement_store_mismatch, message: I18n.t('spree.errors.messages.seller_requirement_store_mismatch'))
|
|
89
89
|
end
|
|
90
90
|
end
|
|
91
91
|
end
|
|
@@ -90,14 +90,13 @@ module Spree
|
|
|
90
90
|
# On the preference rather than :base, so the operator's form marks the
|
|
91
91
|
# field they got wrong instead of only showing a summary line.
|
|
92
92
|
errors.add(:preferred_terms_effective_from, :invalid_terms_effective_from,
|
|
93
|
-
message:
|
|
94
|
-
default: 'Terms effective from is not a date'))
|
|
93
|
+
message: I18n.t('spree.seller_requirements.invalid_terms_effective_from'))
|
|
95
94
|
end
|
|
96
95
|
|
|
97
96
|
def store_terms_body
|
|
98
97
|
return if store.nil?
|
|
99
98
|
|
|
100
|
-
store.policies.with_matching_name(
|
|
99
|
+
store.policies.with_matching_name(I18n.t('spree.terms_of_service')).detect(&:with_body?)&.body
|
|
101
100
|
end
|
|
102
101
|
end
|
|
103
102
|
end
|
|
@@ -112,6 +112,11 @@ module Spree
|
|
|
112
112
|
end
|
|
113
113
|
|
|
114
114
|
self.whitelisted_ransackable_attributes = %w[amount currency kind status provider reference created_at seller_id order_id payout_id]
|
|
115
|
+
# Filtered by the provider's API shorthand (`system`); the column holds
|
|
116
|
+
# its class name.
|
|
117
|
+
ransacker :provider, formatter: ->(value) { Spree::ApiTyped.class_name_for(Spree.payout_providers, value) } do |parent|
|
|
118
|
+
parent.table[:provider]
|
|
119
|
+
end
|
|
115
120
|
# No `order`: filtering through it reaches the buyer's email and address,
|
|
116
121
|
# which a payouts-only caller may not read. `order_id` covers the lookup.
|
|
117
122
|
self.whitelisted_ransackable_associations = %w[seller payout refund]
|
|
@@ -17,11 +17,11 @@ module Spree
|
|
|
17
17
|
if variant.available? || variant.preorder?
|
|
18
18
|
line_item.errors.add(:quantity,
|
|
19
19
|
:selected_quantity_not_available,
|
|
20
|
-
message:
|
|
20
|
+
message: I18n.t('spree.selected_quantity_not_available', item: display_name.inspect))
|
|
21
21
|
else
|
|
22
22
|
line_item.errors.add(:base,
|
|
23
23
|
:only_active_products_can_be_added_to_cart,
|
|
24
|
-
message:
|
|
24
|
+
message: I18n.t('spree.only_active_products_can_be_added_to_cart'))
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
@@ -14,7 +14,7 @@ module Spree
|
|
|
14
14
|
@order.line_items.map do |line_item|
|
|
15
15
|
# They go through multiple splits, avoid loading the
|
|
16
16
|
# association to order until needed.
|
|
17
|
-
Spree::
|
|
17
|
+
Spree::FulfillmentItem.new(
|
|
18
18
|
pending: true,
|
|
19
19
|
line_item_id: line_item.id,
|
|
20
20
|
variant_id: line_item.variant_id,
|
|
@@ -35,8 +35,8 @@ module Spree
|
|
|
35
35
|
next unless stock_location.stocks? variant
|
|
36
36
|
|
|
37
37
|
on_hand, backordered = stock_location.fill_status(variant, unit.quantity)
|
|
38
|
-
package.add(
|
|
39
|
-
package.add(
|
|
38
|
+
package.add(FulfillmentItem.split(unit, backordered), :backordered) if backordered.positive?
|
|
39
|
+
package.add(FulfillmentItem.split(unit, on_hand), :on_hand) if on_hand.positive?
|
|
40
40
|
else
|
|
41
41
|
package.add unit
|
|
42
42
|
end
|
|
@@ -73,7 +73,7 @@ module Spree
|
|
|
73
73
|
per_content_max_quantity = 1 if per_content_max_quantity.zero?
|
|
74
74
|
content_items = [content_item]
|
|
75
75
|
while content_item.quantity > per_content_max_quantity
|
|
76
|
-
split_inventory =
|
|
76
|
+
split_inventory = FulfillmentItem.split(content_item.inventory_unit, per_content_max_quantity)
|
|
77
77
|
content_items << ContentItem.new(split_inventory, content_item.state)
|
|
78
78
|
end
|
|
79
79
|
content_items
|
|
@@ -17,6 +17,12 @@ module Spree
|
|
|
17
17
|
LEGACY_EVENT_PREFIX = 'stock_item'
|
|
18
18
|
LEGACY_EVENT_SUFFIXES = %w[created updated deleted].freeze
|
|
19
19
|
|
|
20
|
+
def self.included(base)
|
|
21
|
+
LEGACY_EVENT_SUFFIXES.each do |suffix|
|
|
22
|
+
base.publishes_event("#{LEGACY_EVENT_PREFIX}.#{suffix}", deprecated_alias_of: "#{base.event_prefix}.#{suffix}")
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
20
26
|
# Wraps publishing rather than the three callbacks that call it, so the
|
|
21
27
|
# decisions Publishable makes — whether events are enabled at all,
|
|
22
28
|
# whether a touch-only update is worth announcing — are made once and the
|
|
@@ -114,7 +114,7 @@ module Spree
|
|
|
114
114
|
return default_adjustment_reason if reason.blank?
|
|
115
115
|
return reason.to_s unless ADJUSTMENT_REASONS.include?(reason.to_s)
|
|
116
116
|
|
|
117
|
-
|
|
117
|
+
I18n.t("spree.stock_movement.reasons.#{reason}", locale: :en)
|
|
118
118
|
end
|
|
119
119
|
|
|
120
120
|
# A movement is an immutable audit row: once written, nothing may rewrite
|
|
@@ -29,7 +29,7 @@ module Spree
|
|
|
29
29
|
def counts_something
|
|
30
30
|
return if quantity_counted.positive?
|
|
31
31
|
|
|
32
|
-
errors.add(:base, :nothing_counted, message:
|
|
32
|
+
errors.add(:base, :nothing_counted, message: I18n.t('spree.stock_receipt.errors.nothing_counted'))
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
end
|
|
@@ -127,7 +127,7 @@ module Spree
|
|
|
127
127
|
end
|
|
128
128
|
|
|
129
129
|
def exactly_one_owner
|
|
130
|
-
errors.add(:base, :exactly_one_of_cart_or_order, message:
|
|
130
|
+
errors.add(:base, :exactly_one_of_cart_or_order, message: I18n.t('spree.errors.messages.exactly_one_of_cart_or_order')) unless [order, cart].compact.one?
|
|
131
131
|
end
|
|
132
132
|
|
|
133
133
|
# Only a quantity change moves units between counters, so re-pointing a
|
|
@@ -135,7 +135,7 @@ module Spree
|
|
|
135
135
|
# missing from the new. A hold that belongs elsewhere is released and
|
|
136
136
|
# taken again, never moved.
|
|
137
137
|
def stock_level_unchanged
|
|
138
|
-
errors.add(:stock_level_id, :immutable, message:
|
|
138
|
+
errors.add(:stock_level_id, :immutable, message: I18n.t('spree.errors.messages.stock_level_immutable')) if stock_level_id_changed?
|
|
139
139
|
end
|
|
140
140
|
end
|
|
141
141
|
end
|
|
@@ -36,6 +36,8 @@ module Spree
|
|
|
36
36
|
acts_as_paranoid
|
|
37
37
|
|
|
38
38
|
publishes_lifecycle_events
|
|
39
|
+
publishes_events :canceled, :draft, :partially_received, :over_received, :ready_to_ship,
|
|
40
|
+
:received, :shipped
|
|
39
41
|
|
|
40
42
|
has_status :draft, :ready_to_ship, :in_transit, :partially_received, :received, :over_received, :canceled,
|
|
41
43
|
default: :draft
|
|
@@ -97,7 +99,7 @@ module Spree
|
|
|
97
99
|
return if source_location_id.blank? || destination_location_id.blank?
|
|
98
100
|
return if source_location_id != destination_location_id
|
|
99
101
|
|
|
100
|
-
errors.add(:source_location, :same_location, message:
|
|
102
|
+
errors.add(:source_location, :same_location, message: I18n.t('spree.stock_transfer.errors.same_location'))
|
|
101
103
|
end
|
|
102
104
|
|
|
103
105
|
# A transfer moves a merchant's own stock between their own warehouses. Two
|
|
@@ -108,7 +110,7 @@ module Spree
|
|
|
108
110
|
return if source_location.store_id == destination_location.store_id
|
|
109
111
|
|
|
110
112
|
errors.add(:destination_location, :must_belong_to_same_store,
|
|
111
|
-
message:
|
|
113
|
+
message: I18n.t('spree.stock_transfer.errors.locations_in_different_stores'))
|
|
112
114
|
end
|
|
113
115
|
end
|
|
114
116
|
end
|
data/app/models/spree/store.rb
CHANGED
|
@@ -13,6 +13,7 @@ module Spree
|
|
|
13
13
|
include Spree::Stores::Setup
|
|
14
14
|
include Spree::Stores::Markets
|
|
15
15
|
include Spree::Stores::Channels
|
|
16
|
+
include Spree::Stores::EmailBranding
|
|
16
17
|
include Spree::StoreDataSources
|
|
17
18
|
include Spree::Security::Stores if defined?(Spree::Security::Stores)
|
|
18
19
|
include Spree::UserManagement
|
|
@@ -45,6 +46,9 @@ module Spree
|
|
|
45
46
|
preference :timezone, :string, default: Time.zone.name
|
|
46
47
|
preference :weight_unit, :string, default: 'lb'
|
|
47
48
|
preference :unit_system, :string, default: 'imperial'
|
|
49
|
+
# Anonymous identifier of this installation, kept on the default store
|
|
50
|
+
# (see Spree.install_id). Written by Spree, never by the operator.
|
|
51
|
+
preference :install_id, :string, internal: true, nullable: true
|
|
48
52
|
# email preferences
|
|
49
53
|
preference :send_consumer_transactional_emails, :boolean, default: true
|
|
50
54
|
# Sellers are a different audience from shoppers, with their own reasons to
|
|
@@ -69,7 +73,8 @@ module Spree
|
|
|
69
73
|
# Who pays this store's sellers. Blank means core's record-only provider,
|
|
70
74
|
# so a marketplace that has connected nothing still keeps a correct ledger
|
|
71
75
|
# and settles by hand.
|
|
72
|
-
preference :payout_provider, :string, default: nil
|
|
76
|
+
preference :payout_provider, :string, default: nil,
|
|
77
|
+
parse_on_set: ->(value) { Spree::ApiTyped.class_name_for(Spree.payout_providers, value) }
|
|
73
78
|
# Refused at write time rather than silently falling back at read time: an
|
|
74
79
|
# operator who mistypes a provider would otherwise get a bookkeeping-only
|
|
75
80
|
# ledger and no indication anywhere that their choice was ignored.
|
|
@@ -151,7 +156,8 @@ module Spree
|
|
|
151
156
|
preference :digital_asset_link_expire_time, :integer, default: 300
|
|
152
157
|
# Class name of the Spree::OrderRouting::Strategy::Base subclass that
|
|
153
158
|
# decides which StockLocation fulfills which items.
|
|
154
|
-
preference :order_routing_strategy, :string, default: 'Spree::OrderRouting::Strategy::Rules'
|
|
159
|
+
preference :order_routing_strategy, :string, default: 'Spree::OrderRouting::Strategy::Rules',
|
|
160
|
+
parse_on_set: ->(value) { Spree::ApiTyped.class_name_for(Spree.order_routing.strategies, value) }
|
|
155
161
|
|
|
156
162
|
# Document numbering (docs/plans/6.0-document-numbers.md). The format
|
|
157
163
|
# applies to every numbered document; prefix, suffix and starting value
|
|
@@ -300,6 +306,8 @@ module Spree
|
|
|
300
306
|
has_many :policies, class_name: 'Spree::Policy', dependent: :destroy, as: :owner
|
|
301
307
|
|
|
302
308
|
has_many :webhook_endpoints, class_name: 'Spree::WebhookEndpoint', dependent: :destroy, inverse_of: :store
|
|
309
|
+
has_many :email_templates, class_name: 'Spree::EmailTemplate', dependent: :destroy, inverse_of: :store
|
|
310
|
+
has_many :email_template_drafts, class_name: 'Spree::EmailTemplateDraft', dependent: :destroy, inverse_of: :store
|
|
303
311
|
has_many :webhook_deliveries, through: :webhook_endpoints, class_name: 'Spree::WebhookDelivery'
|
|
304
312
|
|
|
305
313
|
has_many :channels, class_name: 'Spree::Channel', dependent: :destroy
|
|
@@ -384,6 +392,7 @@ module Spree
|
|
|
384
392
|
before_validation :set_default_code, on: :create
|
|
385
393
|
before_validation :normalize_preferred_storefront_url
|
|
386
394
|
before_save :ensure_default_exists_and_is_unique
|
|
395
|
+
before_save :set_install_id
|
|
387
396
|
after_create :create_default_policies
|
|
388
397
|
after_create :create_default_delivery_profile
|
|
389
398
|
|
|
@@ -475,14 +484,12 @@ module Spree
|
|
|
475
484
|
#
|
|
476
485
|
# @return [Class]
|
|
477
486
|
def payout_provider_class
|
|
478
|
-
configured = preferred_payout_provider.presence
|
|
479
487
|
# A name no longer in the registry — a typo, or a gem since removed —
|
|
480
488
|
# would otherwise raise inside a subscriber on every fulfillment and stop
|
|
481
489
|
# the ledger recording anything. The built-in provider keeps the books
|
|
482
490
|
# until an operator fixes the setting.
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
(configured || Spree.default_payout_provider.to_s).constantize
|
|
491
|
+
Spree::ApiTyped.registered_class(Spree.payout_providers, preferred_payout_provider) ||
|
|
492
|
+
Spree.default_payout_provider.to_s.constantize
|
|
486
493
|
end
|
|
487
494
|
|
|
488
495
|
def formatted_url
|
|
@@ -543,6 +550,21 @@ module Spree
|
|
|
543
550
|
allowed_origins.any? { |allowed_origin| allowed_origin.matches?(url) }
|
|
544
551
|
end
|
|
545
552
|
|
|
553
|
+
# The logo emails show: the dedicated mailer logo, else the store logo.
|
|
554
|
+
#
|
|
555
|
+
# @return [ActiveStorage::Attached::One, nil] nil when neither is an image
|
|
556
|
+
def email_logo
|
|
557
|
+
logo = mailer_logo.attached? ? mailer_logo : self.logo
|
|
558
|
+
logo if logo.attached? && logo.variable?
|
|
559
|
+
end
|
|
560
|
+
|
|
561
|
+
# The address customers are told to write to: the support address, else the sender address.
|
|
562
|
+
#
|
|
563
|
+
# @return [String, nil]
|
|
564
|
+
def support_email_address
|
|
565
|
+
customer_support_email.presence || mail_from_address
|
|
566
|
+
end
|
|
567
|
+
|
|
546
568
|
# Returns the states available for checkout for the store
|
|
547
569
|
# @param country [Spree::Country] the country to get the states for
|
|
548
570
|
# @return [Array<Spree::State>]
|
|
@@ -613,7 +635,7 @@ module Spree
|
|
|
613
635
|
@default_stock_location ||= begin
|
|
614
636
|
stock_location_scope = stock_locations.first_party.where(default: true)
|
|
615
637
|
stock_location_scope.first || ActiveRecord::Base.connected_to(role: :writing) do
|
|
616
|
-
stock_location_scope.create(default: true, name:
|
|
638
|
+
stock_location_scope.create(default: true, name: I18n.t('spree.default_stock_location_name'),
|
|
617
639
|
country_code: default_country&.iso)
|
|
618
640
|
end
|
|
619
641
|
end
|
|
@@ -699,6 +721,10 @@ module Spree
|
|
|
699
721
|
I18n.t(key, locale: locale, default: I18n.t(key, locale: :en))
|
|
700
722
|
end
|
|
701
723
|
|
|
724
|
+
def set_install_id
|
|
725
|
+
self.preferred_install_id = SecureRandom.uuid if preferred_install_id.blank?
|
|
726
|
+
end
|
|
727
|
+
|
|
702
728
|
def ensure_default_exists_and_is_unique
|
|
703
729
|
if default
|
|
704
730
|
Spree::Store.where.not(id: id).update_all(default: false)
|
|
@@ -18,7 +18,6 @@ module Spree
|
|
|
18
18
|
AUTHORIZE_ACTION = 'authorize'.freeze
|
|
19
19
|
ALLOCATION_ACTION = 'allocation'.freeze
|
|
20
20
|
|
|
21
|
-
belongs_to :store, class_name: 'Spree::Store'
|
|
22
21
|
# A gift card applied to a guest cart issues store credit with no customer
|
|
23
22
|
# to attach it to.
|
|
24
23
|
belongs_to :customer, class_name: "::#{Spree.customer_class}", optional: true
|
|
@@ -146,16 +145,16 @@ module Spree
|
|
|
146
145
|
)
|
|
147
146
|
authorization_code
|
|
148
147
|
else
|
|
149
|
-
errors.add(:base, :insufficient_authorized_amount, message:
|
|
148
|
+
errors.add(:base, :insufficient_authorized_amount, message: I18n.t('spree.store_credit_payment_method.insufficient_authorized_amount'))
|
|
150
149
|
false
|
|
151
150
|
end
|
|
152
151
|
end
|
|
153
152
|
|
|
154
153
|
def validate_authorization(amount, order_currency)
|
|
155
154
|
if BigDecimal(amount_remaining, 3) < BigDecimal(amount, 3)
|
|
156
|
-
errors.add(:base, :insufficient_funds, message:
|
|
155
|
+
errors.add(:base, :insufficient_funds, message: I18n.t('spree.store_credit_payment_method.insufficient_funds'))
|
|
157
156
|
elsif currency != order_currency
|
|
158
|
-
errors.add(:base, :currency_mismatch, message:
|
|
157
|
+
errors.add(:base, :currency_mismatch, message: I18n.t('spree.store_credit_payment_method.currency_mismatch'))
|
|
159
158
|
end
|
|
160
159
|
errors.blank?
|
|
161
160
|
end
|
|
@@ -165,7 +164,7 @@ module Spree
|
|
|
165
164
|
|
|
166
165
|
if amount <= amount_authorized
|
|
167
166
|
if currency != order_currency
|
|
168
|
-
errors.add(:base, :currency_mismatch, message:
|
|
167
|
+
errors.add(:base, :currency_mismatch, message: I18n.t('spree.store_credit_payment_method.currency_mismatch'))
|
|
169
168
|
false
|
|
170
169
|
else
|
|
171
170
|
update!(
|
|
@@ -179,7 +178,7 @@ module Spree
|
|
|
179
178
|
authorization_code
|
|
180
179
|
end
|
|
181
180
|
else
|
|
182
|
-
errors.add(:base, :insufficient_authorized_amount, message:
|
|
181
|
+
errors.add(:base, :insufficient_authorized_amount, message: I18n.t('spree.store_credit_payment_method.insufficient_authorized_amount'))
|
|
183
182
|
false
|
|
184
183
|
end
|
|
185
184
|
end
|
|
@@ -196,7 +195,7 @@ module Spree
|
|
|
196
195
|
true
|
|
197
196
|
else
|
|
198
197
|
errors.add(:base, :unable_to_void, auth_code: authorization_code,
|
|
199
|
-
message:
|
|
198
|
+
message: I18n.t('spree.store_credit_payment_method.unable_to_void', auth_code: authorization_code))
|
|
200
199
|
false
|
|
201
200
|
end
|
|
202
201
|
end
|
|
@@ -206,7 +205,7 @@ module Spree
|
|
|
206
205
|
capture_event = store_credit_events.find_by(action: CAPTURE_ACTION, authorization_code: authorization_code)
|
|
207
206
|
|
|
208
207
|
if currency != order_currency # sanity check to make sure the order currency hasn't changed since the auth
|
|
209
|
-
errors.add(:base, :currency_mismatch, message:
|
|
208
|
+
errors.add(:base, :currency_mismatch, message: I18n.t('spree.store_credit_payment_method.currency_mismatch'))
|
|
210
209
|
false
|
|
211
210
|
elsif capture_event && amount <= capture_event.amount
|
|
212
211
|
action_attributes = {
|
|
@@ -219,7 +218,7 @@ module Spree
|
|
|
219
218
|
true
|
|
220
219
|
else
|
|
221
220
|
errors.add(:base, :unable_to_credit, auth_code: authorization_code,
|
|
222
|
-
message:
|
|
221
|
+
message: I18n.t('spree.store_credit_payment_method.unable_to_credit', auth_code: authorization_code))
|
|
223
222
|
false
|
|
224
223
|
end
|
|
225
224
|
end
|