0

I've created a module to notify the customer when a custom carrier has been added. I've used an observer on the sales_order_shipment_save_after event but the tracking info and items ordered are empty in the shipment email. I'm guessing I need to load the tracking info and order items into the $shipment object?

Example/SendShipmentTracking/Observer/SendShipmentTrackingProcessor.php

<?php

namespace Example\SendShipmentTracking\Observer;

use Example\SendShipmentTracking\Helper\Data;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Serialize\Serializer\Json;
use Magento\Sales\Model\Order\Shipment\Notifier;
use Psr\Log\LoggerInterface;

class SendShipmentTrackingProcessor implements ObserverInterface
{
    /**
     * @var LoggerInterface
     */
    protected LoggerInterface $logger;

    /**
     * @var Json
     */
    protected Json $jsonHelper;

    /**
     * @var Data
     */
    protected Data $helperData;

    /**
     * @var Notifier
     */
    protected Notifier $shipmentNotifier;

    /**
     * @param LoggerInterface $logger
     * @param Json $jsonHelper
     * @param Data $helperData
     * @param Notifier $shipmentNotifier
     */
    public function __construct(
        LoggerInterface $logger,
        Json $jsonHelper,
        Data $helperData,
        Notifier $shipmentNotifier
    ) {
        $this->logger = $logger;
        $this->jsonHelper = $jsonHelper;
        $this->helperData = $helperData;
        $this->shipmentNotifier = $shipmentNotifier;
    }

    /**
     * @param Observer $observer
     * @return void
     */
    public function execute(Observer $observer)
    {
        if ($this->helperData->isEnabled()) {
            try {
                $shipment = $observer->getEvent()->getShipment();

                if ($shipment && $this->hasShipmentTracking($shipment)) {
                    $order = $shipment->getOrder();
                    $this->logger->debug('shipment data ' . $this->jsonHelper->serialize($shipment->getData()));
                    $this->shipmentNotifier->notify($order, $shipment);
                }
            } catch (\Exception $e) {
                $this->logger->error($e->getMessage());
            }
        }
    }

    /**
     * @param $shipment
     * @return bool
     */
    private function hasShipmentTracking($shipment): bool
    {
        $tracksCollection = $shipment->getTracksCollection();
        $trackingNumber = [];

        foreach ($tracksCollection->getItems() as $track) {
            if ($track->isCustom()) {
                $trackTile = $track->getTitle();
                $carrierServices = $this->helperData->getCarriers();

                if (in_array($trackTile, $carrierServices) && $track->getTrackNumber()) {
                    $trackingNumber[] = $track->getTrackNumber();
                }
            }
        }

        return count($trackingNumber) > 0;
    }
}

1 Answer 1

1

After get shipment by this line code:

$shipment = $observer->getEvent()->getShipment();

You can get items of shipment by using method:

$shipment->getItems() // return record in table `sales_shipment_item`

and get tracks of this shipment by using method:

$shipment->getAllTracks()
2
  • With using these methods $shipment->getItems() and $shipment->getAllTracks() I get empty arrays? May 23, 2023 at 8:21
  • I think you should comment code of this observer and check default flow create shipment first. After create new shipment, check information of that new shipment. If everything working right, it should have data (you can check in shipment detail page admin or table sales_shipment_item). If not, maybe the reason you can not get item and get all tracks because your another code.
    – Shou
    May 23, 2023 at 8:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.