dolibarr  17.0.4
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 }
$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