89 lines
3.6 KiB
PHP
89 lines
3.6 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Esun\LingxingErp\Model\Order;
|
|
|
|
use Esun\LingxingErp\Model\Api\ApiException;
|
|
use Esun\LingxingErp\Model\Api\Client;
|
|
use Esun\LingxingErp\Model\Api\Endpoint;
|
|
use Esun\LingxingErp\Model\Config;
|
|
use Magento\Sales\Api\Data\OrderInterface;
|
|
use Magento\Store\Model\StoreManagerInterface;
|
|
|
|
class OrderExporter
|
|
{
|
|
public function __construct(
|
|
private readonly Client $client,
|
|
private readonly Config $config,
|
|
private readonly OrderPayloadBuilder $payloadBuilder,
|
|
private readonly StoreManagerInterface $storeManager
|
|
) {
|
|
}
|
|
|
|
public function export(OrderInterface $order, ?array $payload = null): array
|
|
{
|
|
$payload ??= $this->payloadBuilder->build($order);
|
|
$websiteId = (int)$this->storeManager->getStore((int)$order->getStoreId())->getWebsiteId();
|
|
try {
|
|
$response = $this->client->post(Endpoint::ORDER_CREATE, $payload);
|
|
} catch (ApiException $exception) {
|
|
// The ERP may have committed the order even if the response was lost. Reconcile before retrying.
|
|
try {
|
|
$existing = $this->findExisting((string)$order->getIncrementId(), $websiteId);
|
|
} catch (\Throwable) {
|
|
throw $exception;
|
|
}
|
|
if ($existing !== null) {
|
|
return [
|
|
'payload' => $payload,
|
|
'response' => $exception->getResponse(),
|
|
'global_order_no' => $existing,
|
|
];
|
|
}
|
|
throw $exception;
|
|
}
|
|
$successes = $response['data']['success_details'] ?? [];
|
|
foreach (is_array($successes) ? $successes : [] as $success) {
|
|
if ((string)($success['platform_order_no'] ?? '') === (string)$order->getIncrementId()
|
|
&& (string)($success['global_order_no'] ?? '') !== '') {
|
|
return ['payload' => $payload, 'response' => $response, 'global_order_no' => (string)$success['global_order_no']];
|
|
}
|
|
}
|
|
|
|
$existing = $this->findExisting((string)$order->getIncrementId(), $websiteId);
|
|
if ($existing !== null) {
|
|
return ['payload' => $payload, 'response' => $response, 'global_order_no' => $existing];
|
|
}
|
|
|
|
$errors = $response['data']['error_details'] ?? [];
|
|
$message = is_array($errors) && $errors !== []
|
|
? implode('; ', array_filter(array_map(static fn(array $error): string => (string)($error['error_message'] ?? ''), $errors)))
|
|
: 'Lingxing did not return a success record for this order.';
|
|
throw new ApiException($message, 'order_not_created', $response);
|
|
}
|
|
|
|
private function findExisting(string $incrementId, int $websiteId): ?string
|
|
{
|
|
$response = $this->client->post(Endpoint::ORDER_LIST, [
|
|
'offset' => 0,
|
|
'length' => 20,
|
|
'store_id' => [$this->config->getLingxingStoreId($websiteId)],
|
|
'platform_code' => [$this->config->getPlatformCode($websiteId)],
|
|
'platform_order_nos' => [$incrementId],
|
|
]);
|
|
foreach (($response['data']['list'] ?? []) as $order) {
|
|
foreach (($order['platform_info'] ?? []) as $platformInfo) {
|
|
if ((string)($platformInfo['platform_order_no'] ?? '') === $incrementId) {
|
|
return (string)($order['global_order_no'] ?? '') ?: null;
|
|
}
|
|
}
|
|
foreach (($order['item_info'] ?? []) as $item) {
|
|
if ((string)($item['platform_order_no'] ?? '') === $incrementId) {
|
|
return (string)($order['global_order_no'] ?? '') ?: null;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|