PaymentOrderSEPAExporter   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 165
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 68
dl 0
loc 165
rs 10
c 1
b 0
f 0
wmc 16

4 Methods

Rating   Name   Duplication   Size   Complexity  
A exportAuto() 0 37 4
B exportUsingGivenIBAN() 0 70 6
A exportAutoSingle() 0 22 5
A __construct() 0 4 1
1
<?php
2
/*
3
 * Copyright (C) 2020  Jan Böhmer
4
 *
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU Affero 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
 * This program 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 Affero General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Affero General Public License
16
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17
 */
18
19
namespace App\Services\SEPAExport;
20
21
use App\Entity\BankAccount;
22
use App\Entity\PaymentOrder;
23
use App\Entity\SEPAExport;
24
use App\Exception\SEPAExportAutoModeNotPossible;
25
use App\Helpers\SEPAXML\SEPAXMLExportResult;
26
use Digitick\Sepa\DomBuilder\BaseDomBuilder;
27
use Digitick\Sepa\DomBuilder\DomBuilderFactory;
28
use Digitick\Sepa\PaymentInformation;
29
use Digitick\Sepa\TransferFile\CustomerCreditTransferFile;
30
use Digitick\Sepa\TransferInformation\CustomerCreditTransferInformation;
31
use Doctrine\Common\Collections\ArrayCollection;
32
use Webmozart\Assert\Assert;
33
34
final class PaymentOrderSEPAExporter
35
{
36
    /** @var GroupHeaderHelper */
37
    private $group_header_helper;
38
39
    /** @var SEPAExportGroupAndSplitHelper */
40
    private $splitHelper;
41
42
    public function __construct(GroupHeaderHelper $group_header_helper, SEPAExportGroupAndSplitHelper $splitHelper)
43
    {
44
        $this->group_header_helper = $group_header_helper;
45
        $this->splitHelper = $splitHelper;
46
    }
47
48
    /**
49
     * Exports the given payment orders and automatically assign the used bank accounts.
50
     * For this the bankaccount of the associated departments are used, and the FSR-Kom bank account if a payment is an
51
     * FSR-Kom transaction.
52
     * @param  PaymentOrder[]  $payment_orders The payment orders which should be exported
53
     * @throws SEPAExportAutoModeNotPossible If an element has no assigned default bank account, then automatic mode is not possible
54
     * @return SEPAXMLExportResult
55
     */
56
    public function exportAuto(array $payment_orders): SEPAXMLExportResult
57
    {
58
        //First we have to group the payment orders according to their bank accounts
59
        $results = $this->splitHelper->groupAndSplitPaymentOrdersForAutoExport($payment_orders);
60
61
        $exports = [];
62
63
        //Export each group on its own
64
        foreach ($results as $bank_account)
65
        {
66
            /** @var BankAccount $bank_account */
67
            /** @var PaymentOrder[][] $file */
68
            $file = $results[$bank_account];
69
70
            $file_number = 1;
71
            $max_number = count($file);
72
73
            foreach ($file as $group) {
74
                $tmp = $this->exportUsingGivenIBAN(
75
                    $group,
76
                    $bank_account->getIbanWithoutSpaces(),
77
                    $bank_account->getBic(),
78
                    $bank_account->getExportAccountName()
79
                );
80
81
                $description = $bank_account->getExportAccountName();
82
                if ($max_number > 1)
83
                {
84
                    $description .= ' ' . $file_number . ' / ' . $max_number;
85
                }
86
                $tmp->setDescription($description);
87
88
                $exports[] = $tmp;
89
            }
90
        }
91
92
        return new SEPAXMLExportResult($exports);
93
    }
94
95
    /**
96
     * Exports the given payment orders and automatically assign the used bank accounts.
97
     * Each payment order is put into its own file.
98
     * For this the bankaccount of the associated departments are used, and the FSR-Kom bank account if a payment is an
99
     * FSR-Kom transaction.
100
     * @param  PaymentOrder[]  $payment_orders The payment orders which should be exported
101
     * @throws SEPAExportAutoModeNotPossible If an element has no assigned default bank account, then automatic mode is not possible
102
     * @return SEPAXMLExportResult
103
     */
104
    public function exportAutoSingle(array $payment_orders): SEPAXMLExportResult
105
    {
106
        $exports = [];
107
108
        //Export each group on its own
109
        foreach ($payment_orders as $paymentOrder)
110
        {
111
            if ($paymentOrder->isFsrKomResolution()) {
112
                $bank_account = $this->splitHelper->getFSRKomBankAccount();
113
            } elseif ($paymentOrder->getDepartment() !== null && $paymentOrder->getDepartment()->getBankAccount() !== null) {
114
                $bank_account = $paymentOrder->getDepartment()->getBankAccount();
115
            } else {
116
                throw new SEPAExportAutoModeNotPossible($paymentOrder->getDepartment());
117
            }
118
119
            $tmp = $this->exportUsingGivenIBAN([$paymentOrder], $bank_account->getIbanWithoutSpaces(), $bank_account->getBic(), $bank_account->getExportAccountName());
120
            $tmp->setDescription($paymentOrder->getIDString());
121
122
            $exports[] = $tmp;
123
        }
124
125
        return new SEPAXMLExportResult($exports);
126
    }
127
128
129
    public function exportUsingGivenIBAN(array $payment_orders, string $debtor_iban, string $debtor_bic, string $debtor_account_name): SEPAExport
130
    {
131
        //We need IBAN without spaces
132
        $debtor_iban = str_replace(" ", "", $debtor_iban);
133
134
        $groupHeader = $this->group_header_helper->getGroupHeader($debtor_bic);
135
        $sepaFile = new CustomerCreditTransferFile($groupHeader);
136
137
        $payment = new PaymentInformation(
138
            md5(random_bytes(50)), //Use a random payment identifier ID
139
            $debtor_iban,
140
            $debtor_bic,
141
            $debtor_account_name
142
        );
143
144
        //Disable batch booking, as the commerzbank does not show details for "Sammelüberweisungen"
145
        $payment->setBatchBooking(false);
146
147
        //Add each payment order as transaction
148
        foreach ($payment_orders as $payment_order) {
149
            //Ensure that type is correct
150
            if (!$payment_order instanceof PaymentOrder) {
151
                throw new \InvalidArgumentException('$payment_orders must be an array of PaymentOrder elements!');
152
            }
153
154
            //Ensure that the ID is available
155
            if (!$payment_order->getId() === null) {
156
                throw new \InvalidArgumentException('A payment order that should be exported misses an ID. All payment orders must have been persisted!');
157
            }
158
159
            $transfer = new CustomerCreditTransferInformation(
160
                $payment_order->getAmount(),
161
                $payment_order->getBankInfo()->getIbanWithoutSpaces(),
162
                $payment_order->getBankInfo()->getAccountOwner()
163
            );
164
165
            //BIC is optional, only set it if it was set.
166
            if (!empty($payment_order->getBankInfo()->getBic())) {
167
                $transfer->setBic($payment_order->getBankInfo()->getBic());
168
            }
169
170
            //We use the ID String of the payment order as end to end reference
171
            $transfer->setEndToEndIdentification($payment_order->getIDString());
172
            //Set the reference ID of the payment order as
173
            $transfer->setRemittanceInformation($payment_order->getBankInfo()->getReference());
174
175
            $payment->addTransfer($transfer);
176
        }
177
178
        //Add payment infos to SEPA file
179
        $sepaFile->addPaymentInformation($payment);
180
181
        // We have to use the format 'pain.001.001.03'
182
        $domBuilder = DomBuilderFactory::createDomBuilder($sepaFile, 'pain.001.001.03');
183
184
        if (!$domBuilder instanceof BaseDomBuilder) {
0 ignored issues
show
introduced by
$domBuilder is always a sub-type of Digitick\Sepa\DomBuilder\BaseDomBuilder.
Loading history...
185
            throw new \RuntimeException('$domBuilder must be an BaseDomBuilder instance!');
186
        }
187
188
        //Create a temporary file with the XML content
189
        $xml_string = $domBuilder->asXml();
190
191
        //We use the format YYYYMMDDHHmmss_MsgID.xml
192
        $original_filename = sprintf("%s_%s.xml",
193
            (new \DateTime())->format('YmdHis'),
194
            $groupHeader->getMessageIdentification(),
195
        );
196
197
        return SEPAExport::createFromXMLString($xml_string, $original_filename)
198
            ->setAssociatedPaymentOrders(new ArrayCollection($payment_orders));
199
    }
200
201
202
203
204
}