dolibarr  17.0.3
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 $date_trans;
74  public $user_trans;
75  public $method_trans;
76 
77  public $total;
78  public $fetched;
79  public $statut; // 0-Wait, 1-Trans, 2-Done
80  public $labelStatus = array();
81 
82  public $factures = array();
83 
84  public $invoice_in_error = array();
85  public $thirdparty_in_error = array();
86 
87  public $amount;
88  public $note;
89  public $datec;
90 
91  public $date_credit;
92  public $user_credit;
93 
94  public $type;
95 
96  const STATUS_DRAFT = 0;
97  const STATUS_TRANSFERED = 1;
98  const STATUS_CREDITED = 2; // STATUS_CREDITED and STATUS_DEBITED is same. Difference is in ->type
99  const STATUS_DEBITED = 2; // STATUS_CREDITED and STATUS_DEBITED is same. Difference is in ->type
100 
101 
107  public function __construct($db)
108  {
109  global $conf, $langs;
110 
111  $this->db = $db;
112 
113  $this->filename = '';
114 
115  $this->date_echeance = dol_now();
116  $this->raison_sociale = "";
117  $this->reference_remise = "";
118 
119  $this->emetteur_code_guichet = "";
120  $this->emetteur_numero_compte = "";
121  $this->emetteur_code_banque = "";
122  $this->emetteur_number_key = "";
123  $this->sepa_xml_pti_in_ctti = false;
124 
125  $this->emetteur_iban = "";
126  $this->emetteur_bic = "";
127  $this->emetteur_ics = "";
128 
129  $this->factures = array();
130 
131  $this->methodes_trans = array();
132 
133  $this->methodes_trans[0] = "Internet";
134 
135  $this->fetched = 0;
136  }
137 
138  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
153  public function AddFacture($invoice_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $type = 'debit-order')
154  {
155  // phpcs:enable
156  $result = 0;
157  $line_id = 0;
158 
159  // Add lines
160  $result = $this->addline($line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key);
161 
162  if ($result == 0) {
163  if ($line_id > 0) {
164  $sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement (";
165  if ($type != 'bank-transfer') {
166  $sql .= "fk_facture";
167  } else {
168  $sql .= "fk_facture_fourn";
169  }
170  $sql .= ",fk_prelevement_lignes";
171  $sql .= ") VALUES (";
172  $sql .= ((int) $invoice_id);
173  $sql .= ", ".((int) $line_id);
174  $sql .= ")";
175 
176  if ($this->db->query($sql)) {
177  $result = 0;
178  } else {
179  $result = -1;
180  $this->errors[] = get_class($this)."::AddFacture ".$this->db->lasterror;
181  dol_syslog(get_class($this)."::AddFacture Error $result");
182  }
183  } else {
184  $result = -2;
185  $this->errors[] = get_class($this)."::AddFacture linedid Empty";
186  dol_syslog(get_class($this)."::AddFacture Error $result");
187  }
188  } else {
189  $result = -3;
190  dol_syslog(get_class($this)."::AddFacture Error $result");
191  }
192 
193  return $result;
194  }
195 
209  public function addline(&$line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key)
210  {
211  $result = -1;
212  $concat = 0;
213 
214  if ($concat == 1) {
215  /*
216  * We aggregate the lines
217  */
218  $sql = "SELECT rowid";
219  $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_lignes";
220  $sql .= " WHERE fk_prelevement_bons = ".((int) $this->id);
221  $sql .= " AND fk_soc =".((int) $client_id);
222  $sql .= " AND code_banque = '".$this->db->escape($code_banque)."'";
223  $sql .= " AND code_guichet = '".$this->db->escape($code_guichet)."'";
224  $sql .= " AND number = '".$this->db->escape($number)."'";
225 
226  $resql = $this->db->query($sql);
227  if ($resql) {
228  $num = $this->db->num_rows($resql);
229  } else {
230  $result = -1;
231  }
232  } else {
233  /*
234  * No aggregate
235  */
236  $sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement_lignes (";
237  $sql .= "fk_prelevement_bons";
238  $sql .= ", fk_soc";
239  $sql .= ", client_nom";
240  $sql .= ", amount";
241  $sql .= ", code_banque";
242  $sql .= ", code_guichet";
243  $sql .= ", number";
244  $sql .= ", cle_rib";
245  $sql .= ") VALUES (";
246  $sql .= $this->id;
247  $sql .= ", ".((int) $client_id);
248  $sql .= ", '".$this->db->escape($client_nom)."'";
249  $sql .= ", ".((float) price2num($amount));
250  $sql .= ", '".$this->db->escape($code_banque)."'";
251  $sql .= ", '".$this->db->escape($code_guichet)."'";
252  $sql .= ", '".$this->db->escape($number)."'";
253  $sql .= ", '".$this->db->escape($number_key)."'";
254  $sql .= ")";
255 
256  if ($this->db->query($sql)) {
257  $line_id = $this->db->last_insert_id(MAIN_DB_PREFIX."prelevement_lignes");
258  $result = 0;
259  } else {
260  $this->errors[] = get_class($this)."::addline Error -2 ".$this->db->lasterror;
261  dol_syslog(get_class($this)."::addline Error -2");
262  $result = -2;
263  }
264  }
265 
266  return $result;
267  }
268 
275  public function getErrorString($error)
276  {
277  global $langs;
278 
279  $errors = array();
280 
281  $errors[1027] = $langs->trans("DateInvalid");
282 
283  return $errors[abs($error)];
284  }
285 
293  public function fetch($rowid, $ref = '')
294  {
295  global $conf;
296 
297  $sql = "SELECT p.rowid, p.ref, p.amount, p.note";
298  $sql .= ", p.datec as dc";
299  $sql .= ", p.date_trans as date_trans";
300  $sql .= ", p.method_trans, p.fk_user_trans";
301  $sql .= ", p.date_credit as date_credit";
302  $sql .= ", p.fk_user_credit";
303  $sql .= ", p.type";
304  $sql .= ", p.statut as status";
305  $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons as p";
306  $sql .= " WHERE p.entity IN (".getEntity('invoice').")";
307  if ($rowid > 0) {
308  $sql .= " AND p.rowid = ".((int) $rowid);
309  } else {
310  $sql .= " AND p.ref = '".$this->db->escape($ref)."'";
311  }
312 
313  dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
314  $result = $this->db->query($sql);
315  if ($result) {
316  if ($this->db->num_rows($result)) {
317  $obj = $this->db->fetch_object($result);
318 
319  $this->id = $obj->rowid;
320  $this->ref = $obj->ref;
321  $this->amount = $obj->amount;
322  $this->note = $obj->note;
323  $this->datec = $this->db->jdate($obj->dc);
324 
325  $this->date_trans = $this->db->jdate($obj->date_trans);
326  $this->method_trans = $obj->method_trans;
327  $this->user_trans = $obj->fk_user_trans;
328 
329  $this->date_credit = $this->db->jdate($obj->date_credit);
330  $this->user_credit = $obj->fk_user_credit;
331 
332  $this->type = $obj->type;
333 
334  $this->status = $obj->status;
335  $this->statut = $obj->status; // For backward compatibility
336 
337  $this->fetched = 1;
338 
339  return 1;
340  } else {
341  dol_syslog(get_class($this)."::Fetch Erreur aucune ligne retournee");
342  return -1;
343  }
344  } else {
345  return -2;
346  }
347  }
348 
349  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
357  public function set_infocredit($user, $date)
358  {
359  // phpcs:enable
360  global $conf, $langs;
361 
362  $error = 0;
363 
364  if ($this->fetched == 1) {
365  if ($date < $this->date_trans) {
366  $langs->load("errors");
367  $this->error = $langs->trans('ErrorDateOfMovementLowerThanDateOfFileTransmission');
368  dol_syslog("bon-prelevment::set_infocredit 1027 ".$this->error);
369  return -1027;
370  }
371 
372  $this->db->begin();
373 
374  $sql = " UPDATE ".MAIN_DB_PREFIX."prelevement_bons ";
375  $sql .= " SET fk_user_credit = ".$user->id;
376  $sql .= ", statut = ".self::STATUS_CREDITED;
377  $sql .= ", date_credit = '".$this->db->idate($date)."'";
378  $sql .= " WHERE rowid=".((int) $this->id);
379  $sql .= " AND entity = ".((int) $conf->entity);
380  $sql .= " AND statut = ".self::STATUS_TRANSFERED;
381 
382  $resql = $this->db->query($sql);
383  if ($resql) {
384  $langs->load('withdrawals');
385  $subject = $langs->trans("InfoCreditSubject", $this->ref);
386  $message = $langs->trans("InfoCreditMessage", $this->ref, dol_print_date($date, 'dayhour'));
387 
388  //Add payment of withdrawal into bank
389  $bankaccount = ($this->type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT);
390  $facs = array();
391  $amounts = array();
392  $amountsperthirdparty = array();
393 
394  $facs = $this->getListInvoices(1);
395 
396  // Loop on each invoice. $facs=array(0=>id, 1=>amount requested)
397  $num = count($facs);
398  for ($i = 0; $i < $num; $i++) {
399  if ($this->type == 'bank-transfer') {
400  $fac = new FactureFournisseur($this->db);
401  } else {
402  $fac = new Facture($this->db);
403  }
404 
405  $result = $fac->fetch($facs[$i][0]);
406 
407  $amounts[$fac->id] = $facs[$i][1];
408  $amountsperthirdparty[$fac->socid][$fac->id] = $facs[$i][1];
409 
410  $totalpaid = $fac->getSommePaiement();
411  $totalcreditnotes = $fac->getSumCreditNotesUsed();
412  $totaldeposits = $fac->getSumDepositsUsed();
413  $alreadypayed = $totalpaid + $totalcreditnotes + $totaldeposits;
414 
415  // @TODO Move this after creation of payment
416  if (price2num($alreadypayed + $facs[$i][1], 'MT') == $fac->total_ttc) {
417  $result = $fac->setPaid($user);
418  if ($result < 0) {
419  $this->error = $fac->error;
420  $this->errors = $fac->errors;
421  }
422  }
423  }
424  //var_dump($amountsperthirdparty);exit;
425 
426  // Make one payment per customer
427  foreach ($amountsperthirdparty as $thirdpartyid => $cursoramounts) {
428  if ($this->type == 'bank-transfer') {
429  $paiement = new PaiementFourn($this->db);
430  } else {
431  $paiement = new Paiement($this->db);
432  }
433  $paiement->datepaye = $date;
434  $paiement->amounts = $cursoramounts; // Array with detail of dispatching of payments for each invoice
435 
436  if ($this->type == 'bank-transfer') {
437  $paiement->paiementid = 2;
438  $paiement->paiementcode = 'VIR';
439  } else {
440  $paiement->paiementid = 3;
441  $paiement->paiementcode = 'PRE';
442  }
443 
444  $paiement->num_payment = $this->ref; // Set ref of direct debit note
445  $paiement->id_prelevement = $this->id;
446 
447  $paiement_id = $paiement->create($user); // This use ->paiementid, that is ID of payment mode
448  if ($paiement_id < 0) {
449  $error++;
450  $this->error = $paiement->error;
451  $this->errors = $paiement->errors;
452  dol_syslog(get_class($this)."::set_infocredit AddPayment Error ".$this->error);
453  } else {
454  if ($this->type == 'bank-transfer') {
455  $modeforaddpayment = 'payment_supplier';
456  $labelforaddpayment = '(BankTransferPayment)';
457  } else {
458  $modeforaddpayment = 'payment';
459  $labelforaddpayment = '(WithdrawalPayment)';
460  }
461 
462  $result = $paiement->addPaymentToBank($user, $modeforaddpayment, $labelforaddpayment, $bankaccount, '', '');
463  if ($result < 0) {
464  $error++;
465  $this->error = $paiement->error;
466  $this->errors = $paiement->errors;
467  dol_syslog(get_class($this)."::set_infocredit AddPaymentToBank Error ".$this->error);
468  }
469  }
470  }
471 
472  // Update withdrawal line
473  // TODO: Translate to ligneprelevement.class.php
474  if (!$error) {
475  $sql = " UPDATE ".MAIN_DB_PREFIX."prelevement_lignes";
476  $sql .= " SET statut = 2";
477  $sql .= " WHERE fk_prelevement_bons = ".((int) $this->id);
478 
479  if (!$this->db->query($sql)) {
480  dol_syslog(get_class($this)."::set_infocredit Update lines Error");
481  $error++;
482  }
483  }
484  } else {
485  $this->error = $this->db->lasterror();
486  dol_syslog(get_class($this)."::set_infocredit Update Bons Error");
487  $error++;
488  }
489 
490  /*
491  * End of procedure
492  */
493  if ($error == 0) {
494  $this->date_credit = $date;
495  $this->statut = self::STATUS_CREDITED;
496 
497  $this->db->commit();
498  return 0;
499  } else {
500  $this->db->rollback();
501  return -1;
502  }
503  } else {
504  return -1026;
505  }
506  }
507 
508  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
517  public function set_infotrans($user, $date, $method)
518  {
519  // phpcs:enable
520  global $conf, $langs;
521 
522  $error = 0;
523 
524  dol_syslog(get_class($this)."::set_infotrans Start", LOG_INFO);
525  if ($this->db->begin()) {
526  $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_bons ";
527  $sql .= " SET fk_user_trans = ".$user->id;
528  $sql .= " , date_trans = '".$this->db->idate($date)."'";
529  $sql .= " , method_trans = ".((int) $method);
530  $sql .= " , statut = ".self::STATUS_TRANSFERED;
531  $sql .= " WHERE rowid = ".((int) $this->id);
532  $sql .= " AND entity = ".((int) $conf->entity);
533  $sql .= " AND statut = 0";
534 
535  if ($this->db->query($sql)) {
536  $this->method_trans = $method;
537  $langs->load('withdrawals');
538  $subject = $langs->trans("InfoTransSubject", $this->ref);
539  $message = $langs->trans("InfoTransMessage", $this->ref, dolGetFirstLastname($user->firstname, $user->lastname));
540  $message .= $langs->trans("InfoTransData", price($this->amount), $this->methodes_trans[$this->method_trans], dol_print_date($date, 'day'));
541 
542  // TODO Call trigger to create a notification using notification module
543  } else {
544  $error++;
545  }
546 
547  if ($error == 0) {
548  $this->date_trans = $date;
549  $this->statut = 1;
550  $this->user_trans = $user->id;
551  $this->db->commit();
552 
553  return 0;
554  } else {
555  $this->db->rollback();
556  dol_syslog(get_class($this)."::set_infotrans ROLLBACK", LOG_ERR);
557 
558  return -1;
559  }
560  } else {
561  dol_syslog(get_class($this)."::set_infotrans Ouverture transaction SQL impossible", LOG_CRIT);
562  return -2;
563  }
564  }
565 
572  private function getListInvoices($amounts = 0)
573  {
574  global $conf;
575 
576  $arr = array();
577 
578  /*
579  * Returns all invoices presented within same order
580  */
581  $sql = "SELECT ";
582  if ($this->type == 'bank-transfer') {
583  $sql .= " pf.fk_facture_fourn";
584  } else {
585  $sql .= " pf.fk_facture";
586  }
587  if ($amounts) {
588  $sql .= ", SUM(pl.amount)";
589  }
590  $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons as p";
591  $sql .= " , ".MAIN_DB_PREFIX."prelevement_lignes as pl";
592  $sql .= " , ".MAIN_DB_PREFIX."prelevement as pf";
593  $sql .= " WHERE pf.fk_prelevement_lignes = pl.rowid";
594  $sql .= " AND pl.fk_prelevement_bons = p.rowid";
595  $sql .= " AND p.rowid = ".((int) $this->id);
596  $sql .= " AND p.entity = ".((int) $conf->entity);
597  if ($amounts) {
598  if ($this->type == 'bank-transfer') {
599  $sql .= " GROUP BY fk_facture_fourn";
600  } else {
601  $sql .= " GROUP BY fk_facture";
602  }
603  }
604 
605  $resql = $this->db->query($sql);
606  if ($resql) {
607  $num = $this->db->num_rows($resql);
608 
609  if ($num) {
610  $i = 0;
611  while ($i < $num) {
612  $row = $this->db->fetch_row($resql);
613  if (!$amounts) {
614  $arr[$i] = $row[0];
615  } else {
616  $arr[$i] = array(
617  $row[0],
618  $row[1]
619  );
620  }
621  $i++;
622  }
623  }
624  $this->db->free($resql);
625  } else {
626  dol_syslog(get_class($this)."::getListInvoices Erreur");
627  }
628 
629  return $arr;
630  }
631 
632  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
639  public function SommeAPrelever($mode = 'direct-debit')
640  {
641  // phpcs:enable
642  global $conf;
643 
644  $sql = "SELECT sum(pfd.amount) as nb";
645  if ($mode != 'bank-transfer') {
646  $sql .= " FROM ".MAIN_DB_PREFIX."facture as f,";
647  } else {
648  $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f,";
649  }
650  $sql .= " ".MAIN_DB_PREFIX."prelevement_demande as pfd";
651  $sql .= " WHERE f.entity IN (".getEntity('invoice').")";
652  if (empty($conf->global->WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS)) {
653  $sql .= " AND f.fk_statut = ".Facture::STATUS_VALIDATED;
654  }
655  if ($mode != 'bank-transfer') {
656  $sql .= " AND f.rowid = pfd.fk_facture";
657  } else {
658  $sql .= " AND f.rowid = pfd.fk_facture_fourn";
659  }
660  $sql .= " AND f.paye = 0";
661  $sql .= " AND pfd.traite = 0";
662  $sql .= " AND pfd.ext_payment_id IS NULL";
663  $sql .= " AND f.total_ttc > 0";
664 
665  $resql = $this->db->query($sql);
666  if ($resql) {
667  $obj = $this->db->fetch_object($resql);
668 
669  $this->db->free($resql);
670 
671  return $obj->nb;
672  } else {
673  $error = 1;
674  dol_syslog(get_class($this)."::SommeAPrelever Erreur -1");
675  dol_syslog($this->db->error());
676 
677  return -1;
678  }
679  }
680 
687  public function nbOfInvoiceToPay($mode = 'direct-debit')
688  {
689  return $this->NbFactureAPrelever($mode);
690  }
691 
692  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
699  public function NbFactureAPrelever($type = 'direct-debit')
700  {
701  // phpcs:enable
702  global $conf;
703 
704  $sql = "SELECT count(f.rowid) as nb";
705  if ($type == 'bank-transfer') {
706  $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
707  } else {
708  $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
709  }
710  $sql .= ", ".MAIN_DB_PREFIX."prelevement_demande as pfd";
711  $sql .= " WHERE f.entity IN (".getEntity('invoice').")";
712  if (empty($conf->global->WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS)) {
713  $sql .= " AND f.fk_statut = ".Facture::STATUS_VALIDATED;
714  }
715  if ($type == 'bank-transfer') {
716  $sql .= " AND f.rowid = pfd.fk_facture_fourn";
717  } else {
718  $sql .= " AND f.rowid = pfd.fk_facture";
719  }
720  $sql .= " AND pfd.traite = 0";
721  $sql .= " AND pfd.ext_payment_id IS NULL";
722  $sql .= " AND f.total_ttc > 0";
723 
724  dol_syslog(get_class($this)."::NbFactureAPrelever");
725  $resql = $this->db->query($sql);
726 
727  if ($resql) {
728  $obj = $this->db->fetch_object($resql);
729 
730  $this->db->free($resql);
731 
732  return $obj->nb;
733  } else {
734  $this->error = get_class($this)."::NbFactureAPrelever Erreur -1 sql=".$this->db->error();
735  return -1;
736  }
737  }
738 
739 
740  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
754  public function create($banque = 0, $agence = 0, $mode = 'real', $format = 'ALL', $executiondate = '', $notrigger = 0, $type = 'direct-debit')
755  {
756  // phpcs:enable
757  global $conf, $langs, $user;
758 
759  dol_syslog(__METHOD__."::Bank=".$banque." Office=".$agence." mode=".$mode." format=".$format, LOG_DEBUG);
760 
761  require_once DOL_DOCUMENT_ROOT."/compta/facture/class/facture.class.php";
762  require_once DOL_DOCUMENT_ROOT."/societe/class/societe.class.php";
763 
764  if ($type != 'bank-transfer') {
765  if (empty($format)) {
766  $this->error = 'ErrorBadParametersForDirectDebitFileCreate';
767  return -1;
768  }
769  }
770 
771  $error = 0;
772 
773  $datetimeprev = dol_now('gmt');
774  //Choice the date of the execution direct debit
775  if (!empty($executiondate)) {
776  $datetimeprev = $executiondate;
777  }
778 
779  $month = dol_print_date($datetimeprev, "%m", 'gmt');
780  $year = dol_print_date($datetimeprev, "%Y", 'gmt');
781 
782  $this->invoice_in_error = array();
783  $this->thirdparty_in_error = array();
784 
785  // Read invoices
786  $factures = array();
787  $factures_prev = array();
788  $factures_result = array();
789  $factures_prev_id = array();
790  $factures_errors = array();
791 
792  if (!$error) {
793  $sql = "SELECT f.rowid, pfd.rowid as pfdrowid, f.fk_soc";
794  $sql .= ", pfd.code_banque, pfd.code_guichet, pfd.number, pfd.cle_rib";
795  $sql .= ", pfd.amount";
796  $sql .= ", s.nom as name";
797  if ($type != 'bank-transfer') {
798  $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
799  } else {
800  $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
801  }
802  $sql .= ", ".MAIN_DB_PREFIX."societe as s";
803  $sql .= ", ".MAIN_DB_PREFIX."prelevement_demande as pfd";
804  $sql .= " WHERE f.entity IN (".getEntity('invoice').')';
805  if ($type != 'bank-transfer') {
806  $sql .= " AND f.rowid = pfd.fk_facture";
807  } else {
808  $sql .= " AND f.rowid = pfd.fk_facture_fourn";
809  }
810  $sql .= " AND s.rowid = f.fk_soc";
811  $sql .= " AND f.fk_statut = 1"; // Invoice validated
812  $sql .= " AND f.paye = 0";
813  $sql .= " AND pfd.traite = 0";
814  $sql .= " AND f.total_ttc > 0";
815  $sql .= " AND pfd.ext_payment_id IS NULL";
816 
817  dol_syslog(__METHOD__."::Read invoices,", LOG_DEBUG);
818 
819  $resql = $this->db->query($sql);
820  if ($resql) {
821  $num = $this->db->num_rows($resql);
822  $i = 0;
823 
824  while ($i < $num) {
825  $row = $this->db->fetch_row($resql);
826  $factures[$i] = $row; // All fields
827  if ($row[7] == 0) {
828  $error++;
829  dol_syslog(__METHOD__."::Read invoices error Found a null invoice", LOG_ERR);
830  $this->invoice_in_error[$row[0]] = "Error for invoice id ".$row[0].", found a null amount";
831  break;
832  }
833  $i++;
834  }
835  $this->db->free($resql);
836  dol_syslog(__METHOD__."::Read invoices, ".$i." invoices to withdraw", LOG_DEBUG);
837  } else {
838  $error++;
839  dol_syslog(__METHOD__."::Read invoices error ".$this->db->error(), LOG_ERR);
840  }
841  }
842 
843  if (!$error) {
844  require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php';
845  $soc = new Societe($this->db);
846 
847  // Check BAN
848  $i = 0;
849  dol_syslog(__METHOD__."::Check BAN", LOG_DEBUG);
850 
851  if (count($factures) > 0) {
852  foreach ($factures as $key => $fac) {
853  if ($type != 'bank-transfer') {
854  $tmpinvoice = new Facture($this->db);
855  } else {
856  $tmpinvoice = new FactureFournisseur($this->db);
857  }
858  $resfetch = $tmpinvoice->fetch($fac[0]);
859  if ($resfetch >= 0) { // Field 0 of $fac is rowid of invoice
860  if ($soc->fetch($tmpinvoice->socid) >= 0) {
861  $bac = new CompanyBankAccount($this->db);
862  $bac->fetch(0, $soc->id);
863 
864  if ($type != 'bank-transfer') {
865  if ($format == 'FRST' && $bac->frstrecur != 'FRST') {
866  continue;
867  }
868  if ($format == 'RCUR' && ($bac->frstrecur != 'RCUR' && $bac->frstrecur != 'RECUR')) {
869  continue;
870  }
871  }
872 
873  if ($bac->verif() >= 1) {
874  $factures_prev[$i] = $fac;
875  /* second array necessary for BonPrelevement */
876  $factures_prev_id[$i] = $fac[0];
877  $i++;
878  //dol_syslog(__METHOD__."::RIB is ok", LOG_DEBUG);
879  } else {
880  dol_syslog(__METHOD__."::Check BAN Error on default bank number IBAN/BIC for thirdparty reported by verif() ".$tmpinvoice->socid." ".$soc->name, LOG_WARNING);
881  $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice ".$tmpinvoice->getNomUrl(0)." for thirdparty ".$soc->getNomUrl(0);
882  $this->thirdparty_in_error[$soc->id] = "Error on default bank number IBAN/BIC for invoice ".$tmpinvoice->getNomUrl(0)." for thirdparty ".$soc->getNomUrl(0);
883  }
884  } else {
885  dol_syslog(__METHOD__."::Check BAN Failed to read company", LOG_WARNING);
886  }
887  } else {
888  dol_syslog(__METHOD__."::Check BAN Failed to read invoice", LOG_WARNING);
889  }
890  }
891  } else {
892  dol_syslog(__METHOD__."::Check BAN No invoice to process", LOG_WARNING);
893  }
894  }
895 
896  $ok = 0;
897 
898  // Withdraw invoices in factures_prev array
899  $out = count($factures_prev)." invoices will be included.";
900  //print $out."\n";
901  dol_syslog($out);
902 
903  // Return warning
904  /*$i=0;
905  foreach ($this->thirdparty_in_error as $key => $val)
906  {
907  if ($i < 10) setEventMessages($val, null, 'warnings');
908  else setEventMessages('More error were discarded...', null, 'warnings');
909  $i++;
910  }*/
911 
912  if (count($factures_prev) > 0) {
913  if ($mode == 'real') {
914  $ok = 1;
915  } else {
916  print $langs->trans("ModeWarning"); // "Option for real mode was not set, we stop after this simulation\n";
917  }
918  }
919 
920  if ($ok) {
921  /*
922  * We are in real mode.
923  * We create order and build file into disk
924  */
925  $this->db->begin();
926 
927  $now = dol_now();
928  $ref = '';
929 
930  /*
931  * Process order generation
932  */
933  if (!$error) {
934  $ref = substr($year, -2).$month;
935 
936  $sql = "SELECT substring(ref from char_length(ref) - 1)"; // To extract "YYMMXX" from "TYYMMXX"
937  $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons";
938  $sql .= " WHERE ref LIKE '_".$this->db->escape($ref)."%'";
939  $sql .= " AND entity = ".((int) $conf->entity);
940  $sql .= " ORDER BY ref DESC LIMIT 1";
941 
942  dol_syslog(get_class($this)."::create", LOG_DEBUG);
943  $resql = $this->db->query($sql);
944 
945  if ($resql) {
946  $row = $this->db->fetch_row($resql);
947 
948  // Build the new ref
949  $ref = "T".$ref.sprintf("%02d", (intval($row[0]) + 1));
950 
951  // $conf->abc->dir_output may be:
952  // /home/ldestailleur/git/dolibarr_15.0/documents/abc/
953  // or
954  // /home/ldestailleur/git/dolibarr_15.0/documents/X/abc with X >= 2 with multicompany.
955  if ($type != 'bank-transfer') {
956  $dir = $conf->prelevement->dir_output.'/receipts';
957  } else {
958  $dir = $conf->paymentbybanktransfer->dir_output.'/receipts';
959  }
960  if (!is_dir($dir)) {
961  dol_mkdir($dir);
962  }
963 
964  $this->filename = $dir.'/'.$ref.'.xml';
965 
966  // Create withdraw receipt in database
967  $sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement_bons (";
968  $sql .= "ref, entity, datec, type";
969  $sql .= ") VALUES (";
970  $sql .= "'".$this->db->escape($ref)."'";
971  $sql .= ", ".((int) $conf->entity);
972  $sql .= ", '".$this->db->idate($now)."'";
973  $sql .= ", '".($type == 'bank-transfer' ? 'bank-transfer' : 'debit-order')."'";
974  $sql .= ")";
975 
976  $resql = $this->db->query($sql);
977  if ($resql) {
978  $prev_id = $this->db->last_insert_id(MAIN_DB_PREFIX."prelevement_bons");
979  $this->id = $prev_id;
980  $this->ref = $ref;
981  } else {
982  $error++;
983  dol_syslog(__METHOD__."::Create withdraw receipt ".$this->db->lasterror(), LOG_ERR);
984  }
985  } else {
986  $error++;
987  dol_syslog(__METHOD__."::Get last withdraw receipt ".$this->db->lasterror(), LOG_ERR);
988  }
989  }
990 
991  if (!$error) {
992  if ($type != 'bank-transfer') {
993  $fact = new Facture($this->db);
994  } else {
995  $fact = new FactureFournisseur($this->db);
996  }
997 
998  /*
999  * Create withdrawal receipt in database
1000  */
1001  if (count($factures_prev) > 0) {
1002  foreach ($factures_prev as $fac) { // Add a link in database for each invoice
1003  // Fetch invoice
1004  $result = $fact->fetch($fac[0]);
1005  if ($result < 0) {
1006  $this->error = 'ERRORBONPRELEVEMENT Failed to load invoice with id '.$fac[0];
1007  break;
1008  }
1009 
1010  /*
1011  * Add standing order. This add record into llx_prelevement_lignes
1012  *
1013  * $fac[0] : invoice_id
1014  * $fac[1] : ???
1015  * $fac[2] : third party id
1016  * $fac[3] : banque
1017  * $fac[4] : guichet
1018  * $fac[5] : number
1019  * $fac[6] : cle rib
1020  * $fac[7] : amount
1021  * $fac[8] : client nom
1022  */
1023  $ri = $this->AddFacture($fac[0], $fac[2], $fac[8], $fac[7], $fac[3], $fac[4], $fac[5], $fac[6], $type);
1024  if ($ri <> 0) {
1025  $error++;
1026  }
1027 
1028  // Update invoice requests as done
1029  $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_demande";
1030  $sql .= " SET traite = 1";
1031  $sql .= ", date_traite = '".$this->db->idate($now)."'";
1032  $sql .= ", fk_prelevement_bons = ".((int) $this->id);
1033  $sql .= " WHERE rowid = ".((int) $fac[1]);
1034 
1035  $resql = $this->db->query($sql);
1036  if (!$resql) {
1037  $error++;
1038  $this->errors[] = $this->db->lasterror();
1039  dol_syslog(__METHOD__."::Update Error=".$this->db->lasterror(), LOG_ERR);
1040  }
1041  }
1042  }
1043  }
1044 
1045  if (!$error) {
1046  /*
1047  * Create file of type='direct-debit' for direct debit order or type='bank-transfer' for credit transfer into a XML file
1048  */
1049 
1050  dol_syslog(__METHOD__."::Init direct debit or credit transfer file for ".count($factures_prev)." invoices", LOG_DEBUG);
1051 
1052  if (count($factures_prev) > 0) {
1053  $this->date_echeance = $datetimeprev;
1054  $this->reference_remise = $ref;
1055 
1056  $id = $conf->global->PRELEVEMENT_ID_BANKACCOUNT;
1057  if ($type == 'bank-transfer') {
1058  $id = $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT;
1059  }
1060  $account = new Account($this->db);
1061  if ($account->fetch($id) > 0) {
1062  $this->emetteur_code_banque = $account->code_banque;
1063  $this->emetteur_code_guichet = $account->code_guichet;
1064  $this->emetteur_numero_compte = $account->number;
1065  $this->emetteur_number_key = $account->cle_rib;
1066  $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
1067  $this->emetteur_iban = $account->iban;
1068  $this->emetteur_bic = $account->bic;
1069 
1070  $this->emetteur_ics = ($type == 'bank-transfer' ? $account->ics_transfer : $account->ics);
1071 
1072  $this->raison_sociale = $account->proprio;
1073  }
1074 
1075  $this->factures = $factures_prev_id;
1076  $this->context['factures_prev'] = $factures_prev;
1077 
1078  // Generation of direct debit or credti transfer file $this->filename (May be a SEPA file for european countries)
1079  // This also set the property $this->total with amount that is included into file
1080  $result = $this->generate($format, $executiondate, $type);
1081  if ($result < 0) {
1082  //var_dump($this->error);
1083  //var_dump($this->invoice_in_error);
1084  $error++;
1085  }
1086  }
1087  dol_syslog(__METHOD__."::End withdraw receipt, file ".$this->filename, LOG_DEBUG);
1088  }
1089  //var_dump($this->total);exit;
1090 
1091  /*
1092  * Update total defined after generation of file
1093  */
1094  if (!$error) {
1095  $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_bons";
1096  $sql .= " SET amount = ".price2num($this->total);
1097  $sql .= " WHERE rowid = ".((int) $this->id);
1098  $sql .= " AND entity = ".((int) $conf->entity);
1099 
1100  $resql = $this->db->query($sql);
1101  if (!$resql) {
1102  $error++;
1103  dol_syslog(__METHOD__."::Error update total: ".$this->db->error(), LOG_ERR);
1104  }
1105  }
1106 
1107  if (!$error && !$notrigger) {
1108  $triggername = 'DIRECT_DEBIT_ORDER_CREATE';
1109  if ($type != 'bank-transfer') {
1110  $triggername = 'CREDIT_TRANSFER_ORDER_CREATE';
1111  }
1112 
1113  // Call trigger
1114  $result = $this->call_trigger($triggername, $user);
1115  if ($result < 0) {
1116  $error++;
1117  }
1118  // End call triggers
1119  }
1120 
1121  if (!$error) {
1122  $this->db->commit();
1123  return count($factures_prev);
1124  } else {
1125  $this->db->rollback();
1126  return -1;
1127  }
1128  } else {
1129  return 0;
1130  }
1131  }
1132 
1133 
1141  public function delete($user = null, $notrigger = 0)
1142  {
1143  $this->db->begin();
1144 
1145  $error = 0;
1146  $resql1 = $resql2 = $resql3 = $resql4 = 0;
1147 
1148  if (!$notrigger) {
1149  $triggername = 'DIRECT_DEBIT_ORDER_DELETE';
1150  if ($this->type == 'bank-transfer') {
1151  $triggername = 'PAYMENTBYBANKTRANFER_DELETE';
1152  }
1153  // Call trigger
1154  $result = $this->call_trigger($triggername, $user);
1155  if ($result < 0) {
1156  $error++;
1157  }
1158  // End call triggers
1159  }
1160 
1161  if (!$error) {
1162  $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).")";
1163  $resql1 = $this->db->query($sql);
1164  if (!$resql1) {
1165  dol_print_error($this->db);
1166  }
1167  }
1168 
1169  if (!$error) {
1170  $sql = "DELETE FROM ".MAIN_DB_PREFIX."prelevement_lignes WHERE fk_prelevement_bons = ".((int) $this->id);
1171  $resql2 = $this->db->query($sql);
1172  if (!$resql2) {
1173  dol_print_error($this->db);
1174  }
1175  }
1176 
1177  if (!$error) {
1178  $sql = "DELETE FROM ".MAIN_DB_PREFIX."prelevement_bons WHERE rowid = ".((int) $this->id);
1179  $resql3 = $this->db->query($sql);
1180  if (!$resql3) {
1181  dol_print_error($this->db);
1182  }
1183  }
1184 
1185  if (!$error) {
1186  $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_demande SET fk_prelevement_bons = NULL, traite = 0 WHERE fk_prelevement_bons = ".((int) $this->id);
1187  $resql4 = $this->db->query($sql);
1188  if (!$resql4) {
1189  dol_print_error($this->db);
1190  }
1191  }
1192 
1193  if ($resql1 && $resql2 && $resql3 && $resql4 && !$error) {
1194  $this->db->commit();
1195  return 1;
1196  } else {
1197  $this->db->rollback();
1198  return -1;
1199  }
1200  }
1201 
1202 
1213  public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1214  {
1215  global $conf, $langs, $hookmanager;
1216 
1217  if (!empty($conf->dol_no_mouse_hover)) {
1218  $notooltip = 1; // Force disable tooltips
1219  }
1220 
1221  $result = '';
1222 
1223  $labeltoshow = 'PaymentByDirectDebit';
1224  if (!empty($this->type) && $this->type == 'bank-transfer') {
1225  $labeltoshow = 'PaymentByBankTransfer';
1226  }
1227 
1228  $label = '<u>'.$langs->trans($labeltoshow).'</u>';
1229  $label .= '<br>';
1230  $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
1231  if (isset($this->statut)) {
1232  $label .= '<br><b>'.$langs->trans("Status").":</b> ".$this->getLibStatut(5);
1233  }
1234 
1235  $url = DOL_URL_ROOT.'/compta/prelevement/card.php?id='.$this->id;
1236  if (!empty($this->type) && $this->type == 'bank-transfer') {
1237  $url = DOL_URL_ROOT.'/compta/prelevement/card.php?id='.$this->id;
1238  }
1239 
1240  if ($option != 'nolink') {
1241  // Add param to save lastsearch_values or not
1242  $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1243  if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1244  $add_save_lastsearch_values = 1;
1245  }
1246  if ($add_save_lastsearch_values) {
1247  $url .= '&save_lastsearch_values=1';
1248  }
1249  }
1250 
1251  $linkclose = '';
1252  if (empty($notooltip)) {
1253  if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
1254  $label = $langs->trans("ShowMyObject");
1255  $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
1256  }
1257  $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
1258  $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
1259  } else {
1260  $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1261  }
1262 
1263  $linkstart = '<a href="'.$url.'"';
1264  $linkstart .= $linkclose.'>';
1265  $linkend = '</a>';
1266 
1267  $result .= $linkstart;
1268  if ($withpicto) {
1269  $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);
1270  }
1271  if ($withpicto != 2) {
1272  $result .= $this->ref;
1273  }
1274  $result .= $linkend;
1275 
1276  global $action, $hookmanager;
1277  $hookmanager->initHooks(array('banktransferdao'));
1278  $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
1279  $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1280  if ($reshook > 0) {
1281  $result = $hookmanager->resPrint;
1282  } else {
1283  $result .= $hookmanager->resPrint;
1284  }
1285 
1286  return $result;
1287  }
1288 
1289 
1296  public function deleteNotificationById($rowid)
1297  {
1298  $sql = "DELETE FROM ".MAIN_DB_PREFIX."notify_def";
1299  $sql .= " WHERE rowid = ".((int) $rowid);
1300 
1301  if ($this->db->query($sql)) {
1302  return 0;
1303  } else {
1304  return -1;
1305  }
1306  }
1307 
1315  public function deleteNotification($user, $action)
1316  {
1317  if (is_object($user)) {
1318  $userid = $user->id;
1319  } else { // If user is an id
1320  $userid = $user;
1321  }
1322 
1323  $sql = "DELETE FROM ".MAIN_DB_PREFIX."notify_def";
1324  $sql .= " WHERE fk_user=".((int) $userid)." AND fk_action='".$this->db->escape($action)."'";
1325 
1326  if ($this->db->query($sql)) {
1327  return 0;
1328  } else {
1329  return -1;
1330  }
1331  }
1332 
1333  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1342  public function addNotification($db, $user, $action)
1343  {
1344  // phpcs:enable
1345  $result = 0;
1346 
1347  if (is_object($user)) {
1348  $userid = $user->id;
1349  } else { // If user is an id
1350  $userid = $user;
1351  }
1352 
1353  if ($this->deleteNotification($user, $action) == 0) {
1354  $now = dol_now();
1355 
1356  $sql = "INSERT INTO ".MAIN_DB_PREFIX."notify_def (datec,fk_user, fk_soc, fk_contact, fk_action)";
1357  $sql .= " VALUES ('".$this->db->idate($now)."', ".((int) $userid).", 'NULL', 'NULL', '".$this->db->escape($action)."')";
1358 
1359  dol_syslog("adnotiff: ".$sql);
1360  if ($this->db->query($sql)) {
1361  $result = 0;
1362  } else {
1363  $result = -1;
1364  dol_syslog(get_class($this)."::addNotification Error $result");
1365  }
1366  }
1367 
1368  return $result;
1369  }
1370 
1371 
1384  public function generate($format = 'ALL', $executiondate = '', $type = 'direct-debit')
1385  {
1386  global $conf, $langs, $mysoc;
1387 
1388  //TODO: Optimize code to read lines in a single function
1389 
1390  $result = 0;
1391 
1392  dol_syslog(get_class($this)."::generate build file=".$this->filename." type=".$type);
1393 
1394  $this->file = fopen($this->filename, "w");
1395  if (empty($this->file)) {
1396  $this->error = $langs->trans('ErrorFailedToOpenFile', $this->filename);
1397  return -1;
1398  }
1399 
1400  $found = 0;
1401  $this->total = 0;
1402 
1403  // Build file for European countries
1404  if ($mysoc->isInEEC()) {
1405  $found++;
1406 
1407  if ($type != 'bank-transfer') {
1411  // SEPA Initialisation
1412  $CrLf = "\n";
1413 
1414  $now = dol_now();
1415 
1416  $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S');
1417 
1418  $date_actu = $now;
1419  if (!empty($executiondate)) {
1420  $date_actu = $executiondate;
1421  }
1422 
1423  $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d');
1424  $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S');
1425  $fileDebiteurSection = '';
1426  $fileEmetteurSection = '';
1427  $i = 0;
1428 
1429  /*
1430  * Section Debitor (sepa Debiteurs bloc lines)
1431  */
1432 
1433  $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
1434  $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1435  $sql .= " f.ref as fac, pf.fk_facture as idfac,";
1436  $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
1437  $sql .= " FROM";
1438  $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,";
1439  $sql .= " ".MAIN_DB_PREFIX."facture as f,";
1440  $sql .= " ".MAIN_DB_PREFIX."prelevement as pf,";
1441  $sql .= " ".MAIN_DB_PREFIX."societe as soc,";
1442  $sql .= " ".MAIN_DB_PREFIX."c_country as c,";
1443  $sql .= " ".MAIN_DB_PREFIX."societe_rib as rib";
1444  $sql .= " WHERE pl.fk_prelevement_bons = ".((int) $this->id);
1445  $sql .= " AND pl.rowid = pf.fk_prelevement_lignes";
1446  $sql .= " AND pf.fk_facture = f.rowid";
1447  $sql .= " AND f.fk_soc = soc.rowid";
1448  $sql .= " AND soc.fk_pays = c.rowid";
1449  $sql .= " AND rib.fk_soc = f.fk_soc";
1450  $sql .= " AND rib.default_rib = 1";
1451  $sql .= " AND rib.type = 'ban'";
1452 
1453  // Define $fileDebiteurSection. One section DrctDbtTxInf per invoice.
1454  $resql = $this->db->query($sql);
1455  if ($resql) {
1456  $cachearraytotestduplicate = array();
1457 
1458  $num = $this->db->num_rows($resql);
1459  while ($i < $num) {
1460  $obj = $this->db->fetch_object($resql);
1461 
1462  if (!empty($cachearraytotestduplicate[$obj->idfac])) {
1463  $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
1464  $this->invoice_in_error[$obj->idfac] = $this->error;
1465  $result = -2;
1466  break;
1467  }
1468  $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
1469 
1470  $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
1471  $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->fac, $obj->idfac, $obj->iban, $obj->bic, $daterum, $obj->drum, $obj->rum, $type);
1472  $this->total = $this->total + $obj->somme;
1473  $i++;
1474  }
1475  $nbtotalDrctDbtTxInf = $i;
1476  } else {
1477  $this->error = $this->db->lasterror();
1478  fputs($this->file, 'ERROR DEBITOR '.$sql.$CrLf); // DEBITOR = Customers
1479  $result = -2;
1480  }
1481 
1482  // Define $fileEmetteurSection. Start of bloc PmtInf. Will contains all $nbtotalDrctDbtTxInf
1483  if ($result != -2) {
1484  $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type);
1485  }
1486 
1490  // SEPA File Header
1491  fputs($this->file, '<'.'?xml version="1.0" encoding="UTF-8" standalone="yes"?'.'>'.$CrLf);
1492  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);
1493  fputs($this->file, ' <CstmrDrctDbtInitn>'.$CrLf);
1494  // SEPA Group header
1495  fputs($this->file, ' <GrpHdr>'.$CrLf);
1496  fputs($this->file, ' <MsgId>'.('DD/'.$dateTime_YMD.'/REF'.$this->id).'</MsgId>'.$CrLf);
1497  fputs($this->file, ' <CreDtTm>'.$dateTime_ECMA.'</CreDtTm>'.$CrLf);
1498  fputs($this->file, ' <NbOfTxs>'.$i.'</NbOfTxs>'.$CrLf);
1499  fputs($this->file, ' <CtrlSum>'.$this->total.'</CtrlSum>'.$CrLf);
1500  fputs($this->file, ' <InitgPty>'.$CrLf);
1501  fputs($this->file, ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf);
1502  fputs($this->file, ' <Id>'.$CrLf);
1503  fputs($this->file, ' <PrvtId>'.$CrLf);
1504  fputs($this->file, ' <Othr>'.$CrLf);
1505  fputs($this->file, ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf);
1506  fputs($this->file, ' </Othr>'.$CrLf);
1507  fputs($this->file, ' </PrvtId>'.$CrLf);
1508  fputs($this->file, ' </Id>'.$CrLf);
1509  fputs($this->file, ' </InitgPty>'.$CrLf);
1510  fputs($this->file, ' </GrpHdr>'.$CrLf);
1511  // SEPA File Emetteur
1512  if ($result != -2) {
1513  fputs($this-> file, $fileEmetteurSection);
1514  }
1515  // SEPA File Debiteurs
1516  if ($result != -2) {
1517  fputs($this-> file, $fileDebiteurSection);
1518  }
1519  // SEPA FILE FOOTER
1520  fputs($this->file, ' </PmtInf>'.$CrLf);
1521  fputs($this->file, ' </CstmrDrctDbtInitn>'.$CrLf);
1522  fputs($this->file, '</Document>'.$CrLf);
1523  } else {
1527  // SEPA Initialisation
1528  $CrLf = "\n";
1529 
1530  $now = dol_now();
1531 
1532  $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S');
1533 
1534  $date_actu = $now;
1535  if (!empty($executiondate)) {
1536  $date_actu = $executiondate;
1537  }
1538 
1539  $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d');
1540  $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S');
1541  $fileCrediteurSection = '';
1542  $fileEmetteurSection = '';
1543  $i = 0;
1544 
1545  /*
1546  * Section Creditor (sepa Crediteurs bloc lines)
1547  */
1548 
1549  $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
1550  $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1551  $sql .= " f.ref as fac, pf.fk_facture_fourn as idfac, f.ref_supplier as fac_ref_supplier,";
1552  $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
1553  $sql .= " FROM";
1554  $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,";
1555  $sql .= " ".MAIN_DB_PREFIX."facture_fourn as f,";
1556  $sql .= " ".MAIN_DB_PREFIX."prelevement as pf,";
1557  $sql .= " ".MAIN_DB_PREFIX."societe as soc,";
1558  $sql .= " ".MAIN_DB_PREFIX."c_country as c,";
1559  $sql .= " ".MAIN_DB_PREFIX."societe_rib as rib";
1560  $sql .= " WHERE pl.fk_prelevement_bons = ".((int) $this->id);
1561  $sql .= " AND pl.rowid = pf.fk_prelevement_lignes";
1562  $sql .= " AND pf.fk_facture_fourn = f.rowid";
1563  $sql .= " AND f.fk_soc = soc.rowid";
1564  $sql .= " AND soc.fk_pays = c.rowid";
1565  $sql .= " AND rib.fk_soc = f.fk_soc";
1566  $sql .= " AND rib.default_rib = 1";
1567  $sql .= " AND rib.type = 'ban'";
1568 
1569  // Define $fileCrediteurSection. One section DrctDbtTxInf per invoice.
1570  $resql = $this->db->query($sql);
1571  if ($resql) {
1572  $cachearraytotestduplicate = array();
1573 
1574  $num = $this->db->num_rows($resql);
1575  while ($i < $num) {
1576  $obj = $this->db->fetch_object($resql);
1577 
1578  if (!empty($cachearraytotestduplicate[$obj->idfac])) {
1579  $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
1580  $this->invoice_in_error[$obj->idfac] = $this->error;
1581  $result = -2;
1582  break;
1583  }
1584  $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
1585 
1586  $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
1587  $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->fac.($obj->fac_ref_supplier ? ' '.$obj->fac_ref_supplier : ''), $obj->idfac, $obj->iban, $obj->bic, $daterum, $obj->drum, $obj->rum, $type);
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 CREDITOR '.$sql.$CrLf); // CREDITORS = Suppliers
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);
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.001.001.03" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'.$CrLf);
1609  fputs($this->file, ' <CstmrCdtTrfInitn>'.$CrLf);
1610  // SEPA Group header
1611  fputs($this->file, ' <GrpHdr>'.$CrLf);
1612  fputs($this->file, ' <MsgId>'.('TRF/'.$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 (mycompany)
1628  if ($result != -2) {
1629  fputs($this-> file, $fileEmetteurSection);
1630  }
1631  // SEPA File Creditors
1632  if ($result != -2) {
1633  fputs($this-> file, $fileCrediteurSection);
1634  }
1635  // SEPA FILE FOOTER
1636  fputs($this->file, ' </PmtInf>'.$CrLf);
1637  fputs($this->file, ' </CstmrCdtTrfInitn>'.$CrLf);
1638  fputs($this->file, '</Document>'.$CrLf);
1639  }
1640  }
1641 
1642  // Build file for Other Countries with unknow format
1643  if (!$found) {
1644  if ($type != 'bank-transfer') {
1645  $sql = "SELECT pl.amount";
1646  $sql .= " FROM";
1647  $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,";
1648  $sql .= " ".MAIN_DB_PREFIX."facture as f,";
1649  $sql .= " ".MAIN_DB_PREFIX."prelevement as pf";
1650  $sql .= " WHERE pl.fk_prelevement_bons = ".((int) $this->id);
1651  $sql .= " AND pl.rowid = pf.fk_prelevement_lignes";
1652  $sql .= " AND pf.fk_facture = f.rowid";
1653 
1654  // Lines
1655  $i = 0;
1656  $resql = $this->db->query($sql);
1657  if ($resql) {
1658  $num = $this->db->num_rows($resql);
1659 
1660  while ($i < $num) {
1661  $obj = $this->db->fetch_object($resql);
1662  $this->total = $this->total + $obj->amount;
1663 
1664  // TODO Write record into file
1665  $i++;
1666  }
1667  } else {
1668  $result = -2;
1669  }
1670  } else {
1671  $sql = "SELECT pl.amount";
1672  $sql .= " FROM";
1673  $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,";
1674  $sql .= " ".MAIN_DB_PREFIX."facture_fourn as f,";
1675  $sql .= " ".MAIN_DB_PREFIX."prelevement as pf";
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 
1680  // Lines
1681  $i = 0;
1682  $resql = $this->db->query($sql);
1683  if ($resql) {
1684  $num = $this->db->num_rows($resql);
1685 
1686  while ($i < $num) {
1687  $obj = $this->db->fetch_object($resql);
1688  $this->total = $this->total + $obj->amount;
1689 
1690  // TODO Write record into file
1691  $i++;
1692  }
1693  } else {
1694  $result = -2;
1695  }
1696  }
1697 
1698  $langs->load('withdrawals');
1699 
1700  // TODO Add here code to generate a generic file
1701  fputs($this->file, $langs->transnoentitiesnoconv('WithdrawalFileNotCapable', $mysoc->country_code));
1702  }
1703 
1704  fclose($this->file);
1705  if (!empty($conf->global->MAIN_UMASK)) {
1706  @chmod($this->filename, octdec($conf->global->MAIN_UMASK));
1707  }
1708 
1709  return $result;
1710  }
1711 
1712 
1721  public static function buildRumNumber($row_code_client, $row_datec, $row_drum)
1722  {
1723  global $langs;
1724 
1725  $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)
1726 
1727  // 3 char + '-' + 12 + '-' + id + '-' + code Must be lower than 32.
1728  return $pre.'-'.dol_print_date($row_datec, 'dayhourlogsmall').'-'.dol_trunc($row_drum.($row_code_client ? '-'.$row_code_client : ''), 13, 'right', 'UTF-8', 1);
1729  }
1730 
1731 
1732  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1749  public function EnregDestinataire($rowid, $client_nom, $rib_banque, $rib_guichet, $rib_number, $amount, $ref, $facid, $rib_dom = '', $type = 'direct-debit')
1750  {
1751  // phpcs:enable
1752  fputs($this->file, "06");
1753  fputs($this->file, "08"); // Prelevement ordinaire
1754 
1755  fputs($this->file, " "); // Zone Reservee B2
1756 
1757  fputs($this->file, $this->emetteur_ics); // ICS
1758 
1759  // Date d'echeance C1
1760 
1761  fputs($this->file, " ");
1762  fputs($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
1763  fputs($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
1764 
1765  // Raison Sociale Destinataire C2
1766 
1767  fputs($this->file, substr(strtoupper($client_nom)." ", 0, 24));
1768 
1769  // Domiciliation facultative D1
1770  $domiciliation = strtr($rib_dom, array(" " => "-", CHR(13) => " ", CHR(10) => ""));
1771  fputs($this->file, substr($domiciliation." ", 0, 24));
1772 
1773  // Zone Reservee D2
1774 
1775  fputs($this->file, substr(" ", 0, 8));
1776 
1777  // Code Guichet D3
1778 
1779  fputs($this->file, $rib_guichet);
1780 
1781  // Numero de compte D4
1782 
1783  fputs($this->file, substr("000000000000000".$rib_number, -11));
1784 
1785  // Zone E Montant
1786 
1787  $montant = (round($amount, 2) * 100);
1788 
1789  fputs($this->file, substr("000000000000000".$montant, -16));
1790 
1791  // Libelle F
1792 
1793  fputs($this->file, substr("*_".$ref."_RDVnet".$rowid." ", 0, 31));
1794 
1795  // Code etablissement G1
1796 
1797  fputs($this->file, $rib_banque);
1798 
1799  // Zone Reservee G2
1800 
1801  fputs($this->file, substr(" ", 0, 5));
1802 
1803  fputs($this->file, "\n");
1804  }
1805 
1806  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1831  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')
1832  {
1833  // phpcs:enable
1834  global $conf;
1835 
1836  include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
1837 
1838  $CrLf = "\n";
1839  $Rowing = sprintf("%010d", $row_idfac);
1840 
1841  // Define value for RUM
1842  // Example: RUM-CustomerCode-CustomerBankAccountId-01424448606 (note: Date is the timestamp of the date of creation of CustomerBankAccountId)
1843  $Rum = (empty($row_rum) ? $this->buildRumNumber($row_code_client, $row_datec, $row_drum) : $row_rum);
1844 
1845  // Define date of RUM signature
1846  $DtOfSgntr = dol_print_date($row_datec, '%Y-%m-%d');
1847 
1848  if ($type != 'bank-transfer') {
1849  // SEPA Paiement Information of buyer for Direct Debit
1850  $XML_DEBITOR = '';
1851  $XML_DEBITOR .= ' <DrctDbtTxInf>'.$CrLf;
1852  $XML_DEBITOR .= ' <PmtId>'.$CrLf;
1853  // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
1854  $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
1855  $XML_DEBITOR .= ' </PmtId>'.$CrLf;
1856  $XML_DEBITOR .= ' <InstdAmt Ccy="EUR">'.round($row_somme, 2).'</InstdAmt>'.$CrLf;
1857  $XML_DEBITOR .= ' <DrctDbtTx>'.$CrLf;
1858  $XML_DEBITOR .= ' <MndtRltdInf>'.$CrLf;
1859  $XML_DEBITOR .= ' <MndtId>'.$Rum.'</MndtId>'.$CrLf;
1860  $XML_DEBITOR .= ' <DtOfSgntr>'.$DtOfSgntr.'</DtOfSgntr>'.$CrLf;
1861  $XML_DEBITOR .= ' <AmdmntInd>false</AmdmntInd>'.$CrLf;
1862  $XML_DEBITOR .= ' </MndtRltdInf>'.$CrLf;
1863  $XML_DEBITOR .= ' </DrctDbtTx>'.$CrLf;
1864  $XML_DEBITOR .= ' <DbtrAgt>'.$CrLf;
1865  $XML_DEBITOR .= ' <FinInstnId>'.$CrLf;
1866  $XML_DEBITOR .= ' <BIC>'.$row_bic.'</BIC>'.$CrLf;
1867  $XML_DEBITOR .= ' </FinInstnId>'.$CrLf;
1868  $XML_DEBITOR .= ' </DbtrAgt>'.$CrLf;
1869  $XML_DEBITOR .= ' <Dbtr>'.$CrLf;
1870  $XML_DEBITOR .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))).'</Nm>'.$CrLf;
1871  $XML_DEBITOR .= ' <PstlAdr>'.$CrLf;
1872  $XML_DEBITOR .= ' <Ctry>'.$row_country_code.'</Ctry>'.$CrLf;
1873  $addressline1 = strtr($row_address, array(CHR(13) => ", ", CHR(10) => ""));
1874  $addressline2 = strtr($row_zip.(($row_zip && $row_town) ? ' ' : ''.$row_town), array(CHR(13) => ", ", CHR(10) => ""));
1875  if (trim($addressline1)) {
1876  $XML_DEBITOR .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
1877  }
1878  if (trim($addressline2)) {
1879  $XML_DEBITOR .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
1880  }
1881  $XML_DEBITOR .= ' </PstlAdr>'.$CrLf;
1882  $XML_DEBITOR .= ' </Dbtr>'.$CrLf;
1883  $XML_DEBITOR .= ' <DbtrAcct>'.$CrLf;
1884  $XML_DEBITOR .= ' <Id>'.$CrLf;
1885  $XML_DEBITOR .= ' <IBAN>'.preg_replace('/\s/', '', $row_iban).'</IBAN>'.$CrLf;
1886  $XML_DEBITOR .= ' </Id>'.$CrLf;
1887  $XML_DEBITOR .= ' </DbtrAcct>'.$CrLf;
1888  $XML_DEBITOR .= ' <RmtInf>'.$CrLf;
1889  // A string with some information on payment - 140 max
1890  $XML_DEBITOR .= ' <Ustrd>'.(($conf->global->PRELEVEMENT_USTRD != "") ? $conf->global->PRELEVEMENT_USTRD : dol_trunc($row_ref, 135, 'right', 'UTF-8', 1)).'</Ustrd>'.$CrLf; // 140 max
1891  $XML_DEBITOR .= ' </RmtInf>'.$CrLf;
1892  $XML_DEBITOR .= ' </DrctDbtTxInf>'.$CrLf;
1893  return $XML_DEBITOR;
1894  } else {
1895  // SEPA Paiement Information of seller for Credit Transfer
1896  $XML_CREDITOR = '';
1897  $XML_CREDITOR .= ' <CdtTrfTxInf>'.$CrLf;
1898  $XML_CREDITOR .= ' <PmtId>'.$CrLf;
1899  // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
1900  $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
1901  $XML_CREDITOR .= ' </PmtId>'.$CrLf;
1902  if (!empty($this->sepa_xml_pti_in_ctti)) {
1903  $XML_CREDITOR .= ' <PmtTpInf>' . $CrLf;
1904 
1905  // Can be 'NORM' for normal or 'HIGH' for high priority level
1906  if (!empty($conf->global->PAYMENTBYBANKTRANSFER_FORCE_HIGH_PRIORITY)) {
1907  $instrprty = 'HIGH';
1908  } else {
1909  $instrprty = 'NORM';
1910  }
1911  $XML_CREDITOR .= ' <InstrPrty>'.$instrprty.'</InstrPrty>' . $CrLf;
1912  $XML_CREDITOR .= ' <SvcLvl>' . $CrLf;
1913  $XML_CREDITOR .= ' <Cd>SEPA</Cd>' . $CrLf;
1914  $XML_CREDITOR .= ' </SvcLvl>' . $CrLf;
1915  $XML_CREDITOR .= ' <CtgyPurp>' . $CrLf;
1916  $XML_CREDITOR .= ' <Cd>CORE</Cd>' . $CrLf;
1917  $XML_CREDITOR .= ' </CtgyPurp>' . $CrLf;
1918  $XML_CREDITOR .= ' </PmtTpInf>' . $CrLf;
1919  }
1920  $XML_CREDITOR .= ' <Amt>'.$CrLf;
1921  $XML_CREDITOR .= ' <InstdAmt Ccy="EUR">'.round($row_somme, 2).'</InstdAmt>'.$CrLf;
1922  $XML_CREDITOR .= ' </Amt>'.$CrLf;
1923  /*
1924  $XML_CREDITOR .= ' <DrctDbtTx>'.$CrLf;
1925  $XML_CREDITOR .= ' <MndtRltdInf>'.$CrLf;
1926  $XML_CREDITOR .= ' <MndtId>'.$Rum.'</MndtId>'.$CrLf;
1927  $XML_CREDITOR .= ' <DtOfSgntr>'.$DtOfSgntr.'</DtOfSgntr>'.$CrLf;
1928  $XML_CREDITOR .= ' <AmdmntInd>false</AmdmntInd>'.$CrLf;
1929  $XML_CREDITOR .= ' </MndtRltdInf>'.$CrLf;
1930  $XML_CREDITOR .= ' </DrctDbtTx>'.$CrLf;
1931  */
1932  //$XML_CREDITOR .= ' <ChrgBr>SLEV</ChrgBr>'.$CrLf;
1933  $XML_CREDITOR .= ' <CdtrAgt>'.$CrLf;
1934  $XML_CREDITOR .= ' <FinInstnId>'.$CrLf;
1935  $XML_CREDITOR .= ' <BIC>'.$row_bic.'</BIC>'.$CrLf;
1936  $XML_CREDITOR .= ' </FinInstnId>'.$CrLf;
1937  $XML_CREDITOR .= ' </CdtrAgt>'.$CrLf;
1938  $XML_CREDITOR .= ' <Cdtr>'.$CrLf;
1939  $XML_CREDITOR .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))).'</Nm>'.$CrLf;
1940  $XML_CREDITOR .= ' <PstlAdr>'.$CrLf;
1941  $XML_CREDITOR .= ' <Ctry>'.$row_country_code.'</Ctry>'.$CrLf;
1942  $addressline1 = strtr($row_address, array(CHR(13) => ", ", CHR(10) => ""));
1943  $addressline2 = strtr($row_zip.(($row_zip && $row_town) ? ' ' : ''.$row_town), array(CHR(13) => ", ", CHR(10) => ""));
1944  if (trim($addressline1)) {
1945  $XML_CREDITOR .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
1946  }
1947  if (trim($addressline2)) {
1948  $XML_CREDITOR .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
1949  }
1950  $XML_CREDITOR .= ' </PstlAdr>'.$CrLf;
1951  $XML_CREDITOR .= ' </Cdtr>'.$CrLf;
1952  $XML_CREDITOR .= ' <CdtrAcct>'.$CrLf;
1953  $XML_CREDITOR .= ' <Id>'.$CrLf;
1954  $XML_CREDITOR .= ' <IBAN>'.preg_replace('/\s/', '', $row_iban).'</IBAN>'.$CrLf;
1955  $XML_CREDITOR .= ' </Id>'.$CrLf;
1956  $XML_CREDITOR .= ' </CdtrAcct>'.$CrLf;
1957  $XML_CREDITOR .= ' <RmtInf>'.$CrLf;
1958  // A string with some information on payment - 140 max
1959  $XML_CREDITOR .= ' <Ustrd>'.(($conf->global->PRELEVEMENT_USTRD != "") ? $conf->global->PRELEVEMENT_USTRD : dol_trunc($row_ref, 135, 'right', 'UTF-8', 1)).'</Ustrd>'.$CrLf; // 140 max
1960  $XML_CREDITOR .= ' </RmtInf>'.$CrLf;
1961  $XML_CREDITOR .= ' </CdtTrfTxInf>'.$CrLf;
1962  return $XML_CREDITOR;
1963  }
1964  }
1965 
1966 
1967  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1975  public function EnregEmetteur($type = 'direct-debit')
1976  {
1977  // phpcs:enable
1978  fputs($this->file, "03");
1979  fputs($this->file, "08"); // Prelevement ordinaire
1980 
1981  fputs($this->file, " "); // Zone Reservee B2
1982 
1983  fputs($this->file, $this->emetteur_ics); // ICS
1984 
1985  // Date d'echeance C1
1986 
1987  fputs($this->file, " ");
1988  fputs($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
1989  fputs($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
1990 
1991  // Raison Sociale C2
1992 
1993  fputs($this->file, substr($this->raison_sociale." ", 0, 24));
1994 
1995  // Reference de la remise creancier D1 sur 7 caracteres
1996 
1997  fputs($this->file, substr($this->reference_remise." ", 0, 7));
1998 
1999  // Zone Reservee D1-2
2000 
2001  fputs($this->file, substr(" ", 0, 17));
2002 
2003  // Zone Reservee D2
2004 
2005  fputs($this->file, substr(" ", 0, 2));
2006  fputs($this->file, "E");
2007  fputs($this->file, substr(" ", 0, 5));
2008 
2009  // Code Guichet D3
2010 
2011  fputs($this->file, $this->emetteur_code_guichet);
2012 
2013  // Numero de compte D4
2014 
2015  fputs($this->file, substr("000000000000000".$this->emetteur_numero_compte, -11));
2016 
2017  // Zone Reservee E
2018 
2019  fputs($this->file, substr(" ", 0, 16));
2020 
2021  // Zone Reservee F
2022 
2023  fputs($this->file, substr(" ", 0, 31));
2024 
2025  // Code etablissement
2026 
2027  fputs($this->file, $this->emetteur_code_banque);
2028 
2029  // Zone Reservee G
2030 
2031  fputs($this->file, substr(" ", 0, 5));
2032 
2033  fputs($this->file, "\n");
2034  }
2035 
2036  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2051  public function EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf = '\n', $format = 'FRST', $type = 'direct-debit')
2052  {
2053  // phpcs:enable
2054  // SEPA INITIALISATION
2055  global $conf;
2056 
2057  $dateTime_YMD = dol_print_date($ladate, '%Y%m%d');
2058  $dateTime_ETAD = dol_print_date($ladate, '%Y-%m-%d');
2059  $dateTime_YMDHMS = dol_print_date($ladate, '%Y-%m-%dT%H:%M:%S');
2060 
2061  // Get data of bank account
2062  //$id = $configuration->global->PRELEVEMENT_ID_BANKACCOUNT;
2063  $id = ($type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT);
2064  $account = new Account($this->db);
2065  if ($account->fetch($id) > 0) {
2066  $this->emetteur_code_banque = $account->code_banque;
2067  $this->emetteur_code_guichet = $account->code_guichet;
2068  $this->emetteur_numero_compte = $account->number;
2069  $this->emetteur_number_key = $account->cle_rib;
2070  $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
2071  $this->emetteur_iban = $account->iban;
2072  $this->emetteur_bic = $account->bic;
2073 
2074  $this->emetteur_ics = ($type == 'bank-transfer' ? $account->ics_transfer : $account->ics); // Ex: PRELEVEMENT_ICS = "FR78ZZZ123456";
2075 
2076  $this->raison_sociale = $account->proprio;
2077  }
2078 
2079  // Get pending payments
2080  $sql = "SELECT rowid, ref";
2081  $sql .= " FROM";
2082  $sql .= " ".MAIN_DB_PREFIX."prelevement_bons as pb";
2083  $sql .= " WHERE pb.rowid = ".((int) $this->id);
2084 
2085  $resql = $this->db->query($sql);
2086  if ($resql) {
2087  $obj = $this->db->fetch_object($resql);
2088 
2089  $country = explode(':', $configuration->global->MAIN_INFO_SOCIETE_COUNTRY);
2090  $IdBon = sprintf("%05d", $obj->rowid);
2091  $RefBon = $obj->ref;
2092 
2093  if ($type != 'bank-transfer') {
2094  // SEPA Paiement Information of my company for Direct Debit
2095  $XML_SEPA_INFO = '';
2096  $XML_SEPA_INFO .= ' <PmtInf>'.$CrLf;
2097  $XML_SEPA_INFO .= ' <PmtInfId>'.('DD/'.$dateTime_YMD.'/ID'.$IdBon.'-'.$RefBon).'</PmtInfId>'.$CrLf;
2098  $XML_SEPA_INFO .= ' <PmtMtd>DD</PmtMtd>'.$CrLf;
2099  $XML_SEPA_INFO .= ' <NbOfTxs>'.$nombre.'</NbOfTxs>'.$CrLf;
2100  $XML_SEPA_INFO .= ' <CtrlSum>'.$total.'</CtrlSum>'.$CrLf;
2101  $XML_SEPA_INFO .= ' <PmtTpInf>'.$CrLf;
2102  $XML_SEPA_INFO .= ' <SvcLvl>'.$CrLf;
2103  $XML_SEPA_INFO .= ' <Cd>SEPA</Cd>'.$CrLf;
2104  $XML_SEPA_INFO .= ' </SvcLvl>'.$CrLf;
2105  $XML_SEPA_INFO .= ' <LclInstrm>'.$CrLf;
2106  $XML_SEPA_INFO .= ' <Cd>CORE</Cd>'.$CrLf;
2107  $XML_SEPA_INFO .= ' </LclInstrm>'.$CrLf;
2108  $XML_SEPA_INFO .= ' <SeqTp>'.$format.'</SeqTp>'.$CrLf;
2109  $XML_SEPA_INFO .= ' </PmtTpInf>'.$CrLf;
2110  $XML_SEPA_INFO .= ' <ReqdColltnDt>'.$dateTime_ETAD.'</ReqdColltnDt>'.$CrLf;
2111  $XML_SEPA_INFO .= ' <Cdtr>'.$CrLf;
2112  $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2113  $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2114  $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2115  $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(CHR(13) => ", ", CHR(10) => ""));
2116  $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) => ""));
2117  if ($addressline1) {
2118  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2119  }
2120  if ($addressline2) {
2121  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2122  }
2123  $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2124  $XML_SEPA_INFO .= ' </Cdtr>'.$CrLf;
2125  $XML_SEPA_INFO .= ' <CdtrAcct>'.$CrLf;
2126  $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2127  $XML_SEPA_INFO .= ' <IBAN>'.preg_replace('/\s/', '', $this->emetteur_iban).'</IBAN>'.$CrLf;
2128  $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2129  $XML_SEPA_INFO .= ' </CdtrAcct>'.$CrLf;
2130  $XML_SEPA_INFO .= ' <CdtrAgt>'.$CrLf;
2131  $XML_SEPA_INFO .= ' <FinInstnId>'.$CrLf;
2132  $XML_SEPA_INFO .= ' <BIC>'.$this->emetteur_bic.'</BIC>'.$CrLf;
2133  $XML_SEPA_INFO .= ' </FinInstnId>'.$CrLf;
2134  $XML_SEPA_INFO .= ' </CdtrAgt>'.$CrLf;
2135  /* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf;
2136  $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2137  $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2138  $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2139  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ADDRESS), ' ')).'</AdrLine>'.$CrLf;
2140  $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;
2141  $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2142  $XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/
2143  $XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>'.$CrLf; // Field "Responsible of fees". Must be SLEV
2144  $XML_SEPA_INFO .= ' <CdtrSchmeId>'.$CrLf;
2145  $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2146  $XML_SEPA_INFO .= ' <PrvtId>'.$CrLf;
2147  $XML_SEPA_INFO .= ' <Othr>'.$CrLf;
2148  $XML_SEPA_INFO .= ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf;
2149  $XML_SEPA_INFO .= ' <SchmeNm>'.$CrLf;
2150  $XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>'.$CrLf;
2151  $XML_SEPA_INFO .= ' </SchmeNm>'.$CrLf;
2152  $XML_SEPA_INFO .= ' </Othr>'.$CrLf;
2153  $XML_SEPA_INFO .= ' </PrvtId>'.$CrLf;
2154  $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2155  $XML_SEPA_INFO .= ' </CdtrSchmeId>'.$CrLf;
2156  } else {
2157  // SEPA Paiement Information of my company for Credit Transfer
2158  $XML_SEPA_INFO = '';
2159  $XML_SEPA_INFO .= ' <PmtInf>'.$CrLf;
2160  $XML_SEPA_INFO .= ' <PmtInfId>'.('TRF/'.$dateTime_YMD.'/ID'.$IdBon.'-'.$RefBon).'</PmtInfId>'.$CrLf;
2161  $XML_SEPA_INFO .= ' <PmtMtd>TRF</PmtMtd>'.$CrLf;
2162  //$XML_SEPA_INFO .= ' <BtchBookg>False</BtchBookg>'.$CrLf;
2163  $XML_SEPA_INFO .= ' <NbOfTxs>'.$nombre.'</NbOfTxs>'.$CrLf;
2164  $XML_SEPA_INFO .= ' <CtrlSum>'.$total.'</CtrlSum>'.$CrLf;
2165  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.
2166  $XML_SEPA_INFO .= ' <PmtTpInf>' . $CrLf;
2167  $XML_SEPA_INFO .= ' <SvcLvl>' . $CrLf;
2168  $XML_SEPA_INFO .= ' <Cd>SEPA</Cd>' . $CrLf;
2169  $XML_SEPA_INFO .= ' </SvcLvl>' . $CrLf;
2170  $XML_SEPA_INFO .= ' <LclInstrm>' . $CrLf;
2171  $XML_SEPA_INFO .= ' <Cd>CORE</Cd>' . $CrLf;
2172  $XML_SEPA_INFO .= ' </LclInstrm>' . $CrLf;
2173  $XML_SEPA_INFO .= ' <SeqTp>' . $format . '</SeqTp>' . $CrLf;
2174  $XML_SEPA_INFO .= ' </PmtTpInf>' . $CrLf;
2175  }
2176  $XML_SEPA_INFO .= ' <ReqdExctnDt>'.dol_print_date($dateTime_ETAD, 'dayrfc').'</ReqdExctnDt>'.$CrLf;
2177  $XML_SEPA_INFO .= ' <Dbtr>'.$CrLf;
2178  $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2179  $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2180  $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2181  $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(CHR(13) => ", ", CHR(10) => ""));
2182  $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) => ""));
2183  if ($addressline1) {
2184  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2185  }
2186  if ($addressline2) {
2187  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2188  }
2189  $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2190  $XML_SEPA_INFO .= ' </Dbtr>'.$CrLf;
2191  $XML_SEPA_INFO .= ' <DbtrAcct>'.$CrLf;
2192  $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2193  $XML_SEPA_INFO .= ' <IBAN>'.preg_replace('/\s/', '', $this->emetteur_iban).'</IBAN>'.$CrLf;
2194  $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2195  $XML_SEPA_INFO .= ' </DbtrAcct>'.$CrLf;
2196  $XML_SEPA_INFO .= ' <DbtrAgt>'.$CrLf;
2197  $XML_SEPA_INFO .= ' <FinInstnId>'.$CrLf;
2198  $XML_SEPA_INFO .= ' <BIC>'.$this->emetteur_bic.'</BIC>'.$CrLf;
2199  $XML_SEPA_INFO .= ' </FinInstnId>'.$CrLf;
2200  $XML_SEPA_INFO .= ' </DbtrAgt>'.$CrLf;
2201  /* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf;
2202  $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2203  $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2204  $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2205  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ADDRESS), ' ')).'</AdrLine>'.$CrLf;
2206  $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;
2207  $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2208  $XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/
2209  $XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>'.$CrLf; // Field "Responsible of fees". Must be SLEV
2210  /*$XML_SEPA_INFO .= ' <CdtrSchmeId>'.$CrLf;
2211  $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2212  $XML_SEPA_INFO .= ' <PrvtId>'.$CrLf;
2213  $XML_SEPA_INFO .= ' <Othr>'.$CrLf;
2214  $XML_SEPA_INFO .= ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf;
2215  $XML_SEPA_INFO .= ' <SchmeNm>'.$CrLf;
2216  $XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>'.$CrLf;
2217  $XML_SEPA_INFO .= ' </SchmeNm>'.$CrLf;
2218  $XML_SEPA_INFO .= ' </Othr>'.$CrLf;
2219  $XML_SEPA_INFO .= ' </PrvtId>'.$CrLf;
2220  $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2221  $XML_SEPA_INFO .= ' </CdtrSchmeId>'.$CrLf;*/
2222  }
2223  } else {
2224  fputs($this->file, 'INCORRECT EMETTEUR '.$this->raison_sociale.$CrLf);
2225  $XML_SEPA_INFO = '';
2226  }
2227  return $XML_SEPA_INFO;
2228  }
2229 
2230  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2237  public function EnregTotal($total)
2238  {
2239  // phpcs:enable
2240  fputs($this->file, "08");
2241  fputs($this->file, "08"); // Prelevement ordinaire
2242 
2243  fputs($this->file, " "); // Zone Reservee B2
2244 
2245  fputs($this->file, $this->emetteur_ics); // ICS
2246 
2247  // Reserve C1
2248 
2249  fputs($this->file, substr(" ", 0, 12));
2250 
2251 
2252  // Raison Sociale C2
2253 
2254  fputs($this->file, substr(" ", 0, 24));
2255 
2256  // D1
2257 
2258  fputs($this->file, substr(" ", 0, 24));
2259 
2260  // Zone Reservee D2
2261 
2262  fputs($this->file, substr(" ", 0, 8));
2263 
2264  // Code Guichet D3
2265 
2266  fputs($this->file, substr(" ", 0, 5));
2267 
2268  // Numero de compte D4
2269 
2270  fputs($this->file, substr(" ", 0, 11));
2271 
2272  // Zone E Montant
2273 
2274  $montant = ($total * 100);
2275 
2276  fputs($this->file, substr("000000000000000".$montant, -16));
2277 
2278  // Zone Reservee F
2279 
2280  fputs($this->file, substr(" ", 0, 31));
2281 
2282  // Code etablissement
2283 
2284  fputs($this->file, substr(" ", 0, 5));
2285 
2286  // Zone Reservee F
2287 
2288  fputs($this->file, substr(" ", 0, 5));
2289 
2290  fputs($this->file, "\n");
2291  }
2292 
2299  public function getLibStatut($mode = 0)
2300  {
2301  return $this->LibStatut($this->statut, $mode);
2302  }
2303 
2304  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2312  public function LibStatut($status, $mode = 0)
2313  {
2314  // phpcs:enable
2315  if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
2316  global $langs;
2317  //$langs->load("mymodule");
2318  $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2319  $this->labelStatus[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2320  $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2321  $this->labelStatusShort[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2322  if ($this->type == 'bank-transfer') {
2323  $this->labelStatus[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2324  $this->labelStatusShort[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2325  } else {
2326  $this->labelStatus[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2327  $this->labelStatusShort[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2328  }
2329  }
2330 
2331  $statusType = 'status1';
2332  if ($status == self::STATUS_TRANSFERED) {
2333  $statusType = 'status3';
2334  }
2335  if ($status == self::STATUS_CREDITED || $status == self::STATUS_DEBITED) {
2336  $statusType = 'status6';
2337  }
2338 
2339  return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
2340  }
2341 
2342  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2350  public function load_board($user, $mode)
2351  {
2352  // phpcs:enable
2353  global $conf, $langs;
2354 
2355  if ($user->socid) {
2356  return -1; // protection pour eviter appel par utilisateur externe
2357  }
2358 
2359  /*
2360  if ($mode == 'direct_debit') {
2361  $sql = "SELECT b.rowid, f.datedue as datefin";
2362  $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
2363  $sql .= " WHERE f.entity IN (".getEntity('facture').")";
2364  $sql .= " AND f.total_ttc > 0";
2365  } else {
2366  $sql = "SELECT b.rowid, f.datedue as datefin";
2367  $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
2368  $sql .= " WHERE f.entity IN (".getEntity('facture_fourn').")";
2369  $sql .= " AND f.total_ttc > 0";
2370  }
2371 
2372  $resql = $this->db->query($sql);
2373  if ($resql) {
2374  $langs->load("banks");
2375  $now = dol_now();
2376 
2377  $response = new WorkboardResponse();
2378  if ($mode == 'direct_debit') {
2379  $response->warning_delay = $conf->prelevement->warning_delay / 60 / 60 / 24;
2380  $response->label = $langs->trans("PendingDirectDebitToComplete");
2381  $response->labelShort = $langs->trans("PendingDirectDebitToCompleteShort");
2382  $response->url = DOL_URL_ROOT.'/compta/prelevement/index.php?leftmenu=checks&mainmenu=bank';
2383  } else {
2384  $response->warning_delay = $conf->paymentbybanktransfer->warning_delay / 60 / 60 / 24;
2385  $response->label = $langs->trans("PendingCreditTransferToComplete");
2386  $response->labelShort = $langs->trans("PendingCreditTransferToCompleteShort");
2387  $response->url = DOL_URL_ROOT.'/compta/paymentbybanktransfer/index.php?leftmenu=checks&mainmenu=bank';
2388  }
2389  $response->img = img_object('', "payment");
2390 
2391  while ($obj = $this->db->fetch_object($resql)) {
2392  $response->nbtodo++;
2393 
2394  if ($this->db->jdate($obj->datefin) < ($now - $conf->withdraw->warning_delay)) {
2395  $response->nbtodolate++;
2396  }
2397  }
2398 
2399  $response->nbtodo = 0;
2400  $response->nbtodolate = 0;
2401  // Return workboard only if quantity is not 0
2402  if ($response->nbtodo) {
2403  return $response;
2404  } else {
2405  return 0;
2406  }
2407  } else {
2408  dol_print_error($this->db);
2409  $this->error = $this->db->error();
2410  return -1;
2411  }
2412  */
2413  return 0;
2414  }
2415 }
Societe
Class to manage third parties objects (customers, suppliers, prospects...)
Definition: societe.class.php:49
db
$conf db
API class for accounts.
Definition: inc.php:41
BonPrelevement\deleteNotificationById
deleteNotificationById($rowid)
Delete a notification def by id.
Definition: bonprelevement.class.php:1296
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:3949
BonPrelevement\fetch
fetch($rowid, $ref='')
Get object and lines from database.
Definition: bonprelevement.class.php:293
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:4993
ref
$object ref
Definition: info.php:78
BonPrelevement\EnregEmetteur
EnregEmetteur($type='direct-debit')
Write sender of request (me).
Definition: bonprelevement.class.php:1975
BonPrelevement\nbOfInvoiceToPay
nbOfInvoiceToPay($mode='direct-debit')
Get number of invoices waiting for payment.
Definition: bonprelevement.class.php:687
Facture
Class to manage invoices.
Definition: facture.class.php:60
CommonObject
Parent class of all other business classes (invoices, contracts, proposals, orders,...
Definition: commonobject.class.php:44
CompanyBankAccount
Class to manage bank accounts description of third parties.
Definition: companybankaccount.class.php:34
BonPrelevement\__construct
__construct($db)
Constructor.
Definition: bonprelevement.class.php:107
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:153
price2num
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
Definition: functions.lib.php:5823
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:2550
BonPrelevement\getErrorString
getErrorString($error)
Return error string.
Definition: bonprelevement.class.php:275
BonPrelevement
Class to manage withdrawal receipts.
Definition: bonprelevement.class.php:43
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')
Write recipient of request (customer)
Definition: bonprelevement.class.php:1831
BonPrelevement\getLibStatut
getLibStatut($mode=0)
Return status label of object.
Definition: bonprelevement.class.php:2299
dol_string_nospecial
dol_string_nospecial($str, $newstr='_', $badcharstoreplace='', $badcharstoremove='')
Clean a string from all punctuation characters to use it as a ref or login.
Definition: functions.lib.php:1397
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:1326
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:1721
$resql
if(isModEnabled('facture') &&!empty($user->rights->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') &&!empty($user->rights->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)) $resql
Social contributions to pay.
Definition: index.php:745
BonPrelevement\SommeAPrelever
SommeAPrelever($mode='direct-debit')
Returns amount waiting for direct debit payment or credit transfer payment.
Definition: bonprelevement.class.php:639
BonPrelevement\generate
generate($format='ALL', $executiondate='', $type='direct-debit')
Generate a direct debit or credit transfer file.
Definition: bonprelevement.class.php:1384
dol_syslog
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
Definition: functions.lib.php:1628
BonPrelevement\deleteNotification
deleteNotification($user, $action)
Delete a notification.
Definition: bonprelevement.class.php:1315
BonPrelevement\load_board
load_board($user, $mode)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
Definition: bonprelevement.class.php:2350
BonPrelevement\create
create($banque=0, $agence=0, $mode='real', $format='ALL', $executiondate='', $notrigger=0, $type='direct-debit')
Create a direct debit order or a credit transfer order TODO delete params banque and agence when not ...
Definition: bonprelevement.class.php:754
dolGetFirstLastname
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
Definition: functions.lib.php:8390
PaiementFourn
Class to manage payments for supplier invoices.
Definition: paiementfourn.class.php:38
Paiement
Class to manage payments of customer invoices.
Definition: paiement.class.php:42
BonPrelevement\LibStatut
LibStatut($status, $mode=0)
Return status label for a status.
Definition: bonprelevement.class.php:2312
BonPrelevement\EnregTotal
EnregTotal($total)
Write end.
Definition: bonprelevement.class.php:2237
BonPrelevement\EnregEmetteurSEPA
EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf='\n', $format='FRST', $type='direct-debit')
Write sender of request (me).
Definition: bonprelevement.class.php:2051
dolGetStatus
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
Definition: functions.lib.php:10740
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:4360
BonPrelevement\NbFactureAPrelever
NbFactureAPrelever($type='direct-debit')
Get number of invoices to pay.
Definition: bonprelevement.class.php:699
BonPrelevement\addNotification
addNotification($db, $user, $action)
Add a notification.
Definition: bonprelevement.class.php:1342
BonPrelevement\set_infocredit
set_infocredit($user, $date)
Set direct debit or credit transfer order to "paid" status.
Definition: bonprelevement.class.php:357
dol_now
dol_now($mode='auto')
Return date for now.
Definition: functions.lib.php:2951
BonPrelevement\set_infotrans
set_infotrans($user, $date, $method)
Set withdrawal to transmited status.
Definition: bonprelevement.class.php:517
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:209
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:5697
CommonObject\call_trigger
call_trigger($triggerName, $user)
Call trigger based on this instance.
Definition: commonobject.class.php:5806
dol_mkdir
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
Definition: functions.lib.php:6789
type
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:119
BonPrelevement\getListInvoices
getListInvoices($amounts=0)
Get invoice list.
Definition: bonprelevement.class.php:572
Account
Class to manage bank accounts.
Definition: account.class.php:39
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:1749
BonPrelevement\getNomUrl
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Returns clickable name (with picto)
Definition: bonprelevement.class.php:1213