ToOfx::createSignOnFi()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 10
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Beccha\OfxParser;
6
7
use Beccha\OfxParser\Entity\BankAccount;
8
use Beccha\OfxParser\Entity\SignOn;
9
use XMLWriter;
10
11
class ToOfx
12
{
13
    /**
14
     * @var array<BankAccount>
15
     */
16
    private array $banks;
17
    private SignOn $signOn;
18
19
    /**
20
     * @param array<BankAccount> $banks
21
     */
22
    public function __construct(SignOn $signOn, array $banks)
23
    {
24
        $this->banks = $banks;
25
        $this->signOn = $signOn;
26
    }
27
28
    public function generate(): string
29
    {
30
        $writer = new XMLWriter();
31
        $writer->openMemory();
32
        $writer->startDocument('1.0', 'UTF-8', 'no');
33
        $writer->setIndent(true);
34
        $writer->setIndentString(' ');
35
36
        // Write OFX declaration
37
        $writer->writeRaw(
38
            '<?OFX'
39
            . ' OFXHEADER="200"'
40
            . ' VERSION="211"'
41
            . ' SECURITY="NONE"'
42
            . ' OLDFILEUID="NONE"'
43
            . ' NEWFILEUID="12345678901234567890123456789012"?>'
44
            . "\n"
45
        );
46
47
        $writer->startElement('OFX');
48
        $this->createSignOn($writer);
49
50
        // Banks
51
        foreach ($this->banks as $bank) {
52
            $writer->startElement('BANKMSGSRSV1');
53
            $writer->startElement('STMTTRNRS');
54
            $writer->startElement('TRNUID');
55
            $writer->text($bank->getTransactionUid());
56
            $writer->endElement(); // TRNUID
57
            $writer->startElement('STMTRS');
58
            $writer->startElement('CURDEF');
59
            $writer->text($bank->getStatement()->getCurrency());
60
            $writer->endElement(); // CURDEF
61
            $this->createBankAccountFrom($writer, $bank);
62
            $writer->startElement('BANKTRANLIST');
63
            $writer->startElement('DTSTART');
64
            $writer->text($bank->getStatement()->getStartDate()->format('YmdHis'));
65
            $writer->endElement(); // DTSTART
66
            $writer->startElement('DTEND');
67
            $writer->text($bank->getStatement()->getEndDate()->format('YmdHis'));
68
            $writer->endElement(); // DTEND
69
            foreach ($bank->getStatement()->getTransactions() as $transaction) {
70
                $this->createTransaction($writer, $transaction);
71
            }
72
            $writer->endElement(); // BANKTRANLIST
73
            $this->createLedgerBalance($writer, $bank);
74
            $writer->endElement(); // STMTRS
75
            $writer->endElement(); // STMTTRNRS
76
            $writer->endElement(); // BANKMSGSRSV1
77
        }
78
79
        $writer->endElement(); // OFX
80
        $writer->endDocument();
81
82
        return $writer->outputMemory(true);
83
    }
84
85
    private function createTransaction(XMLWriter $writer, Entity\Transaction $transaction): void
86
    {
87
        $writer->startElement('STMTTRN');
88
        $writer->startElement('TRNTYPE');
89
        $writer->text($transaction->getType());
90
        $writer->endElement(); // TRNTYPE
91
        $writer->startElement('DTPOSTED');
92
        $writer->text($transaction->getDate()->format('YmdHis'));
93
        $writer->endElement(); // DTPOSTED
94
        $writer->startElement('TRNAMT');
95
        $writer->text($this->formatAmount($transaction->getAmount()));
96
        $writer->endElement(); // TRNAMT
97
        $writer->startElement('FITID');
98
        $writer->text($transaction->getUniqueId());
99
        $writer->endElement(); // FITID
100
        $writer->startElement('NAME');
101
        $writer->text($transaction->getName());
102
        $writer->endElement(); // NAME
103
        $writer->startElement('MEMO');
104
        $writer->text($transaction->getMemo());
105
        $writer->endElement(); // NAME
106
        $writer->endElement(); // STMTTRN
107
    }
108
109
    private function createSignOn(XMLWriter $writer): void
110
    {
111
// SignOn
112
        $writer->startElement('SIGNONMSGSRSV1');
113
        $writer->startElement('SONRS');
114
        $this->createServerStatus($writer);
115
        $writer->startElement('DTSERVER');
116
        $writer->text($this->signOn->getDate()->format('YmdHis'));
117
        $writer->endElement(); // DTSERVER
118
        $writer->startElement('LANGUAGE');
119
        $writer->text($this->signOn->getLanguage());
120
        $writer->endElement(); // LANGUAGE
121
        $this->createSignOnFi($writer);
122
        $writer->endElement(); // SONRS
123
        $writer->endElement(); // SIGNONMSGSRSV1
124
    }
125
126
    private function createSignOnFi(XMLWriter $writer): void
127
    {
128
        $writer->startElement('FI');
129
        $writer->startElement('ORG');
130
        $writer->text($this->signOn->getInstitution()->getName());
131
        $writer->endElement(); // ORG
132
        $writer->startElement('FID');
133
        $writer->text($this->signOn->getInstitution()->getId());
134
        $writer->endElement(); // FID
135
        $writer->endElement(); // FI
136
    }
137
138
    private function createServerStatus(XMLWriter $writer): void
139
    {
140
        $writer->startElement('STATUS');
141
        $writer->startElement('CODE');
142
        $writer->text($this->signOn->getStatus()->getCode());
143
        $writer->endElement(); // CODE
144
        $writer->startElement('SEVERITY');
145
        $writer->text($this->signOn->getStatus()->getSeverity());
146
        $writer->endElement(); // SEVERITY
147
        $writer->startElement('MESSAGE');
148
        $writer->text($this->signOn->getStatus()->getMessage());
149
        $writer->endElement(); // MESSAGE
150
        $writer->endElement(); // STATUS
151
    }
152
153
    /**
154
     * @param XMLWriter $writer
155
     * @param BankAccount $bank
156
     * @return void
157
     */
158
    private function createLedgerBalance(XMLWriter $writer, BankAccount $bank): void
159
    {
160
        $writer->startElement('LEDGERBAL');
161
        $writer->startElement('BALAMT');
162
        $writer->text($this->formatAmount($bank->getBalance()));
163
        $writer->endElement(); // BALAMT
164
        $writer->startElement('DTASOF');
165
        $writer->text($bank->getBalanceDate()->format('YmdHis'));
166
        $writer->endElement(); // DTASOF
167
        $writer->endElement(); // LEDGERBAL
168
    }
169
170
    /**
171
     * @param XMLWriter $writer
172
     * @param BankAccount $bank
173
     * @return void
174
     */
175
    private function createBankAccountFrom(XMLWriter $writer, BankAccount $bank): void
176
    {
177
        $writer->startElement('BANKACCTFROM');
178
        $writer->startElement('BANKID');
179
        $writer->text($bank->getRoutingNumber());
180
        $writer->endElement(); // BANKID
181
        $writer->startElement('ACCTID');
182
        $writer->text($bank->getAccountNumber());
183
        $writer->endElement(); // ACCTID
184
        $writer->startElement('ACCTTYPE');
185
        $writer->text($bank->getAccountType());
186
        $writer->endElement(); // ACCTTYPE
187
        $writer->endElement(); // BANKACCTFROM
188
    }
189
190
    private function formatAmount(int $amount): string
191
    {
192
        return number_format((float)\bcdiv((string)$amount, '100', 2), 2, '.', '');
193
    }
194
}
195