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
|
@@ -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)
|
|
@@ -14,11 +14,13 @@ module Spree
|
|
|
14
14
|
hooks :validate, :before_capture, :after_capture
|
|
15
15
|
|
|
16
16
|
# @param payment [Spree::Payment] a completed payment is a no-op
|
|
17
|
-
# @param amount [
|
|
18
|
-
# a smaller amount splits the remainder into a new
|
|
17
|
+
# @param amount [BigDecimal, nil] in the currency's own units; nil
|
|
18
|
+
# captures in full, a smaller amount splits the remainder into a new
|
|
19
|
+
# pending payment. An Integer is read as hundredths of the currency,
|
|
20
|
+
# the pre-6.0 contract (deprecated, removed in 6.1).
|
|
19
21
|
def perform(payment:, amount: nil)
|
|
20
22
|
super
|
|
21
|
-
@amount = amount
|
|
23
|
+
@amount = capture_amount(amount)
|
|
22
24
|
|
|
23
25
|
step :ensure_capturable
|
|
24
26
|
# Veto point — fraud holds, manual review. Before any money moves.
|
|
@@ -44,6 +46,17 @@ module Spree
|
|
|
44
46
|
|
|
45
47
|
attr_reader :response, :remainder
|
|
46
48
|
|
|
49
|
+
def capture_amount(amount)
|
|
50
|
+
return payment.amount if amount.nil?
|
|
51
|
+
return Spree::Money::Rounding.to_currency(amount, payment.currency) unless amount.is_a?(Integer)
|
|
52
|
+
|
|
53
|
+
Spree::Deprecation.warn(
|
|
54
|
+
'Passing an Integer amount to the payment capture workflow is deprecated and is read as hundredths of ' \
|
|
55
|
+
'the currency. Pass the amount in the currency\'s own units as a BigDecimal; removed in Spree 6.1.'
|
|
56
|
+
)
|
|
57
|
+
Spree::Money::Rounding.from_hundredths(amount)
|
|
58
|
+
end
|
|
59
|
+
|
|
47
60
|
# An already-captured payment returns success rather than failing:
|
|
48
61
|
# capture is naturally idempotent and double-submitted admin actions
|
|
49
62
|
# must not surface as errors. A failed payment is capturable — the
|
|
@@ -65,7 +78,9 @@ module Spree
|
|
|
65
78
|
def capture_at_gateway
|
|
66
79
|
@response = payment.protect_from_connection_error do
|
|
67
80
|
instrument_gateway_call(:capture, payment.payment_method) do
|
|
68
|
-
payment.payment_method.capture(
|
|
81
|
+
payment.payment_method.capture(
|
|
82
|
+
payment.payment_method.gateway_amount(@amount, payment.currency), payment.response_code, payment.gateway_options
|
|
83
|
+
)
|
|
69
84
|
end
|
|
70
85
|
end
|
|
71
86
|
|
|
@@ -86,7 +101,7 @@ module Spree
|
|
|
86
101
|
if Spree::Payment.where(id: payment.id, status: 'completed').exists?
|
|
87
102
|
already_captured = true
|
|
88
103
|
else
|
|
89
|
-
payment.capture_events.create!(amount:
|
|
104
|
+
payment.capture_events.create!(amount: @amount)
|
|
90
105
|
# Split before completing, so payment.completed publishes with
|
|
91
106
|
# the captured amount and the order recomputes from correct rows.
|
|
92
107
|
@remainder = payment.split_uncaptured_amount
|
|
@@ -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
|
|
|
@@ -57,7 +57,9 @@ module Spree
|
|
|
57
57
|
|
|
58
58
|
response = payment.protect_from_connection_error do
|
|
59
59
|
instrument_gateway_call(verb, payment.payment_method) do
|
|
60
|
-
payment.payment_method.public_send(
|
|
60
|
+
payment.payment_method.public_send(
|
|
61
|
+
verb, payment.payment_method.gateway_amount(payment.amount, payment.currency), payment.source, payment.gateway_options
|
|
62
|
+
)
|
|
61
63
|
end
|
|
62
64
|
end
|
|
63
65
|
|
|
@@ -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
|
|
@@ -61,7 +61,9 @@ module Spree
|
|
|
61
61
|
unless result.success?
|
|
62
62
|
refusal = result.error&.value
|
|
63
63
|
refusal = {} unless refusal.is_a?(Hash)
|
|
64
|
-
if refusal[:
|
|
64
|
+
if refusal[:malformed_amounts].present?
|
|
65
|
+
price_list.errors.add(:base, :malformed_price)
|
|
66
|
+
elsif refusal[:invalid_amounts].present?
|
|
65
67
|
price_list.errors.add(:base, :negative_price)
|
|
66
68
|
elsif refusal[:invalid_quantities].present?
|
|
67
69
|
price_list.errors.add(:base, :invalid_quantity)
|
|
@@ -76,12 +78,10 @@ module Spree
|
|
|
76
78
|
end
|
|
77
79
|
return failure(price_list)
|
|
78
80
|
end
|
|
79
|
-
|
|
80
|
-
touch_variants(rows.map { |row| row[:variant_id] }.uniq)
|
|
81
81
|
end
|
|
82
82
|
|
|
83
83
|
def clear_prices
|
|
84
|
-
variant_ids = price_list.prices.distinct.pluck(:variant_id)
|
|
84
|
+
variant_ids = price_list.prices.where.not(amount: nil).distinct.pluck(:variant_id)
|
|
85
85
|
price_list.prices.update_all(amount: nil, compare_at_amount: nil, updated_at: Time.current)
|
|
86
86
|
touch_variants(variant_ids)
|
|
87
87
|
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
|
|
@@ -19,9 +19,10 @@ module Spree
|
|
|
19
19
|
# @param expected_at [Date, nil]
|
|
20
20
|
# @param reference [String, nil] the supplier's own order number
|
|
21
21
|
# @param notes [String, nil]
|
|
22
|
+
# @param metadata [Hash, nil]
|
|
22
23
|
# @param created_by [Object, nil]
|
|
23
24
|
def perform(store:, supplier:, destination_location:, items: [], currency: nil,
|
|
24
|
-
expected_at: nil, cancel_by: nil, reference: nil, notes: nil, created_by: nil)
|
|
25
|
+
expected_at: nil, cancel_by: nil, reference: nil, notes: nil, metadata: nil, created_by: nil)
|
|
25
26
|
super
|
|
26
27
|
|
|
27
28
|
step :build_purchase_order
|
|
@@ -50,6 +51,7 @@ module Spree
|
|
|
50
51
|
created_by: created_by,
|
|
51
52
|
status: Spree::PurchaseOrder.default_status
|
|
52
53
|
)
|
|
54
|
+
@purchase_order.metadata = metadata if metadata
|
|
53
55
|
|
|
54
56
|
Array(items).each do |item|
|
|
55
57
|
@purchase_order.items.build(
|
|
@@ -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
|