diff --git a/composer.json b/composer.json index 701f222..dfa1d83 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ "symfony/translation": "^7.0" }, "require-dev": { - "assoconnect/php-quality-config": "^2.2" + "assoconnect/php-quality-config": "^2.4" }, "config": { "allow-plugins": { diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 2634ffc..191f302 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -13,7 +13,7 @@ parameters: path: src/ApiClient.php - - message: '#^Parameter \#1 \$data of class AssoConnect\\LinxoClient\\Dto\\TransactionDto constructor expects array\{id\: string, account_id\: string, amount\: array\{amount\: string, currency\: string\}, enrichments\: array\{display_label\?\: string, date\: string, notes\?\: string\}, type\?\: string\}, array given\.$#' + message: '#^Parameter \#1 \$data of class AssoConnect\\LinxoClient\\Dto\\TransactionDto constructor expects array\{id\: string, account_id\: string, amount\: array\{amount\: string, currency\: string\}, enrichments\: array\{display_label\?\: string, date\: string, notes\?\: string\}, type\?\: string, remittance_information\?\: list\\}, array given\.$#' identifier: argument.type count: 1 path: src/ApiClient.php @@ -67,9 +67,9 @@ parameters: path: tests/Dto/TransactionDtoTest.php - - message: '#^Parameter \#1 \$data of class AssoConnect\\LinxoClient\\Dto\\TransactionDto constructor expects array\{id\: string, account_id\: string, amount\: array\{amount\: string, currency\: string\}, enrichments\: array\{display_label\?\: string, date\: string, notes\?\: string\}, type\?\: string\}, array\ given\.$#' + message: '#^Parameter \#1 \$data of class AssoConnect\\LinxoClient\\Dto\\TransactionDto constructor expects array\{id\: string, account_id\: string, amount\: array\{amount\: string, currency\: string\}, enrichments\: array\{display_label\?\: string, date\: string, notes\?\: string\}, type\?\: string, remittance_information\?\: list\\}, array\ given\.$#' identifier: argument.type - count: 11 + count: 14 path: tests/Dto/TransactionDtoTest.php - diff --git a/src/Dto/TransactionDto.php b/src/Dto/TransactionDto.php index 4cb81a5..f6d5ccb 100644 --- a/src/Dto/TransactionDto.php +++ b/src/Dto/TransactionDto.php @@ -13,8 +13,13 @@ * id: string, * account_id: string, * amount: array{amount: string, currency: string}, - * enrichments: array{display_label?: string, date: string, notes?: string}, - * type?: string + * enrichments: array{ + * display_label?: string, + * date: string, + * notes?: string + * }, + * type?: string, + * remittance_information?: list * } */ class TransactionDto @@ -24,6 +29,7 @@ class TransactionDto private Money $amount; private ?string $label; private ?string $notes; + private ?string $remittanceInformation; private string $type; private AbsoluteDate $date; /** @var Transaction */ @@ -70,6 +76,11 @@ public function __construct(array $data) ); $this->label = $data['enrichments']['display_label'] ?? null; $this->notes = $data['enrichments']['notes'] ?? null; + // Linxo sends the ISO 20022 remittance information as one entry per unstructured line + $remittanceInformationLines = $data['remittance_information'] ?? []; + $this->remittanceInformation = [] === $remittanceInformationLines + ? null + : implode(' ', $remittanceInformationLines); $this->type = $data['type'] ?? self::TYPE_OTHER; $this->date = AbsoluteDate::createInTimezone( // Linxo uses timestamps but their servers' timezone is Europe/Paris @@ -104,6 +115,15 @@ public function getNotes(): ?string return $this->notes; } + /** + * Free-text reference sent along with the payment by the counterparty (ISO 20022 remittance information), + * with all its unstructured lines joined by a space + */ + public function getRemittanceInformation(): ?string + { + return $this->remittanceInformation; + } + public function getType(): string { return $this->type; diff --git a/tests/Dto/AccountDtoTest.php b/tests/Dto/AccountDtoTest.php index 33b8513..8d9c10a 100644 --- a/tests/Dto/AccountDtoTest.php +++ b/tests/Dto/AccountDtoTest.php @@ -7,6 +7,7 @@ use AssoConnect\LinxoClient\Dto\AccountDto; use Money\Currency; use Money\Money; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Translation\TranslatableMessage; @@ -161,9 +162,7 @@ public function testGetLocalizedStatusReturnsTranslatableMessage(): void self::assertSame('linxo', $message->getDomain()); } - /** - * @dataProvider statusProvider - */ + #[DataProvider('statusProvider')] public function testAllStatusConstants(string $status): void { $data = $this->createBaseData(['status' => $status]); diff --git a/tests/Dto/ConnectionDtoTest.php b/tests/Dto/ConnectionDtoTest.php index 7af4e84..6547ed0 100644 --- a/tests/Dto/ConnectionDtoTest.php +++ b/tests/Dto/ConnectionDtoTest.php @@ -5,6 +5,7 @@ namespace AssoConnect\LinxoClient\Tests\Dto; use AssoConnect\LinxoClient\Dto\ConnectionDto; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class ConnectionDtoTest extends TestCase @@ -26,9 +27,7 @@ public function testConstructorSetsAllProperties(): void self::assertSame('https://example.com/bnp-logo.png', $dto->getLogoUrl()); } - /** - * @dataProvider statusProvider - */ + #[DataProvider('statusProvider')] public function testAllStatusConstants(string $status): void { $data = $this->createBaseData(['status' => $status]); diff --git a/tests/Dto/TransactionDtoTest.php b/tests/Dto/TransactionDtoTest.php index e83eea3..324329f 100644 --- a/tests/Dto/TransactionDtoTest.php +++ b/tests/Dto/TransactionDtoTest.php @@ -8,6 +8,7 @@ use AssoConnect\PHPDate\AbsoluteDate; use Money\Currency; use Money\Money; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class TransactionDtoTest extends TestCase @@ -27,6 +28,7 @@ public function testConstructorSetsAllProperties(): void 'notes' => 'Weekly groceries', ], 'type' => TransactionDto::TYPE_POINT_OF_SALE, + 'remittance_information' => ['INVOICE 2024-0315'], ]; $dto = new TransactionDto($data); @@ -36,6 +38,7 @@ public function testConstructorSetsAllProperties(): void self::assertSame('Grocery Store Purchase', $dto->getLabel()); self::assertSame('Weekly groceries', $dto->getNotes()); self::assertSame(TransactionDto::TYPE_POINT_OF_SALE, $dto->getType()); + self::assertSame('INVOICE 2024-0315', $dto->getRemittanceInformation()); } public function testAmountConvertedToMoneyInCents(): void @@ -119,6 +122,33 @@ public function testNotesIsNullWhenNotProvided(): void self::assertNull($dto->getNotes()); } + public function testRemittanceInformationLinesAreJoined(): void + { + $data = $this->createBaseData(['remittance_information' => ['INVOICE 2024-0117', 'ORDER 42']]); + + $dto = new TransactionDto($data); + + self::assertSame('INVOICE 2024-0117 ORDER 42', $dto->getRemittanceInformation()); + } + + public function testRemittanceInformationIsNullWhenNotProvided(): void + { + $data = $this->createBaseData(); + + $dto = new TransactionDto($data); + + self::assertNull($dto->getRemittanceInformation()); + } + + public function testRemittanceInformationIsNullWhenNoLineIsProvided(): void + { + $data = $this->createBaseData(['remittance_information' => []]); + + $dto = new TransactionDto($data); + + self::assertNull($dto->getRemittanceInformation()); + } + public function testDateParsedAsAbsoluteDate(): void { $data = $this->createBaseData(['enrichments' => [ @@ -165,9 +195,7 @@ public function testDifferentCurrencies(): void } } - /** - * @dataProvider transactionTypeProvider - */ + #[DataProvider('transactionTypeProvider')] public function testAllTransactionTypeConstants(string $type): void { $data = $this->createBaseData(['type' => $type]);