dolibarr 24.0.0-beta
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 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
8 * Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
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
32require_once DOL_DOCUMENT_ROOT.'/core/class/commondocgenerator.class.php';
33require_once DOL_DOCUMENT_ROOT.'/core/class/commonnumrefgenerator.class.php';
34require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
35require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; // Required because used in classes that inherit
36
37// For the experimental feature using swiss QR invoice generated by composer lib sparin/swiss-qr-bill
38use Sprain\SwissQrBill;
39
44{
48 public $posxpicture;
52 public $posxtva;
56 public $posxup;
60 public $posxqty;
64 public $posxunit;
68 public $posxdesc;
72 public $posxdiscount;
76 public $postotalht;
77
78
82 public $tva;
86 public $tva_array;
92 public $localtax1;
93
99 public $localtax2;
100
104 public $atleastonediscount = 0;
108 public $atleastoneratenotnull = 0;
109
113 public $showAmountBeforeDiscount = 1;
114
118 public $showDiscountAmount = 1;
119
120 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
128 public static function liste_modeles($db, $maxfilenamelength = 0)
129 {
130 // phpcs:enable
131 $type = 'invoice';
132 $list = array();
133
134 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
135 $list = getListOfModels($db, $type, $maxfilenamelength);
136
137 return $list;
138 }
139
140
141 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
153 abstract public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0);
154 // phpcs:enable
155
156
164 private function getSwissQrBill(Facture $object, Translate $langs)
165 {
166 global $conf;
167
168 if (getDolGlobalString('INVOICE_ADD_SWISS_QR_CODE') != 'bottom') {
169 return false;
170 }
171
172 if ($object->mode_reglement_code != 'VIR') {
173 $this->error = $langs->transnoentities("SwissQrOnlyVIR");
174 return false;
175 }
176
177 if (empty($object->fk_account)) {
178 $this->error = 'Bank account must be defined to use this experimental feature';
179 return false;
180 }
181
182 // Load the autoload file generated by composer
183 if (file_exists(DOL_DOCUMENT_ROOT.'/includes/sprain/swiss-qr-bill/autoload.php')) {
184 require_once DOL_DOCUMENT_ROOT.'/includes/sprain/swiss-qr-bill/autoload.php'; // @phpstan-ignore-line
185 } elseif (file_exists(DOL_DOCUMENT_ROOT.'/includes/autoload.php')) {
186 require_once DOL_DOCUMENT_ROOT.'/includes/autoload.php'; // @phpstan-ignore-line
187 } else {
188 $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;';
189 return false;
190 }
191
192 // Create a new instance of SwissQrBill, containing default headers with fixed values
193 $qrBill = SwissQrBill\QrBill::create();
194
195 // First, set creditor address
196 $address = SwissQrBill\DataGroup\Element\CombinedAddress::create(
197 $this->emetteur->name,
198 $this->emetteur->address,
199 $this->emetteur->zip . " " . $this->emetteur->town,
200 $this->emetteur->country_code
201 );
202 if (!$address->isValid()) {
203 $this->error = $langs->transnoentities("SwissQrCreditorAddressInvalid", (string) $address->getViolations());
204 return false;
205 }
206 $qrBill->setCreditor($address);
207
208 // Get IBAN from account.
209 $account = new Account($this->db);
210 $account->fetch((int) $object->fk_account);
211 $creditorInformation = SwissQrBill\DataGroup\Element\CreditorInformation::create($account->iban);
212 if (!$creditorInformation->isValid()) {
213 $langs->load("errors");
214 $this->error = $langs->transnoentities("SwissQrCreditorInformationInvalid", $account->iban, (string) $creditorInformation->getViolations());
215 return false;
216 }
217 $qrBill->setCreditorInformation($creditorInformation);
218
219 if ($creditorInformation->containsQrIban()) {
220 $this->error = $langs->transnoentities("SwissQrIbanNotImplementedYet", $account->iban);
221 return false;
222 }
223
224 // Add payment reference CLASSIC-IBAN
225 // This is what you will need to identify incoming payments.
226 $qrBill->setPaymentReference(
227 SwissQrBill\DataGroup\Element\PaymentReference::create(
228 SwissQrBill\DataGroup\Element\PaymentReference::TYPE_NON
229 )
230 );
231
232 $currencyinvoicecode = $object->multicurrency_code ? $object->multicurrency_code : $conf->currency;
233
234 // Add payment amount, with currency
235 $pai = SwissQrBill\DataGroup\Element\PaymentAmountInformation::create($currencyinvoicecode, $object->total_ttc);
236 if (!$pai->isValid()) {
237 $this->error = $langs->transnoentities("SwissQrPaymentInformationInvalid", (string) $object->total_ttc, (string) $pai->getViolations());
238 return false;
239 }
240 $qrBill->setPaymentAmountInformation($pai);
241
242 // Add some human-readable information about what the bill is for.
243 $qrBill->setAdditionalInformation(
244 SwissQrBill\DataGroup\Element\AdditionalInformation::create(
245 $object->ref
246 )
247 );
248
249 // Set debtor address; We _know_ zip&town have to be filled, so skip that if unfilled.
250 if (!empty($object->thirdparty->zip) && !empty($object->thirdparty->town)) {
251 $address = SwissQrBill\DataGroup\Element\CombinedAddress::create(
252 $object->thirdparty->name,
253 $object->thirdparty->address,
254 $object->thirdparty->zip . " " . $object->thirdparty->town,
255 $object->thirdparty->country_code
256 );
257 if (!$address->isValid()) {
258 $this->error = $langs->transnoentities("SwissQrDebitorAddressInvalid", (string) $address->getViolations());
259 return false;
260 }
261 $qrBill->setUltimateDebtor($address);
262 }
263
264 return $qrBill;
265 }
266
275 protected function getHeightForQRInvoice(int $pagenbr, Facture $object, Translate $langs)
276 {
277 if (getDolGlobalString('INVOICE_ADD_SWISS_QR_CODE') == 'bottom') {
278 // Keep it, to reset it after QRinvoice getter
279 $error = $this->error;
280
281 if (!$this->getSwissQrBill($object, $langs)) {
282 // Reset error to previous one if exists
283 if (!empty($error)) {
284 $this->error = $error;
285 }
286 return 0;
287 }
288 // SWIFT's requirementis 105, but we get more room with 100 and the page number is in a nice place.
289 return $pagenbr == 1 ? 100 : 0;
290 }
291
292 return 0;
293 }
294
303 public function addBottomQRInvoice(TCPDF $pdf, Facture $object, Translate $langs): bool
304 {
305 if (!($qrBill = $this->getSwissQrBill($object, $langs))) {
306 return false;
307 }
308
309 try {
310 $pdf->startTransaction();
311
312 $pdf->setPage(1);
313 $pdf->SetTextColor(0, 0, 0);
314 $output = new SwissQrBill\PaymentPart\Output\TcPdfOutput\TcPdfOutput($qrBill, in_array($langs->shortlang, ['de', 'fr', 'it']) ? $langs->shortlang : 'en', $pdf);
315 $output->setPrintable(false)->getPaymentPart();
316 } catch (Exception $e) {
317 $pdf->rollbackTransaction(true);
318 return false;
319 }
320 return true;
321 }
322}
323
328{
337 abstract public function getNextValue($objsoc, $invoice, $mode = 'next');
338
344 abstract public function getExample();
345}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
Class to manage bank accounts.
Parent class for documents (PDF, ODT, ...) generators.
Parent class for number ref generators.
Class to manage invoices.
Parent class of invoice reference numbering templates.
getExample()
Return an example of numbering.
getNextValue($objsoc, $invoice, $mode='next')
Return next value not used or last value used.
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.
write_file($object, $outputlangs, $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function to build pdf onto disk.
Class to manage translations.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
getListOfModels($db, $type, $maxfilenamelength=0, $showempty=0)
Return list of activated modules usable for document generation.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.