Files
2026-09-15 10:35:56 +08:00

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;
}
}