Feat: Shipping functionalities redesign, elta courier integration, commenting out acs since no integration can happen, flow updates
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Shipping\Services;
|
||||
|
||||
use Modules\Core\Shipping\Contracts\CarrierFulfillmentInterface;
|
||||
use Modules\Core\Shipping\Contracts\SupportsTracking;
|
||||
use Modules\Core\Shipping\DTOs\TrackingCheckpoint;
|
||||
use Modules\Core\Shipping\Events\ShipmentStatusUpdatedByCarrier;
|
||||
use Modules\Core\Shipping\Models\Shipment;
|
||||
use Modules\Core\Shipping\Models\ShipmentInfo;
|
||||
|
||||
/**
|
||||
* The one place carrier checkpoints become ShipmentInfo rows (the carrier
|
||||
* info every screen reads): new checkpoints only — matched on status +
|
||||
* time — each dispatching ShipmentStatusUpdatedByCarrier, so order status,
|
||||
* emails and the order Timeline follow. Used by PollShipmentTrackingJob,
|
||||
* the voucher sync and the "Refresh tracking" actions.
|
||||
*/
|
||||
class ShipmentTrackingRecorder
|
||||
{
|
||||
/**
|
||||
* Fetches the shipment's history from its carrier and records what's
|
||||
* new. Returns how many checkpoints were added (0 when the carrier has
|
||||
* no tracking API).
|
||||
*/
|
||||
public function refresh(Shipment $shipment): int
|
||||
{
|
||||
$service = app(CarrierFulfillmentInterface::class, ['carrier' => $shipment->carrier]);
|
||||
|
||||
if (! $service instanceof SupportsTracking || blank($shipment->tracking_reference)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $this->record($shipment, $service->trackShipment($shipment));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param iterable<TrackingCheckpoint> $checkpoints
|
||||
*/
|
||||
public function record(Shipment $shipment, iterable $checkpoints): int
|
||||
{
|
||||
$existing = $shipment->shipmentInfo()
|
||||
->get(['status', 'occurred_at'])
|
||||
->map(fn (ShipmentInfo $info) => $this->fingerprint($info->status->value, $info->occurred_at->toIso8601String()))
|
||||
->flip();
|
||||
|
||||
$added = 0;
|
||||
|
||||
foreach ($checkpoints as $checkpoint) {
|
||||
$fingerprint = $this->fingerprint($checkpoint->status->value, $checkpoint->occurredAt->toIso8601String());
|
||||
|
||||
if ($existing->has($fingerprint)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$existing->put($fingerprint, true);
|
||||
|
||||
$info = ShipmentInfo::create([
|
||||
'shipment_id' => $shipment->id,
|
||||
'status' => $checkpoint->status,
|
||||
'carrier_status' => $checkpoint->carrierStatus,
|
||||
'message' => $checkpoint->message,
|
||||
'location' => $checkpoint->location,
|
||||
'occurred_at' => $checkpoint->occurredAt,
|
||||
'meta' => $checkpoint->meta,
|
||||
]);
|
||||
|
||||
ShipmentStatusUpdatedByCarrier::dispatch($info);
|
||||
|
||||
$added++;
|
||||
}
|
||||
|
||||
return $added;
|
||||
}
|
||||
|
||||
private function fingerprint(string $status, string $occurredAt): string
|
||||
{
|
||||
return $status.'|'.$occurredAt;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user