90 lines
3.2 KiB
PHP
90 lines
3.2 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Esun\LingxingErp\Model\Inventory;
|
|
|
|
use Esun\LingxingErp\Model\Api\ApiException;
|
|
use Esun\LingxingErp\Model\Api\Client;
|
|
use Esun\LingxingErp\Model\Api\Endpoint;
|
|
use Esun\LingxingErp\Model\Sync\LogWriter;
|
|
|
|
class InventoryFetcher
|
|
{
|
|
/**
|
|
* Lingxing API documentation:
|
|
* https://apidoc.lingxing.com/#/docs/Warehouse/InventoryDetails
|
|
*/
|
|
private const PAGE_SIZE = 800;
|
|
|
|
public function __construct(
|
|
private readonly Client $client,
|
|
private readonly LogWriter $logWriter
|
|
) {
|
|
}
|
|
|
|
/** @return array<int, array<string, mixed>> */
|
|
public function fetchAll(int $wid): array
|
|
{
|
|
$inventory = [];
|
|
$offset = 0;
|
|
do {
|
|
$request = [
|
|
'wid' => (string)$wid,
|
|
'offset' => $offset,
|
|
'length' => self::PAGE_SIZE,
|
|
];
|
|
$started = microtime(true);
|
|
$response = [];
|
|
try {
|
|
$response = $this->client->post(Endpoint::INVENTORY_DETAILS, $request);
|
|
$rows = $response['data'] ?? null;
|
|
if (!is_array($rows)) {
|
|
throw new \RuntimeException('Lingxing inventory response is missing data.');
|
|
}
|
|
$this->logWriter->write([
|
|
'direction' => 'pull',
|
|
'operation' => 'inventory_pull',
|
|
'entity_type' => 'inventory',
|
|
'external_id' => (string)$wid,
|
|
'status' => 'success',
|
|
'attempt_number' => 1,
|
|
'request_id' => (string)($response['request_id'] ?? ''),
|
|
'request_payload' => $request,
|
|
'response_payload' => $response,
|
|
'duration_ms' => (int)round((microtime(true) - $started) * 1000),
|
|
]);
|
|
} catch (\Throwable $exception) {
|
|
$apiResponse = $exception instanceof ApiException ? $exception->getResponse() : $response;
|
|
$this->logWriter->write([
|
|
'direction' => 'pull',
|
|
'operation' => 'inventory_pull',
|
|
'entity_type' => 'inventory',
|
|
'external_id' => (string)$wid,
|
|
'status' => 'failed',
|
|
'attempt_number' => 1,
|
|
'error_code' => $exception instanceof ApiException
|
|
? $exception->getErrorCode()
|
|
: (string)$exception->getCode(),
|
|
'error_message' => $exception->getMessage(),
|
|
'request_id' => (string)($apiResponse['request_id'] ?? ''),
|
|
'request_payload' => $request,
|
|
'response_payload' => $apiResponse,
|
|
'duration_ms' => (int)round((microtime(true) - $started) * 1000),
|
|
]);
|
|
throw $exception;
|
|
}
|
|
|
|
foreach ($rows as $row) {
|
|
if (is_array($row)) {
|
|
$inventory[] = $row;
|
|
}
|
|
}
|
|
$received = count($rows);
|
|
$offset += $received;
|
|
$total = max(0, (int)($response['total'] ?? $offset));
|
|
} while ($received > 0 && $offset < $total);
|
|
|
|
return $inventory;
|
|
}
|
|
}
|