dolibarr  20.0.0-beta
bonprelevement.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2004-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
4  * Copyright (C) 2010-2015 Juanjo Menent <jmenent@2byte.es>
5  * Copyright (C) 2010-2014 Laurent Destailleur <eldy@users.sourceforge.net>
6  * Copyright (C) 2014-2016 Ferran Marcet <fmarcet@2byte.es>
7  * Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
8  * Copyright (C) 2019 JC Prieto <jcprieto@virtual20.com><prietojc@gmail.com>
9  * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
10  * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program. If not, see <https://www.gnu.org/licenses/>.
24  */
25 
32 require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php';
33 require_once DOL_DOCUMENT_ROOT . '/core/lib/bank.lib.php';
34 require_once DOL_DOCUMENT_ROOT . '/compta/bank/class/account.class.php';
35 require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
36 require_once DOL_DOCUMENT_ROOT . '/compta/paiement/class/paiement.class.php';
37 require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.facture.class.php';
38 require_once DOL_DOCUMENT_ROOT . '/fourn/class/paiementfourn.class.php';
39 require_once DOL_DOCUMENT_ROOT . '/salaries/class/salary.class.php';
40 require_once DOL_DOCUMENT_ROOT . '/salaries/class/paymentsalary.class.php';
41 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
42 require_once DOL_DOCUMENT_ROOT . '/user/class/userbankaccount.class.php';
43 
44 
49 {
53  public $element = 'widthdraw';
54 
58  public $table_element = 'prelevement_bons';
59 
63  public $picto = 'payment';
64 
65  public $date_echeance;
66  public $raison_sociale;
67  public $reference_remise;
68  public $emetteur_code_guichet;
69  public $emetteur_numero_compte;
70  public $emetteur_code_banque;
71  public $emetteur_number_key;
72  public $sepa_xml_pti_in_ctti;
73 
74  public $emetteur_iban;
75  public $emetteur_bic;
76  public $emetteur_ics;
77 
78  public $user_trans;
79  public $user_credit;
80 
81  public $total;
82  public $fetched;
83  public $labelStatus = array();
84 
85  public $factures = array();
86 
90  public $methodes_trans = array();
91 
92  public $invoice_in_error = array();
93  public $thirdparty_in_error = array();
94 
98  public $file;
99 
103  public $filename;
104 
105  const STATUS_DRAFT = 0;
106  const STATUS_TRANSFERED = 1;
107  const STATUS_CREDITED = 2; // STATUS_CREDITED and STATUS_DEBITED is same. Difference is in ->type
108  const STATUS_DEBITED = 2; // STATUS_CREDITED and STATUS_DEBITED is same. Difference is in ->type
109 
110 
150  // BEGIN MODULEBUILDER PROPERTIES
154  public $fields = array(
155  'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 10, 'notnull' => 1, 'visible' => 0,),
156  'ref' => array('type' => 'varchar(12)', 'label' => 'Ref', 'enabled' => 1, 'position' => 15, 'notnull' => 0, 'visible' => -1, 'csslist' => 'tdoverflowmax150', 'showoncombobox' => 1,),
157  'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 25, 'notnull' => 0, 'visible' => -1,),
158  'amount' => array('type' => 'double(24,8)', 'label' => 'Amount', 'enabled' => 1, 'position' => 30, 'notnull' => 0, 'visible' => -1,),
159  'statut' => array('type' => 'smallint(6)', 'label' => 'Statut', 'enabled' => 1, 'position' => 500, 'notnull' => 0, 'visible' => -1, 'arrayofkeyval' => array(0 => 'Wait', 1 => 'Transfered', 2 => 'Credited')),
160  'credite' => array('type' => 'smallint(6)', 'label' => 'Credite', 'enabled' => 1, 'position' => 40, 'notnull' => 0, 'visible' => -1,),
161  'note' => array('type' => 'text', 'label' => 'Note', 'enabled' => 1, 'position' => 45, 'notnull' => 0, 'visible' => -1,),
162  'date_trans' => array('type' => 'datetime', 'label' => 'Datetrans', 'enabled' => 1, 'position' => 50, 'notnull' => 0, 'visible' => -1,),
163  'method_trans' => array('type' => 'smallint(6)', 'label' => 'Methodtrans', 'enabled' => 1, 'position' => 55, 'notnull' => 0, 'visible' => -1,),
164  'fk_user_trans' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fkusertrans', 'enabled' => 1, 'position' => 60, 'notnull' => 0, 'visible' => -1, 'css' => 'maxwidth500 widthcentpercentminusxx', 'csslist' => 'tdoverflowmax150',),
165  'date_credit' => array('type' => 'datetime', 'label' => 'Datecredit', 'enabled' => 1, 'position' => 65, 'notnull' => 0, 'visible' => -1,),
166  'fk_user_credit' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fkusercredit', 'enabled' => 1, 'position' => 70, 'notnull' => 0, 'visible' => -1, 'css' => 'maxwidth500 widthcentpercentminusxx', 'csslist' => 'tdoverflowmax150',),
167  'type' => array('type' => 'varchar(16)', 'label' => 'Type', 'enabled' => 1, 'position' => 75, 'notnull' => 0, 'visible' => -1,),
168  'fk_bank_account' => array('type' => 'integer', 'label' => 'Fkbankaccount', 'enabled' => 1, 'position' => 80, 'notnull' => 0, 'visible' => -1, 'css' => 'maxwidth500 widthcentpercentminusxx',),
169  );
170  public $rowid;
171  public $ref;
172  public $datec;
173  public $amount;
174 
179  public $statut;
183  public $status;
184 
185  public $credite;
186  public $note;
187  public $date_trans;
191  public $method_trans;
192  public $fk_user_trans;
193  public $date_credit;
194  public $fk_user_credit;
195  public $type;
196  public $fk_bank_account;
197  // END MODULEBUILDER PROPERTIES
198 
199 
200 
206  public function __construct($db)
207  {
208  $this->db = $db;
209 
210  $this->filename = '';
211 
212  $this->date_echeance = dol_now();
213  $this->raison_sociale = "";
214  $this->reference_remise = "";
215 
216  $this->emetteur_code_guichet = "";
217  $this->emetteur_numero_compte = "";
218  $this->emetteur_code_banque = "";
219  $this->emetteur_number_key = "";
220  $this->sepa_xml_pti_in_ctti = false;
221 
222  $this->emetteur_iban = "";
223  $this->emetteur_bic = "";
224  $this->emetteur_ics = "";
225 
226  $this->factures = array();
227 
228  $this->methodes_trans = array(0 => 'Internet', 2 => 'Email', 3 => 'Api');
229 
230  $this->fetched = 0;
231  }
232 
233  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
249  public function AddFacture($invoice_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $type = 'debit-order', $sourcetype = '')
250  {
251  // phpcs:enable
252  $result = 0;
253  $line_id = 0;
254 
255  // Add lines into prelevement_lignes
256  $result = $this->addline($line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $sourcetype);
257 
258 
259  if ($result == 0) {
260  if ($line_id > 0) {
261  $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement (";
262  if ($type != 'bank-transfer') {
263  $sql .= "fk_facture";
264  } else {
265  if ($sourcetype == 'salary') {
266  $sql .= "fk_salary";
267  } else {
268  $sql .= "fk_facture_fourn";
269  }
270  }
271  $sql .= ",fk_prelevement_lignes";
272  $sql .= ") VALUES (";
273  $sql .= ((int) $invoice_id);
274  $sql .= ", " . ((int) $line_id);
275  $sql .= ")";
276 
277  if ($this->db->query($sql)) {
278  $result = 0;
279  } else {
280  $result = -1;
281  $this->errors[] = get_class($this) . "::AddFacture " . $this->db->lasterror;
282  dol_syslog(get_class($this) . "::AddFacture Error $result");
283  }
284  } else {
285  $result = -2;
286  $this->errors[] = get_class($this) . "::AddFacture linedid Empty";
287  dol_syslog(get_class($this) . "::AddFacture Error $result");
288  }
289  } else {
290  $result = -3;
291  dol_syslog(get_class($this) . "::AddFacture Error $result");
292  }
293 
294  return $result;
295  }
296 
311  public function addline(&$line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $sourcetype = '')
312  {
313  $result = -1;
314  $concat = 0; // ??? what is this for. Seems not used.
315 
316  if ($concat == 1) {
317  /*
318  * We aggregate the lines
319  */
320  $sql = "SELECT rowid";
321  $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_lignes";
322  $sql .= " WHERE fk_prelevement_bons = " . ((int) $this->id);
323  if ($sourcetype == 'salary') {
324  $sql .= " AND fk_soc = " . ((int) $client_id);
325  } else {
326  $sql .= " AND fk_user = " . ((int) $client_id);
327  }
328  $sql .= " AND code_banque = '" . $this->db->escape($code_banque) . "'";
329  $sql .= " AND code_guichet = '" . $this->db->escape($code_guichet) . "'";
330  $sql .= " AND number = '" . $this->db->escape($number) . "'";
331 
332  $resql = $this->db->query($sql);
333  if ($resql) {
334  $num = $this->db->num_rows($resql);
335  } else {
336  $result = -1;
337  }
338  } else {
339  /*
340  * No aggregate
341  */
342  $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_lignes (";
343  $sql .= "fk_prelevement_bons";
344  $sql .= ", fk_soc";
345  $sql .= ", client_nom";
346  $sql .= ", amount";
347  $sql .= ", code_banque";
348  $sql .= ", code_guichet";
349  $sql .= ", number";
350  $sql .= ", cle_rib";
351  $sql .= ($sourcetype == 'salary' ? ", fk_user" : "");
352  $sql .= ") VALUES (";
353  $sql .= $this->id;
354  $sql .= ", " . (($sourcetype != 'salary') ? ((int) $client_id) : "0"); // fk_soc can't be null
355  $sql .= ", '" . $this->db->escape($client_nom) . "'";
356  $sql .= ", " . ((float) price2num($amount));
357  $sql .= ", '" . $this->db->escape($code_banque) . "'";
358  $sql .= ", '" . $this->db->escape($code_guichet) . "'";
359  $sql .= ", '" . $this->db->escape($number) . "'";
360  $sql .= ", '" . $this->db->escape($number_key) . "'";
361  $sql .= (($sourcetype == 'salary') ? ", " . ((int) $client_id) : '');
362  $sql .= ")";
363  if ($this->db->query($sql)) {
364  $line_id = $this->db->last_insert_id(MAIN_DB_PREFIX . "prelevement_lignes");
365  $result = 0;
366  } else {
367  $this->errors[] = get_class($this) . "::addline Error -2 " . $this->db->lasterror;
368  dol_syslog(get_class($this) . "::addline Error -2");
369  $result = -2;
370  }
371  }
372 
373  return $result;
374  }
375 
382  public function getErrorString($error)
383  {
384  global $langs;
385 
386  $errors = array();
387 
388  $errors[1027] = $langs->trans("DateInvalid");
389 
390  return $errors[abs($error)];
391  }
392 
400  public function fetch($rowid, $ref = '')
401  {
402  $sql = "SELECT p.rowid, p.ref, p.amount, p.note";
403  $sql .= ", p.datec as dc";
404  $sql .= ", p.date_trans as date_trans";
405  $sql .= ", p.method_trans, p.fk_user_trans";
406  $sql .= ", p.date_credit as date_credit";
407  $sql .= ", p.fk_user_credit";
408  $sql .= ", p.type";
409  $sql .= ", p.fk_bank_account";
410  $sql .= ", p.statut as status";
411  $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons as p";
412  $sql .= " WHERE p.entity IN (" . getEntity('invoice') . ")";
413  if ($rowid > 0) {
414  $sql .= " AND p.rowid = " . ((int) $rowid);
415  } else {
416  $sql .= " AND p.ref = '" . $this->db->escape($ref) . "'";
417  }
418 
419  dol_syslog(get_class($this) . "::fetch", LOG_DEBUG);
420  $result = $this->db->query($sql);
421  if ($result) {
422  if ($this->db->num_rows($result)) {
423  $obj = $this->db->fetch_object($result);
424 
425  $this->id = $obj->rowid;
426  $this->ref = $obj->ref;
427  $this->amount = $obj->amount;
428  $this->note = $obj->note;
429  $this->datec = $this->db->jdate($obj->dc);
430 
431  $this->date_trans = $this->db->jdate($obj->date_trans);
432  $this->method_trans = $obj->method_trans;
433  $this->user_trans = $obj->fk_user_trans;
434 
435  $this->date_credit = $this->db->jdate($obj->date_credit);
436  $this->user_credit = $obj->fk_user_credit;
437 
438  $this->type = $obj->type;
439  $this->fk_bank_account = $obj->fk_bank_account;
440 
441  $this->status = $obj->status;
442  if (empty($this->status)) { // Value is sometimes null in database
443  $this->status = 0;
444  }
445  $this->statut = $this->status; // For backward compatibility
446 
447  $this->fetched = 1;
448 
449  return 1;
450  } else {
451  dol_syslog(get_class($this) . "::Fetch Erreur aucune ligne retournee");
452  return -1;
453  }
454  } else {
455  return -2;
456  }
457  }
458 
466  public function update(User $user, $notrigger = 0)
467  {
468  return $this->updateCommon($user, $notrigger);
469  }
470 
471  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
481  public function set_infocredit($user, $date, $type = '')
482  {
483  // phpcs:enable
484  global $conf, $langs;
485 
486  $error = 0;
487 
488  if ($this->fetched == 1) {
489  if ($date < $this->date_trans) {
490  $langs->load("errors");
491  $this->error = $langs->trans('ErrorDateOfMovementLowerThanDateOfFileTransmission');
492  dol_syslog("bon-prelevment::set_infocredit 1027 " . $this->error);
493  return -1027;
494  }
495 
496  $this->db->begin();
497 
498  $sql = " UPDATE " . MAIN_DB_PREFIX . "prelevement_bons";
499  $sql .= " SET fk_user_credit = " . ((int) $user->id);
500  $sql .= ", statut = " . self::STATUS_CREDITED;
501  $sql .= ", date_credit = '" . $this->db->idate($date) . "'";
502  $sql .= " WHERE rowid = " . ((int) $this->id);
503  $sql .= " AND entity = " . ((int) $conf->entity);
504  $sql .= " AND statut = " . self::STATUS_TRANSFERED;
505 
506  $resql = $this->db->query($sql);
507  if ($resql) {
508  $langs->load('withdrawals');
509  $subject = $langs->trans("InfoCreditSubject", $this->ref);
510  $message = $langs->trans("InfoCreditMessage", $this->ref, dol_print_date($date, 'dayhour'));
511 
512  // Add payment of withdrawal into bank
513  $fk_bank_account = $this->fk_bank_account;
514  if (empty($fk_bank_account)) {
515  $fk_bank_account = ($this->type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
516  }
517 
518  $facs = array();
519  $amounts = array();
520  $amountsperthirdparty = array();
521 
522  $facs = $this->getListInvoices(1, $type);
523  if ($this->error) {
524  $error++;
525  }
526 
527  // Loop on each invoice or salary.
528  // $facs should be array(0=>id, 1=>amount requested)
529  $num = count($facs);
530  for ($i = 0; $i < $num; $i++) {
531  if ($this->type == 'bank-transfer') {
532  if ($type == 'salary') {
533  $fac = new Salary($this->db);
534  } else {
535  $fac = new FactureFournisseur($this->db);
536  }
537  } else {
538  $fac = new Facture($this->db);
539  }
540 
541  $result = $fac->fetch($facs[$i][0]);
542 
543  $amounts[$fac->id] = $facs[$i][1];
544  if ($this->type == 'bank-transfer') {
545  if ($type == 'salary') {
546  $amountsperthirdparty[$fac->fk_user][$fac->id] = $facs[$i][1];
547  } else {
548  $amountsperthirdparty[$fac->socid][$fac->id] = $facs[$i][1];
549  }
550  } else {
551  $amountsperthirdparty[$fac->socid][$fac->id] = $facs[$i][1];
552  }
553 
554  $totalpaid = $fac->getSommePaiement();
555  $totalcreditnotes = 0;
556  if (method_exists($fac, 'getSumCreditNotesUsed')) {
557  $totalcreditnotes = $fac->getSumCreditNotesUsed();
558  }
559  $totaldeposits = 0;
560  if (method_exists($fac, 'getSumDepositsUsed')) {
561  $totaldeposits = $fac->getSumDepositsUsed();
562  }
563  $alreadypayed = $totalpaid + $totalcreditnotes + $totaldeposits;
564 
565  // Set the main document to pay with status Paid.
566  // @TODO Move this after creation of payments done after
567  $amountofdocument = $fac->total_ttc;
568  if ($type == 'salary') {
569  $amountofdocument = $fac->amount;
570  }
571  if (price2num($alreadypayed + $facs[$i][1], 'MT') == price2num($amountofdocument, 'MT')) {
572  $result = $fac->setPaid($user);
573  if ($result < 0) {
574  $this->error = $fac->error;
575  $this->errors = $fac->errors;
576  }
577  }
578  }
579 
580  // Make one payment per customer or employee
581  foreach ($amountsperthirdparty as $thirdpartyid => $cursoramounts) {
582  if ($this->type == 'bank-transfer') {
583  if ($type == 'salary') {
584  $paiement = new PaymentSalary($this->db);
585  } else {
586  $paiement = new PaiementFourn($this->db);
587  }
588  } else {
589  $paiement = new Paiement($this->db);
590  }
591  $paiement->datepaye = $date;
592  $paiement->amounts = $cursoramounts; // Array with detail of dispatching of payments for each invoice
593 
594  if ($this->type == 'bank-transfer') {
595  if ($type == 'salary') {
596  $paiement->datep = $date;
597 
598  $paiement->paiementid = 2;
599  $paiement->fk_typepayment = 2;
600  $paiement->paiementcode = 'VIR';
601  } else {
602  $paiement->paiementid = 2;
603  $paiement->paiementcode = 'VIR';
604  }
605  } else {
606  $paiement->paiementid = 3;
607  $paiement->paiementcode = 'PRE';
608  }
609 
610  $paiement->num_payment = $this->ref; // Set ref of direct debit note
611  $paiement->id_prelevement = $this->id;
612 
613  $result = $paiement->create($user); // This use ->paiementid, that is ID of payment mode
614 
615  if ($result < 0) {
616  $error++;
617  $this->error = $paiement->error;
618  $this->errors = $paiement->errors;
619  dol_syslog(get_class($this) . "::set_infocredit AddPayment Error " . $this->error);
620  } else {
621  if ($this->type == 'bank-transfer') {
622  if ($type == 'salary') {
623  $modeforaddpayment = 'payment_salary';
624  $labelforaddpayment = '(SalaryPayment)';
625  $addbankurl = 'credit-transfer';
626  } else {
627  $modeforaddpayment = 'payment_supplier';
628  $labelforaddpayment = '(SupplierInvoicePayment)';
629  $addbankurl = 'credit-transfer';
630  }
631  } else {
632  $modeforaddpayment = 'payment';
633  $labelforaddpayment = '(CustomerInvoicePayment)';
634  $addbankurl = 'direct-debit'; // = 'directdebit'
635  }
636 
637  $result = $paiement->addPaymentToBank($user, $modeforaddpayment, $labelforaddpayment, $fk_bank_account, '', '', 0, '', $addbankurl);
638 
639  if ($result < 0) {
640  $error++;
641  $this->error = $paiement->error;
642  $this->errors = $paiement->errors;
643  dol_syslog(get_class($this) . "::set_infocredit AddPaymentToBank Error " . $this->error);
644  }
645  }
646  }
647 
648  // Update withdrawal line
649  // TODO: Translate to ligneprelevement.class.php
650  if (!$error) {
651  $sql = " UPDATE " . MAIN_DB_PREFIX . "prelevement_lignes";
652  $sql .= " SET statut = 2";
653  $sql .= " WHERE fk_prelevement_bons = " . ((int) $this->id);
654 
655  if (!$this->db->query($sql)) {
656  dol_syslog(get_class($this) . "::set_infocredit Update lines Error");
657  $error++;
658  }
659  }
660  } else {
661  $this->error = $this->db->lasterror();
662  dol_syslog(get_class($this) . "::set_infocredit Update Bons Error");
663  $error++;
664  }
665 
666  // End of procedure
667  if ($error == 0) {
668  $this->date_credit = $date; // date credit or debit
669  $this->statut = self::STATUS_CREDITED;
670  $this->status = self::STATUS_CREDITED;
671 
672  $this->db->commit();
673  return 0;
674  } else {
675  $this->db->rollback();
676  return -1;
677  }
678  } else {
679  return -1026;
680  }
681  }
682 
683  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
692  public function set_infotrans($user, $date, $method)
693  {
694  // phpcs:enable
695  global $conf, $langs;
696 
697  $error = 0;
698 
699  dol_syslog(get_class($this) . "::set_infotrans Start", LOG_INFO);
700 
701  if ($this->db->begin()) {
702  $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_bons ";
703  $sql .= " SET fk_user_trans = " . $user->id;
704  $sql .= " , date_trans = '" . $this->db->idate($date) . "'";
705  $sql .= " , method_trans = " . ((int) $method);
706  $sql .= " , statut = " . self::STATUS_TRANSFERED;
707  $sql .= " WHERE rowid = " . ((int) $this->id);
708  $sql .= " AND entity = " . ((int) $conf->entity);
709  $sql .= " AND statut = " . self::STATUS_DRAFT;
710 
711  if ($this->db->query($sql)) {
712  $this->method_trans = $method;
713  $langs->load('withdrawals');
714  $subject = $langs->trans("InfoTransSubject", $this->ref);
715  $message = $langs->trans("InfoTransMessage", $this->ref, dolGetFirstLastname($user->firstname, $user->lastname));
716  $message .= $langs->trans("InfoTransData", price($this->amount), $this->methodes_trans[$this->method_trans], dol_print_date($date, 'day'));
717 
718  // TODO Call trigger to create a notification using notification module
719  } else {
720  $error++;
721  }
722 
723  if ($error == 0) {
724  $this->date_trans = $date;
725  $this->statut = self::STATUS_TRANSFERED;
726  $this->status = self::STATUS_TRANSFERED;
727  $this->user_trans = $user->id;
728 
729  $this->db->commit();
730 
731  return 0;
732  } else {
733  $this->db->rollback();
734  dol_syslog(get_class($this) . "::set_infotrans ROLLBACK", LOG_ERR);
735 
736  return -1;
737  }
738  } else {
739  dol_syslog(get_class($this) . "::set_infotrans Ouverture transaction SQL impossible", LOG_CRIT);
740  return -2;
741  }
742  }
743 
751  private function getListInvoices($amounts = 0, $type = '')
752  {
753  global $conf;
754 
755  $arr = array();
756 
757  dol_syslog(get_class($this) . "::getListInvoices");
758 
759  // Returns all invoices presented within same order
760  $sql = "SELECT ";
761  if ($this->type == 'bank-transfer') {
762  if ($type == 'salary') {
763  $sql .= " p.fk_salary";
764  } else {
765  $sql .= " p.fk_facture_fourn";
766  }
767  } else {
768  $sql .= " p.fk_facture";
769  }
770  if ($amounts) {
771  $sql .= ", SUM(pl.amount)";
772  }
773  $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons as pb,";
774  $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
775  $sql .= " " . MAIN_DB_PREFIX . "prelevement as p";
776  $sql .= " WHERE p.fk_prelevement_lignes = pl.rowid";
777  $sql .= " AND pl.fk_prelevement_bons = pb.rowid";
778  $sql .= " AND pb.rowid = " . ((int) $this->id);
779  $sql .= " AND pb.entity = " . ((int) $conf->entity);
780  if ($amounts) {
781  if ($this->type == 'bank-transfer') {
782  if ($type == 'salary') {
783  $sql .= " GROUP BY p.fk_salary";
784  } else {
785  $sql .= " GROUP BY p.fk_facture_fourn";
786  }
787  } else {
788  $sql .= " GROUP BY p.fk_facture";
789  }
790  }
791 
792  $resql = $this->db->query($sql);
793  if ($resql) {
794  $num = $this->db->num_rows($resql);
795 
796  if ($num) {
797  $i = 0;
798  while ($i < $num) {
799  $row = $this->db->fetch_row($resql);
800  if (!$amounts) {
801  $arr[$i] = $row[0];
802  } else {
803  $arr[$i] = array(
804  $row[0],
805  $row[1]
806  );
807  }
808  $i++;
809  }
810  }
811  $this->db->free($resql);
812  } else {
813  $this->error = $this->db->lasterror();
814  }
815 
816  return $arr;
817  }
818 
819  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
827  public function SommeAPrelever($mode = 'direct-debit', $type = '')
828  {
829  // phpcs:enable
830  $sql = "SELECT sum(pd.amount) as nb";
831  if ($type !== 'salary') {
832  if ($mode != 'bank-transfer') {
833  $sql .= " FROM " . MAIN_DB_PREFIX . "facture as f,";
834  } else {
835  $sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f,";
836  }
837  } else {
838  $sql .= " FROM " . MAIN_DB_PREFIX . "salary as s,";
839  }
840  $sql .= " " . MAIN_DB_PREFIX . "prelevement_demande as pd";
841  $sql .= ($type !== 'salary' ? " WHERE f.entity IN (" . getEntity('invoice') . ")" : " WHERE s.entity IN (" . getEntity('salary') . ")");
842  if (!getDolGlobalString('WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS')) {
843  $sql .= ($type !== 'salary' ? " AND f.fk_statut = " . Facture::STATUS_VALIDATED : " AND s.paye = " . Salary::STATUS_UNPAID);
844  }
845  if ($type !== 'salary') {
846  if ($mode != 'bank-transfer') {
847  $sql .= " AND f.rowid = pd.fk_facture";
848  } else {
849  $sql .= " AND f.rowid = pd.fk_facture_fourn";
850  }
851  } else {
852  $sql .= " AND s.rowid = pd.fk_salary";
853  }
854  $sql .= ($type !== 'salary' ? " AND f.paye = 0" : "");
855  $sql .= " AND pd.traite = 0";
856  $sql .= " AND pd.ext_payment_id IS NULL";
857  $sql .= ($type !== 'salary' ? " AND f.total_ttc > 0" : "");
858 
859  $resql = $this->db->query($sql);
860  if ($resql) {
861  $obj = $this->db->fetch_object($resql);
862 
863  $this->db->free($resql);
864 
865  return $obj->nb;
866  } else {
867  $error = 1;
868  dol_syslog(get_class($this) . "::SommeAPrelever Erreur -1");
869  dol_syslog($this->db->error());
870 
871  return -1;
872  }
873  }
874 
882  public function nbOfInvoiceToPay($mode = 'direct-debit', $type = '')
883  {
884  if ($type === 'salary') {
885  return $this->NbFactureAPrelever($mode, 1);
886  } else {
887  return $this->NbFactureAPrelever($mode);
888  }
889  }
890 
891  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
899  public function NbFactureAPrelever($type = 'direct-debit', $forsalary = 0)
900  {
901  // phpcs:enable
902  if ($forsalary == 1) {
903  $sql = "SELECT count(s.rowid) as nb";
904  $sql .= " FROM " . MAIN_DB_PREFIX . "salary as s";
905  } else {
906  $sql = "SELECT count(f.rowid) as nb";
907 
908  if ($type == 'bank-transfer') {
909  $sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
910  } else {
911  $sql .= " FROM " . MAIN_DB_PREFIX . "facture as f";
912  }
913  }
914  $sql .= ", " . MAIN_DB_PREFIX . "prelevement_demande as pd";
915  if ($forsalary == 1) {
916  $sql .= " WHERE s.entity IN (" . getEntity('invoice') . ")";
917  if (!getDolGlobalString('WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS')) {
918  $sql .= " AND s.paye = 0";
919  }
920  } else {
921  $sql .= " WHERE f.entity IN (" . getEntity('invoice') . ")";
922  if (!getDolGlobalString('WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS')) {
923  $sql .= " AND f.fk_statut = " . Facture::STATUS_VALIDATED;
924  }
925  }
926  if ($forsalary == 1) {
927  $sql .= " AND s.rowid = pd.fk_salary";
928  } else {
929  if ($type == 'bank-transfer') {
930  $sql .= " AND f.rowid = pd.fk_facture_fourn";
931  } else {
932  $sql .= " AND f.rowid = pd.fk_facture";
933  }
934  }
935  $sql .= " AND pd.traite = 0";
936  $sql .= " AND pd.ext_payment_id IS NULL";
937  if (!$forsalary == 1) {
938  $sql .= " AND f.total_ttc > 0";
939  } else {
940  $sql .= " AND s.paye = 0";
941  }
942 
943  dol_syslog(get_class($this) . "::NbFactureAPrelever");
944  $resql = $this->db->query($sql);
945 
946  if ($resql) {
947  $obj = $this->db->fetch_object($resql);
948  $this->db->free($resql);
949 
950  return $obj->nb;
951  } else {
952  $this->error = get_class($this) . "::NbFactureAPrelever Erreur -1 sql=" . $this->db->error();
953  return -1;
954  }
955  }
956 
957 
958  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
979  public function create($banque = 0, $agence = 0, $mode = 'real', $format = 'ALL', $executiondate = '', $notrigger = 0, $type = 'direct-debit', $did = 0, $fk_bank_account = 0, $sourcetype = 'invoice')
980  {
981  // phpcs:enable
982  global $conf, $langs, $user;
983 
984  dol_syslog(__METHOD__ . " Bank=" . $banque . " Office=" . $agence . " mode=" . $mode . " format=" . $format, LOG_DEBUG);
985 
986  require_once DOL_DOCUMENT_ROOT . "/compta/facture/class/facture.class.php";
987  require_once DOL_DOCUMENT_ROOT . "/societe/class/societe.class.php";
988 
989  // Check params
990  if ($type != 'bank-transfer') {
991  if (empty($format)) {
992  $this->error = 'ErrorBadParametersForDirectDebitFileCreate';
993  return -1;
994  }
995  }
996 
997  // Clean params
998  if (empty($fk_bank_account)) {
999  $fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
1000  }
1001 
1002  $error = 0;
1003 
1004  $datetimeprev = dol_now('gmt');
1005  // Choice the date of the execution direct debit
1006  if (!empty($executiondate)) {
1007  $datetimeprev = $executiondate;
1008  }
1009 
1010  $month = dol_print_date($datetimeprev, "%m", 'gmt');
1011  $year = dol_print_date($datetimeprev, "%Y", 'gmt');
1012 
1013  $this->invoice_in_error = array();
1014  $this->thirdparty_in_error = array();
1015 
1016  // Read invoices
1017  $factures = array();
1018  $factures_prev = array();
1019  $factures_result = array();
1020  $factures_prev_id = array();
1021  $factures_errors = array();
1022  if (!$error) {
1023  dol_syslog(__METHOD__ . " Read invoices for did=" . ((int) $did), LOG_DEBUG);
1024 
1025  $sql = "SELECT f.rowid, pd.rowid as pfdrowid";
1026  if ($sourcetype != 'salary') {
1027  $sql .= ", f.fk_soc";
1028  } else {
1029  $sql .= ", f.fk_user";
1030  }
1031  $sql .= ", pd.code_banque, pd.code_guichet, pd.number, pd.cle_rib";
1032  $sql .= ", pd.amount";
1033  if ($sourcetype != 'salary') {
1034  $sql .= ", s.nom as name";
1035  $sql .= ", f.ref, sr.bic, sr.iban_prefix, sr.frstrecur";
1036  } else {
1037  $sql .= ", CONCAT(s.firstname,' ',s.lastname) as name";
1038  $sql .= ", f.ref, sr.bic, sr.iban_prefix, 'FRST' as frstrecur";
1039  }
1040  if ($sourcetype != 'salary') {
1041  if ($type != 'bank-transfer') {
1042  $sql .= " FROM " . MAIN_DB_PREFIX . "facture as f";
1043  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "prelevement_demande as pd ON f.rowid = pd.fk_facture";
1044  } else {
1045  $sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
1046  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "prelevement_demande as pd ON f.rowid = pd.fk_facture_fourn";
1047  }
1048  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe as s ON s.rowid = f.fk_soc";
1049  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe_rib as sr ON s.rowid = sr.fk_soc AND sr.default_rib = 1";
1050  } else {
1051  $sql .= " FROM " . MAIN_DB_PREFIX . "salary as f";
1052  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "prelevement_demande as pd ON f.rowid = pd.fk_salary";
1053  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "user as s ON s.rowid = f.fk_user";
1054  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "user_rib as sr ON s.rowid = sr.fk_user"; // TODO Add AND sr.default_rib = 1 here
1055  }
1056  if ($sourcetype != 'salary') {
1057  if ($type != 'bank-transfer') {
1058  $sql .= " WHERE f.entity IN (" . getEntity('invoice') . ')';
1059  } else {
1060  $sql .= " WHERE f.entity IN (" . getEntity('supplier_invoice') . ')';
1061  }
1062  } else {
1063  $sql .= " WHERE f.entity IN (" . getEntity('salary') . ')';
1064  }
1065  if ($sourcetype != 'salary') {
1066  $sql .= " AND f.fk_statut = 1"; // Invoice validated
1067  $sql .= " AND f.paye = 0";
1068  $sql .= " AND f.total_ttc > 0";
1069  } else {
1070  //$sql .= " AND f.fk_statut = 1"; // Invoice validated
1071  $sql .= " AND f.paye = 0";
1072  $sql .= " AND f.amount > 0";
1073  }
1074  $sql .= " AND pd.traite = 0";
1075  $sql .= " AND pd.ext_payment_id IS NULL";
1076  if ($sourcetype != 'salary') {
1077  $sql .= " AND sr.type = 'ban'"; // TODO Add AND sr.type = 'ban' for users too
1078  }
1079  if ($did > 0) {
1080  $sql .= " AND pd.rowid = " . ((int) $did);
1081  }
1082 
1083  $resql = $this->db->query($sql);
1084  if ($resql) {
1085  $num = $this->db->num_rows($resql);
1086  $i = 0;
1087 
1088  while ($i < $num) {
1089  $row = $this->db->fetch_row($resql); // TODO Replace with fetch_object()
1090  $factures[$i] = $row; // All fields
1091 
1092  if ($row[7] == 0) {
1093  $error++;
1094  dol_syslog(__METHOD__ . " Read invoices/salary error Found a null amount", LOG_ERR);
1095  $this->invoice_in_error[$row[0]] = "Error for invoice or salary id " . $row[0] . ", found a null amount";
1096  break;
1097  }
1098  $i++;
1099  }
1100 
1101  $this->db->free($resql);
1102  dol_syslog(__METHOD__ . " Read invoices/salary, " . $i . " invoices/salary to withdraw", LOG_DEBUG);
1103  } else {
1104  $error++;
1105  $this->error = $this->db->lasterror();
1106  dol_syslog(__METHOD__ . " Read invoices/salary error " . $this->db->lasterror(), LOG_ERR);
1107  return -1;
1108  }
1109  }
1110 
1111  if (!$error) {
1112  // Make some checks
1113  require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
1114  require_once DOL_DOCUMENT_ROOT . '/user/class/user.class.php';
1115  require_once DOL_DOCUMENT_ROOT . '/societe/class/companybankaccount.class.php';
1116  require_once DOL_DOCUMENT_ROOT . '/core/lib/bank.lib.php';
1117 
1118  $tmpsoc = new Societe($this->db);
1119  $tmpuser = new User($this->db);
1120 
1121  // Check BAN
1122  $i = 0;
1123  dol_syslog(__METHOD__ . " Check BAN", LOG_DEBUG);
1124 
1125  if (count($factures) > 0) {
1126  foreach ($factures as $key => $fac) {
1127  /*
1128  if ($type != 'bank-transfer') {
1129  $tmpinvoice = new Facture($this->db);
1130  } else {
1131  $tmpinvoice = new FactureFournisseur($this->db);
1132  }
1133  $resfetch = $tmpinvoice->fetch($fac[0]);
1134  if ($resfetch >= 0) { // Field 0 of $fac is rowid of invoice
1135  */
1136 
1137  // Check if $fac[8] s.nom is null
1138  if ($fac[8] != null) {
1139  if ($type != 'bank-transfer') {
1140  if ($format == 'FRST' && $fac[12] != 'FRST') {
1141  continue;
1142  }
1143  if ($format == 'RCUR' && $fac[12] != 'RCUR') {
1144  continue;
1145  }
1146  }
1147 
1148  $verif = checkSwiftForAccount(null, $fac[10]);
1149  if ($verif) {
1150  $verif = checkIbanForAccount(null, $fac[11]);
1151  }
1152 
1153  if ($verif) {
1154  $factures_prev[$i] = $fac;
1155  /* second array necessary for BonPrelevement */
1156  $factures_prev_id[$i] = $fac[0];
1157  $i++;
1158  //dol_syslog(__METHOD__."::RIB is ok", LOG_DEBUG);
1159  } else {
1160  if ($type != 'bank-transfer') {
1161  $tmpsoc->id = $fac[2];
1162  $tmpsoc->name = $fac[8];
1163  $invoice_url = "<a href='" . DOL_URL_ROOT . '/compta/facture/card.php?facid=' . $fac[0] . "'>" . $fac[9] . "</a>";
1164  $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1165  $this->thirdparty_in_error[$tmpsoc->id] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1166  $error++;
1167  }
1168  if ($type == 'bank-transfer' && $sourcetype != 'salary') {
1169  $tmpsoc->id = $fac[2];
1170  $tmpsoc->name = $fac[8];
1171  $invoice_url = "<a href='" . DOL_URL_ROOT . '/fourn/facture/card.php?facid=' . $fac[0] . "'>" . $fac[9] . "</a>";
1172  $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1173  $this->thirdparty_in_error[$tmpsoc->id] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1174  $error++;
1175  }
1176  if ($type == 'bank-transfer' && $sourcetype == 'salary') {
1177  $tmpuser->id = $fac[2];
1178  $tmpuser->firstname = $fac[8];
1179  $salary_url = "<a href='" . DOL_URL_ROOT . '/salaries/card.php?id=' . $fac[0] . "'>" . $fac[0] . "</a>";
1180  $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for salary " . $salary_url . " for employee " . $tmpuser->getNomUrl(0);
1181  $this->thirdparty_in_error[$tmpuser->id] = "Error on default bank number IBAN/BIC for salary " . $salary_url . " for employee " . $tmpuser->getNomUrl(0);
1182  $error++;
1183  }
1184  dol_syslog(__METHOD__ . " Check BAN Error on default bank number IBAN/BIC reported by verif(): " . implode(', ', $fac), LOG_WARNING);
1185  }
1186  } else {
1187  dol_syslog(__METHOD__ . " Check BAN Failed to read company", LOG_WARNING);
1188  }
1189  /*
1190  } else {
1191  dol_syslog(__METHOD__." Check BAN Failed to read invoice", LOG_WARNING);
1192  }
1193  */
1194  }
1195  } else {
1196  dol_syslog(__METHOD__ . " Check BAN No invoice to process", LOG_WARNING);
1197  }
1198  }
1199 
1200  $ok = 0;
1201 
1202  // Withdraw invoices in factures_prev array
1203  $out = count($factures_prev) . " invoices will be included.";
1204  //print $out."\n";
1205  dol_syslog($out);
1206 
1207  // Return warning
1208  /*$i=0;
1209  foreach ($this->thirdparty_in_error as $key => $val)
1210  {
1211  if ($i < 10) setEventMessages($val, null, 'warnings');
1212  else setEventMessages('More error were discarded...', null, 'warnings');
1213  $i++;
1214  }*/
1215 
1216  if (count($factures_prev) > 0) {
1217  if ($mode == 'real') {
1218  $ok = 1;
1219  } else {
1220  print $langs->trans("ModeWarning"); // "Option for real mode was not set, we stop after this simulation\n";
1221  }
1222  }
1223  if ($ok) {
1224  /*
1225  * We are in real mode.
1226  * We create order and build file into disk
1227  */
1228  $this->db->begin();
1229 
1230  $now = dol_now();
1231  $ref = '';
1232 
1233  /*
1234  * Process order generation
1235  */
1236  if (!$error) {
1237  $ref = substr($year, -2) . $month;
1238 
1239  // Get next free number for the ref of bon prelevement
1240  $sql = "SELECT substring(ref from char_length(ref) - 1)"; // To extract "YYMMXX" from "TYYMMXX"
1241  $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons";
1242  $sql .= " WHERE ref LIKE '_" . $this->db->escape($ref) . "%'";
1243  $sql .= " AND entity = " . ((int) $conf->entity);
1244  $sql .= " ORDER BY ref DESC LIMIT 1";
1245 
1246  dol_syslog(get_class($this) . " get next free number", LOG_DEBUG);
1247  $resql = $this->db->query($sql);
1248 
1249  if ($resql) {
1250  $row = $this->db->fetch_row($resql);
1251 
1252  // Build the new ref
1253  $ref = "T" . $ref . sprintf("%02d", (intval($row[0]) + 1));
1254 
1255  // $conf->abc->dir_output may be:
1256  // /home/ldestailleur/git/dolibarr_15.0/documents/abc/
1257  // or
1258  // /home/ldestailleur/git/dolibarr_15.0/documents/X/abc with X >= 2 with multicompany.
1259  if ($type != 'bank-transfer') {
1260  $dir = $conf->prelevement->dir_output . '/receipts';
1261  } else {
1262  $dir = $conf->paymentbybanktransfer->dir_output . '/receipts';
1263  }
1264  if (!is_dir($dir)) {
1265  dol_mkdir($dir);
1266  }
1267 
1268  if (isModEnabled('multicompany')) {
1269  $labelentity = $conf->entity;
1270  $this->filename = $dir . '/' . $ref . '-' . $labelentity . '.xml';
1271  } else {
1272  $this->filename = $dir . '/' . $ref . '.xml';
1273  }
1274 
1275  // Create withdraw order in database
1276  $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_bons (";
1277  $sql .= "ref, entity, datec, type, fk_bank_account";
1278  $sql .= ") VALUES (";
1279  $sql .= "'" . $this->db->escape($ref) . "'";
1280  $sql .= ", " . ((int) $conf->entity);
1281  $sql .= ", '" . $this->db->idate($now) . "'";
1282  $sql .= ", '" . ($type == 'bank-transfer' ? 'bank-transfer' : 'debit-order') . "'";
1283  $sql .= ", " . ((int) $fk_bank_account);
1284  $sql .= ")";
1285 
1286  $resql = $this->db->query($sql);
1287 
1288 
1289  if ($resql) {
1290  $prev_id = $this->db->last_insert_id(MAIN_DB_PREFIX . "prelevement_bons");
1291  $this->id = $prev_id;
1292  $this->ref = $ref;
1293  } else {
1294  $error++;
1295  dol_syslog(__METHOD__ . " Create withdraw receipt " . $this->db->lasterror(), LOG_ERR);
1296  }
1297  } else {
1298  $error++;
1299  dol_syslog(__METHOD__ . " Get last withdraw receipt " . $this->db->lasterror(), LOG_ERR);
1300  }
1301  }
1302 
1303  if (!$error) {
1304  dol_syslog(__METHOD__ . " Now loop on each document to insert them in llx_prelevement_demande");
1305 
1306  // Add lines for the bon
1307  if (count($factures_prev) > 0) {
1308  foreach ($factures_prev as $fac) { // Add a link in database for each invoice ro salary
1309  /*
1310  * Add standing order. This add record into llx_prelevement_lignes and llx_prelevement
1311  *
1312  * $fac[0] : invoice_id
1313  * $fac[1] : ???
1314  * $fac[2] : third party id
1315  * $fac[3] : banque
1316  * $fac[4] : guichet
1317  * $fac[5] : number
1318  * $fac[6] : cle rib
1319  * $fac[7] : amount
1320  * $fac[8] : client nom
1321  * $fac[9] : Invoice ref
1322  * $fac[10] : BIC
1323  * $fac[11] : IBAN
1324  * $fac[12] : frstrcur
1325  */
1326  $ri = $this->AddFacture($fac[0], $fac[2], $fac[8], $fac[7], $fac[3], $fac[4], $fac[5], $fac[6], $type, $sourcetype);
1327 
1328  if ($ri != 0) {
1329  $error++;
1330  }
1331 
1332  // Update invoice requests as done
1333  $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_demande";
1334  $sql .= " SET traite = 1";
1335  $sql .= ", date_traite = '" . $this->db->idate($now) . "'";
1336  $sql .= ", fk_prelevement_bons = " . ((int) $this->id);
1337  $sql .= " WHERE rowid = " . ((int) $fac[1]);
1338 
1339  $resql = $this->db->query($sql);
1340  if (!$resql) {
1341  $error++;
1342  $this->errors[] = $this->db->lasterror();
1343  dol_syslog(__METHOD__ . " Update Error=" . $this->db->lasterror(), LOG_ERR);
1344  }
1345  }
1346  }
1347  }
1348 
1349  if (!$error) {
1350  /*
1351  * Create file of type='direct-debit' for direct debit order or type='bank-transfer' for credit transfer into a XML file
1352  */
1353 
1354  dol_syslog(__METHOD__ . " Init direct debit or credit transfer file for " . count($factures_prev) . " invoices", LOG_DEBUG);
1355 
1356  if (count($factures_prev) > 0) {
1357  $this->date_echeance = $datetimeprev;
1358  $this->reference_remise = $ref;
1359 
1360  $account = new Account($this->db);
1361  if ($account->fetch($fk_bank_account) > 0) {
1362  $this->emetteur_code_banque = $account->code_banque;
1363  $this->emetteur_code_guichet = $account->code_guichet;
1364  $this->emetteur_numero_compte = $account->number;
1365  $this->emetteur_number_key = $account->cle_rib;
1366  $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
1367  $this->emetteur_iban = $account->iban;
1368  $this->emetteur_bic = $account->bic;
1369 
1370  $this->emetteur_ics = (($type == 'bank-transfer' && getDolGlobalString("SEPA_USE_IDS")) ? $account->ics_transfer : $account->ics); // Example "FR78ZZZ123456"
1371 
1372  $this->raison_sociale = $account->proprio;
1373  }
1374  $this->factures = $factures_prev_id;
1375  $this->context['factures_prev'] = $factures_prev;
1376  // Generation of direct debit or credit transfer file $this->filename (May be a SEPA file for european countries)
1377  // This also set the property $this->total with amount that is included into file
1378  $userid = 0;
1379  if ($sourcetype == 'salary') {
1380  $userid = $this->context['factures_prev'][0][2];
1381  }
1382  $result = $this->generate($format, $executiondate, $type, $fk_bank_account, $userid);
1383  if ($result < 0) {
1384  //var_dump($this->error);
1385  //var_dump($this->invoice_in_error);
1386  $error++;
1387  }
1388  }
1389  dol_syslog(__METHOD__ . " Bank order file has been generated under filename " . $this->filename, LOG_DEBUG);
1390  }
1391 
1392 
1393  /*
1394  * Update total defined after generation of file
1395  */
1396  if (!$error) {
1397  $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_bons";
1398  $sql .= " SET amount = " . price2num($this->total);
1399  $sql .= " WHERE rowid = " . ((int) $this->id);
1400  $sql .= " AND entity = " . ((int) $conf->entity);
1401  $resql = $this->db->query($sql);
1402 
1403  if (!$resql) {
1404  $error++;
1405  dol_syslog(__METHOD__ . " Error update total: " . $this->db->error(), LOG_ERR);
1406  }
1407  }
1408 
1409  if (!$error && !$notrigger) {
1410  $triggername = 'DIRECT_DEBIT_ORDER_CREATE';
1411  if ($type != 'bank-transfer') {
1412  $triggername = 'CREDIT_TRANSFER_ORDER_CREATE';
1413  }
1414 
1415  // Call trigger
1416  $result = $this->call_trigger($triggername, $user);
1417  if ($result < 0) {
1418  $error++;
1419  }
1420  // End call triggers
1421  }
1422 
1423  if (!$error) {
1424  $this->db->commit();
1425  return count($factures_prev); // The error of failed lines are into $this->invoice_in_error and $this->thirdparty_in_error
1426  } else {
1427  $this->db->rollback();
1428  return -1;
1429  }
1430  } else {
1431  return 0;
1432  }
1433  }
1434 
1435 
1443  public function delete($user = null, $notrigger = 0)
1444  {
1445  $this->db->begin();
1446 
1447  $error = 0;
1448  $resql1 = $resql2 = $resql3 = $resql4 = 0;
1449 
1450  if (!$notrigger) {
1451  $triggername = 'DIRECT_DEBIT_ORDER_DELETE';
1452  if ($this->type == 'bank-transfer') {
1453  $triggername = 'PAYMENTBYBANKTRANFER_DELETE';
1454  }
1455  // Call trigger
1456  $result = $this->call_trigger($triggername, $user);
1457  if ($result < 0) {
1458  $error++;
1459  }
1460  // End call triggers
1461  }
1462 
1463  if (!$error) {
1464  $sql = "DELETE FROM " . MAIN_DB_PREFIX . "prelevement WHERE fk_prelevement_lignes IN (SELECT rowid FROM " . MAIN_DB_PREFIX . "prelevement_lignes WHERE fk_prelevement_bons = " . ((int) $this->id) . ")";
1465  $resql1 = $this->db->query($sql);
1466  if (!$resql1) {
1467  dol_print_error($this->db);
1468  }
1469  }
1470 
1471  if (!$error) {
1472  $sql = "DELETE FROM " . MAIN_DB_PREFIX . "prelevement_lignes WHERE fk_prelevement_bons = " . ((int) $this->id);
1473  $resql2 = $this->db->query($sql);
1474  if (!$resql2) {
1475  dol_print_error($this->db);
1476  }
1477  }
1478 
1479  if (!$error) {
1480  $sql = "DELETE FROM " . MAIN_DB_PREFIX . "prelevement_bons WHERE rowid = " . ((int) $this->id);
1481  $resql3 = $this->db->query($sql);
1482  if (!$resql3) {
1483  dol_print_error($this->db);
1484  }
1485  }
1486 
1487  if (!$error) {
1488  $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_demande SET fk_prelevement_bons = NULL, traite = 0 WHERE fk_prelevement_bons = " . ((int) $this->id);
1489  $resql4 = $this->db->query($sql);
1490  if (!$resql4) {
1491  dol_print_error($this->db);
1492  }
1493  }
1494 
1495  if ($resql1 && $resql2 && $resql3 && $resql4 && !$error) {
1496  $this->db->commit();
1497  return 1;
1498  } else {
1499  $this->db->rollback();
1500  return -1;
1501  }
1502  }
1503 
1504 
1515  public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1516  {
1517  global $conf, $langs, $hookmanager;
1518 
1519  if (!empty($conf->dol_no_mouse_hover)) {
1520  $notooltip = 1; // Force disable tooltips
1521  }
1522 
1523  $result = '';
1524 
1525  $labeltoshow = 'PaymentByDirectDebit';
1526  if (!empty($this->type) && $this->type == 'bank-transfer') {
1527  $labeltoshow = 'PaymentByBankTransfer';
1528  }
1529 
1530  $label = img_picto('', $this->picto) . ' <u>' . $langs->trans($labeltoshow) . '</u> ' . $this->getLibStatut(5);
1531  $label .= '<br>';
1532  $label .= '<b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
1533  if (isset($this->amount)) {
1534  $label .= '<br><b>' . $langs->trans("Amount") . ":</b> " . price($this->amount);
1535  }
1536  if (isset($this->date_trans)) {
1537  $label .= '<br><b>' . $langs->trans("TransData") . ":</b> " . dol_print_date($this->date_trans, 'dayhour', 'tzuserrel');
1538  }
1539  /*if (isset($this->date_credit)) {
1540  $label .= '<br><b>'.$langs->trans("TransData").":</b> ".dol_print_date($this->date_credit, 'dayhour', 'tzuserrel');
1541  }*/
1542 
1543  $url = DOL_URL_ROOT . '/compta/prelevement/card.php?id=' . $this->id;
1544  if (!empty($this->type) && $this->type == 'bank-transfer') {
1545  $url = DOL_URL_ROOT . '/compta/prelevement/card.php?id=' . $this->id;
1546  }
1547 
1548  if ($option != 'nolink') {
1549  // Add param to save lastsearch_values or not
1550  $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1551  if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1552  $add_save_lastsearch_values = 1;
1553  }
1554  if ($add_save_lastsearch_values) {
1555  $url .= '&save_lastsearch_values=1';
1556  }
1557  }
1558 
1559  $linkclose = '';
1560  if (empty($notooltip)) {
1561  if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1562  $label = $langs->trans("ShowMyObject");
1563  $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
1564  }
1565  $linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"';
1566  $linkclose .= ' class="classfortooltip' . ($morecss ? ' ' . $morecss : '') . '"';
1567  } else {
1568  $linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
1569  }
1570 
1571  $linkstart = '<a href="' . $url . '"';
1572  $linkstart .= $linkclose . '>';
1573  $linkend = '</a>';
1574 
1575  $result .= $linkstart;
1576  if ($withpicto) {
1577  $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="' . (($withpicto != 2) ? 'paddingright ' : '') . 'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
1578  }
1579  if ($withpicto != 2) {
1580  $result .= $this->ref;
1581  }
1582  $result .= $linkend;
1583 
1584  global $action, $hookmanager;
1585  $hookmanager->initHooks(array('banktransferdao'));
1586  $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1587  $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1588  if ($reshook > 0) {
1589  $result = $hookmanager->resPrint;
1590  } else {
1591  $result .= $hookmanager->resPrint;
1592  }
1593 
1594  return $result;
1595  }
1596 
1597 
1604  public function deleteNotificationById($rowid)
1605  {
1606  $sql = "DELETE FROM " . MAIN_DB_PREFIX . "notify_def";
1607  $sql .= " WHERE rowid = " . ((int) $rowid);
1608 
1609  if ($this->db->query($sql)) {
1610  return 0;
1611  } else {
1612  return -1;
1613  }
1614  }
1615 
1623  public function deleteNotification($user, $action)
1624  {
1625  if (is_object($user)) {
1626  $userid = $user->id;
1627  } else { // If user is an id
1628  $userid = $user;
1629  }
1630 
1631  $sql = "DELETE FROM " . MAIN_DB_PREFIX . "notify_def";
1632  $sql .= " WHERE fk_user=" . ((int) $userid) . " AND fk_action='" . $this->db->escape($action) . "'";
1633 
1634  if ($this->db->query($sql)) {
1635  return 0;
1636  } else {
1637  return -1;
1638  }
1639  }
1640 
1641  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1650  public function addNotification($db, $user, $action)
1651  {
1652  // phpcs:enable
1653  $result = 0;
1654 
1655  if (is_object($user)) {
1656  $userid = $user->id;
1657  } else { // If user is an id
1658  $userid = $user;
1659  }
1660 
1661  if ($this->deleteNotification($user, $action) == 0) {
1662  $now = dol_now();
1663 
1664  $sql = "INSERT INTO " . MAIN_DB_PREFIX . "notify_def (datec,fk_user, fk_soc, fk_contact, fk_action)";
1665  $sql .= " VALUES ('" . $this->db->idate($now) . "', " . ((int) $userid) . ", 'NULL', 'NULL', '" . $this->db->escape($action) . "')";
1666 
1667  dol_syslog("adnotiff: " . $sql);
1668  if ($this->db->query($sql)) {
1669  $result = 0;
1670  } else {
1671  $result = -1;
1672  dol_syslog(get_class($this) . "::addNotification Error $result");
1673  }
1674  }
1675 
1676  return $result;
1677  }
1678 
1679 
1694  public function generate($format = 'ALL', $executiondate = 0, $type = 'direct-debit', $fk_bank_account = 0, $forsalary = 0)
1695  {
1696  global $conf, $langs, $mysoc;
1697 
1698  //TODO: Optimize code to read lines in a single function
1699 
1700  // Clean params
1701  if (empty($fk_bank_account)) {
1702  $fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
1703  }
1704 
1705  $result = 0;
1706 
1707  dol_syslog(get_class($this) . "::generate build file=" . $this->filename . " type=" . $type);
1708 
1709  $this->file = fopen($this->filename, "w");
1710  if (empty($this->file)) {
1711  $this->error = $langs->trans('ErrorFailedToOpenFile', $this->filename);
1712  return -1;
1713  }
1714 
1715  $found = 0;
1716  $this->total = 0;
1717 
1718  // Build file for European countries
1719  if ($mysoc->isInEEC()) {
1720  $found++;
1721 
1722  if ($type != 'bank-transfer') {
1726  // SEPA Initialisation
1727  $CrLf = "\n";
1728 
1729  $now = dol_now();
1730 
1731  $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S');
1732 
1733  $date_actu = $now;
1734  if (!empty($executiondate)) {
1735  $date_actu = $executiondate;
1736  }
1737 
1738  $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d');
1739  $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S');
1740  $fileDebiteurSection = '';
1741  $fileEmetteurSection = '';
1742  $i = 0;
1743 
1744  /*
1745  * Section Debitor (sepa Debiteurs block lines)
1746  */
1747 
1748  $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
1749  $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1750  $sql .= " f.ref as reffac, p.fk_facture as idfac,";
1751  $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
1752  $sql .= " FROM";
1753  $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1754  $sql .= " " . MAIN_DB_PREFIX . "facture as f,";
1755  $sql .= " " . MAIN_DB_PREFIX . "prelevement as p,";
1756  $sql .= " " . MAIN_DB_PREFIX . "societe as soc,";
1757  $sql .= " " . MAIN_DB_PREFIX . "c_country as c,";
1758  $sql .= " " . MAIN_DB_PREFIX . "societe_rib as rib";
1759  $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
1760  $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1761  $sql .= " AND p.fk_facture = f.rowid";
1762  $sql .= " AND f.fk_soc = soc.rowid";
1763  $sql .= " AND soc.fk_pays = c.rowid";
1764  $sql .= " AND rib.fk_soc = f.fk_soc";
1765  $sql .= " AND rib.default_rib = 1";
1766  $sql .= " AND rib.type = 'ban'";
1767 
1768  // Define $fileDebiteurSection. One section DrctDbtTxInf per invoice.
1769  $resql = $this->db->query($sql);
1770  if ($resql) {
1771  $cachearraytotestduplicate = array();
1772 
1773  $num = $this->db->num_rows($resql);
1774  while ($i < $num) {
1775  $obj = $this->db->fetch_object($resql);
1776 
1777  if (!empty($cachearraytotestduplicate[$obj->idfac])) {
1778  $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
1779  $this->invoice_in_error[$obj->idfac] = $this->error;
1780  $result = -2;
1781  break;
1782  }
1783  $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
1784 
1785  $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
1786 
1787  $fileDebiteurSection .= $this->EnregDestinataireSEPA($obj->code, $obj->nom, $obj->address, $obj->zip, $obj->town, $obj->country_code, $obj->cb, $obj->cg, $obj->cc, $obj->somme, $obj->reffac, $obj->idfac, $obj->iban, $obj->bic, $daterum, $obj->drum, $obj->rum, $type);
1788 
1789  $this->total = $this->total + $obj->somme;
1790  $i++;
1791  }
1792  $nbtotalDrctDbtTxInf = $i;
1793  } else {
1794  $this->error = $this->db->lasterror();
1795  fwrite($this->file, 'ERROR DEBITOR ' . $sql . $CrLf); // DEBITOR = Customers
1796  $result = -2;
1797  }
1798 
1799  // Define $fileEmetteurSection. Start of block PmtInf. Will contains all $nbtotalDrctDbtTxInf
1800  if ($result != -2) {
1801  $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type, $fk_bank_account);
1802  }
1803 
1804  if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) {
1805  $this->total = number_format((float) price2num($this->total, 'MT'), 2, ".", "");
1806  }
1807 
1811  // SEPA File Header
1812  fwrite($this->file, '<' . '?xml version="1.0" encoding="UTF-8" standalone="yes"?' . '>' . $CrLf);
1813  fwrite($this->file, '<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' . $CrLf);
1814  fwrite($this->file, ' <CstmrDrctDbtInitn>' . $CrLf);
1815  // SEPA Group header
1816  fwrite($this->file, ' <GrpHdr>' . $CrLf);
1817  fwrite($this->file, ' <MsgId>' . ('DD/' . $dateTime_YMD . '/REF' . $this->id) . '</MsgId>' . $CrLf);
1818  fwrite($this->file, ' <CreDtTm>' . $dateTime_ECMA . '</CreDtTm>' . $CrLf);
1819  fwrite($this->file, ' <NbOfTxs>' . $i . '</NbOfTxs>' . $CrLf);
1820  fwrite($this->file, ' <CtrlSum>' . $this->total . '</CtrlSum>' . $CrLf);
1821  fwrite($this->file, ' <InitgPty>' . $CrLf);
1822  fwrite($this->file, ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf);
1823  fwrite($this->file, ' <Id>' . $CrLf);
1824  fwrite($this->file, ' <PrvtId>' . $CrLf);
1825  fwrite($this->file, ' <Othr>' . $CrLf);
1826  fwrite($this->file, ' <Id>' . $this->emetteur_ics . '</Id>' . $CrLf);
1827  fwrite($this->file, ' </Othr>' . $CrLf);
1828  fwrite($this->file, ' </PrvtId>' . $CrLf);
1829  fwrite($this->file, ' </Id>' . $CrLf);
1830  fwrite($this->file, ' </InitgPty>' . $CrLf);
1831  fwrite($this->file, ' </GrpHdr>' . $CrLf);
1832  // SEPA File Emetteur
1833  if ($result != -2) {
1834  fwrite($this->file, $fileEmetteurSection);
1835  }
1836  // SEPA File Debiteurs
1837  if ($result != -2) {
1838  fwrite($this->file, $fileDebiteurSection);
1839  }
1840  // SEPA FILE FOOTER
1841  fwrite($this->file, ' </PmtInf>' . $CrLf);
1842  fwrite($this->file, ' </CstmrDrctDbtInitn>' . $CrLf);
1843  fwrite($this->file, '</Document>' . $CrLf);
1844  } else {
1848  // SEPA Initialisation
1849  $CrLf = "\n";
1850 
1851  $now = dol_now();
1852 
1853  $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S');
1854 
1855  $date_actu = $now;
1856  if (!empty($executiondate)) {
1857  $date_actu = $executiondate;
1858  }
1859 
1860  $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d');
1861  $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S');
1862  $fileCrediteurSection = '';
1863  $fileEmetteurSection = '';
1864  $i = 0;
1865 
1866  /*
1867  * Section Creditor (sepa Crediteurs block lines)
1868  */
1869  if (!empty($forsalary)) {
1870  $sql = "SELECT u.rowid as userId, u.address, u.zip, u.town, c.code as country_code, CONCAT(u.firstname,' ',u.lastname) as nom,";
1871  $sql .= " pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1872  $sql .= " s.ref as reffac, p.fk_salary as idfac,";
1873  $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, '' as rum, '' as date_rum";
1874  $sql .= " FROM";
1875  $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1876  $sql .= " " . MAIN_DB_PREFIX . "salary as s,";
1877  $sql .= " " . MAIN_DB_PREFIX . "prelevement as p,";
1878  $sql .= " " . MAIN_DB_PREFIX . "user as u";
1879  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_country as c ON u.fk_country = c.rowid,";
1880  $sql .= " " . MAIN_DB_PREFIX . "user_rib as rib";
1881  $sql .= " WHERE pl.fk_prelevement_bons=" . ((int) $this->id);
1882  $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1883  $sql .= " AND p.fk_salary = s.rowid";
1884  $sql .= " AND s.fk_user = u.rowid";
1885  $sql .= " AND rib.fk_user = s.fk_user";
1886  } else {
1887  $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
1888  $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1889  $sql .= " f.ref as reffac, f.ref_supplier as fac_ref_supplier, p.fk_facture_fourn as idfac,";
1890  $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
1891  $sql .= " FROM";
1892  $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1893  $sql .= " " . MAIN_DB_PREFIX . "facture_fourn as f,";
1894  $sql .= " " . MAIN_DB_PREFIX . "prelevement as p,";
1895  $sql .= " " . MAIN_DB_PREFIX . "societe as soc";
1896  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_country as c ON soc.fk_pays = c.rowid,";
1897  $sql .= " " . MAIN_DB_PREFIX . "societe_rib as rib";
1898  $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
1899  $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1900  $sql .= " AND p.fk_facture_fourn = f.rowid";
1901  $sql .= " AND f.fk_soc = soc.rowid";
1902  $sql .= " AND rib.fk_soc = f.fk_soc";
1903  $sql .= " AND rib.default_rib = 1";
1904  $sql .= " AND rib.type = 'ban'";
1905  }
1906  // Define $fileCrediteurSection. One section DrctDbtTxInf per invoice.
1907  $resql = $this->db->query($sql);
1908  if ($resql) {
1909  $cachearraytotestduplicate = array();
1910 
1911  $num = $this->db->num_rows($resql);
1912  while ($i < $num) {
1913  $obj = $this->db->fetch_object($resql);
1914  if (!empty($cachearraytotestduplicate[$obj->idfac])) {
1915  $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
1916  $this->invoice_in_error[$obj->idfac] = $this->error;
1917  $result = -2;
1918  break;
1919  }
1920  $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
1921 
1922  $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
1923  $refobj = $obj->reffac;
1924  if (empty($refobj) && !empty($forsalary)) { // If ref of salary not defined, we force a value
1925  $refobj = "SAL" . $obj->idfac;
1926  }
1927 
1928  $fileCrediteurSection .= $this->EnregDestinataireSEPA($obj->code, $obj->nom, $obj->address, $obj->zip, $obj->town, $obj->country_code, $obj->cb, $obj->cg, $obj->cc, $obj->somme, $refobj, $obj->idfac, $obj->iban, $obj->bic, $daterum, $obj->drum, $obj->rum, $type, $obj->fac_ref_supplier);
1929 
1930  $this->total = $this->total + $obj->somme;
1931  $i++;
1932  }
1933  $nbtotalDrctDbtTxInf = $i;
1934  } else {
1935  $this->error = $this->db->lasterror();
1936  fwrite($this->file, 'ERROR CREDITOR ' . $sql . $CrLf); // CREDITORS = Suppliers
1937  $result = -2;
1938  }
1939  // Define $fileEmetteurSection. Start of block PmtInf. Will contains all $nbtotalDrctDbtTxInf
1940  if ($result != -2) {
1941  $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type);
1942  }
1943 
1944  if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) {
1945  $this->total = number_format((float) price2num($this->total, 'MT'), 2, ".", "");
1946  }
1947 
1951  // SEPA File Header
1952  fwrite($this->file, '<' . '?xml version="1.0" encoding="UTF-8" standalone="yes"?' . '>' . $CrLf);
1953  fwrite($this->file, '<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' . $CrLf);
1954  fwrite($this->file, ' <CstmrCdtTrfInitn>' . $CrLf);
1955  // SEPA Group header
1956  fwrite($this->file, ' <GrpHdr>' . $CrLf);
1957  fwrite($this->file, ' <MsgId>' . ('TRF/' . $dateTime_YMD . '/REF' . $this->id) . '</MsgId>' . $CrLf);
1958  fwrite($this->file, ' <CreDtTm>' . $dateTime_ECMA . '</CreDtTm>' . $CrLf);
1959  fwrite($this->file, ' <NbOfTxs>' . $i . '</NbOfTxs>' . $CrLf);
1960  fwrite($this->file, ' <CtrlSum>' . $this->total . '</CtrlSum>' . $CrLf);
1961  fwrite($this->file, ' <InitgPty>' . $CrLf);
1962  fwrite($this->file, ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf);
1963  fwrite($this->file, ' <Id>' . $CrLf);
1964  fwrite($this->file, ' <PrvtId>' . $CrLf);
1965  fwrite($this->file, ' <Othr>' . $CrLf);
1966  fwrite($this->file, ' <Id>' . $this->emetteur_ics . '</Id>' . $CrLf);
1967  fwrite($this->file, ' </Othr>' . $CrLf);
1968  fwrite($this->file, ' </PrvtId>' . $CrLf);
1969  fwrite($this->file, ' </Id>' . $CrLf);
1970  fwrite($this->file, ' </InitgPty>' . $CrLf);
1971  fwrite($this->file, ' </GrpHdr>' . $CrLf);
1972  // SEPA File Emetteur (mycompany)
1973  if ($result != -2) {
1974  fwrite($this->file, $fileEmetteurSection);
1975  }
1976  // SEPA File Creditors
1977  if ($result != -2) {
1978  fwrite($this->file, $fileCrediteurSection);
1979  }
1980  // SEPA FILE FOOTER
1981  fwrite($this->file, ' </PmtInf>' . $CrLf);
1982  fwrite($this->file, ' </CstmrCdtTrfInitn>' . $CrLf);
1983  fwrite($this->file, '</Document>' . $CrLf);
1984  }
1985  }
1986 
1987  // Build file for Other Countries with unknown format
1988  if (!$found) {
1989  if ($type != 'bank-transfer') {
1990  $sql = "SELECT pl.amount";
1991  $sql .= " FROM";
1992  $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1993  $sql .= " " . MAIN_DB_PREFIX . "facture as f,";
1994  $sql .= " " . MAIN_DB_PREFIX . "prelevement as p";
1995  $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
1996  $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1997  $sql .= " AND p.fk_facture = f.rowid";
1998 
1999  // Lines
2000  $i = 0;
2001  $resql = $this->db->query($sql);
2002  if ($resql) {
2003  $num = $this->db->num_rows($resql);
2004 
2005  while ($i < $num) {
2006  $obj = $this->db->fetch_object($resql);
2007  $this->total = $this->total + $obj->amount;
2008 
2009  // TODO Write record into file
2010  $i++;
2011  }
2012  } else {
2013  $result = -2;
2014  }
2015  } else {
2016  $sql = "SELECT pl.amount";
2017  $sql .= " FROM";
2018  $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
2019  $sql .= " " . MAIN_DB_PREFIX . "facture_fourn as f,";
2020  $sql .= " " . MAIN_DB_PREFIX . "prelevement as p";
2021  $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
2022  $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
2023  $sql .= " AND p.fk_facture_fourn = f.rowid";
2024  // Lines
2025  $i = 0;
2026  $resql = $this->db->query($sql);
2027  if ($resql) {
2028  $num = $this->db->num_rows($resql);
2029 
2030  while ($i < $num) {
2031  $obj = $this->db->fetch_object($resql);
2032  $this->total = $this->total + $obj->amount;
2033 
2034  // TODO Write record into file
2035  $i++;
2036  }
2037  } else {
2038  $result = -2;
2039  }
2040  }
2041 
2042  $langs->load('withdrawals');
2043 
2044  // TODO Add here code to generate a generic file
2045  fwrite($this->file, $langs->transnoentitiesnoconv('WithdrawalFileNotCapable', $mysoc->country_code));
2046  }
2047 
2048  fclose($this->file);
2049  dolChmod($this->filename);
2050 
2051  return $result;
2052  }
2053 
2054 
2063  public static function buildRumNumber($row_code_client, $row_datec, $row_drum)
2064  {
2065  global $langs;
2066 
2067  $pre = substr(dol_string_nospecial(dol_string_unaccent($langs->transnoentitiesnoconv('RUM'))), 0, 3); // Must always be on 3 char ('RUM' or 'UMR'. This is a protection against bad translation)
2068 
2069  // 3 char + '-' + 12 + '-' + id + '-' + code Must be lower than 32.
2070  return $pre . '-' . dol_print_date($row_datec, 'dayhourlogsmall') . '-' . dol_trunc($row_drum . ($row_code_client ? '-' . $row_code_client : ''), 13, 'right', 'UTF-8', 1);
2071  }
2072 
2073 
2074  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2091  public function EnregDestinataire($rowid, $client_nom, $rib_banque, $rib_guichet, $rib_number, $amount, $ref, $facid, $rib_dom = '', $type = 'direct-debit')
2092  {
2093  // phpcs:enable
2094  fwrite($this->file, "06");
2095  fwrite($this->file, "08"); // Prelevement ordinaire
2096 
2097  fwrite($this->file, " "); // Zone Reservee B2
2098 
2099  fwrite($this->file, $this->emetteur_ics); // ICS
2100 
2101  // Date d'echeance C1
2102 
2103  fwrite($this->file, " ");
2104  fwrite($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
2105  fwrite($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
2106 
2107  // Raison Sociale Destinataire C2
2108 
2109  fwrite($this->file, substr(strtoupper($client_nom) . " ", 0, 24));
2110 
2111  // Address optional D1
2112  $address = strtr($rib_dom, array(" " => "-", chr(13) => " ", chr(10) => ""));
2113  fwrite($this->file, substr($address . " ", 0, 24));
2114 
2115  // Zone Reservee D2
2116 
2117  fwrite($this->file, substr(" ", 0, 8));
2118 
2119  // Code Guichet D3
2120 
2121  fwrite($this->file, $rib_guichet);
2122 
2123  // Numero de compte D4
2124 
2125  fwrite($this->file, substr("000000000000000" . $rib_number, -11));
2126 
2127  // Zone E Montant
2128 
2129  $montant = (round($amount, 2) * 100);
2130 
2131  fwrite($this->file, substr("000000000000000" . $montant, -16));
2132 
2133  // Label F
2134 
2135  fwrite($this->file, substr("*_" . $ref . "_RDVnet" . $rowid . " ", 0, 31));
2136 
2137  // Code etablissement G1
2138 
2139  fwrite($this->file, $rib_banque);
2140 
2141  // Zone Reservee G2
2142 
2143  fwrite($this->file, substr(" ", 0, 5));
2144 
2145  fwrite($this->file, "\n");
2146  }
2147 
2148 
2149  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2175  public function EnregDestinataireSEPA($row_code_client, $row_nom, $row_address, $row_zip, $row_town, $row_country_code, $row_cb, $row_cg, $row_cc, $row_somme, $row_ref, $row_idfac, $row_iban, $row_bic, $row_datec, $row_drum, $row_rum, $type = 'direct-debit', $row_comment = '')
2176  {
2177  // phpcs:enable
2178  global $conf;
2179 
2180  if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) {
2181  $row_somme = number_format((float) price2num($row_somme, 'MT'), 2, ".", "");
2182  } else {
2183  $row_somme = round((float) $row_somme, 2);
2184  }
2185 
2186  include_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php';
2187 
2188  $CrLf = "\n";
2189  $Rowing = sprintf("%010d", $row_idfac);
2190 
2191  // Define value for RUM
2192  // Example: RUM-CustomerCode-CustomerBankAccountId-01424448606 (note: Date is the timestamp of the date of creation of CustomerBankAccountId)
2193  $Rum = (empty($row_rum) ? $this->buildRumNumber($row_code_client, $row_datec, $row_drum) : $row_rum);
2194 
2195  // Define date of RUM signature
2196  $DtOfSgntr = dol_print_date($row_datec, '%Y-%m-%d');
2197 
2198  if ($type != 'bank-transfer') {
2199  // SEPA Paiement Information of buyer for Direct Debit
2200  $XML_DEBITOR = '';
2201  $XML_DEBITOR .= ' <DrctDbtTxInf>' . $CrLf;
2202  $XML_DEBITOR .= ' <PmtId>' . $CrLf;
2203  // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
2204  $XML_DEBITOR .= ' <EndToEndId>' . ((getDolGlobalString('PRELEVEMENT_END_TO_END') != "") ? $conf->global->PRELEVEMENT_END_TO_END : ('DD-' . dol_trunc($row_idfac . '-' . $row_ref, 20, 'right', 'UTF-8', 1)) . '-' . $Rowing) . '</EndToEndId>' . $CrLf; // ISO20022 states that EndToEndId has a MaxLength of 35 characters
2205  $XML_DEBITOR .= ' </PmtId>' . $CrLf;
2206  $XML_DEBITOR .= ' <InstdAmt Ccy="EUR">' . $row_somme . '</InstdAmt>' . $CrLf;
2207  $XML_DEBITOR .= ' <DrctDbtTx>' . $CrLf;
2208  $XML_DEBITOR .= ' <MndtRltdInf>' . $CrLf;
2209  $XML_DEBITOR .= ' <MndtId>' . $Rum . '</MndtId>' . $CrLf;
2210  $XML_DEBITOR .= ' <DtOfSgntr>' . $DtOfSgntr . '</DtOfSgntr>' . $CrLf;
2211  $XML_DEBITOR .= ' <AmdmntInd>false</AmdmntInd>' . $CrLf;
2212  $XML_DEBITOR .= ' </MndtRltdInf>' . $CrLf;
2213  $XML_DEBITOR .= ' </DrctDbtTx>' . $CrLf;
2214  $XML_DEBITOR .= ' <DbtrAgt>' . $CrLf;
2215  $XML_DEBITOR .= ' <FinInstnId>' . $CrLf;
2216  $XML_DEBITOR .= ' <BIC>' . $row_bic . '</BIC>' . $CrLf;
2217  $XML_DEBITOR .= ' </FinInstnId>' . $CrLf;
2218  $XML_DEBITOR .= ' </DbtrAgt>' . $CrLf;
2219  $XML_DEBITOR .= ' <Dbtr>' . $CrLf;
2220  $XML_DEBITOR .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))) . '</Nm>' . $CrLf;
2221  $XML_DEBITOR .= ' <PstlAdr>' . $CrLf;
2222  $XML_DEBITOR .= ' <Ctry>' . $row_country_code . '</Ctry>' . $CrLf;
2223  $addressline1 = strtr($row_address, array(chr(13) => ", ", chr(10) => ""));
2224  $addressline2 = strtr($row_zip . (($row_zip && $row_town) ? ' ' : (string) $row_town), array(chr(13) => ", ", chr(10) => ""));
2225  if (trim($addressline1)) {
2226  $XML_DEBITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2227  }
2228  if (trim($addressline2)) {
2229  $XML_DEBITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2230  }
2231  $XML_DEBITOR .= ' </PstlAdr>' . $CrLf;
2232  $XML_DEBITOR .= ' </Dbtr>' . $CrLf;
2233  $XML_DEBITOR .= ' <DbtrAcct>' . $CrLf;
2234  $XML_DEBITOR .= ' <Id>' . $CrLf;
2235  $XML_DEBITOR .= ' <IBAN>' . preg_replace('/\s/', '', $row_iban) . '</IBAN>' . $CrLf;
2236  $XML_DEBITOR .= ' </Id>' . $CrLf;
2237  $XML_DEBITOR .= ' </DbtrAcct>' . $CrLf;
2238  $XML_DEBITOR .= ' <RmtInf>' . $CrLf;
2239  // A string with some information on payment - 140 max
2240  $XML_DEBITOR .= ' <Ustrd>' . getDolGlobalString('PRELEVEMENT_USTRD', dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($row_ref . ($row_comment ? ' - ' . $row_comment : '')), '', '', '', 1), 135, 'right', 'UTF-8', 1))) . '</Ustrd>' . $CrLf; // Free unstuctured data - 140 max
2241  $XML_DEBITOR .= ' </RmtInf>' . $CrLf;
2242  $XML_DEBITOR .= ' </DrctDbtTxInf>' . $CrLf;
2243  return $XML_DEBITOR;
2244  } else {
2245  // SEPA Payment Information of seller for Credit Transfer
2246  $XML_CREDITOR = '';
2247  $XML_CREDITOR .= ' <CdtTrfTxInf>' . $CrLf;
2248  $XML_CREDITOR .= ' <PmtId>' . $CrLf;
2249  // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
2250  $XML_CREDITOR .= ' <EndToEndId>' . ((getDolGlobalString('PRELEVEMENT_END_TO_END') != "") ? $conf->global->PRELEVEMENT_END_TO_END : ('CT-' . dol_trunc($row_idfac . '-' . $row_ref, 20, 'right', 'UTF-8', 1)) . '-' . $Rowing) . '</EndToEndId>' . $CrLf; // ISO20022 states that EndToEndId has a MaxLength of 35 characters
2251  $XML_CREDITOR .= ' </PmtId>' . $CrLf;
2252  if (!empty($this->sepa_xml_pti_in_ctti)) {
2253  $XML_CREDITOR .= ' <PmtTpInf>' . $CrLf;
2254 
2255  // Can be 'NORM' for normal or 'HIGH' for high priority level
2256  if (getDolGlobalString('PAYMENTBYBANKTRANSFER_FORCE_HIGH_PRIORITY')) {
2257  $instrprty = 'HIGH';
2258  } else {
2259  $instrprty = 'NORM';
2260  }
2261  $XML_CREDITOR .= ' <InstrPrty>' . $instrprty . '</InstrPrty>' . $CrLf;
2262  $XML_CREDITOR .= ' <SvcLvl>' . $CrLf;
2263  $XML_CREDITOR .= ' <Cd>SEPA</Cd>' . $CrLf;
2264  $XML_CREDITOR .= ' </SvcLvl>' . $CrLf;
2265  $XML_CREDITOR .= ' <CtgyPurp>' . $CrLf;
2266  $XML_CREDITOR .= ' <Cd>CORE</Cd>' . $CrLf;
2267  $XML_CREDITOR .= ' </CtgyPurp>' . $CrLf;
2268  $XML_CREDITOR .= ' </PmtTpInf>' . $CrLf;
2269  }
2270  $XML_CREDITOR .= ' <Amt>' . $CrLf;
2271  $XML_CREDITOR .= ' <InstdAmt Ccy="EUR">'.round((float) $row_somme, 2).'</InstdAmt>'.$CrLf;
2272  $XML_CREDITOR .= ' </Amt>' . $CrLf;
2273  /*
2274  $XML_CREDITOR .= ' <DrctDbtTx>'.$CrLf;
2275  $XML_CREDITOR .= ' <MndtRltdInf>'.$CrLf;
2276  $XML_CREDITOR .= ' <MndtId>'.$Rum.'</MndtId>'.$CrLf;
2277  $XML_CREDITOR .= ' <DtOfSgntr>'.$DtOfSgntr.'</DtOfSgntr>'.$CrLf;
2278  $XML_CREDITOR .= ' <AmdmntInd>false</AmdmntInd>'.$CrLf;
2279  $XML_CREDITOR .= ' </MndtRltdInf>'.$CrLf;
2280  $XML_CREDITOR .= ' </DrctDbtTx>'.$CrLf;
2281  */
2282  //$XML_CREDITOR .= ' <ChrgBr>SLEV</ChrgBr>'.$CrLf;
2283  $XML_CREDITOR .= ' <CdtrAgt>' . $CrLf;
2284  $XML_CREDITOR .= ' <FinInstnId>' . $CrLf;
2285  $XML_CREDITOR .= ' <BIC>' . $row_bic . '</BIC>' . $CrLf;
2286  $XML_CREDITOR .= ' </FinInstnId>' . $CrLf;
2287  $XML_CREDITOR .= ' </CdtrAgt>' . $CrLf;
2288  $XML_CREDITOR .= ' <Cdtr>' . $CrLf;
2289  $XML_CREDITOR .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))) . '</Nm>' . $CrLf;
2290  $XML_CREDITOR .= ' <PstlAdr>' . $CrLf;
2291  $XML_CREDITOR .= ' <Ctry>' . $row_country_code . '</Ctry>' . $CrLf;
2292  $addressline1 = strtr($row_address, array(chr(13) => ", ", chr(10) => ""));
2293  $addressline2 = strtr($row_zip . (($row_zip && $row_town) ? ' ' : (string) $row_town), array(chr(13) => ", ", chr(10) => ""));
2294  if (trim($addressline1)) {
2295  $XML_CREDITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2296  }
2297  if (trim($addressline2)) {
2298  $XML_CREDITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2299  }
2300  $XML_CREDITOR .= ' </PstlAdr>' . $CrLf;
2301  $XML_CREDITOR .= ' </Cdtr>' . $CrLf;
2302  $XML_CREDITOR .= ' <CdtrAcct>' . $CrLf;
2303  $XML_CREDITOR .= ' <Id>' . $CrLf;
2304  $XML_CREDITOR .= ' <IBAN>' . preg_replace('/\s/', '', $row_iban) . '</IBAN>' . $CrLf;
2305  $XML_CREDITOR .= ' </Id>' . $CrLf;
2306  $XML_CREDITOR .= ' </CdtrAcct>' . $CrLf;
2307  $XML_CREDITOR .= ' <RmtInf>' . $CrLf;
2308  // A string with some information on payment - 140 max
2309  $XML_CREDITOR .= ' <Ustrd>' . getDolGlobalString('CREDITTRANSFER_USTRD', dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($row_ref . ($row_comment ? ' - ' . $row_comment : '')), '', '', '', 1), 135, 'right', 'UTF-8', 1))) . '</Ustrd>' . $CrLf; // Free unstructured data - 140 max
2310  $XML_CREDITOR .= ' </RmtInf>' . $CrLf;
2311  $XML_CREDITOR .= ' </CdtTrfTxInf>' . $CrLf;
2312  return $XML_CREDITOR;
2313  }
2314  }
2315 
2316 
2317  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2325  public function EnregEmetteur($type = 'direct-debit')
2326  {
2327  // phpcs:enable
2328  fwrite($this->file, "03");
2329  fwrite($this->file, "08"); // Prelevement ordinaire
2330 
2331  fwrite($this->file, " "); // Zone Reservee B2
2332 
2333  fwrite($this->file, $this->emetteur_ics); // ICS
2334 
2335  // Date d'echeance C1
2336 
2337  fwrite($this->file, " ");
2338  fwrite($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
2339  fwrite($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
2340 
2341  // Raison Sociale C2
2342 
2343  fwrite($this->file, substr($this->raison_sociale . " ", 0, 24));
2344 
2345  // Reference de la remise creancier D1 sur 7 caracteres
2346 
2347  fwrite($this->file, substr($this->reference_remise . " ", 0, 7));
2348 
2349  // Zone Reservee D1-2
2350 
2351  fwrite($this->file, substr(" ", 0, 17));
2352 
2353  // Zone Reservee D2
2354 
2355  fwrite($this->file, substr(" ", 0, 2));
2356  fwrite($this->file, "E");
2357  fwrite($this->file, substr(" ", 0, 5));
2358 
2359  // Code Guichet D3
2360 
2361  fwrite($this->file, $this->emetteur_code_guichet);
2362 
2363  // Numero de compte D4
2364 
2365  fwrite($this->file, substr("000000000000000" . $this->emetteur_numero_compte, -11));
2366 
2367  // Zone Reservee E
2368 
2369  fwrite($this->file, substr(" ", 0, 16));
2370 
2371  // Zone Reservee F
2372 
2373  fwrite($this->file, substr(" ", 0, 31));
2374 
2375  // Code etablissement
2376 
2377  fwrite($this->file, $this->emetteur_code_banque);
2378 
2379  // Zone Reservee G
2380 
2381  fwrite($this->file, substr(" ", 0, 5));
2382 
2383  fwrite($this->file, "\n");
2384  }
2385 
2386 
2387  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2403  public function EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf = '\n', $format = 'FRST', $type = 'direct-debit', $fk_bank_account = 0)
2404  {
2405  // phpcs:enable
2406 
2407  // Clean parameters
2408  $dateTime_YMD = dol_print_date($ladate, '%Y%m%d');
2409  $dateTime_ETAD = dol_print_date($ladate, '%Y-%m-%d');
2410  $dateTime_YMDHMS = dol_print_date($ladate, '%Y-%m-%dT%H:%M:%S');
2411 
2412  // Clean params
2413  if (empty($fk_bank_account)) {
2414  $fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
2415  }
2416 
2417  // Get data of bank account
2418  $account = new Account($this->db);
2419  if ($account->fetch($fk_bank_account) > 0) {
2420  $this->emetteur_code_banque = $account->code_banque;
2421  $this->emetteur_code_guichet = $account->code_guichet;
2422  $this->emetteur_numero_compte = $account->number;
2423  $this->emetteur_number_key = $account->cle_rib;
2424  $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
2425  $this->emetteur_iban = $account->iban;
2426  $this->emetteur_bic = $account->bic;
2427 
2428  $this->emetteur_ics = (($type == 'bank-transfer' && getDolGlobalString("SEPA_USE_IDS")) ? $account->ics_transfer : $account->ics); // Ex: PRELEVEMENT_ICS = "FR78ZZZ123456";
2429 
2430  $this->raison_sociale = $account->proprio;
2431  }
2432 
2433  // Get pending payments
2434  $sql = "SELECT rowid, ref";
2435  $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons as pb";
2436  $sql .= " WHERE pb.rowid = " . ((int) $this->id);
2437 
2438  $resql = $this->db->query($sql);
2439  if ($resql) {
2440  $obj = $this->db->fetch_object($resql);
2441 
2442  $country = explode(':', $configuration->global->MAIN_INFO_SOCIETE_COUNTRY);
2443  $IdBon = sprintf("%05d", $obj->rowid);
2444  $RefBon = $obj->ref;
2445 
2446  if (!empty($configuration->global->SEPA_FORCE_TWO_DECIMAL)) {
2447  $total = number_format((float) price2num($total, 'MT'), 2, ".", "");
2448  }
2449 
2450  if ($type != 'bank-transfer') {
2451  // SEPA Paiement Information of my company for Direct Debit
2452  $XML_SEPA_INFO = '';
2453  $XML_SEPA_INFO .= ' <PmtInf>' . $CrLf;
2454  $XML_SEPA_INFO .= ' <PmtInfId>' . ('DD/' . $dateTime_YMD . '/ID' . $IdBon . '-' . $RefBon) . '</PmtInfId>' . $CrLf;
2455  $XML_SEPA_INFO .= ' <PmtMtd>DD</PmtMtd>' . $CrLf;
2456  $XML_SEPA_INFO .= ' <NbOfTxs>' . $nombre . '</NbOfTxs>' . $CrLf;
2457  $XML_SEPA_INFO .= ' <CtrlSum>' . $total . '</CtrlSum>' . $CrLf;
2458  $XML_SEPA_INFO .= ' <PmtTpInf>' . $CrLf;
2459  $XML_SEPA_INFO .= ' <SvcLvl>' . $CrLf;
2460  $XML_SEPA_INFO .= ' <Cd>SEPA</Cd>' . $CrLf;
2461  $XML_SEPA_INFO .= ' </SvcLvl>' . $CrLf;
2462  $XML_SEPA_INFO .= ' <LclInstrm>' . $CrLf;
2463  $XML_SEPA_INFO .= ' <Cd>CORE</Cd>' . $CrLf;
2464  $XML_SEPA_INFO .= ' </LclInstrm>' . $CrLf;
2465  $XML_SEPA_INFO .= ' <SeqTp>' . $format . '</SeqTp>' . $CrLf;
2466  $XML_SEPA_INFO .= ' </PmtTpInf>' . $CrLf;
2467  $XML_SEPA_INFO .= ' <ReqdColltnDt>' . $dateTime_ETAD . '</ReqdColltnDt>' . $CrLf;
2468  $XML_SEPA_INFO .= ' <Cdtr>' . $CrLf;
2469  $XML_SEPA_INFO .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf;
2470  $XML_SEPA_INFO .= ' <PstlAdr>' . $CrLf;
2471  $XML_SEPA_INFO .= ' <Ctry>' . $country[1] . '</Ctry>' . $CrLf;
2472  $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(chr(13) => ", ", chr(10) => ""));
2473  $addressline2 = strtr($configuration->global->MAIN_INFO_SOCIETE_ZIP . (($configuration->global->MAIN_INFO_SOCIETE_ZIP || ' ' . $configuration->global->MAIN_INFO_SOCIETE_TOWN) ? ' ' : '') . $configuration->global->MAIN_INFO_SOCIETE_TOWN, array(chr(13) => ", ", chr(10) => ""));
2474  if ($addressline1) {
2475  $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2476  }
2477  if ($addressline2) {
2478  $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2479  }
2480  $XML_SEPA_INFO .= ' </PstlAdr>' . $CrLf;
2481  $XML_SEPA_INFO .= ' </Cdtr>' . $CrLf;
2482  $XML_SEPA_INFO .= ' <CdtrAcct>' . $CrLf;
2483  $XML_SEPA_INFO .= ' <Id>' . $CrLf;
2484  $XML_SEPA_INFO .= ' <IBAN>' . preg_replace('/\s/', '', $this->emetteur_iban) . '</IBAN>' . $CrLf;
2485  $XML_SEPA_INFO .= ' </Id>' . $CrLf;
2486  $XML_SEPA_INFO .= ' </CdtrAcct>' . $CrLf;
2487  $XML_SEPA_INFO .= ' <CdtrAgt>' . $CrLf;
2488  $XML_SEPA_INFO .= ' <FinInstnId>' . $CrLf;
2489  $XML_SEPA_INFO .= ' <BIC>' . $this->emetteur_bic . '</BIC>' . $CrLf;
2490  $XML_SEPA_INFO .= ' </FinInstnId>' . $CrLf;
2491  $XML_SEPA_INFO .= ' </CdtrAgt>' . $CrLf;
2492  /* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf;
2493  $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2494  $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2495  $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2496  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ADDRESS), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2497  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ZIP.' '.$conf->global->MAIN_INFO_SOCIETE_TOWN), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2498  $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2499  $XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/
2500  $XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>' . $CrLf; // Field "Responsible of fees". Must be SLEV
2501  $XML_SEPA_INFO .= ' <CdtrSchmeId>' . $CrLf;
2502  $XML_SEPA_INFO .= ' <Id>' . $CrLf;
2503  $XML_SEPA_INFO .= ' <PrvtId>' . $CrLf;
2504  $XML_SEPA_INFO .= ' <Othr>' . $CrLf;
2505  $XML_SEPA_INFO .= ' <Id>' . $this->emetteur_ics . '</Id>' . $CrLf;
2506  $XML_SEPA_INFO .= ' <SchmeNm>' . $CrLf;
2507  $XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>' . $CrLf;
2508  $XML_SEPA_INFO .= ' </SchmeNm>' . $CrLf;
2509  $XML_SEPA_INFO .= ' </Othr>' . $CrLf;
2510  $XML_SEPA_INFO .= ' </PrvtId>' . $CrLf;
2511  $XML_SEPA_INFO .= ' </Id>' . $CrLf;
2512  $XML_SEPA_INFO .= ' </CdtrSchmeId>' . $CrLf;
2513  } else {
2514  // SEPA Paiement Information of my company for Credit Transfer
2515  $XML_SEPA_INFO = '';
2516  $XML_SEPA_INFO .= ' <PmtInf>' . $CrLf;
2517  $XML_SEPA_INFO .= ' <PmtInfId>' . ('TRF/' . $dateTime_YMD . '/ID' . $IdBon . '-' . $RefBon) . '</PmtInfId>' . $CrLf;
2518  $XML_SEPA_INFO .= ' <PmtMtd>TRF</PmtMtd>' . $CrLf;
2519  //$XML_SEPA_INFO .= ' <BtchBookg>False</BtchBookg>'.$CrLf;
2520  $XML_SEPA_INFO .= ' <NbOfTxs>' . $nombre . '</NbOfTxs>' . $CrLf;
2521  $XML_SEPA_INFO .= ' <CtrlSum>' . $total . '</CtrlSum>' . $CrLf;
2522  if (!empty($this->sepa_xml_pti_in_ctti) && !empty($format)) { // @TODO Using $format (FRST ou RCUR) in a section for a Credit Transfer looks strange.
2523  $XML_SEPA_INFO .= ' <PmtTpInf>' . $CrLf;
2524  $XML_SEPA_INFO .= ' <SvcLvl>' . $CrLf;
2525  $XML_SEPA_INFO .= ' <Cd>SEPA</Cd>' . $CrLf;
2526  $XML_SEPA_INFO .= ' </SvcLvl>' . $CrLf;
2527  $XML_SEPA_INFO .= ' <LclInstrm>' . $CrLf;
2528  $XML_SEPA_INFO .= ' <Cd>CORE</Cd>' . $CrLf;
2529  $XML_SEPA_INFO .= ' </LclInstrm>' . $CrLf;
2530  $XML_SEPA_INFO .= ' <SeqTp>' . $format . '</SeqTp>' . $CrLf;
2531  $XML_SEPA_INFO .= ' </PmtTpInf>' . $CrLf;
2532  }
2533  $XML_SEPA_INFO .= ' <ReqdExctnDt>' . dol_print_date($dateTime_ETAD, 'dayrfc') . '</ReqdExctnDt>' . $CrLf;
2534  $XML_SEPA_INFO .= ' <Dbtr>' . $CrLf;
2535  $XML_SEPA_INFO .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf;
2536  $XML_SEPA_INFO .= ' <PstlAdr>' . $CrLf;
2537  $XML_SEPA_INFO .= ' <Ctry>' . $country[1] . '</Ctry>' . $CrLf;
2538  $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(chr(13) => ", ", chr(10) => ""));
2539  $addressline2 = strtr($configuration->global->MAIN_INFO_SOCIETE_ZIP . (($configuration->global->MAIN_INFO_SOCIETE_ZIP || ' ' . $configuration->global->MAIN_INFO_SOCIETE_TOWN) ? ' ' : '') . $configuration->global->MAIN_INFO_SOCIETE_TOWN, array(chr(13) => ", ", chr(10) => ""));
2540  if ($addressline1) {
2541  $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2542  }
2543  if ($addressline2) {
2544  $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2545  }
2546  $XML_SEPA_INFO .= ' </PstlAdr>' . $CrLf;
2547  $XML_SEPA_INFO .= ' </Dbtr>' . $CrLf;
2548  $XML_SEPA_INFO .= ' <DbtrAcct>' . $CrLf;
2549  $XML_SEPA_INFO .= ' <Id>' . $CrLf;
2550  $XML_SEPA_INFO .= ' <IBAN>' . preg_replace('/\s/', '', $this->emetteur_iban) . '</IBAN>' . $CrLf;
2551  $XML_SEPA_INFO .= ' </Id>' . $CrLf;
2552  $XML_SEPA_INFO .= ' </DbtrAcct>' . $CrLf;
2553  $XML_SEPA_INFO .= ' <DbtrAgt>' . $CrLf;
2554  $XML_SEPA_INFO .= ' <FinInstnId>' . $CrLf;
2555  $XML_SEPA_INFO .= ' <BIC>' . $this->emetteur_bic . '</BIC>' . $CrLf;
2556  $XML_SEPA_INFO .= ' </FinInstnId>' . $CrLf;
2557  $XML_SEPA_INFO .= ' </DbtrAgt>' . $CrLf;
2558  /* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf;
2559  $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2560  $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2561  $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2562  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ADDRESS), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2563  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ZIP.' '.$conf->global->MAIN_INFO_SOCIETE_TOWN), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2564  $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2565  $XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/
2566  $XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>' . $CrLf; // Field "Responsible of fees". Must be SLEV
2567  /*$XML_SEPA_INFO .= ' <CdtrSchmeId>'.$CrLf;
2568  $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2569  $XML_SEPA_INFO .= ' <PrvtId>'.$CrLf;
2570  $XML_SEPA_INFO .= ' <Othr>'.$CrLf;
2571  $XML_SEPA_INFO .= ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf;
2572  $XML_SEPA_INFO .= ' <SchmeNm>'.$CrLf;
2573  $XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>'.$CrLf;
2574  $XML_SEPA_INFO .= ' </SchmeNm>'.$CrLf;
2575  $XML_SEPA_INFO .= ' </Othr>'.$CrLf;
2576  $XML_SEPA_INFO .= ' </PrvtId>'.$CrLf;
2577  $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2578  $XML_SEPA_INFO .= ' </CdtrSchmeId>'.$CrLf;*/
2579  }
2580  } else {
2581  fwrite($this->file, 'INCORRECT EMETTEUR ' . $this->raison_sociale . $CrLf);
2582  $XML_SEPA_INFO = '';
2583  }
2584  return $XML_SEPA_INFO;
2585  }
2586 
2587  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2594  public function EnregTotal($total)
2595  {
2596  // phpcs:enable
2597  fwrite($this->file, "08");
2598  fwrite($this->file, "08"); // Prelevement ordinaire
2599 
2600  fwrite($this->file, " "); // Zone Reservee B2
2601 
2602  fwrite($this->file, $this->emetteur_ics); // ICS
2603 
2604  // Reserve C1
2605 
2606  fwrite($this->file, substr(" ", 0, 12));
2607 
2608 
2609  // Raison Sociale C2
2610 
2611  fwrite($this->file, substr(" ", 0, 24));
2612 
2613  // D1
2614 
2615  fwrite($this->file, substr(" ", 0, 24));
2616 
2617  // Zone Reservee D2
2618 
2619  fwrite($this->file, substr(" ", 0, 8));
2620 
2621  // Code Guichet D3
2622 
2623  fwrite($this->file, substr(" ", 0, 5));
2624 
2625  // Numero de compte D4
2626 
2627  fwrite($this->file, substr(" ", 0, 11));
2628 
2629  // Zone E Montant
2630 
2631  $montant = ($total * 100);
2632 
2633  fwrite($this->file, substr("000000000000000" . $montant, -16));
2634 
2635  // Zone Reservee F
2636 
2637  fwrite($this->file, substr(" ", 0, 31));
2638 
2639  // Code etablissement
2640 
2641  fwrite($this->file, substr(" ", 0, 5));
2642 
2643  // Zone Reservee F
2644 
2645  fwrite($this->file, substr(" ", 0, 5));
2646 
2647  fwrite($this->file, "\n");
2648  }
2649 
2656  public function getLibStatut($mode = 0)
2657  {
2658  return $this->LibStatut($this->statut, $mode);
2659  }
2660 
2661  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2669  public function LibStatut($status, $mode = 0)
2670  {
2671  // phpcs:enable
2672  if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
2673  global $langs;
2674  //$langs->load("mymodule");
2675  $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2676  $this->labelStatus[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2677  $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2678  $this->labelStatusShort[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2679  if ($this->type == 'bank-transfer') {
2680  $this->labelStatus[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2681  $this->labelStatusShort[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2682  } else {
2683  $this->labelStatus[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2684  $this->labelStatusShort[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2685  }
2686  }
2687 
2688  $statusType = 'status1';
2689  if ($status == self::STATUS_TRANSFERED) {
2690  $statusType = 'status3';
2691  }
2692  if ($status == self::STATUS_CREDITED || $status == self::STATUS_DEBITED) {
2693  $statusType = 'status6';
2694  }
2695 
2696  return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
2697  }
2698 
2699  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2707  public function load_board($user, $mode)
2708  {
2709  // phpcs:enable
2710  if ($user->socid) {
2711  return -1; // protection pour eviter appel par utilisateur externe
2712  }
2713 
2714  /*
2715  if ($mode == 'direct_debit') {
2716  $sql = "SELECT b.rowid, f.datedue as datefin";
2717  $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
2718  $sql .= " WHERE f.entity IN (".getEntity('facture').")";
2719  $sql .= " AND f.total_ttc > 0";
2720  } else {
2721  $sql = "SELECT b.rowid, f.datedue as datefin";
2722  $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
2723  $sql .= " WHERE f.entity IN (".getEntity('facture_fourn').")";
2724  $sql .= " AND f.total_ttc > 0";
2725  }
2726 
2727  $resql = $this->db->query($sql);
2728  if ($resql) {
2729  $langs->load("banks");
2730  $now = dol_now();
2731 
2732  $response = new WorkboardResponse();
2733  if ($mode == 'direct_debit') {
2734  $response->warning_delay = $conf->prelevement->warning_delay / 60 / 60 / 24;
2735  $response->label = $langs->trans("PendingDirectDebitToComplete");
2736  $response->labelShort = $langs->trans("PendingDirectDebitToCompleteShort");
2737  $response->url = DOL_URL_ROOT.'/compta/prelevement/index.php?leftmenu=checks&mainmenu=bank';
2738  } else {
2739  $response->warning_delay = $conf->paymentbybanktransfer->warning_delay / 60 / 60 / 24;
2740  $response->label = $langs->trans("PendingCreditTransferToComplete");
2741  $response->labelShort = $langs->trans("PendingCreditTransferToCompleteShort");
2742  $response->url = DOL_URL_ROOT.'/compta/paymentbybanktransfer/index.php?leftmenu=checks&mainmenu=bank';
2743  }
2744  $response->img = img_object('', "payment");
2745 
2746  while ($obj = $this->db->fetch_object($resql)) {
2747  $response->nbtodo++;
2748 
2749  if ($this->db->jdate($obj->datefin) < ($now - $conf->withdraw->warning_delay)) {
2750  $response->nbtodolate++;
2751  }
2752  }
2753 
2754  $response->nbtodo = 0;
2755  $response->nbtodolate = 0;
2756  // Return workboard only if quantity is not 0
2757  if ($response->nbtodo) {
2758  return $response;
2759  } else {
2760  return 0;
2761  }
2762  } else {
2763  dol_print_error($this->db);
2764  $this->error = $this->db->error();
2765  return -1;
2766  }
2767  */
2768  return 0;
2769  }
2770 
2778  public function getKanbanView($option = '', $arraydata = null)
2779  {
2780  global $langs;
2781 
2782  $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2783 
2784  $return = '<div class="box-flex-item box-flex-grow-zero">';
2785  $return .= '<div class="info-box info-box-sm">';
2786  $return .= '<span class="info-box-icon bg-infobox-action">';
2787  $return .= img_picto('', $this->picto);
2788  $return .= '</span>';
2789  $return .= '<div class="info-box-content">';
2790  $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . (method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref) . '</span>';
2791  if ($selected >= 0) {
2792  $return .= '<input id="cb' . $this->id . '" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="' . $this->id . '"' . ($selected ? ' checked="checked"' : '') . '>';
2793  }
2794  if (property_exists($this, 'date_echeance')) {
2795  $return .= '<br><span class="opacitymedium">' . $langs->trans("Date") . '</span> : <span class="info-box-label">' . dol_print_date($this->db->jdate($this->date_echeance), 'day') . '</span>';
2796  }
2797  if (property_exists($this, 'total')) {
2798  $return .= '<br><span class="opacitymedium">' . $langs->trans("Amount") . '</span> : <span class="amount">' . price($this->total) . '</span>';
2799  }
2800  if (method_exists($this, 'LibStatut')) {
2801  $return .= '<br><div class="info-box-status">' . $this->getLibStatut(3) . '</div>';
2802  }
2803  $return .= '</div>';
2804  $return .= '</div>';
2805  $return .= '</div>';
2806  return $return;
2807  }
2808 
2815  {
2816  if (!empty($this->id)) {
2817  $id = $this->id;
2818  } else {
2819  return 0;
2820  }
2821  if ($id) {
2822  $sql = "SELECT COUNT(*) AS nb FROM " . MAIN_DB_PREFIX . "prelevement_lignes";
2823  $sql .= " WHERE fk_prelevement_bons = " . ((int) $id);
2824  $sql .= " AND fk_soc = 0"; // fk_soc can't be NULL
2825  $sql .= " AND fk_user IS NOT NULL";
2826 
2827  $num = 0;
2828  $resql = $this->db->query($sql);
2829  if ($resql) {
2830  $obj = $this->db->fetch_object($resql);
2831  $num = $obj->nb;
2832  }
2833  if ($num > 0) {
2834  return 1;
2835  }
2836  } else {
2837  dol_print_error($this->db);
2838  }
2839 
2840  return 0;
2841  }
2842 }
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition: security.php:607
checkSwiftForAccount(Account $account=null, $swift=null)
Check SWIFT information for a bank account.
Definition: bank.lib.php:284
checkIbanForAccount(Account $account=null, $ibantocheck=null)
Check IBAN number information for a bank account.
Definition: bank.lib.php:305
$object ref
Definition: info.php:79
Class to manage bank accounts.
Class to manage withdrawal receipts.
load_board($user, $mode)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
SommeAPrelever($mode='direct-debit', $type='')
Returns amount waiting for direct debit payment or credit transfer payment.
static buildRumNumber($row_code_client, $row_datec, $row_drum)
Generate dynamically a RUM number for a customer bank account.
EnregEmetteur($type='direct-debit')
Write sender of request (me).
checkIfSalaryBonPrelevement()
Check if is bon prelevement for salary invoice.
EnregTotal($total)
Write end.
NbFactureAPrelever($type='direct-debit', $forsalary=0)
Get number of invoices to pay.
generate($format='ALL', $executiondate=0, $type='direct-debit', $fk_bank_account=0, $forsalary=0)
Generate a direct debit or credit transfer file.
fetch($rowid, $ref='')
Get object and lines from database.
getListInvoices($amounts=0, $type='')
Get invoice or salary list (with amount or not)
deleteNotificationById($rowid)
Delete a notification def by id.
AddFacture($invoice_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $type='debit-order', $sourcetype='')
Add invoice to withdrawal.
__construct($db)
Constructor.
EnregDestinataire($rowid, $client_nom, $rib_banque, $rib_guichet, $rib_number, $amount, $ref, $facid, $rib_dom='', $type='direct-debit')
Write recipient of request (customer)
getKanbanView($option='', $arraydata=null)
Return clicable link of object (with eventually picto)
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Returns clickable name (with picto)
LibStatut($status, $mode=0)
Return status label for a status.
update(User $user, $notrigger=0)
Update object into database.
set_infotrans($user, $date, $method)
Set withdrawal to transmitted status.
getErrorString($error)
Return error string.
EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf='\n', $format='FRST', $type='direct-debit', $fk_bank_account=0)
Write sender of request (me).
set_infocredit($user, $date, $type='')
Set direct debit or credit transfer order to "paid" status.
addline(&$line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $sourcetype='')
Add line to withdrawal.
getLibStatut($mode=0)
Return status label of object.
EnregDestinataireSEPA($row_code_client, $row_nom, $row_address, $row_zip, $row_town, $row_country_code, $row_cb, $row_cg, $row_cc, $row_somme, $row_ref, $row_idfac, $row_iban, $row_bic, $row_datec, $row_drum, $row_rum, $type='direct-debit', $row_comment='')
Write recipient (thirdparty concerned by request)
addNotification($db, $user, $action)
Add a notification.
nbOfInvoiceToPay($mode='direct-debit', $type='')
Get number of invoices waiting for payment.
create($banque=0, $agence=0, $mode='real', $format='ALL', $executiondate='', $notrigger=0, $type='direct-debit', $did=0, $fk_bank_account=0, $sourcetype='invoice')
Create a BAN payment order:
deleteNotification($user, $action)
Delete a notification.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
updateCommon(User $user, $notrigger=0)
Update object into database.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Class to manage suppliers invoices.
Class to manage invoices.
const STATUS_VALIDATED
Validated (need to be paid)
Class to manage payments for supplier invoices.
Class to manage payments of customer invoices.
Class to manage payments of salaries.
Class to manage salary payments.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage Dolibarr users.
Definition: user.class.php:50
if(isModEnabled('invoice') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&!getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') && $user->hasRight('tax', 'charges', 'lire')) if(isModEnabled('invoice') &&isModEnabled('order') && $user->hasRight("commande", "lire") &&!getDolGlobalString('WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER')) $sql
Social contributions to pay.
Definition: index.php:745
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_string_nospecial($str, $newstr='_', $badcharstoreplace='', $badcharstoremove='', $keepspaces=0)
Clean a string from all punctuation characters to use it as a ref or login.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dolChmod($filepath, $newmask='')
Change mod of a file.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_string_unaccent($str)
Clean a string from all accent characters to be used as ref, login or by dol_sanitizeFileName.
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
td amount
Definition: global.inc.php:554
div float
Buy price without taxes.
Definition: style.css.php:960
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:123