1. Rate Collection (Checkout)
During checkout, shipping rates are collected when the customer enters their shipping address. This flow is triggered by the Quote module's address rate request.
CHECKOUT SHIPPING STEP
=======================
Customer enters address
|
v
+---------------------------+
| Quote\Address |
| ::collectShippingRates() |
+------------+--------------+
|
v
+---------------------------+
| RateCollectorInterface |
| ::collectRates($request) | --> Shipping::collectRates()
+------------+--------------+
|
v
+---------------------------+
| ScopeConfig::getValue() |
| 'carriers/*' config |
+------------+--------------+
|
+-------+-------+-------+-------+
| | | | |
v v v v v
+------+ +------+ +------+ +------+ +------+
| UPS | | USPS | |FedEx | | Flat | | Free |
| Rate | | Rate | | Rate | | Rate | | Ship |
+--+---+ +--+---+ +--+---+ +--+---+ +--+---+
| | | | |
v v v v v
+---------------------------+
| CarrierResult |
| ::appendResult() |
+------------+--------------+
|
v
+---------------------------+
| Quote\Address |
| ::setShippingRates() |
+---------------------------+
|
v
+---------------------------+
| Displayed at checkout |
| as radio button options |
+---------------------------+
Key Method: Shipping::collectRates()
- Sets origin address from store config if not provided in request
- Gets list of enabled carriers from
carriers/*config - Iterates through carriers, calling
collectCarrierRates() - For each carrier: validates country availability, creates via factory, calls
collectRates() - Aggregates all rate results into CarrierResult
- Returns aggregated result to Quote for display
2. Single Carrier Rate Request
Shipping::collectCarrierRates($carrierCode, $request)
|
v
+------------------+
| prepareCarrier() |
+--------+---------+
|
+------------+------------+
| |
v v
+-----------+ +---------------+
| isActive? |--NO-----> | Skip carrier |
+-----------+ +---------------+
| YES
v
+--------------------+
| checkAvailable |
| ShipCountries() |
+--------+-----------+
|
+----+----+
| |
v v
+-------+ +-------+
| true | | Error |---> append Error to result
+---+---+ +-------+
|
v
+------------------------+
| processAdditional |
| Validation() |
+--------+---------------+
|
+----+----+
| |
v v
+-------+ +-------+
| true | | false |---> skip carrier silently
+---+---+ +-------+
|
v
+------------------------+
| Check shipment_ |
| requesttype config |
+--------+---------------+
|
+----+----+
| |
v v
+--------+ +----------------+
| false | | true |
+---+----+ | compose |
| | Packages() |
| +-------+--------+
| |
+------+-------+
|
v
+------------------------+
| carrier->collectRates |
| ($request) |
+--------+---------------+
|
v
+------------------------+
| Result (methods/error) |
+--------+---------------+
|
v
+------------------------+
| getResult()->append |
| Result($result) |
+------------------------+
3. Shipment Creation (Admin)
Shipments are created from the admin order view. This flow handles the creation of the shipment record and optionally generates shipping labels.
ADMIN: Order View -> Ship
=========================
+----------------------------+
| Controller\Adminhtml\ |
| Order\Shipment\NewAction |
+------------+---------------+
|
v
+----------------------------+
| ShipmentLoader::load() |
| (builds Shipment model) |
+------------+---------------+
|
v
+----------------------------+
| Render create form |
| Block\Adminhtml\Create |
+------------+---------------+
|
v [Submit Form]
+----------------------------+
| Controller\Adminhtml\ |
| Order\Shipment\Save |
+------------+---------------+
|
+-------+--------+
| |
v v
+----------+ +------------------+
| No Label | | Create Label? |
+----+-----+ +--------+---------+
| |
| v
| +------------------+
| | Shipping\Labels |
| | ::requestTo |
| | Shipment() |
| +--------+---------+
| |
| v
| +------------------+
| | carrier-> |
| | requestToShipment|
| +--------+---------+
| |
| v
| +------------------+
| | Store label data |
| | on Shipment |
| +--------+---------+
| |
+--------+---------+
|
v
+----------------------------+
| ShipmentRepository::save() |
+------------+---------------+
|
v
+----------------------------+
| Create shipment tracks |
| (tracking numbers) |
+------------+---------------+
|
v
+----------------------------+
| Dispatch event: |
| sales_order_shipment_ |
| save_after |
+----------------------------+
4. Tracking Lookup (Frontend)
Customers can view tracking information via a popup window accessed from their order confirmation email or account order history.
TRACKING POPUP
==============
Customer clicks tracking link
|
v
+----------------------------+
| Controller\Tracking\Popup |
+------------+---------------+
|
v
+----------------------------+
| Load order/shipment/track |
| from hash parameter |
+------------+---------------+
|
v
+----------------------------+
| Info::getTrackingInfo() |
+------------+---------------+
|
+-------+-------+
| |
v v
+----------+ +--------------+
| By Order | | By Shipment |
| ID | | ID |
+----+-----+ +------+-------+
| |
+-------+--------+
|
v
+----------------------------+
| Get all tracks for entity |
| ShipmentTrackCollection |
+------------+---------------+
|
v (for each track)
+----------------------------+
| CarrierFactory::create() |
| ($carrierCode) |
+------------+---------------+
|
v
+----------------------------+
| carrier->getTracking |
| ($trackNumber) |
+------------+---------------+
|
v
+----------------------------+
| Carrier calls external API |
| (UPS/FedEx/USPS/etc) |
+------------+---------------+
|
v
+----------------------------+
| Return Tracking\Result |
| with Status objects |
+------------+---------------+
|
v
+----------------------------+
| Render Block\Tracking\ |
| Popup with tracking data |
+----------------------------+
Tracking Status Fields
Basic Info
tracking- Tracking numbercarrier- Carrier codecarrier_title- Display nameurl- Carrier tracking URL
Delivery Info
status- Current statusdeliverydate- Expected deliverydeliverytime- Delivery timesignedby- Signature
5. Shipping Label Generation
Shipping labels are generated during shipment creation when the carrier supports labels. This requires integration with the carrier's API.
LABEL GENERATION FLOW
=====================
+--------------------------------+
| Controller\Adminhtml\Order\ |
| Shipment\CreateLabel |
+--------------+-----------------+
|
v
+--------------------------------+
| Shipping\Labels |
| ::requestToShipment() |
+--------------+-----------------+
|
v
+--------------------------------+
| Build Shipment\Request from |
| order and package data |
+--------------+-----------------+
|
v
+--------------------------------+
| CarrierFactory::create() |
+--------------+-----------------+
|
v
+--------------------------------+
| AbstractCarrierOnline |
| ::requestToShipment($request) |
+--------------+-----------------+
|
+---------+----------+
| |
v v
+----------+ +----------------+
| Success | | Error |
+----+-----+ +-------+--------+
| |
v v
+-------------+ +----------------+
| Get label | | Throw |
| content & | | Localized |
| tracking # | | Exception |
+------+------+ +----------------+
|
v
+--------------------------------+
| Shipment::setShippingLabel() |
| (store binary label data) |
+--------------+-----------------+
|
v
+--------------------------------+
| Create ShipmentTrack with |
| tracking number from response |
+--------------+-----------------+
|
v
+--------------------------------+
| ShipmentRepository::save() |
+--------------------------------+
Label Data Storage
Labels are stored as binary data in sales_shipment.shipping_label.
The format (PDF, PNG, GIF) depends on the carrier's response.
Use Shipment::getShippingLabel() to retrieve.
6. Shipment Report Aggregation (Cron)
A daily cron job aggregates shipment data for reporting. This runs at midnight.
<!-- etc/crontab.xml -->
<job name="aggregate_sales_report_shipment_data"
instance="Magento\Shipping\Model\Observer"
method="aggregateSalesReportShipmentData">
<schedule>0 0 * * *</schedule>
</job>
CRON: aggregate_sales_report_shipment_data
==========================================
+--------------------------------+
| Magento\Shipping\Model\Observer|
| ::aggregateSalesReportShipment |
| Data() |
+--------------+-----------------+
|
v
+--------------------------------+
| ResourceModel\Report\Shipping |
| ::aggregate() |
+--------------+-----------------+
|
v
+--------------------------------+
| Query sales_shipment table |
| Group by date, store, status |
+--------------+-----------------+
|
v
+--------------------------------+
| Insert into |
| sales_shipping_aggregated |
| _order table |
+--------------------------------+
Error Handling Patterns
Rate Collection Errors
When a carrier fails during rate collection, an Error result is appended:
$error->setCarrier($this->_code);
$error->setCarrierTitle($this->getConfigData('title'));
$error->setErrorMessage(__('Carrier unavailable'));
return $error;
Country Restriction
When destination country is not allowed, carrier is skipped:
if (false === $result) {
// Skip silently (admin configured)
return $this;
}
Label Generation Errors
Label failures throw LocalizedException:
throw new LocalizedException(
__($result->getErrors())
);
}
Tracking Errors
Tracking failures use Tracking\Result\Error:
$error->setTracking($trackNumber);
$error->setCarrier($this->_code);
$error->setErrorMessage(__('Unable to retrieve tracking'));
$result->append($error);