82 lines
2.2 KiB
PHP
82 lines
2.2 KiB
PHP
<?php
|
|||
|
|
|
||
|
|
namespace Modules\Core\Shipping\Carriers\Acs;
|
||
|
|
|
||
|
|
use Illuminate\Support\Facades\Cache;
|
||
|
|
use Modules\Core\Shipping\Carriers\Acs\Exceptions\AcsApiException;
|
||
|
|
|
||
|
|
class AreaResolver
|
||
|
|
{
|
||
|
|
public const CACHE_KEY = 'acs.areas';
|
||
|
|
|
||
|
|
public function __construct(private readonly AcsClient $client) {}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Resolve a Greek postcode to its ACS station/branch codes.
|
||
|
|
*
|
||
|
|
* Reads from the table warmed daily by WarmAcsAreaCacheJob. Falls
|
||
|
|
* back to a live lookup for that single postcode if the warmed cache is
|
||
|
|
* missing (e.g. the daily job never ran or failed) or doesn't contain it.
|
||
|
|
*/
|
||
|
|
public function resolve(string $postcode): AcsArea
|
||
|
|
{
|
||
|
|
$areas = Cache::get(self::CACHE_KEY);
|
||
|
|
|
||
|
|
if ($areas !== null && isset($areas[$postcode])) {
|
||
|
|
return $this->toArea($areas[$postcode]);
|
||
|
|
}
|
||
|
|
|
||
|
|
return $this->toArea($this->fetch($postcode));
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Fetch and cache the full country's postcode-to-station map in one call.
|
||
|
|
*/
|
||
|
|
public function warmAll(): void
|
||
|
|
{
|
||
|
|
$areas = [];
|
||
|
|
|
||
|
|
foreach ($this->fetchAll() as $row) {
|
||
|
|
$areas[$row['Zip_Code']] = $row;
|
||
|
|
}
|
||
|
|
|
||
|
|
Cache::forever(self::CACHE_KEY, $areas);
|
||
|
|
}
|
||
|
|
|
||
|
|
private function fetch(string $postcode): array
|
||
|
|
{
|
||
|
|
$response = $this->client->call('ACS_Area_Find_By_Zip_Code', [
|
||
|
|
'Zip_Code' => $postcode,
|
||
|
|
'Show_Only_Inaccessible_Areas' => 0,
|
||
|
|
'Country' => 'GR',
|
||
|
|
])->throwIfError();
|
||
|
|
|
||
|
|
$area = $response->tableOutput['Table_Data'][0] ?? null;
|
||
|
|
|
||
|
|
if (! $area) {
|
||
|
|
throw new AcsApiException("No ACS area found for postcode {$postcode}");
|
||
|
|
}
|
||
|
|
|
||
|
|
return $area;
|
||
|
|
}
|
||
|
|
|
||
|
|
private function fetchAll(): array
|
||
|
|
{
|
||
|
|
$response = $this->client->call('ACS_Area_Find_By_Zip_Code', [
|
||
|
|
'Zip_Code' => null,
|
||
|
|
'Show_Only_Inaccessible_Areas' => 0,
|
||
|
|
'Country' => 'GR',
|
||
|
|
])->throwIfError();
|
||
|
|
|
||
|
|
return $response->tableOutput['Table_Data'] ?? [];
|
||
|
|
}
|
||
|
|
|
||
|
|
private function toArea(array $row): AcsArea
|
||
|
|
{
|
||
|
|
return new AcsArea(
|
||
|
|
stationId: $row['Station_ID'],
|
||
|
|
branchId: (int) $row['Branch_ID'],
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|