Phase 128 complete: - add Erli /inbox order import with safe mark-read ACK - add cron/manual import controls and sync state tracking - map Erli orders into orderPRO aggregates with mapper tests and docs
153 lines
5.3 KiB
PHP
153 lines
5.3 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Unit;
|
|
|
|
use App\Core\Constants\IntegrationSources;
|
|
use App\Modules\Settings\ErliOrderMapper;
|
|
use PHPUnit\Framework\TestCase;
|
|
use RuntimeException;
|
|
|
|
final class ErliOrderMapperTest extends TestCase
|
|
{
|
|
private ErliOrderMapper $mapper;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->mapper = new ErliOrderMapper();
|
|
}
|
|
|
|
public function testPurchasedOrderMapsToImportAggregate(): void
|
|
{
|
|
$aggregate = $this->mapper->mapInboxMessage(7, $this->message('purchased'));
|
|
|
|
self::assertIsArray($aggregate);
|
|
self::assertSame(IntegrationSources::ERLI, $aggregate['order']['source']);
|
|
self::assertSame('erli-123', $aggregate['order']['source_order_id']);
|
|
self::assertSame('nowe', $aggregate['order']['status_code']);
|
|
self::assertSame(2, $aggregate['order']['payment_status']);
|
|
self::assertSame(129.99, $aggregate['order']['total_with_tax']);
|
|
self::assertSame(14.99, $aggregate['order']['delivery_price']);
|
|
self::assertCount(1, $aggregate['items']);
|
|
self::assertSame('Produkt Erli', $aggregate['items'][0]['original_name']);
|
|
self::assertCount(1, $aggregate['payments']);
|
|
}
|
|
|
|
public function testPendingOrderMapsAsUnpaid(): void
|
|
{
|
|
$aggregate = $this->mapper->mapInboxMessage(7, $this->message('pending'));
|
|
|
|
self::assertIsArray($aggregate);
|
|
self::assertSame('nieoplacone', $aggregate['order']['status_code']);
|
|
self::assertSame(0, $aggregate['order']['payment_status']);
|
|
}
|
|
|
|
public function testCancelledOrderMapsCancellationFlag(): void
|
|
{
|
|
$aggregate = $this->mapper->mapInboxMessage(7, $this->message('cancelled'));
|
|
|
|
self::assertIsArray($aggregate);
|
|
self::assertSame('anulowane', $aggregate['order']['status_code']);
|
|
self::assertTrue($aggregate['order']['is_canceled_by_buyer']);
|
|
}
|
|
|
|
public function testCompanyInvoiceDataDetectsInvoiceRequest(): void
|
|
{
|
|
$message = $this->message('purchased');
|
|
$message['payload']['user']['invoiceAddress'] = [
|
|
'type' => 'company',
|
|
'companyName' => 'Test Sp. z o.o.',
|
|
'nip' => '1234567890',
|
|
'address' => 'Testowa 1',
|
|
'street' => 'Testowa',
|
|
'buildingNumber' => '1',
|
|
'zip' => '00-001',
|
|
'city' => 'Warszawa',
|
|
'country' => 'pl',
|
|
];
|
|
|
|
$aggregate = $this->mapper->mapInboxMessage(7, $message);
|
|
|
|
self::assertIsArray($aggregate);
|
|
self::assertTrue($aggregate['invoice_detected']);
|
|
self::assertSame('1234567890', $aggregate['addresses'][2]['company_tax_number']);
|
|
}
|
|
|
|
public function testUnsupportedInboxMessageIsSkipped(): void
|
|
{
|
|
$message = $this->message('purchased');
|
|
$message['type'] = 'productsNeedSync';
|
|
|
|
self::assertNull($this->mapper->mapInboxMessage(7, $message));
|
|
}
|
|
|
|
public function testMissingOrderIdThrowsControlledException(): void
|
|
{
|
|
$message = $this->message('purchased');
|
|
unset($message['payload']['id']);
|
|
|
|
$this->expectException(RuntimeException::class);
|
|
$this->expectExceptionMessage('ID zamowienia');
|
|
|
|
$this->mapper->mapInboxMessage(7, $message);
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
private function message(string $status): array
|
|
{
|
|
return [
|
|
'id' => '5f9e1b3b0f0b9b0001c3e0a0',
|
|
'shopId' => 99,
|
|
'created' => '2026-05-15T10:00:00+02:00',
|
|
'read' => false,
|
|
'type' => 'orderCreated',
|
|
'payload' => [
|
|
'id' => 'erli-123',
|
|
'externalOrderId' => 'EXT-123',
|
|
'status' => $status,
|
|
'created' => '2026-05-15T09:00:00+02:00',
|
|
'updated' => '2026-05-15T09:05:00+02:00',
|
|
'purchasedAt' => '2026-05-15T09:01:00+02:00',
|
|
'totalPrice' => 129.99,
|
|
'user' => [
|
|
'email' => 'jan@example.com',
|
|
'deliveryAddress' => [
|
|
'firstName' => 'Jan',
|
|
'lastName' => 'Kowalski',
|
|
'address' => 'Testowa 1',
|
|
'street' => 'Testowa',
|
|
'buildingNumber' => '1',
|
|
'zip' => '00-001',
|
|
'city' => 'Warszawa',
|
|
'country' => 'pl',
|
|
'phone' => '500100200',
|
|
],
|
|
],
|
|
'delivery' => [
|
|
'methodName' => 'Kurier',
|
|
'price' => 14.99,
|
|
],
|
|
'payment' => [
|
|
'id' => 'pay-123',
|
|
'status' => $status === 'purchased' ? 'COMPLETED' : 'NEW',
|
|
'methodCode' => 'PAYU.p',
|
|
],
|
|
'items' => [
|
|
[
|
|
'id' => 'item-1',
|
|
'externalProductId' => 'sku-1',
|
|
'name' => 'Produkt Erli',
|
|
'quantity' => 2,
|
|
'price' => 57.50,
|
|
'sku' => 'SKU-1',
|
|
],
|
|
],
|
|
'comment' => 'Prosze o szybka wysylke',
|
|
'sellerStatus' => 'created',
|
|
],
|
|
];
|
|
}
|
|
}
|