Completed
Push — master ( 7009cf...36f2c1 )
by Hannes
03:05
created

TreeBuilder::addIncomingPaymentRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
c 0
b 0
f 0
rs 9.4285
cc 1
eloc 16
nc 1
nop 6
1
<?php
2
/**
3
 * This file is part of byrokrat\autogiro.
4
 *
5
 * byrokrat\autogiro is free software: you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License as published
7
 * by the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * byrokrat\autogiro is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with byrokrat\autogiro. If not, see <http://www.gnu.org/licenses/>.
17
 *
18
 * Copyright 2016-18 Hannes Forsgård
19
 */
20
21
declare(strict_types = 1);
22
23
namespace byrokrat\autogiro\Writer;
24
25
use byrokrat\autogiro\Layouts;
26
use byrokrat\autogiro\Tree\RecordNode;
27
use byrokrat\autogiro\Tree\Request\RequestOpening;
28
use byrokrat\autogiro\Tree\Request\AcceptDigitalMandateRequest;
29
use byrokrat\autogiro\Tree\Request\CreateMandateRequest;
30
use byrokrat\autogiro\Tree\Request\DeleteMandateRequest;
31
use byrokrat\autogiro\Tree\Request\RejectDigitalMandateRequest;
32
use byrokrat\autogiro\Tree\Request\UpdateMandateRequest;
33
use byrokrat\autogiro\Tree\Request\IncomingPaymentRequest;
34
use byrokrat\autogiro\Tree\Request\OutgoingPaymentRequest;
35
use byrokrat\autogiro\Tree\Request\MandateRequestSection;
36
use byrokrat\autogiro\Tree\Request\PaymentRequestSection;
37
use byrokrat\autogiro\Tree\Request\AmendmentRequestSection;
38
use byrokrat\autogiro\Tree\FileNode;
39
use byrokrat\autogiro\Tree\DateNode;
40
use byrokrat\autogiro\Tree\ImmediateDateNode;
41
use byrokrat\autogiro\Tree\TextNode;
42
use byrokrat\autogiro\Tree\BgcNumberNode;
43
use byrokrat\autogiro\Tree\BankgiroNode;
44
use byrokrat\autogiro\Tree\PayerNumberNode;
45
use byrokrat\autogiro\Tree\AccountNode;
46
use byrokrat\autogiro\Tree\IdNode;
47
use byrokrat\autogiro\Tree\IntervalNode;
48
use byrokrat\autogiro\Tree\RepetitionsNode;
49
use byrokrat\autogiro\Tree\AmountNode;
50
use byrokrat\banking\AccountNumber;
51
use byrokrat\banking\Bankgiro;
52
use byrokrat\id\IdInterface;
53
use byrokrat\amount\Currency\SEK;
54
55
/**
56
 * Build trees representing autogiro request files
57
 */
58
class TreeBuilder
59
{
60
    /**
61
     * Map section classes to record store array names
62
     */
63
    private const SECTION_TO_RECORD_STORE_MAP = [
64
        MandateRequestSection::CLASS => 'mandates',
65
        PaymentRequestSection::CLASS => 'payments',
66
        AmendmentRequestSection::CLASS => 'amendments'
67
    ];
68
69
    /**
70
     * @var RequestOpening Opening record used for each section
71
     */
72
    private $opening;
73
74
    /**
75
     * @var RecordNode[] List of created mandate requests
76
     */
77
    private $mandates;
78
79
    /**
80
     * @var RecordNode[] List of created payment requests
81
     */
82
    private $payments;
83
84
    /**
85
     * @var RecordNode[] List of created amendment requests
86
     */
87
    private $amendments;
88
89
    /**
90
     * @var string Payee BGC customer number
91
     */
92
    private $bgcNr;
93
94
    /**
95
     * @var BankgiroNode Wrapper around payee bankgiro account number
96
     */
97
    private $payeeBgNode;
98
99
    /**
100
     * @var \DateTimeInterface Date of file creation
101
     */
102
    private $date;
103
104
    /**
105
     * @var IntervalFormatter
106
     */
107
    private $intervalFormatter;
108
109
    /**
110
     * @var RepititionsFormatter
111
     */
112
    private $repititionsFormatter;
113
114
    /**
115
     * @param string               $bgcNr                The BGC customer number of payee
116
     * @param Bankgiro             $bankgiro             Payee bankgiro account number
117
     * @param \DateTimeInterface   $date                 Creation date
118
     * @param IntervalFormatter    $intervalFormatter    Interval formatter
119
     * @param RepititionsFormatter $repititionsFormatter Repititions formatter
120
     */
121
    public function __construct(
122
        string $bgcNr,
123
        Bankgiro $bankgiro,
124
        \DateTimeInterface $date,
125
        IntervalFormatter $intervalFormatter,
126
        RepititionsFormatter $repititionsFormatter
127
    ) {
128
        $this->bgcNr = $bgcNr;
129
        $this->payeeBgNode = BankgiroNode::fromBankgiro($bankgiro);
130
        $this->date = $date;
131
        $this->intervalFormatter = $intervalFormatter;
132
        $this->repititionsFormatter = $repititionsFormatter;
133
        $this->reset();
134
    }
135
136
    /**
137
     * Reset builder to initial state
138
     */
139
    public function reset(): void
140
    {
141
        $this->opening = new RequestOpening(
142
            0,
143
            [
144
                'date' => DateNode::fromDate($this->date),
145
                'autogiro_txt' => new TextNode(0, 'AUTOGIRO'),
146
                'space' => new TextNode(0, str_pad('', 44)),
147
                'payee_bgc_number' => new BgcNumberNode(0, $this->bgcNr),
148
                'payee_bankgiro' => $this->payeeBgNode,
149
                'end' => new TextNode(0, '  ')
150
            ]
151
        );
152
        $this->mandates = [];
153
        $this->payments = [];
154
        $this->amendments = [];
155
    }
156
157
    /**
158
     * Add a new mandate request to tree
159
     */
160
    public function addCreateMandateRequest(string $payerNr, AccountNumber $account, IdInterface $id): void
161
    {
162
        $this->mandates[] = new CreateMandateRequest(
163
            0,
164
            [
165
                'payee_bankgiro' => $this->payeeBgNode,
166
                'payer_number' => new PayerNumberNode(0, $payerNr),
167
                'account' => AccountNode::fromAccount($account),
168
                'id' => IdNode::fromId($id),
169
                'end' => new TextNode(0, str_pad('', 24))
170
            ]
171
        );
172
    }
173
174
    /**
175
     * Add a delete mandate request to tree
176
     */
177
    public function addDeleteMandateRequest(string $payerNr): void
178
    {
179
        $this->mandates[] = new DeleteMandateRequest(
180
            0,
181
            [
182
                'payee_bankgiro' => $this->payeeBgNode,
183
                'payer_number' => new PayerNumberNode(0, $payerNr),
184
                'end' => new TextNode(0, str_pad('', 52))
185
            ]
186
        );
187
    }
188
189
    /**
190
     * Add an accept digital mandate request to tree
191
     */
192
    public function addAcceptDigitalMandateRequest(string $payerNr): void
193
    {
194
        $this->mandates[] = new AcceptDigitalMandateRequest(
195
            0,
196
            [
197
                'payee_bankgiro' => $this->payeeBgNode,
198
                'payer_number' => new PayerNumberNode(0, $payerNr),
199
                'end' => new TextNode(0, str_pad('', 52))
200
            ]
201
        );
202
    }
203
204
    /**
205
     * Add a reject digital mandate request to tree
206
     */
207
    public function addRejectDigitalMandateRequest(string $payerNr): void
208
    {
209
        $this->mandates[] = new RejectDigitalMandateRequest(
210
            0,
211
            [
212
                'payee_bankgiro' => $this->payeeBgNode,
213
                'payer_number' => new PayerNumberNode(0, $payerNr),
214
                'space' => new TextNode(0, str_pad('', 48)),
215
                'reject' => new TextNode(0, 'AV'),
216
                'end' => new TextNode(0, '  ')
217
            ]
218
        );
219
    }
220
221
    /**
222
     * Add an update mandate request to tree
223
     */
224
    public function addUpdateMandateRequest(string $payerNr, string $newPayerNr): void
225
    {
226
        $this->mandates[] = new UpdateMandateRequest(
227
            0,
228
            [
229
                'payee_bankgiro' => $this->payeeBgNode,
230
                'payer_number' => new PayerNumberNode(0, $payerNr),
231
                'new_payee_bankgiro' => $this->payeeBgNode,
232
                'new_payer_number' => new PayerNumberNode(0, $newPayerNr),
233
                'end' => new TextNode(0, str_pad('', 26))
234
            ]
235
        );
236
    }
237
238
    /**
239
     * Add an incoming payment request to tree
240
     */
241
    public function addIncomingPaymentRequest(
242
        string $payerNr,
243
        SEK $amount,
244
        \DateTimeInterface $date,
245
        string $ref,
246
        string $interval,
247
        int $repetitions
248
    ): void {
249
        $this->addPaymentRequest(
250
            IncomingPaymentRequest::CLASS,
251
            $payerNr,
252
            $amount,
253
            $date,
254
            $ref,
255
            $interval,
256
            $repetitions
257
        );
258
    }
259
260
    /**
261
     * Add an outgoing payment request to tree
262
     */
263
    public function addOutgoingPaymentRequest(
264
        string $payerNr,
265
        SEK $amount,
266
        \DateTimeInterface $date,
267
        string $ref,
268
        string $interval,
269
        int $repetitions
270
    ): void {
271
        $this->addPaymentRequest(
272
            OutgoingPaymentRequest::CLASS,
273
            $payerNr,
274
            $amount,
275
            $date,
276
            $ref,
277
            $interval,
278
            $repetitions
279
        );
280
    }
281
282
    /**
283
     * Add an incoming payment at next possible bank date request to tree
284
     */
285
    public function addImmediateIncomingPaymentRequest(string $payerNr, SEK $amount, string $ref): void
286
    {
287
        $this->addImmediatePaymentRequest(IncomingPaymentRequest::CLASS, $payerNr, $amount, $ref);
288
    }
289
290
    /**
291
     * Add an outgoing payment at next possible bank date request to tree
292
     */
293
    public function addImmediateOutgoingPaymentRequest(string $payerNr, SEK $amount, string $ref): void
294
    {
295
        $this->addImmediatePaymentRequest(OutgoingPaymentRequest::CLASS, $payerNr, $amount, $ref);
296
    }
297
298
    /**
299
     * Get the created request tree
300
     */
301
    public function buildTree(): FileNode
302
    {
303
        $sections = [];
304
305
        foreach (self::SECTION_TO_RECORD_STORE_MAP as $sectionClass => $recordStore) {
306
            if (!empty($this->$recordStore)) {
307
                $sections[] = new $sectionClass($this->opening, ...$this->$recordStore);
308
            }
309
        }
310
311
        return new FileNode(Layouts::LAYOUT_REQUEST, ...$sections);
312
    }
313
314
    private function addPaymentRequest(
315
        string $classname,
316
        string $payerNr,
317
        SEK $amount,
318
        \DateTimeInterface $date,
319
        string $ref,
320
        string $interval,
321
        int $repetitions
322
    ): void {
323
        $this->payments[] = new $classname(
324
            0,
325
            [
326
                'date' => DateNode::fromDate($date),
327
                'interval' => new IntervalNode(0, $this->intervalFormatter->format($interval)),
328
                'repetitions' => new RepetitionsNode(0, $this->repititionsFormatter->format($repetitions)),
329
                'space' => new TextNode(0, ' '),
330
                'payer_number' => new PayerNumberNode(0, $payerNr),
331
                'amount' => AmountNode::fromAmount($amount),
332
                'payee_bankgiro' => $this->payeeBgNode,
333
                'reference' => new TextNode(0, str_pad($ref, 16, ' ', STR_PAD_LEFT), '/^.{16}$/'),
334
                'end' => new TextNode(0, str_pad('', 11))
335
            ]
336
        );
337
    }
338
339
    private function addImmediatePaymentRequest(string $classname, string $payerNr, SEK $amount, string $ref): void
340
    {
341
        $this->payments[] = new $classname(
342
            0,
343
            [
344
                'date' => new ImmediateDateNode,
345
                'interval' => new IntervalNode(0, '0'),
346
                'repetitions' => new RepetitionsNode(0, '   '),
347
                'space' => new TextNode(0, ' '),
348
                'payer_number' => new PayerNumberNode(0, $payerNr),
349
                'amount' => AmountNode::fromAmount($amount),
350
                'payee_bankgiro' => $this->payeeBgNode,
351
                'reference' => new TextNode(0, str_pad($ref, 16, ' ', STR_PAD_LEFT), '/^.{16}$/'),
352
                'end' => new TextNode(0, str_pad('', 11))
353
            ]
354
        );
355
    }
356
}
357