Passed
Push — GENERAL_BUG_REVIEW_240911 ( c757bd...0ad96d )
by Rafael
45:56
created

ModelePDFFactures::getSwissQrBill()   C

Complexity

Conditions 14
Paths 26

Size

Total Lines 101
Code Lines 60

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 14
eloc 60
nc 26
nop 2
dl 0
loc 101
rs 6.2666
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/* Copyright (C) 2003-2005  Rodolphe Quiedeville        <[email protected]>
4
 * Copyright (C) 2004-2011  Laurent Destailleur         <[email protected]>
5
 * Copyright (C) 2004       Eric Seigne                 <[email protected]>
6
 * Copyright (C) 2005-2012  Regis Houssin               <[email protected]>
7
 * Copyright (C) 2014       Marcos García               <[email protected]>
8
 * Copyright (C) 2024       Rafael San José             <[email protected]>
9
 *
10
 * This program is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 3 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22
 * or see https://www.gnu.org/
23
 */
24
25
namespace Dolibarr\Code\Facture\Classes;
26
27
use Dolibarr\Code\Compta\Classes\Facture;
28
use Dolibarr\Code\Core\Classes\CommonDocGenerator;
29
use Dolibarr\Code\Core\Classes\Translate;
30
use DoliDB;
31
use Sprain\SwissQrBill;
32
33
// use Sprain\SwissQrBill: For the experimental feature using swiss QR invoice generated by composer lib sparin/swiss-qr-bill
34
35
/**
36
 *  \file       htdocs/core/modules/facture/modules_facture.php
37
 *  \ingroup    invoice
38
 *  \brief      File that contains parent class for invoices models
39
 *              and parent class for invoices numbering models
40
 */
41
42
43
/**
44
 *  Parent class of invoice document generators
45
 */
46
abstract class ModelePDFFactures extends CommonDocGenerator
47
{
48
    public $posxpicture;
49
    public $posxtva;
50
    public $posxup;
51
    public $posxqty;
52
    public $posxunit;
53
    public $posxdesc;
54
    public $posxdiscount;
55
    public $postotalht;
56
57
    public $tva;
58
    public $tva_array;
59
    public $localtax1;
60
    public $localtax2;
61
62
    public $atleastonediscount = 0;
63
    public $atleastoneratenotnull = 0;
64
65
66
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
67
68
    /**
69
     *  Return list of active generation modules
70
     *
71
     * @param DoliDB $db Database handler
72
     * @param integer $maxfilenamelength Max length of value to show
73
     * @return array                       List of templates
74
     */
75
    public static function liste_modeles($db, $maxfilenamelength = 0)
76
    {
77
        // phpcs:enable
78
        $type = 'invoice';
79
        $list = array();
80
81
        include_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php';
82
        $list = getListOfModels($db, $type, $maxfilenamelength);
83
84
        return $list;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $list also could return the type integer which is incompatible with the documented return type array.
Loading history...
85
    }
86
87
    /**
88
     * Add SwissQR invoice at bottom of page 1
89
     *
90
     * @param TCPDF $pdf TCPDF object
91
     * @param Facture $object Invoice object
92
     * @param Translate $langs Translation object
93
     * @return bool                 True for for success
94
     */
95
    public function addBottomQRInvoice(TCPDF $pdf, Facture $object, Translate $langs): bool
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Facture\Classes\TCPDF was not found. Did you mean TCPDF? If so, make sure to prefix the type with \.
Loading history...
96
    {
97
        if (!($qrBill = $this->getSwissQrBill($object, $langs))) {
98
            return false;
99
        }
100
101
        try {
102
            $pdf->startTransaction();
103
104
            $pdf->setPage(1);
105
            $pdf->SetTextColor(0, 0, 0);
106
            $output = new SwissQrBill\PaymentPart\Output\TcPdfOutput\TcPdfOutput($qrBill, in_array($langs->shortlang, ['de', 'fr', 'it']) ? $langs->shortlang : 'en', $pdf);
107
            $output->setPrintable(false)->getPaymentPart();
108
        } catch (Exception $e) {
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Facture\Classes\Exception was not found. Did you mean Exception? If so, make sure to prefix the type with \.
Loading history...
109
            $pdf->rollbackTransaction(true);
110
            return false;
111
        }
112
        return true;
113
    }
114
115
    /**
116
     * Get the height for bottom-page QR invoice in mm, depending on the page number.
117
     *
118
     * @param int $pagenbr Page number
119
     * @param Facture $object Invoice object
120
     * @param Translate $langs Translation object
121
     * @return int                  Height in mm of the bottom-page QR invoice. Can be zero if not on right page; not enabled
122
     */
123
    protected function getHeightForQRInvoice(int $pagenbr, Facture $object, Translate $langs)
124
    {
125
        if (getDolGlobalString('INVOICE_ADD_SWISS_QR_CODE') == 'bottom') {
126
            // Keep it, to reset it after QRinvoice getter
127
            $error = $this->error;
128
129
            if (!$this->getSwissQrBill($object, $langs)) {
130
                // Reset error to previous one if exists
131
                if (!empty($error)) {
132
                    $this->error = $error;
133
                }
134
                return 0;
135
            }
136
            // SWIFT's requirementis 105, but we get more room with 100 and the page number is in a nice place.
137
            return $pagenbr == 1 ? 100 : 0;
138
        }
139
140
        return 0;
141
    }
142
143
    /**
144
     * Get the SwissQR object, including validation
145
     *
146
     * @param Facture $object Invoice object
147
     * @param Translate $langs Translation object
148
     * @return  SwissQrBill\QrBill|bool             The valid SwissQR object, or false
149
     */
150
    private function getSwissQrBill(Facture $object, Translate $langs)
151
    {
152
        global $conf;
153
154
        if (getDolGlobalString('INVOICE_ADD_SWISS_QR_CODE') != 'bottom') {
155
            return false;
156
        }
157
158
        if ($object->mode_reglement_code != 'VIR') {
159
            $this->error = $langs->transnoentities("SwissQrOnlyVIR");
160
            return false;
161
        }
162
163
        if (empty($object->fk_account)) {
164
            $this->error = 'Bank account must be defined to use this experimental feature';
165
            return false;
166
        }
167
168
        // Load the autoload file generated by composer
169
        if (file_exists(DOL_DOCUMENT_ROOT . '/includes/sprain/swiss-qr-bill/autoload.php')) {
170
            require_once constant('DOL_DOCUMENT_ROOT') . '/includes/sprain/swiss-qr-bill/autoload.php';
171
        } elseif (file_exists(DOL_DOCUMENT_ROOT . '/includes/autoload.php')) {
172
            require_once constant('DOL_DOCUMENT_ROOT') . '/includes/autoload.php';
173
        } else {
174
            $this->error = 'PHP library sprain/swiss-qr-bill was not found. Please install it with:<br>cd ' . dirname(DOL_DOCUMENT_ROOT) . '; cp composer.json.disabled composer.json; composer require sprain/swiss-qr-bill;';
175
            return false;
176
        }
177
178
        // Create a new instance of SwissQrBill, containing default headers with fixed values
179
        $qrBill = SwissQrBill\QrBill::create();
180
181
        // First, set creditor address
182
        $address = SwissQrBill\DataGroup\Element\CombinedAddress::create(
183
            $this->emetteur->name,
184
            $this->emetteur->address,
185
            $this->emetteur->zip . " " . $this->emetteur->town,
186
            $this->emetteur->country_code
187
        );
188
        if (!$address->isValid()) {
189
            $this->error = $langs->transnoentities("SwissQrCreditorAddressInvalid", (string)$address->getViolations());
190
            return false;
191
        }
192
        $qrBill->setCreditor($address);
193
194
        // Get IBAN from account.
195
        $account = new Account($this->db);
196
        $account->fetch($object->fk_account);
197
        $creditorInformation = SwissQrBill\DataGroup\Element\CreditorInformation::create($account->iban);
198
        if (!$creditorInformation->isValid()) {
199
            $langs->load("errors");
200
            $this->error = $langs->transnoentities("SwissQrCreditorInformationInvalid", $account->iban, (string)$creditorInformation->getViolations());
201
            return false;
202
        }
203
        $qrBill->setCreditorInformation($creditorInformation);
204
205
        if ($creditorInformation->containsQrIban()) {
206
            $this->error = $langs->transnoentities("SwissQrIbanNotImplementedYet", $account->iban);
207
            return false;
208
        }
209
210
        // Add payment reference CLASSIC-IBAN
211
        // This is what you will need to identify incoming payments.
212
        $qrBill->setPaymentReference(
213
            SwissQrBill\DataGroup\Element\PaymentReference::create(
214
                SwissQrBill\DataGroup\Element\PaymentReference::TYPE_NON
215
            )
216
        );
217
218
        $currencyinvoicecode = $object->multicurrency_code ? $object->multicurrency_code : $conf->currency;
219
220
        // Add payment amount, with currency
221
        $pai = SwissQrBill\DataGroup\Element\PaymentAmountInformation::create($currencyinvoicecode, $object->total_ttc);
222
        if (!$pai->isValid()) {
223
            $this->error = $langs->transnoentities("SwissQrPaymentInformationInvalid", $object->total_ttc, (string)$pai->getViolations());
224
            return false;
225
        }
226
        $qrBill->setPaymentAmountInformation($pai);
227
228
        // Add some human-readable information about what the bill is for.
229
        $qrBill->setAdditionalInformation(
230
            SwissQrBill\DataGroup\Element\AdditionalInformation::create(
231
                $object->ref
232
            )
233
        );
234
235
        // Set debtor address; We _know_ zip&town have to be filled, so skip that if unfilled.
236
        if (!empty($object->thirdparty->zip) && !empty($object->thirdparty->town)) {
237
            $address = SwissQrBill\DataGroup\Element\CombinedAddress::create(
238
                $object->thirdparty->name,
239
                $object->thirdparty->address,
240
                $object->thirdparty->zip . " " . $object->thirdparty->town,
241
                $object->thirdparty->country_code
242
            );
243
            if (!$address->isValid()) {
244
                $this->error = $langs->transnoentities("SwissQrDebitorAddressInvalid", (string)$address->getViolations());
245
                return false;
246
            }
247
            $qrBill->setUltimateDebtor($address);
248
        }
249
250
        return $qrBill;
251
    }
252
}
253