Issues (24)

src/Decoder/EntryTransactionDetail.php (3 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Genkgo\Camt\Decoder;
6
7
use Genkgo\Camt\Decoder\Factory\DTO as DTOFactory;
8
use Genkgo\Camt\DTO;
9
use Genkgo\Camt\DTO\RelatedParty;
10
use Genkgo\Camt\DTO\RelatedPartyTypeInterface;
11
use Genkgo\Camt\Util\MoneyFactory;
12
use SimpleXMLElement;
13
14
abstract class EntryTransactionDetail
15
{
16
    private DateDecoderInterface $dateDecoder;
17
18
    private MoneyFactory $moneyFactory;
19
20
    /**
21
     * EntryTransactionDetail constructor.
22
     */
23
    public function __construct(DateDecoderInterface $dateDecoder)
24
    {
25 40
        $this->dateDecoder = $dateDecoder;
26
        $this->moneyFactory = new MoneyFactory();
27 40
    }
28 40
29
    public function addCreditDebitIdentifier(DTO\EntryTransactionDetail $detail, SimpleXMLElement $CdtDbtInd): void
30 24
    {
31
        $creditDebitIdentifier = (string) $CdtDbtInd;
32 24
        $creditDebitIdentifier = in_array($creditDebitIdentifier, ['CRDT', 'DBIT'], true)
33 8
            ? $creditDebitIdentifier
34
            : null;
35
        $detail->setCreditDebitIndicator($creditDebitIdentifier);
36 19
    }
37 19
38
    public function addReference(DTO\EntryTransactionDetail $detail, SimpleXMLElement $xmlDetail): void
39 19
    {
40 19
        if (false === isset($xmlDetail->Refs)) {
41 19
            return;
42 19
        }
43 19
44 19
        $refs = $xmlDetail->Refs;
45 19
        $reference = new DTO\Reference();
46 19
47 19
        $reference->setMessageId(isset($refs->MsgId) ? (string) $refs->MsgId : null);
48 19
        $reference->setAccountServicerReference(isset($refs->AcctSvcrRef) ? (string) $refs->AcctSvcrRef : null);
49 19
        $reference->setPaymentInformationId(isset($refs->PmtInfId) ? (string) $refs->PmtInfId : null);
50 19
        $reference->setInstructionId(isset($refs->InstrId) ? (string) $refs->InstrId : null);
51 19
        $reference->setEndToEndId(isset($refs->EndToEndId) ? (string) $refs->EndToEndId : null);
52
        $reference->setUuidEndToEndReference(isset($refs->UETR) ? (string) $refs->UETR : null);
53 19
        $reference->setTransactionId(isset($refs->TxId) ? (string) $refs->TxId : null);
54 9
        $reference->setMandateId(isset($refs->MndtId) ? (string) $refs->MndtId : null);
55 9
        $reference->setChequeNumber(isset($refs->ChqNb) ? (string) $refs->ChqNb : null);
56
        $reference->setClearingSystemReference(isset($refs->ClrSysRef) ? (string) $refs->ClrSysRef : null);
57 9
        $reference->setAccountOwnerTransactionId(isset($refs->AcctOwnrTxId) ? (string) $refs->AcctOwnrTxId : null);
58
        $reference->setAccountServicerTransactionId(isset($refs->AcctSvcrTxId) ? (string) $refs->AcctSvcrTxId : null);
59
        $reference->setMarketInfrastructureTransactionId(isset($refs->MktInfrstrctrTxId) ? (string) $refs->MktInfrstrctrTxId : null);
60 19
        $reference->setProcessingId(isset($refs->PrcgId) ? (string) $refs->PrcgId : null);
61 19
62
        foreach ($refs->Prtry as $xmlProprietary) {
63 24
            $type = isset($xmlProprietary->Tp) ? (string) $xmlProprietary->Tp : null;
64
            $subReference = isset($xmlProprietary->Ref) ? (string) $xmlProprietary->Ref : null;
65 24
66 1
            $reference->addProprietary(new DTO\ProprietaryReference($type, $subReference));
67
        }
68
69
        $detail->setReference($reference);
70 23
    }
71 23
72 23
    public function addRelatedParties(DTO\EntryTransactionDetail $detail, SimpleXMLElement $xmlDetail): void
73 23
    {
74 23
        if (false === isset($xmlDetail->RltdPties)) {
75 23
            return;
76
        }
77 23
78
        /** @var SimpleXMLElement $xmlRelatedParty */
79
        foreach ($xmlDetail->RltdPties as $xmlRelatedParty) {
80 23
            if (isset($xmlRelatedParty->Cdtr)) {
81 5
                $xmlRelatedPartyType = $xmlRelatedParty->Cdtr;
82 5
                $xmlRelatedPartyTypeAccount = $xmlRelatedParty->CdtrAcct;
83 5
84
                $this->addRelatedParty($detail, $xmlRelatedPartyType, DTO\Creditor::class, $xmlRelatedPartyTypeAccount);
85 5
            }
86
87
            if (isset($xmlRelatedParty->UltmtCdtr)) {
88 23
                $xmlRelatedPartyType = $xmlRelatedParty->UltmtCdtr;
89 20
90 20
                $this->addRelatedParty($detail, $xmlRelatedPartyType, DTO\UltimateCreditor::class);
91 20
            }
92 20
93
            if (isset($xmlRelatedParty->Dbtr)) {
94 20
                $xmlRelatedPartyType = $xmlRelatedParty->Dbtr;
95
                $xmlRelatedPartyTypeAccount = $xmlRelatedParty->DbtrAcct;
96
97 23
                $this->addRelatedParty($detail, $xmlRelatedPartyType, DTO\Debtor::class, $xmlRelatedPartyTypeAccount);
98 5
            }
99 5
100 5
            if (isset($xmlRelatedParty->UltmtDbtr)) {
101
                $xmlRelatedPartyType = $xmlRelatedParty->UltmtDbtr;
102 5
103
                $this->addRelatedParty($detail, $xmlRelatedPartyType, DTO\UltimateDebtor::class);
104
            }
105 23
        }
106
    }
107 23
108
    /**
109 23
     * @param class-string<RelatedPartyTypeInterface> $relatedPartyTypeClass
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<RelatedPartyTypeInterface> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<RelatedPartyTypeInterface>.
Loading history...
110 23
     */
111
    protected function addRelatedParty(DTO\EntryTransactionDetail $detail, SimpleXMLElement $xmlRelatedPartyType, string $relatedPartyTypeClass, ?SimpleXMLElement $xmlRelatedPartyTypeAccount = null): void
112
    {
113 23
        // CAMT v08 uses substructure, so we check for its existence or fallback to the element itself to keep compatibility with CAMT v04
114
        $xmlPartyDetail = $xmlRelatedPartyType->Pty ?: $xmlRelatedPartyType->Agt?->FinInstnId ?: $xmlRelatedPartyType;
115 23
116
        $xmlRelatedPartyName = (isset($xmlPartyDetail->Nm)) ? (string) $xmlPartyDetail->Nm : null;
117 23
        $relatedPartyType = new $relatedPartyTypeClass($xmlRelatedPartyName);
118
119
        if (isset($xmlPartyDetail->PstlAdr)) {
120 22
            $relatedPartyType->setAddress(DTOFactory\Address::createFromXml($xmlPartyDetail->PstlAdr));
121
        }
122 22
123 14
        $relatedParty = new RelatedParty($relatedPartyType, $this->getRelatedPartyAccount($xmlRelatedPartyTypeAccount));
124
125
        $detail->addRelatedParty($relatedParty);
126 17
    }
127 17
128 17
    public function addRelatedAgents(DTO\EntryTransactionDetail $detail, SimpleXMLElement $xmlDetail): void
129 17
    {
130 17
        if (false === isset($xmlDetail->RltdAgts)) {
131
            return;
132
        }
133 17
134 17
        foreach ($xmlDetail->RltdAgts as $xmlRelatedAgent) {
135 17
            if (isset($xmlRelatedAgent->CdtrAgt)) {
136 17
                $agent = new DTO\CreditorAgent((string) $xmlRelatedAgent->CdtrAgt->FinInstnId->Nm, (string) $xmlRelatedAgent->CdtrAgt->FinInstnId->BIC);
137
                $relatedAgent = new DTO\RelatedAgent($agent);
138
                $detail->addRelatedAgent($relatedAgent);
139 17
            }
140
141 25
            if (isset($xmlRelatedAgent->DbtrAgt)) {
142
                $agent = new DTO\DebtorAgent((string) $xmlRelatedAgent->DbtrAgt->FinInstnId->Nm, (string) $xmlRelatedAgent->DbtrAgt->FinInstnId->BIC);
143 25
                $relatedAgent = new DTO\RelatedAgent($agent);
144 8
                $detail->addRelatedAgent($relatedAgent);
145
            }
146
        }
147 20
    }
148 20
149
    public function addRemittanceInformation(DTO\EntryTransactionDetail $detail, SimpleXMLElement $xmlDetail): void
150
    {
151 20
        if (false === isset($xmlDetail->RmtInf)) {
152 20
            return;
153 20
        }
154 10
155 10
        $remittanceInformation = new DTO\RemittanceInformation();
156
        $unstructuredBlockExists = false;
157
158 10
        // Unstructured blocks
159
        $xmlDetailsUnstructuredBlocks = $xmlDetail->RmtInf->Ustrd;
160
        if ($xmlDetailsUnstructuredBlocks !== null) {
161 10
            foreach ($xmlDetailsUnstructuredBlocks as $xmlDetailsUnstructuredBlock) {
162 10
                $unstructuredRemittanceInformation = new DTO\UnstructuredRemittanceInformation(
163 10
                    (string) $xmlDetailsUnstructuredBlock
164 10
                );
165
166
                $remittanceInformation->addUnstructuredBlock($unstructuredRemittanceInformation);
167
168
                // Legacy : use the very first unstructured block
169
                if ($remittanceInformation->getMessage() === null) {
0 ignored issues
show
Deprecated Code introduced by
The function Genkgo\Camt\DTO\Remittan...formation::getMessage() has been deprecated: Use getStructuredBlocks method instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

169
                if (/** @scrutinizer ignore-deprecated */ $remittanceInformation->getMessage() === null) {

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.

Loading history...
170
                    $unstructuredBlockExists = true;
171 20
                    $remittanceInformation->setMessage(
0 ignored issues
show
Deprecated Code introduced by
The function Genkgo\Camt\DTO\Remittan...formation::setMessage() has been deprecated: Use addStructuredBlock method instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

171
                    /** @scrutinizer ignore-deprecated */ $remittanceInformation->setMessage(

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.

Loading history...
172 20
                        (string) $xmlDetailsUnstructuredBlock
173 20
                    );
174 14
                }
175
            }
176 14
        }
177 4
178 4
        // Strutcured blocks
179
        $xmlDetailsStructuredBlocks = $xmlDetail->RmtInf->Strd;
180
        if ($xmlDetailsStructuredBlocks !== null) {
181
            foreach ($xmlDetailsStructuredBlocks as $xmlDetailsStructuredBlock) {
182 14
                $structuredRemittanceInformation = new DTO\StructuredRemittanceInformation();
183 14
184
                if (isset($xmlDetailsStructuredBlock->AddtlRmtInf)) {
185 14
                    $structuredRemittanceInformation->setAdditionalRemittanceInformation(
186 14
                        (string) $xmlDetailsStructuredBlock->AddtlRmtInf
187 14
                    );
188
                }
189
190
                if (isset($xmlDetailsStructuredBlock->CdtrRefInf)) {
191 14
                    $creditorReferenceInformation = new DTO\CreditorReferenceInformation();
192
193
                    if (isset($xmlDetailsStructuredBlock->CdtrRefInf->Ref)) {
194 4
                        $creditorReferenceInformation->setRef(
195 4
                            (string) $xmlDetailsStructuredBlock->CdtrRefInf->Ref
196
                        );
197
                    }
198
199 14
                    if (isset($xmlDetailsStructuredBlock->CdtrRefInf->Tp, $xmlDetailsStructuredBlock->CdtrRefInf->Tp->CdOrPrtry, $xmlDetailsStructuredBlock->CdtrRefInf->Tp->CdOrPrtry->Prtry)
200
201
                    ) {
202 13
                        $creditorReferenceInformation->setProprietary(
203 13
                            (string) $xmlDetailsStructuredBlock->CdtrRefInf->Tp->CdOrPrtry->Prtry
204
                        );
205
                    }
206
207 14
                    if (isset($xmlDetailsStructuredBlock->CdtrRefInf->Tp, $xmlDetailsStructuredBlock->CdtrRefInf->Tp->CdOrPrtry, $xmlDetailsStructuredBlock->CdtrRefInf->Tp->CdOrPrtry->Cd)
208
209
                    ) {
210
                        $creditorReferenceInformation->setCode(
211 14
                            (string) $xmlDetailsStructuredBlock->CdtrRefInf->Tp->CdOrPrtry->Cd
212 14
                        );
213 14
                    }
214
215
                    $structuredRemittanceInformation->setCreditorReferenceInformation($creditorReferenceInformation);
216
217 14
                    // Legacy : do not overwrite message if already defined above
218
                    // and no creditor reference is already defined
219
                    if (false === $unstructuredBlockExists
220
                        && $remittanceInformation->getCreditorReferenceInformation() === null) {
221 20
                        $remittanceInformation->setCreditorReferenceInformation($creditorReferenceInformation);
222 20
                    }
223
                }
224 24
225
                $remittanceInformation->addStructuredBlock($structuredRemittanceInformation);
226 24
            }
227 23
        }
228
229
        $detail->setRemittanceInformation($remittanceInformation);
230 1
    }
231 1
232 1
    public function addRelatedDates(DTO\EntryTransactionDetail $detail, SimpleXMLElement $xmlDetail): void
233
    {
234 1
        if (false === isset($xmlDetail->RltdDts)) {
235
            return;
236 1
        }
237
238
        if (isset($xmlDetail->RltdDts->AccptncDtTm)) {
239
            $RelatedDates = DTO\RelatedDates::fromUnstructured(
240 24
                $this->dateDecoder->decode((string) $xmlDetail->RltdDts->AccptncDtTm)
241
            );
242 24
            $detail->setRelatedDates($RelatedDates);
243 1
244 1
            return;
245 1
        }
246
    }
247 1
248
    public function addReturnInformation(DTO\EntryTransactionDetail $detail, SimpleXMLElement $xmlDetail): void
249 24
    {
250
        if (isset($xmlDetail->RtrInf, $xmlDetail->RtrInf->Rsn->Cd)) {
251 24
            $remittanceInformation = DTO\ReturnInformation::fromUnstructured(
252
                (string) $xmlDetail->RtrInf->Rsn->Cd,
253 24
                (string) $xmlDetail->RtrInf->AddtlInf
254 1
            );
255 1
            $detail->setReturnInformation($remittanceInformation);
256
        }
257 1
    }
258
259 24
    public function addAdditionalTransactionInformation(DTO\EntryTransactionDetail $detail, SimpleXMLElement $xmlDetail): void
260
    {
261 22
        if (isset($xmlDetail->AddtlTxInf)) {
262
            $additionalInformation = new DTO\AdditionalTransactionInformation(
263 22
                (string) $xmlDetail->AddtlTxInf
264
            );
265 22
            $detail->setAdditionalTransactionInformation($additionalInformation);
266 20
        }
267
    }
268 20
269 20
    public function addBankTransactionCode(DTO\EntryTransactionDetail $detail, SimpleXMLElement $xmlDetail): void
270 20
    {
271 20
        $bankTransactionCode = new DTO\BankTransactionCode();
272
273
        if (isset($xmlDetail->BkTxCd)) {
274 20
            $bankTransactionCode = new DTO\BankTransactionCode();
275
276
            if (isset($xmlDetail->BkTxCd->Prtry)) {
277 20
                $proprietaryBankTransactionCode = new DTO\ProprietaryBankTransactionCode(
278 7
                    (string) $xmlDetail->BkTxCd->Prtry->Cd,
279 7
                    (string) $xmlDetail->BkTxCd->Prtry->Issr
280
                );
281
282 7
                $bankTransactionCode->setProprietary($proprietaryBankTransactionCode);
283 7
            }
284 7
285 7
            if (isset($xmlDetail->BkTxCd->Domn)) {
286
                $domainBankTransactionCode = new DTO\DomainBankTransactionCode(
287
                    (string) $xmlDetail->BkTxCd->Domn->Cd
288 7
                );
289
290
                if (isset($xmlDetail->BkTxCd->Domn->Fmly)) {
291 7
                    $domainFamilyBankTransactionCode = new DTO\DomainFamilyBankTransactionCode(
292
                        (string) $xmlDetail->BkTxCd->Domn->Fmly->Cd,
293
                        (string) $xmlDetail->BkTxCd->Domn->Fmly->SubFmlyCd
294
                    );
295 22
296 22
                    $domainBankTransactionCode->setFamily($domainFamilyBankTransactionCode);
297
                }
298 24
299
                $bankTransactionCode->setDomain($domainBankTransactionCode);
300 24
            }
301 4
        }
302
303 4
        $detail->setBankTransactionCode($bankTransactionCode);
304 4
    }
305 4
306
    public function addCharges(DTO\EntryTransactionDetail $detail, SimpleXMLElement $xmlDetail): void
307 4
    {
308
        if (isset($xmlDetail->Chrgs)) {
309
            $charges = new DTO\Charges();
310 4
311 4
            if (isset($xmlDetail->Chrgs->TtlChrgsAndTaxAmt) && (string) $xmlDetail->Chrgs->TtlChrgsAndTaxAmt) {
312
                $money = $this->moneyFactory->create($xmlDetail->Chrgs->TtlChrgsAndTaxAmt, null);
313
314 4
                $charges->setTotalChargesAndTaxAmount($money);
315 4
            }
316
317 4
            $chargesRecords = $xmlDetail->Chrgs->Rcrd;
318 4
            if ($chargesRecords !== null) {
319 4
                /** @var SimpleXMLElement $chargesRecord */
320
                foreach ($chargesRecords as $chargesRecord) {
321 4
                    $chargesDetail = new DTO\ChargesRecord();
322 4
323
                    if (isset($chargesRecord->Amt) && (string) $chargesRecord->Amt) {
324
                        $money = $this->moneyFactory->create($chargesRecord->Amt, $chargesRecord->CdtDbtInd);
325 4
                        $chargesDetail->setAmount($money);
326
                    }
327 4
                    if (isset($chargesRecord->CdtDbtInd) && (string) $chargesRecord->CdtDbtInd === 'true') {
328
                        $chargesDetail->setChargesIncludedIndicator(true);
329
                    }
330 4
                    if (isset($chargesRecord->Tp->Prtry->Id) && (string) $chargesRecord->Tp->Prtry->Id) {
331 4
                        $chargesDetail->setIdentification((string) $chargesRecord->Tp->Prtry->Id);
332
                    }
333 4
                    $charges->addRecord($chargesDetail);
334
                }
335
            }
336 4
            $detail->setCharges($charges);
337
        }
338 24
    }
339
340 23
    public function addAmountDetails(DTO\EntryTransactionDetail $detail, SimpleXMLElement $xmlDetail, SimpleXMLElement $CdtDbtInd): void
341
    {
342 23
        if (isset($xmlDetail->AmtDtls, $xmlDetail->AmtDtls->TxAmt, $xmlDetail->AmtDtls->TxAmt->Amt)) {
343 8
            $money = $this->moneyFactory->create($xmlDetail->AmtDtls->TxAmt->Amt, $CdtDbtInd);
344 8
            $detail->setAmountDetails($money);
345
        }
346 23
    }
347
348 23
    public function addAmount(DTO\EntryTransactionDetail $detail, SimpleXMLElement $xmlDetail, SimpleXMLElement $CdtDbtInd): void
349
    {
350 23
        if (isset($xmlDetail->Amt)) {
351 15
            $money = $this->moneyFactory->create($xmlDetail->Amt, $CdtDbtInd);
352 15
            $detail->setAmount($money);
353
        }
354 23
    }
355
356 16
    abstract public function getRelatedPartyAccount(?SimpleXMLElement $xmlRelatedPartyTypeAccount): ?DTO\Account;
357
}
358