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 }
Societe
Class to manage third parties objects (customers, suppliers, prospects...)
Definition: societe.class.php:51
BonPrelevement\deleteNotificationById
deleteNotificationById($rowid)
Delete a notification def by id.
Definition: bonprelevement.class.php:1404
dol_string_nospecial
dol_string_nospecial($str, $newstr='_', $badcharstoreplace='', $badcharstoremove='', $keepspaces=0)
Clean a string from all punctuation characters to use it as a ref or login.
Definition: functions.lib.php:1496
dol_trunc
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.
Definition: functions.lib.php:4059
BonPrelevement\fetch
fetch($rowid, $ref='')
Get object and lines from database.
Definition: bonprelevement.class.php:363
FactureFournisseur
Class to manage suppliers invoices.
Definition: fournisseur.facture.class.php:51
dol_print_error
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
Definition: functions.lib.php:5107
BonPrelevement\EnregEmetteur
EnregEmetteur($type='direct-debit')
Write sender of request (me).
Definition: bonprelevement.class.php:2092
BonPrelevement\nbOfInvoiceToPay
nbOfInvoiceToPay($mode='direct-debit')
Get number of invoices waiting for payment.
Definition: bonprelevement.class.php:774
Facture
Class to manage invoices.
Definition: facture.class.php:60
BonPrelevement\generate
generate($format='ALL', $executiondate=0, $type='direct-debit', $fk_bank_account=0)
Generate a direct debit or credit transfer file.
Definition: bonprelevement.class.php:1493
CommonObject
Parent class of all other business classes (invoices, contracts, proposals, orders,...
Definition: commonobject.class.php:45
CompanyBankAccount
Class to manage bank accounts description of third parties.
Definition: companybankaccount.class.php:34
BonPrelevement\__construct
__construct($db)
Constructor.
Definition: bonprelevement.class.php:179
BonPrelevement\AddFacture
AddFacture($invoice_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $type='debit-order')
Add invoice to withdrawal.
Definition: bonprelevement.class.php:223
price2num
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
Definition: functions.lib.php:5955
dol_print_date
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
Definition: functions.lib.php:2675
img_picto
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
Definition: functions.lib.php:4135
dolChmod
dolChmod($filepath, $newmask='')
Change mod of a file.
Definition: functions.lib.php:7007
BonPrelevement\getErrorString
getErrorString($error)
Return error string.
Definition: bonprelevement.class.php:345
BonPrelevement
Class to manage withdrawal receipts.
Definition: bonprelevement.class.php:43
BonPrelevement\getLibStatut
getLibStatut($mode=0)
Return status label of object.
Definition: bonprelevement.class.php:2420
dol_string_unaccent
dol_string_unaccent($str)
Clean a string from all accent characters to be used as ref, login or by dol_sanitizeFileName.
Definition: functions.lib.php:1424
BonPrelevement\buildRumNumber
static buildRumNumber($row_code_client, $row_datec, $row_drum)
Generate dynamically a RUM number for a customer bank account.
Definition: bonprelevement.class.php:1837
BonPrelevement\update
update(User $user, $notrigger=false)
Update object into database.
Definition: bonprelevement.class.php:426
BonPrelevement\SommeAPrelever
SommeAPrelever($mode='direct-debit')
Returns amount waiting for direct debit payment or credit transfer payment.
Definition: bonprelevement.class.php:726
BonPrelevement\getKanbanView
getKanbanView($option='', $arraydata=null)
Return clicable link of object (with eventually picto)
Definition: bonprelevement.class.php:2544
dol_syslog
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
Definition: functions.lib.php:1741
CommonObject\updateCommon
updateCommon(User $user, $notrigger=false)
Update object into database.
Definition: commonobject.class.php:9501
$sql
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
BonPrelevement\deleteNotification
deleteNotification($user, $action)
Delete a notification.
Definition: bonprelevement.class.php:1423
BonPrelevement\load_board
load_board($user, $mode)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
Definition: bonprelevement.class.php:2471
isModEnabled
isModEnabled($module)
Is Dolibarr module enabled.
Definition: functions.lib.php:207
dolGetFirstLastname
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
Definition: functions.lib.php:8590
BonPrelevement\EnregDestinataireSEPA
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)
Definition: bonprelevement.class.php:1948
ref
$object ref
Definition: info.php:78
PaiementFourn
Class to manage payments for supplier invoices.
Definition: paiementfourn.class.php:39
User
Class to manage Dolibarr users.
Definition: user.class.php:47
Paiement
Class to manage payments of customer invoices.
Definition: paiement.class.php:43
BonPrelevement\LibStatut
LibStatut($status, $mode=0)
Return status label for a status.
Definition: bonprelevement.class.php:2433
BonPrelevement\EnregTotal
EnregTotal($total)
Write end.
Definition: bonprelevement.class.php:2358
BonPrelevement\EnregEmetteurSEPA
EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf='\n', $format='FRST', $type='direct-debit', $fk_bank_account=0)
Write sender of request (me).
Definition: bonprelevement.class.php:2169
dolGetStatus
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
Definition: functions.lib.php:10967
img_object
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
Definition: functions.lib.php:4473
BonPrelevement\NbFactureAPrelever
NbFactureAPrelever($type='direct-debit')
Get number of invoices to pay.
Definition: bonprelevement.class.php:786
BonPrelevement\addNotification
addNotification($db, $user, $action)
Add a notification.
Definition: bonprelevement.class.php:1450
BonPrelevement\set_infocredit
set_infocredit($user, $date)
Set direct debit or credit transfer order to "paid" status.
Definition: bonprelevement.class.php:440
dol_now
dol_now($mode='auto')
Return date for now.
Definition: functions.lib.php:3056
BonPrelevement\set_infotrans
set_infotrans($user, $date, $method)
Set withdrawal to transmited status.
Definition: bonprelevement.class.php:604
BonPrelevement\addline
addline(&$line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key)
Add line to withdrawal.
Definition: bonprelevement.class.php:279
price
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.
Definition: functions.lib.php:5829
CommonObject\call_trigger
call_trigger($triggerName, $user)
Call trigger based on this instance.
Definition: commonobject.class.php:5790
dol_mkdir
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
Definition: functions.lib.php:6936
BonPrelevement\create
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:
Definition: bonprelevement.class.php:847
type
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:120
BonPrelevement\getListInvoices
getListInvoices($amounts=0)
Get invoice list.
Definition: bonprelevement.class.php:659
Account
Class to manage bank accounts.
Definition: account.class.php:40
BonPrelevement\EnregDestinataire
EnregDestinataire($rowid, $client_nom, $rib_banque, $rib_guichet, $rib_number, $amount, $ref, $facid, $rib_dom='', $type='direct-debit')
Write recipient of request (customer)
Definition: bonprelevement.class.php:1865
BonPrelevement\getNomUrl
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Returns clickable name (with picto)
Definition: bonprelevement.class.php:1315