dolibarr  19.0.0-dev
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  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <https://www.gnu.org/licenses/>.
22  */
23 
30 require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
31 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
32 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
33 require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
35 require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
36 require_once DOL_DOCUMENT_ROOT.'/fourn/class/paiementfourn.class.php';
37 
38 
39 
44 {
48  public $element = 'widthdraw';
49 
53  public $table_element = 'prelevement_bons';
54 
58  public $picto = 'payment';
59 
60  public $date_echeance;
61  public $raison_sociale;
62  public $reference_remise;
63  public $emetteur_code_guichet;
64  public $emetteur_numero_compte;
65  public $emetteur_code_banque;
66  public $emetteur_number_key;
67  public $sepa_xml_pti_in_ctti;
68 
69  public $emetteur_iban;
70  public $emetteur_bic;
71  public $emetteur_ics;
72 
73  public $user_trans;
74  public $user_credit;
75 
76  public $total;
77  public $fetched;
78  public $labelStatus = array();
79 
80  public $factures = array();
81 
82  public $invoice_in_error = array();
83  public $thirdparty_in_error = array();
84 
88  public $file;
89 
90 
91  const STATUS_DRAFT = 0;
92  const STATUS_TRANSFERED = 1;
93  const STATUS_CREDITED = 2; // STATUS_CREDITED and STATUS_DEBITED is same. Difference is in ->type
94  const STATUS_DEBITED = 2; // STATUS_CREDITED and STATUS_DEBITED is same. Difference is in ->type
95 
96 
136  // BEGIN MODULEBUILDER PROPERTIES
140  public $fields=array(
141  'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>10, 'notnull'=>1, 'visible'=>0,),
142  'ref' => array('type'=>'varchar(12)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>15, 'notnull'=>0, 'visible'=>-1, 'csslist'=>'tdoverflowmax150', 'showoncombobox'=>'1',),
143  'datec' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>25, 'notnull'=>0, 'visible'=>-1,),
144  'amount' => array('type'=>'double(24,8)', 'label'=>'Amount', 'enabled'=>'1', 'position'=>30, 'notnull'=>0, 'visible'=>-1,),
145  'statut' => array('type'=>'smallint(6)', 'label'=>'Statut', 'enabled'=>'1', 'position'=>500, 'notnull'=>0, 'visible'=>-1, 'arrayofkeyval'=>array(0=>'Wait', 1=>'Transfered', 2=>'Credited')),
146  'credite' => array('type'=>'smallint(6)', 'label'=>'Credite', 'enabled'=>'1', 'position'=>40, 'notnull'=>0, 'visible'=>-1,),
147  'note' => array('type'=>'text', 'label'=>'Note', 'enabled'=>'1', 'position'=>45, 'notnull'=>0, 'visible'=>-1,),
148  'date_trans' => array('type'=>'datetime', 'label'=>'Datetrans', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>-1,),
149  'method_trans' => array('type'=>'smallint(6)', 'label'=>'Methodtrans', 'enabled'=>'1', 'position'=>55, 'notnull'=>0, 'visible'=>-1,),
150  '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',),
151  'date_credit' => array('type'=>'datetime', 'label'=>'Datecredit', 'enabled'=>'1', 'position'=>65, 'notnull'=>0, 'visible'=>-1,),
152  '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',),
153  'type' => array('type'=>'varchar(16)', 'label'=>'Type', 'enabled'=>'1', 'position'=>75, 'notnull'=>0, 'visible'=>-1,),
154  'fk_bank_account' => array('type'=>'integer', 'label'=>'Fkbankaccount', 'enabled'=>'1', 'position'=>80, 'notnull'=>0, 'visible'=>-1, 'css'=>'maxwidth500 widthcentpercentminusxx',),
155  );
156  public $rowid;
157  public $ref;
158  public $datec;
159  public $amount;
160  public $statut;
161  public $credite;
162  public $note;
163  public $date_trans;
164  public $method_trans;
165  public $fk_user_trans;
166  public $date_credit;
167  public $fk_user_credit;
168  public $type;
169  public $fk_bank_account;
170  // END MODULEBUILDER PROPERTIES
171 
172 
173 
179  public function __construct($db)
180  {
181  global $conf, $langs;
182 
183  $this->db = $db;
184 
185  $this->filename = '';
186 
187  $this->date_echeance = dol_now();
188  $this->raison_sociale = "";
189  $this->reference_remise = "";
190 
191  $this->emetteur_code_guichet = "";
192  $this->emetteur_numero_compte = "";
193  $this->emetteur_code_banque = "";
194  $this->emetteur_number_key = "";
195  $this->sepa_xml_pti_in_ctti = false;
196 
197  $this->emetteur_iban = "";
198  $this->emetteur_bic = "";
199  $this->emetteur_ics = "";
200 
201  $this->factures = array();
202 
203  $this->methodes_trans = array(0 => 'Internet', 2 => 'Email', 3 => 'Api');
204 
205  $this->fetched = 0;
206  }
207 
208  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
223  public function AddFacture($invoice_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $type = 'debit-order')
224  {
225  // phpcs:enable
226  $result = 0;
227  $line_id = 0;
228 
229  // Add lines
230  $result = $this->addline($line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key);
231 
232  if ($result == 0) {
233  if ($line_id > 0) {
234  $sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement (";
235  if ($type != 'bank-transfer') {
236  $sql .= "fk_facture";
237  } else {
238  $sql .= "fk_facture_fourn";
239  }
240  $sql .= ",fk_prelevement_lignes";
241  $sql .= ") VALUES (";
242  $sql .= ((int) $invoice_id);
243  $sql .= ", ".((int) $line_id);
244  $sql .= ")";
245 
246  if ($this->db->query($sql)) {
247  $result = 0;
248  } else {
249  $result = -1;
250  $this->errors[] = get_class($this)."::AddFacture ".$this->db->lasterror;
251  dol_syslog(get_class($this)."::AddFacture Error $result");
252  }
253  } else {
254  $result = -2;
255  $this->errors[] = get_class($this)."::AddFacture linedid Empty";
256  dol_syslog(get_class($this)."::AddFacture Error $result");
257  }
258  } else {
259  $result = -3;
260  dol_syslog(get_class($this)."::AddFacture Error $result");
261  }
262 
263  return $result;
264  }
265 
279  public function addline(&$line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key)
280  {
281  $result = -1;
282  $concat = 0;
283 
284  if ($concat == 1) {
285  /*
286  * We aggregate the lines
287  */
288  $sql = "SELECT rowid";
289  $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_lignes";
290  $sql .= " WHERE fk_prelevement_bons = ".((int) $this->id);
291  $sql .= " AND fk_soc =".((int) $client_id);
292  $sql .= " AND code_banque = '".$this->db->escape($code_banque)."'";
293  $sql .= " AND code_guichet = '".$this->db->escape($code_guichet)."'";
294  $sql .= " AND number = '".$this->db->escape($number)."'";
295 
296  $resql = $this->db->query($sql);
297  if ($resql) {
298  $num = $this->db->num_rows($resql);
299  } else {
300  $result = -1;
301  }
302  } else {
303  /*
304  * No aggregate
305  */
306  $sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement_lignes (";
307  $sql .= "fk_prelevement_bons";
308  $sql .= ", fk_soc";
309  $sql .= ", client_nom";
310  $sql .= ", amount";
311  $sql .= ", code_banque";
312  $sql .= ", code_guichet";
313  $sql .= ", number";
314  $sql .= ", cle_rib";
315  $sql .= ") VALUES (";
316  $sql .= $this->id;
317  $sql .= ", ".((int) $client_id);
318  $sql .= ", '".$this->db->escape($client_nom)."'";
319  $sql .= ", ".((float) price2num($amount));
320  $sql .= ", '".$this->db->escape($code_banque)."'";
321  $sql .= ", '".$this->db->escape($code_guichet)."'";
322  $sql .= ", '".$this->db->escape($number)."'";
323  $sql .= ", '".$this->db->escape($number_key)."'";
324  $sql .= ")";
325 
326  if ($this->db->query($sql)) {
327  $line_id = $this->db->last_insert_id(MAIN_DB_PREFIX."prelevement_lignes");
328  $result = 0;
329  } else {
330  $this->errors[] = get_class($this)."::addline Error -2 ".$this->db->lasterror;
331  dol_syslog(get_class($this)."::addline Error -2");
332  $result = -2;
333  }
334  }
335 
336  return $result;
337  }
338 
345  public function getErrorString($error)
346  {
347  global $langs;
348 
349  $errors = array();
350 
351  $errors[1027] = $langs->trans("DateInvalid");
352 
353  return $errors[abs($error)];
354  }
355 
363  public function fetch($rowid, $ref = '')
364  {
365  $sql = "SELECT p.rowid, p.ref, p.amount, p.note";
366  $sql .= ", p.datec as dc";
367  $sql .= ", p.date_trans as date_trans";
368  $sql .= ", p.method_trans, p.fk_user_trans";
369  $sql .= ", p.date_credit as date_credit";
370  $sql .= ", p.fk_user_credit";
371  $sql .= ", p.type";
372  $sql .= ", p.fk_bank_account";
373  $sql .= ", p.statut as status";
374  $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons as p";
375  $sql .= " WHERE p.entity IN (".getEntity('invoice').")";
376  if ($rowid > 0) {
377  $sql .= " AND p.rowid = ".((int) $rowid);
378  } else {
379  $sql .= " AND p.ref = '".$this->db->escape($ref)."'";
380  }
381 
382  dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
383  $result = $this->db->query($sql);
384  if ($result) {
385  if ($this->db->num_rows($result)) {
386  $obj = $this->db->fetch_object($result);
387 
388  $this->id = $obj->rowid;
389  $this->ref = $obj->ref;
390  $this->amount = $obj->amount;
391  $this->note = $obj->note;
392  $this->datec = $this->db->jdate($obj->dc);
393 
394  $this->date_trans = $this->db->jdate($obj->date_trans);
395  $this->method_trans = $obj->method_trans;
396  $this->user_trans = $obj->fk_user_trans;
397 
398  $this->date_credit = $this->db->jdate($obj->date_credit);
399  $this->user_credit = $obj->fk_user_credit;
400 
401  $this->type = $obj->type;
402  $this->fk_bank_account = $obj->fk_bank_account;
403 
404  $this->status = $obj->status;
405  $this->statut = $obj->status; // For backward compatibility
406 
407  $this->fetched = 1;
408 
409  return 1;
410  } else {
411  dol_syslog(get_class($this)."::Fetch Erreur aucune ligne retournee");
412  return -1;
413  }
414  } else {
415  return -2;
416  }
417  }
418 
426  public function update(User $user, $notrigger = false)
427  {
428  return $this->updateCommon($user, $notrigger);
429  }
430 
431  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
440  public function set_infocredit($user, $date)
441  {
442  // phpcs:enable
443  global $conf, $langs;
444 
445  $error = 0;
446 
447  if ($this->fetched == 1) {
448  if ($date < $this->date_trans) {
449  $langs->load("errors");
450  $this->error = $langs->trans('ErrorDateOfMovementLowerThanDateOfFileTransmission');
451  dol_syslog("bon-prelevment::set_infocredit 1027 ".$this->error);
452  return -1027;
453  }
454 
455  $this->db->begin();
456 
457  $sql = " UPDATE ".MAIN_DB_PREFIX."prelevement_bons";
458  $sql .= " SET fk_user_credit = ".$user->id;
459  $sql .= ", statut = ".self::STATUS_CREDITED;
460  $sql .= ", date_credit = '".$this->db->idate($date)."'";
461  $sql .= " WHERE rowid=".((int) $this->id);
462  $sql .= " AND entity = ".((int) $conf->entity);
463  $sql .= " AND statut = ".self::STATUS_TRANSFERED;
464 
465  $resql = $this->db->query($sql);
466  if ($resql) {
467  $langs->load('withdrawals');
468  $subject = $langs->trans("InfoCreditSubject", $this->ref);
469  $message = $langs->trans("InfoCreditMessage", $this->ref, dol_print_date($date, 'dayhour'));
470 
471  // Add payment of withdrawal into bank
472  $fk_bank_account = $this->fk_bank_account;
473  if (empty($fk_bank_account)) {
474  $fk_bank_account = ($this->type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT);
475  }
476 
477  $facs = array();
478  $amounts = array();
479  $amountsperthirdparty = array();
480 
481  $facs = $this->getListInvoices(1);
482 
483  // Loop on each invoice. $facs=array(0=>id, 1=>amount requested)
484  $num = count($facs);
485  for ($i = 0; $i < $num; $i++) {
486  if ($this->type == 'bank-transfer') {
487  $fac = new FactureFournisseur($this->db);
488  } else {
489  $fac = new Facture($this->db);
490  }
491 
492  $result = $fac->fetch($facs[$i][0]);
493 
494  $amounts[$fac->id] = $facs[$i][1];
495  $amountsperthirdparty[$fac->socid][$fac->id] = $facs[$i][1];
496 
497  $totalpaid = $fac->getSommePaiement();
498  $totalcreditnotes = $fac->getSumCreditNotesUsed();
499  $totaldeposits = $fac->getSumDepositsUsed();
500  $alreadypayed = $totalpaid + $totalcreditnotes + $totaldeposits;
501 
502  // @TODO Move this after creation of payment
503  if (price2num($alreadypayed + $facs[$i][1], 'MT') == $fac->total_ttc) {
504  $result = $fac->setPaid($user);
505  if ($result < 0) {
506  $this->error = $fac->error;
507  $this->errors = $fac->errors;
508  }
509  }
510  }
511  //var_dump($amountsperthirdparty);exit;
512 
513  // Make one payment per customer
514  foreach ($amountsperthirdparty as $thirdpartyid => $cursoramounts) {
515  if ($this->type == 'bank-transfer') {
516  $paiement = new PaiementFourn($this->db);
517  } else {
518  $paiement = new Paiement($this->db);
519  }
520  $paiement->datepaye = $date;
521  $paiement->amounts = $cursoramounts; // Array with detail of dispatching of payments for each invoice
522 
523  if ($this->type == 'bank-transfer') {
524  $paiement->paiementid = 2;
525  $paiement->paiementcode = 'VIR';
526  } else {
527  $paiement->paiementid = 3;
528  $paiement->paiementcode = 'PRE';
529  }
530 
531  $paiement->num_payment = $this->ref; // Set ref of direct debit note
532  $paiement->id_prelevement = $this->id;
533 
534  $paiement_id = $paiement->create($user); // This use ->paiementid, that is ID of payment mode
535  if ($paiement_id < 0) {
536  $error++;
537  $this->error = $paiement->error;
538  $this->errors = $paiement->errors;
539  dol_syslog(get_class($this)."::set_infocredit AddPayment Error ".$this->error);
540  } else {
541  if ($this->type == 'bank-transfer') {
542  $modeforaddpayment = 'payment_supplier';
543  $labelforaddpayment = '(BankTransferPayment)';
544  } else {
545  $modeforaddpayment = 'payment';
546  $labelforaddpayment = '(WithdrawalPayment)';
547  }
548 
549  $result = $paiement->addPaymentToBank($user, $modeforaddpayment, $labelforaddpayment, $fk_bank_account, '', '');
550  if ($result < 0) {
551  $error++;
552  $this->error = $paiement->error;
553  $this->errors = $paiement->errors;
554  dol_syslog(get_class($this)."::set_infocredit AddPaymentToBank Error ".$this->error);
555  }
556  }
557  }
558 
559  // Update withdrawal line
560  // TODO: Translate to ligneprelevement.class.php
561  if (!$error) {
562  $sql = " UPDATE ".MAIN_DB_PREFIX."prelevement_lignes";
563  $sql .= " SET statut = 2";
564  $sql .= " WHERE fk_prelevement_bons = ".((int) $this->id);
565 
566  if (!$this->db->query($sql)) {
567  dol_syslog(get_class($this)."::set_infocredit Update lines Error");
568  $error++;
569  }
570  }
571  } else {
572  $this->error = $this->db->lasterror();
573  dol_syslog(get_class($this)."::set_infocredit Update Bons Error");
574  $error++;
575  }
576 
577  /*
578  * End of procedure
579  */
580  if ($error == 0) {
581  $this->date_credit = $date;
582  $this->statut = self::STATUS_CREDITED;
583 
584  $this->db->commit();
585  return 0;
586  } else {
587  $this->db->rollback();
588  return -1;
589  }
590  } else {
591  return -1026;
592  }
593  }
594 
595  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
604  public function set_infotrans($user, $date, $method)
605  {
606  // phpcs:enable
607  global $conf, $langs;
608 
609  $error = 0;
610 
611  dol_syslog(get_class($this)."::set_infotrans Start", LOG_INFO);
612  if ($this->db->begin()) {
613  $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_bons ";
614  $sql .= " SET fk_user_trans = ".$user->id;
615  $sql .= " , date_trans = '".$this->db->idate($date)."'";
616  $sql .= " , method_trans = ".((int) $method);
617  $sql .= " , statut = ".self::STATUS_TRANSFERED;
618  $sql .= " WHERE rowid = ".((int) $this->id);
619  $sql .= " AND entity = ".((int) $conf->entity);
620  $sql .= " AND statut = 0";
621 
622  if ($this->db->query($sql)) {
623  $this->method_trans = $method;
624  $langs->load('withdrawals');
625  $subject = $langs->trans("InfoTransSubject", $this->ref);
626  $message = $langs->trans("InfoTransMessage", $this->ref, dolGetFirstLastname($user->firstname, $user->lastname));
627  $message .= $langs->trans("InfoTransData", price($this->amount), $this->methodes_trans[$this->method_trans], dol_print_date($date, 'day'));
628 
629  // TODO Call trigger to create a notification using notification module
630  } else {
631  $error++;
632  }
633 
634  if ($error == 0) {
635  $this->date_trans = $date;
636  $this->statut = 1;
637  $this->user_trans = $user->id;
638  $this->db->commit();
639 
640  return 0;
641  } else {
642  $this->db->rollback();
643  dol_syslog(get_class($this)."::set_infotrans ROLLBACK", LOG_ERR);
644 
645  return -1;
646  }
647  } else {
648  dol_syslog(get_class($this)."::set_infotrans Ouverture transaction SQL impossible", LOG_CRIT);
649  return -2;
650  }
651  }
652 
659  private function getListInvoices($amounts = 0)
660  {
661  global $conf;
662 
663  $arr = array();
664 
665  /*
666  * Returns all invoices presented within same order
667  */
668  $sql = "SELECT ";
669  if ($this->type == 'bank-transfer') {
670  $sql .= " pf.fk_facture_fourn";
671  } else {
672  $sql .= " pf.fk_facture";
673  }
674  if ($amounts) {
675  $sql .= ", SUM(pl.amount)";
676  }
677  $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons as p";
678  $sql .= " , ".MAIN_DB_PREFIX."prelevement_lignes as pl";
679  $sql .= " , ".MAIN_DB_PREFIX."prelevement as pf";
680  $sql .= " WHERE pf.fk_prelevement_lignes = pl.rowid";
681  $sql .= " AND pl.fk_prelevement_bons = p.rowid";
682  $sql .= " AND p.rowid = ".((int) $this->id);
683  $sql .= " AND p.entity = ".((int) $conf->entity);
684  if ($amounts) {
685  if ($this->type == 'bank-transfer') {
686  $sql .= " GROUP BY fk_facture_fourn";
687  } else {
688  $sql .= " GROUP BY fk_facture";
689  }
690  }
691 
692  $resql = $this->db->query($sql);
693  if ($resql) {
694  $num = $this->db->num_rows($resql);
695 
696  if ($num) {
697  $i = 0;
698  while ($i < $num) {
699  $row = $this->db->fetch_row($resql);
700  if (!$amounts) {
701  $arr[$i] = $row[0];
702  } else {
703  $arr[$i] = array(
704  $row[0],
705  $row[1]
706  );
707  }
708  $i++;
709  }
710  }
711  $this->db->free($resql);
712  } else {
713  dol_syslog(get_class($this)."::getListInvoices Erreur");
714  }
715 
716  return $arr;
717  }
718 
719  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
726  public function SommeAPrelever($mode = 'direct-debit')
727  {
728  // phpcs:enable
729  global $conf;
730 
731  $sql = "SELECT sum(pfd.amount) as nb";
732  if ($mode != 'bank-transfer') {
733  $sql .= " FROM ".MAIN_DB_PREFIX."facture as f,";
734  } else {
735  $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f,";
736  }
737  $sql .= " ".MAIN_DB_PREFIX."prelevement_demande as pfd";
738  $sql .= " WHERE f.entity IN (".getEntity('invoice').")";
739  if (empty($conf->global->WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS)) {
740  $sql .= " AND f.fk_statut = ".Facture::STATUS_VALIDATED;
741  }
742  if ($mode != 'bank-transfer') {
743  $sql .= " AND f.rowid = pfd.fk_facture";
744  } else {
745  $sql .= " AND f.rowid = pfd.fk_facture_fourn";
746  }
747  $sql .= " AND f.paye = 0";
748  $sql .= " AND pfd.traite = 0";
749  $sql .= " AND pfd.ext_payment_id IS NULL";
750  $sql .= " AND f.total_ttc > 0";
751 
752  $resql = $this->db->query($sql);
753  if ($resql) {
754  $obj = $this->db->fetch_object($resql);
755 
756  $this->db->free($resql);
757 
758  return $obj->nb;
759  } else {
760  $error = 1;
761  dol_syslog(get_class($this)."::SommeAPrelever Erreur -1");
762  dol_syslog($this->db->error());
763 
764  return -1;
765  }
766  }
767 
774  public function nbOfInvoiceToPay($mode = 'direct-debit')
775  {
776  return $this->NbFactureAPrelever($mode);
777  }
778 
779  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
786  public function NbFactureAPrelever($type = 'direct-debit')
787  {
788  // phpcs:enable
789  global $conf;
790 
791  $sql = "SELECT count(f.rowid) as nb";
792  if ($type == 'bank-transfer') {
793  $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
794  } else {
795  $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
796  }
797  $sql .= ", ".MAIN_DB_PREFIX."prelevement_demande as pfd";
798  $sql .= " WHERE f.entity IN (".getEntity('invoice').")";
799  if (empty($conf->global->WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS)) {
800  $sql .= " AND f.fk_statut = ".Facture::STATUS_VALIDATED;
801  }
802  if ($type == 'bank-transfer') {
803  $sql .= " AND f.rowid = pfd.fk_facture_fourn";
804  } else {
805  $sql .= " AND f.rowid = pfd.fk_facture";
806  }
807  $sql .= " AND pfd.traite = 0";
808  $sql .= " AND pfd.ext_payment_id IS NULL";
809  $sql .= " AND f.total_ttc > 0";
810 
811  dol_syslog(get_class($this)."::NbFactureAPrelever");
812  $resql = $this->db->query($sql);
813 
814  if ($resql) {
815  $obj = $this->db->fetch_object($resql);
816 
817  $this->db->free($resql);
818 
819  return $obj->nb;
820  } else {
821  $this->error = get_class($this)."::NbFactureAPrelever Erreur -1 sql=".$this->db->error();
822  return -1;
823  }
824  }
825 
826 
827  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
847  public function create($banque = 0, $agence = 0, $mode = 'real', $format = 'ALL', $executiondate = '', $notrigger = 0, $type = 'direct-debit', $did = 0, $fk_bank_account = 0)
848  {
849  // phpcs:enable
850  global $conf, $langs, $user;
851 
852  dol_syslog(__METHOD__." Bank=".$banque." Office=".$agence." mode=".$mode." format=".$format, LOG_DEBUG);
853 
854  require_once DOL_DOCUMENT_ROOT."/compta/facture/class/facture.class.php";
855  require_once DOL_DOCUMENT_ROOT."/societe/class/societe.class.php";
856 
857  // Check params
858  if ($type != 'bank-transfer') {
859  if (empty($format)) {
860  $this->error = 'ErrorBadParametersForDirectDebitFileCreate';
861  return -1;
862  }
863  }
864 
865  // Clean params
866  if (empty($fk_bank_account)) {
867  $fk_bank_account = ($type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT);
868  }
869 
870  $error = 0;
871 
872  $datetimeprev = dol_now('gmt');
873  // Choice the date of the execution direct debit
874  if (!empty($executiondate)) {
875  $datetimeprev = $executiondate;
876  }
877 
878  $month = dol_print_date($datetimeprev, "%m", 'gmt');
879  $year = dol_print_date($datetimeprev, "%Y", 'gmt');
880 
881  $this->invoice_in_error = array();
882  $this->thirdparty_in_error = array();
883 
884  // Read invoices
885  $factures = array();
886  $factures_prev = array();
887  $factures_result = array();
888  $factures_prev_id = array();
889  $factures_errors = array();
890 
891  if (!$error) {
892  $sql = "SELECT f.rowid, pfd.rowid as pfdrowid, f.fk_soc";
893  $sql .= ", pfd.code_banque, pfd.code_guichet, pfd.number, pfd.cle_rib";
894  $sql .= ", pfd.amount";
895  $sql .= ", s.nom as name";
896  if ($type != 'bank-transfer') {
897  $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
898  } else {
899  $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
900  }
901  $sql .= ", ".MAIN_DB_PREFIX."societe as s";
902  $sql .= ", ".MAIN_DB_PREFIX."prelevement_demande as pfd";
903  $sql .= " WHERE f.entity IN (".getEntity('invoice').')';
904  if ($type != 'bank-transfer') {
905  $sql .= " AND f.rowid = pfd.fk_facture";
906  } else {
907  $sql .= " AND f.rowid = pfd.fk_facture_fourn";
908  }
909  $sql .= " AND s.rowid = f.fk_soc";
910  $sql .= " AND f.fk_statut = 1"; // Invoice validated
911  $sql .= " AND f.paye = 0";
912  $sql .= " AND pfd.traite = 0";
913  $sql .= " AND f.total_ttc > 0";
914  $sql .= " AND pfd.ext_payment_id IS NULL";
915  if ($did > 0) {
916  $sql .= " AND pfd.rowid = ".((int) $did);
917  }
918  dol_syslog(__METHOD__." Read invoices,", LOG_DEBUG);
919 
920  $resql = $this->db->query($sql);
921  if ($resql) {
922  $num = $this->db->num_rows($resql);
923  $i = 0;
924 
925  while ($i < $num) {
926  $row = $this->db->fetch_row($resql);
927  $factures[$i] = $row; // All fields
928  if ($row[7] == 0) {
929  $error++;
930  dol_syslog(__METHOD__." Read invoices error Found a null invoice", LOG_ERR);
931  $this->invoice_in_error[$row[0]] = "Error for invoice id ".$row[0].", found a null amount";
932  break;
933  }
934  $i++;
935  }
936  $this->db->free($resql);
937  dol_syslog(__METHOD__." Read invoices, ".$i." invoices to withdraw", LOG_DEBUG);
938  } else {
939  $error++;
940  dol_syslog(__METHOD__." Read invoices error ".$this->db->error(), LOG_ERR);
941  }
942  }
943 
944  if (!$error) {
945  require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php';
946  $soc = new Societe($this->db);
947 
948  // Check BAN
949  $i = 0;
950  dol_syslog(__METHOD__." Check BAN", LOG_DEBUG);
951 
952  if (count($factures) > 0) {
953  foreach ($factures as $key => $fac) {
954  if ($type != 'bank-transfer') {
955  $tmpinvoice = new Facture($this->db);
956  } else {
957  $tmpinvoice = new FactureFournisseur($this->db);
958  }
959  $resfetch = $tmpinvoice->fetch($fac[0]);
960  if ($resfetch >= 0) { // Field 0 of $fac is rowid of invoice
961  if ($soc->fetch($tmpinvoice->socid) >= 0) {
962  $bac = new CompanyBankAccount($this->db);
963  $bac->fetch(0, $soc->id);
964 
965  if ($type != 'bank-transfer') {
966  if ($format == 'FRST' && $bac->frstrecur != 'FRST') {
967  continue;
968  }
969  if ($format == 'RCUR' && $bac->frstrecur != 'RCUR') {
970  continue;
971  }
972  }
973 
974  if ($bac->verif() >= 1) {
975  $factures_prev[$i] = $fac;
976  /* second array necessary for BonPrelevement */
977  $factures_prev_id[$i] = $fac[0];
978  $i++;
979  //dol_syslog(__METHOD__."::RIB is ok", LOG_DEBUG);
980  } else {
981  dol_syslog(__METHOD__." Check BAN Error on default bank number IBAN/BIC for thirdparty reported by verif() ".$tmpinvoice->socid." ".$soc->name, LOG_WARNING);
982  $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice ".$tmpinvoice->getNomUrl(0)." for thirdparty ".$soc->getNomUrl(0);
983  $this->thirdparty_in_error[$soc->id] = "Error on default bank number IBAN/BIC for invoice ".$tmpinvoice->getNomUrl(0)." for thirdparty ".$soc->getNomUrl(0);
984  }
985  } else {
986  dol_syslog(__METHOD__." Check BAN Failed to read company", LOG_WARNING);
987  }
988  } else {
989  dol_syslog(__METHOD__." Check BAN Failed to read invoice", LOG_WARNING);
990  }
991  }
992  } else {
993  dol_syslog(__METHOD__." Check BAN No invoice to process", LOG_WARNING);
994  }
995  }
996 
997  $ok = 0;
998 
999  // Withdraw invoices in factures_prev array
1000  $out = count($factures_prev)." invoices will be included.";
1001  //print $out."\n";
1002  dol_syslog($out);
1003 
1004  // Return warning
1005  /*$i=0;
1006  foreach ($this->thirdparty_in_error as $key => $val)
1007  {
1008  if ($i < 10) setEventMessages($val, null, 'warnings');
1009  else setEventMessages('More error were discarded...', null, 'warnings');
1010  $i++;
1011  }*/
1012 
1013  if (count($factures_prev) > 0) {
1014  if ($mode == 'real') {
1015  $ok = 1;
1016  } else {
1017  print $langs->trans("ModeWarning"); // "Option for real mode was not set, we stop after this simulation\n";
1018  }
1019  }
1020 
1021  if ($ok) {
1022  /*
1023  * We are in real mode.
1024  * We create order and build file into disk
1025  */
1026  $this->db->begin();
1027 
1028  $now = dol_now();
1029  $ref = '';
1030 
1031  /*
1032  * Process order generation
1033  */
1034  if (!$error) {
1035  $ref = substr($year, -2).$month;
1036 
1037  // Get next free nuber for the ref of bon
1038  $sql = "SELECT substring(ref from char_length(ref) - 1)"; // To extract "YYMMXX" from "TYYMMXX"
1039  $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons";
1040  $sql .= " WHERE ref LIKE '_".$this->db->escape($ref)."%'";
1041  $sql .= " AND entity = ".((int) $conf->entity);
1042  $sql .= " ORDER BY ref DESC LIMIT 1";
1043 
1044  dol_syslog(get_class($this)." get next free number", LOG_DEBUG);
1045  $resql = $this->db->query($sql);
1046 
1047  if ($resql) {
1048  $row = $this->db->fetch_row($resql);
1049 
1050  // Build the new ref
1051  $ref = "T".$ref.sprintf("%02d", (intval($row[0]) + 1));
1052 
1053  // $conf->abc->dir_output may be:
1054  // /home/ldestailleur/git/dolibarr_15.0/documents/abc/
1055  // or
1056  // /home/ldestailleur/git/dolibarr_15.0/documents/X/abc with X >= 2 with multicompany.
1057  if ($type != 'bank-transfer') {
1058  $dir = $conf->prelevement->dir_output.'/receipts';
1059  } else {
1060  $dir = $conf->paymentbybanktransfer->dir_output.'/receipts';
1061  }
1062  if (!is_dir($dir)) {
1063  dol_mkdir($dir);
1064  }
1065 
1066  if (isModEnabled('multicompany')) {
1067  $labelentity = $conf->entity;
1068  $this->filename = $dir.'/'.$ref.'-'.$labelentity.'.xml';
1069  } else {
1070  $this->filename = $dir.'/'.$ref.'.xml';
1071  }
1072 
1073  // Create withdraw order in database
1074  $sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement_bons (";
1075  $sql .= "ref, entity, datec, type, fk_bank_account";
1076  $sql .= ") VALUES (";
1077  $sql .= "'".$this->db->escape($ref)."'";
1078  $sql .= ", ".((int) $conf->entity);
1079  $sql .= ", '".$this->db->idate($now)."'";
1080  $sql .= ", '".($type == 'bank-transfer' ? 'bank-transfer' : 'debit-order')."'";
1081  $sql .= ", ".((int) $fk_bank_account);
1082  $sql .= ")";
1083 
1084  $resql = $this->db->query($sql);
1085  if ($resql) {
1086  $prev_id = $this->db->last_insert_id(MAIN_DB_PREFIX."prelevement_bons");
1087  $this->id = $prev_id;
1088  $this->ref = $ref;
1089  } else {
1090  $error++;
1091  dol_syslog(__METHOD__." Create withdraw receipt ".$this->db->lasterror(), LOG_ERR);
1092  }
1093  } else {
1094  $error++;
1095  dol_syslog(__METHOD__." Get last withdraw receipt ".$this->db->lasterror(), LOG_ERR);
1096  }
1097  }
1098 
1099  if (!$error) {
1100  if ($type != 'bank-transfer') {
1101  $fact = new Facture($this->db);
1102  } else {
1103  $fact = new FactureFournisseur($this->db);
1104  }
1105 
1106  // Add lines for the bon
1107  if (count($factures_prev) > 0) {
1108  foreach ($factures_prev as $fac) { // Add a link in database for each invoice
1109  // Fetch invoice
1110  $result = $fact->fetch($fac[0]);
1111  if ($result < 0) {
1112  $this->error = 'ERRORBONPRELEVEMENT Failed to load invoice with id '.$fac[0];
1113  break;
1114  }
1115 
1116  /*
1117  * Add standing order. This add record into llx_prelevement_lignes and llx_prelevement
1118  *
1119  * $fac[0] : invoice_id
1120  * $fac[1] : ???
1121  * $fac[2] : third party id
1122  * $fac[3] : banque
1123  * $fac[4] : guichet
1124  * $fac[5] : number
1125  * $fac[6] : cle rib
1126  * $fac[7] : amount
1127  * $fac[8] : client nom
1128  */
1129  $ri = $this->AddFacture($fac[0], $fac[2], $fac[8], $fac[7], $fac[3], $fac[4], $fac[5], $fac[6], $type);
1130  if ($ri <> 0) {
1131  $error++;
1132  }
1133 
1134  // Update invoice requests as done
1135  $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_demande";
1136  $sql .= " SET traite = 1";
1137  $sql .= ", date_traite = '".$this->db->idate($now)."'";
1138  $sql .= ", fk_prelevement_bons = ".((int) $this->id);
1139  $sql .= " WHERE rowid = ".((int) $fac[1]);
1140 
1141  $resql = $this->db->query($sql);
1142  if (!$resql) {
1143  $error++;
1144  $this->errors[] = $this->db->lasterror();
1145  dol_syslog(__METHOD__." Update Error=".$this->db->lasterror(), LOG_ERR);
1146  }
1147  }
1148  }
1149  }
1150 
1151  if (!$error) {
1152  /*
1153  * Create file of type='direct-debit' for direct debit order or type='bank-transfer' for credit transfer into a XML file
1154  */
1155 
1156  dol_syslog(__METHOD__." Init direct debit or credit transfer file for ".count($factures_prev)." invoices", LOG_DEBUG);
1157 
1158  if (count($factures_prev) > 0) {
1159  $this->date_echeance = $datetimeprev;
1160  $this->reference_remise = $ref;
1161 
1162  $account = new Account($this->db);
1163  if ($account->fetch($fk_bank_account) > 0) {
1164  $this->emetteur_code_banque = $account->code_banque;
1165  $this->emetteur_code_guichet = $account->code_guichet;
1166  $this->emetteur_numero_compte = $account->number;
1167  $this->emetteur_number_key = $account->cle_rib;
1168  $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
1169  $this->emetteur_iban = $account->iban;
1170  $this->emetteur_bic = $account->bic;
1171 
1172  $this->emetteur_ics = ($type == 'bank-transfer' ? $account->ics_transfer : $account->ics);
1173 
1174  $this->raison_sociale = $account->proprio;
1175  }
1176 
1177  $this->factures = $factures_prev_id;
1178  $this->context['factures_prev'] = $factures_prev;
1179 
1180  // Generation of direct debit or credit transfer file $this->filename (May be a SEPA file for european countries)
1181  // This also set the property $this->total with amount that is included into file
1182  $result = $this->generate($format, $executiondate, $type);
1183  if ($result < 0) {
1184  //var_dump($this->error);
1185  //var_dump($this->invoice_in_error);
1186  $error++;
1187  }
1188  }
1189  dol_syslog(__METHOD__." Bank order file has been generated under filename ".$this->filename, LOG_DEBUG);
1190  }
1191  //var_dump($this->total);exit;
1192 
1193  /*
1194  * Update total defined after generation of file
1195  */
1196  if (!$error) {
1197  $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_bons";
1198  $sql .= " SET amount = ".price2num($this->total);
1199  $sql .= " WHERE rowid = ".((int) $this->id);
1200  $sql .= " AND entity = ".((int) $conf->entity);
1201 
1202  $resql = $this->db->query($sql);
1203  if (!$resql) {
1204  $error++;
1205  dol_syslog(__METHOD__." Error update total: ".$this->db->error(), LOG_ERR);
1206  }
1207  }
1208 
1209  if (!$error && !$notrigger) {
1210  $triggername = 'DIRECT_DEBIT_ORDER_CREATE';
1211  if ($type != 'bank-transfer') {
1212  $triggername = 'CREDIT_TRANSFER_ORDER_CREATE';
1213  }
1214 
1215  // Call trigger
1216  $result = $this->call_trigger($triggername, $user);
1217  if ($result < 0) {
1218  $error++;
1219  }
1220  // End call triggers
1221  }
1222 
1223  if (!$error) {
1224  $this->db->commit();
1225  return count($factures_prev);
1226  } else {
1227  $this->db->rollback();
1228  return -1;
1229  }
1230  } else {
1231  return 0;
1232  }
1233  }
1234 
1235 
1243  public function delete($user = null, $notrigger = 0)
1244  {
1245  $this->db->begin();
1246 
1247  $error = 0;
1248  $resql1 = $resql2 = $resql3 = $resql4 = 0;
1249 
1250  if (!$notrigger) {
1251  $triggername = 'DIRECT_DEBIT_ORDER_DELETE';
1252  if ($this->type == 'bank-transfer') {
1253  $triggername = 'PAYMENTBYBANKTRANFER_DELETE';
1254  }
1255  // Call trigger
1256  $result = $this->call_trigger($triggername, $user);
1257  if ($result < 0) {
1258  $error++;
1259  }
1260  // End call triggers
1261  }
1262 
1263  if (!$error) {
1264  $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).")";
1265  $resql1 = $this->db->query($sql);
1266  if (!$resql1) {
1267  dol_print_error($this->db);
1268  }
1269  }
1270 
1271  if (!$error) {
1272  $sql = "DELETE FROM ".MAIN_DB_PREFIX."prelevement_lignes WHERE fk_prelevement_bons = ".((int) $this->id);
1273  $resql2 = $this->db->query($sql);
1274  if (!$resql2) {
1275  dol_print_error($this->db);
1276  }
1277  }
1278 
1279  if (!$error) {
1280  $sql = "DELETE FROM ".MAIN_DB_PREFIX."prelevement_bons WHERE rowid = ".((int) $this->id);
1281  $resql3 = $this->db->query($sql);
1282  if (!$resql3) {
1283  dol_print_error($this->db);
1284  }
1285  }
1286 
1287  if (!$error) {
1288  $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_demande SET fk_prelevement_bons = NULL, traite = 0 WHERE fk_prelevement_bons = ".((int) $this->id);
1289  $resql4 = $this->db->query($sql);
1290  if (!$resql4) {
1291  dol_print_error($this->db);
1292  }
1293  }
1294 
1295  if ($resql1 && $resql2 && $resql3 && $resql4 && !$error) {
1296  $this->db->commit();
1297  return 1;
1298  } else {
1299  $this->db->rollback();
1300  return -1;
1301  }
1302  }
1303 
1304 
1315  public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1316  {
1317  global $conf, $langs, $hookmanager;
1318 
1319  if (!empty($conf->dol_no_mouse_hover)) {
1320  $notooltip = 1; // Force disable tooltips
1321  }
1322 
1323  $result = '';
1324 
1325  $labeltoshow = 'PaymentByDirectDebit';
1326  if (!empty($this->type) && $this->type == 'bank-transfer') {
1327  $labeltoshow = 'PaymentByBankTransfer';
1328  }
1329 
1330  $label = img_picto('', $this->picto).' <u>'.$langs->trans($labeltoshow).'</u> '.$this->getLibStatut(5);
1331  $label .= '<br>';
1332  $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
1333  if (isset($this->amount)) {
1334  $label .= '<br><b>'.$langs->trans("Amount").":</b> ".price($this->amount);
1335  }
1336  if (isset($this->date_trans)) {
1337  $label .= '<br><b>'.$langs->trans("TransData").":</b> ".dol_print_date($this->date_trans, 'dayhour', 'tzuserrel');
1338  }
1339  /*if (isset($this->date_credit)) {
1340  $label .= '<br><b>'.$langs->trans("TransData").":</b> ".dol_print_date($this->date_credit, 'dayhour', 'tzuserrel');
1341  }*/
1342 
1343  $url = DOL_URL_ROOT.'/compta/prelevement/card.php?id='.$this->id;
1344  if (!empty($this->type) && $this->type == 'bank-transfer') {
1345  $url = DOL_URL_ROOT.'/compta/prelevement/card.php?id='.$this->id;
1346  }
1347 
1348  if ($option != 'nolink') {
1349  // Add param to save lastsearch_values or not
1350  $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1351  if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1352  $add_save_lastsearch_values = 1;
1353  }
1354  if ($add_save_lastsearch_values) {
1355  $url .= '&save_lastsearch_values=1';
1356  }
1357  }
1358 
1359  $linkclose = '';
1360  if (empty($notooltip)) {
1361  if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
1362  $label = $langs->trans("ShowMyObject");
1363  $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
1364  }
1365  $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
1366  $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
1367  } else {
1368  $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1369  }
1370 
1371  $linkstart = '<a href="'.$url.'"';
1372  $linkstart .= $linkclose.'>';
1373  $linkend = '</a>';
1374 
1375  $result .= $linkstart;
1376  if ($withpicto) {
1377  $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);
1378  }
1379  if ($withpicto != 2) {
1380  $result .= $this->ref;
1381  }
1382  $result .= $linkend;
1383 
1384  global $action, $hookmanager;
1385  $hookmanager->initHooks(array('banktransferdao'));
1386  $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
1387  $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1388  if ($reshook > 0) {
1389  $result = $hookmanager->resPrint;
1390  } else {
1391  $result .= $hookmanager->resPrint;
1392  }
1393 
1394  return $result;
1395  }
1396 
1397 
1404  public function deleteNotificationById($rowid)
1405  {
1406  $sql = "DELETE FROM ".MAIN_DB_PREFIX."notify_def";
1407  $sql .= " WHERE rowid = ".((int) $rowid);
1408 
1409  if ($this->db->query($sql)) {
1410  return 0;
1411  } else {
1412  return -1;
1413  }
1414  }
1415 
1423  public function deleteNotification($user, $action)
1424  {
1425  if (is_object($user)) {
1426  $userid = $user->id;
1427  } else { // If user is an id
1428  $userid = $user;
1429  }
1430 
1431  $sql = "DELETE FROM ".MAIN_DB_PREFIX."notify_def";
1432  $sql .= " WHERE fk_user=".((int) $userid)." AND fk_action='".$this->db->escape($action)."'";
1433 
1434  if ($this->db->query($sql)) {
1435  return 0;
1436  } else {
1437  return -1;
1438  }
1439  }
1440 
1441  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1450  public function addNotification($db, $user, $action)
1451  {
1452  // phpcs:enable
1453  $result = 0;
1454 
1455  if (is_object($user)) {
1456  $userid = $user->id;
1457  } else { // If user is an id
1458  $userid = $user;
1459  }
1460 
1461  if ($this->deleteNotification($user, $action) == 0) {
1462  $now = dol_now();
1463 
1464  $sql = "INSERT INTO ".MAIN_DB_PREFIX."notify_def (datec,fk_user, fk_soc, fk_contact, fk_action)";
1465  $sql .= " VALUES ('".$this->db->idate($now)."', ".((int) $userid).", 'NULL', 'NULL', '".$this->db->escape($action)."')";
1466 
1467  dol_syslog("adnotiff: ".$sql);
1468  if ($this->db->query($sql)) {
1469  $result = 0;
1470  } else {
1471  $result = -1;
1472  dol_syslog(get_class($this)."::addNotification Error $result");
1473  }
1474  }
1475 
1476  return $result;
1477  }
1478 
1479 
1493  public function generate($format = 'ALL', $executiondate = 0, $type = 'direct-debit', $fk_bank_account = 0)
1494  {
1495  global $conf, $langs, $mysoc;
1496 
1497  //TODO: Optimize code to read lines in a single function
1498 
1499  // Clean params
1500  if (empty($fk_bank_account)) {
1501  $fk_bank_account = ($type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT);
1502  }
1503 
1504  $result = 0;
1505 
1506  dol_syslog(get_class($this)."::generate build file=".$this->filename." type=".$type);
1507 
1508  $this->file = fopen($this->filename, "w");
1509  if (empty($this->file)) {
1510  $this->error = $langs->trans('ErrorFailedToOpenFile', $this->filename);
1511  return -1;
1512  }
1513 
1514  $found = 0;
1515  $this->total = 0;
1516 
1517  // Build file for European countries
1518  if ($mysoc->isInEEC()) {
1519  $found++;
1520 
1521  if ($type != 'bank-transfer') {
1525  // SEPA Initialisation
1526  $CrLf = "\n";
1527 
1528  $now = dol_now();
1529 
1530  $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S');
1531 
1532  $date_actu = $now;
1533  if (!empty($executiondate)) {
1534  $date_actu = $executiondate;
1535  }
1536 
1537  $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d');
1538  $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S');
1539  $fileDebiteurSection = '';
1540  $fileEmetteurSection = '';
1541  $i = 0;
1542 
1543  /*
1544  * Section Debitor (sepa Debiteurs bloc lines)
1545  */
1546 
1547  $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
1548  $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1549  $sql .= " f.ref as reffac, pf.fk_facture as idfac,";
1550  $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
1551  $sql .= " FROM";
1552  $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,";
1553  $sql .= " ".MAIN_DB_PREFIX."facture as f,";
1554  $sql .= " ".MAIN_DB_PREFIX."prelevement as pf,";
1555  $sql .= " ".MAIN_DB_PREFIX."societe as soc,";
1556  $sql .= " ".MAIN_DB_PREFIX."c_country as c,";
1557  $sql .= " ".MAIN_DB_PREFIX."societe_rib as rib";
1558  $sql .= " WHERE pl.fk_prelevement_bons = ".((int) $this->id);
1559  $sql .= " AND pl.rowid = pf.fk_prelevement_lignes";
1560  $sql .= " AND pf.fk_facture = f.rowid";
1561  $sql .= " AND f.fk_soc = soc.rowid";
1562  $sql .= " AND soc.fk_pays = c.rowid";
1563  $sql .= " AND rib.fk_soc = f.fk_soc";
1564  $sql .= " AND rib.default_rib = 1";
1565  $sql .= " AND rib.type = 'ban'";
1566 
1567  // Define $fileDebiteurSection. One section DrctDbtTxInf per invoice.
1568  $resql = $this->db->query($sql);
1569  if ($resql) {
1570  $cachearraytotestduplicate = array();
1571 
1572  $num = $this->db->num_rows($resql);
1573  while ($i < $num) {
1574  $obj = $this->db->fetch_object($resql);
1575 
1576  if (!empty($cachearraytotestduplicate[$obj->idfac])) {
1577  $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
1578  $this->invoice_in_error[$obj->idfac] = $this->error;
1579  $result = -2;
1580  break;
1581  }
1582  $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
1583 
1584  $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
1585 
1586  $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);
1587 
1588  $this->total = $this->total + $obj->somme;
1589  $i++;
1590  }
1591  $nbtotalDrctDbtTxInf = $i;
1592  } else {
1593  $this->error = $this->db->lasterror();
1594  fputs($this->file, 'ERROR DEBITOR '.$sql.$CrLf); // DEBITOR = Customers
1595  $result = -2;
1596  }
1597 
1598  // Define $fileEmetteurSection. Start of bloc PmtInf. Will contains all $nbtotalDrctDbtTxInf
1599  if ($result != -2) {
1600  $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type, $fk_bank_account);
1601  }
1602 
1606  // SEPA File Header
1607  fputs($this->file, '<'.'?xml version="1.0" encoding="UTF-8" standalone="yes"?'.'>'.$CrLf);
1608  fputs($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);
1609  fputs($this->file, ' <CstmrDrctDbtInitn>'.$CrLf);
1610  // SEPA Group header
1611  fputs($this->file, ' <GrpHdr>'.$CrLf);
1612  fputs($this->file, ' <MsgId>'.('DD/'.$dateTime_YMD.'/REF'.$this->id).'</MsgId>'.$CrLf);
1613  fputs($this->file, ' <CreDtTm>'.$dateTime_ECMA.'</CreDtTm>'.$CrLf);
1614  fputs($this->file, ' <NbOfTxs>'.$i.'</NbOfTxs>'.$CrLf);
1615  fputs($this->file, ' <CtrlSum>'.$this->total.'</CtrlSum>'.$CrLf);
1616  fputs($this->file, ' <InitgPty>'.$CrLf);
1617  fputs($this->file, ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf);
1618  fputs($this->file, ' <Id>'.$CrLf);
1619  fputs($this->file, ' <PrvtId>'.$CrLf);
1620  fputs($this->file, ' <Othr>'.$CrLf);
1621  fputs($this->file, ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf);
1622  fputs($this->file, ' </Othr>'.$CrLf);
1623  fputs($this->file, ' </PrvtId>'.$CrLf);
1624  fputs($this->file, ' </Id>'.$CrLf);
1625  fputs($this->file, ' </InitgPty>'.$CrLf);
1626  fputs($this->file, ' </GrpHdr>'.$CrLf);
1627  // SEPA File Emetteur
1628  if ($result != -2) {
1629  fputs($this-> file, $fileEmetteurSection);
1630  }
1631  // SEPA File Debiteurs
1632  if ($result != -2) {
1633  fputs($this-> file, $fileDebiteurSection);
1634  }
1635  // SEPA FILE FOOTER
1636  fputs($this->file, ' </PmtInf>'.$CrLf);
1637  fputs($this->file, ' </CstmrDrctDbtInitn>'.$CrLf);
1638  fputs($this->file, '</Document>'.$CrLf);
1639  } else {
1643  // SEPA Initialisation
1644  $CrLf = "\n";
1645 
1646  $now = dol_now();
1647 
1648  $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S');
1649 
1650  $date_actu = $now;
1651  if (!empty($executiondate)) {
1652  $date_actu = $executiondate;
1653  }
1654 
1655  $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d');
1656  $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S');
1657  $fileCrediteurSection = '';
1658  $fileEmetteurSection = '';
1659  $i = 0;
1660 
1661  /*
1662  * Section Creditor (sepa Crediteurs bloc lines)
1663  */
1664 
1665  $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
1666  $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1667  $sql .= " f.ref as reffac, pf.fk_facture_fourn as idfac, f.ref_supplier as fac_ref_supplier,";
1668  $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
1669  $sql .= " FROM";
1670  $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,";
1671  $sql .= " ".MAIN_DB_PREFIX."facture_fourn as f,";
1672  $sql .= " ".MAIN_DB_PREFIX."prelevement as pf,";
1673  $sql .= " ".MAIN_DB_PREFIX."societe as soc,";
1674  $sql .= " ".MAIN_DB_PREFIX."c_country as c,";
1675  $sql .= " ".MAIN_DB_PREFIX."societe_rib as rib";
1676  $sql .= " WHERE pl.fk_prelevement_bons = ".((int) $this->id);
1677  $sql .= " AND pl.rowid = pf.fk_prelevement_lignes";
1678  $sql .= " AND pf.fk_facture_fourn = f.rowid";
1679  $sql .= " AND f.fk_soc = soc.rowid";
1680  $sql .= " AND soc.fk_pays = c.rowid";
1681  $sql .= " AND rib.fk_soc = f.fk_soc";
1682  $sql .= " AND rib.default_rib = 1";
1683  $sql .= " AND rib.type = 'ban'";
1684 
1685  // Define $fileCrediteurSection. One section DrctDbtTxInf per invoice.
1686  $resql = $this->db->query($sql);
1687  if ($resql) {
1688  $cachearraytotestduplicate = array();
1689 
1690  $num = $this->db->num_rows($resql);
1691  while ($i < $num) {
1692  $obj = $this->db->fetch_object($resql);
1693 
1694  if (!empty($cachearraytotestduplicate[$obj->idfac])) {
1695  $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
1696  $this->invoice_in_error[$obj->idfac] = $this->error;
1697  $result = -2;
1698  break;
1699  }
1700  $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
1701 
1702  $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
1703 
1704  $fileCrediteurSection .= $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, $obj->fac_ref_supplier);
1705 
1706  $this->total = $this->total + $obj->somme;
1707  $i++;
1708  }
1709  $nbtotalDrctDbtTxInf = $i;
1710  } else {
1711  $this->error = $this->db->lasterror();
1712  fputs($this->file, 'ERROR CREDITOR '.$sql.$CrLf); // CREDITORS = Suppliers
1713  $result = -2;
1714  }
1715 
1716  // Define $fileEmetteurSection. Start of bloc PmtInf. Will contains all $nbtotalDrctDbtTxInf
1717  if ($result != -2) {
1718  $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type);
1719  }
1720 
1724  // SEPA File Header
1725  fputs($this->file, '<'.'?xml version="1.0" encoding="UTF-8" standalone="yes"?'.'>'.$CrLf);
1726  fputs($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);
1727  fputs($this->file, ' <CstmrCdtTrfInitn>'.$CrLf);
1728  // SEPA Group header
1729  fputs($this->file, ' <GrpHdr>'.$CrLf);
1730  fputs($this->file, ' <MsgId>'.('TRF/'.$dateTime_YMD.'/REF'.$this->id).'</MsgId>'.$CrLf);
1731  fputs($this->file, ' <CreDtTm>'.$dateTime_ECMA.'</CreDtTm>'.$CrLf);
1732  fputs($this->file, ' <NbOfTxs>'.$i.'</NbOfTxs>'.$CrLf);
1733  fputs($this->file, ' <CtrlSum>'.$this->total.'</CtrlSum>'.$CrLf);
1734  fputs($this->file, ' <InitgPty>'.$CrLf);
1735  fputs($this->file, ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf);
1736  fputs($this->file, ' <Id>'.$CrLf);
1737  fputs($this->file, ' <PrvtId>'.$CrLf);
1738  fputs($this->file, ' <Othr>'.$CrLf);
1739  fputs($this->file, ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf);
1740  fputs($this->file, ' </Othr>'.$CrLf);
1741  fputs($this->file, ' </PrvtId>'.$CrLf);
1742  fputs($this->file, ' </Id>'.$CrLf);
1743  fputs($this->file, ' </InitgPty>'.$CrLf);
1744  fputs($this->file, ' </GrpHdr>'.$CrLf);
1745  // SEPA File Emetteur (mycompany)
1746  if ($result != -2) {
1747  fputs($this-> file, $fileEmetteurSection);
1748  }
1749  // SEPA File Creditors
1750  if ($result != -2) {
1751  fputs($this-> file, $fileCrediteurSection);
1752  }
1753  // SEPA FILE FOOTER
1754  fputs($this->file, ' </PmtInf>'.$CrLf);
1755  fputs($this->file, ' </CstmrCdtTrfInitn>'.$CrLf);
1756  fputs($this->file, '</Document>'.$CrLf);
1757  }
1758  }
1759 
1760  // Build file for Other Countries with unknow format
1761  if (!$found) {
1762  if ($type != 'bank-transfer') {
1763  $sql = "SELECT pl.amount";
1764  $sql .= " FROM";
1765  $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,";
1766  $sql .= " ".MAIN_DB_PREFIX."facture as f,";
1767  $sql .= " ".MAIN_DB_PREFIX."prelevement as pf";
1768  $sql .= " WHERE pl.fk_prelevement_bons = ".((int) $this->id);
1769  $sql .= " AND pl.rowid = pf.fk_prelevement_lignes";
1770  $sql .= " AND pf.fk_facture = f.rowid";
1771 
1772  // Lines
1773  $i = 0;
1774  $resql = $this->db->query($sql);
1775  if ($resql) {
1776  $num = $this->db->num_rows($resql);
1777 
1778  while ($i < $num) {
1779  $obj = $this->db->fetch_object($resql);
1780  $this->total = $this->total + $obj->amount;
1781 
1782  // TODO Write record into file
1783  $i++;
1784  }
1785  } else {
1786  $result = -2;
1787  }
1788  } else {
1789  $sql = "SELECT pl.amount";
1790  $sql .= " FROM";
1791  $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,";
1792  $sql .= " ".MAIN_DB_PREFIX."facture_fourn as f,";
1793  $sql .= " ".MAIN_DB_PREFIX."prelevement as pf";
1794  $sql .= " WHERE pl.fk_prelevement_bons = ".((int) $this->id);
1795  $sql .= " AND pl.rowid = pf.fk_prelevement_lignes";
1796  $sql .= " AND pf.fk_facture_fourn = f.rowid";
1797 
1798  // Lines
1799  $i = 0;
1800  $resql = $this->db->query($sql);
1801  if ($resql) {
1802  $num = $this->db->num_rows($resql);
1803 
1804  while ($i < $num) {
1805  $obj = $this->db->fetch_object($resql);
1806  $this->total = $this->total + $obj->amount;
1807 
1808  // TODO Write record into file
1809  $i++;
1810  }
1811  } else {
1812  $result = -2;
1813  }
1814  }
1815 
1816  $langs->load('withdrawals');
1817 
1818  // TODO Add here code to generate a generic file
1819  fputs($this->file, $langs->transnoentitiesnoconv('WithdrawalFileNotCapable', $mysoc->country_code));
1820  }
1821 
1822  fclose($this->file);
1823  dolChmod($this->filename);
1824 
1825  return $result;
1826  }
1827 
1828 
1837  public static function buildRumNumber($row_code_client, $row_datec, $row_drum)
1838  {
1839  global $langs;
1840 
1841  $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)
1842 
1843  // 3 char + '-' + 12 + '-' + id + '-' + code Must be lower than 32.
1844  return $pre.'-'.dol_print_date($row_datec, 'dayhourlogsmall').'-'.dol_trunc($row_drum.($row_code_client ? '-'.$row_code_client : ''), 13, 'right', 'UTF-8', 1);
1845  }
1846 
1847 
1848  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1865  public function EnregDestinataire($rowid, $client_nom, $rib_banque, $rib_guichet, $rib_number, $amount, $ref, $facid, $rib_dom = '', $type = 'direct-debit')
1866  {
1867  // phpcs:enable
1868  fputs($this->file, "06");
1869  fputs($this->file, "08"); // Prelevement ordinaire
1870 
1871  fputs($this->file, " "); // Zone Reservee B2
1872 
1873  fputs($this->file, $this->emetteur_ics); // ICS
1874 
1875  // Date d'echeance C1
1876 
1877  fputs($this->file, " ");
1878  fputs($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
1879  fputs($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
1880 
1881  // Raison Sociale Destinataire C2
1882 
1883  fputs($this->file, substr(strtoupper($client_nom)." ", 0, 24));
1884 
1885  // Domiciliation facultative D1
1886  $domiciliation = strtr($rib_dom, array(" " => "-", CHR(13) => " ", CHR(10) => ""));
1887  fputs($this->file, substr($domiciliation." ", 0, 24));
1888 
1889  // Zone Reservee D2
1890 
1891  fputs($this->file, substr(" ", 0, 8));
1892 
1893  // Code Guichet D3
1894 
1895  fputs($this->file, $rib_guichet);
1896 
1897  // Numero de compte D4
1898 
1899  fputs($this->file, substr("000000000000000".$rib_number, -11));
1900 
1901  // Zone E Montant
1902 
1903  $montant = (round($amount, 2) * 100);
1904 
1905  fputs($this->file, substr("000000000000000".$montant, -16));
1906 
1907  // Label F
1908 
1909  fputs($this->file, substr("*_".$ref."_RDVnet".$rowid." ", 0, 31));
1910 
1911  // Code etablissement G1
1912 
1913  fputs($this->file, $rib_banque);
1914 
1915  // Zone Reservee G2
1916 
1917  fputs($this->file, substr(" ", 0, 5));
1918 
1919  fputs($this->file, "\n");
1920  }
1921 
1922  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1948  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 = '')
1949  {
1950  // phpcs:enable
1951  global $conf;
1952 
1953  include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
1954 
1955  $CrLf = "\n";
1956  $Rowing = sprintf("%010d", $row_idfac);
1957 
1958  // Define value for RUM
1959  // Example: RUM-CustomerCode-CustomerBankAccountId-01424448606 (note: Date is the timestamp of the date of creation of CustomerBankAccountId)
1960  $Rum = (empty($row_rum) ? $this->buildRumNumber($row_code_client, $row_datec, $row_drum) : $row_rum);
1961 
1962  // Define date of RUM signature
1963  $DtOfSgntr = dol_print_date($row_datec, '%Y-%m-%d');
1964 
1965  if ($type != 'bank-transfer') {
1966  // SEPA Paiement Information of buyer for Direct Debit
1967  $XML_DEBITOR = '';
1968  $XML_DEBITOR .= ' <DrctDbtTxInf>'.$CrLf;
1969  $XML_DEBITOR .= ' <PmtId>'.$CrLf;
1970  // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
1971  $XML_DEBITOR .= ' <EndToEndId>'.(($conf->global->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
1972  $XML_DEBITOR .= ' </PmtId>'.$CrLf;
1973  $XML_DEBITOR .= ' <InstdAmt Ccy="EUR">'.round($row_somme, 2).'</InstdAmt>'.$CrLf;
1974  $XML_DEBITOR .= ' <DrctDbtTx>'.$CrLf;
1975  $XML_DEBITOR .= ' <MndtRltdInf>'.$CrLf;
1976  $XML_DEBITOR .= ' <MndtId>'.$Rum.'</MndtId>'.$CrLf;
1977  $XML_DEBITOR .= ' <DtOfSgntr>'.$DtOfSgntr.'</DtOfSgntr>'.$CrLf;
1978  $XML_DEBITOR .= ' <AmdmntInd>false</AmdmntInd>'.$CrLf;
1979  $XML_DEBITOR .= ' </MndtRltdInf>'.$CrLf;
1980  $XML_DEBITOR .= ' </DrctDbtTx>'.$CrLf;
1981  $XML_DEBITOR .= ' <DbtrAgt>'.$CrLf;
1982  $XML_DEBITOR .= ' <FinInstnId>'.$CrLf;
1983  $XML_DEBITOR .= ' <BIC>'.$row_bic.'</BIC>'.$CrLf;
1984  $XML_DEBITOR .= ' </FinInstnId>'.$CrLf;
1985  $XML_DEBITOR .= ' </DbtrAgt>'.$CrLf;
1986  $XML_DEBITOR .= ' <Dbtr>'.$CrLf;
1987  $XML_DEBITOR .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))).'</Nm>'.$CrLf;
1988  $XML_DEBITOR .= ' <PstlAdr>'.$CrLf;
1989  $XML_DEBITOR .= ' <Ctry>'.$row_country_code.'</Ctry>'.$CrLf;
1990  $addressline1 = strtr($row_address, array(CHR(13) => ", ", CHR(10) => ""));
1991  $addressline2 = strtr($row_zip.(($row_zip && $row_town) ? ' ' : (string) $row_town), array(CHR(13) => ", ", CHR(10) => ""));
1992  if (trim($addressline1)) {
1993  $XML_DEBITOR .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
1994  }
1995  if (trim($addressline2)) {
1996  $XML_DEBITOR .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
1997  }
1998  $XML_DEBITOR .= ' </PstlAdr>'.$CrLf;
1999  $XML_DEBITOR .= ' </Dbtr>'.$CrLf;
2000  $XML_DEBITOR .= ' <DbtrAcct>'.$CrLf;
2001  $XML_DEBITOR .= ' <Id>'.$CrLf;
2002  $XML_DEBITOR .= ' <IBAN>'.preg_replace('/\s/', '', $row_iban).'</IBAN>'.$CrLf;
2003  $XML_DEBITOR .= ' </Id>'.$CrLf;
2004  $XML_DEBITOR .= ' </DbtrAcct>'.$CrLf;
2005  $XML_DEBITOR .= ' <RmtInf>'.$CrLf;
2006  // A string with some information on payment - 140 max
2007  $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
2008  $XML_DEBITOR .= ' </RmtInf>'.$CrLf;
2009  $XML_DEBITOR .= ' </DrctDbtTxInf>'.$CrLf;
2010  return $XML_DEBITOR;
2011  } else {
2012  // SEPA Paiement Information of seller for Credit Transfer
2013  $XML_CREDITOR = '';
2014  $XML_CREDITOR .= ' <CdtTrfTxInf>'.$CrLf;
2015  $XML_CREDITOR .= ' <PmtId>'.$CrLf;
2016  // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
2017  $XML_CREDITOR .= ' <EndToEndId>'.(($conf->global->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
2018  $XML_CREDITOR .= ' </PmtId>'.$CrLf;
2019  if (!empty($this->sepa_xml_pti_in_ctti)) {
2020  $XML_CREDITOR .= ' <PmtTpInf>' . $CrLf;
2021 
2022  // Can be 'NORM' for normal or 'HIGH' for high priority level
2023  if (!empty($conf->global->PAYMENTBYBANKTRANSFER_FORCE_HIGH_PRIORITY)) {
2024  $instrprty = 'HIGH';
2025  } else {
2026  $instrprty = 'NORM';
2027  }
2028  $XML_CREDITOR .= ' <InstrPrty>'.$instrprty.'</InstrPrty>' . $CrLf;
2029  $XML_CREDITOR .= ' <SvcLvl>' . $CrLf;
2030  $XML_CREDITOR .= ' <Cd>SEPA</Cd>' . $CrLf;
2031  $XML_CREDITOR .= ' </SvcLvl>' . $CrLf;
2032  $XML_CREDITOR .= ' <CtgyPurp>' . $CrLf;
2033  $XML_CREDITOR .= ' <Cd>CORE</Cd>' . $CrLf;
2034  $XML_CREDITOR .= ' </CtgyPurp>' . $CrLf;
2035  $XML_CREDITOR .= ' </PmtTpInf>' . $CrLf;
2036  }
2037  $XML_CREDITOR .= ' <Amt>'.$CrLf;
2038  $XML_CREDITOR .= ' <InstdAmt Ccy="EUR">'.round($row_somme, 2).'</InstdAmt>'.$CrLf;
2039  $XML_CREDITOR .= ' </Amt>'.$CrLf;
2040  /*
2041  $XML_CREDITOR .= ' <DrctDbtTx>'.$CrLf;
2042  $XML_CREDITOR .= ' <MndtRltdInf>'.$CrLf;
2043  $XML_CREDITOR .= ' <MndtId>'.$Rum.'</MndtId>'.$CrLf;
2044  $XML_CREDITOR .= ' <DtOfSgntr>'.$DtOfSgntr.'</DtOfSgntr>'.$CrLf;
2045  $XML_CREDITOR .= ' <AmdmntInd>false</AmdmntInd>'.$CrLf;
2046  $XML_CREDITOR .= ' </MndtRltdInf>'.$CrLf;
2047  $XML_CREDITOR .= ' </DrctDbtTx>'.$CrLf;
2048  */
2049  //$XML_CREDITOR .= ' <ChrgBr>SLEV</ChrgBr>'.$CrLf;
2050  $XML_CREDITOR .= ' <CdtrAgt>'.$CrLf;
2051  $XML_CREDITOR .= ' <FinInstnId>'.$CrLf;
2052  $XML_CREDITOR .= ' <BIC>'.$row_bic.'</BIC>'.$CrLf;
2053  $XML_CREDITOR .= ' </FinInstnId>'.$CrLf;
2054  $XML_CREDITOR .= ' </CdtrAgt>'.$CrLf;
2055  $XML_CREDITOR .= ' <Cdtr>'.$CrLf;
2056  $XML_CREDITOR .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))).'</Nm>'.$CrLf;
2057  $XML_CREDITOR .= ' <PstlAdr>'.$CrLf;
2058  $XML_CREDITOR .= ' <Ctry>'.$row_country_code.'</Ctry>'.$CrLf;
2059  $addressline1 = strtr($row_address, array(CHR(13) => ", ", CHR(10) => ""));
2060  $addressline2 = strtr($row_zip.(($row_zip && $row_town) ? ' ' : (string) $row_town), array(CHR(13) => ", ", CHR(10) => ""));
2061  if (trim($addressline1)) {
2062  $XML_CREDITOR .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2063  }
2064  if (trim($addressline2)) {
2065  $XML_CREDITOR .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2066  }
2067  $XML_CREDITOR .= ' </PstlAdr>'.$CrLf;
2068  $XML_CREDITOR .= ' </Cdtr>'.$CrLf;
2069  $XML_CREDITOR .= ' <CdtrAcct>'.$CrLf;
2070  $XML_CREDITOR .= ' <Id>'.$CrLf;
2071  $XML_CREDITOR .= ' <IBAN>'.preg_replace('/\s/', '', $row_iban).'</IBAN>'.$CrLf;
2072  $XML_CREDITOR .= ' </Id>'.$CrLf;
2073  $XML_CREDITOR .= ' </CdtrAcct>'.$CrLf;
2074  $XML_CREDITOR .= ' <RmtInf>'.$CrLf;
2075  // A string with some information on payment - 140 max
2076  $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
2077  $XML_CREDITOR .= ' </RmtInf>'.$CrLf;
2078  $XML_CREDITOR .= ' </CdtTrfTxInf>'.$CrLf;
2079  return $XML_CREDITOR;
2080  }
2081  }
2082 
2083 
2084  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2092  public function EnregEmetteur($type = 'direct-debit')
2093  {
2094  // phpcs:enable
2095  fputs($this->file, "03");
2096  fputs($this->file, "08"); // Prelevement ordinaire
2097 
2098  fputs($this->file, " "); // Zone Reservee B2
2099 
2100  fputs($this->file, $this->emetteur_ics); // ICS
2101 
2102  // Date d'echeance C1
2103 
2104  fputs($this->file, " ");
2105  fputs($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
2106  fputs($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
2107 
2108  // Raison Sociale C2
2109 
2110  fputs($this->file, substr($this->raison_sociale." ", 0, 24));
2111 
2112  // Reference de la remise creancier D1 sur 7 caracteres
2113 
2114  fputs($this->file, substr($this->reference_remise." ", 0, 7));
2115 
2116  // Zone Reservee D1-2
2117 
2118  fputs($this->file, substr(" ", 0, 17));
2119 
2120  // Zone Reservee D2
2121 
2122  fputs($this->file, substr(" ", 0, 2));
2123  fputs($this->file, "E");
2124  fputs($this->file, substr(" ", 0, 5));
2125 
2126  // Code Guichet D3
2127 
2128  fputs($this->file, $this->emetteur_code_guichet);
2129 
2130  // Numero de compte D4
2131 
2132  fputs($this->file, substr("000000000000000".$this->emetteur_numero_compte, -11));
2133 
2134  // Zone Reservee E
2135 
2136  fputs($this->file, substr(" ", 0, 16));
2137 
2138  // Zone Reservee F
2139 
2140  fputs($this->file, substr(" ", 0, 31));
2141 
2142  // Code etablissement
2143 
2144  fputs($this->file, $this->emetteur_code_banque);
2145 
2146  // Zone Reservee G
2147 
2148  fputs($this->file, substr(" ", 0, 5));
2149 
2150  fputs($this->file, "\n");
2151  }
2152 
2153  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2169  public function EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf = '\n', $format = 'FRST', $type = 'direct-debit', $fk_bank_account = 0)
2170  {
2171  // phpcs:enable
2172  // SEPA INITIALISATION
2173  global $conf;
2174 
2175  // Clean parameters
2176  $dateTime_YMD = dol_print_date($ladate, '%Y%m%d');
2177  $dateTime_ETAD = dol_print_date($ladate, '%Y-%m-%d');
2178  $dateTime_YMDHMS = dol_print_date($ladate, '%Y-%m-%dT%H:%M:%S');
2179 
2180  // Clean params
2181  if (empty($fk_bank_account)) {
2182  $fk_bank_account = ($type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT);
2183  }
2184 
2185  // Get data of bank account
2186  $account = new Account($this->db);
2187  if ($account->fetch($fk_bank_account) > 0) {
2188  $this->emetteur_code_banque = $account->code_banque;
2189  $this->emetteur_code_guichet = $account->code_guichet;
2190  $this->emetteur_numero_compte = $account->number;
2191  $this->emetteur_number_key = $account->cle_rib;
2192  $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
2193  $this->emetteur_iban = $account->iban;
2194  $this->emetteur_bic = $account->bic;
2195 
2196  $this->emetteur_ics = ($type == 'bank-transfer' ? $account->ics_transfer : $account->ics); // Ex: PRELEVEMENT_ICS = "FR78ZZZ123456";
2197 
2198  $this->raison_sociale = $account->proprio;
2199  }
2200 
2201  // Get pending payments
2202  $sql = "SELECT rowid, ref";
2203  $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons as pb";
2204  $sql .= " WHERE pb.rowid = ".((int) $this->id);
2205 
2206  $resql = $this->db->query($sql);
2207  if ($resql) {
2208  $obj = $this->db->fetch_object($resql);
2209 
2210  $country = explode(':', $configuration->global->MAIN_INFO_SOCIETE_COUNTRY);
2211  $IdBon = sprintf("%05d", $obj->rowid);
2212  $RefBon = $obj->ref;
2213 
2214  if ($type != 'bank-transfer') {
2215  // SEPA Paiement Information of my company for Direct Debit
2216  $XML_SEPA_INFO = '';
2217  $XML_SEPA_INFO .= ' <PmtInf>'.$CrLf;
2218  $XML_SEPA_INFO .= ' <PmtInfId>'.('DD/'.$dateTime_YMD.'/ID'.$IdBon.'-'.$RefBon).'</PmtInfId>'.$CrLf;
2219  $XML_SEPA_INFO .= ' <PmtMtd>DD</PmtMtd>'.$CrLf;
2220  $XML_SEPA_INFO .= ' <NbOfTxs>'.$nombre.'</NbOfTxs>'.$CrLf;
2221  $XML_SEPA_INFO .= ' <CtrlSum>'.$total.'</CtrlSum>'.$CrLf;
2222  $XML_SEPA_INFO .= ' <PmtTpInf>'.$CrLf;
2223  $XML_SEPA_INFO .= ' <SvcLvl>'.$CrLf;
2224  $XML_SEPA_INFO .= ' <Cd>SEPA</Cd>'.$CrLf;
2225  $XML_SEPA_INFO .= ' </SvcLvl>'.$CrLf;
2226  $XML_SEPA_INFO .= ' <LclInstrm>'.$CrLf;
2227  $XML_SEPA_INFO .= ' <Cd>CORE</Cd>'.$CrLf;
2228  $XML_SEPA_INFO .= ' </LclInstrm>'.$CrLf;
2229  $XML_SEPA_INFO .= ' <SeqTp>'.$format.'</SeqTp>'.$CrLf;
2230  $XML_SEPA_INFO .= ' </PmtTpInf>'.$CrLf;
2231  $XML_SEPA_INFO .= ' <ReqdColltnDt>'.$dateTime_ETAD.'</ReqdColltnDt>'.$CrLf;
2232  $XML_SEPA_INFO .= ' <Cdtr>'.$CrLf;
2233  $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2234  $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2235  $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2236  $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(CHR(13) => ", ", CHR(10) => ""));
2237  $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) => ""));
2238  if ($addressline1) {
2239  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2240  }
2241  if ($addressline2) {
2242  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2243  }
2244  $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2245  $XML_SEPA_INFO .= ' </Cdtr>'.$CrLf;
2246  $XML_SEPA_INFO .= ' <CdtrAcct>'.$CrLf;
2247  $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2248  $XML_SEPA_INFO .= ' <IBAN>'.preg_replace('/\s/', '', $this->emetteur_iban).'</IBAN>'.$CrLf;
2249  $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2250  $XML_SEPA_INFO .= ' </CdtrAcct>'.$CrLf;
2251  $XML_SEPA_INFO .= ' <CdtrAgt>'.$CrLf;
2252  $XML_SEPA_INFO .= ' <FinInstnId>'.$CrLf;
2253  $XML_SEPA_INFO .= ' <BIC>'.$this->emetteur_bic.'</BIC>'.$CrLf;
2254  $XML_SEPA_INFO .= ' </FinInstnId>'.$CrLf;
2255  $XML_SEPA_INFO .= ' </CdtrAgt>'.$CrLf;
2256  /* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf;
2257  $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2258  $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2259  $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2260  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ADDRESS), ' ')).'</AdrLine>'.$CrLf;
2261  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ZIP.' '.$conf->global->MAIN_INFO_SOCIETE_TOWN), ' ')).'</AdrLine>'.$CrLf;
2262  $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2263  $XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/
2264  $XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>'.$CrLf; // Field "Responsible of fees". Must be SLEV
2265  $XML_SEPA_INFO .= ' <CdtrSchmeId>'.$CrLf;
2266  $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2267  $XML_SEPA_INFO .= ' <PrvtId>'.$CrLf;
2268  $XML_SEPA_INFO .= ' <Othr>'.$CrLf;
2269  $XML_SEPA_INFO .= ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf;
2270  $XML_SEPA_INFO .= ' <SchmeNm>'.$CrLf;
2271  $XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>'.$CrLf;
2272  $XML_SEPA_INFO .= ' </SchmeNm>'.$CrLf;
2273  $XML_SEPA_INFO .= ' </Othr>'.$CrLf;
2274  $XML_SEPA_INFO .= ' </PrvtId>'.$CrLf;
2275  $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2276  $XML_SEPA_INFO .= ' </CdtrSchmeId>'.$CrLf;
2277  } else {
2278  // SEPA Paiement Information of my company for Credit Transfer
2279  $XML_SEPA_INFO = '';
2280  $XML_SEPA_INFO .= ' <PmtInf>'.$CrLf;
2281  $XML_SEPA_INFO .= ' <PmtInfId>'.('TRF/'.$dateTime_YMD.'/ID'.$IdBon.'-'.$RefBon).'</PmtInfId>'.$CrLf;
2282  $XML_SEPA_INFO .= ' <PmtMtd>TRF</PmtMtd>'.$CrLf;
2283  //$XML_SEPA_INFO .= ' <BtchBookg>False</BtchBookg>'.$CrLf;
2284  $XML_SEPA_INFO .= ' <NbOfTxs>'.$nombre.'</NbOfTxs>'.$CrLf;
2285  $XML_SEPA_INFO .= ' <CtrlSum>'.$total.'</CtrlSum>'.$CrLf;
2286  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.
2287  $XML_SEPA_INFO .= ' <PmtTpInf>' . $CrLf;
2288  $XML_SEPA_INFO .= ' <SvcLvl>' . $CrLf;
2289  $XML_SEPA_INFO .= ' <Cd>SEPA</Cd>' . $CrLf;
2290  $XML_SEPA_INFO .= ' </SvcLvl>' . $CrLf;
2291  $XML_SEPA_INFO .= ' <LclInstrm>' . $CrLf;
2292  $XML_SEPA_INFO .= ' <Cd>CORE</Cd>' . $CrLf;
2293  $XML_SEPA_INFO .= ' </LclInstrm>' . $CrLf;
2294  $XML_SEPA_INFO .= ' <SeqTp>' . $format . '</SeqTp>' . $CrLf;
2295  $XML_SEPA_INFO .= ' </PmtTpInf>' . $CrLf;
2296  }
2297  $XML_SEPA_INFO .= ' <ReqdExctnDt>'.dol_print_date($dateTime_ETAD, 'dayrfc').'</ReqdExctnDt>'.$CrLf;
2298  $XML_SEPA_INFO .= ' <Dbtr>'.$CrLf;
2299  $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2300  $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2301  $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2302  $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(CHR(13) => ", ", CHR(10) => ""));
2303  $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) => ""));
2304  if ($addressline1) {
2305  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2306  }
2307  if ($addressline2) {
2308  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2309  }
2310  $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2311  $XML_SEPA_INFO .= ' </Dbtr>'.$CrLf;
2312  $XML_SEPA_INFO .= ' <DbtrAcct>'.$CrLf;
2313  $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2314  $XML_SEPA_INFO .= ' <IBAN>'.preg_replace('/\s/', '', $this->emetteur_iban).'</IBAN>'.$CrLf;
2315  $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2316  $XML_SEPA_INFO .= ' </DbtrAcct>'.$CrLf;
2317  $XML_SEPA_INFO .= ' <DbtrAgt>'.$CrLf;
2318  $XML_SEPA_INFO .= ' <FinInstnId>'.$CrLf;
2319  $XML_SEPA_INFO .= ' <BIC>'.$this->emetteur_bic.'</BIC>'.$CrLf;
2320  $XML_SEPA_INFO .= ' </FinInstnId>'.$CrLf;
2321  $XML_SEPA_INFO .= ' </DbtrAgt>'.$CrLf;
2322  /* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf;
2323  $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2324  $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2325  $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2326  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ADDRESS), ' ')).'</AdrLine>'.$CrLf;
2327  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ZIP.' '.$conf->global->MAIN_INFO_SOCIETE_TOWN), ' ')).'</AdrLine>'.$CrLf;
2328  $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2329  $XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/
2330  $XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>'.$CrLf; // Field "Responsible of fees". Must be SLEV
2331  /*$XML_SEPA_INFO .= ' <CdtrSchmeId>'.$CrLf;
2332  $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2333  $XML_SEPA_INFO .= ' <PrvtId>'.$CrLf;
2334  $XML_SEPA_INFO .= ' <Othr>'.$CrLf;
2335  $XML_SEPA_INFO .= ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf;
2336  $XML_SEPA_INFO .= ' <SchmeNm>'.$CrLf;
2337  $XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>'.$CrLf;
2338  $XML_SEPA_INFO .= ' </SchmeNm>'.$CrLf;
2339  $XML_SEPA_INFO .= ' </Othr>'.$CrLf;
2340  $XML_SEPA_INFO .= ' </PrvtId>'.$CrLf;
2341  $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2342  $XML_SEPA_INFO .= ' </CdtrSchmeId>'.$CrLf;*/
2343  }
2344  } else {
2345  fputs($this->file, 'INCORRECT EMETTEUR '.$this->raison_sociale.$CrLf);
2346  $XML_SEPA_INFO = '';
2347  }
2348  return $XML_SEPA_INFO;
2349  }
2350 
2351  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2358  public function EnregTotal($total)
2359  {
2360  // phpcs:enable
2361  fputs($this->file, "08");
2362  fputs($this->file, "08"); // Prelevement ordinaire
2363 
2364  fputs($this->file, " "); // Zone Reservee B2
2365 
2366  fputs($this->file, $this->emetteur_ics); // ICS
2367 
2368  // Reserve C1
2369 
2370  fputs($this->file, substr(" ", 0, 12));
2371 
2372 
2373  // Raison Sociale C2
2374 
2375  fputs($this->file, substr(" ", 0, 24));
2376 
2377  // D1
2378 
2379  fputs($this->file, substr(" ", 0, 24));
2380 
2381  // Zone Reservee D2
2382 
2383  fputs($this->file, substr(" ", 0, 8));
2384 
2385  // Code Guichet D3
2386 
2387  fputs($this->file, substr(" ", 0, 5));
2388 
2389  // Numero de compte D4
2390 
2391  fputs($this->file, substr(" ", 0, 11));
2392 
2393  // Zone E Montant
2394 
2395  $montant = ($total * 100);
2396 
2397  fputs($this->file, substr("000000000000000".$montant, -16));
2398 
2399  // Zone Reservee F
2400 
2401  fputs($this->file, substr(" ", 0, 31));
2402 
2403  // Code etablissement
2404 
2405  fputs($this->file, substr(" ", 0, 5));
2406 
2407  // Zone Reservee F
2408 
2409  fputs($this->file, substr(" ", 0, 5));
2410 
2411  fputs($this->file, "\n");
2412  }
2413 
2420  public function getLibStatut($mode = 0)
2421  {
2422  return $this->LibStatut($this->statut, $mode);
2423  }
2424 
2425  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2433  public function LibStatut($status, $mode = 0)
2434  {
2435  // phpcs:enable
2436  if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
2437  global $langs;
2438  //$langs->load("mymodule");
2439  $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2440  $this->labelStatus[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2441  $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2442  $this->labelStatusShort[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2443  if ($this->type == 'bank-transfer') {
2444  $this->labelStatus[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2445  $this->labelStatusShort[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2446  } else {
2447  $this->labelStatus[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2448  $this->labelStatusShort[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2449  }
2450  }
2451 
2452  $statusType = 'status1';
2453  if ($status == self::STATUS_TRANSFERED) {
2454  $statusType = 'status3';
2455  }
2456  if ($status == self::STATUS_CREDITED || $status == self::STATUS_DEBITED) {
2457  $statusType = 'status6';
2458  }
2459 
2460  return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
2461  }
2462 
2463  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2471  public function load_board($user, $mode)
2472  {
2473  // phpcs:enable
2474  global $conf, $langs;
2475 
2476  if ($user->socid) {
2477  return -1; // protection pour eviter appel par utilisateur externe
2478  }
2479 
2480  /*
2481  if ($mode == 'direct_debit') {
2482  $sql = "SELECT b.rowid, f.datedue as datefin";
2483  $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
2484  $sql .= " WHERE f.entity IN (".getEntity('facture').")";
2485  $sql .= " AND f.total_ttc > 0";
2486  } else {
2487  $sql = "SELECT b.rowid, f.datedue as datefin";
2488  $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
2489  $sql .= " WHERE f.entity IN (".getEntity('facture_fourn').")";
2490  $sql .= " AND f.total_ttc > 0";
2491  }
2492 
2493  $resql = $this->db->query($sql);
2494  if ($resql) {
2495  $langs->load("banks");
2496  $now = dol_now();
2497 
2498  $response = new WorkboardResponse();
2499  if ($mode == 'direct_debit') {
2500  $response->warning_delay = $conf->prelevement->warning_delay / 60 / 60 / 24;
2501  $response->label = $langs->trans("PendingDirectDebitToComplete");
2502  $response->labelShort = $langs->trans("PendingDirectDebitToCompleteShort");
2503  $response->url = DOL_URL_ROOT.'/compta/prelevement/index.php?leftmenu=checks&mainmenu=bank';
2504  } else {
2505  $response->warning_delay = $conf->paymentbybanktransfer->warning_delay / 60 / 60 / 24;
2506  $response->label = $langs->trans("PendingCreditTransferToComplete");
2507  $response->labelShort = $langs->trans("PendingCreditTransferToCompleteShort");
2508  $response->url = DOL_URL_ROOT.'/compta/paymentbybanktransfer/index.php?leftmenu=checks&mainmenu=bank';
2509  }
2510  $response->img = img_object('', "payment");
2511 
2512  while ($obj = $this->db->fetch_object($resql)) {
2513  $response->nbtodo++;
2514 
2515  if ($this->db->jdate($obj->datefin) < ($now - $conf->withdraw->warning_delay)) {
2516  $response->nbtodolate++;
2517  }
2518  }
2519 
2520  $response->nbtodo = 0;
2521  $response->nbtodolate = 0;
2522  // Return workboard only if quantity is not 0
2523  if ($response->nbtodo) {
2524  return $response;
2525  } else {
2526  return 0;
2527  }
2528  } else {
2529  dol_print_error($this->db);
2530  $this->error = $this->db->error();
2531  return -1;
2532  }
2533  */
2534  return 0;
2535  }
2536 
2544  public function getKanbanView($option = '', $arraydata = null)
2545  {
2546  global $langs;
2547 
2548  $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2549 
2550  $return = '<div class="box-flex-item box-flex-grow-zero">';
2551  $return .= '<div class="info-box info-box-sm">';
2552  $return .= '<span class="info-box-icon bg-infobox-action">';
2553  $return .= img_picto('', $this->picto);
2554  $return .= '</span>';
2555  $return .= '<div class="info-box-content">';
2556  $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).'</span>';
2557  $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
2558 
2559  if (property_exists($this, 'date_echeance')) {
2560  $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>';
2561  }
2562  if (property_exists($this, 'total')) {
2563  $return .= '<br><span class="opacitymedium">'.$langs->trans("Amount").'</span> : <span class="amount">'.price($this->total).'</span>';
2564  }
2565  if (method_exists($this, 'LibStatut')) {
2566  $return .= '<br><div class="info-box-status margintoponly">'.$this->getLibStatut(3).'</div>';
2567  }
2568  $return .= '</div>';
2569  $return .= '</div>';
2570  $return .= '</div>';
2571  return $return;
2572  }
2573 }
$object ref
Definition: info.php:78
Class to manage bank accounts.
Class to manage withdrawal receipts.
load_board($user, $mode)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
static buildRumNumber($row_code_client, $row_datec, $row_drum)
Generate dynamically a RUM number for a customer bank account.
SommeAPrelever($mode='direct-debit')
Returns amount waiting for direct debit payment or credit transfer payment.
EnregEmetteur($type='direct-debit')
Write sender of request (me).
update(User $user, $notrigger=false)
Update object into database.
EnregTotal($total)
Write end.
fetch($rowid, $ref='')
Get object and lines from database.
create($banque=0, $agence=0, $mode='real', $format='ALL', $executiondate='', $notrigger=0, $type='direct-debit', $did=0, $fk_bank_account=0)
Create a BAN payment order:
generate($format='ALL', $executiondate=0, $type='direct-debit', $fk_bank_account=0)
Generate a direct debit or credit transfer file.
deleteNotificationById($rowid)
Delete a notification def by id.
addline(&$line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key)
Add line 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)
NbFactureAPrelever($type='direct-debit')
Get number of invoices to pay.
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.
set_infotrans($user, $date, $method)
Set withdrawal to transmited 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)
Set direct debit or credit transfer order to "paid" status.
nbOfInvoiceToPay($mode='direct-debit')
Get number of invoices waiting for payment.
AddFacture($invoice_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $type='debit-order')
Add invoice 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)
getListInvoices($amounts=0)
Get invoice list.
addNotification($db, $user, $action)
Add a notification.
deleteNotification($user, $action)
Delete a notification.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
updateCommon(User $user, $notrigger=false)
Update object into database.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Class to manage bank accounts description of third parties.
Class to manage suppliers invoices.
Class to manage invoices.
Class to manage payments for supplier invoices.
Class to manage payments of customer invoices.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage Dolibarr users.
Definition: user.class.php:48
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->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') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
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.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dolChmod($filepath, $newmask='')
Change mod of a file.
dol_now($mode='auto')
Return date for now.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
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_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.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:120