Completed
Pull Request — master (#38)
by
unknown
04:53
created

PaymentInformation::addTransaction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Z38\SwissPayment\PaymentInformation;
4
5
use DateTime;
6
use DOMDocument;
7
use DOMElement;
8
use InvalidArgumentException;
9
use LogicException;
10
use Z38\SwissPayment\BIC;
11
use Z38\SwissPayment\FinancialInstitutionInterface;
12
use Z38\SwissPayment\IBAN;
13
use Z38\SwissPayment\IID;
14
use Z38\SwissPayment\Money;
15
use Z38\SwissPayment\Text;
16
use Z38\SwissPayment\TransactionInformation\CreditTransfer;
17
18
/**
19
 * PaymentInformation contains a group of transactions as well as details about the debtor
20
 */
21
class PaymentInformation
22
{
23
    /**
24
     * @var string
25
     */
26
    protected $id;
27
28
    /**
29
     * @var array
30
     */
31
    protected $transactions;
32
33
    /**
34
     * @var bool
35
     */
36
    protected $batchBooking;
37
38
    /**
39
     * @var string|null
40
     */
41
    protected $serviceLevel;
42
43
    /**
44
     * @var string|null
45
     */
46
    protected $localInstrument;
47
48
    /**
49
     * @var CategoryPurposeCode|null
50
     */
51
    protected $categoryPurpose;
52
53
    /**
54
     * @var DateTime
55
     */
56
    protected $executionDate;
57
58
    /**
59
     * @var string
60
     */
61
    protected $debtorName;
62
63
    /**
64
     * @var FinancialInstitutionInterface
65
     */
66
    protected $debtorAgent;
67
68
    /**
69
     * @var IBAN
70
     */
71
    protected $debtorIBAN;
72
73
    /**
74
     * Constructor
75
     *
76
     * @param string $id Identifier of this group (should be unique within a message)
77
     * @param string $debtorName Name of the debtor
78
     * @param FinancialInstitutionInterface $debtorAgent BIC or IID of the debtor's financial institution
79
     * @param IBAN $debtorIBAN IBAN of the debtor's account
80
     *
81
     */
82 4
    public function __construct($id, $debtorName, FinancialInstitutionInterface $debtorAgent, IBAN $debtorIBAN)
83
    {
84 4
        if (!$debtorAgent instanceof BIC && !$debtorAgent instanceof IID) {
85 1
            throw new InvalidArgumentException('The debtor agent must be an instance of BIC or IID.');
86
        }
87
88 3
        $this->id = Text::assertIdentifier($id);
89 3
        $this->transactions = [];
90 3
        $this->batchBooking = true;
91 3
        $this->executionDate = new DateTime();
92 3
        $this->debtorName = Text::assert($debtorName, 70);
93 3
        $this->debtorAgent = $debtorAgent;
94 3
        $this->debtorIBAN = $debtorIBAN;
95 3
    }
96
97
    /**
98
     * Adds a single transaction to this payment
99
     *
100
     * @param CreditTransfer $transaction The transaction to be added
101
     *
102
     * @return PaymentInformation This payment instruction
103
     */
104 3
    public function addTransaction(CreditTransfer $transaction)
105
    {
106 3
        $this->transactions[] = $transaction;
107
108 3
        return $this;
109
    }
110
111
    /**
112
     * Gets the number of transactions
113
     *
114
     * @return int Number of transactions
115
     */
116 2
    public function getTransactionCount()
117
    {
118 2
        return count($this->transactions);
119
    }
120
121
    /**
122
     * Gets the sum of transactions
123
     *
124
     * @return Money\Mixed Sum of transactions
125
     */
126 2
    public function getTransactionSum()
127
    {
128 2
        $sum = new Money\Mixed(0);
129
130 2
        foreach ($this->transactions as $transaction) {
131 2
            $sum = $sum->plus($transaction->getAmount());
132 2
        }
133
134 2
        return $sum;
135
    }
136
137
    /**
138
     * Sets the required execution date.
139
     * Where appropriate, the value data is automatically modified to the next possible banking/Post Office working day.
140
     *
141
     * @param DateTime $executionDate
142
     *
143
     * @return PaymentInformation This payment instruction
144
     */
145
    public function setExecutionDate(DateTime $executionDate)
146
    {
147
        $this->executionDate = $executionDate;
148
149
        return $this;
150
    }
151
152
    /**
153
     * Sets the batch booking option.
154
     * It is recommended that one payment instruction is created for each currency transferred.
155
     *
156
     * @param bool $batchBooking
157
     *
158
     * @return PaymentInformation This payment instruction
159
     */
160
    public function setBatchBooking($batchBooking)
161
    {
162
        $this->batchBooking = boolval($batchBooking);
163
164
        return $this;
165
    }
166
167
    /**
168
     * Checks whether the payment type information is included on B- or C-level
169
     *
170
     * @return bool true if it is included on B-level
171
     */
172 4
    public function hasPaymentTypeInformation()
173
    {
174 4
        return ($this->localInstrument !== null || $this->serviceLevel !== null || $this->categoryPurpose !== null);
175
    }
176
177
    /**
178
     * Gets the local instrument
179
     *
180
     * @return string|null The local instrument
181
     */
182
    public function getLocalInstrument()
183
    {
184
        return $this->localInstrument;
185
    }
186
187
    /**
188
     * Gets the service level
189
     *
190
     * @return string|null The service level
191
     */
192
    public function getServiceLevel()
193
    {
194
        return $this->serviceLevel;
195
    }
196
197
    /**
198
     * Sets the category purpose
199
     *
200
     * @param CategoryPurposeCode $categoryPurpose The category purpose
201
     *
202
     * @return PaymentInformation This payment instruction
203
     */
204 3
    public function setCategoryPurpose(CategoryPurposeCode $categoryPurpose)
205
    {
206 3
        $this->categoryPurpose = $categoryPurpose;
207
208 3
        return $this;
209
    }
210
211
    /**
212
     * Builds a DOM tree of this payment instruction
213
     *
214
     * @param DOMDocument $doc
215
     *
216
     * @return DOMElement The built DOM tree
217
     */
218 5
    public function asDom(DOMDocument $doc)
219
    {
220 5
        $root = $doc->createElement('PmtInf');
221
222 5
        $root->appendChild(Text::xml($doc, 'PmtInfId', $this->id));
223 5
        $root->appendChild($doc->createElement('PmtMtd', 'TRF'));
224 5
        $root->appendChild($doc->createElement('BtchBookg', ($this->batchBooking ? 'true' : 'false')));
225
226 5
        $localInstrument = null;
227 5
        $serviceLevel = null;
228
229 5
        if ($this->hasPaymentTypeInformation()) {
230 5
            $paymentType = $doc->createElement('PmtTpInf');
231 5
            $localInstrument = $this->localInstrument ?: $this->inferLocalInstrument();
232 5
            if ($localInstrument !== null) {
233 3
                $localInstrumentNode = $doc->createElement('LclInstrm');
234 3
                $localInstrumentNode->appendChild($doc->createElement('Prtry', $localInstrument));
235 3
                $paymentType->appendChild($localInstrumentNode);
236 3
            }
237 5
            $serviceLevel = $this->serviceLevel ?: $this->inferServiceLevel();
238 5
            if ($serviceLevel !== null) {
239 4
                $serviceLevelNode = $doc->createElement('SvcLvl');
240 4
                $serviceLevelNode->appendChild($doc->createElement('Cd', $serviceLevel));
241 4
                $paymentType->appendChild($serviceLevelNode);
242 4
            }
243 5
            if ($this->categoryPurpose !== null) {
244 3
                $categoryPurposeNode = $doc->createElement('CtgyPurp');
245 3
                $categoryPurposeNode->appendChild($this->categoryPurpose->asDom($doc));
246 3
                $paymentType->appendChild($categoryPurposeNode);
247 3
            }
248 5
            $root->appendChild($paymentType);
249 5
        }
250
251 5
        $root->appendChild($doc->createElement('ReqdExctnDt', $this->executionDate->format('Y-m-d')));
252
253 5
        $debtor = $doc->createElement('Dbtr');
254 5
        $debtor->appendChild(Text::xml($doc, 'Nm', $this->debtorName));
255 5
        $root->appendChild($debtor);
256
257 5
        $debtorAccount = $doc->createElement('DbtrAcct');
258 5
        $debtorAccountId = $doc->createElement('Id');
259 5
        $debtorAccountId->appendChild($doc->createElement('IBAN', $this->debtorIBAN->normalize()));
260 5
        $debtorAccount->appendChild($debtorAccountId);
261 5
        $root->appendChild($debtorAccount);
262
263 5
        $debtorAgent = $doc->createElement('DbtrAgt');
264 5
        $debtorAgent->appendChild($this->debtorAgent->asDom($doc));
265 5
        $root->appendChild($debtorAgent);
266
267 5
        foreach ($this->transactions as $transaction) {
268 5
            if ($this->hasPaymentTypeInformation()) {
269 5
                if ($transaction->getLocalInstrument() !== $localInstrument) {
270
                    throw new LogicException('You can not set the local instrument on B- and C-level.');
271
                }
272 5
                if ($transaction->getServiceLevel() !== $serviceLevel) {
273 1
                    throw new LogicException('You can not set the service level on B- and C-level.');
274
                }
275 4
            }
276 4
            $root->appendChild($transaction->asDom($doc, $this));
277 4
        }
278
279 4
        return $root;
280
    }
281
282 2
    private function inferServiceLevel()
283
    {
284 2
        if (!count($this->transactions)) {
285
            return null;
286
        }
287
288 2
        return $this->transactions[0]->getServiceLevel();
289
    }
290
291 2
    private function inferLocalInstrument()
292
    {
293 2
        if (!count($this->transactions)) {
294
            return null;
295
        }
296
297 2
        return $this->transactions[0]->getLocalInstrument();
298
    }
299
}
300