spree_core 6.0.0.beta4 → 6.0.0.rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +5 -5
- data/app/helpers/spree/images_helper.rb +0 -57
- data/app/jobs/spree/base_job.rb +21 -0
- data/app/jobs/spree/carts/reap_expired_job.rb +2 -2
- data/app/jobs/spree/collections/regenerate_time_based_job.rb +6 -3
- data/app/jobs/spree/orders/finalize_stale_drafts_job.rb +8 -5
- data/app/jobs/spree/payments/cancel_unused_sessions_job.rb +61 -0
- data/app/jobs/spree/search_provider/index_job.rb +4 -0
- data/app/jobs/spree/seller_payouts/sweep_seller_job.rb +2 -0
- data/app/jobs/spree/uploads/purge_unattached_job.rb +49 -0
- data/app/mailers/spree/admin_user_mailer.rb +4 -19
- data/app/mailers/spree/base_mailer.rb +97 -13
- data/app/mailers/spree/email_template_mailer.rb +27 -0
- data/app/mailers/spree/export_mailer.rb +3 -4
- data/app/mailers/spree/import_mailer.rb +3 -4
- data/app/mailers/spree/invitation_mailer.rb +24 -7
- data/app/mailers/spree/seller_user_mailer.rb +4 -16
- data/app/mailers/spree/webhook_mailer.rb +2 -2
- data/app/models/concerns/spree/acted_by.rb +1 -1
- data/app/models/concerns/spree/admin_user_methods.rb +15 -1
- data/app/models/concerns/spree/api_typed.rb +91 -0
- data/app/models/concerns/spree/calculated_adjustments.rb +41 -13
- data/app/models/concerns/spree/calculator/currency_amounts.rb +1 -1
- data/app/models/concerns/spree/calculator/tiers.rb +63 -0
- data/app/models/concerns/spree/canonical_decimals.rb +61 -0
- data/app/models/concerns/spree/customer_methods.rb +23 -18
- data/app/models/concerns/spree/derived_number.rb +11 -13
- data/app/models/concerns/spree/email_template_identity.rb +52 -0
- data/app/models/concerns/spree/parameterizable_name.rb +2 -0
- data/app/models/concerns/spree/payment_session_transitions.rb +8 -2
- data/app/models/concerns/spree/post_sale/taxation.rb +54 -0
- data/app/models/concerns/spree/post_sale/taxed_line.rb +51 -0
- data/app/models/concerns/spree/preference_schema/json_schema.rb +139 -0
- data/app/models/concerns/spree/preference_schema.rb +62 -32
- data/app/models/concerns/spree/product_scopes.rb +16 -2
- data/app/models/concerns/spree/provider_listing.rb +41 -0
- data/app/models/concerns/spree/publishable.rb +82 -14
- data/app/models/concerns/spree/purchase/addresses.rb +23 -10
- data/app/models/concerns/spree/purchase/currency.rb +1 -1
- data/app/models/concerns/spree/purchase/deprecated_aliases.rb +87 -0
- data/app/models/concerns/spree/purchase/gift_cards.rb +10 -4
- data/app/models/concerns/spree/purchase/locale.rb +1 -1
- data/app/models/concerns/spree/purchase/payment_processing.rb +8 -4
- data/app/models/concerns/spree/purchase/purchase_order.rb +9 -4
- data/app/models/concerns/spree/purchase/store_credits.rb +36 -1
- data/app/models/concerns/spree/purchase/totals.rb +49 -8
- data/app/models/concerns/spree/ransackable_attributes.rb +46 -0
- data/app/models/concerns/spree/receivable.rb +1 -1
- data/app/models/concerns/spree/searchable.rb +0 -4
- data/app/models/concerns/spree/secret_preferences.rb +59 -0
- data/app/models/concerns/spree/signed_id_attachments.rb +54 -0
- data/app/models/concerns/spree/single_store_resource.rb +1 -1
- data/app/models/concerns/spree/stores/email_branding.rb +32 -0
- data/app/models/concerns/spree/stores/markets.rb +5 -2
- data/app/models/concerns/spree/type_labels.rb +38 -0
- data/app/models/concerns/spree/typed_adjustment_line.rb +5 -6
- data/app/models/concerns/spree/typed_associations.rb +12 -18
- data/app/models/concerns/spree/vat_price_calculation.rb +5 -6
- data/app/models/spree/address.rb +12 -2
- data/app/models/spree/adjusters/largest_remainder.rb +14 -1
- data/app/models/spree/adjusters/promotion.rb +4 -19
- data/app/models/spree/allowed_origin.rb +3 -1
- data/app/models/spree/api_key.rb +5 -6
- data/app/models/spree/authentication/strategies/oidc_strategy.rb +5 -5
- data/app/models/spree/base.rb +99 -22
- data/app/models/spree/calculator/flat_percent_item_total.rb +2 -4
- data/app/models/spree/calculator/flat_rate.rb +3 -5
- data/app/models/spree/calculator/flexi_rate.rb +4 -6
- data/app/models/spree/calculator/percent_on_line_item.rb +2 -2
- data/app/models/spree/calculator/price_sack.rb +5 -7
- data/app/models/spree/calculator/shipping/digital_delivery.rb +3 -5
- data/app/models/spree/calculator/shipping/flat_percent_item_total.rb +7 -7
- data/app/models/spree/calculator/shipping/flat_rate.rb +5 -7
- data/app/models/spree/calculator/shipping/flexi_rate.rb +4 -6
- data/app/models/spree/calculator/shipping/per_item.rb +3 -5
- data/app/models/spree/calculator/shipping/price_sack.rb +5 -7
- data/app/models/spree/calculator/tiered_flat_rate.rb +7 -24
- data/app/models/spree/calculator/tiered_percent.rb +7 -25
- data/app/models/spree/cart.rb +78 -18
- data/app/models/spree/catalog.rb +1 -0
- data/app/models/spree/catalog_price.rb +0 -7
- data/app/models/spree/catalog_price_tier.rb +0 -8
- data/app/models/spree/category.rb +3 -1
- data/app/models/spree/channel/gating.rb +3 -2
- data/app/models/spree/channel.rb +6 -4
- data/app/models/spree/claim.rb +22 -1
- data/app/models/spree/claim_line_item.rb +41 -6
- data/app/models/spree/collection.rb +2 -1
- data/app/models/spree/collection_rule.rb +5 -21
- data/app/models/spree/commission_line.rb +1 -1
- data/app/models/spree/commission_rate.rb +7 -4
- data/app/models/spree/commission_rate_value.rb +1 -1
- data/app/models/spree/commission_rule.rb +4 -11
- data/app/models/spree/commission_rules/category_rule.rb +2 -5
- data/app/models/spree/commission_rules/item_total_rule.rb +2 -2
- data/app/models/spree/commission_rules/product_rule.rb +1 -1
- data/app/models/spree/commission_rules/seller_rule.rb +2 -5
- data/app/models/spree/company.rb +1 -0
- data/app/models/spree/company_invitation.rb +1 -0
- data/app/models/spree/consent_record.rb +0 -1
- data/app/models/spree/credit_card.rb +1 -1
- data/app/models/spree/current.rb +23 -0
- data/app/models/spree/custom_field.rb +2 -2
- data/app/models/spree/custom_field_definition.rb +20 -35
- data/app/models/spree/custom_fields/boolean.rb +1 -1
- data/app/models/spree/custom_fields/json.rb +1 -1
- data/app/models/spree/customer_group.rb +1 -0
- data/app/models/spree/data_feed/google.rb +0 -2
- data/app/models/spree/data_request.rb +2 -1
- data/app/models/spree/delivery_method.rb +36 -14
- data/app/models/spree/delivery_method_rule.rb +4 -11
- data/app/models/spree/delivery_method_rules/channel_rule.rb +2 -5
- data/app/models/spree/delivery_method_rules/item_total_rule.rb +2 -2
- data/app/models/spree/delivery_profile.rb +1 -0
- data/app/models/spree/delivery_rate.rb +7 -8
- data/app/models/spree/delivery_rate_provider/base.rb +1 -0
- data/app/models/spree/delivery_zone.rb +1 -2
- data/app/models/spree/delivery_zone_member.rb +4 -4
- data/app/models/spree/digital_asset.rb +7 -0
- data/app/models/spree/digital_asset_provider/base.rb +2 -0
- data/app/models/spree/digital_link.rb +2 -5
- data/app/models/spree/discount.rb +1 -1
- data/app/models/spree/email_template.rb +25 -0
- data/app/models/spree/email_template_draft.rb +13 -0
- data/app/models/spree/email_template_revision.rb +17 -0
- data/app/models/spree/email_templates/entry.rb +118 -0
- data/app/models/spree/email_templates/sample_record.rb +16 -0
- data/app/models/spree/emails/branding.rb +80 -0
- data/app/models/spree/exchange.rb +16 -1
- data/app/models/spree/exchange_line_item.rb +121 -5
- data/app/models/spree/export.rb +0 -1
- data/app/models/spree/exports/products.rb +10 -1
- data/app/models/spree/exports/report.rb +3 -3
- data/app/models/spree/fee.rb +4 -2
- data/app/models/spree/file_upload.rb +155 -0
- data/app/models/spree/fulfillment.rb +66 -30
- data/app/models/spree/fulfillment_changer.rb +2 -2
- data/app/models/spree/fulfillment_group.rb +6 -1
- data/app/models/spree/fulfillment_item.rb +0 -4
- data/app/models/spree/fulfillment_provider/base.rb +1 -0
- data/app/models/spree/gateway/bogus.rb +6 -0
- data/app/models/spree/gateway/custom_payment_source_method.rb +5 -0
- data/app/models/spree/gateway.rb +6 -2
- data/app/models/spree/gift_card.rb +18 -8
- data/app/models/spree/gift_card_batch.rb +3 -5
- data/app/models/spree/import.rb +5 -7
- data/app/models/spree/import_mapping.rb +1 -2
- data/app/models/spree/import_row.rb +2 -2
- data/app/models/spree/import_schemas/products.rb +1 -0
- data/app/models/spree/integration.rb +9 -19
- data/app/models/spree/invitation.rb +5 -5
- data/app/models/spree/line_item.rb +15 -4
- data/app/models/spree/locale.rb +11 -8
- data/app/models/spree/market.rb +8 -2
- data/app/models/spree/media.rb +1 -9
- data/app/models/spree/newsletter_subscriber.rb +4 -0
- data/app/models/spree/option_type.rb +2 -1
- data/app/models/spree/option_value.rb +2 -1
- data/app/models/spree/order.rb +60 -142
- data/app/models/spree/order_group.rb +18 -4
- data/app/models/spree/order_inventory.rb +10 -5
- data/app/models/spree/order_promotion.rb +1 -1
- data/app/models/spree/order_routing/has_strategy_preference.rb +1 -1
- data/app/models/spree/order_routing/strategy/base.rb +4 -2
- data/app/models/spree/order_routing/strategy/rules.rb +1 -1
- data/app/models/spree/order_routing_rule.rb +6 -22
- data/app/models/spree/package_type.rb +2 -2
- data/app/models/spree/payment/gateway_options.rb +15 -53
- data/app/models/spree/payment/processing.rb +2 -4
- data/app/models/spree/payment.rb +21 -13
- data/app/models/spree/payment_method/check.rb +2 -0
- data/app/models/spree/payment_method/session_instrumentation.rb +1 -0
- data/app/models/spree/payment_method/store_credit.rb +15 -13
- data/app/models/spree/payment_method.rb +78 -6
- data/app/models/spree/payment_session.rb +5 -1
- data/app/models/spree/payment_setup_session.rb +1 -0
- data/app/models/spree/payout_provider/base.rb +3 -1
- data/app/models/spree/pickup_point_provider/base.rb +2 -0
- data/app/models/spree/policy.rb +1 -0
- data/app/models/spree/price.rb +17 -14
- data/app/models/spree/price_adjustment_tier.rb +4 -0
- data/app/models/spree/price_list.rb +14 -9
- data/app/models/spree/price_rules/channel_rule.rb +3 -6
- data/app/models/spree/price_rules/customer_group_rule.rb +3 -6
- data/app/models/spree/price_rules/market_rule.rb +2 -5
- data/app/models/spree/price_rules/user_rule.rb +1 -3
- data/app/models/spree/product/channels.rb +9 -2
- data/app/models/spree/product.rb +54 -30
- data/app/models/spree/product_submission.rb +0 -12
- data/app/models/spree/product_type.rb +1 -1
- data/app/models/spree/promotion/actions/create_line_items.rb +28 -18
- data/app/models/spree/promotion/rules/category.rb +1 -5
- data/app/models/spree/promotion/rules/channel.rb +2 -9
- data/app/models/spree/promotion/rules/country.rb +3 -8
- data/app/models/spree/promotion/rules/currency.rb +1 -5
- data/app/models/spree/promotion/rules/customer_group.rb +2 -9
- data/app/models/spree/promotion/rules/first_order.rb +0 -4
- data/app/models/spree/promotion/rules/item_total.rb +6 -10
- data/app/models/spree/promotion/rules/market.rb +2 -9
- data/app/models/spree/promotion/rules/one_use_per_user.rb +0 -4
- data/app/models/spree/promotion/rules/option_value.rb +2 -6
- data/app/models/spree/promotion/rules/product.rb +1 -5
- data/app/models/spree/promotion/rules/user.rb +0 -4
- data/app/models/spree/promotion/rules/user_logged_in.rb +0 -4
- data/app/models/spree/promotion.rb +36 -6
- data/app/models/spree/promotion_action.rb +7 -14
- data/app/models/spree/promotion_action_line_item.rb +1 -1
- data/app/models/spree/promotion_handler/coupon.rb +59 -27
- data/app/models/spree/promotion_rule.rb +7 -14
- data/app/models/spree/purchase_order.rb +3 -0
- data/app/models/spree/quantity_rule.rb +1 -1
- data/app/models/spree/refund.rb +41 -18
- data/app/models/spree/return.rb +31 -2
- data/app/models/spree/return_line_item.rb +65 -14
- data/app/models/spree/role.rb +7 -7
- data/app/models/spree/saved_report.rb +2 -1
- data/app/models/spree/search_provider/base.rb +4 -0
- data/app/models/spree/seller.rb +10 -2
- data/app/models/spree/seller_payout.rb +8 -0
- data/app/models/spree/seller_requirement.rb +5 -12
- data/app/models/spree/seller_requirement_custom_field.rb +1 -2
- data/app/models/spree/seller_requirement_submission.rb +3 -2
- data/app/models/spree/seller_requirements/accept_terms.rb +2 -3
- data/app/models/spree/seller_transfer.rb +6 -0
- data/app/models/spree/shipping_label.rb +2 -0
- data/app/models/spree/stock/availability_validator.rb +2 -2
- data/app/models/spree/stock/estimator.rb +1 -1
- data/app/models/spree/stock/inventory_unit_builder.rb +1 -1
- data/app/models/spree/stock/packer.rb +2 -2
- data/app/models/spree/stock/splitter/weight.rb +1 -1
- data/app/models/spree/stock_level/custom_events.rb +6 -0
- data/app/models/spree/stock_level.rb +3 -1
- data/app/models/spree/stock_location.rb +1 -0
- data/app/models/spree/stock_movement.rb +1 -1
- data/app/models/spree/stock_receipt_item.rb +1 -1
- data/app/models/spree/stock_reservation.rb +2 -2
- data/app/models/spree/stock_transfer.rb +6 -2
- data/app/models/spree/store.rb +70 -19
- data/app/models/spree/store_credit.rb +13 -13
- data/app/models/spree/store_credit_event.rb +5 -5
- data/app/models/spree/supplier.rb +1 -0
- data/app/models/spree/tax_category.rb +1 -0
- data/app/models/spree/tax_exemption_certificate.rb +3 -0
- data/app/models/spree/tax_identifier.rb +3 -1
- data/app/models/spree/tax_line.rb +53 -3
- data/app/models/spree/tax_provider/base.rb +71 -14
- data/app/models/spree/tax_provider/internal.rb +70 -41
- data/app/models/spree/tax_provider/recorded_share.rb +114 -0
- data/app/models/spree/tax_rate.rb +30 -8
- data/app/models/spree/taxon.rb +1 -1
- data/app/models/spree/taxonomy.rb +0 -1
- data/app/models/spree/update_status.rb +25 -0
- data/app/models/spree/variant.rb +10 -12
- data/app/models/spree/variant_media.rb +1 -1
- data/app/models/spree/webhook_delivery.rb +1 -0
- data/app/models/spree/webhook_endpoint.rb +46 -13
- data/app/models/spree/wishlist.rb +1 -6
- data/app/models/spree/wishlist_item/custom_events.rb +6 -0
- data/app/presenters/spree/csv/customer_presenter.rb +1 -1
- data/app/presenters/spree/csv/newsletter_subscriber_presenter.rb +1 -1
- data/app/presenters/spree/csv/order_line_item_presenter.rb +10 -6
- data/app/presenters/spree/csv/price_list_price_presenter.rb +3 -8
- data/app/presenters/spree/csv/product_variant_presenter.rb +59 -20
- data/app/presenters/spree/csv/purchase_order_item_presenter.rb +1 -3
- data/app/serializers/spree/emails/base_serializer.rb +14 -0
- data/app/serializers/spree/emails/export_serializer.rb +13 -0
- data/app/serializers/spree/emails/import_serializer.rb +19 -0
- data/app/serializers/spree/emails/invitation_serializer.rb +28 -0
- data/app/serializers/spree/emails/store_serializer.rb +31 -0
- data/app/serializers/spree/emails/user_serializer.rb +12 -0
- data/app/serializers/spree/emails/webhook_endpoint_serializer.rb +16 -0
- data/app/services/spree/carts/create.rb +8 -2
- data/app/services/spree/carts/destroy.rb +2 -2
- data/app/services/spree/carts/remove_out_of_stock_items.rb +2 -2
- data/app/services/spree/carts/split_by_seller.rb +1 -1
- data/app/services/spree/carts/update.rb +22 -8
- data/app/services/spree/catalogs/set_product_terms.rb +1 -1
- data/app/services/spree/categories/add_products.rb +13 -31
- data/app/services/spree/categories/remove_products.rb +12 -51
- data/app/services/spree/checkout/advance.rb +1 -4
- data/app/services/spree/collections/add_products.rb +10 -23
- data/app/services/spree/collections/remove_products.rb +7 -43
- data/app/services/spree/coupon_codes/bulk_generate.rb +8 -14
- data/app/services/spree/data_requests/create.rb +1 -1
- data/app/services/spree/deliveries/destroy.rb +2 -2
- data/app/services/spree/email_templates/check.rb +58 -0
- data/app/services/spree/email_templates/no_sample_record.rb +7 -0
- data/app/services/spree/email_templates/preview.rb +99 -0
- data/app/services/spree/emails/file_system.rb +23 -0
- data/app/services/spree/emails/filters.rb +84 -0
- data/app/services/spree/emails/liquid_context.rb +48 -0
- data/app/services/spree/emails/rendered_email.rb +14 -0
- data/app/services/spree/emails/renderer.rb +125 -0
- data/app/services/spree/emails/template.rb +51 -0
- data/app/services/spree/emails/template_data.rb +23 -0
- data/app/services/spree/emails/template_resolver.rb +109 -0
- data/app/services/spree/emails/text_converter.rb +72 -0
- data/app/services/spree/emails/translation_inliner.rb +134 -0
- data/app/services/spree/imports/row_processors/price_list_price.rb +10 -10
- data/app/services/spree/imports/row_processors/product_variant.rb +77 -34
- data/app/services/spree/imports/row_processors/purchase_order.rb +13 -13
- data/app/services/spree/locales.rb +43 -10
- data/app/services/spree/newsletter/subscribe.rb +8 -12
- data/app/services/spree/orders/build_fulfillments.rb +3 -2
- data/app/services/spree/orders/create.rb +5 -4
- data/app/services/spree/orders/discounts/create.rb +14 -11
- data/app/services/spree/orders/discounts/destroy.rb +1 -0
- data/app/services/spree/orders/discounts/update.rb +1 -0
- data/app/services/spree/orders/fees/create.rb +1 -0
- data/app/services/spree/orders/fees/destroy.rb +1 -0
- data/app/services/spree/orders/fees/update.rb +1 -0
- data/app/services/spree/orders/remove_line_item.rb +13 -3
- data/app/services/spree/orders/update.rb +10 -6
- data/app/services/spree/orders/update_item.rb +6 -3
- data/app/services/spree/orders/update_statuses.rb +3 -1
- data/app/services/spree/prices/bulk_upsert.rb +32 -25
- data/app/services/spree/product_memberships.rb +61 -0
- data/app/services/spree/returns/eligibility_validator.rb +1 -1
- data/app/services/spree/search_provider/custom_field_schema.rb +2 -2
- data/app/services/spree/seeds/commission_rates.rb +1 -1
- data/app/services/spree/seeds/digital_delivery.rb +1 -1
- data/app/services/spree/seeds/payment_methods.rb +2 -2
- data/app/services/spree/seeds/saved_reports.rb +3 -3
- data/app/services/spree/seeds/stores.rb +1 -1
- data/app/services/spree/sellers/requirements.rb +1 -2
- data/app/services/spree/shipping_labels/confirm_refund.rb +1 -1
- data/app/services/spree/shipping_labels/store_file.rb +3 -3
- data/app/services/spree/stock_levels/correct.rb +3 -3
- data/app/services/spree/stock_reservations/reserve.rb +2 -3
- data/app/services/spree/store_credits/apply.rb +15 -13
- data/app/services/spree/stores/provision_defaults.rb +23 -25
- data/app/services/spree/update_check.rb +160 -0
- data/app/services/spree/uploads/assign_stores.rb +92 -0
- data/app/subscribers/spree/seller_onboarding_subscriber.rb +1 -1
- data/app/validators/spree/attachment_content_type_validator.rb +19 -2
- data/app/validators/spree/locale_codes_validator.rb +22 -0
- data/app/views/layouts/spree/base_mailer.html.erb +2 -43
- data/app/views/layouts/spree/base_mailer.liquid +79 -0
- data/app/views/spree/admin_user_mailer/password_reset_email.liquid +14 -0
- data/app/views/spree/export_mailer/export_done.liquid +12 -0
- data/app/views/spree/import_mailer/import_done.liquid +15 -0
- data/app/views/spree/invitation_mailer/invitation_accepted.liquid +9 -0
- data/app/views/spree/invitation_mailer/invitation_email.liquid +13 -0
- data/app/views/spree/seller_user_mailer/password_reset_email.liquid +14 -0
- data/app/views/spree/shared/_mailer_button.html.erb +4 -5
- data/app/views/spree/shared/_mailer_hero.html.erb +6 -5
- data/app/views/spree/shared/_summary_row.liquid +8 -0
- data/app/views/spree/webhook_mailer/endpoint_disabled.liquid +21 -0
- data/app/workflows/spree/carts/add_item.rb +4 -4
- data/app/workflows/spree/carts/complete.rb +13 -3
- data/app/workflows/spree/carts/merge.rb +1 -1
- data/app/workflows/spree/carts/recalculate_totals.rb +5 -0
- data/app/workflows/spree/carts/upsert_items.rb +18 -9
- data/app/workflows/spree/claims/approve.rb +5 -22
- data/app/workflows/spree/claims/cancel.rb +5 -21
- data/app/workflows/spree/claims/create.rb +15 -0
- data/app/workflows/spree/claims/deny.rb +7 -0
- data/app/workflows/spree/claims/resolve.rb +34 -31
- data/app/workflows/spree/customers/anonymize.rb +3 -4
- data/app/workflows/spree/customers/create.rb +1 -1
- data/app/workflows/spree/data_requests/fulfill.rb +2 -2
- data/app/workflows/spree/deliveries/update_tracking.rb +1 -1
- data/app/workflows/spree/email_templates/discard_draft.rb +20 -0
- data/app/workflows/spree/email_templates/publish.rb +70 -0
- data/app/workflows/spree/email_templates/restore_revision.rb +33 -0
- data/app/workflows/spree/email_templates/revert.rb +29 -0
- data/app/workflows/spree/email_templates/save_draft.rb +85 -0
- data/app/workflows/spree/exchanges/approve.rb +5 -22
- data/app/workflows/spree/exchanges/cancel.rb +5 -21
- data/app/workflows/spree/exchanges/create.rb +6 -0
- data/app/workflows/spree/exchanges/fulfill.rb +75 -51
- data/app/workflows/spree/exchanges/receive.rb +6 -65
- data/app/workflows/spree/fulfillments/cancel.rb +1 -1
- data/app/workflows/spree/fulfillments/create.rb +53 -49
- data/app/workflows/spree/fulfillments/fulfill.rb +23 -27
- data/app/workflows/spree/fulfillments/mark_delivered.rb +1 -1
- data/app/workflows/spree/fulfillments/replacements.rb +59 -0
- data/app/workflows/spree/gift_cards/apply.rb +2 -2
- data/app/workflows/spree/orders/add_item.rb +5 -1
- data/app/workflows/spree/orders/cancel.rb +3 -3
- data/app/workflows/spree/orders/complete.rb +16 -8
- data/app/workflows/spree/payments/capture.rb +20 -5
- data/app/workflows/spree/payments/process.rb +5 -3
- data/app/workflows/spree/post_sale/approval.rb +35 -0
- data/app/workflows/spree/post_sale/cancellation.rb +44 -0
- data/app/workflows/spree/post_sale/receipt.rb +92 -0
- data/app/workflows/spree/price_lists/update.rb +4 -4
- data/app/workflows/spree/products/nested_attributes.rb +1 -1
- data/app/workflows/spree/purchase_orders/cancel.rb +1 -1
- data/app/workflows/spree/purchase_orders/close.rb +3 -31
- data/app/workflows/spree/purchase_orders/create.rb +3 -1
- data/app/workflows/spree/purchase_orders/mark_draft.rb +2 -2
- data/app/workflows/spree/purchase_orders/mark_ordered.rb +2 -2
- data/app/workflows/spree/purchase_orders/receive.rb +1 -1
- data/app/workflows/spree/purchase_orders/update.rb +5 -34
- data/app/workflows/spree/receivables/closing_short.rb +46 -0
- data/app/workflows/spree/receivables/draft_editing.rb +48 -0
- data/app/workflows/spree/refunds/create.rb +5 -2
- data/app/workflows/spree/refunds/order_payments.rb +14 -2
- data/app/workflows/spree/refunds/tax_credit.rb +67 -0
- data/app/workflows/spree/returns/approve.rb +5 -22
- data/app/workflows/spree/returns/cancel.rb +5 -22
- data/app/workflows/spree/returns/create.rb +8 -0
- data/app/workflows/spree/returns/receive.rb +5 -76
- data/app/workflows/spree/returns/refund.rb +31 -8
- data/app/workflows/spree/seller_requirement_submissions/create.rb +1 -2
- data/app/workflows/spree/seller_transfers/reverse.rb +28 -1
- data/app/workflows/spree/shipping_labels/purchase.rb +8 -8
- data/app/workflows/spree/shipping_labels/record.rb +7 -7
- data/app/workflows/spree/shipping_labels/refund.rb +2 -2
- data/app/workflows/spree/stock_receipts/recording.rb +4 -4
- data/app/workflows/spree/stock_transfers/cancel.rb +2 -2
- data/app/workflows/spree/stock_transfers/close.rb +3 -30
- data/app/workflows/spree/stock_transfers/create.rb +3 -1
- data/app/workflows/spree/stock_transfers/mark_draft.rb +1 -1
- data/app/workflows/spree/stock_transfers/mark_in_transit.rb +3 -3
- data/app/workflows/spree/stock_transfers/mark_ready.rb +2 -2
- data/app/workflows/spree/stock_transfers/receive.rb +1 -1
- data/app/workflows/spree/stock_transfers/update.rb +5 -33
- data/config/currency_exponents.json +180 -0
- data/config/i18n-tasks.yml +32 -18
- data/config/initializers/alba.rb +7 -0
- data/config/language_names.csv +264 -0
- data/config/locales/ar.yml +811 -0
- data/config/locales/be.yml +855 -0
- data/config/locales/bg.yml +723 -0
- data/config/locales/ca.yml +689 -0
- data/config/locales/content_locales.rb +9 -0
- data/config/locales/cs.yml +855 -0
- data/config/locales/da.yml +771 -0
- data/config/locales/de-CH.yml +248 -0
- data/config/locales/de.yml +835 -0
- data/config/locales/el.yml +769 -0
- data/config/locales/en.yml +47 -505
- data/config/locales/es-CL.yml +301 -0
- data/config/locales/es-EC.yml +186 -0
- data/config/locales/es-MX.yml +334 -0
- data/config/locales/es.yml +831 -0
- data/config/locales/et.yml +644 -0
- data/config/locales/fa.yml +709 -0
- data/config/locales/fi.yml +771 -0
- data/config/locales/fr.yml +830 -0
- data/config/locales/hu.yml +751 -0
- data/config/locales/id.yml +756 -0
- data/config/locales/it.yml +833 -0
- data/config/locales/ja.yml +726 -0
- data/config/locales/km.yml +759 -0
- data/config/locales/ko.yml +575 -0
- data/config/locales/ku.yml +753 -0
- data/config/locales/lt.yml +821 -0
- data/config/locales/lv.yml +685 -0
- data/config/locales/nb.yml +824 -0
- data/config/locales/ne.yml +823 -0
- data/config/locales/nl.yml +826 -0
- data/config/locales/pl.yml +835 -0
- data/config/locales/pt-BR.yml +547 -0
- data/config/locales/pt.yml +636 -0
- data/config/locales/ro.yml +750 -0
- data/config/locales/ru.yml +834 -0
- data/config/locales/sk.yml +680 -0
- data/config/locales/sl-SI.yml +600 -0
- data/config/locales/sv.yml +827 -0
- data/config/locales/th.yml +745 -0
- data/config/locales/tr.yml +777 -0
- data/config/locales/uk.yml +836 -0
- data/config/locales/vi.yml +768 -0
- data/config/locales/zh-CN.yml +786 -0
- data/config/locales/zh-TW.yml +834 -0
- data/db/migrate/20260925000001_add_replacement_to_spree_fulfillment_items.rb +5 -0
- data/db/migrate/20261001000001_add_post_sale_tax.rb +30 -0
- data/db/migrate/20261001000001_convert_preferences_to_json.rb +166 -0
- data/db/migrate/20261001000001_create_spree_email_templates.rb +52 -0
- data/db/migrate/20261009000001_change_money_columns_to_decimal_19_4.rb +116 -0
- data/db/migrate/20261010000001_add_store_id_to_active_storage_blobs.rb +12 -0
- data/lib/generators/spree/dummy/dummy_generator.rb +0 -9
- data/lib/generators/spree/dummy/templates/rails/test.rb +26 -0
- data/lib/spree/checkout/default_requirements.rb +37 -13
- data/lib/spree/core/configuration.rb +19 -1
- data/lib/spree/core/controller_helpers/store.rb +1 -1
- data/lib/spree/core/dependencies.rb +5 -4
- data/lib/spree/core/emails/escaped_output.rb +60 -0
- data/lib/spree/core/engine.rb +72 -165
- data/lib/spree/core/permissions/default_catalog.rb +5 -0
- data/lib/spree/core/preferences/invalid_preferences.rb +18 -0
- data/lib/spree/core/preferences/json_conversion.rb +186 -0
- data/lib/spree/core/preferences/masking.rb +55 -2
- data/lib/spree/core/preferences/preferable.rb +343 -103
- data/lib/spree/core/preferences/preferable_class_methods.rb +188 -136
- data/lib/spree/core/previews/import_preview.rb +10 -0
- data/lib/spree/core/ransack_configuration.rb +13 -2
- data/lib/spree/core/tax/provider_error.rb +37 -0
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/core.rb +91 -373
- data/lib/spree/emails/editable_templates.rb +82 -0
- data/lib/spree/events/catalog.rb +189 -0
- data/lib/spree/events.rb +21 -1
- data/lib/spree/hooks.rb +0 -17
- data/lib/spree/i18n.rb +32 -15
- data/lib/spree/iso_data.rb +7 -0
- data/lib/spree/localized_number.rb +6 -0
- data/lib/spree/migrations.rb +4 -1
- data/lib/spree/money.rb +196 -15
- data/lib/spree/reporting/adapters/base.rb +7 -6
- data/lib/spree/reporting/adapters/live.rb +6 -6
- data/lib/spree/reporting/default_vocabulary.rb +22 -10
- data/lib/spree/reporting/hydration.rb +1 -1
- data/lib/spree/reporting/query.rb +8 -0
- data/lib/spree/reporting/registry.rb +13 -0
- data/lib/spree/reporting/schema.rb +10 -10
- data/lib/spree/testing_support/editable_email_templates.rb +61 -0
- data/lib/spree/testing_support/emails.rb +22 -0
- data/lib/spree/testing_support/factories/cart_factory.rb +1 -1
- data/lib/spree/testing_support/factories/email_template_factory.rb +28 -0
- data/lib/spree/testing_support/factories/order_factory.rb +2 -2
- data/lib/spree/testing_support/factories/product_factory.rb +9 -0
- data/lib/spree/testing_support/factories/refund_factory.rb +1 -1
- data/lib/spree/testing_support/factories/stock_factory.rb +1 -1
- data/lib/spree/testing_support/factories/variant_factory.rb +1 -1
- data/lib/spree/testing_support/i18n.rb +3 -94
- data/lib/spree/testing_support/lifecycle_events.rb +1 -1
- data/lib/spree/testing_support/order_walkthrough.rb +1 -1
- data/lib/spree/testing_support/preferences.rb +0 -5
- data/lib/spree/testing_support/store.rb +9 -1
- data/lib/spree/upgrades/5_6_to_6_0/manifest.yml +67 -1
- data/lib/spree/uploads.rb +101 -0
- data/lib/tasks/categories_and_collections.rake +3 -3
- data/lib/tasks/core.rake +6 -4
- data/lib/tasks/markets.rake +2 -1
- data/lib/tasks/media.rake +3 -3
- data/lib/tasks/migrate_users_to_customers.rake +23 -18
- data/lib/tasks/money.rake +46 -0
- data/lib/tasks/package_types.rake +1 -1
- data/lib/tasks/preferences_json.rake +101 -0
- data/lib/tasks/seller_sample_data.rake +2 -2
- data/lib/tasks/store_settings.rake +13 -6
- data/lib/tasks/typed_adjustments_migration.rake +1 -1
- data/lib/tasks/uploads.rake +19 -0
- data/spec/fixtures/mailer_views/custom_views_probe_mailer/welcome_email.html.erb +4 -0
- metadata +219 -46
- data/app/jobs/spree/products/touch_categories_job.rb +0 -15
- data/app/jobs/spree/products/touch_taxons_job.rb +0 -13
- data/app/models/acts_as_taggable_on/tag_decorator.rb +0 -10
- data/app/models/concerns/spree/has_image_alt_text.rb +0 -18
- data/app/models/spree/base_analytics_event_handler.rb +0 -54
- data/app/models/spree/invitations/store.rb +0 -6
- data/app/models/spree/preference.rb +0 -14
- data/app/models/spree/promotion_handler/page.rb +0 -25
- data/app/models/spree/promotion_handler/promotion_duplicator.rb +0 -60
- data/app/models/spree/stock/differentiator.rb +0 -45
- data/app/presenters/spree/filters/options_presenter.rb +0 -47
- data/app/services/spree/carts/empty.rb +0 -42
- data/app/services/spree/country_to_timezone.rb +0 -273
- data/app/services/spree/payments/create.rb +0 -92
- data/app/validators/spree/url_validator.rb +0 -23
- data/app/views/active_storage/blobs/_blob.html.erb +0 -14
- data/app/views/spree/admin_user_mailer/password_reset_email.html.erb +0 -8
- data/app/views/spree/export_mailer/export_done.html.erb +0 -7
- data/app/views/spree/import_mailer/import_done.html.erb +0 -12
- data/app/views/spree/invitation_mailer/invitation_accepted.html.erb +0 -4
- data/app/views/spree/invitation_mailer/invitation_email.html.erb +0 -12
- data/app/views/spree/seller_user_mailer/password_reset_email.html.erb +0 -8
- data/app/views/spree/shared/_base_mailer_footer.html.erb +0 -19
- data/app/views/spree/shared/_base_mailer_header.html.erb +0 -8
- data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +0 -399
- data/app/views/spree/shared/_mailer_logo.html.erb +0 -41
- data/app/views/spree/shared/_purchased_items_styles.html.erb +0 -119
- data/app/views/spree/webhook_mailer/endpoint_disabled.html.erb +0 -51
- data/app/views/spree/webhook_mailer/endpoint_disabled.text.erb +0 -10
- data/app/workflows/spree/fulfillments/purchase_label.rb +0 -40
- data/app/workflows/spree/returns/purchase_label.rb +0 -32
- data/lib/spree/analytics.rb +0 -11
- data/lib/spree/core/preferences/scoped_store.rb +0 -34
- data/lib/spree/core/preferences/store.rb +0 -105
- data/lib/spree/translation_migrations.rb +0 -52
|
@@ -9,13 +9,22 @@ module Spree
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def variant_includes
|
|
12
|
-
[:images, :prices, :
|
|
12
|
+
[:images, :prices, { stock_levels: :stock_location, option_values: [:option_type] }]
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def multi_line_csv?
|
|
16
16
|
true
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
+
# The seller scopes which locations the inventory columns cover; their
|
|
20
|
+
# default, worked out once per export, carries the full row's stock.
|
|
21
|
+
def to_csv_options
|
|
22
|
+
@to_csv_options ||= {
|
|
23
|
+
seller: seller,
|
|
24
|
+
default_stock_location: Spree::StockLocation.owned_by(store_id: store.id, seller_id: seller&.id).active.order_default.first || store.default_stock_location
|
|
25
|
+
}
|
|
26
|
+
end
|
|
27
|
+
|
|
19
28
|
# when doing full product export, we want to exclude archived products
|
|
20
29
|
def scope
|
|
21
30
|
if search_params.nil?
|
|
@@ -46,13 +46,13 @@ module Spree
|
|
|
46
46
|
result.rows.each do |row|
|
|
47
47
|
csv << Spree::CSV::FormulaSanitizer.row(
|
|
48
48
|
row[:dimensions].map { |name, raw| hydration.label(name, raw) } +
|
|
49
|
-
query.metrics.map { |m| row[:metrics][m.name][:value] }
|
|
49
|
+
query.metrics.map { |m| m.format_value(row[:metrics][m.name][:value], result.meta[:currency]) }
|
|
50
50
|
)
|
|
51
51
|
end
|
|
52
|
-
totals = query.metrics.map { |m| result.totals[m.name][:value] }
|
|
52
|
+
totals = query.metrics.map { |m| m.format_value(result.totals[m.name][:value], result.meta[:currency]) }
|
|
53
53
|
# With a breakdown the totals close the file under a "Total" label in
|
|
54
54
|
# the first dimension column; without one the totals are the only row.
|
|
55
|
-
label = query.dimensions.empty? ? [] : [
|
|
55
|
+
label = query.dimensions.empty? ? [] : [I18n.t('spree.reporting.export.total')] + Array.new(query.dimensions.size - 1, '')
|
|
56
56
|
csv << Spree::CSV::FormulaSanitizer.row(label + totals)
|
|
57
57
|
end
|
|
58
58
|
end
|
data/app/models/spree/fee.rb
CHANGED
|
@@ -10,8 +10,10 @@ module Spree
|
|
|
10
10
|
# Extensions may append their own kinds — the list is validated, not frozen.
|
|
11
11
|
# `duty` rows are written by a duties provider's adjuster and snapshot the
|
|
12
12
|
# classification they were calculated from in `metadata` — never re-derive
|
|
13
|
-
# a duty from the live catalog.
|
|
14
|
-
|
|
13
|
+
# a duty from the live catalog. `exchange` is what a customer owes when an
|
|
14
|
+
# exchange's replacement costs more, put on the order for the merchant to
|
|
15
|
+
# collect.
|
|
16
|
+
KINDS = %w[surcharge handling gift_wrap cod payment duty exchange]
|
|
15
17
|
|
|
16
18
|
has_prefix_id :fee
|
|
17
19
|
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
# A file sent to `POST /files` (docs/plans/6.0-uploads-and-file-ownership.md),
|
|
3
|
+
# before anything uses it.
|
|
4
|
+
#
|
|
5
|
+
# Two ways in, one result. A presigned upload carries only the file's
|
|
6
|
+
# metadata and gets back a storage target the client sends the bytes to; a
|
|
7
|
+
# multipart upload carries the bytes, which are stored here. Either way the
|
|
8
|
+
# result is a blob owned by +store+ and an expiring, opaque `signed_id` the
|
|
9
|
+
# client passes to whichever endpoint uses the file.
|
|
10
|
+
#
|
|
11
|
+
# Never persisted: the blob is the record.
|
|
12
|
+
class FileUpload
|
|
13
|
+
include ActiveModel::Model
|
|
14
|
+
include ActiveModel::Attributes
|
|
15
|
+
|
|
16
|
+
VISIBILITIES = %w[public private].freeze
|
|
17
|
+
|
|
18
|
+
attribute :filename, :string
|
|
19
|
+
attribute :content_type, :string
|
|
20
|
+
attribute :byte_size, :integer
|
|
21
|
+
attribute :checksum, :string
|
|
22
|
+
attribute :visibility, :string, default: 'public'
|
|
23
|
+
# The bytes of a multipart upload (an uploaded file or any IO).
|
|
24
|
+
attribute :file
|
|
25
|
+
attribute :store
|
|
26
|
+
# Narrower limits for a caller with its own rules (a buyer's purchase
|
|
27
|
+
# order document); the installation-wide ones apply otherwise.
|
|
28
|
+
attribute :max_byte_size, :integer
|
|
29
|
+
attribute :allowed_content_types
|
|
30
|
+
|
|
31
|
+
attr_reader :blob, :signed_id, :expires_at
|
|
32
|
+
|
|
33
|
+
validates :store, presence: true
|
|
34
|
+
validates :visibility, inclusion: { in: VISIBILITIES }
|
|
35
|
+
validates :filename, :content_type, presence: true
|
|
36
|
+
validates :checksum, presence: true, unless: :multipart?
|
|
37
|
+
validates :byte_size, numericality: { only_integer: true, greater_than: 0 }
|
|
38
|
+
validate :byte_size_within_limit
|
|
39
|
+
validate :content_type_allowed
|
|
40
|
+
|
|
41
|
+
# The content types a public upload may have. Private uploads accept any
|
|
42
|
+
# type: digital products are ebooks, archives and audio, and each
|
|
43
|
+
# attachment validates its own file.
|
|
44
|
+
#
|
|
45
|
+
# @return [Array<String>]
|
|
46
|
+
def self.public_content_types
|
|
47
|
+
Rails.application.config.active_storage.web_image_content_types +
|
|
48
|
+
Spree::Config.video_content_types +
|
|
49
|
+
%w[text/csv]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @return [Boolean] whether the bytes travel in the request
|
|
53
|
+
def multipart?
|
|
54
|
+
file.respond_to?(:read)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# @return [Boolean] whether the file lands on private storage
|
|
58
|
+
def private?
|
|
59
|
+
visibility == 'private'
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Validates and creates the blob. A multipart upload is stored here; a
|
|
63
|
+
# presigned one waits for the client to send its bytes to {#upload_target}.
|
|
64
|
+
#
|
|
65
|
+
# @return [Boolean]
|
|
66
|
+
def save
|
|
67
|
+
read_file_facts if multipart?
|
|
68
|
+
return false unless valid?
|
|
69
|
+
|
|
70
|
+
@blob = multipart? ? store_bytes : reserve_blob
|
|
71
|
+
@expires_at = Spree::Uploads::SIGNED_ID_EXPIRY.from_now
|
|
72
|
+
@signed_id = Spree::Uploads.signed_id_for(@blob)
|
|
73
|
+
true
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Where a presigned upload's bytes go, or nil once the file is stored.
|
|
77
|
+
#
|
|
78
|
+
# @return [Spree::FileUpload::Target, nil]
|
|
79
|
+
def upload_target
|
|
80
|
+
return if multipart? || blob.nil?
|
|
81
|
+
|
|
82
|
+
Target.new(
|
|
83
|
+
http_method: 'PUT',
|
|
84
|
+
url: blob.service_url_for_direct_upload,
|
|
85
|
+
headers: blob.service_headers_for_direct_upload
|
|
86
|
+
)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# The storage target a presigned upload sends its bytes to.
|
|
90
|
+
class Target
|
|
91
|
+
include ActiveModel::Model
|
|
92
|
+
include ActiveModel::Attributes
|
|
93
|
+
|
|
94
|
+
# Not `method`, which every Ruby object already answers.
|
|
95
|
+
attribute :http_method, :string
|
|
96
|
+
attribute :url, :string
|
|
97
|
+
attribute :headers
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
private
|
|
101
|
+
|
|
102
|
+
# The size of a multipart upload comes from the bytes, and so does its type
|
|
103
|
+
# wherever the bytes carry a recognisable signature: Marcel reads the
|
|
104
|
+
# content first, so a renamed executable is not accepted as an image. Only
|
|
105
|
+
# bytes it cannot place fall back to the declared type and the file name.
|
|
106
|
+
def read_file_facts
|
|
107
|
+
self.filename = filename.presence || file.try(:original_filename)
|
|
108
|
+
self.byte_size = io.size
|
|
109
|
+
self.content_type = Marcel::MimeType.for(io, name: filename, declared_type: content_type.presence || file.try(:content_type))
|
|
110
|
+
io.rewind
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def reserve_blob
|
|
114
|
+
ActiveStorage::Blob.create!(
|
|
115
|
+
filename: filename, byte_size: byte_size, checksum: checksum, content_type: content_type,
|
|
116
|
+
service_name: service_name, store_id: store.id
|
|
117
|
+
)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def store_bytes
|
|
121
|
+
ActiveStorage::Blob.build_after_unfurling(
|
|
122
|
+
io: io, filename: filename, content_type: content_type, service_name: service_name, identify: false
|
|
123
|
+
).tap do |blob|
|
|
124
|
+
blob.store_id = store.id
|
|
125
|
+
blob.save!
|
|
126
|
+
blob.upload_without_unfurling(io)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def io
|
|
131
|
+
@io ||= file.respond_to?(:to_io) ? file.to_io : file
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def service_name
|
|
135
|
+
private? ? Spree.private_storage_service_name : Spree.public_storage_service_name
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def size_limit
|
|
139
|
+
max_byte_size || (multipart? ? Spree::Config.max_multipart_upload_size : Spree::Config.max_upload_size)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def byte_size_within_limit
|
|
143
|
+
return if byte_size.nil? || byte_size <= size_limit
|
|
144
|
+
|
|
145
|
+
errors.add(:byte_size, :less_than_or_equal_to, count: ActiveSupport::NumberHelper.number_to_human_size(size_limit))
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def content_type_allowed
|
|
149
|
+
allowed = allowed_content_types || (self.class.public_content_types unless private?)
|
|
150
|
+
return if allowed.nil? || content_type.blank? || allowed.include?(content_type)
|
|
151
|
+
|
|
152
|
+
errors.add(:content_type, :inclusion, value: content_type)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
require 'ostruct'
|
|
2
|
-
|
|
3
1
|
module Spree
|
|
4
2
|
class Fulfillment < Spree.base_class
|
|
5
3
|
has_prefix_id :ful
|
|
@@ -15,6 +13,9 @@ module Spree
|
|
|
15
13
|
include Spree::Fulfillment::CustomEvents
|
|
16
14
|
|
|
17
15
|
publishes_lifecycle_events
|
|
16
|
+
publishes_events :canceled, :delivered, :fulfilled
|
|
17
|
+
publishes_event 'shipment.shipped', deprecated_alias_of: 'fulfillment.fulfilled'
|
|
18
|
+
publishes_event 'shipment.canceled', deprecated_alias_of: 'fulfillment.canceled'
|
|
18
19
|
|
|
19
20
|
with_options inverse_of: :fulfillments do
|
|
20
21
|
belongs_to :address, class_name: 'Spree::Address', optional: true
|
|
@@ -92,6 +93,18 @@ module Spree
|
|
|
92
93
|
|
|
93
94
|
delegate :store, :currency, to: :owner
|
|
94
95
|
|
|
96
|
+
# What a rebuild hands to {#carry_over_selection}, read before the old
|
|
97
|
+
# proposals and their rates are deleted. Grouped rather than keyed by
|
|
98
|
+
# location: one location can ship several proposals (a digital item beside
|
|
99
|
+
# a physical one, stock on hand beside a backorder), each with its own choice.
|
|
100
|
+
#
|
|
101
|
+
# @return [Hash{Integer => Array<Spree::DeliveryRate>}] the selected rates
|
|
102
|
+
# of each stock location's proposals
|
|
103
|
+
def self.selected_rates_by_stock_location
|
|
104
|
+
includes(:selected_delivery_rate).group_by(&:stock_location_id).
|
|
105
|
+
transform_values { |proposals| proposals.filter_map(&:selected_delivery_rate) }
|
|
106
|
+
end
|
|
107
|
+
|
|
95
108
|
# The exactly-one owner of this fulfillment — the cart during checkout,
|
|
96
109
|
# the order after completion. New code must read +owner+, never assume
|
|
97
110
|
# +order+.
|
|
@@ -221,7 +234,7 @@ module Spree
|
|
|
221
234
|
#
|
|
222
235
|
# @return [String, Spree::Money]
|
|
223
236
|
def display_cost(**options)
|
|
224
|
-
return
|
|
237
|
+
return I18n.t('spree.delivery_rates.quoted_after_review') if unpriced?
|
|
225
238
|
|
|
226
239
|
Spree::Money.new(cost, { currency: currency }.merge(options))
|
|
227
240
|
end
|
|
@@ -338,7 +351,7 @@ module Spree
|
|
|
338
351
|
#
|
|
339
352
|
# @return [String, Spree::Money]
|
|
340
353
|
def display_final_price(**options)
|
|
341
|
-
return
|
|
354
|
+
return I18n.t('spree.delivery_rates.quoted_after_review') if unpriced?
|
|
342
355
|
|
|
343
356
|
Spree::Money.new(final_price, { currency: currency }.merge(options))
|
|
344
357
|
end
|
|
@@ -361,9 +374,20 @@ module Spree
|
|
|
361
374
|
#
|
|
362
375
|
# @return [Boolean]
|
|
363
376
|
def with_free_shipping_promotion?
|
|
377
|
+
return discounts.any?(&:promotion?) if read_association_in_memory?(:discounts)
|
|
378
|
+
|
|
364
379
|
discounts.promotion.exists?
|
|
365
380
|
end
|
|
366
381
|
|
|
382
|
+
# What promotions took off this shipment's cost, as a negative amount.
|
|
383
|
+
#
|
|
384
|
+
# @return [BigDecimal]
|
|
385
|
+
def promotion_discount_total
|
|
386
|
+
return discounts.select(&:promotion?).sum(BigDecimal('0'), &:amount) if read_association_in_memory?(:discounts)
|
|
387
|
+
|
|
388
|
+
discounts.promotion.sum(:amount)
|
|
389
|
+
end
|
|
390
|
+
|
|
367
391
|
# Placement no longer moves physical stock — the units are promised in
|
|
368
392
|
# Spree::Orders::Complete and only leave the shelf when the parcel does.
|
|
369
393
|
def finalize!
|
|
@@ -543,34 +567,13 @@ module Spree
|
|
|
543
567
|
|
|
544
568
|
# StockEstimator.new assignment below will replace the current delivery_method
|
|
545
569
|
original_shipping_method_id = delivery_method.try(:id)
|
|
546
|
-
# A carrier method quotes several rates (one per service), so the
|
|
547
|
-
# method id alone no longer identifies the customer's choice — capture
|
|
548
|
-
# the selected rate's carrier service too.
|
|
549
570
|
original_selection = selected_delivery_rate
|
|
550
|
-
original_carrier = original_selection&.carrier
|
|
551
|
-
original_service_level = original_selection&.service_level
|
|
552
571
|
|
|
553
572
|
self.delivery_rates = Stock::Estimator.new(owner).
|
|
554
573
|
delivery_rates(to_package, audience)
|
|
555
574
|
|
|
556
575
|
if delivery_method
|
|
557
|
-
|
|
558
|
-
# then the previously chosen method, then the estimator's own pick
|
|
559
|
-
# (the cheapest rate, already flagged selected) rather than leaving
|
|
560
|
-
# the fulfillment unselected.
|
|
561
|
-
selected_rate =
|
|
562
|
-
if original_shipping_method_id && original_carrier
|
|
563
|
-
delivery_rates.detect do |rate|
|
|
564
|
-
rate.delivery_method_id == original_shipping_method_id &&
|
|
565
|
-
rate.carrier == original_carrier &&
|
|
566
|
-
rate.service_level == original_service_level
|
|
567
|
-
end
|
|
568
|
-
end
|
|
569
|
-
selected_rate ||=
|
|
570
|
-
if original_shipping_method_id
|
|
571
|
-
delivery_rates.detect { |rate| rate.delivery_method_id == original_shipping_method_id }
|
|
572
|
-
end
|
|
573
|
-
selected_rate ||= delivery_rates.detect(&:selected)
|
|
576
|
+
selected_rate = successor_rate(original_shipping_method_id, original_selection)
|
|
574
577
|
|
|
575
578
|
save!
|
|
576
579
|
self.selected_shipping_rate_id = selected_rate.id if selected_rate
|
|
@@ -709,7 +712,7 @@ module Spree
|
|
|
709
712
|
#
|
|
710
713
|
# @return [Spree::Delivery, nil]
|
|
711
714
|
def primary_delivery
|
|
712
|
-
deliveries.first
|
|
715
|
+
read_association_in_memory?(:deliveries) ? deliveries.to_a.first : deliveries.first
|
|
713
716
|
end
|
|
714
717
|
|
|
715
718
|
# The primary delivery's tracking number. Read-only since 6.0: tracking is
|
|
@@ -755,6 +758,25 @@ module Spree
|
|
|
755
758
|
end
|
|
756
759
|
end
|
|
757
760
|
|
|
761
|
+
# Carries the customer's choice onto a freshly built, unsaved proposal:
|
|
762
|
+
# takes the first of +candidates+ whose method this proposal is quoted for,
|
|
763
|
+
# selects the rate standing for it and prices the proposal at it, so a
|
|
764
|
+
# rebuild neither resets the choice nor drops its cost. The rate taken is
|
|
765
|
+
# removed from +candidates+, leaving the rest to this proposal's siblings.
|
|
766
|
+
#
|
|
767
|
+
# @param candidates [Array<Spree::DeliveryRate>] the rates selected on the
|
|
768
|
+
# proposals this stock location had before the rebuild
|
|
769
|
+
# @return [void]
|
|
770
|
+
def carry_over_selection(candidates)
|
|
771
|
+
quoted_method_ids = delivery_rates.map(&:delivery_method_id)
|
|
772
|
+
previous_rate = candidates.find { |rate| quoted_method_ids.include?(rate.delivery_method_id) }
|
|
773
|
+
candidates.delete(previous_rate)
|
|
774
|
+
|
|
775
|
+
choice = successor_rate(previous_rate&.delivery_method_id, previous_rate)
|
|
776
|
+
delivery_rates.each { |rate| rate.selected = rate == choice }
|
|
777
|
+
self.cost = choice&.cost || 0
|
|
778
|
+
end
|
|
779
|
+
|
|
758
780
|
# @deprecated No-op since 6.0; removed in 6.1.
|
|
759
781
|
#
|
|
760
782
|
# This re-derived the status from the order's payment state on every order
|
|
@@ -792,6 +814,21 @@ module Spree
|
|
|
792
814
|
|
|
793
815
|
private
|
|
794
816
|
|
|
817
|
+
# The previously chosen carrier service when it is still quoted, then the
|
|
818
|
+
# previously chosen method, then the estimator's own pick - a carrier
|
|
819
|
+
# method quotes one rate per service, so the method alone does not
|
|
820
|
+
# identify the choice.
|
|
821
|
+
def successor_rate(delivery_method_id, previous_rate)
|
|
822
|
+
same_method = delivery_method_id ? delivery_rates.select { |rate| rate.delivery_method_id == delivery_method_id } : []
|
|
823
|
+
same_service = if previous_rate&.carrier
|
|
824
|
+
same_method.detect do |rate|
|
|
825
|
+
rate.carrier == previous_rate.carrier && rate.service_level == previous_rate.service_level
|
|
826
|
+
end
|
|
827
|
+
end
|
|
828
|
+
|
|
829
|
+
same_service || same_method.first || delivery_rates.detect(&:selected)
|
|
830
|
+
end
|
|
831
|
+
|
|
795
832
|
# @return [Boolean] whether this parcel's order shares its payment with
|
|
796
833
|
# others placed in the same checkout
|
|
797
834
|
# Draws one parcel's worth from a payment and reports what it took.
|
|
@@ -869,8 +906,7 @@ module Spree
|
|
|
869
906
|
def capture_at_gateway(payment, amount)
|
|
870
907
|
return 0 if amount <= 0
|
|
871
908
|
|
|
872
|
-
|
|
873
|
-
result = Spree.payment_capture_workflow.call(payment: payment, amount: units)
|
|
909
|
+
result = Spree.payment_capture_workflow.call(payment: payment, amount: amount)
|
|
874
910
|
raise Spree::Core::GatewayError, result.error.value.to_s if result.failure?
|
|
875
911
|
|
|
876
912
|
amount
|
|
@@ -957,7 +993,7 @@ module Spree
|
|
|
957
993
|
end
|
|
958
994
|
|
|
959
995
|
def exactly_one_owner
|
|
960
|
-
errors.add(:base, :exactly_one_of_cart_or_order, message:
|
|
996
|
+
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?
|
|
961
997
|
end
|
|
962
998
|
|
|
963
999
|
def update_adjustments
|
|
@@ -106,8 +106,8 @@ module Spree
|
|
|
106
106
|
end
|
|
107
107
|
|
|
108
108
|
def get_desired_shipment_inventory_unit(state)
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
current_shipment_unit = current_shipment_units.first
|
|
110
|
+
desired_shipment.fulfillment_items.find_or_create_by(status: state, variant: variant, replacement: current_shipment_unit&.replacement || false) do |unit|
|
|
111
111
|
unit.variant_id = current_shipment_unit.variant_id
|
|
112
112
|
unit.order_id = current_shipment_unit.order_id
|
|
113
113
|
unit.line_item_id = current_shipment_unit.line_item_id
|
|
@@ -72,12 +72,17 @@ module Spree
|
|
|
72
72
|
fulfillments.sum { |fulfillment| fulfillment.discounted_cost.to_d }
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
+
# @return [String] the currency the parcel was quoted in
|
|
76
|
+
def currency
|
|
77
|
+
primary.currency
|
|
78
|
+
end
|
|
79
|
+
|
|
75
80
|
# @return [String, Spree::Money] the forwarder's placeholder while a
|
|
76
81
|
# freight rate is unpriced, money otherwise
|
|
77
82
|
def display_cost(**options)
|
|
78
83
|
return primary.display_cost(**options) if unpriced?
|
|
79
84
|
|
|
80
|
-
Spree::Money.new(cost, { currency:
|
|
85
|
+
Spree::Money.new(cost, { currency: currency }.merge(options))
|
|
81
86
|
end
|
|
82
87
|
|
|
83
88
|
# @return [Boolean]
|
|
@@ -15,11 +15,7 @@ module Spree
|
|
|
15
15
|
belongs_to :line_item, class_name: 'Spree::LineItem'
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
scope :backordered, -> { where status: 'backordered' }
|
|
19
|
-
scope :on_hand, -> { where status: 'on_hand' }
|
|
20
18
|
scope :on_hand_or_backordered, -> { where status: ['backordered', 'on_hand'] }
|
|
21
|
-
scope :shipped, -> { where status: 'shipped' }
|
|
22
|
-
scope :returned, -> { where status: 'returned' }
|
|
23
19
|
scope :backordered_per_variant, ->(stock_level) do
|
|
24
20
|
includes(:fulfillment, :order).
|
|
25
21
|
where.not(Spree::Fulfillment.table_name => { status: 'canceled' }).
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class Gateway::Bogus < Gateway
|
|
3
|
+
self.accepts_money_amounts = true
|
|
4
|
+
|
|
3
5
|
TEST_VISA = ['4111111111111111', '4012888888881881', '4222222222222']
|
|
4
6
|
TEST_MC = ['5500000000000004', '5555555555554444', '5105105105105100', '2223000010309703']
|
|
5
7
|
TEST_AMEX = ['378282246310005', '371449635398431', '378734493671000', '340000000000009']
|
|
@@ -117,6 +119,10 @@ module Spree
|
|
|
117
119
|
payment_session.complete
|
|
118
120
|
end
|
|
119
121
|
|
|
122
|
+
def cancel_payment_session(payment_session:)
|
|
123
|
+
payment_session.cancel
|
|
124
|
+
end
|
|
125
|
+
|
|
120
126
|
def setup_session_supported?
|
|
121
127
|
true
|
|
122
128
|
end
|
data/app/models/spree/gateway.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class Gateway < PaymentMethod
|
|
3
|
-
FROM_DOLLAR_TO_CENT_RATE = 100
|
|
3
|
+
FROM_DOLLAR_TO_CENT_RATE = 100
|
|
4
4
|
|
|
5
5
|
delegate :authorize, :purchase, :capture, :void, :credit, to: :provider
|
|
6
6
|
|
|
@@ -31,6 +31,10 @@ module Spree
|
|
|
31
31
|
outer ? outer.underscore : leaf
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
def self.third_party?
|
|
35
|
+
true
|
|
36
|
+
end
|
|
37
|
+
|
|
34
38
|
def payment_source_class
|
|
35
39
|
CreditCard
|
|
36
40
|
end
|
|
@@ -49,7 +53,7 @@ module Spree
|
|
|
49
53
|
end
|
|
50
54
|
|
|
51
55
|
def options
|
|
52
|
-
|
|
56
|
+
preference_values.symbolize_keys
|
|
53
57
|
end
|
|
54
58
|
|
|
55
59
|
def method_missing(method, *args)
|
|
@@ -5,9 +5,13 @@ module Spree
|
|
|
5
5
|
extend DisplayMoney
|
|
6
6
|
include Spree::SingleStoreResource
|
|
7
7
|
include Spree::HasCustomFields
|
|
8
|
+
include Spree::CanonicalDecimals
|
|
9
|
+
|
|
10
|
+
canonical_decimals :amount
|
|
8
11
|
include Spree::Security::GiftCards if defined?(Spree::Security::GiftCards)
|
|
9
12
|
|
|
10
13
|
publishes_lifecycle_events
|
|
14
|
+
publishes_events :canceled, :partially_redeemed, :redeemed
|
|
11
15
|
|
|
12
16
|
#
|
|
13
17
|
# Status
|
|
@@ -35,7 +39,6 @@ module Spree
|
|
|
35
39
|
#
|
|
36
40
|
# Associations
|
|
37
41
|
#
|
|
38
|
-
belongs_to :store, class_name: 'Spree::Store'
|
|
39
42
|
belongs_to :customer, class_name: Spree.customer_class.to_s, optional: true
|
|
40
43
|
include Spree::DeprecatedCustomerAlias
|
|
41
44
|
belongs_to :created_by, class_name: Spree.admin_user_class.to_s, optional: true
|
|
@@ -62,10 +65,12 @@ module Spree
|
|
|
62
65
|
# Ransack
|
|
63
66
|
#
|
|
64
67
|
ransack_alias :state, :status # @deprecated filter alias — removed in 6.1
|
|
65
|
-
self.whitelisted_ransackable_attributes = %w[code customer_id status state gift_card_batch_id created_by_id]
|
|
68
|
+
self.whitelisted_ransackable_attributes = %w[code customer_id status state gift_card_batch_id created_by_id currency expires_at]
|
|
69
|
+
search_by :code
|
|
66
70
|
# `users` is the pre-6.0 name for `customers` — removed in 6.1.
|
|
67
71
|
self.whitelisted_ransackable_associations = %w[customers users orders batch]
|
|
68
72
|
self.whitelisted_ransackable_scopes = %w[active expired redeemed partially_redeemed]
|
|
73
|
+
self.ransackable_scope_types = %w[active expired redeemed partially_redeemed].index_with('boolean')
|
|
69
74
|
|
|
70
75
|
normalizes :code, with: ->(value) { value&.to_s&.squish&.presence }
|
|
71
76
|
|
|
@@ -82,18 +87,23 @@ module Spree
|
|
|
82
87
|
#
|
|
83
88
|
money_methods :amount, :amount_used, :amount_authorized, :amount_remaining
|
|
84
89
|
|
|
85
|
-
# Sets the amount
|
|
86
|
-
# @param amount [String]
|
|
87
|
-
def amount=(amount)
|
|
88
|
-
self[:amount] = Spree::LocalizedNumber.parse(amount)
|
|
89
|
-
end
|
|
90
|
-
|
|
91
90
|
# Calculates the remaining amount
|
|
92
91
|
# @return [Decimal]
|
|
93
92
|
def amount_remaining
|
|
94
93
|
amount - amount_used - amount_authorized
|
|
95
94
|
end
|
|
96
95
|
|
|
96
|
+
# What the card can still give towards an order: nothing once it has
|
|
97
|
+
# expired, been redeemed or been cancelled, and never less than zero,
|
|
98
|
+
# since an admin can lower the amount below what is already in use.
|
|
99
|
+
#
|
|
100
|
+
# @return [BigDecimal]
|
|
101
|
+
def spendable_amount
|
|
102
|
+
return BigDecimal('0') if expired? || redeemed? || canceled?
|
|
103
|
+
|
|
104
|
+
[amount_remaining, 0].max
|
|
105
|
+
end
|
|
106
|
+
|
|
97
107
|
delegate :email, to: :customer, prefix: true, allow_nil: true
|
|
98
108
|
|
|
99
109
|
def self.json_api_columns
|
|
@@ -4,13 +4,15 @@ module Spree
|
|
|
4
4
|
|
|
5
5
|
extend DisplayMoney
|
|
6
6
|
include Spree::SingleStoreResource
|
|
7
|
+
include Spree::CanonicalDecimals
|
|
8
|
+
|
|
9
|
+
canonical_decimals :amount
|
|
7
10
|
|
|
8
11
|
publishes_lifecycle_events
|
|
9
12
|
|
|
10
13
|
#
|
|
11
14
|
# Associations
|
|
12
15
|
#
|
|
13
|
-
belongs_to :store, class_name: 'Spree::Store'
|
|
14
16
|
belongs_to :created_by, class_name: Spree.admin_user_class.to_s, optional: true
|
|
15
17
|
has_many :gift_cards, class_name: 'Spree::GiftCard', inverse_of: :batch, dependent: :destroy
|
|
16
18
|
|
|
@@ -35,10 +37,6 @@ module Spree
|
|
|
35
37
|
|
|
36
38
|
money_methods :amount
|
|
37
39
|
|
|
38
|
-
def amount=(amount)
|
|
39
|
-
self[:amount] = Spree::LocalizedNumber.parse(amount)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
40
|
self.whitelisted_ransackable_attributes = %w[prefix]
|
|
43
41
|
|
|
44
42
|
def generate_gift_cards
|
data/app/models/spree/import.rb
CHANGED
|
@@ -17,6 +17,7 @@ module Spree
|
|
|
17
17
|
'https://raw.githubusercontent.com/spree/spree/refs/tags/v%<version>s/spree/core/db/sample_data'.freeze
|
|
18
18
|
|
|
19
19
|
publishes_lifecycle_events
|
|
20
|
+
publishes_events :completed, :progress
|
|
20
21
|
|
|
21
22
|
# Set event prefix for all Import subclasses
|
|
22
23
|
# This ensures Spree::Imports::Products publishes 'import.create' not 'products.create'
|
|
@@ -54,6 +55,7 @@ module Spree
|
|
|
54
55
|
# Ransack configuration
|
|
55
56
|
#
|
|
56
57
|
self.whitelisted_ransackable_attributes = %w[number type status seller_id]
|
|
58
|
+
search_by :number
|
|
57
59
|
# Lets an operator filter their list by who ran the job — the seller's
|
|
58
60
|
# name, not an id they would have to look up first.
|
|
59
61
|
self.whitelisted_ransackable_associations = %w[seller]
|
|
@@ -71,6 +73,7 @@ module Spree
|
|
|
71
73
|
# Attachments
|
|
72
74
|
#
|
|
73
75
|
has_one_attached :attachment, service: Spree.private_storage_service_name
|
|
76
|
+
signed_id_attachments :attachment
|
|
74
77
|
|
|
75
78
|
#
|
|
76
79
|
# Status
|
|
@@ -86,6 +89,7 @@ module Spree
|
|
|
86
89
|
# Preferences
|
|
87
90
|
#
|
|
88
91
|
preference :delimiter, :string, default: ','
|
|
92
|
+
exposes_preferences :delimiter
|
|
89
93
|
# Run the pipeline in-process instead of enqueuing it. For rake tasks, seeds
|
|
90
94
|
# and the console, where the caller needs the data to exist when the call
|
|
91
95
|
# returns and there may be no worker attached. Never set it from a request:
|
|
@@ -191,12 +195,6 @@ module Spree
|
|
|
191
195
|
Spree.import_retry_failed_rows_workflow.call(import: self).success?
|
|
192
196
|
end
|
|
193
197
|
|
|
194
|
-
# Returns true if the import is in mapping state
|
|
195
|
-
# @return [Boolean]
|
|
196
|
-
def mapping?
|
|
197
|
-
status == 'mapping'
|
|
198
|
-
end
|
|
199
|
-
|
|
200
198
|
# Returns true if the import is processing or completed mapping
|
|
201
199
|
# @return [Boolean]
|
|
202
200
|
def processing?
|
|
@@ -331,7 +329,7 @@ module Spree
|
|
|
331
329
|
# Returns the display name for the import
|
|
332
330
|
# @return [String]
|
|
333
331
|
def display_name
|
|
334
|
-
"#{
|
|
332
|
+
"#{self.class.model_name.human(count: 2)} #{number}"
|
|
335
333
|
end
|
|
336
334
|
|
|
337
335
|
# Returns the headers of the csv file
|
|
@@ -5,7 +5,7 @@ module Spree
|
|
|
5
5
|
#
|
|
6
6
|
# Associations
|
|
7
7
|
#
|
|
8
|
-
belongs_to :import, class_name: 'Spree::Import', inverse_of: :mappings
|
|
8
|
+
belongs_to :import, class_name: 'Spree::Import', inverse_of: :mappings
|
|
9
9
|
|
|
10
10
|
#
|
|
11
11
|
# Validations
|
|
@@ -17,7 +17,6 @@ module Spree
|
|
|
17
17
|
#
|
|
18
18
|
# Scopes
|
|
19
19
|
#
|
|
20
|
-
scope :required, -> { where(schema_field: import.required_fields) }
|
|
21
20
|
scope :mapped, -> { where.not(file_column: [nil, '']) }
|
|
22
21
|
|
|
23
22
|
# Returns true if the mapping is required
|