dolibarr  x.y.z
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  } else {
457  $modeforaddpayment = 'payment';
458  }
459 
460  $result = $paiement->addPaymentToBank($user, $modeforaddpayment, '(WithdrawalPayment)', $bankaccount, '', '');
461  if ($result < 0) {
462  $error++;
463  $this->error = $paiement->error;
464  $this->errors = $paiement->errors;
465  dol_syslog(get_class($this)."::set_infocredit AddPaymentToBank Error ".$this->error);
466  }
467  }
468  }
469 
470  // Update withdrawal line
471  // TODO: Translate to ligneprelevement.class.php
472  if (!$error) {
473  $sql = " UPDATE ".MAIN_DB_PREFIX."prelevement_lignes";
474  $sql .= " SET statut = 2";
475  $sql .= " WHERE fk_prelevement_bons = ".((int) $this->id);
476 
477  if (!$this->db->query($sql)) {
478  dol_syslog(get_class($this)."::set_infocredit Update lines Error");
479  $error++;
480  }
481  }
482  } else {
483  $this->error = $this->db->lasterror();
484  dol_syslog(get_class($this)."::set_infocredit Update Bons Error");
485  $error++;
486  }
487 
488  /*
489  * End of procedure
490  */
491  if ($error == 0) {
492  $this->date_credit = $date;
493  $this->statut = self::STATUS_CREDITED;
494 
495  $this->db->commit();
496  return 0;
497  } else {
498  $this->db->rollback();
499  return -1;
500  }
501  } else {
502  return -1026;
503  }
504  }
505 
506  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
515  public function set_infotrans($user, $date, $method)
516  {
517  // phpcs:enable
518  global $conf, $langs;
519 
520  $error = 0;
521 
522  dol_syslog(get_class($this)."::set_infotrans Start", LOG_INFO);
523  if ($this->db->begin()) {
524  $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_bons ";
525  $sql .= " SET fk_user_trans = ".$user->id;
526  $sql .= " , date_trans = '".$this->db->idate($date)."'";
527  $sql .= " , method_trans = ".((int) $method);
528  $sql .= " , statut = ".self::STATUS_TRANSFERED;
529  $sql .= " WHERE rowid = ".((int) $this->id);
530  $sql .= " AND entity = ".((int) $conf->entity);
531  $sql .= " AND statut = 0";
532 
533  if ($this->db->query($sql)) {
534  $this->method_trans = $method;
535  $langs->load('withdrawals');
536  $subject = $langs->trans("InfoTransSubject", $this->ref);
537  $message = $langs->trans("InfoTransMessage", $this->ref, dolGetFirstLastname($user->firstname, $user->lastname));
538  $message .= $langs->trans("InfoTransData", price($this->amount), $this->methodes_trans[$this->method_trans], dol_print_date($date, 'day'));
539 
540  // TODO Call trigger to create a notification using notification module
541  } else {
542  $error++;
543  }
544 
545  if ($error == 0) {
546  $this->date_trans = $date;
547  $this->statut = 1;
548  $this->user_trans = $user->id;
549  $this->db->commit();
550 
551  return 0;
552  } else {
553  $this->db->rollback();
554  dol_syslog(get_class($this)."::set_infotrans ROLLBACK", LOG_ERR);
555 
556  return -1;
557  }
558  } else {
559  dol_syslog(get_class($this)."::set_infotrans Ouverture transaction SQL impossible", LOG_CRIT);
560  return -2;
561  }
562  }
563 
570  private function getListInvoices($amounts = 0)
571  {
572  global $conf;
573 
574  $arr = array();
575 
576  /*
577  * Returns all invoices presented within same order
578  */
579  $sql = "SELECT ";
580  if ($this->type == 'bank-transfer') {
581  $sql .= " pf.fk_facture_fourn";
582  } else {
583  $sql .= " pf.fk_facture";
584  }
585  if ($amounts) {
586  $sql .= ", SUM(pl.amount)";
587  }
588  $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons as p";
589  $sql .= " , ".MAIN_DB_PREFIX."prelevement_lignes as pl";
590  $sql .= " , ".MAIN_DB_PREFIX."prelevement as pf";
591  $sql .= " WHERE pf.fk_prelevement_lignes = pl.rowid";
592  $sql .= " AND pl.fk_prelevement_bons = p.rowid";
593  $sql .= " AND p.rowid = ".((int) $this->id);
594  $sql .= " AND p.entity = ".((int) $conf->entity);
595  if ($amounts) {
596  if ($this->type == 'bank-transfer') {
597  $sql .= " GROUP BY fk_facture_fourn";
598  } else {
599  $sql .= " GROUP BY fk_facture";
600  }
601  }
602 
603  $resql = $this->db->query($sql);
604  if ($resql) {
605  $num = $this->db->num_rows($resql);
606 
607  if ($num) {
608  $i = 0;
609  while ($i < $num) {
610  $row = $this->db->fetch_row($resql);
611  if (!$amounts) {
612  $arr[$i] = $row[0];
613  } else {
614  $arr[$i] = array(
615  $row[0],
616  $row[1]
617  );
618  }
619  $i++;
620  }
621  }
622  $this->db->free($resql);
623  } else {
624  dol_syslog(get_class($this)."::getListInvoices Erreur");
625  }
626 
627  return $arr;
628  }
629 
630  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
637  public function SommeAPrelever($mode = 'direct-debit')
638  {
639  // phpcs:enable
640  global $conf;
641 
642  $sql = "SELECT sum(pfd.amount) as nb";
643  if ($mode != 'bank-transfer') {
644  $sql .= " FROM ".MAIN_DB_PREFIX."facture as f,";
645  } else {
646  $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f,";
647  }
648  $sql .= " ".MAIN_DB_PREFIX."prelevement_demande as pfd";
649  $sql .= " WHERE f.entity IN (".getEntity('invoice').")";
650  if (empty($conf->global->WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS)) {
651  $sql .= " AND f.fk_statut = ".Facture::STATUS_VALIDATED;
652  }
653  if ($mode != 'bank-transfer') {
654  $sql .= " AND f.rowid = pfd.fk_facture";
655  } else {
656  $sql .= " AND f.rowid = pfd.fk_facture_fourn";
657  }
658  $sql .= " AND f.paye = 0";
659  $sql .= " AND pfd.traite = 0";
660  $sql .= " AND pfd.ext_payment_id IS NULL";
661  $sql .= " AND f.total_ttc > 0";
662 
663  $resql = $this->db->query($sql);
664  if ($resql) {
665  $obj = $this->db->fetch_object($resql);
666 
667  $this->db->free($resql);
668 
669  return $obj->nb;
670  } else {
671  $error = 1;
672  dol_syslog(get_class($this)."::SommeAPrelever Erreur -1");
673  dol_syslog($this->db->error());
674 
675  return -1;
676  }
677  }
678 
685  public function nbOfInvoiceToPay($mode = 'direct-debit')
686  {
687  return $this->NbFactureAPrelever($mode);
688  }
689 
690  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
697  public function NbFactureAPrelever($type = 'direct-debit')
698  {
699  // phpcs:enable
700  global $conf;
701 
702  $sql = "SELECT count(f.rowid) as nb";
703  if ($type == 'bank-transfer') {
704  $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
705  } else {
706  $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
707  }
708  $sql .= ", ".MAIN_DB_PREFIX."prelevement_demande as pfd";
709  $sql .= " WHERE f.entity IN (".getEntity('invoice').")";
710  if (empty($conf->global->WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS)) {
711  $sql .= " AND f.fk_statut = ".Facture::STATUS_VALIDATED;
712  }
713  if ($type == 'bank-transfer') {
714  $sql .= " AND f.rowid = pfd.fk_facture_fourn";
715  } else {
716  $sql .= " AND f.rowid = pfd.fk_facture";
717  }
718  $sql .= " AND pfd.traite = 0";
719  $sql .= " AND pfd.ext_payment_id IS NULL";
720  $sql .= " AND f.total_ttc > 0";
721 
722  dol_syslog(get_class($this)."::NbFactureAPrelever");
723  $resql = $this->db->query($sql);
724 
725  if ($resql) {
726  $obj = $this->db->fetch_object($resql);
727 
728  $this->db->free($resql);
729 
730  return $obj->nb;
731  } else {
732  $this->error = get_class($this)."::NbFactureAPrelever Erreur -1 sql=".$this->db->error();
733  return -1;
734  }
735  }
736 
737 
738  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
752  public function create($banque = 0, $agence = 0, $mode = 'real', $format = 'ALL', $executiondate = '', $notrigger = 0, $type = 'direct-debit')
753  {
754  // phpcs:enable
755  global $conf, $langs, $user;
756 
757  dol_syslog(__METHOD__."::Bank=".$banque." Office=".$agence." mode=".$mode." format=".$format, LOG_DEBUG);
758 
759  require_once DOL_DOCUMENT_ROOT."/compta/facture/class/facture.class.php";
760  require_once DOL_DOCUMENT_ROOT."/societe/class/societe.class.php";
761 
762  if ($type != 'bank-transfer') {
763  if (empty($format)) {
764  $this->error = 'ErrorBadParametersForDirectDebitFileCreate';
765  return -1;
766  }
767  }
768 
769  $error = 0;
770 
771  $datetimeprev = dol_now('gmt');
772  //Choice the date of the execution direct debit
773  if (!empty($executiondate)) {
774  $datetimeprev = $executiondate;
775  }
776 
777  $month = dol_print_date($datetimeprev, "%m", 'gmt');
778  $year = dol_print_date($datetimeprev, "%Y", 'gmt');
779 
780  $this->invoice_in_error = array();
781  $this->thirdparty_in_error = array();
782 
783  // Read invoices
784  $factures = array();
785  $factures_prev = array();
786  $factures_result = array();
787  $factures_prev_id = array();
788  $factures_errors = array();
789 
790  if (!$error) {
791  $sql = "SELECT f.rowid, pfd.rowid as pfdrowid, f.fk_soc";
792  $sql .= ", pfd.code_banque, pfd.code_guichet, pfd.number, pfd.cle_rib";
793  $sql .= ", pfd.amount";
794  $sql .= ", s.nom as name";
795  if ($type != 'bank-transfer') {
796  $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
797  } else {
798  $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
799  }
800  $sql .= ", ".MAIN_DB_PREFIX."societe as s";
801  $sql .= ", ".MAIN_DB_PREFIX."prelevement_demande as pfd";
802  $sql .= " WHERE f.entity IN (".getEntity('invoice').')';
803  if ($type != 'bank-transfer') {
804  $sql .= " AND f.rowid = pfd.fk_facture";
805  } else {
806  $sql .= " AND f.rowid = pfd.fk_facture_fourn";
807  }
808  $sql .= " AND s.rowid = f.fk_soc";
809  $sql .= " AND f.fk_statut = 1"; // Invoice validated
810  $sql .= " AND f.paye = 0";
811  $sql .= " AND pfd.traite = 0";
812  $sql .= " AND f.total_ttc > 0";
813  $sql .= " AND pfd.ext_payment_id IS NULL";
814 
815  dol_syslog(__METHOD__."::Read invoices,", LOG_DEBUG);
816 
817  $resql = $this->db->query($sql);
818  if ($resql) {
819  $num = $this->db->num_rows($resql);
820  $i = 0;
821 
822  while ($i < $num) {
823  $row = $this->db->fetch_row($resql);
824  $factures[$i] = $row; // All fields
825  if ($row[7] == 0) {
826  $error++;
827  dol_syslog(__METHOD__."::Read invoices error Found a null invoice", LOG_ERR);
828  $this->invoice_in_error[$row[0]] = "Error for invoice id ".$row[0].", found a null amount";
829  break;
830  }
831  $i++;
832  }
833  $this->db->free($resql);
834  dol_syslog(__METHOD__."::Read invoices, ".$i." invoices to withdraw", LOG_DEBUG);
835  } else {
836  $error++;
837  dol_syslog(__METHOD__."::Read invoices error ".$this->db->error(), LOG_ERR);
838  }
839  }
840 
841  if (!$error) {
842  require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php';
843  $soc = new Societe($this->db);
844 
845  // Check BAN
846  $i = 0;
847  dol_syslog(__METHOD__."::Check BAN", LOG_DEBUG);
848 
849  if (count($factures) > 0) {
850  foreach ($factures as $key => $fac) {
851  if ($type != 'bank-transfer') {
852  $tmpinvoice = new Facture($this->db);
853  } else {
854  $tmpinvoice = new FactureFournisseur($this->db);
855  }
856  $resfetch = $tmpinvoice->fetch($fac[0]);
857  if ($resfetch >= 0) { // Field 0 of $fac is rowid of invoice
858  if ($soc->fetch($tmpinvoice->socid) >= 0) {
859  $bac = new CompanyBankAccount($this->db);
860  $bac->fetch(0, $soc->id);
861 
862  if ($type != 'bank-transfer') {
863  if ($format == 'FRST' && $bac->frstrecur != 'FRST') {
864  continue;
865  }
866  if ($format == 'RCUR' && ($bac->frstrecur != 'RCUR' && $bac->frstrecur != 'RECUR')) {
867  continue;
868  }
869  }
870 
871  if ($bac->verif() >= 1) {
872  $factures_prev[$i] = $fac;
873  /* second array necessary for BonPrelevement */
874  $factures_prev_id[$i] = $fac[0];
875  $i++;
876  //dol_syslog(__METHOD__."::RIB is ok", LOG_DEBUG);
877  } else {
878  dol_syslog(__METHOD__."::Check BAN Error on default bank number IBAN/BIC for thirdparty reported by verif() ".$tmpinvoice->socid." ".$soc->name, LOG_WARNING);
879  $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice ".$tmpinvoice->getNomUrl(0)." for thirdparty ".$soc->getNomUrl(0);
880  $this->thirdparty_in_error[$soc->id] = "Error on default bank number IBAN/BIC for invoice ".$tmpinvoice->getNomUrl(0)." for thirdparty ".$soc->getNomUrl(0);
881  }
882  } else {
883  dol_syslog(__METHOD__."::Check BAN Failed to read company", LOG_WARNING);
884  }
885  } else {
886  dol_syslog(__METHOD__."::Check BAN Failed to read invoice", LOG_WARNING);
887  }
888  }
889  } else {
890  dol_syslog(__METHOD__."::Check BAN No invoice to process", LOG_WARNING);
891  }
892  }
893 
894  $ok = 0;
895 
896  // Withdraw invoices in factures_prev array
897  $out = count($factures_prev)." invoices will be included.";
898  //print $out."\n";
899  dol_syslog($out);
900 
901  // Return warning
902  /*$i=0;
903  foreach ($this->thirdparty_in_error as $key => $val)
904  {
905  if ($i < 10) setEventMessages($val, null, 'warnings');
906  else setEventMessages('More error were discarded...', null, 'warnings');
907  $i++;
908  }*/
909 
910  if (count($factures_prev) > 0) {
911  if ($mode == 'real') {
912  $ok = 1;
913  } else {
914  print $langs->trans("ModeWarning"); // "Option for real mode was not set, we stop after this simulation\n";
915  }
916  }
917 
918  if ($ok) {
919  /*
920  * We are in real mode.
921  * We create order and build file into disk
922  */
923  $this->db->begin();
924 
925  $now = dol_now();
926  $ref = '';
927 
928  /*
929  * Process order generation
930  */
931  if (!$error) {
932  $ref = substr($year, -2).$month;
933 
934  $sql = "SELECT substring(ref from char_length(ref) - 1)"; // To extract "YYMMXX" from "TYYMMXX"
935  $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons";
936  $sql .= " WHERE ref LIKE '_".$this->db->escape($ref)."%'";
937  $sql .= " AND entity = ".((int) $conf->entity);
938  $sql .= " ORDER BY ref DESC LIMIT 1";
939 
940  dol_syslog(get_class($this)."::create", LOG_DEBUG);
941  $resql = $this->db->query($sql);
942 
943  if ($resql) {
944  $row = $this->db->fetch_row($resql);
945 
946  // Build the new ref
947  $ref = "T".$ref.sprintf("%02d", (intval($row[0]) + 1));
948 
949  // $conf->abc->dir_output may be:
950  // /home/ldestailleur/git/dolibarr_15.0/documents/abc/
951  // or
952  // /home/ldestailleur/git/dolibarr_15.0/documents/X/abc with X >= 2 with multicompany.
953  if ($type != 'bank-transfer') {
954  $dir = $conf->prelevement->dir_output.'/receipts';
955  } else {
956  $dir = $conf->paymentbybanktransfer->dir_output.'/receipts';
957  }
958  if (!is_dir($dir)) {
959  dol_mkdir($dir);
960  }
961 
962  $this->filename = $dir.'/'.$ref.'.xml';
963 
964  // Create withdraw receipt in database
965  $sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement_bons (";
966  $sql .= "ref, entity, datec, type";
967  $sql .= ") VALUES (";
968  $sql .= "'".$this->db->escape($ref)."'";
969  $sql .= ", ".((int) $conf->entity);
970  $sql .= ", '".$this->db->idate($now)."'";
971  $sql .= ", '".($type == 'bank-transfer' ? 'bank-transfer' : 'debit-order')."'";
972  $sql .= ")";
973 
974  $resql = $this->db->query($sql);
975  if ($resql) {
976  $prev_id = $this->db->last_insert_id(MAIN_DB_PREFIX."prelevement_bons");
977  $this->id = $prev_id;
978  $this->ref = $ref;
979  } else {
980  $error++;
981  dol_syslog(__METHOD__."::Create withdraw receipt ".$this->db->lasterror(), LOG_ERR);
982  }
983  } else {
984  $error++;
985  dol_syslog(__METHOD__."::Get last withdraw receipt ".$this->db->lasterror(), LOG_ERR);
986  }
987  }
988 
989  if (!$error) {
990  if ($type != 'bank-transfer') {
991  $fact = new Facture($this->db);
992  } else {
993  $fact = new FactureFournisseur($this->db);
994  }
995 
996  /*
997  * Create withdrawal receipt in database
998  */
999  if (count($factures_prev) > 0) {
1000  foreach ($factures_prev as $fac) { // Add a link in database for each invoice
1001  // Fetch invoice
1002  $result = $fact->fetch($fac[0]);
1003  if ($result < 0) {
1004  $this->error = 'ERRORBONPRELEVEMENT Failed to load invoice with id '.$fac[0];
1005  break;
1006  }
1007 
1008  /*
1009  * Add standing order. This add record into llx_prelevement_lignes
1010  *
1011  * $fac[0] : invoice_id
1012  * $fac[1] : ???
1013  * $fac[2] : third party id
1014  * $fac[3] : banque
1015  * $fac[4] : guichet
1016  * $fac[5] : number
1017  * $fac[6] : cle rib
1018  * $fac[7] : amount
1019  * $fac[8] : client nom
1020  */
1021  $ri = $this->AddFacture($fac[0], $fac[2], $fac[8], $fac[7], $fac[3], $fac[4], $fac[5], $fac[6], $type);
1022  if ($ri <> 0) {
1023  $error++;
1024  }
1025 
1026  // Update invoice requests as done
1027  $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_demande";
1028  $sql .= " SET traite = 1";
1029  $sql .= ", date_traite = '".$this->db->idate($now)."'";
1030  $sql .= ", fk_prelevement_bons = ".((int) $this->id);
1031  $sql .= " WHERE rowid = ".((int) $fac[1]);
1032 
1033  $resql = $this->db->query($sql);
1034  if (!$resql) {
1035  $error++;
1036  $this->errors[] = $this->db->lasterror();
1037  dol_syslog(__METHOD__."::Update Error=".$this->db->lasterror(), LOG_ERR);
1038  }
1039  }
1040  }
1041  }
1042 
1043  if (!$error) {
1044  /*
1045  * Create file of type='direct-debit' for direct debit order or type='bank-transfer' for credit transfer into a XML file
1046  */
1047 
1048  dol_syslog(__METHOD__."::Init direct debit or credit transfer file for ".count($factures_prev)." invoices", LOG_DEBUG);
1049 
1050  if (count($factures_prev) > 0) {
1051  $this->date_echeance = $datetimeprev;
1052  $this->reference_remise = $ref;
1053 
1054  $id = $conf->global->PRELEVEMENT_ID_BANKACCOUNT;
1055  if ($type == 'bank-transfer') {
1056  $id = $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT;
1057  }
1058  $account = new Account($this->db);
1059  if ($account->fetch($id) > 0) {
1060  $this->emetteur_code_banque = $account->code_banque;
1061  $this->emetteur_code_guichet = $account->code_guichet;
1062  $this->emetteur_numero_compte = $account->number;
1063  $this->emetteur_number_key = $account->cle_rib;
1064  $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
1065  $this->emetteur_iban = $account->iban;
1066  $this->emetteur_bic = $account->bic;
1067 
1068  $this->emetteur_ics = ($type == 'bank-transfer' ? $account->ics_transfer : $account->ics);
1069 
1070  $this->raison_sociale = $account->proprio;
1071  }
1072 
1073  $this->factures = $factures_prev_id;
1074  $this->context['factures_prev'] = $factures_prev;
1075 
1076  // Generation of direct debit or credti transfer file $this->filename (May be a SEPA file for european countries)
1077  // This also set the property $this->total with amount that is included into file
1078  $result = $this->generate($format, $executiondate, $type);
1079  if ($result < 0) {
1080  //var_dump($this->error);
1081  //var_dump($this->invoice_in_error);
1082  $error++;
1083  }
1084  }
1085  dol_syslog(__METHOD__."::End withdraw receipt, file ".$this->filename, LOG_DEBUG);
1086  }
1087  //var_dump($this->total);exit;
1088 
1089  /*
1090  * Update total defined after generation of file
1091  */
1092  if (!$error) {
1093  $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_bons";
1094  $sql .= " SET amount = ".price2num($this->total);
1095  $sql .= " WHERE rowid = ".((int) $this->id);
1096  $sql .= " AND entity = ".((int) $conf->entity);
1097 
1098  $resql = $this->db->query($sql);
1099  if (!$resql) {
1100  $error++;
1101  dol_syslog(__METHOD__."::Error update total: ".$this->db->error(), LOG_ERR);
1102  }
1103  }
1104 
1105  if (!$error && !$notrigger) {
1106  $triggername = 'DIRECT_DEBIT_ORDER_CREATE';
1107  if ($type != 'bank-transfer') {
1108  $triggername = 'CREDIT_TRANSFER_ORDER_CREATE';
1109  }
1110 
1111  // Call trigger
1112  $result = $this->call_trigger($triggername, $user);
1113  if ($result < 0) {
1114  $error++;
1115  }
1116  // End call triggers
1117  }
1118 
1119  if (!$error) {
1120  $this->db->commit();
1121  return count($factures_prev);
1122  } else {
1123  $this->db->rollback();
1124  return -1;
1125  }
1126  } else {
1127  return 0;
1128  }
1129  }
1130 
1131 
1139  public function delete($user = null, $notrigger = 0)
1140  {
1141  $this->db->begin();
1142 
1143  $error = 0;
1144  $resql1 = $resql2 = $resql3 = $resql4 = 0;
1145 
1146  if (!$notrigger) {
1147  $triggername = 'DIRECT_DEBIT_ORDER_DELETE';
1148  if ($this->type == 'bank-transfer') {
1149  $triggername = 'PAYMENTBYBANKTRANFER_DELETE';
1150  }
1151  // Call trigger
1152  $result = $this->call_trigger($triggername, $user);
1153  if ($result < 0) {
1154  $error++;
1155  }
1156  // End call triggers
1157  }
1158 
1159  if (!$error) {
1160  $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).")";
1161  $resql1 = $this->db->query($sql);
1162  if (!$resql1) {
1163  dol_print_error($this->db);
1164  }
1165  }
1166 
1167  if (!$error) {
1168  $sql = "DELETE FROM ".MAIN_DB_PREFIX."prelevement_lignes WHERE fk_prelevement_bons = ".((int) $this->id);
1169  $resql2 = $this->db->query($sql);
1170  if (!$resql2) {
1171  dol_print_error($this->db);
1172  }
1173  }
1174 
1175  if (!$error) {
1176  $sql = "DELETE FROM ".MAIN_DB_PREFIX."prelevement_bons WHERE rowid = ".((int) $this->id);
1177  $resql3 = $this->db->query($sql);
1178  if (!$resql3) {
1179  dol_print_error($this->db);
1180  }
1181  }
1182 
1183  if (!$error) {
1184  $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_demande SET fk_prelevement_bons = NULL, traite = 0 WHERE fk_prelevement_bons = ".((int) $this->id);
1185  $resql4 = $this->db->query($sql);
1186  if (!$resql4) {
1187  dol_print_error($this->db);
1188  }
1189  }
1190 
1191  if ($resql1 && $resql2 && $resql3 && $resql4 && !$error) {
1192  $this->db->commit();
1193  return 1;
1194  } else {
1195  $this->db->rollback();
1196  return -1;
1197  }
1198  }
1199 
1200 
1211  public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1212  {
1213  global $conf, $langs, $hookmanager;
1214 
1215  if (!empty($conf->dol_no_mouse_hover)) {
1216  $notooltip = 1; // Force disable tooltips
1217  }
1218 
1219  $result = '';
1220 
1221  $labeltoshow = 'PaymentByDirectDebit';
1222  if (!empty($this->type) && $this->type == 'bank-transfer') {
1223  $labeltoshow = 'PaymentByBankTransfer';
1224  }
1225 
1226  $label = '<u>'.$langs->trans($labeltoshow).'</u>';
1227  $label .= '<br>';
1228  $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
1229  if (isset($this->statut)) {
1230  $label .= '<br><b>'.$langs->trans("Status").":</b> ".$this->getLibStatut(5);
1231  }
1232 
1233  $url = DOL_URL_ROOT.'/compta/prelevement/card.php?id='.$this->id;
1234  if (!empty($this->type) && $this->type == 'bank-transfer') {
1235  $url = DOL_URL_ROOT.'/compta/prelevement/card.php?id='.$this->id;
1236  }
1237 
1238  if ($option != 'nolink') {
1239  // Add param to save lastsearch_values or not
1240  $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1241  if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1242  $add_save_lastsearch_values = 1;
1243  }
1244  if ($add_save_lastsearch_values) {
1245  $url .= '&save_lastsearch_values=1';
1246  }
1247  }
1248 
1249  $linkclose = '';
1250  if (empty($notooltip)) {
1251  if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
1252  $label = $langs->trans("ShowMyObject");
1253  $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
1254  }
1255  $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
1256  $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
1257  } else {
1258  $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1259  }
1260 
1261  $linkstart = '<a href="'.$url.'"';
1262  $linkstart .= $linkclose.'>';
1263  $linkend = '</a>';
1264 
1265  $result .= $linkstart;
1266  if ($withpicto) {
1267  $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);
1268  }
1269  if ($withpicto != 2) {
1270  $result .= $this->ref;
1271  }
1272  $result .= $linkend;
1273 
1274  global $action, $hookmanager;
1275  $hookmanager->initHooks(array('banktransferdao'));
1276  $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
1277  $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1278  if ($reshook > 0) {
1279  $result = $hookmanager->resPrint;
1280  } else {
1281  $result .= $hookmanager->resPrint;
1282  }
1283 
1284  return $result;
1285  }
1286 
1287 
1294  public function deleteNotificationById($rowid)
1295  {
1296  $sql = "DELETE FROM ".MAIN_DB_PREFIX."notify_def";
1297  $sql .= " WHERE rowid = ".((int) $rowid);
1298 
1299  if ($this->db->query($sql)) {
1300  return 0;
1301  } else {
1302  return -1;
1303  }
1304  }
1305 
1313  public function deleteNotification($user, $action)
1314  {
1315  if (is_object($user)) {
1316  $userid = $user->id;
1317  } else { // If user is an id
1318  $userid = $user;
1319  }
1320 
1321  $sql = "DELETE FROM ".MAIN_DB_PREFIX."notify_def";
1322  $sql .= " WHERE fk_user=".((int) $userid)." AND fk_action='".$this->db->escape($action)."'";
1323 
1324  if ($this->db->query($sql)) {
1325  return 0;
1326  } else {
1327  return -1;
1328  }
1329  }
1330 
1331  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1340  public function addNotification($db, $user, $action)
1341  {
1342  // phpcs:enable
1343  $result = 0;
1344 
1345  if (is_object($user)) {
1346  $userid = $user->id;
1347  } else { // If user is an id
1348  $userid = $user;
1349  }
1350 
1351  if ($this->deleteNotification($user, $action) == 0) {
1352  $now = dol_now();
1353 
1354  $sql = "INSERT INTO ".MAIN_DB_PREFIX."notify_def (datec,fk_user, fk_soc, fk_contact, fk_action)";
1355  $sql .= " VALUES ('".$this->db->idate($now)."', ".((int) $userid).", 'NULL', 'NULL', '".$this->db->escape($action)."')";
1356 
1357  dol_syslog("adnotiff: ".$sql);
1358  if ($this->db->query($sql)) {
1359  $result = 0;
1360  } else {
1361  $result = -1;
1362  dol_syslog(get_class($this)."::addNotification Error $result");
1363  }
1364  }
1365 
1366  return $result;
1367  }
1368 
1369 
1382  public function generate($format = 'ALL', $executiondate = '', $type = 'direct-debit')
1383  {
1384  global $conf, $langs, $mysoc;
1385 
1386  //TODO: Optimize code to read lines in a single function
1387 
1388  $result = 0;
1389 
1390  dol_syslog(get_class($this)."::generate build file=".$this->filename." type=".$type);
1391 
1392  $this->file = fopen($this->filename, "w");
1393  if (empty($this->file)) {
1394  $this->error = $langs->trans('ErrorFailedToOpenFile', $this->filename);
1395  return -1;
1396  }
1397 
1398  $found = 0;
1399  $this->total = 0;
1400 
1401  // Build file for European countries
1402  if ($mysoc->isInEEC()) {
1403  $found++;
1404 
1405  if ($type != 'bank-transfer') {
1409  // SEPA Initialisation
1410  $CrLf = "\n";
1411 
1412  $now = dol_now();
1413 
1414  $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S');
1415 
1416  $date_actu = $now;
1417  if (!empty($executiondate)) {
1418  $date_actu = $executiondate;
1419  }
1420 
1421  $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d');
1422  $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S');
1423  $fileDebiteurSection = '';
1424  $fileEmetteurSection = '';
1425  $i = 0;
1426 
1427  /*
1428  * Section Debitor (sepa Debiteurs bloc lines)
1429  */
1430 
1431  $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
1432  $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1433  $sql .= " f.ref as fac, pf.fk_facture as idfac,";
1434  $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
1435  $sql .= " FROM";
1436  $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,";
1437  $sql .= " ".MAIN_DB_PREFIX."facture as f,";
1438  $sql .= " ".MAIN_DB_PREFIX."prelevement as pf,";
1439  $sql .= " ".MAIN_DB_PREFIX."societe as soc,";
1440  $sql .= " ".MAIN_DB_PREFIX."c_country as c,";
1441  $sql .= " ".MAIN_DB_PREFIX."societe_rib as rib";
1442  $sql .= " WHERE pl.fk_prelevement_bons = ".((int) $this->id);
1443  $sql .= " AND pl.rowid = pf.fk_prelevement_lignes";
1444  $sql .= " AND pf.fk_facture = f.rowid";
1445  $sql .= " AND f.fk_soc = soc.rowid";
1446  $sql .= " AND soc.fk_pays = c.rowid";
1447  $sql .= " AND rib.fk_soc = f.fk_soc";
1448  $sql .= " AND rib.default_rib = 1";
1449  $sql .= " AND rib.type = 'ban'";
1450 
1451  // Define $fileDebiteurSection. One section DrctDbtTxInf per invoice.
1452  $resql = $this->db->query($sql);
1453  if ($resql) {
1454  $cachearraytotestduplicate = array();
1455 
1456  $num = $this->db->num_rows($resql);
1457  while ($i < $num) {
1458  $obj = $this->db->fetch_object($resql);
1459 
1460  if (!empty($cachearraytotestduplicate[$obj->idfac])) {
1461  $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
1462  $this->invoice_in_error[$obj->idfac] = $this->error;
1463  $result = -2;
1464  break;
1465  }
1466  $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
1467 
1468  $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
1469  $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);
1470  $this->total = $this->total + $obj->somme;
1471  $i++;
1472  }
1473  $nbtotalDrctDbtTxInf = $i;
1474  } else {
1475  $this->error = $this->db->lasterror();
1476  fputs($this->file, 'ERROR DEBITOR '.$sql.$CrLf); // DEBITOR = Customers
1477  $result = -2;
1478  }
1479 
1480  // Define $fileEmetteurSection. Start of bloc PmtInf. Will contains all $nbtotalDrctDbtTxInf
1481  if ($result != -2) {
1482  $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type);
1483  }
1484 
1488  // SEPA File Header
1489  fputs($this->file, '<'.'?xml version="1.0" encoding="UTF-8" standalone="yes"?'.'>'.$CrLf);
1490  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);
1491  fputs($this->file, ' <CstmrDrctDbtInitn>'.$CrLf);
1492  // SEPA Group header
1493  fputs($this->file, ' <GrpHdr>'.$CrLf);
1494  fputs($this->file, ' <MsgId>'.('DD/'.$dateTime_YMD.'/REF'.$this->id).'</MsgId>'.$CrLf);
1495  fputs($this->file, ' <CreDtTm>'.$dateTime_ECMA.'</CreDtTm>'.$CrLf);
1496  fputs($this->file, ' <NbOfTxs>'.$i.'</NbOfTxs>'.$CrLf);
1497  fputs($this->file, ' <CtrlSum>'.$this->total.'</CtrlSum>'.$CrLf);
1498  fputs($this->file, ' <InitgPty>'.$CrLf);
1499  fputs($this->file, ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf);
1500  fputs($this->file, ' <Id>'.$CrLf);
1501  fputs($this->file, ' <PrvtId>'.$CrLf);
1502  fputs($this->file, ' <Othr>'.$CrLf);
1503  fputs($this->file, ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf);
1504  fputs($this->file, ' </Othr>'.$CrLf);
1505  fputs($this->file, ' </PrvtId>'.$CrLf);
1506  fputs($this->file, ' </Id>'.$CrLf);
1507  fputs($this->file, ' </InitgPty>'.$CrLf);
1508  fputs($this->file, ' </GrpHdr>'.$CrLf);
1509  // SEPA File Emetteur
1510  if ($result != -2) {
1511  fputs($this-> file, $fileEmetteurSection);
1512  }
1513  // SEPA File Debiteurs
1514  if ($result != -2) {
1515  fputs($this-> file, $fileDebiteurSection);
1516  }
1517  // SEPA FILE FOOTER
1518  fputs($this->file, ' </PmtInf>'.$CrLf);
1519  fputs($this->file, ' </CstmrDrctDbtInitn>'.$CrLf);
1520  fputs($this->file, '</Document>'.$CrLf);
1521  } else {
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  $fileCrediteurSection = '';
1540  $fileEmetteurSection = '';
1541  $i = 0;
1542 
1543  /*
1544  * Section Creditor (sepa Crediteurs 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 fac, pf.fk_facture_fourn as idfac, f.ref_supplier as fac_ref_supplier,";
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_fourn 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_fourn = 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 $fileCrediteurSection. 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  $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_ref_supplier, $obj->idfac, $obj->iban, $obj->bic, $daterum, $obj->drum, $obj->rum, $type);
1586  $this->total = $this->total + $obj->somme;
1587  $i++;
1588  }
1589  $nbtotalDrctDbtTxInf = $i;
1590  } else {
1591  $this->error = $this->db->lasterror();
1592  fputs($this->file, 'ERROR CREDITOR '.$sql.$CrLf); // CREDITORS = Suppliers
1593  $result = -2;
1594  }
1595 
1596  // Define $fileEmetteurSection. Start of bloc PmtInf. Will contains all $nbtotalDrctDbtTxInf
1597  if ($result != -2) {
1598  $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type);
1599  }
1600 
1604  // SEPA File Header
1605  fputs($this->file, '<'.'?xml version="1.0" encoding="UTF-8" standalone="yes"?'.'>'.$CrLf);
1606  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);
1607  fputs($this->file, ' <CstmrCdtTrfInitn>'.$CrLf);
1608  // SEPA Group header
1609  fputs($this->file, ' <GrpHdr>'.$CrLf);
1610  fputs($this->file, ' <MsgId>'.('TRF/'.$dateTime_YMD.'/REF'.$this->id).'</MsgId>'.$CrLf);
1611  fputs($this->file, ' <CreDtTm>'.$dateTime_ECMA.'</CreDtTm>'.$CrLf);
1612  fputs($this->file, ' <NbOfTxs>'.$i.'</NbOfTxs>'.$CrLf);
1613  fputs($this->file, ' <CtrlSum>'.$this->total.'</CtrlSum>'.$CrLf);
1614  fputs($this->file, ' <InitgPty>'.$CrLf);
1615  fputs($this->file, ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf);
1616  fputs($this->file, ' <Id>'.$CrLf);
1617  fputs($this->file, ' <PrvtId>'.$CrLf);
1618  fputs($this->file, ' <Othr>'.$CrLf);
1619  fputs($this->file, ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf);
1620  fputs($this->file, ' </Othr>'.$CrLf);
1621  fputs($this->file, ' </PrvtId>'.$CrLf);
1622  fputs($this->file, ' </Id>'.$CrLf);
1623  fputs($this->file, ' </InitgPty>'.$CrLf);
1624  fputs($this->file, ' </GrpHdr>'.$CrLf);
1625  // SEPA File Emetteur (mycompany)
1626  if ($result != -2) {
1627  fputs($this-> file, $fileEmetteurSection);
1628  }
1629  // SEPA File Creditors
1630  if ($result != -2) {
1631  fputs($this-> file, $fileCrediteurSection);
1632  }
1633  // SEPA FILE FOOTER
1634  fputs($this->file, ' </PmtInf>'.$CrLf);
1635  fputs($this->file, ' </CstmrCdtTrfInitn>'.$CrLf);
1636  fputs($this->file, '</Document>'.$CrLf);
1637  }
1638  }
1639 
1640  // Build file for Other Countries with unknow format
1641  if (!$found) {
1642  if ($type != 'bank-transfer') {
1643  $sql = "SELECT pl.amount";
1644  $sql .= " FROM";
1645  $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,";
1646  $sql .= " ".MAIN_DB_PREFIX."facture as f,";
1647  $sql .= " ".MAIN_DB_PREFIX."prelevement as pf";
1648  $sql .= " WHERE pl.fk_prelevement_bons = ".((int) $this->id);
1649  $sql .= " AND pl.rowid = pf.fk_prelevement_lignes";
1650  $sql .= " AND pf.fk_facture = f.rowid";
1651 
1652  // Lines
1653  $i = 0;
1654  $resql = $this->db->query($sql);
1655  if ($resql) {
1656  $num = $this->db->num_rows($resql);
1657 
1658  while ($i < $num) {
1659  $obj = $this->db->fetch_object($resql);
1660  $this->total = $this->total + $obj->amount;
1661 
1662  // TODO Write record into file
1663  $i++;
1664  }
1665  } else {
1666  $result = -2;
1667  }
1668  } else {
1669  $sql = "SELECT pl.amount";
1670  $sql .= " FROM";
1671  $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,";
1672  $sql .= " ".MAIN_DB_PREFIX."facture_fourn as f,";
1673  $sql .= " ".MAIN_DB_PREFIX."prelevement as pf";
1674  $sql .= " WHERE pl.fk_prelevement_bons = ".((int) $this->id);
1675  $sql .= " AND pl.rowid = pf.fk_prelevement_lignes";
1676  $sql .= " AND pf.fk_facture_fourn = f.rowid";
1677 
1678  // Lines
1679  $i = 0;
1680  $resql = $this->db->query($sql);
1681  if ($resql) {
1682  $num = $this->db->num_rows($resql);
1683 
1684  while ($i < $num) {
1685  $obj = $this->db->fetch_object($resql);
1686  $this->total = $this->total + $obj->amount;
1687 
1688  // TODO Write record into file
1689  $i++;
1690  }
1691  } else {
1692  $result = -2;
1693  }
1694  }
1695 
1696  $langs->load('withdrawals');
1697 
1698  // TODO Add here code to generate a generic file
1699  fputs($this->file, $langs->transnoentitiesnoconv('WithdrawalFileNotCapable', $mysoc->country_code));
1700  }
1701 
1702  fclose($this->file);
1703  if (!empty($conf->global->MAIN_UMASK)) {
1704  @chmod($this->filename, octdec($conf->global->MAIN_UMASK));
1705  }
1706 
1707  return $result;
1708  }
1709 
1710 
1719  public static function buildRumNumber($row_code_client, $row_datec, $row_drum)
1720  {
1721  global $langs;
1722  $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)
1723  return $pre.($row_code_client ? '-'.$row_code_client : '').'-'.$row_drum.'-'.date('U', $row_datec);
1724  }
1725 
1726 
1727  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1744  public function EnregDestinataire($rowid, $client_nom, $rib_banque, $rib_guichet, $rib_number, $amount, $ref, $facid, $rib_dom = '', $type = 'direct-debit')
1745  {
1746  // phpcs:enable
1747  fputs($this->file, "06");
1748  fputs($this->file, "08"); // Prelevement ordinaire
1749 
1750  fputs($this->file, " "); // Zone Reservee B2
1751 
1752  fputs($this->file, $this->emetteur_ics); // ICS
1753 
1754  // Date d'echeance C1
1755 
1756  fputs($this->file, " ");
1757  fputs($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
1758  fputs($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
1759 
1760  // Raison Sociale Destinataire C2
1761 
1762  fputs($this->file, substr(strtoupper($client_nom)." ", 0, 24));
1763 
1764  // Domiciliation facultative D1
1765  $domiciliation = strtr($rib_dom, array(" " => "-", CHR(13) => " ", CHR(10) => ""));
1766  fputs($this->file, substr($domiciliation." ", 0, 24));
1767 
1768  // Zone Reservee D2
1769 
1770  fputs($this->file, substr(" ", 0, 8));
1771 
1772  // Code Guichet D3
1773 
1774  fputs($this->file, $rib_guichet);
1775 
1776  // Numero de compte D4
1777 
1778  fputs($this->file, substr("000000000000000".$rib_number, -11));
1779 
1780  // Zone E Montant
1781 
1782  $montant = (round($amount, 2) * 100);
1783 
1784  fputs($this->file, substr("000000000000000".$montant, -16));
1785 
1786  // Libelle F
1787 
1788  fputs($this->file, substr("*_".$ref."_RDVnet".$rowid." ", 0, 31));
1789 
1790  // Code etablissement G1
1791 
1792  fputs($this->file, $rib_banque);
1793 
1794  // Zone Reservee G2
1795 
1796  fputs($this->file, substr(" ", 0, 5));
1797 
1798  fputs($this->file, "\n");
1799  }
1800 
1801  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1826  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')
1827  {
1828  // phpcs:enable
1829  global $conf;
1830 
1831  include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
1832 
1833  $CrLf = "\n";
1834  $Rowing = sprintf("%010d", $row_idfac);
1835 
1836  // Define value for RUM
1837  // Example: RUM-CustomerCode-CustomerBankAccountId-01424448606 (note: Date is the timestamp of the date of creation of CustomerBankAccountId)
1838  $Rum = (empty($row_rum) ? $this->buildRumNumber($row_code_client, $row_datec, $row_drum) : $row_rum);
1839 
1840  // Define date of RUM signature
1841  $DtOfSgntr = dol_print_date($row_datec, '%Y-%m-%d');
1842 
1843  if ($type != 'bank-transfer') {
1844  // SEPA Paiement Information of buyer for Direct Debit
1845  $XML_DEBITOR = '';
1846  $XML_DEBITOR .= ' <DrctDbtTxInf>'.$CrLf;
1847  $XML_DEBITOR .= ' <PmtId>'.$CrLf;
1848  // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
1849  $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
1850  $XML_DEBITOR .= ' </PmtId>'.$CrLf;
1851  $XML_DEBITOR .= ' <InstdAmt Ccy="EUR">'.round($row_somme, 2).'</InstdAmt>'.$CrLf;
1852  $XML_DEBITOR .= ' <DrctDbtTx>'.$CrLf;
1853  $XML_DEBITOR .= ' <MndtRltdInf>'.$CrLf;
1854  $XML_DEBITOR .= ' <MndtId>'.$Rum.'</MndtId>'.$CrLf;
1855  $XML_DEBITOR .= ' <DtOfSgntr>'.$DtOfSgntr.'</DtOfSgntr>'.$CrLf;
1856  $XML_DEBITOR .= ' <AmdmntInd>false</AmdmntInd>'.$CrLf;
1857  $XML_DEBITOR .= ' </MndtRltdInf>'.$CrLf;
1858  $XML_DEBITOR .= ' </DrctDbtTx>'.$CrLf;
1859  $XML_DEBITOR .= ' <DbtrAgt>'.$CrLf;
1860  $XML_DEBITOR .= ' <FinInstnId>'.$CrLf;
1861  $XML_DEBITOR .= ' <BIC>'.$row_bic.'</BIC>'.$CrLf;
1862  $XML_DEBITOR .= ' </FinInstnId>'.$CrLf;
1863  $XML_DEBITOR .= ' </DbtrAgt>'.$CrLf;
1864  $XML_DEBITOR .= ' <Dbtr>'.$CrLf;
1865  $XML_DEBITOR .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))).'</Nm>'.$CrLf;
1866  $XML_DEBITOR .= ' <PstlAdr>'.$CrLf;
1867  $XML_DEBITOR .= ' <Ctry>'.$row_country_code.'</Ctry>'.$CrLf;
1868  $addressline1 = strtr($row_address, array(CHR(13) => ", ", CHR(10) => ""));
1869  $addressline2 = strtr($row_zip.(($row_zip && $row_town) ? ' ' : (string) $row_town), array(CHR(13) => ", ", CHR(10) => ""));
1870  if (trim($addressline1)) {
1871  $XML_DEBITOR .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
1872  }
1873  if (trim($addressline2)) {
1874  $XML_DEBITOR .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
1875  }
1876  $XML_DEBITOR .= ' </PstlAdr>'.$CrLf;
1877  $XML_DEBITOR .= ' </Dbtr>'.$CrLf;
1878  $XML_DEBITOR .= ' <DbtrAcct>'.$CrLf;
1879  $XML_DEBITOR .= ' <Id>'.$CrLf;
1880  $XML_DEBITOR .= ' <IBAN>'.preg_replace('/\s/', '', $row_iban).'</IBAN>'.$CrLf;
1881  $XML_DEBITOR .= ' </Id>'.$CrLf;
1882  $XML_DEBITOR .= ' </DbtrAcct>'.$CrLf;
1883  $XML_DEBITOR .= ' <RmtInf>'.$CrLf;
1884  // A string with some information on payment - 140 max
1885  $XML_DEBITOR .= ' <Ustrd>'.(($conf->global->PRELEVEMENT_USTRD != "") ? $conf->global->PRELEVEMENT_USTRD : dol_trunc($row_ref, 135, 'right', 'UTF-8', 1)).'</Ustrd>'.$CrLf; // 140 max
1886  $XML_DEBITOR .= ' </RmtInf>'.$CrLf;
1887  $XML_DEBITOR .= ' </DrctDbtTxInf>'.$CrLf;
1888  return $XML_DEBITOR;
1889  } else {
1890  // SEPA Paiement Information of seller for Credit Transfer
1891  $XML_CREDITOR = '';
1892  $XML_CREDITOR .= ' <CdtTrfTxInf>'.$CrLf;
1893  $XML_CREDITOR .= ' <PmtId>'.$CrLf;
1894  // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
1895  $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
1896  $XML_CREDITOR .= ' </PmtId>'.$CrLf;
1897  if (!empty($this->sepa_xml_pti_in_ctti)) {
1898  $XML_CREDITOR .= ' <PmtTpInf>' . $CrLf;
1899 
1900  // Can be 'NORM' for normal or 'HIGH' for high priority level
1901  if (!empty($conf->global->PAYMENTBYBANKTRANSFER_FORCE_HIGH_PRIORITY)) {
1902  $instrprty = 'HIGH';
1903  } else {
1904  $instrprty = 'NORM';
1905  }
1906  $XML_CREDITOR .= ' <InstrPrty>'.$instrprty.'</InstrPrty>' . $CrLf;
1907  $XML_CREDITOR .= ' <SvcLvl>' . $CrLf;
1908  $XML_CREDITOR .= ' <Cd>SEPA</Cd>' . $CrLf;
1909  $XML_CREDITOR .= ' </SvcLvl>' . $CrLf;
1910  $XML_CREDITOR .= ' <CtgyPurp>' . $CrLf;
1911  $XML_CREDITOR .= ' <Cd>CORE</Cd>' . $CrLf;
1912  $XML_CREDITOR .= ' </CtgyPurp>' . $CrLf;
1913  $XML_CREDITOR .= ' </PmtTpInf>' . $CrLf;
1914  }
1915  $XML_CREDITOR .= ' <Amt>'.$CrLf;
1916  $XML_CREDITOR .= ' <InstdAmt Ccy="EUR">'.round($row_somme, 2).'</InstdAmt>'.$CrLf;
1917  $XML_CREDITOR .= ' </Amt>'.$CrLf;
1918  /*
1919  $XML_CREDITOR .= ' <DrctDbtTx>'.$CrLf;
1920  $XML_CREDITOR .= ' <MndtRltdInf>'.$CrLf;
1921  $XML_CREDITOR .= ' <MndtId>'.$Rum.'</MndtId>'.$CrLf;
1922  $XML_CREDITOR .= ' <DtOfSgntr>'.$DtOfSgntr.'</DtOfSgntr>'.$CrLf;
1923  $XML_CREDITOR .= ' <AmdmntInd>false</AmdmntInd>'.$CrLf;
1924  $XML_CREDITOR .= ' </MndtRltdInf>'.$CrLf;
1925  $XML_CREDITOR .= ' </DrctDbtTx>'.$CrLf;
1926  */
1927  //$XML_CREDITOR .= ' <ChrgBr>SLEV</ChrgBr>'.$CrLf;
1928  $XML_CREDITOR .= ' <CdtrAgt>'.$CrLf;
1929  $XML_CREDITOR .= ' <FinInstnId>'.$CrLf;
1930  $XML_CREDITOR .= ' <BIC>'.$row_bic.'</BIC>'.$CrLf;
1931  $XML_CREDITOR .= ' </FinInstnId>'.$CrLf;
1932  $XML_CREDITOR .= ' </CdtrAgt>'.$CrLf;
1933  $XML_CREDITOR .= ' <Cdtr>'.$CrLf;
1934  $XML_CREDITOR .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))).'</Nm>'.$CrLf;
1935  $XML_CREDITOR .= ' <PstlAdr>'.$CrLf;
1936  $XML_CREDITOR .= ' <Ctry>'.$row_country_code.'</Ctry>'.$CrLf;
1937  $addressline1 = strtr($row_address, array(CHR(13) => ", ", CHR(10) => ""));
1938  $addressline2 = strtr($row_zip.(($row_zip && $row_town) ? ' ' : (string) $row_town), array(CHR(13) => ", ", CHR(10) => ""));
1939  if (trim($addressline1)) {
1940  $XML_CREDITOR .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
1941  }
1942  if (trim($addressline2)) {
1943  $XML_CREDITOR .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
1944  }
1945  $XML_CREDITOR .= ' </PstlAdr>'.$CrLf;
1946  $XML_CREDITOR .= ' </Cdtr>'.$CrLf;
1947  $XML_CREDITOR .= ' <CdtrAcct>'.$CrLf;
1948  $XML_CREDITOR .= ' <Id>'.$CrLf;
1949  $XML_CREDITOR .= ' <IBAN>'.preg_replace('/\s/', '', $row_iban).'</IBAN>'.$CrLf;
1950  $XML_CREDITOR .= ' </Id>'.$CrLf;
1951  $XML_CREDITOR .= ' </CdtrAcct>'.$CrLf;
1952  $XML_CREDITOR .= ' <RmtInf>'.$CrLf;
1953  // A string with some information on payment - 140 max
1954  $XML_CREDITOR .= ' <Ustrd>'.(($conf->global->PRELEVEMENT_USTRD != "") ? $conf->global->PRELEVEMENT_USTRD : dol_trunc($row_ref, 135, 'right', 'UTF-8', 1)).'</Ustrd>'.$CrLf; // 140 max
1955  $XML_CREDITOR .= ' </RmtInf>'.$CrLf;
1956  $XML_CREDITOR .= ' </CdtTrfTxInf>'.$CrLf;
1957  return $XML_CREDITOR;
1958  }
1959  }
1960 
1961 
1962  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1970  public function EnregEmetteur($type = 'direct-debit')
1971  {
1972  // phpcs:enable
1973  fputs($this->file, "03");
1974  fputs($this->file, "08"); // Prelevement ordinaire
1975 
1976  fputs($this->file, " "); // Zone Reservee B2
1977 
1978  fputs($this->file, $this->emetteur_ics); // ICS
1979 
1980  // Date d'echeance C1
1981 
1982  fputs($this->file, " ");
1983  fputs($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
1984  fputs($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
1985 
1986  // Raison Sociale C2
1987 
1988  fputs($this->file, substr($this->raison_sociale." ", 0, 24));
1989 
1990  // Reference de la remise creancier D1 sur 7 caracteres
1991 
1992  fputs($this->file, substr($this->reference_remise." ", 0, 7));
1993 
1994  // Zone Reservee D1-2
1995 
1996  fputs($this->file, substr(" ", 0, 17));
1997 
1998  // Zone Reservee D2
1999 
2000  fputs($this->file, substr(" ", 0, 2));
2001  fputs($this->file, "E");
2002  fputs($this->file, substr(" ", 0, 5));
2003 
2004  // Code Guichet D3
2005 
2006  fputs($this->file, $this->emetteur_code_guichet);
2007 
2008  // Numero de compte D4
2009 
2010  fputs($this->file, substr("000000000000000".$this->emetteur_numero_compte, -11));
2011 
2012  // Zone Reservee E
2013 
2014  fputs($this->file, substr(" ", 0, 16));
2015 
2016  // Zone Reservee F
2017 
2018  fputs($this->file, substr(" ", 0, 31));
2019 
2020  // Code etablissement
2021 
2022  fputs($this->file, $this->emetteur_code_banque);
2023 
2024  // Zone Reservee G
2025 
2026  fputs($this->file, substr(" ", 0, 5));
2027 
2028  fputs($this->file, "\n");
2029  }
2030 
2031  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2046  public function EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf = '\n', $format = 'FRST', $type = 'direct-debit')
2047  {
2048  // phpcs:enable
2049  // SEPA INITIALISATION
2050  global $conf;
2051 
2052  $dateTime_YMD = dol_print_date($ladate, '%Y%m%d');
2053  $dateTime_ETAD = dol_print_date($ladate, '%Y-%m-%d');
2054  $dateTime_YMDHMS = dol_print_date($ladate, '%Y-%m-%dT%H:%M:%S');
2055 
2056  // Get data of bank account
2057  //$id = $configuration->global->PRELEVEMENT_ID_BANKACCOUNT;
2058  $id = ($type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT);
2059  $account = new Account($this->db);
2060  if ($account->fetch($id) > 0) {
2061  $this->emetteur_code_banque = $account->code_banque;
2062  $this->emetteur_code_guichet = $account->code_guichet;
2063  $this->emetteur_numero_compte = $account->number;
2064  $this->emetteur_number_key = $account->cle_rib;
2065  $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
2066  $this->emetteur_iban = $account->iban;
2067  $this->emetteur_bic = $account->bic;
2068 
2069  $this->emetteur_ics = ($type == 'bank-transfer' ? $account->ics_transfer : $account->ics); // Ex: PRELEVEMENT_ICS = "FR78ZZZ123456";
2070 
2071  $this->raison_sociale = $account->proprio;
2072  }
2073 
2074  // Get pending payments
2075  $sql = "SELECT rowid, ref";
2076  $sql .= " FROM";
2077  $sql .= " ".MAIN_DB_PREFIX."prelevement_bons as pb";
2078  $sql .= " WHERE pb.rowid = ".((int) $this->id);
2079 
2080  $resql = $this->db->query($sql);
2081  if ($resql) {
2082  $obj = $this->db->fetch_object($resql);
2083 
2084  $country = explode(':', $configuration->global->MAIN_INFO_SOCIETE_COUNTRY);
2085  $IdBon = sprintf("%05d", $obj->rowid);
2086  $RefBon = $obj->ref;
2087 
2088  if ($type != 'bank-transfer') {
2089  // SEPA Paiement Information of my company for Direct Debit
2090  $XML_SEPA_INFO = '';
2091  $XML_SEPA_INFO .= ' <PmtInf>'.$CrLf;
2092  $XML_SEPA_INFO .= ' <PmtInfId>'.('DD/'.$dateTime_YMD.'/ID'.$IdBon.'-'.$RefBon).'</PmtInfId>'.$CrLf;
2093  $XML_SEPA_INFO .= ' <PmtMtd>DD</PmtMtd>'.$CrLf;
2094  $XML_SEPA_INFO .= ' <NbOfTxs>'.$nombre.'</NbOfTxs>'.$CrLf;
2095  $XML_SEPA_INFO .= ' <CtrlSum>'.$total.'</CtrlSum>'.$CrLf;
2096  $XML_SEPA_INFO .= ' <PmtTpInf>'.$CrLf;
2097  $XML_SEPA_INFO .= ' <SvcLvl>'.$CrLf;
2098  $XML_SEPA_INFO .= ' <Cd>SEPA</Cd>'.$CrLf;
2099  $XML_SEPA_INFO .= ' </SvcLvl>'.$CrLf;
2100  $XML_SEPA_INFO .= ' <LclInstrm>'.$CrLf;
2101  $XML_SEPA_INFO .= ' <Cd>CORE</Cd>'.$CrLf;
2102  $XML_SEPA_INFO .= ' </LclInstrm>'.$CrLf;
2103  $XML_SEPA_INFO .= ' <SeqTp>'.$format.'</SeqTp>'.$CrLf;
2104  $XML_SEPA_INFO .= ' </PmtTpInf>'.$CrLf;
2105  $XML_SEPA_INFO .= ' <ReqdColltnDt>'.$dateTime_ETAD.'</ReqdColltnDt>'.$CrLf;
2106  $XML_SEPA_INFO .= ' <Cdtr>'.$CrLf;
2107  $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2108  $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2109  $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2110  $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(CHR(13) => ", ", CHR(10) => ""));
2111  $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) => ""));
2112  if ($addressline1) {
2113  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2114  }
2115  if ($addressline2) {
2116  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2117  }
2118  $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2119  $XML_SEPA_INFO .= ' </Cdtr>'.$CrLf;
2120  $XML_SEPA_INFO .= ' <CdtrAcct>'.$CrLf;
2121  $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2122  $XML_SEPA_INFO .= ' <IBAN>'.preg_replace('/\s/', '', $this->emetteur_iban).'</IBAN>'.$CrLf;
2123  $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2124  $XML_SEPA_INFO .= ' </CdtrAcct>'.$CrLf;
2125  $XML_SEPA_INFO .= ' <CdtrAgt>'.$CrLf;
2126  $XML_SEPA_INFO .= ' <FinInstnId>'.$CrLf;
2127  $XML_SEPA_INFO .= ' <BIC>'.$this->emetteur_bic.'</BIC>'.$CrLf;
2128  $XML_SEPA_INFO .= ' </FinInstnId>'.$CrLf;
2129  $XML_SEPA_INFO .= ' </CdtrAgt>'.$CrLf;
2130  /* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf;
2131  $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2132  $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2133  $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2134  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ADDRESS), ' ')).'</AdrLine>'.$CrLf;
2135  $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;
2136  $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2137  $XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/
2138  $XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>'.$CrLf; // Field "Responsible of fees". Must be SLEV
2139  $XML_SEPA_INFO .= ' <CdtrSchmeId>'.$CrLf;
2140  $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2141  $XML_SEPA_INFO .= ' <PrvtId>'.$CrLf;
2142  $XML_SEPA_INFO .= ' <Othr>'.$CrLf;
2143  $XML_SEPA_INFO .= ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf;
2144  $XML_SEPA_INFO .= ' <SchmeNm>'.$CrLf;
2145  $XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>'.$CrLf;
2146  $XML_SEPA_INFO .= ' </SchmeNm>'.$CrLf;
2147  $XML_SEPA_INFO .= ' </Othr>'.$CrLf;
2148  $XML_SEPA_INFO .= ' </PrvtId>'.$CrLf;
2149  $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2150  $XML_SEPA_INFO .= ' </CdtrSchmeId>'.$CrLf;
2151  } else {
2152  // SEPA Paiement Information of my company for Credit Transfer
2153  $XML_SEPA_INFO = '';
2154  $XML_SEPA_INFO .= ' <PmtInf>'.$CrLf;
2155  $XML_SEPA_INFO .= ' <PmtInfId>'.('TRF/'.$dateTime_YMD.'/ID'.$IdBon.'-'.$RefBon).'</PmtInfId>'.$CrLf;
2156  $XML_SEPA_INFO .= ' <PmtMtd>TRF</PmtMtd>'.$CrLf;
2157  //$XML_SEPA_INFO .= ' <BtchBookg>False</BtchBookg>'.$CrLf;
2158  $XML_SEPA_INFO .= ' <NbOfTxs>'.$nombre.'</NbOfTxs>'.$CrLf;
2159  $XML_SEPA_INFO .= ' <CtrlSum>'.$total.'</CtrlSum>'.$CrLf;
2160  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.
2161  $XML_SEPA_INFO .= ' <PmtTpInf>' . $CrLf;
2162  $XML_SEPA_INFO .= ' <SvcLvl>' . $CrLf;
2163  $XML_SEPA_INFO .= ' <Cd>SEPA</Cd>' . $CrLf;
2164  $XML_SEPA_INFO .= ' </SvcLvl>' . $CrLf;
2165  $XML_SEPA_INFO .= ' <LclInstrm>' . $CrLf;
2166  $XML_SEPA_INFO .= ' <Cd>CORE</Cd>' . $CrLf;
2167  $XML_SEPA_INFO .= ' </LclInstrm>' . $CrLf;
2168  $XML_SEPA_INFO .= ' <SeqTp>' . $format . '</SeqTp>' . $CrLf;
2169  $XML_SEPA_INFO .= ' </PmtTpInf>' . $CrLf;
2170  }
2171  $XML_SEPA_INFO .= ' <ReqdExctnDt>'.dol_print_date($dateTime_ETAD, 'dayrfc').'</ReqdExctnDt>'.$CrLf;
2172  $XML_SEPA_INFO .= ' <Dbtr>'.$CrLf;
2173  $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2174  $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2175  $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2176  $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(CHR(13) => ", ", CHR(10) => ""));
2177  $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) => ""));
2178  if ($addressline1) {
2179  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2180  }
2181  if ($addressline2) {
2182  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2183  }
2184  $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2185  $XML_SEPA_INFO .= ' </Dbtr>'.$CrLf;
2186  $XML_SEPA_INFO .= ' <DbtrAcct>'.$CrLf;
2187  $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2188  $XML_SEPA_INFO .= ' <IBAN>'.preg_replace('/\s/', '', $this->emetteur_iban).'</IBAN>'.$CrLf;
2189  $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2190  $XML_SEPA_INFO .= ' </DbtrAcct>'.$CrLf;
2191  $XML_SEPA_INFO .= ' <DbtrAgt>'.$CrLf;
2192  $XML_SEPA_INFO .= ' <FinInstnId>'.$CrLf;
2193  $XML_SEPA_INFO .= ' <BIC>'.$this->emetteur_bic.'</BIC>'.$CrLf;
2194  $XML_SEPA_INFO .= ' </FinInstnId>'.$CrLf;
2195  $XML_SEPA_INFO .= ' </DbtrAgt>'.$CrLf;
2196  /* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf;
2197  $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2198  $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2199  $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2200  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ADDRESS), ' ')).'</AdrLine>'.$CrLf;
2201  $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;
2202  $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2203  $XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/
2204  $XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>'.$CrLf; // Field "Responsible of fees". Must be SLEV
2205  /*$XML_SEPA_INFO .= ' <CdtrSchmeId>'.$CrLf;
2206  $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2207  $XML_SEPA_INFO .= ' <PrvtId>'.$CrLf;
2208  $XML_SEPA_INFO .= ' <Othr>'.$CrLf;
2209  $XML_SEPA_INFO .= ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf;
2210  $XML_SEPA_INFO .= ' <SchmeNm>'.$CrLf;
2211  $XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>'.$CrLf;
2212  $XML_SEPA_INFO .= ' </SchmeNm>'.$CrLf;
2213  $XML_SEPA_INFO .= ' </Othr>'.$CrLf;
2214  $XML_SEPA_INFO .= ' </PrvtId>'.$CrLf;
2215  $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2216  $XML_SEPA_INFO .= ' </CdtrSchmeId>'.$CrLf;*/
2217  }
2218  } else {
2219  fputs($this->file, 'INCORRECT EMETTEUR '.$this->raison_sociale.$CrLf);
2220  $XML_SEPA_INFO = '';
2221  }
2222  return $XML_SEPA_INFO;
2223  }
2224 
2225  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2232  public function EnregTotal($total)
2233  {
2234  // phpcs:enable
2235  fputs($this->file, "08");
2236  fputs($this->file, "08"); // Prelevement ordinaire
2237 
2238  fputs($this->file, " "); // Zone Reservee B2
2239 
2240  fputs($this->file, $this->emetteur_ics); // ICS
2241 
2242  // Reserve C1
2243 
2244  fputs($this->file, substr(" ", 0, 12));
2245 
2246 
2247  // Raison Sociale C2
2248 
2249  fputs($this->file, substr(" ", 0, 24));
2250 
2251  // D1
2252 
2253  fputs($this->file, substr(" ", 0, 24));
2254 
2255  // Zone Reservee D2
2256 
2257  fputs($this->file, substr(" ", 0, 8));
2258 
2259  // Code Guichet D3
2260 
2261  fputs($this->file, substr(" ", 0, 5));
2262 
2263  // Numero de compte D4
2264 
2265  fputs($this->file, substr(" ", 0, 11));
2266 
2267  // Zone E Montant
2268 
2269  $montant = ($total * 100);
2270 
2271  fputs($this->file, substr("000000000000000".$montant, -16));
2272 
2273  // Zone Reservee F
2274 
2275  fputs($this->file, substr(" ", 0, 31));
2276 
2277  // Code etablissement
2278 
2279  fputs($this->file, substr(" ", 0, 5));
2280 
2281  // Zone Reservee F
2282 
2283  fputs($this->file, substr(" ", 0, 5));
2284 
2285  fputs($this->file, "\n");
2286  }
2287 
2294  public function getLibStatut($mode = 0)
2295  {
2296  return $this->LibStatut($this->statut, $mode);
2297  }
2298 
2299  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2307  public function LibStatut($status, $mode = 0)
2308  {
2309  // phpcs:enable
2310  if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
2311  global $langs;
2312  //$langs->load("mymodule");
2313  $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2314  $this->labelStatus[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2315  $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2316  $this->labelStatusShort[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2317  if ($this->type == 'bank-transfer') {
2318  $this->labelStatus[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2319  $this->labelStatusShort[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2320  } else {
2321  $this->labelStatus[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2322  $this->labelStatusShort[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2323  }
2324  }
2325 
2326  $statusType = 'status1';
2327  if ($status == self::STATUS_TRANSFERED) {
2328  $statusType = 'status3';
2329  }
2330  if ($status == self::STATUS_CREDITED || $status == self::STATUS_DEBITED) {
2331  $statusType = 'status6';
2332  }
2333 
2334  return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
2335  }
2336 
2337  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2345  public function load_board($user, $mode)
2346  {
2347  // phpcs:enable
2348  global $conf, $langs;
2349 
2350  if ($user->socid) {
2351  return -1; // protection pour eviter appel par utilisateur externe
2352  }
2353 
2354  /*
2355  if ($mode == 'direct_debit') {
2356  $sql = "SELECT b.rowid, f.datedue as datefin";
2357  $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
2358  $sql .= " WHERE f.entity IN (".getEntity('facture').")";
2359  $sql .= " AND f.total_ttc > 0";
2360  } else {
2361  $sql = "SELECT b.rowid, f.datedue as datefin";
2362  $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
2363  $sql .= " WHERE f.entity IN (".getEntity('facture_fourn').")";
2364  $sql .= " AND f.total_ttc > 0";
2365  }
2366 
2367  $resql = $this->db->query($sql);
2368  if ($resql) {
2369  $langs->load("banks");
2370  $now = dol_now();
2371 
2372  $response = new WorkboardResponse();
2373  if ($mode == 'direct_debit') {
2374  $response->warning_delay = $conf->prelevement->warning_delay / 60 / 60 / 24;
2375  $response->label = $langs->trans("PendingDirectDebitToComplete");
2376  $response->labelShort = $langs->trans("PendingDirectDebitToCompleteShort");
2377  $response->url = DOL_URL_ROOT.'/compta/prelevement/index.php?leftmenu=checks&mainmenu=bank';
2378  } else {
2379  $response->warning_delay = $conf->paymentbybanktransfer->warning_delay / 60 / 60 / 24;
2380  $response->label = $langs->trans("PendingCreditTransferToComplete");
2381  $response->labelShort = $langs->trans("PendingCreditTransferToCompleteShort");
2382  $response->url = DOL_URL_ROOT.'/compta/paymentbybanktransfer/index.php?leftmenu=checks&mainmenu=bank';
2383  }
2384  $response->img = img_object('', "payment");
2385 
2386  while ($obj = $this->db->fetch_object($resql)) {
2387  $response->nbtodo++;
2388 
2389  if ($this->db->jdate($obj->datefin) < ($now - $conf->withdraw->warning_delay)) {
2390  $response->nbtodolate++;
2391  }
2392  }
2393 
2394  $response->nbtodo = 0;
2395  $response->nbtodolate = 0;
2396  // Return workboard only if quantity is not 0
2397  if ($response->nbtodo) {
2398  return $response;
2399  } else {
2400  return 0;
2401  }
2402  } else {
2403  dol_print_error($this->db);
2404  $this->error = $this->db->error();
2405  return -1;
2406  }
2407  */
2408  return 0;
2409  }
2410 }
$object ref
Definition: info.php:78
Class to manage bank accounts.
Class to manage withdrawal receipts.
load_board($user, $mode)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
static buildRumNumber($row_code_client, $row_datec, $row_drum)
Generate dynamically a RUM number for a customer bank account.
SommeAPrelever($mode='direct-debit')
Returns amount waiting for direct debit payment or credit transfer payment.
EnregEmetteur($type='direct-debit')
Write sender of request (me).
EnregTotal($total)
Write end.
fetch($rowid, $ref='')
Get object and lines from database.
generate($format='ALL', $executiondate='', $type='direct-debit')
Generate a direct debit or credit transfer file.
deleteNotificationById($rowid)
Delete a notification def by id.
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)
addline(&$line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key)
Add line to withdrawal.
__construct($db)
Constructor.
EnregDestinataire($rowid, $client_nom, $rib_banque, $rib_guichet, $rib_number, $amount, $ref, $facid, $rib_dom='', $type='direct-debit')
Write recipient of request (customer)
NbFactureAPrelever($type='direct-debit')
Get number of invoices to pay.
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 ...
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Returns clickable name (with picto)
LibStatut($status, $mode=0)
Return status label for a status.
set_infotrans($user, $date, $method)
Set withdrawal to transmited status.
getErrorString($error)
Return error string.
set_infocredit($user, $date)
Set direct debit or credit transfer order to "paid" status.
nbOfInvoiceToPay($mode='direct-debit')
Get number of invoices waiting for payment.
AddFacture($invoice_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $type='debit-order')
Add invoice to withdrawal.
getLibStatut($mode=0)
Return status label of object.
getListInvoices($amounts=0)
Get invoice list.
addNotification($db, $user, $action)
Add a notification.
EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf='\n', $format='FRST', $type='direct-debit')
Write sender of request (me).
deleteNotification($user, $action)
Delete a notification.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
call_trigger($triggerName, $user)
Call trigger based on this instance.
Class to manage bank accounts description of third parties.
Class to manage suppliers invoices.
Class to manage invoices.
Class to manage payments for supplier invoices.
Class to manage payments of customer invoices.
Class to manage third parties objects (customers, suppliers, prospects...)
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
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
dol_string_unaccent($str)
Clean a string from all accent characters to be used as ref, login or by dol_sanitizeFileName.
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
dol_string_nospecial($str, $newstr='_', $badcharstoreplace='', $badcharstoremove='')
Clean a string from all punctuation characters to use it as a ref or login.
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:119
$conf db
API class for accounts.
Definition: inc.php:41