108 lines
4.3 KiB
PHP
108 lines
4.3 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Esun\LingxingErp\Model\Sync;
|
|
|
|
use Magento\Framework\App\ResourceConnection;
|
|
|
|
class ShipmentSyncRepository
|
|
{
|
|
private string $table;
|
|
|
|
public function __construct(private readonly ResourceConnection $resource)
|
|
{
|
|
$this->table = $resource->getTableName('esun_lingxing_shipment_sync');
|
|
}
|
|
|
|
public function enqueue(array $payload, string $requestId = ''): void
|
|
{
|
|
$connection = $this->resource->getConnection();
|
|
$externalKey = (string)$payload['external_key'];
|
|
$existing = $connection->fetchRow($connection->select()->from($this->table)
|
|
->where('external_key = ?', $externalKey)->limit(1));
|
|
$data = [
|
|
'global_order_no' => (string)($payload['global_order_no'] ?? ''),
|
|
'wo_id' => !empty($payload['wo_id']) ? (int)$payload['wo_id'] : null,
|
|
'wo_number' => (string)$payload['wo_number'],
|
|
'package_no' => (string)($payload['package_no'] ?? '') ?: null,
|
|
'tracking_no' => implode(',', array_values(array_filter(array_column($payload['tracks'] ?? [], 'number')))),
|
|
'request_id' => $requestId ?: null,
|
|
'payload_json' => (string)json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR),
|
|
'updated_at' => gmdate('Y-m-d H:i:s'),
|
|
];
|
|
if (!$existing) {
|
|
$data += [
|
|
'external_key' => $externalKey,
|
|
'status' => 'pending',
|
|
'created_at' => gmdate('Y-m-d H:i:s'),
|
|
];
|
|
$connection->insert($this->table, $data);
|
|
return;
|
|
}
|
|
if ((string)$existing['status'] !== 'success') {
|
|
$connection->update($this->table, $data, ['entity_id = ?' => (int)$existing['entity_id']]);
|
|
}
|
|
}
|
|
|
|
public function getDue(int $limit): array
|
|
{
|
|
$connection = $this->resource->getConnection();
|
|
return $connection->fetchAll($connection->select()->from($this->table)
|
|
->where('status IN (?)', ['pending', 'retrying'])
|
|
->where('next_retry_at IS NULL OR next_retry_at <= ?', gmdate('Y-m-d H:i:s'))
|
|
->order('entity_id ASC')->limit($limit));
|
|
}
|
|
|
|
public function claim(int $entityId): bool
|
|
{
|
|
return $this->resource->getConnection()->update($this->table, [
|
|
'status' => 'processing',
|
|
'last_attempt_at' => gmdate('Y-m-d H:i:s'),
|
|
], ['entity_id = ?' => $entityId, 'status IN (?)' => ['pending', 'retrying']]) === 1;
|
|
}
|
|
|
|
public function markSuccess(int $entityId, int $orderId, string $incrementId, int $shipmentId): void
|
|
{
|
|
$now = gmdate('Y-m-d H:i:s');
|
|
$this->resource->getConnection()->update($this->table, [
|
|
'order_id' => $orderId,
|
|
'increment_id' => $incrementId,
|
|
'shipment_id' => $shipmentId,
|
|
'status' => 'success',
|
|
'last_error_code' => null,
|
|
'last_error_message' => null,
|
|
'next_retry_at' => null,
|
|
'synced_at' => $now,
|
|
'updated_at' => $now,
|
|
], ['entity_id = ?' => $entityId]);
|
|
}
|
|
|
|
public function markFailure(int $entityId, int $attemptCount, int $maxAttempts, string $code, string $message): string
|
|
{
|
|
$attemptCount++;
|
|
$status = $attemptCount >= $maxAttempts ? 'failed' : 'retrying';
|
|
$delay = min(3600, 30 * (2 ** min(7, max(0, $attemptCount - 1))));
|
|
$this->resource->getConnection()->update($this->table, [
|
|
'status' => $status,
|
|
'attempt_count' => $attemptCount,
|
|
'next_retry_at' => $status === 'retrying' ? gmdate('Y-m-d H:i:s', time() + $delay) : null,
|
|
'last_error_code' => $code ?: null,
|
|
'last_error_message' => mb_substr($message, 0, 65535),
|
|
'updated_at' => gmdate('Y-m-d H:i:s'),
|
|
], ['entity_id = ?' => $entityId]);
|
|
return $status;
|
|
}
|
|
|
|
public function retry(int $entityId): bool
|
|
{
|
|
return $this->resource->getConnection()->update($this->table, [
|
|
'status' => 'pending',
|
|
'attempt_count' => 0,
|
|
'next_retry_at' => null,
|
|
'last_error_code' => null,
|
|
'last_error_message' => null,
|
|
'updated_at' => gmdate('Y-m-d H:i:s'),
|
|
], ['entity_id = ?' => $entityId, 'status IN (?)' => ['failed', 'retrying']]) === 1;
|
|
}
|
|
}
|