dolibarr  19.0.0-dev
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 
30 require_once DOL_DOCUMENT_ROOT.'/core/class/commondocgenerator.class.php';
31 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
32 require_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
35 use Sprain\SwissQrBill;
36 
40 abstract class ModelePDFFactures extends CommonDocGenerator
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 
254 abstract class ModeleNumRefFactures
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.