Completed
Push — master ( ec86c3...703f3f )
by Hannes
02:24
created

PrintingVisitor::afterIncomingPaymentRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
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\Visitor\Visitor;
26
use byrokrat\autogiro\Exception\RuntimeException;
27
use byrokrat\autogiro\Exception\LogicException;
28
use byrokrat\autogiro\Tree\Node;
29
use byrokrat\autogiro\Tree\Date;
30
use byrokrat\autogiro\Tree\Text;
31
use byrokrat\autogiro\Tree\PayeeBgcNumber;
32
use byrokrat\autogiro\Tree\PayeeBankgiro;
33
use byrokrat\autogiro\Tree\PayerNumber;
34
use byrokrat\autogiro\Tree\Account;
35
use byrokrat\autogiro\Tree\Amount;
36
use byrokrat\autogiro\Tree\Interval;
37
use byrokrat\autogiro\Tree\StateId;
38
use byrokrat\autogiro\Tree\Repetitions;
39
use byrokrat\amount\Currency\SEK;
40
use byrokrat\banking\AccountNumber;
41
use byrokrat\id\IdInterface;
42
use byrokrat\id\PersonalId;
43
use byrokrat\id\OrganizationId;
44
45
/**
46
 * Visitor that generates files to bgc from parse trees
47
 */
48
class PrintingVisitor extends Visitor
49
{
50
    /**
51
     * End-of-line chars used when generating files
52
     */
53
    const EOL = "\r\n";
54
55
    /**
56
     * @var Output
57
     */
58
    private $output;
59
60
    public function setOutput(Output $output): void
61
    {
62
        $this->output = $output;
63
    }
64
65
    public function beforeDate(Date $node): void
66
    {
67
        $this->assertAttribute($node, 'date', \DateTimeInterface::CLASS);
68
        $this->output->write($node->getAttribute('date')->format('Ymd'));
69
    }
70
71
    public function beforeImmediateDate(): void
72
    {
73
        $this->output->write('GENAST  ');
74
    }
75
76
    public function beforeText(Text $node): void
77
    {
78
        $this->output->write($node->getValue());
79
    }
80
81
    public function beforePayeeBgcNumber(PayeeBgcNumber $node): void
82
    {
83
        $this->output->write(str_pad($node->getValue(), 6, '0', STR_PAD_LEFT));
84
    }
85
86
    public function beforePayeeBankgiro(PayeeBankgiro $node): void
87
    {
88
        $this->assertAttribute($node, 'account', AccountNumber::CLASS);
89
        $number = $node->getAttribute('account')->getSerialNumber() . $node->getAttribute('account')->getCheckDigit();
90
        $this->output->write(str_pad($number, 10, '0', STR_PAD_LEFT));
91
    }
92
93
    public function beforePayerNumber(PayerNumber $node): void
94
    {
95
        $this->output->write(str_pad($node->getValue(), 16, '0', STR_PAD_LEFT));
96
    }
97
98
    public function beforeAccount(Account $node): void
99
    {
100
        $this->assertAttribute($node, 'account', AccountNumber::CLASS);
101
        $number = $node->getAttribute('account')->getSerialNumber() . $node->getAttribute('account')->getCheckDigit();
102
        $this->output->write(
103
            $node->getAttribute('account')->getClearingNumber()
104
            . str_pad($number, 12, '0', STR_PAD_LEFT)
105
        );
106
    }
107
108
    public function beforeInterval(Interval $node): void
109
    {
110
        $this->output->write($node->getValue());
111
    }
112
113
    public function beforeRepetitions(Repetitions $node): void
114
    {
115
        $this->output->write($node->getValue());
116
    }
117
118
    public function beforeAmount(Amount $node): void
119
    {
120
        $this->assertAttribute($node, 'amount', SEK::CLASS);
121
122
        $amount = $node->getAttribute('amount');
123
124
        if ($amount->isGreaterThan(new SEK('9999999999.99')) || $amount->isLessThan(new SEK('-9999999999.99'))) {
125
            throw new RuntimeException('Amount must be between 9999999999.99 and -9999999999.99');
126
        }
127
128
        $this->output->write(
129
            str_pad($amount->getSignalString(), 12, '0', STR_PAD_LEFT)
130
        );
131
    }
132
133
    public function beforeStateId(StateId $node): void
134
    {
135
        $this->assertAttribute($node, 'id', IdInterface::CLASS);
136
        if ($node->getAttribute('id') instanceof PersonalId) {
137
            $this->output->write($node->getAttribute('id')->format('Ymdsk'));
138
        }
139
        if ($node->getAttribute('id') instanceof OrganizationId) {
140
            $this->output->write($node->getAttribute('id')->format('00Ssk'));
141
        }
142
    }
143
144
    private function assertAttribute(Node $node, string $attr, string $classname): void
145
    {
146
        if (!$node->hasAttribute($attr) || !$node->getAttribute($attr) instanceof $classname) {
147
            throw new LogicException("Failing attribute '$attr' in {$node->getName()}");
148
        }
149
    }
150
151
    public function beforeRequestOpening(): void
152
    {
153
        $this->output->write('01');
154
    }
155
156
    public function afterRequestOpening(): void
157
    {
158
        $this->output->write(self::EOL);
159
    }
160
161
    public function beforeCreateMandateRequest(): void
162
    {
163
        $this->output->write('04');
164
    }
165
166
    public function afterCreateMandateRequest(): void
167
    {
168
        $this->output->write(self::EOL);
169
    }
170
171
    public function beforeDeleteMandateRequest(): void
172
    {
173
        $this->output->write('03');
174
    }
175
176
    public function afterDeleteMandateRequest(): void
177
    {
178
        $this->output->write(self::EOL);
179
    }
180
181
    public function beforeAcceptDigitalMandateRequest(): void
182
    {
183
        $this->output->write('04');
184
    }
185
186
    public function afterAcceptDigitalMandateRequest(): void
187
    {
188
        $this->output->write(self::EOL);
189
    }
190
191
    public function beforeRejectDigitalMandateRequest(): void
192
    {
193
        $this->output->write('04');
194
    }
195
196
    public function afterRejectDigitalMandateRequest(): void
197
    {
198
        $this->output->write(self::EOL);
199
    }
200
201
    public function beforeUpdateMandateRequest(): void
202
    {
203
        $this->output->write('05');
204
    }
205
206
    public function afterUpdateMandateRequest(): void
207
    {
208
        $this->output->write(self::EOL);
209
    }
210
211
    public function beforeIncomingPaymentRequest(): void
212
    {
213
        $this->output->write('82');
214
    }
215
216
    public function afterIncomingPaymentRequest(): void
217
    {
218
        $this->output->write(self::EOL);
219
    }
220
221
    public function beforeOutgoingPaymentRequest(): void
222
    {
223
        $this->output->write('32');
224
    }
225
226
    public function afterOutgoingPaymentRequest(): void
227
    {
228
        $this->output->write(self::EOL);
229
    }
230
}
231