Sales / Shipping / Payment Coupling Report¶
Modules Scanned¶
Sales family: - Sales, SalesAnalytics, SalesInventory, SalesRule, SalesSequence
Shipping family: - Shipping, Dhl, Fedex, Ups, Usps, OfflineShipping
Payment family: - Payment, Paypal, Vault, OfflinePayments
Direction 1: Sales → Shipping/Payment¶
Sales Module¶
Payment coupling (14+ PHP imports):
| File | Classes Imported |
|---|---|
Block/Adminhtml/Order/Payment.php |
Payment\Model\Info |
Block/Order/Info.php |
Payment\Helper\Data |
Ui/Component/Listing/Column/PaymentMethod.php |
Payment\Helper\Data |
Model/AdminOrder/Create.php |
Payment\Model\Checks\SpecificationFactory, Payment\Model\MethodInterface |
Model/Order/Payment.php |
Payment\Model\SaleOperationInterface |
Model/OrderRepository.php |
Payment\Api\Data\PaymentAdditionalInfoInterface, PaymentAdditionalInfoInterfaceFactory |
Model/Order/Invoice/Validation/CanRefund.php |
Payment\Model\InfoInterface, Payment\Model\MethodInterface, hardcoded Payment\Model\Method\Free |
Model/Order/Payment/Info.php |
Payment\Model\Method\Substitution, Payment\Model\InfoInterface |
Model/Order/Email/Sender/InvoiceSender.php |
Payment\Helper\Data |
Model/Order/Email/Sender/CreditmemoSender.php |
Payment\Helper\Data |
Model/Order/Email/Sender/OrderSender.php |
Payment\Helper\Data |
Model/Order/Email/Sender/ShipmentSender.php |
Payment\Helper\Data |
Model/Order/Shipment/Sender/EmailSender.php |
Payment\Helper\Data |
Model/Service/OrderService.php |
Payment\Gateway\Command\CommandException |
Controller/Adminhtml/Order/Create/Save.php |
Payment\Model\Method\AbstractMethod constants |
DI config: 6 Payment\Model\Checks\* classes in etc/di.xml, Payment\Model\MethodInterface constants in etc/adminhtml/di.xml
Shipping coupling (3 PHP imports):
| File | Classes Imported |
|---|---|
Block/DataProviders/Email/Shipment/TrackingUrl.php |
Shipping\Helper\Data |
Block/Adminhtml/Order/AbstractOrder.php |
Shipping\Helper\Data |
Model/Service/ShipmentService.php |
Shipping\Model\ShipmentNotifier |
Dependencies:
- composer.json: hard require on both magento/module-payment and magento/module-shipping
- module.xml: <sequence> includes Magento_Payment
SalesRule Module¶
- composer.json: hard require on both
magento/module-paymentandmagento/module-shipping - No direct PHP use statements from Payment/Shipping in production code
- Uses shipping/payment through configuration and indirect references
SalesAnalytics, SalesInventory, SalesSequence¶
- No dependencies on Shipping or Payment modules
Direction 2: Shipping → Sales¶
Shipping Module — HEAVY (26 PHP imports, 11 XML refs)¶
| File | # Imports | Sales Classes Used |
|---|---|---|
Controller/Adminhtml/Order/ShipmentLoader.php |
7 | ShipmentTrackCreationInterface, ShipmentTrackCreationInterfaceFactory, ShipmentItemCreationInterfaceFactory, ShipmentRepositoryInterface, OrderRepositoryInterface, ShipmentDocumentFactory, ShipmentItemCreationInterface |
Controller/Adminhtml/Order/Shipment/Save.php |
2 | Sales\Helper\Data, Shipment\Validation\QuantityValidator |
Controller/Adminhtml/Order/Shipment/MassPrintShippingLabel.php |
2 | Shipment\CollectionFactory, Order\CollectionFactory |
Controller/Adminhtml/Order/Shipment/AddTrack.php |
2 | ShipmentTrackInterfaceFactory, ShipmentRepositoryInterface |
Controller/Adminhtml/Order/Shipment/AddComment.php |
3 | ShipmentCommentSender, Shipment\Comment, Shipment\Comment (Resource) |
Controller/Adminhtml/Shipment/MassPrintShippingLabel.php |
1 | Shipment\CollectionFactory |
Model/ShipmentNotifier.php |
2 | ShipmentSender, Status\History\CollectionFactory |
Model/Shipping.php |
1 | Order\Shipment |
Model/Info.php |
1 | Order\Shipment |
Model/Shipping/Labels.php |
2 | Order\Shipment, Order\Address |
Model/Shipping/LabelGenerator.php |
1 | Order\Shipment |
Layout XML: 11 references to Sales\Block\Adminhtml\* blocks in shipment admin layouts
Assessment: This coupling is architectural — shipment admin controllers and views are in the Shipping module but render Sales blocks and work with Sales data objects. This is by design (Shipping handles the "how to ship" while Sales owns the "what was shipped" data model).
Dhl — 3 PHP imports¶
| File | Sales Classes Used |
|---|---|
Model/Carrier.php |
Sales\Model\Order\Shipment, Sales\Exception\DocumentValidationException |
Model/Validator/XmlValidator.php |
Sales\Exception\DocumentValidationException |
Fedex — 1 PHP import¶
| File | Sales Classes Used |
|---|---|
Model/Carrier.php |
Sales\Model\Order |
Ups — 1 PHP import¶
| File | Sales Classes Used |
|---|---|
Model/Carrier.php |
Sales\Model\Order\Shipment |
Usps — 0 PHP imports¶
composer.json requires magento/module-sales but no actual code usage found. Phantom dependency.
OfflineShipping — 1 PHP import (SalesRule, not Sales)¶
| File | Sales Classes Used |
|---|---|
Model/SalesRule/Calculator.php |
SalesRule\Model\Validator |
composer.json requires both magento/module-sales and magento/module-sales-rule. module.xml sequences both.
Direction 3: Payment → Sales¶
Payment Module — 5 PHP imports¶
| File | Sales Classes Used |
|---|---|
Api/PaymentVerificationInterface.php |
Sales\Api\Data\OrderPaymentInterface |
Gateway/Data/PaymentDataObjectFactory.php |
Sales\Model\Order\Payment |
Gateway/Data/Order/OrderAdapter.php |
Sales\Model\Order |
Gateway/Data/Order/AddressAdapter.php |
Sales\Api\Data\OrderAddressInterface |
Model/Method/AbstractMethod.php |
Sales\Model\Order\Payment |
XML:
- system.xml: Sales\Model\Config\Source\Order\Status\Newprocessing source model
- events.xml: listeners for sales_order_save_before and sales_order_status_unassign
composer.json requires magento/module-sales. No module.xml sequence.
Paypal — 31 PHP imports (HEAVIEST)¶
| Area | # Imports | Key Sales Classes |
|---|---|---|
| Model layer (Express, Payflow, IPN, etc.) | 20 | Order, Order\Payment, Payment\Transaction, OrderPaymentInterface, OrderSender, CreditmemoSender, OrderMutexInterface, TransactionRepositoryInterface |
| Controllers | 6 | OrderFactory, PaymentFailuresInterface, OrderManagementInterface, OrderRepositoryInterface |
| Plugins | 5 | Order, Order\Payment, InvoiceRepositoryInterface, CanInvoice, OrderInterface |
| Blocks | 4 | Adminhtml\Order\View, Reorder, Config, Order\Address |
| Setup | 1 | SalesSetupFactory |
XML: plugins on Sales\Model\Order, Sales\Model\Order\Payment, Sales\Model\Order\Validation\CanInvoice; event listeners for sales_order_payment_* events; ACL refs to Magento_Sales resources
composer.json requires magento/module-sales. module.xml sequences Magento_Sales.
Vault — 6 PHP imports¶
| File | Sales Classes Used |
|---|---|
Observer/AfterPaymentSaveObserver.php |
OrderPaymentExtensionInterface, OrderPaymentInterface |
Plugin/PaymentVaultAttributesLoad.php |
OrderPaymentExtensionInterface, OrderPaymentInterface, OrderPaymentExtensionFactory |
Model/Ui/Adminhtml/TokensConfigProvider.php |
OrderRepositoryInterface |
Model/PaymentTokenManagement.php |
OrderPaymentInterface, Order\Payment |
Api/PaymentTokenManagementInterface.php |
OrderPaymentInterface |
Model/Method/Vault.php |
OrderPaymentExtensionInterfaceFactory, OrderPaymentInterface, Order\Payment |
XML: extension_attributes for OrderPaymentInterface, plugin on OrderPaymentInterface, event listener for sales_order_payment_save_after
composer.json requires magento/module-sales. module.xml sequences Magento_Sales.
OfflinePayments — 0 PHP imports¶
system.xml: referencesSales\Model\Config\Source\Order\Status\NewStatus(4 times)events.xml: listener forsales_order_payment_save_before- No composer.json dependency on Sales. No module.xml sequence.
Summary Matrix¶
Coupling Density (PHP imports, production code)¶
| From → To | Sales | Shipping | Payment |
|---|---|---|---|
| Sales | — | 3 | 14+ |
| SalesRule | — | 0 (composer only) | 0 (composer only) |
| Shipping | 26 | — | 0 |
| Dhl | 3 | (parent) | 0 |
| Fedex | 1 | (parent) | 0 |
| Ups | 1 | (parent) | 0 |
| Usps | 0 (phantom) | (parent) | 0 |
| OfflineShipping | 0 | (parent) | 0 |
| Payment | 5 | 0 | — |
| Paypal | 31 | 0 | (parent) |
| Vault | 6 | 0 | (parent) |
| OfflinePayments | 0 (XML only) | 0 | (parent) |
Phantom Dependencies (composer.json require, zero code usage)¶
| Module | Phantom Dependency |
|---|---|
| Usps | magento/module-sales |
| SalesRule | magento/module-payment (no direct PHP imports) |
| SalesRule | magento/module-shipping (no direct PHP imports) |
Key Architectural Observations¶
1. Sales ↔ Payment is a Circular Dependency¶
- Sales requires Payment (14+ PHP imports, composer require, module.xml sequence)
- Payment requires Sales (5 PHP imports, composer require, events)
- This is the tightest bidirectional coupling in this group
2. Sales ↔ Shipping is Architecturally Split¶
- Sales has light coupling TO Shipping (3 imports: helper + notifier)
- Shipping has heavy coupling TO Sales (26 imports) because Shipping admin controllers manage Sales shipment entities
- The admin UI for shipments lives in Shipping but renders Sales blocks — this is by design but creates strong coupling
3. Paypal is Deeply Embedded in Sales¶
- 31 PHP imports from Sales — Paypal directly manipulates Order, Payment, Invoice, and Transaction objects
- Uses Sales email senders, order mutexes, payment state commands
- This is NOT a thin integration — Paypal is wired into Sales internals
4. Carrier Modules (Dhl, Fedex, Ups) Have Light Sales Coupling¶
- Each carrier only needs
Order\Shipmentfor label generation - Dhl also uses
DocumentValidationException - Usps has zero code usage — phantom dependency
5. OfflinePayments is Nearly Decoupled¶
- Zero PHP imports from Sales
- Only XML config references (system.xml source models + event observer)
- Could be fully decoupled with minor XML adjustments
Decoupling Difficulty Assessment¶
| Category | Modules | Difficulty | Notes |
|---|---|---|---|
| Phantom deps | Usps→Sales, SalesRule→Payment, SalesRule→Shipping | Trivial | Remove from composer.json |
| XML-only | OfflinePayments→Sales | Easy | Move source model refs, event could stay |
| Light carrier | Fedex→Sales, Ups→Sales | Easy | 1 import each, could abstract shipment interface |
| Moderate carrier | Dhl→Sales | Easy | 3 imports, same approach |
| Payment base | Payment→Sales | Hard | API interfaces reference Sales order payment — foundational |
| Vault | Vault→Sales | Hard | Extension attributes on OrderPaymentInterface |
| Sales→Payment | Sales→Payment | Very Hard | 14+ imports, DI checks, email senders — deeply architectural |
| Sales→Shipping | Sales→Shipping | Moderate | Only 3 imports but includes ShipmentNotifier |
| Shipping→Sales | Shipping→Sales | Very Hard | 26 imports + 11 XML layout refs — admin UI is built on Sales blocks |
| Paypal→Sales | Paypal→Sales | Extreme | 31 imports across models, controllers, plugins — complete rewrite needed |
Recommended Priority¶
- Quick wins: Remove phantom deps from Usps, SalesRule (3 composer.json changes)
- OfflinePayments: Nearly decoupled already, small XML work
- Carriers (Fedex, Ups, Dhl): Abstract
Order\Shipmentbehind a carrier-facing interface - Sales↔Payment circular: This is architectural debt — both modules are designed as a unit. Decoupling would require extracting shared interfaces into a new base module (e.g.
SalesPaymentApi) - Shipping→Sales admin UI: The 26 imports are mostly admin controllers that build Sales shipment entities. Would need a complete admin architecture rethink to decouple.
- Paypal→Sales: Do not attempt without first resolving the Sales↔Payment circular dependency