dolibarr 18.0.6
modules_facture.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2003-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2011 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
5 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
6 * Copyright (C) 2014 Marcos GarcĂ­a <marcosgdf@gmail.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 * or see https://www.gnu.org/
21 */
22
30require_once DOL_DOCUMENT_ROOT.'/core/class/commondocgenerator.class.php';
31require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
32require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; // Required because used in classes that inherit
33
34// For the experimental feature using swiss QR invoice generated by composer lib sparin/swiss-qr-bill
35use Sprain\SwissQrBill;
36
41{
45 public $error = '';
46
47 public $posxpicture;
48 public $posxtva;
49 public $posxup;
50 public $posxqty;
51 public $posxunit;
52 public $posxdesc;
53 public $posxdiscount;
54 public $postotalht;
55
56 public $tva;
57 public $tva_array;
58 public $localtax1;
59 public $localtax2;
60
61 public $atleastonediscount = 0;
62 public $atleastoneratenotnull = 0;
63
64 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
72 public static function liste_modeles($db, $maxfilenamelength = 0)
73 {
74 // phpcs:enable
75 $type = 'invoice';
76 $list = array();
77
78 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
79 $list = getListOfModels($db, $type, $maxfilenamelength);
80
81 return $list;
82 }
83
91 private function getSwissQrBill(Facture $object, Translate $langs)
92 {
93 global $conf;
94
95 if (getDolGlobalString('INVOICE_ADD_SWISS_QR_CODE') != 'bottom') {
96 return false;
97 }
98
99 if ($object->mode_reglement_code != 'VIR') {
100 $this->error = $langs->transnoentities("SwissQrOnlyVIR");
101 return false;
102 }
103
104 if (empty($object->fk_account)) {
105 $this->error = 'Bank account must be defined to use this experimental feature';
106 return false;
107 }
108
109 // Load the autoload file generated by composer
110 if (file_exists(DOL_DOCUMENT_ROOT.'/includes/sprain/swiss-qr-bill/autoload.php')) {
111 require_once DOL_DOCUMENT_ROOT.'/includes/sprain/swiss-qr-bill/autoload.php';
112 } elseif (file_exists(DOL_DOCUMENT_ROOT.'/includes/autoload.php')) {
113 require_once DOL_DOCUMENT_ROOT.'/includes/autoload.php';
114 } else {
115 $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;';
116 return false;
117 }
118
119 // Create a new instance of SwissQrBill, containing default headers with fixed values
120 $qrBill = SwissQrBill\QrBill::create();
121
122 // First, set creditor address
123 $address = SwissQrBill\DataGroup\Element\CombinedAddress::create(
124 $this->emetteur->name,
125 $this->emetteur->address,
126 $this->emetteur->zip . " " . $this->emetteur->town,
127 $this->emetteur->country_code
128 );
129 if (!$address->isValid()) {
130 $this->error = $langs->transnoentities("SwissQrCreditorAddressInvalid", (string) $address->getViolations());
131 return false;
132 }
133 $qrBill->setCreditor($address);
134
135 // Get IBAN from account.
136 $account = new Account($this->db);
137 $account->fetch($object->fk_account);
138 $creditorInformation = SwissQrBill\DataGroup\Element\CreditorInformation::create($account->iban);
139 if (!$creditorInformation->isValid()) {
140 $langs->load("errors");
141 $this->error = $langs->transnoentities("SwissQrCreditorInformationInvalid", $account->iban, (string) $creditorInformation->getViolations());
142 return false;
143 }
144 $qrBill->setCreditorInformation($creditorInformation);
145
146 if ($creditorInformation->containsQrIban()) {
147 $this->error = $langs->transnoentities("SwissQrIbanNotImplementedYet", $account->iban);
148 return false;
149 }
150
151 // Add payment reference CLASSIC-IBAN
152 // This is what you will need to identify incoming payments.
153 $qrBill->setPaymentReference(
154 SwissQrBill\DataGroup\Element\PaymentReference::create(
155 SwissQrBill\DataGroup\Element\PaymentReference::TYPE_NON
156 )
157 );
158
159 $currencyinvoicecode = $object->multicurrency_code ? $object->multicurrency_code : $conf->currency;
160
161 // Add payment amount, with currency
162 $pai = SwissQrBill\DataGroup\Element\PaymentAmountInformation::create($currencyinvoicecode, $object->total_ttc);
163 if (!$pai->isValid()) {
164 $this->error = $langs->transnoentities("SwissQrPaymentInformationInvalid", $object->total_ttc, (string) $pai->getViolations());
165 return false;
166 }
167 $qrBill->setPaymentAmountInformation($pai);
168
169 // Add some human-readable information about what the bill is for.
170 $qrBill->setAdditionalInformation(
171 SwissQrBill\DataGroup\Element\AdditionalInformation::create(
172 $object->ref
173 )
174 );
175
176 // Set debtor address; We _know_ zip&town have to be filled, so skip that if unfilled.
177 if (!empty($object->thirdparty->zip) && !empty($object->thirdparty->town)) {
178 $address = SwissQrBill\DataGroup\Element\CombinedAddress::create(
179 $object->thirdparty->name,
180 $object->thirdparty->address,
181 $object->thirdparty->zip . " " . $object->thirdparty->town,
182 $object->thirdparty->country_code
183 );
184 if (!$address->isValid()) {
185 $this->error = $langs->transnoentities("SwissQrDebitorAddressInvalid", (string) $address->getViolations());
186 return false;
187 }
188 $qrBill->setUltimateDebtor($address);
189 }
190
191 return $qrBill;
192 }
193
202 protected function getHeightForQRInvoice(int $pagenbr, Facture $object, Translate $langs) : int
203 {
204 if (getDolGlobalString('INVOICE_ADD_SWISS_QR_CODE') == 'bottom') {
205 // Keep it, to reset it after QRinvoice getter
206 $error = $this->error;
207
208 if (!$this->getSwissQrBill($object, $langs)) {
209 // Reset error to previous one if exists
210 if (!empty($error)) {
211 $this->error = $error;
212 }
213 return 0;
214 }
215 // SWIFT's requirementis 105, but we get more room with 100 and the page number is in a nice place.
216 return $pagenbr == 1 ? 100 : 0;
217 }
218
219 return 0;
220 }
221
230 public function addBottomQRInvoice(TCPDF $pdf, Facture $object, Translate $langs) : bool
231 {
232 if (!($qrBill = $this->getSwissQrBill($object, $langs))) {
233 return false;
234 }
235
236 try {
237 $pdf->startTransaction();
238
239 $pdf->setPage(1);
240 $pdf->SetTextColor(0, 0, 0);
241 $output = new SwissQrBill\PaymentPart\Output\TcPdfOutput\TcPdfOutput($qrBill, in_array($langs->shortlang, ['de', 'fr', 'it']) ? $langs->shortlang : 'en', $pdf);
242 $output->setPrintable(false)->getPaymentPart();
243 } catch (Exception $e) {
244 $pdf->rollbackTransaction(true);
245 return false;
246 }
247 return true;
248 }
249}
250
255{
259 public $error = '';
260
261 public $version;
262
263
269 public function isEnabled()
270 {
271 return true;
272 }
273
279 public function info()
280 {
281 global $langs;
282 $langs->load("bills");
283 return $langs->trans("NoDescription");
284 }
285
291 public function getExample()
292 {
293 global $langs;
294 $langs->load("bills");
295 return $langs->trans("NoExample");
296 }
297
304 public function canBeActivated()
305 {
306 return true;
307 }
308
317 public function getNextValue($objsoc, $invoice, $mode = 'next')
318 {
319 global $langs;
320 return $langs->trans("NotAvailable");
321 }
322
328 public function getVersion()
329 {
330 global $langs;
331 $langs->load("admin");
332
333 if ($this->version == 'development') {
334 return $langs->trans("VersionDevelopment");
335 } elseif ($this->version == 'experimental') {
336 return $langs->trans("VersionExperimental");
337 } elseif ($this->version == 'dolibarr') {
338 return DOL_VERSION;
339 } elseif ($this->version) {
340 return $this->version;
341 } else {
342 return $langs->trans("NotAvailable");
343 }
344 }
345}
Class to manage bank accounts.
Parent class for documents generators.
Class to manage invoices.
Parent class of invoice reference numbering templates.
isEnabled()
Return if a module can be used or not.
getExample()
Return an example of numbering.
info()
Returns the default description of the numbering pattern.
getNextValue($objsoc, $invoice, $mode='next')
Renvoi prochaine valeur attribuee.
getVersion()
Renvoi version du modele de numerotation.
canBeActivated()
Checks if the numbers already in the database do not cause conflicts that would prevent this numberin...
Parent class of invoice document generators.
getSwissQrBill(Facture $object, Translate $langs)
Get the SwissQR object, including validation.
addBottomQRInvoice(TCPDF $pdf, Facture $object, Translate $langs)
Add SwissQR invoice at bottom of page 1.
getHeightForQRInvoice(int $pagenbr, Facture $object, Translate $langs)
Get the height for bottom-page QR invoice in mm, depending on the page number.
static liste_modeles($db, $maxfilenamelength=0)
Return list of active generation modules.
Class to manage translations.
getListOfModels($db, $type, $maxfilenamelength=0)
Return list of activated modules usable for document generation.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.