dolibarr 18.0.6
bonprelevement.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2004-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
4 * Copyright (C) 2010-2015 Juanjo Menent <jmenent@2byte.es>
5 * Copyright (C) 2010-2014 Laurent Destailleur <eldy@users.sourceforge.net>
6 * Copyright (C) 2014-2016 Ferran Marcet <fmarcet@2byte.es>
7 * Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
8 * Copyright (C) 2019 JC Prieto <jcprieto@virtual20.com><prietojc@gmail.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 */
23
30require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
31require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
32require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
33require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
34require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
35require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
36require_once DOL_DOCUMENT_ROOT.'/fourn/class/paiementfourn.class.php';
37
38
39
44{
48 public $element = 'widthdraw';
49
53 public $table_element = 'prelevement_bons';
54
58 public $picto = 'payment';
59
60 public $date_echeance;
61 public $raison_sociale;
62 public $reference_remise;
63 public $emetteur_code_guichet;
64 public $emetteur_numero_compte;
65 public $emetteur_code_banque;
66 public $emetteur_number_key;
67 public $sepa_xml_pti_in_ctti;
68
69 public $emetteur_iban;
70 public $emetteur_bic;
71 public $emetteur_ics;
72
73 public $user_trans;
74 public $user_credit;
75
76 public $total;
77 public $fetched;
78 public $labelStatus = array();
79
80 public $factures = array();
81
82 public $invoice_in_error = array();
83 public $thirdparty_in_error = array();
84
88 public $file;
89
90
91 const STATUS_DRAFT = 0;
92 const STATUS_TRANSFERED = 1;
93 const STATUS_CREDITED = 2; // STATUS_CREDITED and STATUS_DEBITED is same. Difference is in ->type
94 const STATUS_DEBITED = 2; // STATUS_CREDITED and STATUS_DEBITED is same. Difference is in ->type
95
96
136 // BEGIN MODULEBUILDER PROPERTIES
140 public $fields=array(
141 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>10, 'notnull'=>1, 'visible'=>0,),
142 'ref' => array('type'=>'varchar(12)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>15, 'notnull'=>0, 'visible'=>-1, 'csslist'=>'tdoverflowmax150', 'showoncombobox'=>'1',),
143 'datec' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>25, 'notnull'=>0, 'visible'=>-1,),
144 'amount' => array('type'=>'double(24,8)', 'label'=>'Amount', 'enabled'=>'1', 'position'=>30, 'notnull'=>0, 'visible'=>-1,),
145 'statut' => array('type'=>'smallint(6)', 'label'=>'Statut', 'enabled'=>'1', 'position'=>500, 'notnull'=>0, 'visible'=>-1, 'arrayofkeyval'=>array(0=>'Wait', 1=>'Transfered', 2=>'Credited')),
146 'credite' => array('type'=>'smallint(6)', 'label'=>'Credite', 'enabled'=>'1', 'position'=>40, 'notnull'=>0, 'visible'=>-1,),
147 'note' => array('type'=>'text', 'label'=>'Note', 'enabled'=>'1', 'position'=>45, 'notnull'=>0, 'visible'=>-1,),
148 'date_trans' => array('type'=>'datetime', 'label'=>'Datetrans', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>-1,),
149 'method_trans' => array('type'=>'smallint(6)', 'label'=>'Methodtrans', 'enabled'=>'1', 'position'=>55, 'notnull'=>0, 'visible'=>-1,),
150 'fk_user_trans' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'Fkusertrans', 'enabled'=>'1', 'position'=>60, 'notnull'=>0, 'visible'=>-1, 'css'=>'maxwidth500 widthcentpercentminusxx', 'csslist'=>'tdoverflowmax150',),
151 'date_credit' => array('type'=>'datetime', 'label'=>'Datecredit', 'enabled'=>'1', 'position'=>65, 'notnull'=>0, 'visible'=>-1,),
152 'fk_user_credit' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'Fkusercredit', 'enabled'=>'1', 'position'=>70, 'notnull'=>0, 'visible'=>-1, 'css'=>'maxwidth500 widthcentpercentminusxx', 'csslist'=>'tdoverflowmax150',),
153 'type' => array('type'=>'varchar(16)', 'label'=>'Type', 'enabled'=>'1', 'position'=>75, 'notnull'=>0, 'visible'=>-1,),
154 'fk_bank_account' => array('type'=>'integer', 'label'=>'Fkbankaccount', 'enabled'=>'1', 'position'=>80, 'notnull'=>0, 'visible'=>-1, 'css'=>'maxwidth500 widthcentpercentminusxx',),
155 );
156 public $rowid;
157 public $ref;
158 public $datec;
159 public $amount;
160 public $statut;
161 public $credite;
162 public $note;
163 public $date_trans;
164 public $method_trans;
165 public $fk_user_trans;
166 public $date_credit;
167 public $fk_user_credit;
168 public $type;
169 public $fk_bank_account;
170 // END MODULEBUILDER PROPERTIES
171
172
173
179 public function __construct($db)
180 {
181 global $conf, $langs;
182
183 $this->db = $db;
184
185 $this->filename = '';
186
187 $this->date_echeance = dol_now();
188 $this->raison_sociale = "";
189 $this->reference_remise = "";
190
191 $this->emetteur_code_guichet = "";
192 $this->emetteur_numero_compte = "";
193 $this->emetteur_code_banque = "";
194 $this->emetteur_number_key = "";
195 $this->sepa_xml_pti_in_ctti = false;
196
197 $this->emetteur_iban = "";
198 $this->emetteur_bic = "";
199 $this->emetteur_ics = "";
200
201 $this->factures = array();
202
203 $this->methodes_trans = array(0 => 'Internet', 2 => 'Email', 3 => 'Api');
204
205 $this->fetched = 0;
206 }
207
208 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
223 public function AddFacture($invoice_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $type = 'debit-order')
224 {
225 // phpcs:enable
226 $result = 0;
227 $line_id = 0;
228
229 // Add lines
230 $result = $this->addline($line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key);
231
232 if ($result == 0) {
233 if ($line_id > 0) {
234 $sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement (";
235 if ($type != 'bank-transfer') {
236 $sql .= "fk_facture";
237 } else {
238 $sql .= "fk_facture_fourn";
239 }
240 $sql .= ",fk_prelevement_lignes";
241 $sql .= ") VALUES (";
242 $sql .= ((int) $invoice_id);
243 $sql .= ", ".((int) $line_id);
244 $sql .= ")";
245
246 if ($this->db->query($sql)) {
247 $result = 0;
248 } else {
249 $result = -1;
250 $this->errors[] = get_class($this)."::AddFacture ".$this->db->lasterror;
251 dol_syslog(get_class($this)."::AddFacture Error $result");
252 }
253 } else {
254 $result = -2;
255 $this->errors[] = get_class($this)."::AddFacture linedid Empty";
256 dol_syslog(get_class($this)."::AddFacture Error $result");
257 }
258 } else {
259 $result = -3;
260 dol_syslog(get_class($this)."::AddFacture Error $result");
261 }
262
263 return $result;
264 }
265
279 public function addline(&$line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key)
280 {
281 $result = -1;
282 $concat = 0;
283
284 if ($concat == 1) {
285 /*
286 * We aggregate the lines
287 */
288 $sql = "SELECT rowid";
289 $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_lignes";
290 $sql .= " WHERE fk_prelevement_bons = ".((int) $this->id);
291 $sql .= " AND fk_soc =".((int) $client_id);
292 $sql .= " AND code_banque = '".$this->db->escape($code_banque)."'";
293 $sql .= " AND code_guichet = '".$this->db->escape($code_guichet)."'";
294 $sql .= " AND number = '".$this->db->escape($number)."'";
295
296 $resql = $this->db->query($sql);
297 if ($resql) {
298 $num = $this->db->num_rows($resql);
299 } else {
300 $result = -1;
301 }
302 } else {
303 /*
304 * No aggregate
305 */
306 $sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement_lignes (";
307 $sql .= "fk_prelevement_bons";
308 $sql .= ", fk_soc";
309 $sql .= ", client_nom";
310 $sql .= ", amount";
311 $sql .= ", code_banque";
312 $sql .= ", code_guichet";
313 $sql .= ", number";
314 $sql .= ", cle_rib";
315 $sql .= ") VALUES (";
316 $sql .= $this->id;
317 $sql .= ", ".((int) $client_id);
318 $sql .= ", '".$this->db->escape($client_nom)."'";
319 $sql .= ", ".((float) price2num($amount));
320 $sql .= ", '".$this->db->escape($code_banque)."'";
321 $sql .= ", '".$this->db->escape($code_guichet)."'";
322 $sql .= ", '".$this->db->escape($number)."'";
323 $sql .= ", '".$this->db->escape($number_key)."'";
324 $sql .= ")";
325
326 if ($this->db->query($sql)) {
327 $line_id = $this->db->last_insert_id(MAIN_DB_PREFIX."prelevement_lignes");
328 $result = 0;
329 } else {
330 $this->errors[] = get_class($this)."::addline Error -2 ".$this->db->lasterror;
331 dol_syslog(get_class($this)."::addline Error -2");
332 $result = -2;
333 }
334 }
335
336 return $result;
337 }
338
345 public function getErrorString($error)
346 {
347 global $langs;
348
349 $errors = array();
350
351 $errors[1027] = $langs->trans("DateInvalid");
352
353 return $errors[abs($error)];
354 }
355
363 public function fetch($rowid, $ref = '')
364 {
365 $sql = "SELECT p.rowid, p.ref, p.amount, p.note";
366 $sql .= ", p.datec as dc";
367 $sql .= ", p.date_trans as date_trans";
368 $sql .= ", p.method_trans, p.fk_user_trans";
369 $sql .= ", p.date_credit as date_credit";
370 $sql .= ", p.fk_user_credit";
371 $sql .= ", p.type";
372 $sql .= ", p.fk_bank_account";
373 $sql .= ", p.statut as status";
374 $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons as p";
375 $sql .= " WHERE p.entity IN (".getEntity('invoice').")";
376 if ($rowid > 0) {
377 $sql .= " AND p.rowid = ".((int) $rowid);
378 } else {
379 $sql .= " AND p.ref = '".$this->db->escape($ref)."'";
380 }
381
382 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
383 $result = $this->db->query($sql);
384 if ($result) {
385 if ($this->db->num_rows($result)) {
386 $obj = $this->db->fetch_object($result);
387
388 $this->id = $obj->rowid;
389 $this->ref = $obj->ref;
390 $this->amount = $obj->amount;
391 $this->note = $obj->note;
392 $this->datec = $this->db->jdate($obj->dc);
393
394 $this->date_trans = $this->db->jdate($obj->date_trans);
395 $this->method_trans = $obj->method_trans;
396 $this->user_trans = $obj->fk_user_trans;
397
398 $this->date_credit = $this->db->jdate($obj->date_credit);
399 $this->user_credit = $obj->fk_user_credit;
400
401 $this->type = $obj->type;
402 $this->fk_bank_account = $obj->fk_bank_account;
403
404 $this->status = $obj->status;
405 $this->statut = $obj->status; // For backward compatibility
406
407 $this->fetched = 1;
408
409 return 1;
410 } else {
411 dol_syslog(get_class($this)."::Fetch Erreur aucune ligne retournee");
412 return -1;
413 }
414 } else {
415 return -2;
416 }
417 }
418
426 public function update(User $user, $notrigger = false)
427 {
428 return $this->updateCommon($user, $notrigger);
429 }
430
431 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
440 public function set_infocredit($user, $date)
441 {
442 // phpcs:enable
443 global $conf, $langs;
444
445 $error = 0;
446
447 if ($this->fetched == 1) {
448 if ($date < $this->date_trans) {
449 $langs->load("errors");
450 $this->error = $langs->trans('ErrorDateOfMovementLowerThanDateOfFileTransmission');
451 dol_syslog("bon-prelevment::set_infocredit 1027 ".$this->error);
452 return -1027;
453 }
454
455 $this->db->begin();
456
457 $sql = " UPDATE ".MAIN_DB_PREFIX."prelevement_bons";
458 $sql .= " SET fk_user_credit = ".$user->id;
459 $sql .= ", statut = ".self::STATUS_CREDITED;
460 $sql .= ", date_credit = '".$this->db->idate($date)."'";
461 $sql .= " WHERE rowid=".((int) $this->id);
462 $sql .= " AND entity = ".((int) $conf->entity);
463 $sql .= " AND statut = ".self::STATUS_TRANSFERED;
464
465 $resql = $this->db->query($sql);
466 if ($resql) {
467 $langs->load('withdrawals');
468 $subject = $langs->trans("InfoCreditSubject", $this->ref);
469 $message = $langs->trans("InfoCreditMessage", $this->ref, dol_print_date($date, 'dayhour'));
470
471 // Add payment of withdrawal into bank
472 $fk_bank_account = $this->fk_bank_account;
473 if (empty($fk_bank_account)) {
474 $fk_bank_account = ($this->type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT);
475 }
476
477 $facs = array();
478 $amounts = array();
479 $amountsperthirdparty = array();
480
481 $facs = $this->getListInvoices(1);
482
483 // Loop on each invoice. $facs=array(0=>id, 1=>amount requested)
484 $num = count($facs);
485 for ($i = 0; $i < $num; $i++) {
486 if ($this->type == 'bank-transfer') {
487 $fac = new FactureFournisseur($this->db);
488 } else {
489 $fac = new Facture($this->db);
490 }
491
492 $result = $fac->fetch($facs[$i][0]);
493
494 $amounts[$fac->id] = $facs[$i][1];
495 $amountsperthirdparty[$fac->socid][$fac->id] = $facs[$i][1];
496
497 $totalpaid = $fac->getSommePaiement();
498 $totalcreditnotes = $fac->getSumCreditNotesUsed();
499 $totaldeposits = $fac->getSumDepositsUsed();
500 $alreadypayed = $totalpaid + $totalcreditnotes + $totaldeposits;
501
502 // @TODO Move this after creation of payment
503 if (price2num($alreadypayed + $facs[$i][1], 'MT') == $fac->total_ttc) {
504 $result = $fac->setPaid($user);
505 if ($result < 0) {
506 $this->error = $fac->error;
507 $this->errors = $fac->errors;
508 }
509 }
510 }
511 //var_dump($amountsperthirdparty);exit;
512
513 // Make one payment per customer
514 foreach ($amountsperthirdparty as $thirdpartyid => $cursoramounts) {
515 if ($this->type == 'bank-transfer') {
516 $paiement = new PaiementFourn($this->db);
517 } else {
518 $paiement = new Paiement($this->db);
519 }
520 $paiement->datepaye = $date;
521 $paiement->amounts = $cursoramounts; // Array with detail of dispatching of payments for each invoice
522
523 if ($this->type == 'bank-transfer') {
524 $paiement->paiementid = 2;
525 $paiement->paiementcode = 'VIR';
526 } else {
527 $paiement->paiementid = 3;
528 $paiement->paiementcode = 'PRE';
529 }
530
531 $paiement->num_payment = $this->ref; // Set ref of direct debit note
532 $paiement->id_prelevement = $this->id;
533
534 $paiement_id = $paiement->create($user); // This use ->paiementid, that is ID of payment mode
535 if ($paiement_id < 0) {
536 $error++;
537 $this->error = $paiement->error;
538 $this->errors = $paiement->errors;
539 dol_syslog(get_class($this)."::set_infocredit AddPayment Error ".$this->error);
540 } else {
541 if ($this->type == 'bank-transfer') {
542 $modeforaddpayment = 'payment_supplier';
543 $labelforaddpayment = '(BankTransferPayment)';
544 } else {
545 $modeforaddpayment = 'payment';
546 $labelforaddpayment = '(WithdrawalPayment)';
547 }
548
549 $result = $paiement->addPaymentToBank($user, $modeforaddpayment, $labelforaddpayment, $fk_bank_account, '', '');
550 if ($result < 0) {
551 $error++;
552 $this->error = $paiement->error;
553 $this->errors = $paiement->errors;
554 dol_syslog(get_class($this)."::set_infocredit AddPaymentToBank Error ".$this->error);
555 }
556 }
557 }
558
559 // Update withdrawal line
560 // TODO: Translate to ligneprelevement.class.php
561 if (!$error) {
562 $sql = " UPDATE ".MAIN_DB_PREFIX."prelevement_lignes";
563 $sql .= " SET statut = 2";
564 $sql .= " WHERE fk_prelevement_bons = ".((int) $this->id);
565
566 if (!$this->db->query($sql)) {
567 dol_syslog(get_class($this)."::set_infocredit Update lines Error");
568 $error++;
569 }
570 }
571 } else {
572 $this->error = $this->db->lasterror();
573 dol_syslog(get_class($this)."::set_infocredit Update Bons Error");
574 $error++;
575 }
576
577 /*
578 * End of procedure
579 */
580 if ($error == 0) {
581 $this->date_credit = $date;
582 $this->statut = self::STATUS_CREDITED;
583
584 $this->db->commit();
585 return 0;
586 } else {
587 $this->db->rollback();
588 return -1;
589 }
590 } else {
591 return -1026;
592 }
593 }
594
595 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
604 public function set_infotrans($user, $date, $method)
605 {
606 // phpcs:enable
607 global $conf, $langs;
608
609 $error = 0;
610
611 dol_syslog(get_class($this)."::set_infotrans Start", LOG_INFO);
612 if ($this->db->begin()) {
613 $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_bons ";
614 $sql .= " SET fk_user_trans = ".$user->id;
615 $sql .= " , date_trans = '".$this->db->idate($date)."'";
616 $sql .= " , method_trans = ".((int) $method);
617 $sql .= " , statut = ".self::STATUS_TRANSFERED;
618 $sql .= " WHERE rowid = ".((int) $this->id);
619 $sql .= " AND entity = ".((int) $conf->entity);
620 $sql .= " AND statut = 0";
621
622 if ($this->db->query($sql)) {
623 $this->method_trans = $method;
624 $langs->load('withdrawals');
625 $subject = $langs->trans("InfoTransSubject", $this->ref);
626 $message = $langs->trans("InfoTransMessage", $this->ref, dolGetFirstLastname($user->firstname, $user->lastname));
627 $message .= $langs->trans("InfoTransData", price($this->amount), $this->methodes_trans[$this->method_trans], dol_print_date($date, 'day'));
628
629 // TODO Call trigger to create a notification using notification module
630 } else {
631 $error++;
632 }
633
634 if ($error == 0) {
635 $this->date_trans = $date;
636 $this->statut = 1;
637 $this->user_trans = $user->id;
638 $this->db->commit();
639
640 return 0;
641 } else {
642 $this->db->rollback();
643 dol_syslog(get_class($this)."::set_infotrans ROLLBACK", LOG_ERR);
644
645 return -1;
646 }
647 } else {
648 dol_syslog(get_class($this)."::set_infotrans Ouverture transaction SQL impossible", LOG_CRIT);
649 return -2;
650 }
651 }
652
659 private function getListInvoices($amounts = 0)
660 {
661 global $conf;
662
663 $arr = array();
664
665 /*
666 * Returns all invoices presented within same order
667 */
668 $sql = "SELECT ";
669 if ($this->type == 'bank-transfer') {
670 $sql .= " pf.fk_facture_fourn";
671 } else {
672 $sql .= " pf.fk_facture";
673 }
674 if ($amounts) {
675 $sql .= ", SUM(pl.amount)";
676 }
677 $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons as p";
678 $sql .= " , ".MAIN_DB_PREFIX."prelevement_lignes as pl";
679 $sql .= " , ".MAIN_DB_PREFIX."prelevement as pf";
680 $sql .= " WHERE pf.fk_prelevement_lignes = pl.rowid";
681 $sql .= " AND pl.fk_prelevement_bons = p.rowid";
682 $sql .= " AND p.rowid = ".((int) $this->id);
683 $sql .= " AND p.entity = ".((int) $conf->entity);
684 if ($amounts) {
685 if ($this->type == 'bank-transfer') {
686 $sql .= " GROUP BY fk_facture_fourn";
687 } else {
688 $sql .= " GROUP BY fk_facture";
689 }
690 }
691
692 $resql = $this->db->query($sql);
693 if ($resql) {
694 $num = $this->db->num_rows($resql);
695
696 if ($num) {
697 $i = 0;
698 while ($i < $num) {
699 $row = $this->db->fetch_row($resql);
700 if (!$amounts) {
701 $arr[$i] = $row[0];
702 } else {
703 $arr[$i] = array(
704 $row[0],
705 $row[1]
706 );
707 }
708 $i++;
709 }
710 }
711 $this->db->free($resql);
712 } else {
713 dol_syslog(get_class($this)."::getListInvoices Erreur");
714 }
715
716 return $arr;
717 }
718
719 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
726 public function SommeAPrelever($mode = 'direct-debit')
727 {
728 // phpcs:enable
729 global $conf;
730
731 $sql = "SELECT sum(pfd.amount) as nb";
732 if ($mode != 'bank-transfer') {
733 $sql .= " FROM ".MAIN_DB_PREFIX."facture as f,";
734 } else {
735 $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f,";
736 }
737 $sql .= " ".MAIN_DB_PREFIX."prelevement_demande as pfd";
738 $sql .= " WHERE f.entity IN (".getEntity('invoice').")";
739 if (empty($conf->global->WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS)) {
740 $sql .= " AND f.fk_statut = ".Facture::STATUS_VALIDATED;
741 }
742 if ($mode != 'bank-transfer') {
743 $sql .= " AND f.rowid = pfd.fk_facture";
744 } else {
745 $sql .= " AND f.rowid = pfd.fk_facture_fourn";
746 }
747 $sql .= " AND f.paye = 0";
748 $sql .= " AND pfd.traite = 0";
749 $sql .= " AND pfd.ext_payment_id IS NULL";
750 $sql .= " AND f.total_ttc > 0";
751
752 $resql = $this->db->query($sql);
753 if ($resql) {
754 $obj = $this->db->fetch_object($resql);
755
756 $this->db->free($resql);
757
758 return $obj->nb;
759 } else {
760 $error = 1;
761 dol_syslog(get_class($this)."::SommeAPrelever Erreur -1");
762 dol_syslog($this->db->error());
763
764 return -1;
765 }
766 }
767
774 public function nbOfInvoiceToPay($mode = 'direct-debit')
775 {
776 return $this->NbFactureAPrelever($mode);
777 }
778
779 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
786 public function NbFactureAPrelever($type = 'direct-debit')
787 {
788 // phpcs:enable
789 global $conf;
790
791 $sql = "SELECT count(f.rowid) as nb";
792 if ($type == 'bank-transfer') {
793 $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
794 } else {
795 $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
796 }
797 $sql .= ", ".MAIN_DB_PREFIX."prelevement_demande as pfd";
798 $sql .= " WHERE f.entity IN (".getEntity('invoice').")";
799 if (empty($conf->global->WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS)) {
800 $sql .= " AND f.fk_statut = ".Facture::STATUS_VALIDATED;
801 }
802 if ($type == 'bank-transfer') {
803 $sql .= " AND f.rowid = pfd.fk_facture_fourn";
804 } else {
805 $sql .= " AND f.rowid = pfd.fk_facture";
806 }
807 $sql .= " AND pfd.traite = 0";
808 $sql .= " AND pfd.ext_payment_id IS NULL";
809 $sql .= " AND f.total_ttc > 0";
810
811 dol_syslog(get_class($this)."::NbFactureAPrelever");
812 $resql = $this->db->query($sql);
813
814 if ($resql) {
815 $obj = $this->db->fetch_object($resql);
816
817 $this->db->free($resql);
818
819 return $obj->nb;
820 } else {
821 $this->error = get_class($this)."::NbFactureAPrelever Erreur -1 sql=".$this->db->error();
822 return -1;
823 }
824 }
825
826
827 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
847 public function create($banque = 0, $agence = 0, $mode = 'real', $format = 'ALL', $executiondate = '', $notrigger = 0, $type = 'direct-debit', $did = 0, $fk_bank_account = 0)
848 {
849 // phpcs:enable
850 global $conf, $langs, $user;
851
852 dol_syslog(__METHOD__." Bank=".$banque." Office=".$agence." mode=".$mode." format=".$format, LOG_DEBUG);
853
854 require_once DOL_DOCUMENT_ROOT."/compta/facture/class/facture.class.php";
855 require_once DOL_DOCUMENT_ROOT."/societe/class/societe.class.php";
856
857 // Check params
858 if ($type != 'bank-transfer') {
859 if (empty($format)) {
860 $this->error = 'ErrorBadParametersForDirectDebitFileCreate';
861 return -1;
862 }
863 }
864
865 // Clean params
866 if (empty($fk_bank_account)) {
867 $fk_bank_account = ($type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT);
868 }
869
870 $error = 0;
871
872 $datetimeprev = dol_now('gmt');
873 // Choice the date of the execution direct debit
874 if (!empty($executiondate)) {
875 $datetimeprev = $executiondate;
876 }
877
878 $month = dol_print_date($datetimeprev, "%m", 'gmt');
879 $year = dol_print_date($datetimeprev, "%Y", 'gmt');
880
881 $this->invoice_in_error = array();
882 $this->thirdparty_in_error = array();
883
884 // Read invoices
885 $factures = array();
886 $factures_prev = array();
887 $factures_result = array();
888 $factures_prev_id = array();
889 $factures_errors = array();
890
891 if (!$error) {
892 $sql = "SELECT f.rowid, pfd.rowid as pfdrowid, f.fk_soc";
893 $sql .= ", pfd.code_banque, pfd.code_guichet, pfd.number, pfd.cle_rib";
894 $sql .= ", pfd.amount";
895 $sql .= ", s.nom as name";
896 if ($type != 'bank-transfer') {
897 $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
898 } else {
899 $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
900 }
901 $sql .= ", ".MAIN_DB_PREFIX."societe as s";
902 $sql .= ", ".MAIN_DB_PREFIX."prelevement_demande as pfd";
903 $sql .= " WHERE f.entity IN (".getEntity('invoice').')';
904 if ($type != 'bank-transfer') {
905 $sql .= " AND f.rowid = pfd.fk_facture";
906 } else {
907 $sql .= " AND f.rowid = pfd.fk_facture_fourn";
908 }
909 $sql .= " AND s.rowid = f.fk_soc";
910 $sql .= " AND f.fk_statut = 1"; // Invoice validated
911 $sql .= " AND f.paye = 0";
912 $sql .= " AND pfd.traite = 0";
913 $sql .= " AND f.total_ttc > 0";
914 $sql .= " AND pfd.ext_payment_id IS NULL";
915 if ($did > 0) {
916 $sql .= " AND pfd.rowid = ".((int) $did);
917 }
918 dol_syslog(__METHOD__." Read invoices,", LOG_DEBUG);
919
920 $resql = $this->db->query($sql);
921 if ($resql) {
922 $num = $this->db->num_rows($resql);
923 $i = 0;
924
925 while ($i < $num) {
926 $row = $this->db->fetch_row($resql);
927 $factures[$i] = $row; // All fields
928 if ($row[7] == 0) {
929 $error++;
930 dol_syslog(__METHOD__." Read invoices error Found a null invoice", LOG_ERR);
931 $this->invoice_in_error[$row[0]] = "Error for invoice id ".$row[0].", found a null amount";
932 break;
933 }
934 $i++;
935 }
936 $this->db->free($resql);
937 dol_syslog(__METHOD__." Read invoices, ".$i." invoices to withdraw", LOG_DEBUG);
938 } else {
939 $error++;
940 dol_syslog(__METHOD__." Read invoices error ".$this->db->error(), LOG_ERR);
941 }
942 }
943
944 if (!$error) {
945 require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php';
946 $soc = new Societe($this->db);
947
948 // Check BAN
949 $i = 0;
950 dol_syslog(__METHOD__." Check BAN", LOG_DEBUG);
951
952 if (count($factures) > 0) {
953 foreach ($factures as $key => $fac) {
954 if ($type != 'bank-transfer') {
955 $tmpinvoice = new Facture($this->db);
956 } else {
957 $tmpinvoice = new FactureFournisseur($this->db);
958 }
959 $resfetch = $tmpinvoice->fetch($fac[0]);
960 if ($resfetch >= 0) { // Field 0 of $fac is rowid of invoice
961 if ($soc->fetch($tmpinvoice->socid) >= 0) {
962 $bac = new CompanyBankAccount($this->db);
963 $bac->fetch(0, $soc->id);
964
965 if ($type != 'bank-transfer') {
966 if ($format == 'FRST' && $bac->frstrecur != 'FRST') {
967 continue;
968 }
969 if ($format == 'RCUR' && ($bac->frstrecur != 'RCUR' && $bac->frstrecur != 'RECUR')) {
970 continue;
971 }
972 }
973
974 if ($bac->verif() >= 1) {
975 $factures_prev[$i] = $fac;
976 /* second array necessary for BonPrelevement */
977 $factures_prev_id[$i] = $fac[0];
978 $i++;
979 //dol_syslog(__METHOD__."::RIB is ok", LOG_DEBUG);
980 } else {
981 dol_syslog(__METHOD__." Check BAN Error on default bank number IBAN/BIC for thirdparty reported by verif() ".$tmpinvoice->socid." ".$soc->name, LOG_WARNING);
982 $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice ".$tmpinvoice->getNomUrl(0)." for thirdparty ".$soc->getNomUrl(0);
983 $this->thirdparty_in_error[$soc->id] = "Error on default bank number IBAN/BIC for invoice ".$tmpinvoice->getNomUrl(0)." for thirdparty ".$soc->getNomUrl(0);
984 }
985 } else {
986 dol_syslog(__METHOD__." Check BAN Failed to read company", LOG_WARNING);
987 }
988 } else {
989 dol_syslog(__METHOD__." Check BAN Failed to read invoice", LOG_WARNING);
990 }
991 }
992 } else {
993 dol_syslog(__METHOD__." Check BAN No invoice to process", LOG_WARNING);
994 }
995 }
996
997 $ok = 0;
998
999 // Withdraw invoices in factures_prev array
1000 $out = count($factures_prev)." invoices will be included.";
1001 //print $out."\n";
1002 dol_syslog($out);
1003
1004 // Return warning
1005 /*$i=0;
1006 foreach ($this->thirdparty_in_error as $key => $val)
1007 {
1008 if ($i < 10) setEventMessages($val, null, 'warnings');
1009 else setEventMessages('More error were discarded...', null, 'warnings');
1010 $i++;
1011 }*/
1012
1013 if (count($factures_prev) > 0) {
1014 if ($mode == 'real') {
1015 $ok = 1;
1016 } else {
1017 print $langs->trans("ModeWarning"); // "Option for real mode was not set, we stop after this simulation\n";
1018 }
1019 }
1020
1021 if ($ok) {
1022 /*
1023 * We are in real mode.
1024 * We create order and build file into disk
1025 */
1026 $this->db->begin();
1027
1028 $now = dol_now();
1029 $ref = '';
1030
1031 /*
1032 * Process order generation
1033 */
1034 if (!$error) {
1035 $ref = substr($year, -2).$month;
1036
1037 // Get next free nuber for the ref of bon
1038 $sql = "SELECT substring(ref from char_length(ref) - 1)"; // To extract "YYMMXX" from "TYYMMXX"
1039 $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons";
1040 $sql .= " WHERE ref LIKE '_".$this->db->escape($ref)."%'";
1041 $sql .= " AND entity = ".((int) $conf->entity);
1042 $sql .= " ORDER BY ref DESC LIMIT 1";
1043
1044 dol_syslog(get_class($this)." get next free number", LOG_DEBUG);
1045 $resql = $this->db->query($sql);
1046
1047 if ($resql) {
1048 $row = $this->db->fetch_row($resql);
1049
1050 // Build the new ref
1051 $ref = "T".$ref.sprintf("%02d", (intval($row[0]) + 1));
1052
1053 // $conf->abc->dir_output may be:
1054 // /home/ldestailleur/git/dolibarr_15.0/documents/abc/
1055 // or
1056 // /home/ldestailleur/git/dolibarr_15.0/documents/X/abc with X >= 2 with multicompany.
1057 if ($type != 'bank-transfer') {
1058 $dir = $conf->prelevement->dir_output.'/receipts';
1059 } else {
1060 $dir = $conf->paymentbybanktransfer->dir_output.'/receipts';
1061 }
1062 if (!is_dir($dir)) {
1063 dol_mkdir($dir);
1064 }
1065
1066 if (isModEnabled('multicompany')) {
1067 $labelentity = $conf->entity;
1068 $this->filename = $dir.'/'.$ref.'-'.$labelentity.'.xml';
1069 } else {
1070 $this->filename = $dir.'/'.$ref.'.xml';
1071 }
1072
1073 // Create withdraw order in database
1074 $sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement_bons (";
1075 $sql .= "ref, entity, datec, type, fk_bank_account";
1076 $sql .= ") VALUES (";
1077 $sql .= "'".$this->db->escape($ref)."'";
1078 $sql .= ", ".((int) $conf->entity);
1079 $sql .= ", '".$this->db->idate($now)."'";
1080 $sql .= ", '".($type == 'bank-transfer' ? 'bank-transfer' : 'debit-order')."'";
1081 $sql .= ", ".((int) $fk_bank_account);
1082 $sql .= ")";
1083
1084 $resql = $this->db->query($sql);
1085 if ($resql) {
1086 $prev_id = $this->db->last_insert_id(MAIN_DB_PREFIX."prelevement_bons");
1087 $this->id = $prev_id;
1088 $this->ref = $ref;
1089 } else {
1090 $error++;
1091 dol_syslog(__METHOD__." Create withdraw receipt ".$this->db->lasterror(), LOG_ERR);
1092 }
1093 } else {
1094 $error++;
1095 dol_syslog(__METHOD__." Get last withdraw receipt ".$this->db->lasterror(), LOG_ERR);
1096 }
1097 }
1098
1099 if (!$error) {
1100 if ($type != 'bank-transfer') {
1101 $fact = new Facture($this->db);
1102 } else {
1103 $fact = new FactureFournisseur($this->db);
1104 }
1105
1106 // Add lines for the bon
1107 if (count($factures_prev) > 0) {
1108 foreach ($factures_prev as $fac) { // Add a link in database for each invoice
1109 // Fetch invoice
1110 $result = $fact->fetch($fac[0]);
1111 if ($result < 0) {
1112 $this->error = 'ERRORBONPRELEVEMENT Failed to load invoice with id '.$fac[0];
1113 break;
1114 }
1115
1116 /*
1117 * Add standing order. This add record into llx_prelevement_lignes and llx_prelevement
1118 *
1119 * $fac[0] : invoice_id
1120 * $fac[1] : ???
1121 * $fac[2] : third party id
1122 * $fac[3] : banque
1123 * $fac[4] : guichet
1124 * $fac[5] : number
1125 * $fac[6] : cle rib
1126 * $fac[7] : amount
1127 * $fac[8] : client nom
1128 */
1129 $ri = $this->AddFacture($fac[0], $fac[2], $fac[8], $fac[7], $fac[3], $fac[4], $fac[5], $fac[6], $type);
1130 if ($ri <> 0) {
1131 $error++;
1132 }
1133
1134 // Update invoice requests as done
1135 $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_demande";
1136 $sql .= " SET traite = 1";
1137 $sql .= ", date_traite = '".$this->db->idate($now)."'";
1138 $sql .= ", fk_prelevement_bons = ".((int) $this->id);
1139 $sql .= " WHERE rowid = ".((int) $fac[1]);
1140
1141 $resql = $this->db->query($sql);
1142 if (!$resql) {
1143 $error++;
1144 $this->errors[] = $this->db->lasterror();
1145 dol_syslog(__METHOD__." Update Error=".$this->db->lasterror(), LOG_ERR);
1146 }
1147 }
1148 }
1149 }
1150
1151 if (!$error) {
1152 /*
1153 * Create file of type='direct-debit' for direct debit order or type='bank-transfer' for credit transfer into a XML file
1154 */
1155
1156 dol_syslog(__METHOD__." Init direct debit or credit transfer file for ".count($factures_prev)." invoices", LOG_DEBUG);
1157
1158 if (count($factures_prev) > 0) {
1159 $this->date_echeance = $datetimeprev;
1160 $this->reference_remise = $ref;
1161
1162 $account = new Account($this->db);
1163 if ($account->fetch($fk_bank_account) > 0) {
1164 $this->emetteur_code_banque = $account->code_banque;
1165 $this->emetteur_code_guichet = $account->code_guichet;
1166 $this->emetteur_numero_compte = $account->number;
1167 $this->emetteur_number_key = $account->cle_rib;
1168 $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
1169 $this->emetteur_iban = $account->iban;
1170 $this->emetteur_bic = $account->bic;
1171
1172 $this->emetteur_ics = ($type == 'bank-transfer' ? $account->ics_transfer : $account->ics);
1173
1174 $this->raison_sociale = $account->proprio;
1175 }
1176
1177 $this->factures = $factures_prev_id;
1178 $this->context['factures_prev'] = $factures_prev;
1179
1180 // Generation of direct debit or credit transfer file $this->filename (May be a SEPA file for european countries)
1181 // This also set the property $this->total with amount that is included into file
1182 $result = $this->generate($format, $executiondate, $type);
1183 if ($result < 0) {
1184 //var_dump($this->error);
1185 //var_dump($this->invoice_in_error);
1186 $error++;
1187 }
1188 }
1189 dol_syslog(__METHOD__." Bank order file has been generated under filename ".$this->filename, LOG_DEBUG);
1190 }
1191 //var_dump($this->total);exit;
1192
1193 /*
1194 * Update total defined after generation of file
1195 */
1196 if (!$error) {
1197 $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_bons";
1198 $sql .= " SET amount = ".price2num($this->total);
1199 $sql .= " WHERE rowid = ".((int) $this->id);
1200 $sql .= " AND entity = ".((int) $conf->entity);
1201
1202 $resql = $this->db->query($sql);
1203 if (!$resql) {
1204 $error++;
1205 dol_syslog(__METHOD__." Error update total: ".$this->db->error(), LOG_ERR);
1206 }
1207 }
1208
1209 if (!$error && !$notrigger) {
1210 $triggername = 'DIRECT_DEBIT_ORDER_CREATE';
1211 if ($type != 'bank-transfer') {
1212 $triggername = 'CREDIT_TRANSFER_ORDER_CREATE';
1213 }
1214
1215 // Call trigger
1216 $result = $this->call_trigger($triggername, $user);
1217 if ($result < 0) {
1218 $error++;
1219 }
1220 // End call triggers
1221 }
1222
1223 if (!$error) {
1224 $this->db->commit();
1225 return count($factures_prev);
1226 } else {
1227 $this->db->rollback();
1228 return -1;
1229 }
1230 } else {
1231 return 0;
1232 }
1233 }
1234
1235
1243 public function delete($user = null, $notrigger = 0)
1244 {
1245 $this->db->begin();
1246
1247 $error = 0;
1248 $resql1 = $resql2 = $resql3 = $resql4 = 0;
1249
1250 if (!$notrigger) {
1251 $triggername = 'DIRECT_DEBIT_ORDER_DELETE';
1252 if ($this->type == 'bank-transfer') {
1253 $triggername = 'PAYMENTBYBANKTRANFER_DELETE';
1254 }
1255 // Call trigger
1256 $result = $this->call_trigger($triggername, $user);
1257 if ($result < 0) {
1258 $error++;
1259 }
1260 // End call triggers
1261 }
1262
1263 if (!$error) {
1264 $sql = "DELETE FROM ".MAIN_DB_PREFIX."prelevement WHERE fk_prelevement_lignes IN (SELECT rowid FROM ".MAIN_DB_PREFIX."prelevement_lignes WHERE fk_prelevement_bons = ".((int) $this->id).")";
1265 $resql1 = $this->db->query($sql);
1266 if (!$resql1) {
1267 dol_print_error($this->db);
1268 }
1269 }
1270
1271 if (!$error) {
1272 $sql = "DELETE FROM ".MAIN_DB_PREFIX."prelevement_lignes WHERE fk_prelevement_bons = ".((int) $this->id);
1273 $resql2 = $this->db->query($sql);
1274 if (!$resql2) {
1275 dol_print_error($this->db);
1276 }
1277 }
1278
1279 if (!$error) {
1280 $sql = "DELETE FROM ".MAIN_DB_PREFIX."prelevement_bons WHERE rowid = ".((int) $this->id);
1281 $resql3 = $this->db->query($sql);
1282 if (!$resql3) {
1283 dol_print_error($this->db);
1284 }
1285 }
1286
1287 if (!$error) {
1288 $sql = "UPDATE ".MAIN_DB_PREFIX."prelevement_demande SET fk_prelevement_bons = NULL, traite = 0 WHERE fk_prelevement_bons = ".((int) $this->id);
1289 $resql4 = $this->db->query($sql);
1290 if (!$resql4) {
1291 dol_print_error($this->db);
1292 }
1293 }
1294
1295 if ($resql1 && $resql2 && $resql3 && $resql4 && !$error) {
1296 $this->db->commit();
1297 return 1;
1298 } else {
1299 $this->db->rollback();
1300 return -1;
1301 }
1302 }
1303
1304
1315 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1316 {
1317 global $conf, $langs, $hookmanager;
1318
1319 if (!empty($conf->dol_no_mouse_hover)) {
1320 $notooltip = 1; // Force disable tooltips
1321 }
1322
1323 $result = '';
1324
1325 $labeltoshow = 'PaymentByDirectDebit';
1326 if (!empty($this->type) && $this->type == 'bank-transfer') {
1327 $labeltoshow = 'PaymentByBankTransfer';
1328 }
1329
1330 $label = img_picto('', $this->picto).' <u>'.$langs->trans($labeltoshow).'</u> '.$this->getLibStatut(5);
1331 $label .= '<br>';
1332 $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
1333 if (isset($this->amount)) {
1334 $label .= '<br><b>'.$langs->trans("Amount").":</b> ".price($this->amount);
1335 }
1336 if (isset($this->date_trans)) {
1337 $label .= '<br><b>'.$langs->trans("TransData").":</b> ".dol_print_date($this->date_trans, 'dayhour', 'tzuserrel');
1338 }
1339 /*if (isset($this->date_credit)) {
1340 $label .= '<br><b>'.$langs->trans("TransData").":</b> ".dol_print_date($this->date_credit, 'dayhour', 'tzuserrel');
1341 }*/
1342
1343 $url = DOL_URL_ROOT.'/compta/prelevement/card.php?id='.$this->id;
1344 if (!empty($this->type) && $this->type == 'bank-transfer') {
1345 $url = DOL_URL_ROOT.'/compta/prelevement/card.php?id='.$this->id;
1346 }
1347
1348 if ($option != 'nolink') {
1349 // Add param to save lastsearch_values or not
1350 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1351 if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1352 $add_save_lastsearch_values = 1;
1353 }
1354 if ($add_save_lastsearch_values) {
1355 $url .= '&save_lastsearch_values=1';
1356 }
1357 }
1358
1359 $linkclose = '';
1360 if (empty($notooltip)) {
1361 if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
1362 $label = $langs->trans("ShowMyObject");
1363 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
1364 }
1365 $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
1366 $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
1367 } else {
1368 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1369 }
1370
1371 $linkstart = '<a href="'.$url.'"';
1372 $linkstart .= $linkclose.'>';
1373 $linkend = '</a>';
1374
1375 $result .= $linkstart;
1376 if ($withpicto) {
1377 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
1378 }
1379 if ($withpicto != 2) {
1380 $result .= $this->ref;
1381 }
1382 $result .= $linkend;
1383
1384 global $action, $hookmanager;
1385 $hookmanager->initHooks(array('banktransferdao'));
1386 $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
1387 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1388 if ($reshook > 0) {
1389 $result = $hookmanager->resPrint;
1390 } else {
1391 $result .= $hookmanager->resPrint;
1392 }
1393
1394 return $result;
1395 }
1396
1397
1404 public function deleteNotificationById($rowid)
1405 {
1406 $sql = "DELETE FROM ".MAIN_DB_PREFIX."notify_def";
1407 $sql .= " WHERE rowid = ".((int) $rowid);
1408
1409 if ($this->db->query($sql)) {
1410 return 0;
1411 } else {
1412 return -1;
1413 }
1414 }
1415
1423 public function deleteNotification($user, $action)
1424 {
1425 if (is_object($user)) {
1426 $userid = $user->id;
1427 } else { // If user is an id
1428 $userid = $user;
1429 }
1430
1431 $sql = "DELETE FROM ".MAIN_DB_PREFIX."notify_def";
1432 $sql .= " WHERE fk_user=".((int) $userid)." AND fk_action='".$this->db->escape($action)."'";
1433
1434 if ($this->db->query($sql)) {
1435 return 0;
1436 } else {
1437 return -1;
1438 }
1439 }
1440
1441 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1450 public function addNotification($db, $user, $action)
1451 {
1452 // phpcs:enable
1453 $result = 0;
1454
1455 if (is_object($user)) {
1456 $userid = $user->id;
1457 } else { // If user is an id
1458 $userid = $user;
1459 }
1460
1461 if ($this->deleteNotification($user, $action) == 0) {
1462 $now = dol_now();
1463
1464 $sql = "INSERT INTO ".MAIN_DB_PREFIX."notify_def (datec,fk_user, fk_soc, fk_contact, fk_action)";
1465 $sql .= " VALUES ('".$this->db->idate($now)."', ".((int) $userid).", 'NULL', 'NULL', '".$this->db->escape($action)."')";
1466
1467 dol_syslog("adnotiff: ".$sql);
1468 if ($this->db->query($sql)) {
1469 $result = 0;
1470 } else {
1471 $result = -1;
1472 dol_syslog(get_class($this)."::addNotification Error $result");
1473 }
1474 }
1475
1476 return $result;
1477 }
1478
1479
1493 public function generate($format = 'ALL', $executiondate = 0, $type = 'direct-debit', $fk_bank_account = 0)
1494 {
1495 global $conf, $langs, $mysoc;
1496
1497 //TODO: Optimize code to read lines in a single function
1498
1499 // Clean params
1500 if (empty($fk_bank_account)) {
1501 $fk_bank_account = ($type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT);
1502 }
1503
1504 $result = 0;
1505
1506 dol_syslog(get_class($this)."::generate build file=".$this->filename." type=".$type);
1507
1508 $this->file = fopen($this->filename, "w");
1509 if (empty($this->file)) {
1510 $this->error = $langs->trans('ErrorFailedToOpenFile', $this->filename);
1511 return -1;
1512 }
1513
1514 $found = 0;
1515 $this->total = 0;
1516
1517 // Build file for European countries
1518 if ($mysoc->isInEEC()) {
1519 $found++;
1520
1521 if ($type != 'bank-transfer') {
1525 // SEPA Initialisation
1526 $CrLf = "\n";
1527
1528 $now = dol_now();
1529
1530 $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S');
1531
1532 $date_actu = $now;
1533 if (!empty($executiondate)) {
1534 $date_actu = $executiondate;
1535 }
1536
1537 $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d');
1538 $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S');
1539 $fileDebiteurSection = '';
1540 $fileEmetteurSection = '';
1541 $i = 0;
1542
1543 /*
1544 * Section Debitor (sepa Debiteurs bloc lines)
1545 */
1546
1547 $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
1548 $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1549 $sql .= " f.ref as reffac, pf.fk_facture as idfac,";
1550 $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
1551 $sql .= " FROM";
1552 $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,";
1553 $sql .= " ".MAIN_DB_PREFIX."facture as f,";
1554 $sql .= " ".MAIN_DB_PREFIX."prelevement as pf,";
1555 $sql .= " ".MAIN_DB_PREFIX."societe as soc,";
1556 $sql .= " ".MAIN_DB_PREFIX."c_country as c,";
1557 $sql .= " ".MAIN_DB_PREFIX."societe_rib as rib";
1558 $sql .= " WHERE pl.fk_prelevement_bons = ".((int) $this->id);
1559 $sql .= " AND pl.rowid = pf.fk_prelevement_lignes";
1560 $sql .= " AND pf.fk_facture = f.rowid";
1561 $sql .= " AND f.fk_soc = soc.rowid";
1562 $sql .= " AND soc.fk_pays = c.rowid";
1563 $sql .= " AND rib.fk_soc = f.fk_soc";
1564 $sql .= " AND rib.default_rib = 1";
1565 $sql .= " AND rib.type = 'ban'";
1566
1567 // Define $fileDebiteurSection. One section DrctDbtTxInf per invoice.
1568 $resql = $this->db->query($sql);
1569 if ($resql) {
1570 $cachearraytotestduplicate = array();
1571
1572 $num = $this->db->num_rows($resql);
1573 while ($i < $num) {
1574 $obj = $this->db->fetch_object($resql);
1575
1576 if (!empty($cachearraytotestduplicate[$obj->idfac])) {
1577 $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
1578 $this->invoice_in_error[$obj->idfac] = $this->error;
1579 $result = -2;
1580 break;
1581 }
1582 $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
1583
1584 $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
1585
1586 $fileDebiteurSection .= $this->EnregDestinataireSEPA($obj->code, $obj->nom, $obj->address, $obj->zip, $obj->town, $obj->country_code, $obj->cb, $obj->cg, $obj->cc, $obj->somme, $obj->reffac, $obj->idfac, $obj->iban, $obj->bic, $daterum, $obj->drum, $obj->rum, $type);
1587
1588 $this->total = $this->total + $obj->somme;
1589 $i++;
1590 }
1591 $nbtotalDrctDbtTxInf = $i;
1592 } else {
1593 $this->error = $this->db->lasterror();
1594 fputs($this->file, 'ERROR DEBITOR '.$sql.$CrLf); // DEBITOR = Customers
1595 $result = -2;
1596 }
1597
1598 // Define $fileEmetteurSection. Start of bloc PmtInf. Will contains all $nbtotalDrctDbtTxInf
1599 if ($result != -2) {
1600 $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type, $fk_bank_account);
1601 }
1602
1606 // SEPA File Header
1607 fputs($this->file, '<'.'?xml version="1.0" encoding="UTF-8" standalone="yes"?'.'>'.$CrLf);
1608 fputs($this->file, '<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'.$CrLf);
1609 fputs($this->file, ' <CstmrDrctDbtInitn>'.$CrLf);
1610 // SEPA Group header
1611 fputs($this->file, ' <GrpHdr>'.$CrLf);
1612 fputs($this->file, ' <MsgId>'.('DD/'.$dateTime_YMD.'/REF'.$this->id).'</MsgId>'.$CrLf);
1613 fputs($this->file, ' <CreDtTm>'.$dateTime_ECMA.'</CreDtTm>'.$CrLf);
1614 fputs($this->file, ' <NbOfTxs>'.$i.'</NbOfTxs>'.$CrLf);
1615 fputs($this->file, ' <CtrlSum>'.$this->total.'</CtrlSum>'.$CrLf);
1616 fputs($this->file, ' <InitgPty>'.$CrLf);
1617 fputs($this->file, ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf);
1618 fputs($this->file, ' <Id>'.$CrLf);
1619 fputs($this->file, ' <PrvtId>'.$CrLf);
1620 fputs($this->file, ' <Othr>'.$CrLf);
1621 fputs($this->file, ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf);
1622 fputs($this->file, ' </Othr>'.$CrLf);
1623 fputs($this->file, ' </PrvtId>'.$CrLf);
1624 fputs($this->file, ' </Id>'.$CrLf);
1625 fputs($this->file, ' </InitgPty>'.$CrLf);
1626 fputs($this->file, ' </GrpHdr>'.$CrLf);
1627 // SEPA File Emetteur
1628 if ($result != -2) {
1629 fputs($this-> file, $fileEmetteurSection);
1630 }
1631 // SEPA File Debiteurs
1632 if ($result != -2) {
1633 fputs($this-> file, $fileDebiteurSection);
1634 }
1635 // SEPA FILE FOOTER
1636 fputs($this->file, ' </PmtInf>'.$CrLf);
1637 fputs($this->file, ' </CstmrDrctDbtInitn>'.$CrLf);
1638 fputs($this->file, '</Document>'.$CrLf);
1639 } else {
1643 // SEPA Initialisation
1644 $CrLf = "\n";
1645
1646 $now = dol_now();
1647
1648 $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S');
1649
1650 $date_actu = $now;
1651 if (!empty($executiondate)) {
1652 $date_actu = $executiondate;
1653 }
1654
1655 $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d');
1656 $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S');
1657 $fileCrediteurSection = '';
1658 $fileEmetteurSection = '';
1659 $i = 0;
1660
1661 /*
1662 * Section Creditor (sepa Crediteurs bloc lines)
1663 */
1664
1665 $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
1666 $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1667 $sql .= " f.ref as reffac, pf.fk_facture_fourn as idfac, f.ref_supplier as fac_ref_supplier,";
1668 $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
1669 $sql .= " FROM";
1670 $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,";
1671 $sql .= " ".MAIN_DB_PREFIX."facture_fourn as f,";
1672 $sql .= " ".MAIN_DB_PREFIX."prelevement as pf,";
1673 $sql .= " ".MAIN_DB_PREFIX."societe as soc,";
1674 $sql .= " ".MAIN_DB_PREFIX."c_country as c,";
1675 $sql .= " ".MAIN_DB_PREFIX."societe_rib as rib";
1676 $sql .= " WHERE pl.fk_prelevement_bons = ".((int) $this->id);
1677 $sql .= " AND pl.rowid = pf.fk_prelevement_lignes";
1678 $sql .= " AND pf.fk_facture_fourn = f.rowid";
1679 $sql .= " AND f.fk_soc = soc.rowid";
1680 $sql .= " AND soc.fk_pays = c.rowid";
1681 $sql .= " AND rib.fk_soc = f.fk_soc";
1682 $sql .= " AND rib.default_rib = 1";
1683 $sql .= " AND rib.type = 'ban'";
1684
1685 // Define $fileCrediteurSection. One section DrctDbtTxInf per invoice.
1686 $resql = $this->db->query($sql);
1687 if ($resql) {
1688 $cachearraytotestduplicate = array();
1689
1690 $num = $this->db->num_rows($resql);
1691 while ($i < $num) {
1692 $obj = $this->db->fetch_object($resql);
1693
1694 if (!empty($cachearraytotestduplicate[$obj->idfac])) {
1695 $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
1696 $this->invoice_in_error[$obj->idfac] = $this->error;
1697 $result = -2;
1698 break;
1699 }
1700 $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
1701
1702 $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
1703
1704 $fileCrediteurSection .= $this->EnregDestinataireSEPA($obj->code, $obj->nom, $obj->address, $obj->zip, $obj->town, $obj->country_code, $obj->cb, $obj->cg, $obj->cc, $obj->somme, $obj->reffac, $obj->idfac, $obj->iban, $obj->bic, $daterum, $obj->drum, $obj->rum, $type, $obj->fac_ref_supplier);
1705
1706 $this->total = $this->total + $obj->somme;
1707 $i++;
1708 }
1709 $nbtotalDrctDbtTxInf = $i;
1710 } else {
1711 $this->error = $this->db->lasterror();
1712 fputs($this->file, 'ERROR CREDITOR '.$sql.$CrLf); // CREDITORS = Suppliers
1713 $result = -2;
1714 }
1715
1716 // Define $fileEmetteurSection. Start of bloc PmtInf. Will contains all $nbtotalDrctDbtTxInf
1717 if ($result != -2) {
1718 $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type);
1719 }
1720
1724 // SEPA File Header
1725 fputs($this->file, '<'.'?xml version="1.0" encoding="UTF-8" standalone="yes"?'.'>'.$CrLf);
1726 fputs($this->file, '<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'.$CrLf);
1727 fputs($this->file, ' <CstmrCdtTrfInitn>'.$CrLf);
1728 // SEPA Group header
1729 fputs($this->file, ' <GrpHdr>'.$CrLf);
1730 fputs($this->file, ' <MsgId>'.('TRF/'.$dateTime_YMD.'/REF'.$this->id).'</MsgId>'.$CrLf);
1731 fputs($this->file, ' <CreDtTm>'.$dateTime_ECMA.'</CreDtTm>'.$CrLf);
1732 fputs($this->file, ' <NbOfTxs>'.$i.'</NbOfTxs>'.$CrLf);
1733 fputs($this->file, ' <CtrlSum>'.$this->total.'</CtrlSum>'.$CrLf);
1734 fputs($this->file, ' <InitgPty>'.$CrLf);
1735 fputs($this->file, ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf);
1736 fputs($this->file, ' <Id>'.$CrLf);
1737 fputs($this->file, ' <PrvtId>'.$CrLf);
1738 fputs($this->file, ' <Othr>'.$CrLf);
1739 fputs($this->file, ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf);
1740 fputs($this->file, ' </Othr>'.$CrLf);
1741 fputs($this->file, ' </PrvtId>'.$CrLf);
1742 fputs($this->file, ' </Id>'.$CrLf);
1743 fputs($this->file, ' </InitgPty>'.$CrLf);
1744 fputs($this->file, ' </GrpHdr>'.$CrLf);
1745 // SEPA File Emetteur (mycompany)
1746 if ($result != -2) {
1747 fputs($this-> file, $fileEmetteurSection);
1748 }
1749 // SEPA File Creditors
1750 if ($result != -2) {
1751 fputs($this-> file, $fileCrediteurSection);
1752 }
1753 // SEPA FILE FOOTER
1754 fputs($this->file, ' </PmtInf>'.$CrLf);
1755 fputs($this->file, ' </CstmrCdtTrfInitn>'.$CrLf);
1756 fputs($this->file, '</Document>'.$CrLf);
1757 }
1758 }
1759
1760 // Build file for Other Countries with unknow format
1761 if (!$found) {
1762 if ($type != 'bank-transfer') {
1763 $sql = "SELECT pl.amount";
1764 $sql .= " FROM";
1765 $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,";
1766 $sql .= " ".MAIN_DB_PREFIX."facture as f,";
1767 $sql .= " ".MAIN_DB_PREFIX."prelevement as pf";
1768 $sql .= " WHERE pl.fk_prelevement_bons = ".((int) $this->id);
1769 $sql .= " AND pl.rowid = pf.fk_prelevement_lignes";
1770 $sql .= " AND pf.fk_facture = f.rowid";
1771
1772 // Lines
1773 $i = 0;
1774 $resql = $this->db->query($sql);
1775 if ($resql) {
1776 $num = $this->db->num_rows($resql);
1777
1778 while ($i < $num) {
1779 $obj = $this->db->fetch_object($resql);
1780 $this->total = $this->total + $obj->amount;
1781
1782 // TODO Write record into file
1783 $i++;
1784 }
1785 } else {
1786 $result = -2;
1787 }
1788 } else {
1789 $sql = "SELECT pl.amount";
1790 $sql .= " FROM";
1791 $sql .= " ".MAIN_DB_PREFIX."prelevement_lignes as pl,";
1792 $sql .= " ".MAIN_DB_PREFIX."facture_fourn as f,";
1793 $sql .= " ".MAIN_DB_PREFIX."prelevement as pf";
1794 $sql .= " WHERE pl.fk_prelevement_bons = ".((int) $this->id);
1795 $sql .= " AND pl.rowid = pf.fk_prelevement_lignes";
1796 $sql .= " AND pf.fk_facture_fourn = f.rowid";
1797
1798 // Lines
1799 $i = 0;
1800 $resql = $this->db->query($sql);
1801 if ($resql) {
1802 $num = $this->db->num_rows($resql);
1803
1804 while ($i < $num) {
1805 $obj = $this->db->fetch_object($resql);
1806 $this->total = $this->total + $obj->amount;
1807
1808 // TODO Write record into file
1809 $i++;
1810 }
1811 } else {
1812 $result = -2;
1813 }
1814 }
1815
1816 $langs->load('withdrawals');
1817
1818 // TODO Add here code to generate a generic file
1819 fputs($this->file, $langs->transnoentitiesnoconv('WithdrawalFileNotCapable', $mysoc->country_code));
1820 }
1821
1822 fclose($this->file);
1823 dolChmod($this->filename);
1824
1825 return $result;
1826 }
1827
1828
1837 public static function buildRumNumber($row_code_client, $row_datec, $row_drum)
1838 {
1839 global $langs;
1840
1841 $pre = substr(dol_string_nospecial(dol_string_unaccent($langs->transnoentitiesnoconv('RUM'))), 0, 3); // Must always be on 3 char ('RUM' or 'UMR'. This is a protection against bad translation)
1842
1843 // 3 char + '-' + 12 + '-' + id + '-' + code Must be lower than 32.
1844 return $pre.'-'.dol_print_date($row_datec, 'dayhourlogsmall').'-'.dol_trunc($row_drum.($row_code_client ? '-'.$row_code_client : ''), 13, 'right', 'UTF-8', 1);
1845 }
1846
1847
1848 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1865 public function EnregDestinataire($rowid, $client_nom, $rib_banque, $rib_guichet, $rib_number, $amount, $ref, $facid, $rib_dom = '', $type = 'direct-debit')
1866 {
1867 // phpcs:enable
1868 fputs($this->file, "06");
1869 fputs($this->file, "08"); // Prelevement ordinaire
1870
1871 fputs($this->file, " "); // Zone Reservee B2
1872
1873 fputs($this->file, $this->emetteur_ics); // ICS
1874
1875 // Date d'echeance C1
1876
1877 fputs($this->file, " ");
1878 fputs($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
1879 fputs($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
1880
1881 // Raison Sociale Destinataire C2
1882
1883 fputs($this->file, substr(strtoupper($client_nom)." ", 0, 24));
1884
1885 // Domiciliation facultative D1
1886 $domiciliation = strtr($rib_dom, array(" " => "-", CHR(13) => " ", CHR(10) => ""));
1887 fputs($this->file, substr($domiciliation." ", 0, 24));
1888
1889 // Zone Reservee D2
1890
1891 fputs($this->file, substr(" ", 0, 8));
1892
1893 // Code Guichet D3
1894
1895 fputs($this->file, $rib_guichet);
1896
1897 // Numero de compte D4
1898
1899 fputs($this->file, substr("000000000000000".$rib_number, -11));
1900
1901 // Zone E Montant
1902
1903 $montant = (round($amount, 2) * 100);
1904
1905 fputs($this->file, substr("000000000000000".$montant, -16));
1906
1907 // Label F
1908
1909 fputs($this->file, substr("*_".$ref."_RDVnet".$rowid." ", 0, 31));
1910
1911 // Code etablissement G1
1912
1913 fputs($this->file, $rib_banque);
1914
1915 // Zone Reservee G2
1916
1917 fputs($this->file, substr(" ", 0, 5));
1918
1919 fputs($this->file, "\n");
1920 }
1921
1922 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1948 public function EnregDestinataireSEPA($row_code_client, $row_nom, $row_address, $row_zip, $row_town, $row_country_code, $row_cb, $row_cg, $row_cc, $row_somme, $row_ref, $row_idfac, $row_iban, $row_bic, $row_datec, $row_drum, $row_rum, $type = 'direct-debit', $row_comment = '')
1949 {
1950 // phpcs:enable
1951 global $conf;
1952
1953 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
1954
1955 $CrLf = "\n";
1956 $Rowing = sprintf("%010d", $row_idfac);
1957
1958 // Define value for RUM
1959 // Example: RUM-CustomerCode-CustomerBankAccountId-01424448606 (note: Date is the timestamp of the date of creation of CustomerBankAccountId)
1960 $Rum = (empty($row_rum) ? $this->buildRumNumber($row_code_client, $row_datec, $row_drum) : $row_rum);
1961
1962 // Define date of RUM signature
1963 $DtOfSgntr = dol_print_date($row_datec, '%Y-%m-%d');
1964
1965 if ($type != 'bank-transfer') {
1966 // SEPA Paiement Information of buyer for Direct Debit
1967 $XML_DEBITOR = '';
1968 $XML_DEBITOR .= ' <DrctDbtTxInf>'.$CrLf;
1969 $XML_DEBITOR .= ' <PmtId>'.$CrLf;
1970 // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
1971 $XML_DEBITOR .= ' <EndToEndId>'.(($conf->global->PRELEVEMENT_END_TO_END != "") ? $conf->global->PRELEVEMENT_END_TO_END : ('DD-'.dol_trunc($row_idfac.'-'.$row_ref, 20, 'right', 'UTF-8', 1)).'-'.$Rowing).'</EndToEndId>'.$CrLf; // ISO20022 states that EndToEndId has a MaxLength of 35 characters
1972 $XML_DEBITOR .= ' </PmtId>'.$CrLf;
1973 $XML_DEBITOR .= ' <InstdAmt Ccy="EUR">'.round($row_somme, 2).'</InstdAmt>'.$CrLf;
1974 $XML_DEBITOR .= ' <DrctDbtTx>'.$CrLf;
1975 $XML_DEBITOR .= ' <MndtRltdInf>'.$CrLf;
1976 $XML_DEBITOR .= ' <MndtId>'.$Rum.'</MndtId>'.$CrLf;
1977 $XML_DEBITOR .= ' <DtOfSgntr>'.$DtOfSgntr.'</DtOfSgntr>'.$CrLf;
1978 $XML_DEBITOR .= ' <AmdmntInd>false</AmdmntInd>'.$CrLf;
1979 $XML_DEBITOR .= ' </MndtRltdInf>'.$CrLf;
1980 $XML_DEBITOR .= ' </DrctDbtTx>'.$CrLf;
1981 $XML_DEBITOR .= ' <DbtrAgt>'.$CrLf;
1982 $XML_DEBITOR .= ' <FinInstnId>'.$CrLf;
1983 $XML_DEBITOR .= ' <BIC>'.$row_bic.'</BIC>'.$CrLf;
1984 $XML_DEBITOR .= ' </FinInstnId>'.$CrLf;
1985 $XML_DEBITOR .= ' </DbtrAgt>'.$CrLf;
1986 $XML_DEBITOR .= ' <Dbtr>'.$CrLf;
1987 $XML_DEBITOR .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))).'</Nm>'.$CrLf;
1988 $XML_DEBITOR .= ' <PstlAdr>'.$CrLf;
1989 $XML_DEBITOR .= ' <Ctry>'.$row_country_code.'</Ctry>'.$CrLf;
1990 $addressline1 = strtr($row_address, array(CHR(13) => ", ", CHR(10) => ""));
1991 $addressline2 = strtr($row_zip.(($row_zip && $row_town) ? ' ' : (string) $row_town), array(CHR(13) => ", ", CHR(10) => ""));
1992 if (trim($addressline1)) {
1993 $XML_DEBITOR .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
1994 }
1995 if (trim($addressline2)) {
1996 $XML_DEBITOR .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
1997 }
1998 $XML_DEBITOR .= ' </PstlAdr>'.$CrLf;
1999 $XML_DEBITOR .= ' </Dbtr>'.$CrLf;
2000 $XML_DEBITOR .= ' <DbtrAcct>'.$CrLf;
2001 $XML_DEBITOR .= ' <Id>'.$CrLf;
2002 $XML_DEBITOR .= ' <IBAN>'.preg_replace('/\s/', '', $row_iban).'</IBAN>'.$CrLf;
2003 $XML_DEBITOR .= ' </Id>'.$CrLf;
2004 $XML_DEBITOR .= ' </DbtrAcct>'.$CrLf;
2005 $XML_DEBITOR .= ' <RmtInf>'.$CrLf;
2006 // A string with some information on payment - 140 max
2007 $XML_DEBITOR .= ' <Ustrd>'.getDolGlobalString('PRELEVEMENT_USTRD', dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($row_ref.($row_comment ? ' - '.$row_comment : '')), '', '', '', 1), 135, 'right', 'UTF-8', 1))).'</Ustrd>'.$CrLf; // Free unstuctured data - 140 max
2008 $XML_DEBITOR .= ' </RmtInf>'.$CrLf;
2009 $XML_DEBITOR .= ' </DrctDbtTxInf>'.$CrLf;
2010 return $XML_DEBITOR;
2011 } else {
2012 // SEPA Paiement Information of seller for Credit Transfer
2013 $XML_CREDITOR = '';
2014 $XML_CREDITOR .= ' <CdtTrfTxInf>'.$CrLf;
2015 $XML_CREDITOR .= ' <PmtId>'.$CrLf;
2016 // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
2017 $XML_CREDITOR .= ' <EndToEndId>'.(($conf->global->PRELEVEMENT_END_TO_END != "") ? $conf->global->PRELEVEMENT_END_TO_END : ('CT-'.dol_trunc($row_idfac.'-'.$row_ref, 20, 'right', 'UTF-8', 1)).'-'.$Rowing).'</EndToEndId>'.$CrLf; // ISO20022 states that EndToEndId has a MaxLength of 35 characters
2018 $XML_CREDITOR .= ' </PmtId>'.$CrLf;
2019 if (!empty($this->sepa_xml_pti_in_ctti)) {
2020 $XML_CREDITOR .= ' <PmtTpInf>' . $CrLf;
2021
2022 // Can be 'NORM' for normal or 'HIGH' for high priority level
2023 if (!empty($conf->global->PAYMENTBYBANKTRANSFER_FORCE_HIGH_PRIORITY)) {
2024 $instrprty = 'HIGH';
2025 } else {
2026 $instrprty = 'NORM';
2027 }
2028 $XML_CREDITOR .= ' <InstrPrty>'.$instrprty.'</InstrPrty>' . $CrLf;
2029 $XML_CREDITOR .= ' <SvcLvl>' . $CrLf;
2030 $XML_CREDITOR .= ' <Cd>SEPA</Cd>' . $CrLf;
2031 $XML_CREDITOR .= ' </SvcLvl>' . $CrLf;
2032 $XML_CREDITOR .= ' <CtgyPurp>' . $CrLf;
2033 $XML_CREDITOR .= ' <Cd>CORE</Cd>' . $CrLf;
2034 $XML_CREDITOR .= ' </CtgyPurp>' . $CrLf;
2035 $XML_CREDITOR .= ' </PmtTpInf>' . $CrLf;
2036 }
2037 $XML_CREDITOR .= ' <Amt>'.$CrLf;
2038 $XML_CREDITOR .= ' <InstdAmt Ccy="EUR">'.round($row_somme, 2).'</InstdAmt>'.$CrLf;
2039 $XML_CREDITOR .= ' </Amt>'.$CrLf;
2040 /*
2041 $XML_CREDITOR .= ' <DrctDbtTx>'.$CrLf;
2042 $XML_CREDITOR .= ' <MndtRltdInf>'.$CrLf;
2043 $XML_CREDITOR .= ' <MndtId>'.$Rum.'</MndtId>'.$CrLf;
2044 $XML_CREDITOR .= ' <DtOfSgntr>'.$DtOfSgntr.'</DtOfSgntr>'.$CrLf;
2045 $XML_CREDITOR .= ' <AmdmntInd>false</AmdmntInd>'.$CrLf;
2046 $XML_CREDITOR .= ' </MndtRltdInf>'.$CrLf;
2047 $XML_CREDITOR .= ' </DrctDbtTx>'.$CrLf;
2048 */
2049 //$XML_CREDITOR .= ' <ChrgBr>SLEV</ChrgBr>'.$CrLf;
2050 $XML_CREDITOR .= ' <CdtrAgt>'.$CrLf;
2051 $XML_CREDITOR .= ' <FinInstnId>'.$CrLf;
2052 $XML_CREDITOR .= ' <BIC>'.$row_bic.'</BIC>'.$CrLf;
2053 $XML_CREDITOR .= ' </FinInstnId>'.$CrLf;
2054 $XML_CREDITOR .= ' </CdtrAgt>'.$CrLf;
2055 $XML_CREDITOR .= ' <Cdtr>'.$CrLf;
2056 $XML_CREDITOR .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))).'</Nm>'.$CrLf;
2057 $XML_CREDITOR .= ' <PstlAdr>'.$CrLf;
2058 $XML_CREDITOR .= ' <Ctry>'.$row_country_code.'</Ctry>'.$CrLf;
2059 $addressline1 = strtr($row_address, array(CHR(13) => ", ", CHR(10) => ""));
2060 $addressline2 = strtr($row_zip.(($row_zip && $row_town) ? ' ' : (string) $row_town), array(CHR(13) => ", ", CHR(10) => ""));
2061 if (trim($addressline1)) {
2062 $XML_CREDITOR .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2063 }
2064 if (trim($addressline2)) {
2065 $XML_CREDITOR .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2066 }
2067 $XML_CREDITOR .= ' </PstlAdr>'.$CrLf;
2068 $XML_CREDITOR .= ' </Cdtr>'.$CrLf;
2069 $XML_CREDITOR .= ' <CdtrAcct>'.$CrLf;
2070 $XML_CREDITOR .= ' <Id>'.$CrLf;
2071 $XML_CREDITOR .= ' <IBAN>'.preg_replace('/\s/', '', $row_iban).'</IBAN>'.$CrLf;
2072 $XML_CREDITOR .= ' </Id>'.$CrLf;
2073 $XML_CREDITOR .= ' </CdtrAcct>'.$CrLf;
2074 $XML_CREDITOR .= ' <RmtInf>'.$CrLf;
2075 // A string with some information on payment - 140 max
2076 $XML_CREDITOR .= ' <Ustrd>'.getDolGlobalString('CREDITTRANSFER_USTRD', dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($row_ref.($row_comment ? ' - '.$row_comment : '')), '', '', '', 1), 135, 'right', 'UTF-8', 1))).'</Ustrd>'.$CrLf; // Free unstructured data - 140 max
2077 $XML_CREDITOR .= ' </RmtInf>'.$CrLf;
2078 $XML_CREDITOR .= ' </CdtTrfTxInf>'.$CrLf;
2079 return $XML_CREDITOR;
2080 }
2081 }
2082
2083
2084 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2092 public function EnregEmetteur($type = 'direct-debit')
2093 {
2094 // phpcs:enable
2095 fputs($this->file, "03");
2096 fputs($this->file, "08"); // Prelevement ordinaire
2097
2098 fputs($this->file, " "); // Zone Reservee B2
2099
2100 fputs($this->file, $this->emetteur_ics); // ICS
2101
2102 // Date d'echeance C1
2103
2104 fputs($this->file, " ");
2105 fputs($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
2106 fputs($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
2107
2108 // Raison Sociale C2
2109
2110 fputs($this->file, substr($this->raison_sociale." ", 0, 24));
2111
2112 // Reference de la remise creancier D1 sur 7 caracteres
2113
2114 fputs($this->file, substr($this->reference_remise." ", 0, 7));
2115
2116 // Zone Reservee D1-2
2117
2118 fputs($this->file, substr(" ", 0, 17));
2119
2120 // Zone Reservee D2
2121
2122 fputs($this->file, substr(" ", 0, 2));
2123 fputs($this->file, "E");
2124 fputs($this->file, substr(" ", 0, 5));
2125
2126 // Code Guichet D3
2127
2128 fputs($this->file, $this->emetteur_code_guichet);
2129
2130 // Numero de compte D4
2131
2132 fputs($this->file, substr("000000000000000".$this->emetteur_numero_compte, -11));
2133
2134 // Zone Reservee E
2135
2136 fputs($this->file, substr(" ", 0, 16));
2137
2138 // Zone Reservee F
2139
2140 fputs($this->file, substr(" ", 0, 31));
2141
2142 // Code etablissement
2143
2144 fputs($this->file, $this->emetteur_code_banque);
2145
2146 // Zone Reservee G
2147
2148 fputs($this->file, substr(" ", 0, 5));
2149
2150 fputs($this->file, "\n");
2151 }
2152
2153 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2169 public function EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf = '\n', $format = 'FRST', $type = 'direct-debit', $fk_bank_account = 0)
2170 {
2171 // phpcs:enable
2172 // SEPA INITIALISATION
2173 global $conf;
2174
2175 // Clean parameters
2176 $dateTime_YMD = dol_print_date($ladate, '%Y%m%d');
2177 $dateTime_ETAD = dol_print_date($ladate, '%Y-%m-%d');
2178 $dateTime_YMDHMS = dol_print_date($ladate, '%Y-%m-%dT%H:%M:%S');
2179
2180 // Clean params
2181 if (empty($fk_bank_account)) {
2182 $fk_bank_account = ($type == 'bank-transfer' ? $conf->global->PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT : $conf->global->PRELEVEMENT_ID_BANKACCOUNT);
2183 }
2184
2185 // Get data of bank account
2186 $account = new Account($this->db);
2187 if ($account->fetch($fk_bank_account) > 0) {
2188 $this->emetteur_code_banque = $account->code_banque;
2189 $this->emetteur_code_guichet = $account->code_guichet;
2190 $this->emetteur_numero_compte = $account->number;
2191 $this->emetteur_number_key = $account->cle_rib;
2192 $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
2193 $this->emetteur_iban = $account->iban;
2194 $this->emetteur_bic = $account->bic;
2195
2196 $this->emetteur_ics = ($type == 'bank-transfer' ? $account->ics_transfer : $account->ics); // Ex: PRELEVEMENT_ICS = "FR78ZZZ123456";
2197
2198 $this->raison_sociale = $account->proprio;
2199 }
2200
2201 // Get pending payments
2202 $sql = "SELECT rowid, ref";
2203 $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons as pb";
2204 $sql .= " WHERE pb.rowid = ".((int) $this->id);
2205
2206 $resql = $this->db->query($sql);
2207 if ($resql) {
2208 $obj = $this->db->fetch_object($resql);
2209
2210 $country = explode(':', $configuration->global->MAIN_INFO_SOCIETE_COUNTRY);
2211 $IdBon = sprintf("%05d", $obj->rowid);
2212 $RefBon = $obj->ref;
2213
2214 if ($type != 'bank-transfer') {
2215 // SEPA Paiement Information of my company for Direct Debit
2216 $XML_SEPA_INFO = '';
2217 $XML_SEPA_INFO .= ' <PmtInf>'.$CrLf;
2218 $XML_SEPA_INFO .= ' <PmtInfId>'.('DD/'.$dateTime_YMD.'/ID'.$IdBon.'-'.$RefBon).'</PmtInfId>'.$CrLf;
2219 $XML_SEPA_INFO .= ' <PmtMtd>DD</PmtMtd>'.$CrLf;
2220 $XML_SEPA_INFO .= ' <NbOfTxs>'.$nombre.'</NbOfTxs>'.$CrLf;
2221 $XML_SEPA_INFO .= ' <CtrlSum>'.$total.'</CtrlSum>'.$CrLf;
2222 $XML_SEPA_INFO .= ' <PmtTpInf>'.$CrLf;
2223 $XML_SEPA_INFO .= ' <SvcLvl>'.$CrLf;
2224 $XML_SEPA_INFO .= ' <Cd>SEPA</Cd>'.$CrLf;
2225 $XML_SEPA_INFO .= ' </SvcLvl>'.$CrLf;
2226 $XML_SEPA_INFO .= ' <LclInstrm>'.$CrLf;
2227 $XML_SEPA_INFO .= ' <Cd>CORE</Cd>'.$CrLf;
2228 $XML_SEPA_INFO .= ' </LclInstrm>'.$CrLf;
2229 $XML_SEPA_INFO .= ' <SeqTp>'.$format.'</SeqTp>'.$CrLf;
2230 $XML_SEPA_INFO .= ' </PmtTpInf>'.$CrLf;
2231 $XML_SEPA_INFO .= ' <ReqdColltnDt>'.$dateTime_ETAD.'</ReqdColltnDt>'.$CrLf;
2232 $XML_SEPA_INFO .= ' <Cdtr>'.$CrLf;
2233 $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2234 $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2235 $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2236 $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(CHR(13) => ", ", CHR(10) => ""));
2237 $addressline2 = strtr($configuration->global->MAIN_INFO_SOCIETE_ZIP.(($configuration->global->MAIN_INFO_SOCIETE_ZIP || ' '.$configuration->global->MAIN_INFO_SOCIETE_TOWN) ? ' ' : '').$configuration->global->MAIN_INFO_SOCIETE_TOWN, array(CHR(13) => ", ", CHR(10) => ""));
2238 if ($addressline1) {
2239 $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2240 }
2241 if ($addressline2) {
2242 $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2243 }
2244 $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2245 $XML_SEPA_INFO .= ' </Cdtr>'.$CrLf;
2246 $XML_SEPA_INFO .= ' <CdtrAcct>'.$CrLf;
2247 $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2248 $XML_SEPA_INFO .= ' <IBAN>'.preg_replace('/\s/', '', $this->emetteur_iban).'</IBAN>'.$CrLf;
2249 $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2250 $XML_SEPA_INFO .= ' </CdtrAcct>'.$CrLf;
2251 $XML_SEPA_INFO .= ' <CdtrAgt>'.$CrLf;
2252 $XML_SEPA_INFO .= ' <FinInstnId>'.$CrLf;
2253 $XML_SEPA_INFO .= ' <BIC>'.$this->emetteur_bic.'</BIC>'.$CrLf;
2254 $XML_SEPA_INFO .= ' </FinInstnId>'.$CrLf;
2255 $XML_SEPA_INFO .= ' </CdtrAgt>'.$CrLf;
2256 /* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf;
2257 $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2258 $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2259 $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2260 $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ADDRESS), ' ')).'</AdrLine>'.$CrLf;
2261 $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ZIP.' '.$conf->global->MAIN_INFO_SOCIETE_TOWN), ' ')).'</AdrLine>'.$CrLf;
2262 $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2263 $XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/
2264 $XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>'.$CrLf; // Field "Responsible of fees". Must be SLEV
2265 $XML_SEPA_INFO .= ' <CdtrSchmeId>'.$CrLf;
2266 $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2267 $XML_SEPA_INFO .= ' <PrvtId>'.$CrLf;
2268 $XML_SEPA_INFO .= ' <Othr>'.$CrLf;
2269 $XML_SEPA_INFO .= ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf;
2270 $XML_SEPA_INFO .= ' <SchmeNm>'.$CrLf;
2271 $XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>'.$CrLf;
2272 $XML_SEPA_INFO .= ' </SchmeNm>'.$CrLf;
2273 $XML_SEPA_INFO .= ' </Othr>'.$CrLf;
2274 $XML_SEPA_INFO .= ' </PrvtId>'.$CrLf;
2275 $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2276 $XML_SEPA_INFO .= ' </CdtrSchmeId>'.$CrLf;
2277 } else {
2278 // SEPA Paiement Information of my company for Credit Transfer
2279 $XML_SEPA_INFO = '';
2280 $XML_SEPA_INFO .= ' <PmtInf>'.$CrLf;
2281 $XML_SEPA_INFO .= ' <PmtInfId>'.('TRF/'.$dateTime_YMD.'/ID'.$IdBon.'-'.$RefBon).'</PmtInfId>'.$CrLf;
2282 $XML_SEPA_INFO .= ' <PmtMtd>TRF</PmtMtd>'.$CrLf;
2283 //$XML_SEPA_INFO .= ' <BtchBookg>False</BtchBookg>'.$CrLf;
2284 $XML_SEPA_INFO .= ' <NbOfTxs>'.$nombre.'</NbOfTxs>'.$CrLf;
2285 $XML_SEPA_INFO .= ' <CtrlSum>'.$total.'</CtrlSum>'.$CrLf;
2286 if (!empty($this->sepa_xml_pti_in_ctti) && !empty($format)) { // @TODO Using $format (FRST ou RCUR) in a section for a Credit Transfer looks strange.
2287 $XML_SEPA_INFO .= ' <PmtTpInf>' . $CrLf;
2288 $XML_SEPA_INFO .= ' <SvcLvl>' . $CrLf;
2289 $XML_SEPA_INFO .= ' <Cd>SEPA</Cd>' . $CrLf;
2290 $XML_SEPA_INFO .= ' </SvcLvl>' . $CrLf;
2291 $XML_SEPA_INFO .= ' <LclInstrm>' . $CrLf;
2292 $XML_SEPA_INFO .= ' <Cd>CORE</Cd>' . $CrLf;
2293 $XML_SEPA_INFO .= ' </LclInstrm>' . $CrLf;
2294 $XML_SEPA_INFO .= ' <SeqTp>' . $format . '</SeqTp>' . $CrLf;
2295 $XML_SEPA_INFO .= ' </PmtTpInf>' . $CrLf;
2296 }
2297 $XML_SEPA_INFO .= ' <ReqdExctnDt>'.dol_print_date($dateTime_ETAD, 'dayrfc').'</ReqdExctnDt>'.$CrLf;
2298 $XML_SEPA_INFO .= ' <Dbtr>'.$CrLf;
2299 $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2300 $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2301 $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2302 $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(CHR(13) => ", ", CHR(10) => ""));
2303 $addressline2 = strtr($configuration->global->MAIN_INFO_SOCIETE_ZIP.(($configuration->global->MAIN_INFO_SOCIETE_ZIP || ' '.$configuration->global->MAIN_INFO_SOCIETE_TOWN) ? ' ' : '').$configuration->global->MAIN_INFO_SOCIETE_TOWN, array(CHR(13) => ", ", CHR(10) => ""));
2304 if ($addressline1) {
2305 $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2306 }
2307 if ($addressline2) {
2308 $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf;
2309 }
2310 $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2311 $XML_SEPA_INFO .= ' </Dbtr>'.$CrLf;
2312 $XML_SEPA_INFO .= ' <DbtrAcct>'.$CrLf;
2313 $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2314 $XML_SEPA_INFO .= ' <IBAN>'.preg_replace('/\s/', '', $this->emetteur_iban).'</IBAN>'.$CrLf;
2315 $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2316 $XML_SEPA_INFO .= ' </DbtrAcct>'.$CrLf;
2317 $XML_SEPA_INFO .= ' <DbtrAgt>'.$CrLf;
2318 $XML_SEPA_INFO .= ' <FinInstnId>'.$CrLf;
2319 $XML_SEPA_INFO .= ' <BIC>'.$this->emetteur_bic.'</BIC>'.$CrLf;
2320 $XML_SEPA_INFO .= ' </FinInstnId>'.$CrLf;
2321 $XML_SEPA_INFO .= ' </DbtrAgt>'.$CrLf;
2322 /* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf;
2323 $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2324 $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2325 $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2326 $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ADDRESS), ' ')).'</AdrLine>'.$CrLf;
2327 $XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ZIP.' '.$conf->global->MAIN_INFO_SOCIETE_TOWN), ' ')).'</AdrLine>'.$CrLf;
2328 $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2329 $XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/
2330 $XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>'.$CrLf; // Field "Responsible of fees". Must be SLEV
2331 /*$XML_SEPA_INFO .= ' <CdtrSchmeId>'.$CrLf;
2332 $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2333 $XML_SEPA_INFO .= ' <PrvtId>'.$CrLf;
2334 $XML_SEPA_INFO .= ' <Othr>'.$CrLf;
2335 $XML_SEPA_INFO .= ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf;
2336 $XML_SEPA_INFO .= ' <SchmeNm>'.$CrLf;
2337 $XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>'.$CrLf;
2338 $XML_SEPA_INFO .= ' </SchmeNm>'.$CrLf;
2339 $XML_SEPA_INFO .= ' </Othr>'.$CrLf;
2340 $XML_SEPA_INFO .= ' </PrvtId>'.$CrLf;
2341 $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2342 $XML_SEPA_INFO .= ' </CdtrSchmeId>'.$CrLf;*/
2343 }
2344 } else {
2345 fputs($this->file, 'INCORRECT EMETTEUR '.$this->raison_sociale.$CrLf);
2346 $XML_SEPA_INFO = '';
2347 }
2348 return $XML_SEPA_INFO;
2349 }
2350
2351 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2358 public function EnregTotal($total)
2359 {
2360 // phpcs:enable
2361 fputs($this->file, "08");
2362 fputs($this->file, "08"); // Prelevement ordinaire
2363
2364 fputs($this->file, " "); // Zone Reservee B2
2365
2366 fputs($this->file, $this->emetteur_ics); // ICS
2367
2368 // Reserve C1
2369
2370 fputs($this->file, substr(" ", 0, 12));
2371
2372
2373 // Raison Sociale C2
2374
2375 fputs($this->file, substr(" ", 0, 24));
2376
2377 // D1
2378
2379 fputs($this->file, substr(" ", 0, 24));
2380
2381 // Zone Reservee D2
2382
2383 fputs($this->file, substr(" ", 0, 8));
2384
2385 // Code Guichet D3
2386
2387 fputs($this->file, substr(" ", 0, 5));
2388
2389 // Numero de compte D4
2390
2391 fputs($this->file, substr(" ", 0, 11));
2392
2393 // Zone E Montant
2394
2395 $montant = ($total * 100);
2396
2397 fputs($this->file, substr("000000000000000".$montant, -16));
2398
2399 // Zone Reservee F
2400
2401 fputs($this->file, substr(" ", 0, 31));
2402
2403 // Code etablissement
2404
2405 fputs($this->file, substr(" ", 0, 5));
2406
2407 // Zone Reservee F
2408
2409 fputs($this->file, substr(" ", 0, 5));
2410
2411 fputs($this->file, "\n");
2412 }
2413
2420 public function getLibStatut($mode = 0)
2421 {
2422 return $this->LibStatut($this->statut, $mode);
2423 }
2424
2425 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2433 public function LibStatut($status, $mode = 0)
2434 {
2435 // phpcs:enable
2436 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
2437 global $langs;
2438 //$langs->load("mymodule");
2439 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2440 $this->labelStatus[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2441 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2442 $this->labelStatusShort[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2443 if ($this->type == 'bank-transfer') {
2444 $this->labelStatus[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2445 $this->labelStatusShort[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2446 } else {
2447 $this->labelStatus[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2448 $this->labelStatusShort[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2449 }
2450 }
2451
2452 $statusType = 'status1';
2453 if ($status == self::STATUS_TRANSFERED) {
2454 $statusType = 'status3';
2455 }
2456 if ($status == self::STATUS_CREDITED || $status == self::STATUS_DEBITED) {
2457 $statusType = 'status6';
2458 }
2459
2460 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
2461 }
2462
2463 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2471 public function load_board($user, $mode)
2472 {
2473 // phpcs:enable
2474 global $conf, $langs;
2475
2476 if ($user->socid) {
2477 return -1; // protection pour eviter appel par utilisateur externe
2478 }
2479
2480 /*
2481 if ($mode == 'direct_debit') {
2482 $sql = "SELECT b.rowid, f.datedue as datefin";
2483 $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
2484 $sql .= " WHERE f.entity IN (".getEntity('facture').")";
2485 $sql .= " AND f.total_ttc > 0";
2486 } else {
2487 $sql = "SELECT b.rowid, f.datedue as datefin";
2488 $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
2489 $sql .= " WHERE f.entity IN (".getEntity('facture_fourn').")";
2490 $sql .= " AND f.total_ttc > 0";
2491 }
2492
2493 $resql = $this->db->query($sql);
2494 if ($resql) {
2495 $langs->load("banks");
2496 $now = dol_now();
2497
2498 $response = new WorkboardResponse();
2499 if ($mode == 'direct_debit') {
2500 $response->warning_delay = $conf->prelevement->warning_delay / 60 / 60 / 24;
2501 $response->label = $langs->trans("PendingDirectDebitToComplete");
2502 $response->labelShort = $langs->trans("PendingDirectDebitToCompleteShort");
2503 $response->url = DOL_URL_ROOT.'/compta/prelevement/index.php?leftmenu=checks&mainmenu=bank';
2504 } else {
2505 $response->warning_delay = $conf->paymentbybanktransfer->warning_delay / 60 / 60 / 24;
2506 $response->label = $langs->trans("PendingCreditTransferToComplete");
2507 $response->labelShort = $langs->trans("PendingCreditTransferToCompleteShort");
2508 $response->url = DOL_URL_ROOT.'/compta/paymentbybanktransfer/index.php?leftmenu=checks&mainmenu=bank';
2509 }
2510 $response->img = img_object('', "payment");
2511
2512 while ($obj = $this->db->fetch_object($resql)) {
2513 $response->nbtodo++;
2514
2515 if ($this->db->jdate($obj->datefin) < ($now - $conf->withdraw->warning_delay)) {
2516 $response->nbtodolate++;
2517 }
2518 }
2519
2520 $response->nbtodo = 0;
2521 $response->nbtodolate = 0;
2522 // Return workboard only if quantity is not 0
2523 if ($response->nbtodo) {
2524 return $response;
2525 } else {
2526 return 0;
2527 }
2528 } else {
2529 dol_print_error($this->db);
2530 $this->error = $this->db->error();
2531 return -1;
2532 }
2533 */
2534 return 0;
2535 }
2536
2544 public function getKanbanView($option = '', $arraydata = null)
2545 {
2546 global $langs;
2547
2548 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2549
2550 $return = '<div class="box-flex-item box-flex-grow-zero">';
2551 $return .= '<div class="info-box info-box-sm">';
2552 $return .= '<span class="info-box-icon bg-infobox-action">';
2553 $return .= img_picto('', $this->picto);
2554 $return .= '</span>';
2555 $return .= '<div class="info-box-content">';
2556 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).'</span>';
2557 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
2558
2559 if (property_exists($this, 'date_echeance')) {
2560 $return .= '<br><span class="opacitymedium">'.$langs->trans("Date").'</span> : <span class="info-box-label">'.dol_print_date($this->db->jdate($this->date_echeance), 'day').'</span>';
2561 }
2562 if (property_exists($this, 'total')) {
2563 $return .= '<br><span class="opacitymedium">'.$langs->trans("Amount").'</span> : <span class="amount">'.price($this->total).'</span>';
2564 }
2565 if (method_exists($this, 'LibStatut')) {
2566 $return .= '<br><div class="info-box-status margintoponly">'.$this->getLibStatut(3).'</div>';
2567 }
2568 $return .= '</div>';
2569 $return .= '</div>';
2570 $return .= '</div>';
2571 return $return;
2572 }
2573}
$object ref
Definition info.php:78
Class to manage bank accounts.
Class to manage withdrawal receipts.
load_board($user, $mode)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
static buildRumNumber($row_code_client, $row_datec, $row_drum)
Generate dynamically a RUM number for a customer bank account.
SommeAPrelever($mode='direct-debit')
Returns amount waiting for direct debit payment or credit transfer payment.
EnregEmetteur($type='direct-debit')
Write sender of request (me).
update(User $user, $notrigger=false)
Update object into database.
EnregTotal($total)
Write end.
fetch($rowid, $ref='')
Get object and lines from database.
create($banque=0, $agence=0, $mode='real', $format='ALL', $executiondate='', $notrigger=0, $type='direct-debit', $did=0, $fk_bank_account=0)
Create a BAN payment order:
generate($format='ALL', $executiondate=0, $type='direct-debit', $fk_bank_account=0)
Generate a direct debit or credit transfer file.
deleteNotificationById($rowid)
Delete a notification def by id.
addline(&$line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key)
Add line to withdrawal.
__construct($db)
Constructor.
EnregDestinataire($rowid, $client_nom, $rib_banque, $rib_guichet, $rib_number, $amount, $ref, $facid, $rib_dom='', $type='direct-debit')
Write recipient of request (customer)
NbFactureAPrelever($type='direct-debit')
Get number of invoices to pay.
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.
set_infotrans($user, $date, $method)
Set withdrawal to transmited 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)
Set direct debit or credit transfer order to "paid" status.
nbOfInvoiceToPay($mode='direct-debit')
Get number of invoices waiting for payment.
AddFacture($invoice_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $type='debit-order')
Add invoice to withdrawal.
getLibStatut($mode=0)
Return status label of object.
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)
getListInvoices($amounts=0)
Get invoice list.
addNotification($db, $user, $action)
Add a notification.
deleteNotification($user, $action)
Delete a notification.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
updateCommon(User $user, $notrigger=false)
Update object into database.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Class to manage bank accounts description of third parties.
Class to manage suppliers invoices.
Class to manage invoices.
Class to manage payments for supplier invoices.
Class to manage payments of customer invoices.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage Dolibarr users.
print $langs trans("Ref").' m m m statut
Definition index.php:152
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
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.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dolChmod($filepath, $newmask='')
Change mod of a file.
dol_now($mode='auto')
Return date for now.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_string_unaccent($str)
Clean a string from all accent characters to be used as ref, login or by dol_sanitizeFileName.
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:120