Files
orderPRO/tests/Unit/ErliOrderMapperTest.php
Jacek Pyziak 2565d9b754 feat(128): erli orders import
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
2026-05-15 23:54:22 +02:00

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',
],
];
}
}