dolibarr  20.0.0-alpha
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  * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
10  * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program. If not, see <https://www.gnu.org/licenses/>.
24  */
25 
32 require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php';
33 require_once DOL_DOCUMENT_ROOT . '/core/lib/bank.lib.php';
34 require_once DOL_DOCUMENT_ROOT . '/compta/bank/class/account.class.php';
35 require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
36 require_once DOL_DOCUMENT_ROOT . '/compta/paiement/class/paiement.class.php';
37 require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.facture.class.php';
38 require_once DOL_DOCUMENT_ROOT . '/fourn/class/paiementfourn.class.php';
39 require_once DOL_DOCUMENT_ROOT . '/salaries/class/salary.class.php';
40 require_once DOL_DOCUMENT_ROOT . '/salaries/class/paymentsalary.class.php';
41 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
42 require_once DOL_DOCUMENT_ROOT . '/user/class/userbankaccount.class.php';
43 
44 
49 {
53  public $element = 'widthdraw';
54 
58  public $table_element = 'prelevement_bons';
59 
63  public $picto = 'payment';
64 
65  public $date_echeance;
66  public $raison_sociale;
67  public $reference_remise;
68  public $emetteur_code_guichet;
69  public $emetteur_numero_compte;
70  public $emetteur_code_banque;
71  public $emetteur_number_key;
72  public $sepa_xml_pti_in_ctti;
73 
74  public $emetteur_iban;
75  public $emetteur_bic;
76  public $emetteur_ics;
77 
78  public $user_trans;
79  public $user_credit;
80 
81  public $total;
82  public $fetched;
83  public $labelStatus = array();
84 
85  public $factures = array();
86 
90  public $methodes_trans = array();
91 
92  public $invoice_in_error = array();
93  public $thirdparty_in_error = array();
94 
98  public $file;
99 
103  public $filename;
104 
105  const STATUS_DRAFT = 0;
106  const STATUS_TRANSFERED = 1;
107  const STATUS_CREDITED = 2; // STATUS_CREDITED and STATUS_DEBITED is same. Difference is in ->type
108  const STATUS_DEBITED = 2; // STATUS_CREDITED and STATUS_DEBITED is same. Difference is in ->type
109 
110 
150  // BEGIN MODULEBUILDER PROPERTIES
154  public $fields = array(
155  'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 10, 'notnull' => 1, 'visible' => 0,),
156  'ref' => array('type' => 'varchar(12)', 'label' => 'Ref', 'enabled' => 1, 'position' => 15, 'notnull' => 0, 'visible' => -1, 'csslist' => 'tdoverflowmax150', 'showoncombobox' => 1,),
157  'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 25, 'notnull' => 0, 'visible' => -1,),
158  'amount' => array('type' => 'double(24,8)', 'label' => 'Amount', 'enabled' => 1, 'position' => 30, 'notnull' => 0, 'visible' => -1,),
159  'statut' => array('type' => 'smallint(6)', 'label' => 'Statut', 'enabled' => 1, 'position' => 500, 'notnull' => 0, 'visible' => -1, 'arrayofkeyval' => array(0 => 'Wait', 1 => 'Transfered', 2 => 'Credited')),
160  'credite' => array('type' => 'smallint(6)', 'label' => 'Credite', 'enabled' => 1, 'position' => 40, 'notnull' => 0, 'visible' => -1,),
161  'note' => array('type' => 'text', 'label' => 'Note', 'enabled' => 1, 'position' => 45, 'notnull' => 0, 'visible' => -1,),
162  'date_trans' => array('type' => 'datetime', 'label' => 'Datetrans', 'enabled' => 1, 'position' => 50, 'notnull' => 0, 'visible' => -1,),
163  'method_trans' => array('type' => 'smallint(6)', 'label' => 'Methodtrans', 'enabled' => 1, 'position' => 55, 'notnull' => 0, 'visible' => -1,),
164  'fk_user_trans' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fkusertrans', 'enabled' => 1, 'position' => 60, 'notnull' => 0, 'visible' => -1, 'css' => 'maxwidth500 widthcentpercentminusxx', 'csslist' => 'tdoverflowmax150',),
165  'date_credit' => array('type' => 'datetime', 'label' => 'Datecredit', 'enabled' => 1, 'position' => 65, 'notnull' => 0, 'visible' => -1,),
166  'fk_user_credit' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fkusercredit', 'enabled' => 1, 'position' => 70, 'notnull' => 0, 'visible' => -1, 'css' => 'maxwidth500 widthcentpercentminusxx', 'csslist' => 'tdoverflowmax150',),
167  'type' => array('type' => 'varchar(16)', 'label' => 'Type', 'enabled' => 1, 'position' => 75, 'notnull' => 0, 'visible' => -1,),
168  'fk_bank_account' => array('type' => 'integer', 'label' => 'Fkbankaccount', 'enabled' => 1, 'position' => 80, 'notnull' => 0, 'visible' => -1, 'css' => 'maxwidth500 widthcentpercentminusxx',),
169  );
170  public $rowid;
171  public $ref;
172  public $datec;
173  public $amount;
174  public $statut;
175  public $credite;
176  public $note;
177  public $date_trans;
181  public $method_trans;
182  public $fk_user_trans;
183  public $date_credit;
184  public $fk_user_credit;
185  public $type;
186  public $fk_bank_account;
187  // END MODULEBUILDER PROPERTIES
188 
189 
190 
196  public function __construct($db)
197  {
198  $this->db = $db;
199 
200  $this->filename = '';
201 
202  $this->date_echeance = dol_now();
203  $this->raison_sociale = "";
204  $this->reference_remise = "";
205 
206  $this->emetteur_code_guichet = "";
207  $this->emetteur_numero_compte = "";
208  $this->emetteur_code_banque = "";
209  $this->emetteur_number_key = "";
210  $this->sepa_xml_pti_in_ctti = false;
211 
212  $this->emetteur_iban = "";
213  $this->emetteur_bic = "";
214  $this->emetteur_ics = "";
215 
216  $this->factures = array();
217 
218  $this->methodes_trans = array(0 => 'Internet', 2 => 'Email', 3 => 'Api');
219 
220  $this->fetched = 0;
221  }
222 
223  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
239  public function AddFacture($invoice_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $type = 'debit-order', $sourcetype = '')
240  {
241  // phpcs:enable
242  $result = 0;
243  $line_id = 0;
244 
245  // Add lines into prelevement_lignes
246  $result = $this->addline($line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $sourcetype);
247 
248 
249  if ($result == 0) {
250  if ($line_id > 0) {
251  $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement (";
252  if ($type != 'bank-transfer') {
253  $sql .= "fk_facture";
254  } else {
255  if ($sourcetype == 'salary') {
256  $sql .= "fk_salary";
257  } else {
258  $sql .= "fk_facture_fourn";
259  }
260  }
261  $sql .= ",fk_prelevement_lignes";
262  $sql .= ") VALUES (";
263  $sql .= ((int) $invoice_id);
264  $sql .= ", " . ((int) $line_id);
265  $sql .= ")";
266 
267  if ($this->db->query($sql)) {
268  $result = 0;
269  } else {
270  $result = -1;
271  $this->errors[] = get_class($this) . "::AddFacture " . $this->db->lasterror;
272  dol_syslog(get_class($this) . "::AddFacture Error $result");
273  }
274  } else {
275  $result = -2;
276  $this->errors[] = get_class($this) . "::AddFacture linedid Empty";
277  dol_syslog(get_class($this) . "::AddFacture Error $result");
278  }
279  } else {
280  $result = -3;
281  dol_syslog(get_class($this) . "::AddFacture Error $result");
282  }
283 
284  return $result;
285  }
286 
301  public function addline(&$line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $sourcetype = '')
302  {
303  $result = -1;
304  $concat = 0; // ??? what is this for. Seems not used.
305 
306  if ($concat == 1) {
307  /*
308  * We aggregate the lines
309  */
310  $sql = "SELECT rowid";
311  $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_lignes";
312  $sql .= " WHERE fk_prelevement_bons = " . ((int) $this->id);
313  if ($sourcetype == 'salary') {
314  $sql .= " AND fk_soc = " . ((int) $client_id);
315  } else {
316  $sql .= " AND fk_user = " . ((int) $client_id);
317  }
318  $sql .= " AND code_banque = '" . $this->db->escape($code_banque) . "'";
319  $sql .= " AND code_guichet = '" . $this->db->escape($code_guichet) . "'";
320  $sql .= " AND number = '" . $this->db->escape($number) . "'";
321 
322  $resql = $this->db->query($sql);
323  if ($resql) {
324  $num = $this->db->num_rows($resql);
325  } else {
326  $result = -1; // @phan-suppress-current-line PhanPluginRedundantAssignment
327  }
328  } else {
329  /*
330  * No aggregate
331  */
332  $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_lignes (";
333  $sql .= "fk_prelevement_bons";
334  $sql .= ", fk_soc";
335  $sql .= ", client_nom";
336  $sql .= ", amount";
337  $sql .= ", code_banque";
338  $sql .= ", code_guichet";
339  $sql .= ", number";
340  $sql .= ", cle_rib";
341  $sql .= ($sourcetype == 'salary' ? ", fk_user" : "");
342  $sql .= ") VALUES (";
343  $sql .= $this->id;
344  $sql .= ", " . (($sourcetype != 'salary') ? ((int) $client_id) : "0"); // fk_soc can't be null
345  $sql .= ", '" . $this->db->escape($client_nom) . "'";
346  $sql .= ", " . ((float) price2num($amount));
347  $sql .= ", '" . $this->db->escape($code_banque) . "'";
348  $sql .= ", '" . $this->db->escape($code_guichet) . "'";
349  $sql .= ", '" . $this->db->escape($number) . "'";
350  $sql .= ", '" . $this->db->escape($number_key) . "'";
351  $sql .= (($sourcetype == 'salary') ? ", " . ((int) $client_id) : '');
352  $sql .= ")";
353  if ($this->db->query($sql)) {
354  $line_id = $this->db->last_insert_id(MAIN_DB_PREFIX . "prelevement_lignes");
355  $result = 0;
356  } else {
357  $this->errors[] = get_class($this) . "::addline Error -2 " . $this->db->lasterror;
358  dol_syslog(get_class($this) . "::addline Error -2");
359  $result = -2;
360  }
361  }
362 
363  return $result;
364  }
365 
372  public function getErrorString($error)
373  {
374  global $langs;
375 
376  $errors = array();
377 
378  $errors[1027] = $langs->trans("DateInvalid");
379 
380  return $errors[abs($error)];
381  }
382 
390  public function fetch($rowid, $ref = '')
391  {
392  $sql = "SELECT p.rowid, p.ref, p.amount, p.note";
393  $sql .= ", p.datec as dc";
394  $sql .= ", p.date_trans as date_trans";
395  $sql .= ", p.method_trans, p.fk_user_trans";
396  $sql .= ", p.date_credit as date_credit";
397  $sql .= ", p.fk_user_credit";
398  $sql .= ", p.type";
399  $sql .= ", p.fk_bank_account";
400  $sql .= ", p.statut as status";
401  $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons as p";
402  $sql .= " WHERE p.entity IN (" . getEntity('invoice') . ")";
403  if ($rowid > 0) {
404  $sql .= " AND p.rowid = " . ((int) $rowid);
405  } else {
406  $sql .= " AND p.ref = '" . $this->db->escape($ref) . "'";
407  }
408 
409  dol_syslog(get_class($this) . "::fetch", LOG_DEBUG);
410  $result = $this->db->query($sql);
411  if ($result) {
412  if ($this->db->num_rows($result)) {
413  $obj = $this->db->fetch_object($result);
414 
415  $this->id = $obj->rowid;
416  $this->ref = $obj->ref;
417  $this->amount = $obj->amount;
418  $this->note = $obj->note;
419  $this->datec = $this->db->jdate($obj->dc);
420 
421  $this->date_trans = $this->db->jdate($obj->date_trans);
422  $this->method_trans = $obj->method_trans;
423  $this->user_trans = $obj->fk_user_trans;
424 
425  $this->date_credit = $this->db->jdate($obj->date_credit);
426  $this->user_credit = $obj->fk_user_credit;
427 
428  $this->type = $obj->type;
429  $this->fk_bank_account = $obj->fk_bank_account;
430 
431  $this->status = $obj->status;
432  $this->statut = $obj->status; // For backward compatibility
433 
434  $this->fetched = 1;
435 
436  return 1;
437  } else {
438  dol_syslog(get_class($this) . "::Fetch Erreur aucune ligne retournee");
439  return -1;
440  }
441  } else {
442  return -2;
443  }
444  }
445 
453  public function update(User $user, $notrigger = 0)
454  {
455  return $this->updateCommon($user, $notrigger);
456  }
457 
458  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
468  public function set_infocredit($user, $date, $type = '')
469  {
470  // phpcs:enable
471  global $conf, $langs;
472 
473  $error = 0;
474 
475  if ($this->fetched == 1) {
476  if ($date < $this->date_trans) {
477  $langs->load("errors");
478  $this->error = $langs->trans('ErrorDateOfMovementLowerThanDateOfFileTransmission');
479  dol_syslog("bon-prelevment::set_infocredit 1027 " . $this->error);
480  return -1027;
481  }
482 
483  $this->db->begin();
484 
485  $sql = " UPDATE " . MAIN_DB_PREFIX . "prelevement_bons";
486  $sql .= " SET fk_user_credit = " . ((int) $user->id);
487  $sql .= ", statut = " . self::STATUS_CREDITED;
488  $sql .= ", date_credit = '" . $this->db->idate($date) . "'";
489  $sql .= " WHERE rowid = " . ((int) $this->id);
490  $sql .= " AND entity = " . ((int) $conf->entity);
491  $sql .= " AND statut = " . self::STATUS_TRANSFERED;
492 
493  $resql = $this->db->query($sql);
494  if ($resql) {
495  $langs->load('withdrawals');
496  $subject = $langs->trans("InfoCreditSubject", $this->ref);
497  $message = $langs->trans("InfoCreditMessage", $this->ref, dol_print_date($date, 'dayhour'));
498 
499  // Add payment of withdrawal into bank
500  $fk_bank_account = $this->fk_bank_account;
501  if (empty($fk_bank_account)) {
502  $fk_bank_account = ($this->type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
503  }
504 
505  $facs = array();
506  $amounts = array();
507  $amountsperthirdparty = array();
508 
509  $facs = $this->getListInvoices(1, $type);
510  if ($this->error) {
511  $error++;
512  }
513 
514  // Loop on each invoice or salary.
515  // $facs should be array(0=>id, 1=>amount requested)
516  $num = count($facs);
517  for ($i = 0; $i < $num; $i++) {
518  if ($this->type == 'bank-transfer') {
519  if ($type == 'salary') {
520  $fac = new Salary($this->db);
521  } else {
522  $fac = new FactureFournisseur($this->db);
523  }
524  } else {
525  $fac = new Facture($this->db);
526  }
527 
528  $result = $fac->fetch($facs[$i][0]);
529 
530  $amounts[$fac->id] = $facs[$i][1];
531  if ($this->type == 'bank-transfer') {
532  if ($type == 'salary') {
533  $amountsperthirdparty[$fac->fk_user][$fac->id] = $facs[$i][1];
534  } else {
535  $amountsperthirdparty[$fac->socid][$fac->id] = $facs[$i][1];
536  }
537  } else {
538  $amountsperthirdparty[$fac->socid][$fac->id] = $facs[$i][1];
539  }
540 
541  $totalpaid = $fac->getSommePaiement();
542  $totalcreditnotes = 0;
543  if (method_exists($fac, 'getSumCreditNotesUsed')) {
544  $totalcreditnotes = $fac->getSumCreditNotesUsed();
545  }
546  $totaldeposits = 0;
547  if (method_exists($fac, 'getSumDepositsUsed')) {
548  $totaldeposits = $fac->getSumDepositsUsed();
549  }
550  $alreadypayed = $totalpaid + $totalcreditnotes + $totaldeposits;
551 
552  // Set the main document to pay with status Paid.
553  // @TODO Move this after creation of payments done after
554  $amountofdocument = $fac->total_ttc;
555  if ($type == 'salary') {
556  $amountofdocument = $fac->amount;
557  }
558  if (price2num($alreadypayed + $facs[$i][1], 'MT') == price2num($amountofdocument, 'MT')) {
559  $result = $fac->setPaid($user);
560  if ($result < 0) {
561  $this->error = $fac->error;
562  $this->errors = $fac->errors;
563  }
564  }
565  }
566 
567  // Make one payment per customer or employee
568  foreach ($amountsperthirdparty as $thirdpartyid => $cursoramounts) {
569  if ($this->type == 'bank-transfer') {
570  if ($type == 'salary') {
571  $paiement = new PaymentSalary($this->db);
572  } else {
573  $paiement = new PaiementFourn($this->db);
574  }
575  } else {
576  $paiement = new Paiement($this->db);
577  }
578  $paiement->datepaye = $date;
579  $paiement->amounts = $cursoramounts; // Array with detail of dispatching of payments for each invoice
580 
581  if ($this->type == 'bank-transfer') {
582  if ($type == 'salary') {
583  $paiement->datep = $date;
584 
585  $paiement->paiementid = 2;
586  $paiement->fk_typepayment = 2;
587  $paiement->paiementcode = 'VIR';
588  } else {
589  $paiement->paiementid = 2;
590  $paiement->paiementcode = 'VIR';
591  }
592  } else {
593  $paiement->paiementid = 3;
594  $paiement->paiementcode = 'PRE';
595  }
596 
597  $paiement->num_payment = $this->ref; // Set ref of direct debit note
598  $paiement->id_prelevement = $this->id;
599 
600  $result = $paiement->create($user); // This use ->paiementid, that is ID of payment mode
601 
602  if ($result < 0) {
603  $error++;
604  $this->error = $paiement->error;
605  $this->errors = $paiement->errors;
606  dol_syslog(get_class($this) . "::set_infocredit AddPayment Error " . $this->error);
607  } else {
608  if ($this->type == 'bank-transfer') {
609  if ($type == 'salary') {
610  $modeforaddpayment = 'payment_salary';
611  $labelforaddpayment = '(SalaryPayment)';
612  $addbankurl = 'credit-transfer';
613  } else {
614  $modeforaddpayment = 'payment_supplier';
615  $labelforaddpayment = '(SupplierInvoicePayment)';
616  $addbankurl = 'credit-transfer';
617  }
618  } else {
619  $modeforaddpayment = 'payment';
620  $labelforaddpayment = '(CustomerInvoicePayment)';
621  $addbankurl = 'direct-debit'; // = 'directdebit'
622  }
623 
624  $result = $paiement->addPaymentToBank($user, $modeforaddpayment, $labelforaddpayment, $fk_bank_account, '', '', 0, '', $addbankurl);
625 
626  if ($result < 0) {
627  $error++;
628  $this->error = $paiement->error;
629  $this->errors = $paiement->errors;
630  dol_syslog(get_class($this) . "::set_infocredit AddPaymentToBank Error " . $this->error);
631  }
632  }
633  }
634 
635  // Update withdrawal line
636  // TODO: Translate to ligneprelevement.class.php
637  if (!$error) {
638  $sql = " UPDATE " . MAIN_DB_PREFIX . "prelevement_lignes";
639  $sql .= " SET statut = 2";
640  $sql .= " WHERE fk_prelevement_bons = " . ((int) $this->id);
641 
642  if (!$this->db->query($sql)) {
643  dol_syslog(get_class($this) . "::set_infocredit Update lines Error");
644  $error++;
645  }
646  }
647  } else {
648  $this->error = $this->db->lasterror();
649  dol_syslog(get_class($this) . "::set_infocredit Update Bons Error");
650  $error++;
651  }
652 
653  // End of procedure
654  if ($error == 0) {
655  $this->date_credit = $date; // date credit or debit
656  $this->statut = self::STATUS_CREDITED;
657  $this->status = self::STATUS_CREDITED;
658 
659  $this->db->commit();
660  return 0;
661  } else {
662  $this->db->rollback();
663  return -1;
664  }
665  } else {
666  return -1026;
667  }
668  }
669 
670  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
679  public function set_infotrans($user, $date, $method)
680  {
681  // phpcs:enable
682  global $conf, $langs;
683 
684  $error = 0;
685 
686  dol_syslog(get_class($this) . "::set_infotrans Start", LOG_INFO);
687 
688  if ($this->db->begin()) {
689  $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_bons ";
690  $sql .= " SET fk_user_trans = " . $user->id;
691  $sql .= " , date_trans = '" . $this->db->idate($date) . "'";
692  $sql .= " , method_trans = " . ((int) $method);
693  $sql .= " , statut = " . self::STATUS_TRANSFERED;
694  $sql .= " WHERE rowid = " . ((int) $this->id);
695  $sql .= " AND entity = " . ((int) $conf->entity);
696  $sql .= " AND statut = " . self::STATUS_DRAFT;
697 
698  if ($this->db->query($sql)) {
699  $this->method_trans = $method;
700  $langs->load('withdrawals');
701  $subject = $langs->trans("InfoTransSubject", $this->ref);
702  $message = $langs->trans("InfoTransMessage", $this->ref, dolGetFirstLastname($user->firstname, $user->lastname));
703  $message .= $langs->trans("InfoTransData", price($this->amount), $this->methodes_trans[$this->method_trans], dol_print_date($date, 'day'));
704 
705  // TODO Call trigger to create a notification using notification module
706  } else {
707  $error++;
708  }
709 
710  if ($error == 0) {
711  $this->date_trans = $date;
712  $this->statut = self::STATUS_TRANSFERED;
713  $this->status = self::STATUS_TRANSFERED;
714  $this->user_trans = $user->id;
715 
716  $this->db->commit();
717 
718  return 0;
719  } else {
720  $this->db->rollback();
721  dol_syslog(get_class($this) . "::set_infotrans ROLLBACK", LOG_ERR);
722 
723  return -1;
724  }
725  } else {
726  dol_syslog(get_class($this) . "::set_infotrans Ouverture transaction SQL impossible", LOG_CRIT);
727  return -2;
728  }
729  }
730 
738  private function getListInvoices($amounts = 0, $type = '')
739  {
740  global $conf;
741 
742  $arr = array();
743 
744  dol_syslog(get_class($this) . "::getListInvoices");
745 
746  // Returns all invoices presented within same order
747  $sql = "SELECT ";
748  if ($this->type == 'bank-transfer') {
749  if ($type == 'salary') {
750  $sql .= " p.fk_salary";
751  } else {
752  $sql .= " p.fk_facture_fourn";
753  }
754  } else {
755  $sql .= " p.fk_facture";
756  }
757  if ($amounts) {
758  $sql .= ", SUM(pl.amount)";
759  }
760  $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons as pb,";
761  $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
762  $sql .= " " . MAIN_DB_PREFIX . "prelevement as p";
763  $sql .= " WHERE p.fk_prelevement_lignes = pl.rowid";
764  $sql .= " AND pl.fk_prelevement_bons = pb.rowid";
765  $sql .= " AND pb.rowid = " . ((int) $this->id);
766  $sql .= " AND pb.entity = " . ((int) $conf->entity);
767  if ($amounts) {
768  if ($this->type == 'bank-transfer') {
769  if ($type == 'salary') {
770  $sql .= " GROUP BY p.fk_salary";
771  } else {
772  $sql .= " GROUP BY p.fk_facture_fourn";
773  }
774  } else {
775  $sql .= " GROUP BY p.fk_facture";
776  }
777  }
778 
779  $resql = $this->db->query($sql);
780  if ($resql) {
781  $num = $this->db->num_rows($resql);
782 
783  if ($num) {
784  $i = 0;
785  while ($i < $num) {
786  $row = $this->db->fetch_row($resql);
787  if (!$amounts) {
788  $arr[$i] = $row[0];
789  } else {
790  $arr[$i] = array(
791  $row[0],
792  $row[1]
793  );
794  }
795  $i++;
796  }
797  }
798  $this->db->free($resql);
799  } else {
800  $this->error = $this->db->lasterror();
801  }
802 
803  return $arr;
804  }
805 
806  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
814  public function SommeAPrelever($mode = 'direct-debit', $type = '')
815  {
816  // phpcs:enable
817  $sql = "SELECT sum(pd.amount) as nb";
818  if ($type !== 'salary') {
819  if ($mode != 'bank-transfer') {
820  $sql .= " FROM " . MAIN_DB_PREFIX . "facture as f,";
821  } else {
822  $sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f,";
823  }
824  } else {
825  $sql .= " FROM " . MAIN_DB_PREFIX . "salary as s,";
826  }
827  $sql .= " " . MAIN_DB_PREFIX . "prelevement_demande as pd";
828  $sql .= ($type !== 'salary' ? " WHERE f.entity IN (" . getEntity('invoice') . ")" : " WHERE s.entity IN (" . getEntity('salary') . ")");
829  if (!getDolGlobalString('WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS')) {
830  $sql .= ($type !== 'salary' ? " AND f.fk_statut = " . Facture::STATUS_VALIDATED : " AND s.paye = " . Salary::STATUS_UNPAID);
831  }
832  if ($type !== 'salary') {
833  if ($mode != 'bank-transfer') {
834  $sql .= " AND f.rowid = pd.fk_facture";
835  } else {
836  $sql .= " AND f.rowid = pd.fk_facture_fourn";
837  }
838  } else {
839  $sql .= " AND s.rowid = pd.fk_salary";
840  }
841  $sql .= ($type !== 'salary' ? " AND f.paye = 0" : "");
842  $sql .= " AND pd.traite = 0";
843  $sql .= " AND pd.ext_payment_id IS NULL";
844  $sql .= ($type !== 'salary' ? " AND f.total_ttc > 0" : "");
845 
846  $resql = $this->db->query($sql);
847  if ($resql) {
848  $obj = $this->db->fetch_object($resql);
849 
850  $this->db->free($resql);
851 
852  return $obj->nb;
853  } else {
854  $error = 1;
855  dol_syslog(get_class($this) . "::SommeAPrelever Erreur -1");
856  dol_syslog($this->db->error());
857 
858  return -1;
859  }
860  }
861 
869  public function nbOfInvoiceToPay($mode = 'direct-debit', $type = '')
870  {
871  if ($type === 'salary') {
872  return $this->NbFactureAPrelever($mode, 1);
873  } else {
874  return $this->NbFactureAPrelever($mode);
875  }
876  }
877 
878  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
886  public function NbFactureAPrelever($type = 'direct-debit', $forsalary = 0)
887  {
888  // phpcs:enable
889  if ($forsalary == 1) {
890  $sql = "SELECT count(s.rowid) as nb";
891  $sql .= " FROM " . MAIN_DB_PREFIX . "salary as s";
892  } else {
893  $sql = "SELECT count(f.rowid) as nb";
894 
895  if ($type == 'bank-transfer') {
896  $sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
897  } else {
898  $sql .= " FROM " . MAIN_DB_PREFIX . "facture as f";
899  }
900  }
901  $sql .= ", " . MAIN_DB_PREFIX . "prelevement_demande as pd";
902  if ($forsalary == 1) {
903  $sql .= " WHERE s.entity IN (" . getEntity('invoice') . ")";
904  if (!getDolGlobalString('WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS')) {
905  $sql .= " AND s.paye = 0";
906  }
907  } else {
908  $sql .= " WHERE f.entity IN (" . getEntity('invoice') . ")";
909  if (!getDolGlobalString('WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS')) {
910  $sql .= " AND f.fk_statut = " . Facture::STATUS_VALIDATED;
911  }
912  }
913  if ($forsalary == 1) {
914  $sql .= " AND s.rowid = pd.fk_salary";
915  } else {
916  if ($type == 'bank-transfer') {
917  $sql .= " AND f.rowid = pd.fk_facture_fourn";
918  } else {
919  $sql .= " AND f.rowid = pd.fk_facture";
920  }
921  }
922  $sql .= " AND pd.traite = 0";
923  $sql .= " AND pd.ext_payment_id IS NULL";
924  if (!$forsalary == 1) {
925  $sql .= " AND f.total_ttc > 0";
926  } else {
927  $sql .= " AND s.paye = 0";
928  }
929 
930  dol_syslog(get_class($this) . "::NbFactureAPrelever");
931  $resql = $this->db->query($sql);
932 
933  if ($resql) {
934  $obj = $this->db->fetch_object($resql);
935  $this->db->free($resql);
936 
937  return $obj->nb;
938  } else {
939  $this->error = get_class($this) . "::NbFactureAPrelever Erreur -1 sql=" . $this->db->error();
940  return -1;
941  }
942  }
943 
944 
945  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
966  public function create($banque = 0, $agence = 0, $mode = 'real', $format = 'ALL', $executiondate = '', $notrigger = 0, $type = 'direct-debit', $did = 0, $fk_bank_account = 0, $sourcetype = 'invoice')
967  {
968  // phpcs:enable
969  global $conf, $langs, $user;
970 
971  dol_syslog(__METHOD__ . " Bank=" . $banque . " Office=" . $agence . " mode=" . $mode . " format=" . $format, LOG_DEBUG);
972 
973  require_once DOL_DOCUMENT_ROOT . "/compta/facture/class/facture.class.php";
974  require_once DOL_DOCUMENT_ROOT . "/societe/class/societe.class.php";
975 
976  // Check params
977  if ($type != 'bank-transfer') {
978  if (empty($format)) {
979  $this->error = 'ErrorBadParametersForDirectDebitFileCreate';
980  return -1;
981  }
982  }
983 
984  // Clean params
985  if (empty($fk_bank_account)) {
986  $fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
987  }
988 
989  $error = 0;
990 
991  $datetimeprev = dol_now('gmt');
992  // Choice the date of the execution direct debit
993  if (!empty($executiondate)) {
994  $datetimeprev = $executiondate;
995  }
996 
997  $month = dol_print_date($datetimeprev, "%m", 'gmt');
998  $year = dol_print_date($datetimeprev, "%Y", 'gmt');
999 
1000  $this->invoice_in_error = array();
1001  $this->thirdparty_in_error = array();
1002 
1003  // Read invoices
1004  $factures = array();
1005  $factures_prev = array();
1006  $factures_result = array();
1007  $factures_prev_id = array();
1008  $factures_errors = array();
1009  if (!$error) {
1010  dol_syslog(__METHOD__ . " Read invoices for did=" . ((int) $did), LOG_DEBUG);
1011 
1012  $sql = "SELECT f.rowid, pd.rowid as pfdrowid";
1013  if ($sourcetype != 'salary') {
1014  $sql .= ", f.fk_soc";
1015  } else {
1016  $sql .= ", f.fk_user";
1017  }
1018  $sql .= ", pd.code_banque, pd.code_guichet, pd.number, pd.cle_rib";
1019  $sql .= ", pd.amount";
1020  if ($sourcetype != 'salary') {
1021  $sql .= ", s.nom as name";
1022  $sql .= ", f.ref, sr.bic, sr.iban_prefix, sr.frstrecur";
1023  } else {
1024  $sql .= ", CONCAT(s.firstname,' ',s.lastname) as name";
1025  $sql .= ", f.ref, sr.bic, sr.iban_prefix, 'FRST' as frstrecur";
1026  }
1027  if ($sourcetype != 'salary') {
1028  if ($type != 'bank-transfer') {
1029  $sql .= " FROM " . MAIN_DB_PREFIX . "facture as f";
1030  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "prelevement_demande as pd ON f.rowid = pd.fk_facture";
1031  } else {
1032  $sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
1033  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "prelevement_demande as pd ON f.rowid = pd.fk_facture_fourn";
1034  }
1035  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe as s ON s.rowid = f.fk_soc";
1036  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe_rib as sr ON s.rowid = sr.fk_soc AND sr.default_rib = 1";
1037  } else {
1038  $sql .= " FROM " . MAIN_DB_PREFIX . "salary as f";
1039  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "prelevement_demande as pd ON f.rowid = pd.fk_salary";
1040  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "user as s ON s.rowid = f.fk_user";
1041  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "user_rib as sr ON s.rowid = sr.fk_user"; // TODO Add AND sr.default_rib = 1 here
1042  }
1043  if ($sourcetype != 'salary') {
1044  if ($type != 'bank-transfer') {
1045  $sql .= " WHERE f.entity IN (" . getEntity('invoice') . ')';
1046  } else {
1047  $sql .= " WHERE f.entity IN (" . getEntity('supplier_invoice') . ')';
1048  }
1049  } else {
1050  $sql .= " WHERE f.entity IN (" . getEntity('salary') . ')';
1051  }
1052  if ($sourcetype != 'salary') {
1053  $sql .= " AND f.fk_statut = 1"; // Invoice validated
1054  $sql .= " AND f.paye = 0";
1055  $sql .= " AND f.total_ttc > 0";
1056  } else {
1057  //$sql .= " AND f.fk_statut = 1"; // Invoice validated
1058  $sql .= " AND f.paye = 0";
1059  $sql .= " AND f.amount > 0";
1060  }
1061  $sql .= " AND pd.traite = 0";
1062  $sql .= " AND pd.ext_payment_id IS NULL";
1063  if ($sourcetype != 'salary') {
1064  $sql .= " AND sr.type = 'ban'"; // TODO Add AND sr.type = 'ban' for users too
1065  }
1066  if ($did > 0) {
1067  $sql .= " AND pd.rowid = " . ((int) $did);
1068  }
1069 
1070  $resql = $this->db->query($sql);
1071  if ($resql) {
1072  $num = $this->db->num_rows($resql);
1073  $i = 0;
1074 
1075  while ($i < $num) {
1076  $row = $this->db->fetch_row($resql); // TODO Replace with fetch_object()
1077  $factures[$i] = $row; // All fields
1078 
1079  if ($row[7] == 0) {
1080  $error++;
1081  dol_syslog(__METHOD__ . " Read invoices/salary error Found a null amount", LOG_ERR);
1082  $this->invoice_in_error[$row[0]] = "Error for invoice or salary id " . $row[0] . ", found a null amount";
1083  break;
1084  }
1085  $i++;
1086  }
1087 
1088  $this->db->free($resql);
1089  dol_syslog(__METHOD__ . " Read invoices/salary, " . $i . " invoices/salary to withdraw", LOG_DEBUG);
1090  } else {
1091  $error++;
1092  $this->error = $this->db->lasterror();
1093  dol_syslog(__METHOD__ . " Read invoices/salary error " . $this->db->lasterror(), LOG_ERR);
1094  return -1;
1095  }
1096  }
1097 
1098  if (!$error) {
1099  // Make some checks
1100  require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
1101  require_once DOL_DOCUMENT_ROOT . '/user/class/user.class.php';
1102  require_once DOL_DOCUMENT_ROOT . '/societe/class/companybankaccount.class.php';
1103  require_once DOL_DOCUMENT_ROOT . '/core/lib/bank.lib.php';
1104 
1105  $tmpsoc = new Societe($this->db);
1106  $tmpuser = new User($this->db);
1107 
1108  // Check BAN
1109  $i = 0;
1110  dol_syslog(__METHOD__ . " Check BAN", LOG_DEBUG);
1111 
1112  if (count($factures) > 0) {
1113  foreach ($factures as $key => $fac) {
1114  /*
1115  if ($type != 'bank-transfer') {
1116  $tmpinvoice = new Facture($this->db);
1117  } else {
1118  $tmpinvoice = new FactureFournisseur($this->db);
1119  }
1120  $resfetch = $tmpinvoice->fetch($fac[0]);
1121  if ($resfetch >= 0) { // Field 0 of $fac is rowid of invoice
1122  */
1123 
1124  // Check if $fac[8] s.nom is null
1125  if ($fac[8] != null) {
1126  if ($type != 'bank-transfer') {
1127  if ($format == 'FRST' && $fac[12] != 'FRST') {
1128  continue;
1129  }
1130  if ($format == 'RCUR' && $fac[12] != 'RCUR') {
1131  continue;
1132  }
1133  }
1134 
1135  $verif = checkSwiftForAccount(null, $fac[10]);
1136  if ($verif) {
1137  $verif = checkIbanForAccount(null, $fac[11]);
1138  }
1139 
1140  if ($verif) {
1141  $factures_prev[$i] = $fac;
1142  /* second array necessary for BonPrelevement */
1143  $factures_prev_id[$i] = $fac[0];
1144  $i++;
1145  //dol_syslog(__METHOD__."::RIB is ok", LOG_DEBUG);
1146  } else {
1147  if ($type != 'bank-transfer') {
1148  $tmpsoc->id = $fac[2];
1149  $tmpsoc->name = $fac[8];
1150  $invoice_url = "<a href='" . DOL_URL_ROOT . '/compta/facture/card.php?facid=' . $fac[0] . "'>" . $fac[9] . "</a>";
1151  $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1152  $this->thirdparty_in_error[$tmpsoc->id] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1153  $error++;
1154  }
1155  if ($type == 'bank-transfer' && $sourcetype != 'salary') {
1156  $tmpsoc->id = $fac[2];
1157  $tmpsoc->name = $fac[8];
1158  $invoice_url = "<a href='" . DOL_URL_ROOT . '/fourn/facture/card.php?facid=' . $fac[0] . "'>" . $fac[9] . "</a>";
1159  $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1160  $this->thirdparty_in_error[$tmpsoc->id] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1161  $error++;
1162  }
1163  if ($type == 'bank-transfer' && $sourcetype == 'salary') {
1164  $tmpuser->id = $fac[2];
1165  $tmpuser->firstname = $fac[8];
1166  $salary_url = "<a href='" . DOL_URL_ROOT . '/salaries/card.php?id=' . $fac[0] . "'>" . $fac[0] . "</a>";
1167  $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for salary " . $salary_url . " for employee " . $tmpuser->getNomUrl(0);
1168  $this->thirdparty_in_error[$tmpuser->id] = "Error on default bank number IBAN/BIC for salary " . $salary_url . " for employee " . $tmpuser->getNomUrl(0);
1169  $error++;
1170  }
1171  dol_syslog(__METHOD__ . " Check BAN Error on default bank number IBAN/BIC reported by verif(): " . implode(', ', $fac), LOG_WARNING);
1172  }
1173  } else {
1174  dol_syslog(__METHOD__ . " Check BAN Failed to read company", LOG_WARNING);
1175  }
1176  /*
1177  } else {
1178  dol_syslog(__METHOD__." Check BAN Failed to read invoice", LOG_WARNING);
1179  }
1180  */
1181  }
1182  } else {
1183  dol_syslog(__METHOD__ . " Check BAN No invoice to process", LOG_WARNING);
1184  }
1185  }
1186 
1187  $ok = 0;
1188 
1189  // Withdraw invoices in factures_prev array
1190  $out = count($factures_prev) . " invoices will be included.";
1191  //print $out."\n";
1192  dol_syslog($out);
1193 
1194  // Return warning
1195  /*$i=0;
1196  foreach ($this->thirdparty_in_error as $key => $val)
1197  {
1198  if ($i < 10) setEventMessages($val, null, 'warnings');
1199  else setEventMessages('More error were discarded...', null, 'warnings');
1200  $i++;
1201  }*/
1202 
1203  if (count($factures_prev) > 0) {
1204  if ($mode == 'real') {
1205  $ok = 1;
1206  } else {
1207  print $langs->trans("ModeWarning"); // "Option for real mode was not set, we stop after this simulation\n";
1208  }
1209  }
1210  if ($ok) {
1211  /*
1212  * We are in real mode.
1213  * We create order and build file into disk
1214  */
1215  $this->db->begin();
1216 
1217  $now = dol_now();
1218  $ref = '';
1219 
1220  /*
1221  * Process order generation
1222  */
1223  if (!$error) {
1224  $ref = substr($year, -2) . $month;
1225 
1226  // Get next free number for the ref of bon prelevement
1227  $sql = "SELECT substring(ref from char_length(ref) - 1)"; // To extract "YYMMXX" from "TYYMMXX"
1228  $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons";
1229  $sql .= " WHERE ref LIKE '_" . $this->db->escape($ref) . "%'";
1230  $sql .= " AND entity = " . ((int) $conf->entity);
1231  $sql .= " ORDER BY ref DESC LIMIT 1";
1232 
1233  dol_syslog(get_class($this) . " get next free number", LOG_DEBUG);
1234  $resql = $this->db->query($sql);
1235 
1236  if ($resql) {
1237  $row = $this->db->fetch_row($resql);
1238 
1239  // Build the new ref
1240  $ref = "T" . $ref . sprintf("%02d", (intval($row[0]) + 1));
1241 
1242  // $conf->abc->dir_output may be:
1243  // /home/ldestailleur/git/dolibarr_15.0/documents/abc/
1244  // or
1245  // /home/ldestailleur/git/dolibarr_15.0/documents/X/abc with X >= 2 with multicompany.
1246  if ($type != 'bank-transfer') {
1247  $dir = $conf->prelevement->dir_output . '/receipts';
1248  } else {
1249  $dir = $conf->paymentbybanktransfer->dir_output . '/receipts';
1250  }
1251  if (!is_dir($dir)) {
1252  dol_mkdir($dir);
1253  }
1254 
1255  if (isModEnabled('multicompany')) {
1256  $labelentity = $conf->entity;
1257  $this->filename = $dir . '/' . $ref . '-' . $labelentity . '.xml';
1258  } else {
1259  $this->filename = $dir . '/' . $ref . '.xml';
1260  }
1261 
1262  // Create withdraw order in database
1263  $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_bons (";
1264  $sql .= "ref, entity, datec, type, fk_bank_account";
1265  $sql .= ") VALUES (";
1266  $sql .= "'" . $this->db->escape($ref) . "'";
1267  $sql .= ", " . ((int) $conf->entity);
1268  $sql .= ", '" . $this->db->idate($now) . "'";
1269  $sql .= ", '" . ($type == 'bank-transfer' ? 'bank-transfer' : 'debit-order') . "'";
1270  $sql .= ", " . ((int) $fk_bank_account);
1271  $sql .= ")";
1272 
1273  $resql = $this->db->query($sql);
1274 
1275 
1276  if ($resql) {
1277  $prev_id = $this->db->last_insert_id(MAIN_DB_PREFIX . "prelevement_bons");
1278  $this->id = $prev_id;
1279  $this->ref = $ref;
1280  } else {
1281  $error++;
1282  dol_syslog(__METHOD__ . " Create withdraw receipt " . $this->db->lasterror(), LOG_ERR);
1283  }
1284  } else {
1285  $error++;
1286  dol_syslog(__METHOD__ . " Get last withdraw receipt " . $this->db->lasterror(), LOG_ERR);
1287  }
1288  }
1289 
1290  if (!$error) {
1291  dol_syslog(__METHOD__ . " Now loop on each document to insert them in llx_prelevement_demande");
1292 
1293  // Add lines for the bon
1294  if (count($factures_prev) > 0) {
1295  foreach ($factures_prev as $fac) { // Add a link in database for each invoice ro salary
1296  /*
1297  * Add standing order. This add record into llx_prelevement_lignes and llx_prelevement
1298  *
1299  * $fac[0] : invoice_id
1300  * $fac[1] : ???
1301  * $fac[2] : third party id
1302  * $fac[3] : banque
1303  * $fac[4] : guichet
1304  * $fac[5] : number
1305  * $fac[6] : cle rib
1306  * $fac[7] : amount
1307  * $fac[8] : client nom
1308  * $fac[9] : Invoice ref
1309  * $fac[10] : BIC
1310  * $fac[11] : IBAN
1311  * $fac[12] : frstrcur
1312  */
1313  $ri = $this->AddFacture($fac[0], $fac[2], $fac[8], $fac[7], $fac[3], $fac[4], $fac[5], $fac[6], $type, $sourcetype);
1314 
1315  if ($ri != 0) {
1316  $error++;
1317  }
1318 
1319  // Update invoice requests as done
1320  $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_demande";
1321  $sql .= " SET traite = 1";
1322  $sql .= ", date_traite = '" . $this->db->idate($now) . "'";
1323  $sql .= ", fk_prelevement_bons = " . ((int) $this->id);
1324  $sql .= " WHERE rowid = " . ((int) $fac[1]);
1325 
1326  $resql = $this->db->query($sql);
1327  if (!$resql) {
1328  $error++;
1329  $this->errors[] = $this->db->lasterror();
1330  dol_syslog(__METHOD__ . " Update Error=" . $this->db->lasterror(), LOG_ERR);
1331  }
1332  }
1333  }
1334  }
1335 
1336  if (!$error) {
1337  /*
1338  * Create file of type='direct-debit' for direct debit order or type='bank-transfer' for credit transfer into a XML file
1339  */
1340 
1341  dol_syslog(__METHOD__ . " Init direct debit or credit transfer file for " . count($factures_prev) . " invoices", LOG_DEBUG);
1342 
1343  if (count($factures_prev) > 0) {
1344  $this->date_echeance = $datetimeprev;
1345  $this->reference_remise = $ref;
1346 
1347  $account = new Account($this->db);
1348  if ($account->fetch($fk_bank_account) > 0) {
1349  $this->emetteur_code_banque = $account->code_banque;
1350  $this->emetteur_code_guichet = $account->code_guichet;
1351  $this->emetteur_numero_compte = $account->number;
1352  $this->emetteur_number_key = $account->cle_rib;
1353  $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
1354  $this->emetteur_iban = $account->iban;
1355  $this->emetteur_bic = $account->bic;
1356 
1357  $this->emetteur_ics = (($type == 'bank-transfer' && getDolGlobalString("SEPA_USE_IDS")) ? $account->ics_transfer : $account->ics); // Example "FR78ZZZ123456"
1358 
1359  $this->raison_sociale = $account->proprio;
1360  }
1361  $this->factures = $factures_prev_id;
1362  $this->context['factures_prev'] = $factures_prev;
1363  // Generation of direct debit or credit transfer file $this->filename (May be a SEPA file for european countries)
1364  // This also set the property $this->total with amount that is included into file
1365  $userid = 0;
1366  if ($sourcetype == 'salary') {
1367  $userid = $this->context['factures_prev'][0][2];
1368  }
1369  $result = $this->generate($format, $executiondate, $type, $fk_bank_account, $userid);
1370  if ($result < 0) {
1371  //var_dump($this->error);
1372  //var_dump($this->invoice_in_error);
1373  $error++;
1374  }
1375  }
1376  dol_syslog(__METHOD__ . " Bank order file has been generated under filename " . $this->filename, LOG_DEBUG);
1377  }
1378 
1379 
1380  /*
1381  * Update total defined after generation of file
1382  */
1383  if (!$error) {
1384  $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_bons";
1385  $sql .= " SET amount = " . price2num($this->total);
1386  $sql .= " WHERE rowid = " . ((int) $this->id);
1387  $sql .= " AND entity = " . ((int) $conf->entity);
1388  $resql = $this->db->query($sql);
1389 
1390  if (!$resql) {
1391  $error++;
1392  dol_syslog(__METHOD__ . " Error update total: " . $this->db->error(), LOG_ERR);
1393  }
1394  }
1395 
1396  if (!$error && !$notrigger) {
1397  $triggername = 'DIRECT_DEBIT_ORDER_CREATE';
1398  if ($type != 'bank-transfer') {
1399  $triggername = 'CREDIT_TRANSFER_ORDER_CREATE';
1400  }
1401 
1402  // Call trigger
1403  $result = $this->call_trigger($triggername, $user);
1404  if ($result < 0) {
1405  $error++;
1406  }
1407  // End call triggers
1408  }
1409 
1410  if (!$error) {
1411  $this->db->commit();
1412  return count($factures_prev); // The error of failed lines are into $this->invoice_in_error and $this->thirdparty_in_error
1413  } else {
1414  $this->db->rollback();
1415  return -1;
1416  }
1417  } else {
1418  return 0;
1419  }
1420  }
1421 
1422 
1430  public function delete($user = null, $notrigger = 0)
1431  {
1432  $this->db->begin();
1433 
1434  $error = 0;
1435  $resql1 = $resql2 = $resql3 = $resql4 = 0;
1436 
1437  if (!$notrigger) {
1438  $triggername = 'DIRECT_DEBIT_ORDER_DELETE';
1439  if ($this->type == 'bank-transfer') {
1440  $triggername = 'PAYMENTBYBANKTRANFER_DELETE';
1441  }
1442  // Call trigger
1443  $result = $this->call_trigger($triggername, $user);
1444  if ($result < 0) {
1445  $error++;
1446  }
1447  // End call triggers
1448  }
1449 
1450  if (!$error) {
1451  $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) . ")";
1452  $resql1 = $this->db->query($sql);
1453  if (!$resql1) {
1454  dol_print_error($this->db);
1455  }
1456  }
1457 
1458  if (!$error) {
1459  $sql = "DELETE FROM " . MAIN_DB_PREFIX . "prelevement_lignes WHERE fk_prelevement_bons = " . ((int) $this->id);
1460  $resql2 = $this->db->query($sql);
1461  if (!$resql2) {
1462  dol_print_error($this->db);
1463  }
1464  }
1465 
1466  if (!$error) {
1467  $sql = "DELETE FROM " . MAIN_DB_PREFIX . "prelevement_bons WHERE rowid = " . ((int) $this->id);
1468  $resql3 = $this->db->query($sql);
1469  if (!$resql3) {
1470  dol_print_error($this->db);
1471  }
1472  }
1473 
1474  if (!$error) {
1475  $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_demande SET fk_prelevement_bons = NULL, traite = 0 WHERE fk_prelevement_bons = " . ((int) $this->id);
1476  $resql4 = $this->db->query($sql);
1477  if (!$resql4) {
1478  dol_print_error($this->db);
1479  }
1480  }
1481 
1482  if ($resql1 && $resql2 && $resql3 && $resql4 && !$error) {
1483  $this->db->commit();
1484  return 1;
1485  } else {
1486  $this->db->rollback();
1487  return -1;
1488  }
1489  }
1490 
1491 
1502  public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1503  {
1504  global $conf, $langs, $hookmanager;
1505 
1506  if (!empty($conf->dol_no_mouse_hover)) {
1507  $notooltip = 1; // Force disable tooltips
1508  }
1509 
1510  $result = '';
1511 
1512  $labeltoshow = 'PaymentByDirectDebit';
1513  if (!empty($this->type) && $this->type == 'bank-transfer') {
1514  $labeltoshow = 'PaymentByBankTransfer';
1515  }
1516 
1517  $label = img_picto('', $this->picto) . ' <u>' . $langs->trans($labeltoshow) . '</u> ' . $this->getLibStatut(5);
1518  $label .= '<br>';
1519  $label .= '<b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
1520  if (isset($this->amount)) {
1521  $label .= '<br><b>' . $langs->trans("Amount") . ":</b> " . price($this->amount);
1522  }
1523  if (isset($this->date_trans)) {
1524  $label .= '<br><b>' . $langs->trans("TransData") . ":</b> " . dol_print_date($this->date_trans, 'dayhour', 'tzuserrel');
1525  }
1526  /*if (isset($this->date_credit)) {
1527  $label .= '<br><b>'.$langs->trans("TransData").":</b> ".dol_print_date($this->date_credit, 'dayhour', 'tzuserrel');
1528  }*/
1529 
1530  $url = DOL_URL_ROOT . '/compta/prelevement/card.php?id=' . $this->id;
1531  if (!empty($this->type) && $this->type == 'bank-transfer') {
1532  $url = DOL_URL_ROOT . '/compta/prelevement/card.php?id=' . $this->id;
1533  }
1534 
1535  if ($option != 'nolink') {
1536  // Add param to save lastsearch_values or not
1537  $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1538  if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1539  $add_save_lastsearch_values = 1;
1540  }
1541  if ($add_save_lastsearch_values) {
1542  $url .= '&save_lastsearch_values=1';
1543  }
1544  }
1545 
1546  $linkclose = '';
1547  if (empty($notooltip)) {
1548  if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1549  $label = $langs->trans("ShowMyObject");
1550  $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
1551  }
1552  $linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"';
1553  $linkclose .= ' class="classfortooltip' . ($morecss ? ' ' . $morecss : '') . '"';
1554  } else {
1555  $linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
1556  }
1557 
1558  $linkstart = '<a href="' . $url . '"';
1559  $linkstart .= $linkclose . '>';
1560  $linkend = '</a>';
1561 
1562  $result .= $linkstart;
1563  if ($withpicto) {
1564  $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);
1565  }
1566  if ($withpicto != 2) {
1567  $result .= $this->ref;
1568  }
1569  $result .= $linkend;
1570 
1571  global $action, $hookmanager;
1572  $hookmanager->initHooks(array('banktransferdao'));
1573  $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1574  $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1575  if ($reshook > 0) {
1576  $result = $hookmanager->resPrint;
1577  } else {
1578  $result .= $hookmanager->resPrint;
1579  }
1580 
1581  return $result;
1582  }
1583 
1584 
1591  public function deleteNotificationById($rowid)
1592  {
1593  $sql = "DELETE FROM " . MAIN_DB_PREFIX . "notify_def";
1594  $sql .= " WHERE rowid = " . ((int) $rowid);
1595 
1596  if ($this->db->query($sql)) {
1597  return 0;
1598  } else {
1599  return -1;
1600  }
1601  }
1602 
1610  public function deleteNotification($user, $action)
1611  {
1612  if (is_object($user)) {
1613  $userid = $user->id;
1614  } else { // If user is an id
1615  $userid = $user;
1616  }
1617 
1618  $sql = "DELETE FROM " . MAIN_DB_PREFIX . "notify_def";
1619  $sql .= " WHERE fk_user=" . ((int) $userid) . " AND fk_action='" . $this->db->escape($action) . "'";
1620 
1621  if ($this->db->query($sql)) {
1622  return 0;
1623  } else {
1624  return -1;
1625  }
1626  }
1627 
1628  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1637  public function addNotification($db, $user, $action)
1638  {
1639  // phpcs:enable
1640  $result = 0;
1641 
1642  if (is_object($user)) {
1643  $userid = $user->id;
1644  } else { // If user is an id
1645  $userid = $user;
1646  }
1647 
1648  if ($this->deleteNotification($user, $action) == 0) {
1649  $now = dol_now();
1650 
1651  $sql = "INSERT INTO " . MAIN_DB_PREFIX . "notify_def (datec,fk_user, fk_soc, fk_contact, fk_action)";
1652  $sql .= " VALUES ('" . $this->db->idate($now) . "', " . ((int) $userid) . ", 'NULL', 'NULL', '" . $this->db->escape($action) . "')";
1653 
1654  dol_syslog("adnotiff: " . $sql);
1655  if ($this->db->query($sql)) {
1656  $result = 0; // @phan-suppress-current-line PhanPluginRedundantAssignment
1657  } else {
1658  $result = -1;
1659  dol_syslog(get_class($this) . "::addNotification Error $result");
1660  }
1661  }
1662 
1663  return $result;
1664  }
1665 
1666 
1681  public function generate($format = 'ALL', $executiondate = 0, $type = 'direct-debit', $fk_bank_account = 0, $forsalary = 0)
1682  {
1683  global $conf, $langs, $mysoc;
1684 
1685  //TODO: Optimize code to read lines in a single function
1686 
1687  // Clean params
1688  if (empty($fk_bank_account)) {
1689  $fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
1690  }
1691 
1692  $result = 0;
1693 
1694  dol_syslog(get_class($this) . "::generate build file=" . $this->filename . " type=" . $type);
1695 
1696  $this->file = fopen($this->filename, "w");
1697  if (empty($this->file)) {
1698  $this->error = $langs->trans('ErrorFailedToOpenFile', $this->filename);
1699  return -1;
1700  }
1701 
1702  $found = 0;
1703  $this->total = 0;
1704 
1705  // Build file for European countries
1706  if ($mysoc->isInEEC()) {
1707  $found++;
1708 
1709  if ($type != 'bank-transfer') {
1713  // SEPA Initialisation
1714  $CrLf = "\n";
1715 
1716  $now = dol_now();
1717 
1718  $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S');
1719 
1720  $date_actu = $now;
1721  if (!empty($executiondate)) {
1722  $date_actu = $executiondate;
1723  }
1724 
1725  $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d');
1726  $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S');
1727  $fileDebiteurSection = '';
1728  $fileEmetteurSection = '';
1729  $i = 0;
1730 
1731  /*
1732  * Section Debitor (sepa Debiteurs block lines)
1733  */
1734 
1735  $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
1736  $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1737  $sql .= " f.ref as reffac, p.fk_facture as idfac,";
1738  $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
1739  $sql .= " FROM";
1740  $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1741  $sql .= " " . MAIN_DB_PREFIX . "facture as f,";
1742  $sql .= " " . MAIN_DB_PREFIX . "prelevement as p,";
1743  $sql .= " " . MAIN_DB_PREFIX . "societe as soc,";
1744  $sql .= " " . MAIN_DB_PREFIX . "c_country as c,";
1745  $sql .= " " . MAIN_DB_PREFIX . "societe_rib as rib";
1746  $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
1747  $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1748  $sql .= " AND p.fk_facture = f.rowid";
1749  $sql .= " AND f.fk_soc = soc.rowid";
1750  $sql .= " AND soc.fk_pays = c.rowid";
1751  $sql .= " AND rib.fk_soc = f.fk_soc";
1752  $sql .= " AND rib.default_rib = 1";
1753  $sql .= " AND rib.type = 'ban'";
1754 
1755  // Define $fileDebiteurSection. One section DrctDbtTxInf per invoice.
1756  $resql = $this->db->query($sql);
1757  if ($resql) {
1758  $cachearraytotestduplicate = array();
1759 
1760  $num = $this->db->num_rows($resql);
1761  while ($i < $num) {
1762  $obj = $this->db->fetch_object($resql);
1763 
1764  if (!empty($cachearraytotestduplicate[$obj->idfac])) {
1765  $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
1766  $this->invoice_in_error[$obj->idfac] = $this->error;
1767  $result = -2;
1768  break;
1769  }
1770  $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
1771 
1772  $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
1773 
1774  $fileDebiteurSection .= $this->EnregDestinataireSEPA($obj->code, $obj->nom, $obj->address, $obj->zip, $obj->town, $obj->country_code, $obj->cb, $obj->cg, $obj->cc, $obj->somme, $obj->reffac, $obj->idfac, $obj->iban, $obj->bic, $daterum, $obj->drum, $obj->rum, $type);
1775 
1776  $this->total = $this->total + $obj->somme;
1777  $i++;
1778  }
1779  $nbtotalDrctDbtTxInf = $i;
1780  } else {
1781  $this->error = $this->db->lasterror();
1782  fwrite($this->file, 'ERROR DEBITOR ' . $sql . $CrLf); // DEBITOR = Customers
1783  $result = -2;
1784  }
1785 
1786  // Define $fileEmetteurSection. Start of block PmtInf. Will contains all $nbtotalDrctDbtTxInf
1787  if ($result != -2) {
1788  $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type, $fk_bank_account);
1789  }
1790 
1791  if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) {
1792  $this->total = number_format((float) price2num($this->total, 'MT'), 2, ".", "");
1793  }
1794 
1798  // SEPA File Header
1799  fwrite($this->file, '<' . '?xml version="1.0" encoding="UTF-8" standalone="yes"?' . '>' . $CrLf);
1800  fwrite($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);
1801  fwrite($this->file, ' <CstmrDrctDbtInitn>' . $CrLf);
1802  // SEPA Group header
1803  fwrite($this->file, ' <GrpHdr>' . $CrLf);
1804  fwrite($this->file, ' <MsgId>' . ('DD/' . $dateTime_YMD . '/REF' . $this->id) . '</MsgId>' . $CrLf);
1805  fwrite($this->file, ' <CreDtTm>' . $dateTime_ECMA . '</CreDtTm>' . $CrLf);
1806  fwrite($this->file, ' <NbOfTxs>' . $i . '</NbOfTxs>' . $CrLf);
1807  fwrite($this->file, ' <CtrlSum>' . $this->total . '</CtrlSum>' . $CrLf);
1808  fwrite($this->file, ' <InitgPty>' . $CrLf);
1809  fwrite($this->file, ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf);
1810  fwrite($this->file, ' <Id>' . $CrLf);
1811  fwrite($this->file, ' <PrvtId>' . $CrLf);
1812  fwrite($this->file, ' <Othr>' . $CrLf);
1813  fwrite($this->file, ' <Id>' . $this->emetteur_ics . '</Id>' . $CrLf);
1814  fwrite($this->file, ' </Othr>' . $CrLf);
1815  fwrite($this->file, ' </PrvtId>' . $CrLf);
1816  fwrite($this->file, ' </Id>' . $CrLf);
1817  fwrite($this->file, ' </InitgPty>' . $CrLf);
1818  fwrite($this->file, ' </GrpHdr>' . $CrLf);
1819  // SEPA File Emetteur
1820  if ($result != -2) {
1821  fwrite($this->file, $fileEmetteurSection);
1822  }
1823  // SEPA File Debiteurs
1824  if ($result != -2) {
1825  fwrite($this->file, $fileDebiteurSection);
1826  }
1827  // SEPA FILE FOOTER
1828  fwrite($this->file, ' </PmtInf>' . $CrLf);
1829  fwrite($this->file, ' </CstmrDrctDbtInitn>' . $CrLf);
1830  fwrite($this->file, '</Document>' . $CrLf);
1831  } else {
1835  // SEPA Initialisation
1836  $CrLf = "\n";
1837 
1838  $now = dol_now();
1839 
1840  $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S');
1841 
1842  $date_actu = $now;
1843  if (!empty($executiondate)) {
1844  $date_actu = $executiondate;
1845  }
1846 
1847  $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d');
1848  $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S');
1849  $fileCrediteurSection = '';
1850  $fileEmetteurSection = '';
1851  $i = 0;
1852 
1853  /*
1854  * Section Creditor (sepa Crediteurs block lines)
1855  */
1856  if (!empty($forsalary)) {
1857  $sql = "SELECT u.rowid as userId, u.address, u.zip, u.town, c.code as country_code, CONCAT(u.firstname,' ',u.lastname) as nom,";
1858  $sql .= " pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1859  $sql .= " s.ref as reffac, p.fk_salary as idfac,";
1860  $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, '' as rum, '' as date_rum";
1861  $sql .= " FROM";
1862  $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1863  $sql .= " " . MAIN_DB_PREFIX . "salary as s,";
1864  $sql .= " " . MAIN_DB_PREFIX . "prelevement as p,";
1865  $sql .= " " . MAIN_DB_PREFIX . "user as u";
1866  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_country as c ON u.fk_country = c.rowid,";
1867  $sql .= " " . MAIN_DB_PREFIX . "user_rib as rib";
1868  $sql .= " WHERE pl.fk_prelevement_bons=" . ((int) $this->id);
1869  $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1870  $sql .= " AND p.fk_salary = s.rowid";
1871  $sql .= " AND s.fk_user = u.rowid";
1872  $sql .= " AND rib.fk_user = s.fk_user";
1873  } else {
1874  $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
1875  $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1876  $sql .= " f.ref as reffac, f.ref_supplier as fac_ref_supplier, p.fk_facture_fourn as idfac,";
1877  $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
1878  $sql .= " FROM";
1879  $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1880  $sql .= " " . MAIN_DB_PREFIX . "facture_fourn as f,";
1881  $sql .= " " . MAIN_DB_PREFIX . "prelevement as p,";
1882  $sql .= " " . MAIN_DB_PREFIX . "societe as soc";
1883  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_country as c ON soc.fk_pays = c.rowid,";
1884  $sql .= " " . MAIN_DB_PREFIX . "societe_rib as rib";
1885  $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
1886  $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1887  $sql .= " AND p.fk_facture_fourn = f.rowid";
1888  $sql .= " AND f.fk_soc = soc.rowid";
1889  $sql .= " AND rib.fk_soc = f.fk_soc";
1890  $sql .= " AND rib.default_rib = 1";
1891  $sql .= " AND rib.type = 'ban'";
1892  }
1893  // Define $fileCrediteurSection. One section DrctDbtTxInf per invoice.
1894  $resql = $this->db->query($sql);
1895  if ($resql) {
1896  $cachearraytotestduplicate = array();
1897 
1898  $num = $this->db->num_rows($resql);
1899  while ($i < $num) {
1900  $obj = $this->db->fetch_object($resql);
1901  if (!empty($cachearraytotestduplicate[$obj->idfac])) {
1902  $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
1903  $this->invoice_in_error[$obj->idfac] = $this->error;
1904  $result = -2;
1905  break;
1906  }
1907  $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
1908 
1909  $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
1910  $refobj = $obj->reffac;
1911  if (empty($refobj) && !empty($forsalary)) { // If ref of salary not defined, we force a value
1912  $refobj = "SAL" . $obj->idfac;
1913  }
1914 
1915  $fileCrediteurSection .= $this->EnregDestinataireSEPA($obj->code, $obj->nom, $obj->address, $obj->zip, $obj->town, $obj->country_code, $obj->cb, $obj->cg, $obj->cc, $obj->somme, $refobj, $obj->idfac, $obj->iban, $obj->bic, $daterum, $obj->drum, $obj->rum, $type, $obj->fac_ref_supplier);
1916 
1917  $this->total = $this->total + $obj->somme;
1918  $i++;
1919  }
1920  $nbtotalDrctDbtTxInf = $i;
1921  } else {
1922  $this->error = $this->db->lasterror();
1923  fwrite($this->file, 'ERROR CREDITOR ' . $sql . $CrLf); // CREDITORS = Suppliers
1924  $result = -2;
1925  }
1926  // Define $fileEmetteurSection. Start of block PmtInf. Will contains all $nbtotalDrctDbtTxInf
1927  if ($result != -2) {
1928  $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type);
1929  }
1930 
1931  if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) {
1932  $this->total = number_format((float) price2num($this->total, 'MT'), 2, ".", "");
1933  }
1934 
1938  // SEPA File Header
1939  fwrite($this->file, '<' . '?xml version="1.0" encoding="UTF-8" standalone="yes"?' . '>' . $CrLf);
1940  fwrite($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);
1941  fwrite($this->file, ' <CstmrCdtTrfInitn>' . $CrLf);
1942  // SEPA Group header
1943  fwrite($this->file, ' <GrpHdr>' . $CrLf);
1944  fwrite($this->file, ' <MsgId>' . ('TRF/' . $dateTime_YMD . '/REF' . $this->id) . '</MsgId>' . $CrLf);
1945  fwrite($this->file, ' <CreDtTm>' . $dateTime_ECMA . '</CreDtTm>' . $CrLf);
1946  fwrite($this->file, ' <NbOfTxs>' . $i . '</NbOfTxs>' . $CrLf);
1947  fwrite($this->file, ' <CtrlSum>' . $this->total . '</CtrlSum>' . $CrLf);
1948  fwrite($this->file, ' <InitgPty>' . $CrLf);
1949  fwrite($this->file, ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf);
1950  fwrite($this->file, ' <Id>' . $CrLf);
1951  fwrite($this->file, ' <PrvtId>' . $CrLf);
1952  fwrite($this->file, ' <Othr>' . $CrLf);
1953  fwrite($this->file, ' <Id>' . $this->emetteur_ics . '</Id>' . $CrLf);
1954  fwrite($this->file, ' </Othr>' . $CrLf);
1955  fwrite($this->file, ' </PrvtId>' . $CrLf);
1956  fwrite($this->file, ' </Id>' . $CrLf);
1957  fwrite($this->file, ' </InitgPty>' . $CrLf);
1958  fwrite($this->file, ' </GrpHdr>' . $CrLf);
1959  // SEPA File Emetteur (mycompany)
1960  if ($result != -2) {
1961  fwrite($this->file, $fileEmetteurSection);
1962  }
1963  // SEPA File Creditors
1964  if ($result != -2) {
1965  fwrite($this->file, $fileCrediteurSection);
1966  }
1967  // SEPA FILE FOOTER
1968  fwrite($this->file, ' </PmtInf>' . $CrLf);
1969  fwrite($this->file, ' </CstmrCdtTrfInitn>' . $CrLf);
1970  fwrite($this->file, '</Document>' . $CrLf);
1971  }
1972  }
1973 
1974  // Build file for Other Countries with unknown format
1975  if (!$found) {
1976  if ($type != 'bank-transfer') {
1977  $sql = "SELECT pl.amount";
1978  $sql .= " FROM";
1979  $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1980  $sql .= " " . MAIN_DB_PREFIX . "facture as f,";
1981  $sql .= " " . MAIN_DB_PREFIX . "prelevement as p";
1982  $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
1983  $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1984  $sql .= " AND p.fk_facture = f.rowid";
1985 
1986  // Lines
1987  $i = 0;
1988  $resql = $this->db->query($sql);
1989  if ($resql) {
1990  $num = $this->db->num_rows($resql);
1991 
1992  while ($i < $num) {
1993  $obj = $this->db->fetch_object($resql);
1994  $this->total = $this->total + $obj->amount;
1995 
1996  // TODO Write record into file
1997  $i++;
1998  }
1999  } else {
2000  $result = -2;
2001  }
2002  } else {
2003  $sql = "SELECT pl.amount";
2004  $sql .= " FROM";
2005  $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
2006  $sql .= " " . MAIN_DB_PREFIX . "facture_fourn as f,";
2007  $sql .= " " . MAIN_DB_PREFIX . "prelevement as p";
2008  $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
2009  $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
2010  $sql .= " AND p.fk_facture_fourn = f.rowid";
2011  // Lines
2012  $i = 0;
2013  $resql = $this->db->query($sql);
2014  if ($resql) {
2015  $num = $this->db->num_rows($resql);
2016 
2017  while ($i < $num) {
2018  $obj = $this->db->fetch_object($resql);
2019  $this->total = $this->total + $obj->amount;
2020 
2021  // TODO Write record into file
2022  $i++;
2023  }
2024  } else {
2025  $result = -2;
2026  }
2027  }
2028 
2029  $langs->load('withdrawals');
2030 
2031  // TODO Add here code to generate a generic file
2032  fwrite($this->file, $langs->transnoentitiesnoconv('WithdrawalFileNotCapable', $mysoc->country_code));
2033  }
2034 
2035  fclose($this->file);
2036  dolChmod($this->filename);
2037 
2038  return $result;
2039  }
2040 
2041 
2050  public static function buildRumNumber($row_code_client, $row_datec, $row_drum)
2051  {
2052  global $langs;
2053 
2054  $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)
2055 
2056  // 3 char + '-' + 12 + '-' + id + '-' + code Must be lower than 32.
2057  return $pre . '-' . dol_print_date($row_datec, 'dayhourlogsmall') . '-' . dol_trunc($row_drum . ($row_code_client ? '-' . $row_code_client : ''), 13, 'right', 'UTF-8', 1);
2058  }
2059 
2060 
2061  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2078  public function EnregDestinataire($rowid, $client_nom, $rib_banque, $rib_guichet, $rib_number, $amount, $ref, $facid, $rib_dom = '', $type = 'direct-debit')
2079  {
2080  // phpcs:enable
2081  fwrite($this->file, "06");
2082  fwrite($this->file, "08"); // Prelevement ordinaire
2083 
2084  fwrite($this->file, " "); // Zone Reservee B2
2085 
2086  fwrite($this->file, $this->emetteur_ics); // ICS
2087 
2088  // Date d'echeance C1
2089 
2090  fwrite($this->file, " ");
2091  fwrite($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
2092  fwrite($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
2093 
2094  // Raison Sociale Destinataire C2
2095 
2096  fwrite($this->file, substr(strtoupper($client_nom) . " ", 0, 24));
2097 
2098  // Address optional D1
2099  $address = strtr($rib_dom, array(" " => "-", chr(13) => " ", chr(10) => ""));
2100  fwrite($this->file, substr($address . " ", 0, 24));
2101 
2102  // Zone Reservee D2
2103 
2104  fwrite($this->file, substr(" ", 0, 8));
2105 
2106  // Code Guichet D3
2107 
2108  fwrite($this->file, $rib_guichet);
2109 
2110  // Numero de compte D4
2111 
2112  fwrite($this->file, substr("000000000000000" . $rib_number, -11));
2113 
2114  // Zone E Montant
2115 
2116  $montant = (round($amount, 2) * 100);
2117 
2118  fwrite($this->file, substr("000000000000000" . $montant, -16));
2119 
2120  // Label F
2121 
2122  fwrite($this->file, substr("*_" . $ref . "_RDVnet" . $rowid . " ", 0, 31));
2123 
2124  // Code etablissement G1
2125 
2126  fwrite($this->file, $rib_banque);
2127 
2128  // Zone Reservee G2
2129 
2130  fwrite($this->file, substr(" ", 0, 5));
2131 
2132  fwrite($this->file, "\n");
2133  }
2134 
2135 
2136  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2162  public function EnregDestinataireSEPA($row_code_client, $row_nom, $row_address, $row_zip, $row_town, $row_country_code, $row_cb, $row_cg, $row_cc, $row_somme, $row_ref, $row_idfac, $row_iban, $row_bic, $row_datec, $row_drum, $row_rum, $type = 'direct-debit', $row_comment = '')
2163  {
2164  // phpcs:enable
2165  global $conf;
2166 
2167  if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) {
2168  $row_somme = number_format((float) price2num($row_somme, 'MT'), 2, ".", "");
2169  } else {
2170  $row_somme = round((float) $row_somme, 2);
2171  }
2172 
2173  include_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php';
2174 
2175  $CrLf = "\n";
2176  $Rowing = sprintf("%010d", $row_idfac);
2177 
2178  // Define value for RUM
2179  // Example: RUM-CustomerCode-CustomerBankAccountId-01424448606 (note: Date is the timestamp of the date of creation of CustomerBankAccountId)
2180  $Rum = (empty($row_rum) ? $this->buildRumNumber($row_code_client, $row_datec, $row_drum) : $row_rum);
2181 
2182  // Define date of RUM signature
2183  $DtOfSgntr = dol_print_date($row_datec, '%Y-%m-%d');
2184 
2185  if ($type != 'bank-transfer') {
2186  // SEPA Paiement Information of buyer for Direct Debit
2187  $XML_DEBITOR = '';
2188  $XML_DEBITOR .= ' <DrctDbtTxInf>' . $CrLf;
2189  $XML_DEBITOR .= ' <PmtId>' . $CrLf;
2190  // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
2191  $XML_DEBITOR .= ' <EndToEndId>' . ((getDolGlobalString('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
2192  $XML_DEBITOR .= ' </PmtId>' . $CrLf;
2193  $XML_DEBITOR .= ' <InstdAmt Ccy="EUR">' . $row_somme . '</InstdAmt>' . $CrLf;
2194  $XML_DEBITOR .= ' <DrctDbtTx>' . $CrLf;
2195  $XML_DEBITOR .= ' <MndtRltdInf>' . $CrLf;
2196  $XML_DEBITOR .= ' <MndtId>' . $Rum . '</MndtId>' . $CrLf;
2197  $XML_DEBITOR .= ' <DtOfSgntr>' . $DtOfSgntr . '</DtOfSgntr>' . $CrLf;
2198  $XML_DEBITOR .= ' <AmdmntInd>false</AmdmntInd>' . $CrLf;
2199  $XML_DEBITOR .= ' </MndtRltdInf>' . $CrLf;
2200  $XML_DEBITOR .= ' </DrctDbtTx>' . $CrLf;
2201  $XML_DEBITOR .= ' <DbtrAgt>' . $CrLf;
2202  $XML_DEBITOR .= ' <FinInstnId>' . $CrLf;
2203  $XML_DEBITOR .= ' <BIC>' . $row_bic . '</BIC>' . $CrLf;
2204  $XML_DEBITOR .= ' </FinInstnId>' . $CrLf;
2205  $XML_DEBITOR .= ' </DbtrAgt>' . $CrLf;
2206  $XML_DEBITOR .= ' <Dbtr>' . $CrLf;
2207  $XML_DEBITOR .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))) . '</Nm>' . $CrLf;
2208  $XML_DEBITOR .= ' <PstlAdr>' . $CrLf;
2209  $XML_DEBITOR .= ' <Ctry>' . $row_country_code . '</Ctry>' . $CrLf;
2210  $addressline1 = strtr($row_address, array(chr(13) => ", ", chr(10) => ""));
2211  $addressline2 = strtr($row_zip . (($row_zip && $row_town) ? ' ' : (string) $row_town), array(chr(13) => ", ", chr(10) => ""));
2212  if (trim($addressline1)) {
2213  $XML_DEBITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2214  }
2215  if (trim($addressline2)) {
2216  $XML_DEBITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2217  }
2218  $XML_DEBITOR .= ' </PstlAdr>' . $CrLf;
2219  $XML_DEBITOR .= ' </Dbtr>' . $CrLf;
2220  $XML_DEBITOR .= ' <DbtrAcct>' . $CrLf;
2221  $XML_DEBITOR .= ' <Id>' . $CrLf;
2222  $XML_DEBITOR .= ' <IBAN>' . preg_replace('/\s/', '', $row_iban) . '</IBAN>' . $CrLf;
2223  $XML_DEBITOR .= ' </Id>' . $CrLf;
2224  $XML_DEBITOR .= ' </DbtrAcct>' . $CrLf;
2225  $XML_DEBITOR .= ' <RmtInf>' . $CrLf;
2226  // A string with some information on payment - 140 max
2227  $XML_DEBITOR .= ' <Ustrd>' . getDolGlobalString('PRELEVEMENT_USTRD', dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($row_ref . ($row_comment ? ' - ' . $row_comment : '')), '', '', '', 1), 135, 'right', 'UTF-8', 1))) . '</Ustrd>' . $CrLf; // Free unstuctured data - 140 max
2228  $XML_DEBITOR .= ' </RmtInf>' . $CrLf;
2229  $XML_DEBITOR .= ' </DrctDbtTxInf>' . $CrLf;
2230  return $XML_DEBITOR;
2231  } else {
2232  // SEPA Payment Information of seller for Credit Transfer
2233  $XML_CREDITOR = '';
2234  $XML_CREDITOR .= ' <CdtTrfTxInf>' . $CrLf;
2235  $XML_CREDITOR .= ' <PmtId>' . $CrLf;
2236  // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
2237  $XML_CREDITOR .= ' <EndToEndId>' . ((getDolGlobalString('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
2238  $XML_CREDITOR .= ' </PmtId>' . $CrLf;
2239  if (!empty($this->sepa_xml_pti_in_ctti)) {
2240  $XML_CREDITOR .= ' <PmtTpInf>' . $CrLf;
2241 
2242  // Can be 'NORM' for normal or 'HIGH' for high priority level
2243  if (getDolGlobalString('PAYMENTBYBANKTRANSFER_FORCE_HIGH_PRIORITY')) {
2244  $instrprty = 'HIGH';
2245  } else {
2246  $instrprty = 'NORM';
2247  }
2248  $XML_CREDITOR .= ' <InstrPrty>' . $instrprty . '</InstrPrty>' . $CrLf;
2249  $XML_CREDITOR .= ' <SvcLvl>' . $CrLf;
2250  $XML_CREDITOR .= ' <Cd>SEPA</Cd>' . $CrLf;
2251  $XML_CREDITOR .= ' </SvcLvl>' . $CrLf;
2252  $XML_CREDITOR .= ' <CtgyPurp>' . $CrLf;
2253  $XML_CREDITOR .= ' <Cd>CORE</Cd>' . $CrLf;
2254  $XML_CREDITOR .= ' </CtgyPurp>' . $CrLf;
2255  $XML_CREDITOR .= ' </PmtTpInf>' . $CrLf;
2256  }
2257  $XML_CREDITOR .= ' <Amt>' . $CrLf;
2258  $XML_CREDITOR .= ' <InstdAmt Ccy="EUR">'.round((float) $row_somme, 2).'</InstdAmt>'.$CrLf;
2259  $XML_CREDITOR .= ' </Amt>' . $CrLf;
2260  /*
2261  $XML_CREDITOR .= ' <DrctDbtTx>'.$CrLf;
2262  $XML_CREDITOR .= ' <MndtRltdInf>'.$CrLf;
2263  $XML_CREDITOR .= ' <MndtId>'.$Rum.'</MndtId>'.$CrLf;
2264  $XML_CREDITOR .= ' <DtOfSgntr>'.$DtOfSgntr.'</DtOfSgntr>'.$CrLf;
2265  $XML_CREDITOR .= ' <AmdmntInd>false</AmdmntInd>'.$CrLf;
2266  $XML_CREDITOR .= ' </MndtRltdInf>'.$CrLf;
2267  $XML_CREDITOR .= ' </DrctDbtTx>'.$CrLf;
2268  */
2269  //$XML_CREDITOR .= ' <ChrgBr>SLEV</ChrgBr>'.$CrLf;
2270  $XML_CREDITOR .= ' <CdtrAgt>' . $CrLf;
2271  $XML_CREDITOR .= ' <FinInstnId>' . $CrLf;
2272  $XML_CREDITOR .= ' <BIC>' . $row_bic . '</BIC>' . $CrLf;
2273  $XML_CREDITOR .= ' </FinInstnId>' . $CrLf;
2274  $XML_CREDITOR .= ' </CdtrAgt>' . $CrLf;
2275  $XML_CREDITOR .= ' <Cdtr>' . $CrLf;
2276  $XML_CREDITOR .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))) . '</Nm>' . $CrLf;
2277  $XML_CREDITOR .= ' <PstlAdr>' . $CrLf;
2278  $XML_CREDITOR .= ' <Ctry>' . $row_country_code . '</Ctry>' . $CrLf;
2279  $addressline1 = strtr($row_address, array(chr(13) => ", ", chr(10) => ""));
2280  $addressline2 = strtr($row_zip . (($row_zip && $row_town) ? ' ' : (string) $row_town), array(chr(13) => ", ", chr(10) => ""));
2281  if (trim($addressline1)) {
2282  $XML_CREDITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2283  }
2284  if (trim($addressline2)) {
2285  $XML_CREDITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2286  }
2287  $XML_CREDITOR .= ' </PstlAdr>' . $CrLf;
2288  $XML_CREDITOR .= ' </Cdtr>' . $CrLf;
2289  $XML_CREDITOR .= ' <CdtrAcct>' . $CrLf;
2290  $XML_CREDITOR .= ' <Id>' . $CrLf;
2291  $XML_CREDITOR .= ' <IBAN>' . preg_replace('/\s/', '', $row_iban) . '</IBAN>' . $CrLf;
2292  $XML_CREDITOR .= ' </Id>' . $CrLf;
2293  $XML_CREDITOR .= ' </CdtrAcct>' . $CrLf;
2294  $XML_CREDITOR .= ' <RmtInf>' . $CrLf;
2295  // A string with some information on payment - 140 max
2296  $XML_CREDITOR .= ' <Ustrd>' . getDolGlobalString('CREDITTRANSFER_USTRD', dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($row_ref . ($row_comment ? ' - ' . $row_comment : '')), '', '', '', 1), 135, 'right', 'UTF-8', 1))) . '</Ustrd>' . $CrLf; // Free unstructured data - 140 max
2297  $XML_CREDITOR .= ' </RmtInf>' . $CrLf;
2298  $XML_CREDITOR .= ' </CdtTrfTxInf>' . $CrLf;
2299  return $XML_CREDITOR;
2300  }
2301  }
2302 
2303 
2304  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2312  public function EnregEmetteur($type = 'direct-debit')
2313  {
2314  // phpcs:enable
2315  fwrite($this->file, "03");
2316  fwrite($this->file, "08"); // Prelevement ordinaire
2317 
2318  fwrite($this->file, " "); // Zone Reservee B2
2319 
2320  fwrite($this->file, $this->emetteur_ics); // ICS
2321 
2322  // Date d'echeance C1
2323 
2324  fwrite($this->file, " ");
2325  fwrite($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
2326  fwrite($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
2327 
2328  // Raison Sociale C2
2329 
2330  fwrite($this->file, substr($this->raison_sociale . " ", 0, 24));
2331 
2332  // Reference de la remise creancier D1 sur 7 caracteres
2333 
2334  fwrite($this->file, substr($this->reference_remise . " ", 0, 7));
2335 
2336  // Zone Reservee D1-2
2337 
2338  fwrite($this->file, substr(" ", 0, 17));
2339 
2340  // Zone Reservee D2
2341 
2342  fwrite($this->file, substr(" ", 0, 2));
2343  fwrite($this->file, "E");
2344  fwrite($this->file, substr(" ", 0, 5));
2345 
2346  // Code Guichet D3
2347 
2348  fwrite($this->file, $this->emetteur_code_guichet);
2349 
2350  // Numero de compte D4
2351 
2352  fwrite($this->file, substr("000000000000000" . $this->emetteur_numero_compte, -11));
2353 
2354  // Zone Reservee E
2355 
2356  fwrite($this->file, substr(" ", 0, 16));
2357 
2358  // Zone Reservee F
2359 
2360  fwrite($this->file, substr(" ", 0, 31));
2361 
2362  // Code etablissement
2363 
2364  fwrite($this->file, $this->emetteur_code_banque);
2365 
2366  // Zone Reservee G
2367 
2368  fwrite($this->file, substr(" ", 0, 5));
2369 
2370  fwrite($this->file, "\n");
2371  }
2372 
2373 
2374  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2390  public function EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf = '\n', $format = 'FRST', $type = 'direct-debit', $fk_bank_account = 0)
2391  {
2392  // phpcs:enable
2393 
2394  // Clean parameters
2395  $dateTime_YMD = dol_print_date($ladate, '%Y%m%d');
2396  $dateTime_ETAD = dol_print_date($ladate, '%Y-%m-%d');
2397  $dateTime_YMDHMS = dol_print_date($ladate, '%Y-%m-%dT%H:%M:%S');
2398 
2399  // Clean params
2400  if (empty($fk_bank_account)) {
2401  $fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
2402  }
2403 
2404  // Get data of bank account
2405  $account = new Account($this->db);
2406  if ($account->fetch($fk_bank_account) > 0) {
2407  $this->emetteur_code_banque = $account->code_banque;
2408  $this->emetteur_code_guichet = $account->code_guichet;
2409  $this->emetteur_numero_compte = $account->number;
2410  $this->emetteur_number_key = $account->cle_rib;
2411  $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
2412  $this->emetteur_iban = $account->iban;
2413  $this->emetteur_bic = $account->bic;
2414 
2415  $this->emetteur_ics = (($type == 'bank-transfer' && getDolGlobalString("SEPA_USE_IDS")) ? $account->ics_transfer : $account->ics); // Ex: PRELEVEMENT_ICS = "FR78ZZZ123456";
2416 
2417  $this->raison_sociale = $account->proprio;
2418  }
2419 
2420  // Get pending payments
2421  $sql = "SELECT rowid, ref";
2422  $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons as pb";
2423  $sql .= " WHERE pb.rowid = " . ((int) $this->id);
2424 
2425  $resql = $this->db->query($sql);
2426  if ($resql) {
2427  $obj = $this->db->fetch_object($resql);
2428 
2429  $country = explode(':', $configuration->global->MAIN_INFO_SOCIETE_COUNTRY);
2430  $IdBon = sprintf("%05d", $obj->rowid);
2431  $RefBon = $obj->ref;
2432 
2433  if (!empty($configuration->global->SEPA_FORCE_TWO_DECIMAL)) {
2434  $total = number_format((float) price2num($total, 'MT'), 2, ".", "");
2435  }
2436 
2437  if ($type != 'bank-transfer') {
2438  // SEPA Paiement Information of my company for Direct Debit
2439  $XML_SEPA_INFO = '';
2440  $XML_SEPA_INFO .= ' <PmtInf>' . $CrLf;
2441  $XML_SEPA_INFO .= ' <PmtInfId>' . ('DD/' . $dateTime_YMD . '/ID' . $IdBon . '-' . $RefBon) . '</PmtInfId>' . $CrLf;
2442  $XML_SEPA_INFO .= ' <PmtMtd>DD</PmtMtd>' . $CrLf;
2443  $XML_SEPA_INFO .= ' <NbOfTxs>' . $nombre . '</NbOfTxs>' . $CrLf;
2444  $XML_SEPA_INFO .= ' <CtrlSum>' . $total . '</CtrlSum>' . $CrLf;
2445  $XML_SEPA_INFO .= ' <PmtTpInf>' . $CrLf;
2446  $XML_SEPA_INFO .= ' <SvcLvl>' . $CrLf;
2447  $XML_SEPA_INFO .= ' <Cd>SEPA</Cd>' . $CrLf;
2448  $XML_SEPA_INFO .= ' </SvcLvl>' . $CrLf;
2449  $XML_SEPA_INFO .= ' <LclInstrm>' . $CrLf;
2450  $XML_SEPA_INFO .= ' <Cd>CORE</Cd>' . $CrLf;
2451  $XML_SEPA_INFO .= ' </LclInstrm>' . $CrLf;
2452  $XML_SEPA_INFO .= ' <SeqTp>' . $format . '</SeqTp>' . $CrLf;
2453  $XML_SEPA_INFO .= ' </PmtTpInf>' . $CrLf;
2454  $XML_SEPA_INFO .= ' <ReqdColltnDt>' . $dateTime_ETAD . '</ReqdColltnDt>' . $CrLf;
2455  $XML_SEPA_INFO .= ' <Cdtr>' . $CrLf;
2456  $XML_SEPA_INFO .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf;
2457  $XML_SEPA_INFO .= ' <PstlAdr>' . $CrLf;
2458  $XML_SEPA_INFO .= ' <Ctry>' . $country[1] . '</Ctry>' . $CrLf;
2459  $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(chr(13) => ", ", chr(10) => ""));
2460  $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) => ""));
2461  if ($addressline1) {
2462  $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2463  }
2464  if ($addressline2) {
2465  $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2466  }
2467  $XML_SEPA_INFO .= ' </PstlAdr>' . $CrLf;
2468  $XML_SEPA_INFO .= ' </Cdtr>' . $CrLf;
2469  $XML_SEPA_INFO .= ' <CdtrAcct>' . $CrLf;
2470  $XML_SEPA_INFO .= ' <Id>' . $CrLf;
2471  $XML_SEPA_INFO .= ' <IBAN>' . preg_replace('/\s/', '', $this->emetteur_iban) . '</IBAN>' . $CrLf;
2472  $XML_SEPA_INFO .= ' </Id>' . $CrLf;
2473  $XML_SEPA_INFO .= ' </CdtrAcct>' . $CrLf;
2474  $XML_SEPA_INFO .= ' <CdtrAgt>' . $CrLf;
2475  $XML_SEPA_INFO .= ' <FinInstnId>' . $CrLf;
2476  $XML_SEPA_INFO .= ' <BIC>' . $this->emetteur_bic . '</BIC>' . $CrLf;
2477  $XML_SEPA_INFO .= ' </FinInstnId>' . $CrLf;
2478  $XML_SEPA_INFO .= ' </CdtrAgt>' . $CrLf;
2479  /* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf;
2480  $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2481  $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2482  $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2483  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ADDRESS), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2484  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ZIP.' '.$conf->global->MAIN_INFO_SOCIETE_TOWN), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2485  $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2486  $XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/
2487  $XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>' . $CrLf; // Field "Responsible of fees". Must be SLEV
2488  $XML_SEPA_INFO .= ' <CdtrSchmeId>' . $CrLf;
2489  $XML_SEPA_INFO .= ' <Id>' . $CrLf;
2490  $XML_SEPA_INFO .= ' <PrvtId>' . $CrLf;
2491  $XML_SEPA_INFO .= ' <Othr>' . $CrLf;
2492  $XML_SEPA_INFO .= ' <Id>' . $this->emetteur_ics . '</Id>' . $CrLf;
2493  $XML_SEPA_INFO .= ' <SchmeNm>' . $CrLf;
2494  $XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>' . $CrLf;
2495  $XML_SEPA_INFO .= ' </SchmeNm>' . $CrLf;
2496  $XML_SEPA_INFO .= ' </Othr>' . $CrLf;
2497  $XML_SEPA_INFO .= ' </PrvtId>' . $CrLf;
2498  $XML_SEPA_INFO .= ' </Id>' . $CrLf;
2499  $XML_SEPA_INFO .= ' </CdtrSchmeId>' . $CrLf;
2500  } else {
2501  // SEPA Paiement Information of my company for Credit Transfer
2502  $XML_SEPA_INFO = '';
2503  $XML_SEPA_INFO .= ' <PmtInf>' . $CrLf;
2504  $XML_SEPA_INFO .= ' <PmtInfId>' . ('TRF/' . $dateTime_YMD . '/ID' . $IdBon . '-' . $RefBon) . '</PmtInfId>' . $CrLf;
2505  $XML_SEPA_INFO .= ' <PmtMtd>TRF</PmtMtd>' . $CrLf;
2506  //$XML_SEPA_INFO .= ' <BtchBookg>False</BtchBookg>'.$CrLf;
2507  $XML_SEPA_INFO .= ' <NbOfTxs>' . $nombre . '</NbOfTxs>' . $CrLf;
2508  $XML_SEPA_INFO .= ' <CtrlSum>' . $total . '</CtrlSum>' . $CrLf;
2509  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.
2510  $XML_SEPA_INFO .= ' <PmtTpInf>' . $CrLf;
2511  $XML_SEPA_INFO .= ' <SvcLvl>' . $CrLf;
2512  $XML_SEPA_INFO .= ' <Cd>SEPA</Cd>' . $CrLf;
2513  $XML_SEPA_INFO .= ' </SvcLvl>' . $CrLf;
2514  $XML_SEPA_INFO .= ' <LclInstrm>' . $CrLf;
2515  $XML_SEPA_INFO .= ' <Cd>CORE</Cd>' . $CrLf;
2516  $XML_SEPA_INFO .= ' </LclInstrm>' . $CrLf;
2517  $XML_SEPA_INFO .= ' <SeqTp>' . $format . '</SeqTp>' . $CrLf;
2518  $XML_SEPA_INFO .= ' </PmtTpInf>' . $CrLf;
2519  }
2520  $XML_SEPA_INFO .= ' <ReqdExctnDt>' . dol_print_date($dateTime_ETAD, 'dayrfc') . '</ReqdExctnDt>' . $CrLf;
2521  $XML_SEPA_INFO .= ' <Dbtr>' . $CrLf;
2522  $XML_SEPA_INFO .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf;
2523  $XML_SEPA_INFO .= ' <PstlAdr>' . $CrLf;
2524  $XML_SEPA_INFO .= ' <Ctry>' . $country[1] . '</Ctry>' . $CrLf;
2525  $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(chr(13) => ", ", chr(10) => ""));
2526  $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) => ""));
2527  if ($addressline1) {
2528  $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2529  }
2530  if ($addressline2) {
2531  $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2532  }
2533  $XML_SEPA_INFO .= ' </PstlAdr>' . $CrLf;
2534  $XML_SEPA_INFO .= ' </Dbtr>' . $CrLf;
2535  $XML_SEPA_INFO .= ' <DbtrAcct>' . $CrLf;
2536  $XML_SEPA_INFO .= ' <Id>' . $CrLf;
2537  $XML_SEPA_INFO .= ' <IBAN>' . preg_replace('/\s/', '', $this->emetteur_iban) . '</IBAN>' . $CrLf;
2538  $XML_SEPA_INFO .= ' </Id>' . $CrLf;
2539  $XML_SEPA_INFO .= ' </DbtrAcct>' . $CrLf;
2540  $XML_SEPA_INFO .= ' <DbtrAgt>' . $CrLf;
2541  $XML_SEPA_INFO .= ' <FinInstnId>' . $CrLf;
2542  $XML_SEPA_INFO .= ' <BIC>' . $this->emetteur_bic . '</BIC>' . $CrLf;
2543  $XML_SEPA_INFO .= ' </FinInstnId>' . $CrLf;
2544  $XML_SEPA_INFO .= ' </DbtrAgt>' . $CrLf;
2545  /* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf;
2546  $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2547  $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2548  $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2549  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ADDRESS), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2550  $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ZIP.' '.$conf->global->MAIN_INFO_SOCIETE_TOWN), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2551  $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2552  $XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/
2553  $XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>' . $CrLf; // Field "Responsible of fees". Must be SLEV
2554  /*$XML_SEPA_INFO .= ' <CdtrSchmeId>'.$CrLf;
2555  $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2556  $XML_SEPA_INFO .= ' <PrvtId>'.$CrLf;
2557  $XML_SEPA_INFO .= ' <Othr>'.$CrLf;
2558  $XML_SEPA_INFO .= ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf;
2559  $XML_SEPA_INFO .= ' <SchmeNm>'.$CrLf;
2560  $XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>'.$CrLf;
2561  $XML_SEPA_INFO .= ' </SchmeNm>'.$CrLf;
2562  $XML_SEPA_INFO .= ' </Othr>'.$CrLf;
2563  $XML_SEPA_INFO .= ' </PrvtId>'.$CrLf;
2564  $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2565  $XML_SEPA_INFO .= ' </CdtrSchmeId>'.$CrLf;*/
2566  }
2567  } else {
2568  fwrite($this->file, 'INCORRECT EMETTEUR ' . $this->raison_sociale . $CrLf);
2569  $XML_SEPA_INFO = '';
2570  }
2571  return $XML_SEPA_INFO;
2572  }
2573 
2574  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2581  public function EnregTotal($total)
2582  {
2583  // phpcs:enable
2584  fwrite($this->file, "08");
2585  fwrite($this->file, "08"); // Prelevement ordinaire
2586 
2587  fwrite($this->file, " "); // Zone Reservee B2
2588 
2589  fwrite($this->file, $this->emetteur_ics); // ICS
2590 
2591  // Reserve C1
2592 
2593  fwrite($this->file, substr(" ", 0, 12));
2594 
2595 
2596  // Raison Sociale C2
2597 
2598  fwrite($this->file, substr(" ", 0, 24));
2599 
2600  // D1
2601 
2602  fwrite($this->file, substr(" ", 0, 24));
2603 
2604  // Zone Reservee D2
2605 
2606  fwrite($this->file, substr(" ", 0, 8));
2607 
2608  // Code Guichet D3
2609 
2610  fwrite($this->file, substr(" ", 0, 5));
2611 
2612  // Numero de compte D4
2613 
2614  fwrite($this->file, substr(" ", 0, 11));
2615 
2616  // Zone E Montant
2617 
2618  $montant = ($total * 100);
2619 
2620  fwrite($this->file, substr("000000000000000" . $montant, -16));
2621 
2622  // Zone Reservee F
2623 
2624  fwrite($this->file, substr(" ", 0, 31));
2625 
2626  // Code etablissement
2627 
2628  fwrite($this->file, substr(" ", 0, 5));
2629 
2630  // Zone Reservee F
2631 
2632  fwrite($this->file, substr(" ", 0, 5));
2633 
2634  fwrite($this->file, "\n");
2635  }
2636 
2643  public function getLibStatut($mode = 0)
2644  {
2645  return $this->LibStatut($this->statut, $mode);
2646  }
2647 
2648  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2656  public function LibStatut($status, $mode = 0)
2657  {
2658  // phpcs:enable
2659  if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
2660  global $langs;
2661  //$langs->load("mymodule");
2662  $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2663  $this->labelStatus[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2664  $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2665  $this->labelStatusShort[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2666  if ($this->type == 'bank-transfer') {
2667  $this->labelStatus[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2668  $this->labelStatusShort[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2669  } else {
2670  $this->labelStatus[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2671  $this->labelStatusShort[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2672  }
2673  }
2674 
2675  $statusType = 'status1';
2676  if ($status == self::STATUS_TRANSFERED) {
2677  $statusType = 'status3';
2678  }
2679  if ($status == self::STATUS_CREDITED || $status == self::STATUS_DEBITED) {
2680  $statusType = 'status6';
2681  }
2682 
2683  return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
2684  }
2685 
2686  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2694  public function load_board($user, $mode)
2695  {
2696  // phpcs:enable
2697  if ($user->socid) {
2698  return -1; // protection pour eviter appel par utilisateur externe
2699  }
2700 
2701  /*
2702  if ($mode == 'direct_debit') {
2703  $sql = "SELECT b.rowid, f.datedue as datefin";
2704  $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
2705  $sql .= " WHERE f.entity IN (".getEntity('facture').")";
2706  $sql .= " AND f.total_ttc > 0";
2707  } else {
2708  $sql = "SELECT b.rowid, f.datedue as datefin";
2709  $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
2710  $sql .= " WHERE f.entity IN (".getEntity('facture_fourn').")";
2711  $sql .= " AND f.total_ttc > 0";
2712  }
2713 
2714  $resql = $this->db->query($sql);
2715  if ($resql) {
2716  $langs->load("banks");
2717  $now = dol_now();
2718 
2719  $response = new WorkboardResponse();
2720  if ($mode == 'direct_debit') {
2721  $response->warning_delay = $conf->prelevement->warning_delay / 60 / 60 / 24;
2722  $response->label = $langs->trans("PendingDirectDebitToComplete");
2723  $response->labelShort = $langs->trans("PendingDirectDebitToCompleteShort");
2724  $response->url = DOL_URL_ROOT.'/compta/prelevement/index.php?leftmenu=checks&mainmenu=bank';
2725  } else {
2726  $response->warning_delay = $conf->paymentbybanktransfer->warning_delay / 60 / 60 / 24;
2727  $response->label = $langs->trans("PendingCreditTransferToComplete");
2728  $response->labelShort = $langs->trans("PendingCreditTransferToCompleteShort");
2729  $response->url = DOL_URL_ROOT.'/compta/paymentbybanktransfer/index.php?leftmenu=checks&mainmenu=bank';
2730  }
2731  $response->img = img_object('', "payment");
2732 
2733  while ($obj = $this->db->fetch_object($resql)) {
2734  $response->nbtodo++;
2735 
2736  if ($this->db->jdate($obj->datefin) < ($now - $conf->withdraw->warning_delay)) {
2737  $response->nbtodolate++;
2738  }
2739  }
2740 
2741  $response->nbtodo = 0;
2742  $response->nbtodolate = 0;
2743  // Return workboard only if quantity is not 0
2744  if ($response->nbtodo) {
2745  return $response;
2746  } else {
2747  return 0;
2748  }
2749  } else {
2750  dol_print_error($this->db);
2751  $this->error = $this->db->error();
2752  return -1;
2753  }
2754  */
2755  return 0;
2756  }
2757 
2765  public function getKanbanView($option = '', $arraydata = null)
2766  {
2767  global $langs;
2768 
2769  $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2770 
2771  $return = '<div class="box-flex-item box-flex-grow-zero">';
2772  $return .= '<div class="info-box info-box-sm">';
2773  $return .= '<span class="info-box-icon bg-infobox-action">';
2774  $return .= img_picto('', $this->picto);
2775  $return .= '</span>';
2776  $return .= '<div class="info-box-content">';
2777  $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . (method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref) . '</span>';
2778  if ($selected >= 0) {
2779  $return .= '<input id="cb' . $this->id . '" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="' . $this->id . '"' . ($selected ? ' checked="checked"' : '') . '>';
2780  }
2781  if (property_exists($this, 'date_echeance')) {
2782  $return .= '<br><span class="opacitymedium">' . $langs->trans("Date") . '</span> : <span class="info-box-label">' . dol_print_date($this->db->jdate($this->date_echeance), 'day') . '</span>';
2783  }
2784  if (property_exists($this, 'total')) {
2785  $return .= '<br><span class="opacitymedium">' . $langs->trans("Amount") . '</span> : <span class="amount">' . price($this->total) . '</span>';
2786  }
2787  if (method_exists($this, 'LibStatut')) {
2788  $return .= '<br><div class="info-box-status">' . $this->getLibStatut(3) . '</div>';
2789  }
2790  $return .= '</div>';
2791  $return .= '</div>';
2792  $return .= '</div>';
2793  return $return;
2794  }
2795 
2802  {
2803  if (!empty($this->id)) {
2804  $id = $this->id;
2805  } else {
2806  return 0;
2807  }
2808  if ($id) {
2809  $sql = "SELECT COUNT(*) AS nb FROM " . MAIN_DB_PREFIX . "prelevement_lignes";
2810  $sql .= " WHERE fk_prelevement_bons = " . ((int) $id);
2811  $sql .= " AND fk_soc = 0"; // fk_soc can't be NULL
2812  $sql .= " AND fk_user IS NOT NULL";
2813 
2814  $num = 0;
2815  $resql = $this->db->query($sql);
2816  if ($resql) {
2817  $obj = $this->db->fetch_object($resql);
2818  $num = $obj->nb;
2819  }
2820  if ($num > 0) {
2821  return 1;
2822  }
2823  } else {
2824  dol_print_error($this->db);
2825  }
2826 
2827  return 0;
2828  }
2829 }
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition: security.php:604
checkSwiftForAccount(Account $account=null, $swift=null)
Check SWIFT information for a bank account.
Definition: bank.lib.php:284
checkIbanForAccount(Account $account=null, $ibantocheck=null)
Check IBAN number information for a bank account.
Definition: bank.lib.php:305
$object ref
Definition: info.php:79
Class to manage bank accounts.
Class to manage withdrawal receipts.
load_board($user, $mode)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
SommeAPrelever($mode='direct-debit', $type='')
Returns amount waiting for direct debit payment or credit transfer payment.
static buildRumNumber($row_code_client, $row_datec, $row_drum)
Generate dynamically a RUM number for a customer bank account.
EnregEmetteur($type='direct-debit')
Write sender of request (me).
checkIfSalaryBonPrelevement()
Check if is bon prelevement for salary invoice.
EnregTotal($total)
Write end.
NbFactureAPrelever($type='direct-debit', $forsalary=0)
Get number of invoices to pay.
generate($format='ALL', $executiondate=0, $type='direct-debit', $fk_bank_account=0, $forsalary=0)
Generate a direct debit or credit transfer file.
fetch($rowid, $ref='')
Get object and lines from database.
getListInvoices($amounts=0, $type='')
Get invoice or salary list (with amount or not)
deleteNotificationById($rowid)
Delete a notification def by id.
AddFacture($invoice_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $type='debit-order', $sourcetype='')
Add invoice 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)
getKanbanView($option='', $arraydata=null)
Return clicable link of object (with eventually picto)
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Returns clickable name (with picto)
LibStatut($status, $mode=0)
Return status label for a status.
update(User $user, $notrigger=0)
Update object into database.
set_infotrans($user, $date, $method)
Set withdrawal to transmitted status.
getErrorString($error)
Return error string.
EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf='\n', $format='FRST', $type='direct-debit', $fk_bank_account=0)
Write sender of request (me).
set_infocredit($user, $date, $type='')
Set direct debit or credit transfer order to "paid" status.
addline(&$line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $sourcetype='')
Add line to withdrawal.
getLibStatut($mode=0)
Return status label of object.
EnregDestinataireSEPA($row_code_client, $row_nom, $row_address, $row_zip, $row_town, $row_country_code, $row_cb, $row_cg, $row_cc, $row_somme, $row_ref, $row_idfac, $row_iban, $row_bic, $row_datec, $row_drum, $row_rum, $type='direct-debit', $row_comment='')
Write recipient (thirdparty concerned by request)
addNotification($db, $user, $action)
Add a notification.
nbOfInvoiceToPay($mode='direct-debit', $type='')
Get number of invoices waiting for payment.
create($banque=0, $agence=0, $mode='real', $format='ALL', $executiondate='', $notrigger=0, $type='direct-debit', $did=0, $fk_bank_account=0, $sourcetype='invoice')
Create a BAN payment order:
deleteNotification($user, $action)
Delete a notification.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
updateCommon(User $user, $notrigger=0)
Update object into database.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Class to manage suppliers invoices.
Class to manage invoices.
const STATUS_VALIDATED
Validated (need to be paid)
Class to manage payments for supplier invoices.
Class to manage payments of customer invoices.
Class to manage payments of salaries.
Class to manage salary payments.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage Dolibarr users.
Definition: user.class.php:50
if(isModEnabled('invoice') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&!getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') && $user->hasRight('tax', 'charges', 'lire')) if(isModEnabled('invoice') &&isModEnabled('order') && $user->hasRight("commande", "lire") &&!getDolGlobalString('WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER')) $sql
Social contributions to pay.
Definition: index.php:744
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_string_nospecial($str, $newstr='_', $badcharstoreplace='', $badcharstoremove='', $keepspaces=0)
Clean a string from all punctuation characters to use it as a ref or login.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dolChmod($filepath, $newmask='')
Change mod of a file.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_string_unaccent($str)
Clean a string from all accent characters to be used as ref, login or by dol_sanitizeFileName.
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
td amount
Definition: global.inc.php:554
div float
Buy price without taxes.
Definition: style.css.php:959
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:122