|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
declare(strict_types=1); |
|
4
|
|
|
|
|
5
|
|
|
namespace Genkgo\TestCamt\Unit\Camt053; |
|
6
|
|
|
|
|
7
|
|
|
use DateTimeImmutable; |
|
8
|
|
|
use DOMDocument; |
|
9
|
|
|
use Genkgo\Camt\Camt053\DTO as Camt053DTO; |
|
10
|
|
|
use Genkgo\Camt\Camt053\MessageFormat; |
|
11
|
|
|
use Genkgo\Camt\DTO; |
|
12
|
|
|
use Genkgo\Camt\DTO\Message; |
|
13
|
|
|
use Genkgo\Camt\DTO\OrganisationIdentification; |
|
14
|
|
|
use Genkgo\Camt\DTO\RecordWithBalances; |
|
15
|
|
|
use Genkgo\Camt\Exception\InvalidMessageException; |
|
16
|
|
|
use Genkgo\TestCamt\AbstractTestCase; |
|
17
|
|
|
|
|
18
|
|
|
class EndToEndTest extends AbstractTestCase |
|
19
|
|
|
{ |
|
20
|
|
|
protected function getV2Message(): Message |
|
21
|
|
|
{ |
|
22
|
|
|
$dom = new DOMDocument('1.0', 'UTF-8'); |
|
23
|
|
|
$dom->load(__DIR__ . '/Stubs/camt053.v2.minimal.xml'); |
|
24
|
|
|
|
|
25
|
|
|
return (new MessageFormat\V02())->getDecoder()->decode($dom); |
|
26
|
|
|
} |
|
27
|
|
|
|
|
28
|
|
|
protected function getV2UltimateMessage(): Message |
|
29
|
|
|
{ |
|
30
|
|
|
$dom = new DOMDocument('1.0', 'UTF-8'); |
|
31
|
|
|
$dom->load(__DIR__ . '/Stubs/camt053.v2.minimal.ultimate.xml'); |
|
32
|
|
|
|
|
33
|
|
|
return (new MessageFormat\V02())->getDecoder()->decode($dom); |
|
34
|
|
|
} |
|
35
|
|
|
|
|
36
|
|
|
protected function getV3Message(): Message |
|
37
|
|
|
{ |
|
38
|
|
|
$dom = new DOMDocument('1.0', 'UTF-8'); |
|
39
|
|
|
$dom->load(__DIR__ . '/Stubs/camt053.v3.xml'); |
|
40
|
|
|
|
|
41
|
|
|
return (new MessageFormat\V03())->getDecoder()->decode($dom); |
|
42
|
|
|
} |
|
43
|
|
|
|
|
44
|
|
|
protected function getV4Message(): Message |
|
45
|
|
|
{ |
|
46
|
|
|
$dom = new DOMDocument('1.0', 'UTF-8'); |
|
47
|
|
|
$dom->load(__DIR__ . '/Stubs/camt053.v4.xml'); |
|
48
|
|
|
|
|
49
|
|
|
return (new MessageFormat\V04())->getDecoder()->decode($dom); |
|
50
|
|
|
} |
|
51
|
|
|
|
|
52
|
|
|
public function testWrongDocument(): Message |
|
53
|
|
|
{ |
|
54
|
|
|
$this->expectException(InvalidMessageException::class); |
|
55
|
|
|
|
|
56
|
|
|
$dom = new DOMDocument('1.0', 'UTF-8'); |
|
57
|
|
|
$dom->load(__DIR__ . '/Stubs/camt053.v2.wrong.xml'); |
|
58
|
|
|
|
|
59
|
|
|
return (new MessageFormat\V02())->getDecoder()->decode($dom); |
|
60
|
|
|
} |
|
61
|
|
|
|
|
62
|
|
|
public function testFiveDecimalsStatement(): void |
|
63
|
|
|
{ |
|
64
|
|
|
$dom = new DOMDocument('1.0', 'UTF-8'); |
|
65
|
|
|
$dom->load(__DIR__ . '/Stubs/camt053.v2.five.decimals.xml'); |
|
66
|
|
|
self::assertInstanceOf(Message::class, (new MessageFormat\V02())->getDecoder()->decode($dom)); |
|
67
|
|
|
} |
|
68
|
|
|
|
|
69
|
|
|
public function testV3Document(): void |
|
70
|
|
|
{ |
|
71
|
|
|
$dom = new DOMDocument('1.0', 'UTF-8'); |
|
72
|
|
|
$dom->load(__DIR__ . '/Stubs/camt053.v3.xml'); |
|
73
|
|
|
self::assertInstanceOf(Message::class, (new MessageFormat\V03())->getDecoder()->decode($dom)); |
|
74
|
|
|
} |
|
75
|
|
|
|
|
76
|
|
|
public function testV4Document(): void |
|
77
|
|
|
{ |
|
78
|
|
|
$dom = new DOMDocument('1.0', 'UTF-8'); |
|
79
|
|
|
$dom->load(__DIR__ . '/Stubs/camt053.v4.xml'); |
|
80
|
|
|
self::assertInstanceOf(Message::class, (new MessageFormat\V04())->getDecoder()->decode($dom)); |
|
81
|
|
|
} |
|
82
|
|
|
|
|
83
|
|
|
public function testGroupHeader(): void |
|
84
|
|
|
{ |
|
85
|
|
|
$messages = [ |
|
86
|
|
|
$this->getV2Message(), |
|
87
|
|
|
$this->getV3Message(), |
|
88
|
|
|
$this->getV4Message(), |
|
89
|
|
|
$this->getV2UltimateMessage(), |
|
90
|
|
|
]; |
|
91
|
|
|
|
|
92
|
|
|
/** @var Message $message */ |
|
93
|
|
|
foreach ($messages as $message) { |
|
94
|
|
|
$groupHeader = $message->getGroupHeader(); |
|
95
|
|
|
|
|
96
|
|
|
self::assertInstanceOf(DTO\GroupHeader::class, $groupHeader); |
|
97
|
|
|
self::assertEquals('CAMT053RIB000000000001', $groupHeader->getMessageId()); |
|
98
|
|
|
self::assertEquals(new DateTimeImmutable('2015-03-10T18:43:50+00:00'), $groupHeader->getCreatedOn()); |
|
99
|
|
|
self::assertEquals('Group header additional information', $groupHeader->getAdditionalInformation()); |
|
100
|
|
|
$msgRecipient = $groupHeader->getMessageRecipient(); |
|
101
|
|
|
self::assertInstanceOf(DTO\Recipient::class, $msgRecipient); |
|
102
|
|
|
self::assertEquals('COMPANY BVBA', $msgRecipient->getName()); |
|
103
|
|
|
self::assertEquals('NL', $msgRecipient->getCountryOfResidence()); |
|
104
|
|
|
self::assertInstanceOf(DTO\Address::class, $msgRecipient->getAddress()); |
|
105
|
|
|
self::assertEquals('12 Oxford Street', $msgRecipient->getAddress()->getStreetName()); |
|
106
|
|
|
self::assertEquals('UK', $msgRecipient->getAddress()->getCountry()); |
|
107
|
|
|
|
|
108
|
|
|
/** @var OrganisationIdentification $identification */ |
|
109
|
|
|
$identification = $msgRecipient->getIdentification(); |
|
110
|
|
|
self::assertInstanceOf(DTO\Identification::class, $identification); |
|
111
|
|
|
self::assertEquals('DABAIE2D', $identification->getBic()); |
|
112
|
|
|
self::assertEquals('Some other Id', $identification->getOtherId()); |
|
113
|
|
|
self::assertEquals('Some other Issuer', $identification->getOtherIssuer()); |
|
114
|
|
|
} |
|
115
|
|
|
} |
|
116
|
|
|
|
|
117
|
|
|
public function testStatements(): void |
|
118
|
|
|
{ |
|
119
|
|
|
$messages = [ |
|
120
|
|
|
$this->getV2Message(), |
|
121
|
|
|
$this->getV3Message(), |
|
122
|
|
|
$this->getV4Message(), |
|
123
|
|
|
$this->getV2UltimateMessage(), |
|
124
|
|
|
]; |
|
125
|
|
|
|
|
126
|
|
|
foreach ($messages as $message) { |
|
127
|
|
|
$statements = $message->getRecords(); |
|
128
|
|
|
|
|
129
|
|
|
self::assertCount(1, $statements); |
|
130
|
|
|
foreach ($statements as $statement) { |
|
131
|
|
|
self::assertInstanceOf(Camt053DTO\Statement::class, $statement); |
|
132
|
|
|
self::assertEquals('253EURNL26VAYB8060476890', $statement->getId()); |
|
133
|
|
|
self::assertEquals('NL26VAYB8060476890', $statement->getAccount()->getIdentification()); |
|
134
|
|
|
self::assertEquals(new DateTimeImmutable('2015-03-10T18:43:50+00:00'), $statement->getCreatedOn()); |
|
135
|
|
|
|
|
136
|
|
|
self::assertEquals('12312', $statement->getElectronicSequenceNumber()); |
|
137
|
|
|
self::assertEquals('12312', $statement->getLegalSequenceNumber()); |
|
138
|
|
|
self::assertEquals('CODU', $statement->getCopyDuplicateIndicator()); |
|
139
|
|
|
self::assertEquals(new DateTimeImmutable('2007-10-18T08:00:00+01:00'), $statement->getFromDate()); |
|
140
|
|
|
self::assertEquals(new DateTimeImmutable('2007-10-18T12:30:00+01:00'), $statement->getToDate()); |
|
141
|
|
|
self::assertEquals('Additional Information', $statement->getAdditionalInformation()); |
|
142
|
|
|
} |
|
143
|
|
|
} |
|
144
|
|
|
|
|
145
|
|
|
$statementV4 = $messages[2]->getRecords()[0]; |
|
146
|
|
|
self::assertInstanceOf(DTO\Pagination::class, $statementV4->getPagination()); |
|
147
|
|
|
self::assertEquals('2', $statementV4->getPagination()->getPageNumber()); |
|
148
|
|
|
self::assertTrue($statementV4->getPagination()->isLastPage()); |
|
149
|
|
|
} |
|
150
|
|
|
|
|
151
|
|
|
public function testBalance(): void |
|
152
|
|
|
{ |
|
153
|
|
|
$messages = [ |
|
154
|
|
|
$this->getV2Message(), |
|
155
|
|
|
$this->getV3Message(), |
|
156
|
|
|
$this->getV4Message(), |
|
157
|
|
|
$this->getV2UltimateMessage(), |
|
158
|
|
|
]; |
|
159
|
|
|
|
|
160
|
|
|
foreach ($messages as $message) { |
|
161
|
|
|
$statements = $message->getRecords(); |
|
162
|
|
|
self::assertCount(1, $statements); |
|
163
|
|
|
|
|
164
|
|
|
/** @var RecordWithBalances $statement */ |
|
165
|
|
|
foreach ($statements as $statement) { |
|
166
|
|
|
$actual = $this->extractBalances($statement); |
|
167
|
|
|
$expected = [ |
|
168
|
|
|
[ |
|
169
|
|
|
'amount' => '1815', |
|
170
|
|
|
'code' => 'EUR', |
|
171
|
|
|
'type' => 'opening', |
|
172
|
|
|
], |
|
173
|
|
|
[ |
|
174
|
|
|
'amount' => '-2700', |
|
175
|
|
|
'code' => 'SEK', |
|
176
|
|
|
'type' => 'closing', |
|
177
|
|
|
], |
|
178
|
|
|
[ |
|
179
|
|
|
'amount' => '3500', |
|
180
|
|
|
'code' => 'CHF', |
|
181
|
|
|
'type' => 'opening_available', |
|
182
|
|
|
], |
|
183
|
|
|
[ |
|
184
|
|
|
'amount' => '-2700', |
|
185
|
|
|
'code' => 'JPY', |
|
186
|
|
|
'type' => 'closing_available', |
|
187
|
|
|
], |
|
188
|
|
|
]; |
|
189
|
|
|
|
|
190
|
|
|
self::assertSame($expected, $actual); |
|
191
|
|
|
} |
|
192
|
|
|
} |
|
193
|
|
|
} |
|
194
|
|
|
|
|
195
|
|
|
private function extractBalances(RecordWithBalances $statement): array |
|
196
|
|
|
{ |
|
197
|
|
|
$result = []; |
|
198
|
|
|
foreach ($statement->getBalances() as $balance) { |
|
199
|
|
|
$result[] = [ |
|
200
|
|
|
'amount' => $balance->getAmount()->getAmount(), |
|
201
|
|
|
'code' => $balance->getAmount()->getCurrency()->getCode(), |
|
202
|
|
|
'type' => $balance->getType(), |
|
203
|
|
|
]; |
|
204
|
|
|
} |
|
205
|
|
|
|
|
206
|
|
|
return $result; |
|
207
|
|
|
} |
|
208
|
|
|
|
|
209
|
|
|
public function testEntries(): void |
|
210
|
|
|
{ |
|
211
|
|
|
$messages = [ |
|
212
|
|
|
$this->getV2Message(), |
|
213
|
|
|
$this->getV3Message(), |
|
214
|
|
|
$this->getV4Message(), |
|
215
|
|
|
$this->getV2UltimateMessage(), |
|
216
|
|
|
]; |
|
217
|
|
|
|
|
218
|
|
|
foreach ($messages as $message) { |
|
219
|
|
|
$statements = $message->getRecords(); |
|
220
|
|
|
|
|
221
|
|
|
self::assertCount(1, $statements); |
|
222
|
|
|
foreach ($statements as $statement) { |
|
223
|
|
|
$entries = $statement->getEntries(); |
|
224
|
|
|
self::assertCount(1, $entries); |
|
225
|
|
|
|
|
226
|
|
|
foreach ($entries as $entry) { |
|
227
|
|
|
self::assertEquals(885, $entry->getAmount()->getAmount()); |
|
228
|
|
|
self::assertEquals('EUR', $entry->getAmount()->getCurrency()->getCode()); |
|
229
|
|
|
self::assertEquals('2014-12-31', $entry->getBookingDate()->format('Y-m-d')); |
|
230
|
|
|
self::assertEquals('2015-01-02', $entry->getValueDate()->format('Y-m-d')); |
|
231
|
|
|
|
|
232
|
|
|
$details = $entry->getTransactionDetails(); |
|
233
|
|
|
self::assertCount(1, $details); |
|
234
|
|
|
foreach ($details as $detail) { |
|
235
|
|
|
$parties = $detail->getRelatedParties(); |
|
236
|
|
|
self::assertCount(2, $parties); |
|
237
|
|
|
|
|
238
|
|
|
foreach ($parties as $party) { |
|
239
|
|
|
if ($party->getRelatedPartyType() instanceof DTO\Creditor) { |
|
240
|
|
|
if ($party->getRelatedPartyType() instanceof DTO\UltimateCreditor) { |
|
241
|
|
|
self::assertEquals('CREDITOR NAME NM', $party->getRelatedPartyType()->getName()); |
|
242
|
|
|
self::assertEquals(['CREDITOR NAME', 'CREDITOR ADD'], $party->getRelatedPartyType()->getAddress()->getAddressLines()); |
|
243
|
|
|
} else { |
|
244
|
|
|
self::assertEquals('Company Name', $party->getRelatedPartyType()->getName()); |
|
245
|
|
|
self::assertEquals('NL', $party->getRelatedPartyType()->getAddress()->getCountry()); |
|
246
|
|
|
self::assertEquals([], $party->getRelatedPartyType()->getAddress()->getAddressLines()); |
|
247
|
|
|
self::assertEquals('NL56AGDH9619008421', (string) $party->getAccount()->getIdentification()); |
|
248
|
|
|
} |
|
249
|
|
|
} elseif ($party->getRelatedPartyType() instanceof DTO\Debtor) { |
|
250
|
|
|
if ($party->getRelatedPartyType() instanceof DTO\UltimateDebtor) { |
|
251
|
|
|
self::assertEquals('DEBTOR NAME NM', $party->getRelatedPartyType()->getName()); |
|
252
|
|
|
self::assertEquals(['DEBTOR NAME', 'DEBTOR ADD'], $party->getRelatedPartyType()->getAddress()->getAddressLines()); |
|
253
|
|
|
} else { |
|
254
|
|
|
self::assertEquals('NAME NAME', $party->getRelatedPartyType()->getName()); |
|
255
|
|
|
self::assertEquals('NL', $party->getRelatedPartyType()->getAddress()->getCountry()); |
|
256
|
|
|
self::assertEquals(['ADDR ADDR 10', '2000 ANTWERPEN'], $party->getRelatedPartyType()->getAddress()->getAddressLines()); |
|
257
|
|
|
self::assertEquals('NL56AGDH9619008421', (string) $party->getAccount()->getIdentification()); |
|
258
|
|
|
} |
|
259
|
|
|
} |
|
260
|
|
|
} |
|
261
|
|
|
|
|
262
|
|
|
$reference = $detail->getReference(); |
|
263
|
|
|
self::assertEquals('LegalSequenceNumber', $reference->getProprietaries()[0]->getType()); |
|
264
|
|
|
self::assertEquals('100', $reference->getProprietaries()[0]->getReference()); |
|
265
|
|
|
self::assertNull($reference->getMandateId()); |
|
266
|
|
|
|
|
267
|
|
|
$remittanceInformation = $detail->getRemittanceInformation(); |
|
268
|
|
|
self::assertEquals('4654654654654654', $remittanceInformation->getCreditorReferenceInformation()->getRef()); |
|
269
|
|
|
} |
|
270
|
|
|
} |
|
271
|
|
|
} |
|
272
|
|
|
} |
|
273
|
|
|
} |
|
274
|
|
|
|
|
275
|
|
|
public function testStructuredMessage(): void |
|
276
|
|
|
{ |
|
277
|
|
|
$messages = [ |
|
278
|
|
|
$this->getV2Message(), |
|
279
|
|
|
$this->getV3Message(), |
|
280
|
|
|
$this->getV4Message(), |
|
281
|
|
|
$this->getV2UltimateMessage(), |
|
282
|
|
|
]; |
|
283
|
|
|
|
|
284
|
|
|
foreach ($messages as $message) { |
|
285
|
|
|
$statements = $message->getRecords(); |
|
286
|
|
|
|
|
287
|
|
|
self::assertCount(1, $statements); |
|
288
|
|
|
foreach ($statements as $statement) { |
|
289
|
|
|
$entries = $statement->getEntries(); |
|
290
|
|
|
self::assertCount(1, $entries); |
|
291
|
|
|
|
|
292
|
|
|
foreach ($entries as $entry) { |
|
293
|
|
|
$details = $entry->getTransactionDetails(); |
|
294
|
|
|
self::assertCount(1, $details); |
|
295
|
|
|
foreach ($details as $detail) { |
|
296
|
|
|
$remittanceInformation = $detail->getRemittanceInformation(); |
|
297
|
|
|
self::assertEquals('4654654654654654', $remittanceInformation->getMessage()); |
|
|
|
|
|
|
298
|
|
|
} |
|
299
|
|
|
} |
|
300
|
|
|
} |
|
301
|
|
|
} |
|
302
|
|
|
} |
|
303
|
|
|
} |
|
304
|
|
|
|
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.