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
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
module Fulfillments
|
|
5
|
+
# Sends replacement goods for an exchange or a claim.
|
|
6
|
+
#
|
|
7
|
+
# Replacement units hang off the line they replace but are flagged, so an
|
|
8
|
+
# edit of that line counts only what the customer bought — otherwise the
|
|
9
|
+
# replacement reads as a unit the line already holds, and raising the
|
|
10
|
+
# quantity adds nothing.
|
|
11
|
+
module Replacements
|
|
12
|
+
extend ActiveSupport::Concern
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def build_replacements(record, items)
|
|
17
|
+
order = record.order
|
|
18
|
+
|
|
19
|
+
# By id, not through the association writers: with has_many inversing
|
|
20
|
+
# each writer adds the template to its owner's collection, and the
|
|
21
|
+
# owner's next save persists it beside the packed copy.
|
|
22
|
+
units = items.map do |item|
|
|
23
|
+
Spree::FulfillmentItem.new(
|
|
24
|
+
order_id: order.id,
|
|
25
|
+
line_item_id: item[:line_item].id,
|
|
26
|
+
variant_id: item[:variant].id,
|
|
27
|
+
quantity: item[:quantity],
|
|
28
|
+
status: 'on_hand',
|
|
29
|
+
replacement: true
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
fulfillments = Spree::Stock::Coordinator.new(order, units).fulfillments
|
|
34
|
+
if fulfillments.flat_map(&:fulfillment_items).sum(&:quantity) != units.sum(&:quantity)
|
|
35
|
+
failure(record, :replacement_out_of_stock)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
order.fulfillments += fulfillments
|
|
39
|
+
order.save!
|
|
40
|
+
fulfillments.each { |fulfillment| allocate_replacement_stock(fulfillment) }
|
|
41
|
+
fulfillments
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# The replacement is promised the moment it exists, exactly as placement
|
|
45
|
+
# promises an order's own fulfillments. Without this the fulfillment holds
|
|
46
|
+
# nothing, and dispatch then writes no movement at all — an unallocated
|
|
47
|
+
# fulfillment is indistinguishable from one created before typed
|
|
48
|
+
# movements, so the goods would leave the shelf untouched and unrecorded.
|
|
49
|
+
def allocate_replacement_stock(fulfillment)
|
|
50
|
+
fulfillment.manifest.each do |item|
|
|
51
|
+
next unless item.variant.track_inventory?
|
|
52
|
+
next unless item.quantity.positive?
|
|
53
|
+
|
|
54
|
+
fulfillment.stock_location.allocate(item.variant, item.quantity, fulfillment)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -185,7 +185,7 @@ module Spree
|
|
|
185
185
|
end
|
|
186
186
|
|
|
187
187
|
def amount
|
|
188
|
-
@amount ||= [gift_card.
|
|
188
|
+
@amount ||= [gift_card.spendable_amount, order.total].min
|
|
189
189
|
end
|
|
190
190
|
|
|
191
191
|
def issue_store_credit
|
|
@@ -224,7 +224,7 @@ module Spree
|
|
|
224
224
|
payment_method = order.store.payment_methods.find_or_initialize_by(
|
|
225
225
|
type: 'Spree::PaymentMethod::StoreCredit'
|
|
226
226
|
)
|
|
227
|
-
payment_method.name ||=
|
|
227
|
+
payment_method.name ||= I18n.t('spree.store_credit_name')
|
|
228
228
|
payment_method.active = true
|
|
229
229
|
payment_method.save! if payment_method.new_record?
|
|
230
230
|
payment_method
|
|
@@ -5,7 +5,11 @@ module Spree
|
|
|
5
5
|
# behavior can diverge without branching one implementation.
|
|
6
6
|
class AddItem < Spree::Carts::AddItem
|
|
7
7
|
def perform(order:, **rest)
|
|
8
|
-
super(cart: order, **rest)
|
|
8
|
+
result = super(cart: order, **rest)
|
|
9
|
+
# Placed orders take items through here too, and their payment
|
|
10
|
+
# status is measured against the total that just moved.
|
|
11
|
+
order.update_statuses!
|
|
12
|
+
result
|
|
9
13
|
end
|
|
10
14
|
end
|
|
11
15
|
end
|
|
@@ -63,7 +63,7 @@ module Spree
|
|
|
63
63
|
external_step :void_tax
|
|
64
64
|
step :recompute_totals, with: -> { Spree.order_recalculate_totals_workflow }
|
|
65
65
|
step :update_statuses, with: -> { Spree.order_update_statuses_service }
|
|
66
|
-
order.publish_event('order.canceled',
|
|
66
|
+
order.publish_event('order.canceled', nil, notify_customer: notify_customer)
|
|
67
67
|
success(order.reload)
|
|
68
68
|
rescue ActiveRecord::RecordInvalid
|
|
69
69
|
failure(order)
|
|
@@ -74,7 +74,7 @@ module Spree
|
|
|
74
74
|
def ensure_cancellable
|
|
75
75
|
return if order.allow_cancel?
|
|
76
76
|
|
|
77
|
-
order.errors.add(:base, :not_cancellable, message:
|
|
77
|
+
order.errors.add(:base, :not_cancellable, message: I18n.t('spree.errors.messages.not_cancellable'))
|
|
78
78
|
failure(order)
|
|
79
79
|
end
|
|
80
80
|
|
|
@@ -86,7 +86,7 @@ module Spree
|
|
|
86
86
|
def ensure_refund_amount_is_settleable
|
|
87
87
|
return if refund_amount.blank? || order.grouped?
|
|
88
88
|
|
|
89
|
-
order.errors.add(:base, :refund_amount_requires_shared_payment, message:
|
|
89
|
+
order.errors.add(:base, :refund_amount_requires_shared_payment, message: I18n.t('spree.errors.messages.refund_amount_requires_shared_payment'))
|
|
90
90
|
failure(order)
|
|
91
91
|
end
|
|
92
92
|
|
|
@@ -52,6 +52,7 @@ module Spree
|
|
|
52
52
|
|
|
53
53
|
step :ensure_placed_status
|
|
54
54
|
step :release_stock_reservations
|
|
55
|
+
step :cancel_unused_payment_sessions
|
|
55
56
|
step :update_statuses
|
|
56
57
|
step :publish_order_placed
|
|
57
58
|
step :complete_sibling_orders
|
|
@@ -69,7 +70,7 @@ module Spree
|
|
|
69
70
|
order.process_payments! unless payment_covered?
|
|
70
71
|
|
|
71
72
|
failure(order, order.errors.full_messages.to_sentence) if order.errors.any?
|
|
72
|
-
failure(order,
|
|
73
|
+
failure(order, I18n.t('spree.payment_processing_failed')) unless payment_covered?
|
|
73
74
|
end
|
|
74
75
|
|
|
75
76
|
# Files the sale under whoever made it, dividing the order into one per
|
|
@@ -212,6 +213,15 @@ module Spree
|
|
|
212
213
|
Spree::StockReservations::Release.call(owner: order)
|
|
213
214
|
end
|
|
214
215
|
|
|
216
|
+
# A session left behind by a switched method or a second tab could still
|
|
217
|
+
# be paid, charging the buyer twice. One provider call per session, so
|
|
218
|
+
# it runs in a job rather than holding up placement.
|
|
219
|
+
def cancel_unused_payment_sessions
|
|
220
|
+
return unless order.payment_sessions.unused.exists?
|
|
221
|
+
|
|
222
|
+
Spree::Payments::CancelUnusedSessionsJob.perform_later(order.id)
|
|
223
|
+
end
|
|
224
|
+
|
|
215
225
|
def update_statuses
|
|
216
226
|
Spree::Orders::UpdateStatuses.call(order: order)
|
|
217
227
|
end
|
|
@@ -221,9 +231,10 @@ module Spree
|
|
|
221
231
|
# order.completed is a one-release alias for 5.x webhook consumers;
|
|
222
232
|
# wildcard subscribers dedupe on the metadata marker.
|
|
223
233
|
def publish_order_placed
|
|
224
|
-
|
|
225
|
-
order.
|
|
226
|
-
order.publish_event('order.
|
|
234
|
+
metadata = { notify_customer: order.notify_customer }
|
|
235
|
+
payload = order.event_payload
|
|
236
|
+
order.publish_event('order.placed', payload, metadata)
|
|
237
|
+
order.publish_event('order.completed', payload, metadata.merge(deprecated_alias_of: 'order.placed'))
|
|
227
238
|
end
|
|
228
239
|
|
|
229
240
|
# Places the orders the division produced beside this one.
|
|
@@ -246,10 +257,7 @@ module Spree
|
|
|
246
257
|
|
|
247
258
|
return unless order_group.orders.all?(&:placed?)
|
|
248
259
|
|
|
249
|
-
order_group.publish_event(
|
|
250
|
-
'order_group.completed',
|
|
251
|
-
order_group.event_payload.merge(notify_customer: @notify_customer_of_purchase)
|
|
252
|
-
)
|
|
260
|
+
order_group.publish_event('order_group.completed', nil, notify_customer: @notify_customer_of_purchase)
|
|
253
261
|
end
|
|
254
262
|
|
|
255
263
|
def place_sibling(sibling)
|
|
@@ -36,11 +36,11 @@ module Spree
|
|
|
36
36
|
halt!(payment) if payment.processing?
|
|
37
37
|
return unless payment.payment_method&.source_required?
|
|
38
38
|
|
|
39
|
-
failure(payment,
|
|
39
|
+
failure(payment, I18n.t('spree.payment_processing_failed')) if payment.source.blank?
|
|
40
40
|
|
|
41
41
|
unless payment.payment_method.supports?(payment.source) || payment.token_based?
|
|
42
42
|
payment.invalidate!
|
|
43
|
-
failure(payment,
|
|
43
|
+
failure(payment, I18n.t('spree.payment_method_not_supported'))
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
46
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module PostSale
|
|
3
|
+
# Approval shared by returns, exchanges and claims. The including
|
|
4
|
+
# workflow names the record it approves (`post_sale_record`) and the
|
|
5
|
+
# status that record must be in (`approvable_status`).
|
|
6
|
+
module Approval
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
def approve
|
|
10
|
+
step :ensure_approvable
|
|
11
|
+
run_hooks :validate
|
|
12
|
+
|
|
13
|
+
ApplicationRecord.transaction do
|
|
14
|
+
step :mark_approved
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
run_hooks :after_approve
|
|
18
|
+
post_sale_record.publish_event("#{post_sale_record.event_prefix}.approved")
|
|
19
|
+
success(post_sale_record.reload)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def ensure_approvable
|
|
23
|
+
failure(post_sale_record, :"not_#{approvable_status}") unless post_sale_record.status == approvable_status
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def mark_approved
|
|
27
|
+
post_sale_record.update!(
|
|
28
|
+
status: 'approved',
|
|
29
|
+
approved_at: Time.current,
|
|
30
|
+
created_by: post_sale_record.created_by || approver
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module PostSale
|
|
3
|
+
# Cancellation shared by returns, exchanges and claims. The including
|
|
4
|
+
# workflow names the record it cancels (`post_sale_record`) and the
|
|
5
|
+
# statuses it may be cancelled from (`cancellable_statuses`). A block
|
|
6
|
+
# runs after the cancellation commits, for work outside the database.
|
|
7
|
+
module Cancellation
|
|
8
|
+
include Spree::Refunds::TaxCredit
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def cancel
|
|
13
|
+
step :ensure_cancellable
|
|
14
|
+
run_hooks :validate
|
|
15
|
+
|
|
16
|
+
ApplicationRecord.transaction do
|
|
17
|
+
step :mark_canceled
|
|
18
|
+
step :clear_tax
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
yield if block_given?
|
|
22
|
+
|
|
23
|
+
run_hooks :after_cancel
|
|
24
|
+
post_sale_record.publish_event("#{post_sale_record.event_prefix}.canceled")
|
|
25
|
+
success(post_sale_record.reload)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def ensure_cancellable
|
|
29
|
+
return if post_sale_record.status.in?(cancellable_statuses)
|
|
30
|
+
|
|
31
|
+
failure(post_sale_record, :not_cancellable)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def mark_canceled
|
|
35
|
+
memo = [post_sale_record.memo, reason].compact_blank.join("\n")
|
|
36
|
+
post_sale_record.update!(status: 'canceled', canceled_at: Time.current, memo: memo.presence)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def clear_tax
|
|
40
|
+
clear_tax_credit(post_sale_record)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module PostSale
|
|
3
|
+
# Records what the warehouse actually received for a return or an
|
|
4
|
+
# exchange. The including workflow names the record (`post_sale_record`);
|
|
5
|
+
# its lines, the item key callers pass (`return_line_item:` or
|
|
6
|
+
# `exchange_line_item:`) and the error codes follow from the record's
|
|
7
|
+
# event prefix. `restock_variant` says which variant a line puts back.
|
|
8
|
+
#
|
|
9
|
+
# Partial and damaged receipt is the normal case, not an edge case: the
|
|
10
|
+
# customer said three items were coming, two arrived, one of those is not
|
|
11
|
+
# resellable. Quantities and resellable flags therefore come from the
|
|
12
|
+
# caller rather than from the request.
|
|
13
|
+
module Receipt
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def receive
|
|
17
|
+
step :ensure_receivable
|
|
18
|
+
step :normalize_items
|
|
19
|
+
run_hooks :validate
|
|
20
|
+
|
|
21
|
+
ApplicationRecord.transaction do
|
|
22
|
+
step :record_receipt
|
|
23
|
+
run_hooks :before_restock
|
|
24
|
+
step :restock_resellable_items
|
|
25
|
+
step :mark_received
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
run_hooks :after_receive
|
|
29
|
+
post_sale_record.publish_event("#{post_sale_kind}.received")
|
|
30
|
+
success(post_sale_record.reload)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def post_sale_kind
|
|
34
|
+
post_sale_record.event_prefix
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def restock_variant(line)
|
|
38
|
+
line.variant
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def ensure_receivable
|
|
42
|
+
failure(post_sale_record, :not_approved) unless post_sale_record.approved?
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def normalize_items
|
|
46
|
+
@normalized_items =
|
|
47
|
+
if items.nil?
|
|
48
|
+
post_sale_record.public_send(:"#{post_sale_kind}_line_items").map do |line|
|
|
49
|
+
{ line: line, quantity: line.quantity, resellable: true }
|
|
50
|
+
end
|
|
51
|
+
else
|
|
52
|
+
items.map { |item| normalize_item(item) }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
failure(post_sale_record, :no_items_received) if @normalized_items.sum { |item| item[:quantity] }.zero?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def normalize_item(item)
|
|
59
|
+
line = item[:"#{post_sale_kind}_line_item"]
|
|
60
|
+
quantity = item[:quantity].to_i
|
|
61
|
+
|
|
62
|
+
unless line&.public_send(:"#{post_sale_kind}_id") == post_sale_record.id
|
|
63
|
+
failure(post_sale_record, :"item_not_on_#{post_sale_kind}")
|
|
64
|
+
end
|
|
65
|
+
failure(post_sale_record, :invalid_quantity) if quantity.negative? || quantity > line.quantity
|
|
66
|
+
|
|
67
|
+
{ line: line, quantity: quantity, resellable: item.fetch(:resellable, true) }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def record_receipt
|
|
71
|
+
@normalized_items.each do |item|
|
|
72
|
+
item[:line].update!(received_quantity: item[:quantity], resellable: item[:resellable])
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Only resellable goods go back into sellable stock — a damaged item
|
|
77
|
+
# is received but never restocked.
|
|
78
|
+
def restock_resellable_items
|
|
79
|
+
@normalized_items.each do |item|
|
|
80
|
+
next unless item[:resellable]
|
|
81
|
+
next unless item[:quantity].positive?
|
|
82
|
+
|
|
83
|
+
post_sale_record.stock_location.restock(restock_variant(item[:line]), item[:quantity], post_sale_record)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def mark_received
|
|
88
|
+
post_sale_record.update!(status: 'received', received_at: Time.current)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -228,7 +228,7 @@ module Spree
|
|
|
228
228
|
# it rather than attaching it wrongly.
|
|
229
229
|
blob = ActiveStorage::Blob.find_signed(signed_id)
|
|
230
230
|
unless blob && blob.service_name.to_s == Spree.private_storage_service_name.to_s
|
|
231
|
-
asset.errors.add(:attachment, :digital_assets_attachment_must_be_private, message:
|
|
231
|
+
asset.errors.add(:attachment, :digital_assets_attachment_must_be_private, message: I18n.t('spree.digital_assets_attachment_must_be_private'))
|
|
232
232
|
raise ActiveRecord::RecordInvalid.new(asset)
|
|
233
233
|
end
|
|
234
234
|
|
|
@@ -40,7 +40,7 @@ module Spree
|
|
|
40
40
|
def ensure_cancelable
|
|
41
41
|
return unless purchase_order.closed?
|
|
42
42
|
|
|
43
|
-
failure(purchase_order,
|
|
43
|
+
failure(purchase_order, I18n.t('spree.purchase_order.errors.already_closed'))
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def uncount_awaited_units
|
|
@@ -8,7 +8,7 @@ module Spree
|
|
|
8
8
|
# lets the outstanding count stand on each line as the record of the gap.
|
|
9
9
|
# No stock moves — the units were never here.
|
|
10
10
|
class Close < Spree::Workflow
|
|
11
|
-
include Spree::Receivables::
|
|
11
|
+
include Spree::Receivables::ClosingShort
|
|
12
12
|
|
|
13
13
|
hooks :validate, :after_close
|
|
14
14
|
|
|
@@ -18,40 +18,12 @@ module Spree
|
|
|
18
18
|
# @param reason [String, nil] why the balance is not expected
|
|
19
19
|
def perform(purchase_order:, reason: nil)
|
|
20
20
|
super
|
|
21
|
-
|
|
22
|
-
purchase_order.with_lock do
|
|
23
|
-
step :ensure_closable
|
|
24
|
-
run_hooks :validate
|
|
25
|
-
step :uncount_awaited_units
|
|
26
|
-
step :close_short
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
run_hooks :after_close
|
|
30
|
-
purchase_order.publish_event('purchase_order.received')
|
|
31
|
-
success(purchase_order.reload)
|
|
21
|
+
close
|
|
32
22
|
end
|
|
33
23
|
|
|
34
24
|
private
|
|
35
25
|
|
|
36
|
-
def
|
|
37
|
-
return if purchase_order.partially_received?
|
|
38
|
-
|
|
39
|
-
failure(purchase_order, Spree.t('purchase_order.errors.not_partially_received'))
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# The merchant has just said the balance is not coming, so it leaves
|
|
43
|
-
# the destination's incoming figure; the outstanding count on each line
|
|
44
|
-
# keeps the record of what never arrived.
|
|
45
|
-
def uncount_awaited_units
|
|
46
|
-
uncount_incoming(purchase_order)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def close_short
|
|
50
|
-
now = Time.current
|
|
51
|
-
attributes = { status: 'received', received_at: now, closed_short_at: now, close_reason: reason.presence }
|
|
52
|
-
|
|
53
|
-
failure(purchase_order) unless purchase_order.update(attributes)
|
|
54
|
-
end
|
|
26
|
+
def receivable = purchase_order
|
|
55
27
|
end
|
|
56
28
|
end
|
|
57
29
|
end
|
|
@@ -32,8 +32,8 @@ module Spree
|
|
|
32
32
|
private
|
|
33
33
|
|
|
34
34
|
def ensure_returnable
|
|
35
|
-
failure(purchase_order,
|
|
36
|
-
failure(purchase_order,
|
|
35
|
+
failure(purchase_order, I18n.t('spree.purchase_order.errors.already_receiving')) if purchase_order.stock_receipts.exists?
|
|
36
|
+
failure(purchase_order, I18n.t('spree.purchase_order.errors.not_ordered_for_draft')) unless purchase_order.ordered?
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
# Nothing has been received, so this is every unit the order placed.
|
|
@@ -32,8 +32,8 @@ module Spree
|
|
|
32
32
|
private
|
|
33
33
|
|
|
34
34
|
def ensure_draft
|
|
35
|
-
failure(purchase_order,
|
|
36
|
-
failure(purchase_order,
|
|
35
|
+
failure(purchase_order, I18n.t('spree.purchase_order.errors.not_draft')) unless purchase_order.draft?
|
|
36
|
+
failure(purchase_order, I18n.t('spree.purchase_order.errors.must_have_variant')) if purchase_order.items.empty?
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def mark_ordered
|
|
@@ -50,7 +50,7 @@ module Spree
|
|
|
50
50
|
def ensure_receivable
|
|
51
51
|
return if purchase_order.ordered? || purchase_order.partially_received?
|
|
52
52
|
|
|
53
|
-
failure(purchase_order,
|
|
53
|
+
failure(purchase_order, I18n.t('spree.purchase_order.errors.not_ordered'))
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
def line_belongs?(line)
|
|
@@ -4,6 +4,8 @@ module Spree
|
|
|
4
4
|
# ordered is a matter of record between two businesses — so this refuses
|
|
5
5
|
# anything past `draft`.
|
|
6
6
|
class Update < Spree::Workflow
|
|
7
|
+
include Spree::Receivables::DraftEditing
|
|
8
|
+
|
|
7
9
|
hooks :validate, :after_update
|
|
8
10
|
|
|
9
11
|
# @param purchase_order [Spree::PurchaseOrder]
|
|
@@ -13,44 +15,13 @@ module Spree
|
|
|
13
15
|
# unit_cost: }]` replacing the current lines; nil leaves them alone
|
|
14
16
|
def perform(purchase_order:, attributes: {}, items: nil)
|
|
15
17
|
super
|
|
16
|
-
|
|
17
|
-
step :ensure_editable
|
|
18
|
-
run_hooks :validate
|
|
19
|
-
|
|
20
|
-
ApplicationRecord.transaction do
|
|
21
|
-
step :apply_changes
|
|
22
|
-
step :save_purchase_order
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
run_hooks :after_update
|
|
26
|
-
success(purchase_order.reload)
|
|
18
|
+
edit
|
|
27
19
|
end
|
|
28
20
|
|
|
29
21
|
private
|
|
30
22
|
|
|
31
|
-
def
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
failure(purchase_order, Spree.t('purchase_order.errors.not_editable'))
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def apply_changes
|
|
38
|
-
purchase_order.assign_attributes(attributes) if attributes.present?
|
|
39
|
-
return if items.nil?
|
|
40
|
-
|
|
41
|
-
purchase_order.items.destroy_all
|
|
42
|
-
Array(items).each do |item|
|
|
43
|
-
purchase_order.items.build(
|
|
44
|
-
variant: item[:variant],
|
|
45
|
-
quantity_ordered: item[:quantity_ordered],
|
|
46
|
-
unit_cost: item[:unit_cost]
|
|
47
|
-
)
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def save_purchase_order
|
|
52
|
-
failure(purchase_order) unless purchase_order.save
|
|
53
|
-
end
|
|
23
|
+
def receivable = purchase_order
|
|
24
|
+
def item_attributes = %i[quantity_ordered unit_cost]
|
|
54
25
|
end
|
|
55
26
|
end
|
|
56
27
|
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Receivables
|
|
3
|
+
# Ends a purchase order or transfer whose missing units are not going to
|
|
4
|
+
# turn up. Nothing is written to any shelf: closing short keeps what was
|
|
5
|
+
# received, records why the rest never arrived, and leaves the outstanding
|
|
6
|
+
# count on each line as the record of the gap. The including workflow
|
|
7
|
+
# names the document (`receivable`).
|
|
8
|
+
module ClosingShort
|
|
9
|
+
include IncomingCounter
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def close
|
|
14
|
+
receivable.with_lock do
|
|
15
|
+
step :ensure_closable
|
|
16
|
+
run_hooks :validate
|
|
17
|
+
step :uncount_awaited_units
|
|
18
|
+
step :close_short
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
run_hooks :after_close
|
|
22
|
+
receivable.publish_event("#{receivable.event_prefix}.received")
|
|
23
|
+
success(receivable.reload)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def ensure_closable
|
|
27
|
+
return if receivable.partially_received?
|
|
28
|
+
|
|
29
|
+
failure(receivable, I18n.t("spree.#{receivable.event_prefix}.errors.not_partially_received"))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# The balance is not coming, so it leaves the destination's incoming
|
|
33
|
+
# figure; each line's outstanding count keeps the record.
|
|
34
|
+
def uncount_awaited_units
|
|
35
|
+
uncount_incoming(receivable)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def close_short
|
|
39
|
+
now = Time.current
|
|
40
|
+
attributes = { status: 'received', received_at: now, closed_short_at: now, close_reason: reason.presence }
|
|
41
|
+
|
|
42
|
+
failure(receivable) unless receivable.update(attributes)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Receivables
|
|
3
|
+
# Edits a draft purchase order or transfer. Past `draft` the document is a
|
|
4
|
+
# matter of record, so the edit is refused rather than quietly rewriting
|
|
5
|
+
# something a supplier or warehouse is already acting on. The including
|
|
6
|
+
# workflow names the document (`receivable`) and the line columns callers
|
|
7
|
+
# may set (`item_attributes`).
|
|
8
|
+
module DraftEditing
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def edit
|
|
12
|
+
step :ensure_editable
|
|
13
|
+
run_hooks :validate
|
|
14
|
+
|
|
15
|
+
ApplicationRecord.transaction do
|
|
16
|
+
step :apply_changes
|
|
17
|
+
step :save_document
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
run_hooks :after_update
|
|
21
|
+
success(receivable.reload)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def ensure_editable
|
|
25
|
+
return if receivable.editable?
|
|
26
|
+
|
|
27
|
+
failure(receivable, I18n.t("spree.#{receivable.event_prefix}.errors.not_editable"))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# A whole-list replacement rather than a per-line diff: a draft's lines
|
|
31
|
+
# are what the merchant is still deciding, and sending the list they
|
|
32
|
+
# want is simpler for a client than working out which rows to delete.
|
|
33
|
+
def apply_changes
|
|
34
|
+
receivable.assign_attributes(attributes) if attributes.present?
|
|
35
|
+
return if items.nil?
|
|
36
|
+
|
|
37
|
+
receivable.items.destroy_all
|
|
38
|
+
Array(items).each do |item|
|
|
39
|
+
receivable.items.build(variant: item[:variant], **item_attributes.index_with { |key| item[key] })
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def save_document
|
|
44
|
+
failure(receivable) unless receivable.save
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -26,7 +26,9 @@ module Spree
|
|
|
26
26
|
# Required only when the payment is shared by a split checkout, where
|
|
27
27
|
# it covers several orders and the payment cannot say which one this
|
|
28
28
|
# refund is for; otherwise the payment's own order is taken.
|
|
29
|
-
|
|
29
|
+
# @param tax_amount [BigDecimal, Numeric] the tax inside +amount+, when
|
|
30
|
+
# what is being refunded carried tax (see Spree::Refund#tax_amount)
|
|
31
|
+
def perform(payment:, amount: nil, reason: nil, refunder: nil, originator: nil, order: nil, tax_amount: 0)
|
|
30
32
|
super
|
|
31
33
|
|
|
32
34
|
step :ensure_refundable
|
|
@@ -96,7 +98,8 @@ module Spree
|
|
|
96
98
|
order: order || payment.order,
|
|
97
99
|
reason: reason || Spree::RefundReason.return_processing_reason(refund_store),
|
|
98
100
|
refunder: refunder,
|
|
99
|
-
originator: originator
|
|
101
|
+
originator: originator,
|
|
102
|
+
tax_amount: tax_amount
|
|
100
103
|
)
|
|
101
104
|
end
|
|
102
105
|
end
|