dolibarr 21.0.0-beta
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
32require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php';
33require_once DOL_DOCUMENT_ROOT . '/core/lib/bank.lib.php';
34require_once DOL_DOCUMENT_ROOT . '/compta/bank/class/account.class.php';
35require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
36require_once DOL_DOCUMENT_ROOT . '/compta/paiement/class/paiement.class.php';
37require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.facture.class.php';
38require_once DOL_DOCUMENT_ROOT . '/fourn/class/paiementfourn.class.php';
39require_once DOL_DOCUMENT_ROOT . '/salaries/class/salary.class.php';
40require_once DOL_DOCUMENT_ROOT . '/salaries/class/paymentsalary.class.php';
41require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
42require_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
68 public $date_echeance;
72 public $raison_sociale;
76 public $reference_remise;
80 public $emetteur_code_guichet;
84 public $emetteur_numero_compte;
88 public $emetteur_code_banque;
92 public $emetteur_number_key;
96 public $sepa_xml_pti_in_ctti;
97
101 public $emetteur_iban;
105 public $emetteur_bic;
109 public $emetteur_ics;
110
114 public $user_trans;
118 public $user_credit;
119
123 public $total;
127 public $fetched;
128 public $labelStatus = array();
129
130 public $factures = array();
131
135 public $methodes_trans = array();
136
137 public $invoice_in_error = array();
138 public $thirdparty_in_error = array();
139
143 public $file;
144
148 public $filename;
149
150 const STATUS_DRAFT = 0;
151 const STATUS_TRANSFERED = 1;
152 const STATUS_CREDITED = 2; // STATUS_CREDITED and STATUS_DEBITED is same. Difference is in ->type
153 const STATUS_DEBITED = 2; // STATUS_CREDITED and STATUS_DEBITED is same. Difference is in ->type
154
155
195 // BEGIN MODULEBUILDER PROPERTIES
199 public $fields = array(
200 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 10, 'notnull' => 1, 'visible' => 0,),
201 'ref' => array('type' => 'varchar(12)', 'label' => 'Ref', 'enabled' => 1, 'position' => 15, 'notnull' => 0, 'visible' => -1, 'csslist' => 'tdoverflowmax150', 'showoncombobox' => 1,),
202 'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 25, 'notnull' => 0, 'visible' => -1,),
203 'amount' => array('type' => 'double(24,8)', 'label' => 'Amount', 'enabled' => 1, 'position' => 30, 'notnull' => 0, 'visible' => -1,),
204 'statut' => array('type' => 'smallint(6)', 'label' => 'Statut', 'enabled' => 1, 'position' => 500, 'notnull' => 0, 'visible' => -1, 'arrayofkeyval' => array(0 => 'Wait', 1 => 'Transfered', 2 => 'Credited')),
205 'credite' => array('type' => 'smallint(6)', 'label' => 'Credite', 'enabled' => 1, 'position' => 40, 'notnull' => 0, 'visible' => -1,),
206 'note' => array('type' => 'text', 'label' => 'Note', 'enabled' => 1, 'position' => 45, 'notnull' => 0, 'visible' => -1,),
207 'date_trans' => array('type' => 'datetime', 'label' => 'Datetrans', 'enabled' => 1, 'position' => 50, 'notnull' => 0, 'visible' => -1,),
208 'method_trans' => array('type' => 'smallint(6)', 'label' => 'Methodtrans', 'enabled' => 1, 'position' => 55, 'notnull' => 0, 'visible' => -1,),
209 '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',),
210 'date_credit' => array('type' => 'datetime', 'label' => 'Datecredit', 'enabled' => 1, 'position' => 65, 'notnull' => 0, 'visible' => -1,),
211 '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',),
212 'type' => array('type' => 'varchar(16)', 'label' => 'Type', 'enabled' => 1, 'position' => 75, 'notnull' => 0, 'visible' => -1,),
213 'fk_bank_account' => array('type' => 'integer', 'label' => 'Fkbankaccount', 'enabled' => 1, 'position' => 80, 'notnull' => 0, 'visible' => -1, 'css' => 'maxwidth500 widthcentpercentminusxx',),
214 );
218 public $rowid;
222 public $ref;
226 public $datec;
230 public $amount;
231
236 public $statut;
240 public $status;
241
245 public $credite;
249 public $note;
253 public $date_trans;
257 public $method_trans;
261 public $fk_user_trans;
265 public $date_credit;
269 public $fk_user_credit;
273 public $type;
277 public $fk_bank_account;
278 // END MODULEBUILDER PROPERTIES
279
280
281
287 public function __construct($db)
288 {
289 $this->db = $db;
290
291 $this->filename = '';
292
293 $this->date_echeance = dol_now();
294 $this->raison_sociale = "";
295 $this->reference_remise = "";
296
297 $this->emetteur_code_guichet = "";
298 $this->emetteur_numero_compte = "";
299 $this->emetteur_code_banque = "";
300 $this->emetteur_number_key = "";
301 $this->sepa_xml_pti_in_ctti = false;
302
303 $this->emetteur_iban = "";
304 $this->emetteur_bic = "";
305 $this->emetteur_ics = "";
306
307 $this->factures = array();
308
309 $this->methodes_trans = array(0 => 'Internet', 2 => 'Email', 3 => 'Api');
310
311 $this->fetched = 0;
312 }
313
314 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
330 public function AddFacture($invoice_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $type = 'debit-order', $sourcetype = '')
331 {
332 // phpcs:enable
333 $result = 0;
334 $line_id = 0;
335
336 // Add lines into prelevement_lignes
337 $result = $this->addline($line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $sourcetype);
338
339
340 if ($result == 0) {
341 if ($line_id > 0) {
342 $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement (";
343 if ($type != 'bank-transfer') {
344 $sql .= "fk_facture";
345 } else {
346 if ($sourcetype == 'salary') {
347 $sql .= "fk_salary";
348 } else {
349 $sql .= "fk_facture_fourn";
350 }
351 }
352 $sql .= ",fk_prelevement_lignes";
353 $sql .= ") VALUES (";
354 $sql .= ((int) $invoice_id);
355 $sql .= ", " . ((int) $line_id);
356 $sql .= ")";
357
358 if ($this->db->query($sql)) {
359 $result = 0;
360 } else {
361 $result = -1;
362 $this->errors[] = get_class($this) . "::AddFacture " . $this->db->lasterror;
363 dol_syslog(get_class($this) . "::AddFacture Error $result");
364 }
365 } else {
366 $result = -2;
367 $this->errors[] = get_class($this) . "::AddFacture linedid Empty";
368 dol_syslog(get_class($this) . "::AddFacture Error $result");
369 }
370 } else {
371 $result = -3;
372 dol_syslog(get_class($this) . "::AddFacture Error $result");
373 }
374
375 return $result;
376 }
377
392 public function addline(&$line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $sourcetype = '')
393 {
394 $result = -1;
395 $concat = 0; // ??? what is this for. Seems not used.
396
397 if ($concat == 1) {
398 /*
399 * We aggregate the lines
400 */
401 $sql = "SELECT rowid";
402 $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_lignes";
403 $sql .= " WHERE fk_prelevement_bons = " . ((int) $this->id);
404 if ($sourcetype == 'salary') {
405 $sql .= " AND fk_soc = " . ((int) $client_id);
406 } else {
407 $sql .= " AND fk_user = " . ((int) $client_id);
408 }
409 $sql .= " AND code_banque = '" . $this->db->escape($code_banque) . "'";
410 $sql .= " AND code_guichet = '" . $this->db->escape($code_guichet) . "'";
411 $sql .= " AND number = '" . $this->db->escape($number) . "'";
412
413 $resql = $this->db->query($sql);
414 if ($resql) {
415 $num = $this->db->num_rows($resql);
416 } else {
417 $result = -1;
418 }
419 } else {
420 /*
421 * No aggregate
422 */
423 $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_lignes (";
424 $sql .= "fk_prelevement_bons";
425 $sql .= ", fk_soc";
426 $sql .= ", client_nom";
427 $sql .= ", amount";
428 $sql .= ", code_banque";
429 $sql .= ", code_guichet";
430 $sql .= ", number";
431 $sql .= ", cle_rib";
432 $sql .= ($sourcetype == 'salary' ? ", fk_user" : "");
433 $sql .= ") VALUES (";
434 $sql .= $this->id;
435 $sql .= ", " . (($sourcetype != 'salary') ? ((int) $client_id) : "0"); // fk_soc can't be null
436 $sql .= ", '" . $this->db->escape($client_nom) . "'";
437 $sql .= ", " . ((float) price2num($amount));
438 $sql .= ", '" . $this->db->escape($code_banque) . "'";
439 $sql .= ", '" . $this->db->escape($code_guichet) . "'";
440 $sql .= ", '" . $this->db->escape($number) . "'";
441 $sql .= ", '" . $this->db->escape($number_key) . "'";
442 $sql .= (($sourcetype == 'salary') ? ", " . ((int) $client_id) : '');
443 $sql .= ")";
444 if ($this->db->query($sql)) {
445 $line_id = $this->db->last_insert_id(MAIN_DB_PREFIX . "prelevement_lignes");
446 $result = 0;
447 } else {
448 $this->errors[] = get_class($this) . "::addline Error -2 " . $this->db->lasterror;
449 dol_syslog(get_class($this) . "::addline Error -2");
450 $result = -2;
451 }
452 }
453
454 return $result;
455 }
456
463 public function getErrorString($error)
464 {
465 global $langs;
466
467 $errors = array();
468
469 $errors[1027] = $langs->trans("DateInvalid");
470
471 return $errors[abs($error)];
472 }
473
481 public function fetch($rowid, $ref = '')
482 {
483 $sql = "SELECT p.rowid, p.ref, p.amount, p.note";
484 $sql .= ", p.datec as dc";
485 $sql .= ", p.date_trans as date_trans";
486 $sql .= ", p.method_trans, p.fk_user_trans";
487 $sql .= ", p.date_credit as date_credit";
488 $sql .= ", p.fk_user_credit";
489 $sql .= ", p.type";
490 $sql .= ", p.fk_bank_account";
491 $sql .= ", p.statut as status";
492 $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons as p";
493 $sql .= " WHERE p.entity IN (" . getEntity('invoice') . ")";
494 if ($rowid > 0) {
495 $sql .= " AND p.rowid = " . ((int) $rowid);
496 } else {
497 $sql .= " AND p.ref = '" . $this->db->escape($ref) . "'";
498 }
499
500 dol_syslog(get_class($this) . "::fetch", LOG_DEBUG);
501 $result = $this->db->query($sql);
502 if ($result) {
503 if ($this->db->num_rows($result)) {
504 $obj = $this->db->fetch_object($result);
505
506 $this->id = $obj->rowid;
507 $this->ref = $obj->ref;
508 $this->amount = $obj->amount;
509 $this->note = $obj->note;
510 $this->datec = $this->db->jdate($obj->dc);
511
512 $this->date_trans = $this->db->jdate($obj->date_trans);
513 $this->method_trans = $obj->method_trans;
514 $this->user_trans = $obj->fk_user_trans;
515
516 $this->date_credit = $this->db->jdate($obj->date_credit);
517 $this->user_credit = $obj->fk_user_credit;
518
519 $this->type = $obj->type;
520 $this->fk_bank_account = $obj->fk_bank_account;
521
522 $this->status = $obj->status;
523 if (empty($this->status)) { // Value is sometimes null in database
524 $this->status = 0;
525 }
526 $this->statut = $this->status; // For backward compatibility
527
528 $this->fetched = 1;
529
530 return 1;
531 } else {
532 dol_syslog(get_class($this) . "::Fetch no record found");
533 return 0;
534 }
535 } else {
536 return -1;
537 }
538 }
539
547 public function update(User $user, $notrigger = 0)
548 {
549 return $this->updateCommon($user, $notrigger);
550 }
551
552 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
562 public function set_infocredit($user, $date, $type = '')
563 {
564 // phpcs:enable
565 global $conf, $langs;
566
567 $error = 0;
568
569 if ($this->fetched == 1) {
570 if ($date < $this->date_trans) {
571 $langs->load("errors");
572 $this->error = $langs->trans('ErrorDateOfMovementLowerThanDateOfFileTransmission');
573 dol_syslog("bon-prelevment::set_infocredit 1027 " . $this->error);
574 return -1027;
575 }
576
577 $this->db->begin();
578
579 $sql = " UPDATE " . MAIN_DB_PREFIX . "prelevement_bons";
580 $sql .= " SET fk_user_credit = " . ((int) $user->id);
581 $sql .= ", statut = " . self::STATUS_CREDITED;
582 $sql .= ", date_credit = '" . $this->db->idate($date) . "'";
583 $sql .= " WHERE rowid = " . ((int) $this->id);
584 $sql .= " AND entity = " . ((int) $conf->entity);
585 $sql .= " AND statut = " . self::STATUS_TRANSFERED;
586
587 $resql = $this->db->query($sql);
588 if ($resql) {
589 $langs->load('withdrawals');
590 $subject = $langs->trans("InfoCreditSubject", $this->ref);
591 $message = $langs->trans("InfoCreditMessage", $this->ref, dol_print_date($date, 'dayhour'));
592
593 // Add payment of withdrawal into bank
594 $fk_bank_account = $this->fk_bank_account;
595 if (empty($fk_bank_account)) {
596 $fk_bank_account = ($this->type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
597 }
598
599 $amounts = array();
600 $amountsperthirdparty = array();
601
602 $facs = $this->getListInvoices(1, $type);
603 if ($this->error) {
604 $error++;
605 }
606
607 // Loop on each invoice or salary.
608 // $facs should be array(0=>id, 1=>amount requested)
609 $num = count($facs);
610 for ($i = 0; $i < $num; $i++) {
611 if ($this->type == 'bank-transfer') {
612 if ($type == 'salary') {
613 $fac = new Salary($this->db);
614 } else {
615 $fac = new FactureFournisseur($this->db);
616 }
617 } else {
618 $fac = new Facture($this->db);
619 }
620
621 $result = $fac->fetch($facs[$i][0]);
622
623 $amounts[$fac->id] = $facs[$i][1];
624 if ($this->type == 'bank-transfer') {
625 if ($type == 'salary') {
626 $amountsperthirdparty[$fac->fk_user][$fac->id] = $facs[$i][1];
627 } else {
628 $amountsperthirdparty[$fac->socid][$fac->id] = $facs[$i][1];
629 }
630 } else {
631 $amountsperthirdparty[$fac->socid][$fac->id] = $facs[$i][1];
632 }
633
634 $totalpaid = $fac->getSommePaiement();
635 $totalcreditnotes = 0;
636 if (method_exists($fac, 'getSumCreditNotesUsed')) {
637 $totalcreditnotes = $fac->getSumCreditNotesUsed();
638 }
639 $totaldeposits = 0;
640 if (method_exists($fac, 'getSumDepositsUsed')) {
641 $totaldeposits = $fac->getSumDepositsUsed();
642 }
643 $alreadypayed = $totalpaid + $totalcreditnotes + $totaldeposits;
644
645 // Set the main document to pay with status Paid.
646 // @TODO Move this after creation of payments done after
647 $amountofdocument = $fac->total_ttc;
648 if ($type == 'salary') {
649 $amountofdocument = $fac->amount;
650 }
651 if (price2num($alreadypayed + $facs[$i][1], 'MT') == price2num($amountofdocument, 'MT')) {
652 $result = $fac->setPaid($user);
653 if ($result < 0) {
654 $this->error = $fac->error;
655 $this->errors = $fac->errors;
656 }
657 }
658 }
659
660 // Make one payment per customer or employee
661 foreach ($amountsperthirdparty as $thirdpartyid => $cursoramounts) {
662 if ($this->type == 'bank-transfer') {
663 if ($type == 'salary') {
664 $paiement = new PaymentSalary($this->db);
665 } else {
666 $paiement = new PaiementFourn($this->db);
667 }
668 } else {
669 $paiement = new Paiement($this->db);
670 }
671 $paiement->datepaye = $date;
672 $paiement->amounts = $cursoramounts; // Array with detail of dispatching of payments for each invoice
673
674 if ($this->type == 'bank-transfer') {
675 if ($type == 'salary') {
676 $paiement->datep = $date;
677
678 $paiement->paiementid = 2;
679 $paiement->fk_typepayment = 2;
680 $paiement->paiementcode = 'VIR';
681 } else {
682 $paiement->paiementid = 2;
683 $paiement->paiementcode = 'VIR';
684 }
685 } else {
686 $paiement->paiementid = 3;
687 $paiement->paiementcode = 'PRE';
688 }
689
690 $paiement->num_payment = $this->ref; // Set ref of direct debit note
691 $paiement->id_prelevement = $this->id;
692
693 $result = $paiement->create($user); // This use ->paiementid, that is ID of payment mode
694
695 if ($result < 0) {
696 $error++;
697 $this->error = $paiement->error;
698 $this->errors = $paiement->errors;
699 dol_syslog(get_class($this) . "::set_infocredit AddPayment Error " . $this->error);
700 } else {
701 if ($this->type == 'bank-transfer') {
702 if ($type == 'salary') {
703 $modeforaddpayment = 'payment_salary';
704 $labelforaddpayment = '(SalaryPayment)';
705 $addbankurl = 'credit-transfer';
706 } else {
707 $modeforaddpayment = 'payment_supplier';
708 $labelforaddpayment = '(SupplierInvoicePayment)';
709 $addbankurl = 'credit-transfer';
710 }
711 } else {
712 $modeforaddpayment = 'payment';
713 $labelforaddpayment = '(CustomerInvoicePayment)';
714 $addbankurl = 'direct-debit'; // = 'directdebit'
715 }
716
717
718 if ($paiement instanceof PaymentSalary) {
719 // Only 6 arguments for PaymentSalary
720 $result = $paiement->addPaymentToBank($user, $modeforaddpayment, $labelforaddpayment, $fk_bank_account, '', '');
721 } else {
722 $result = $paiement->addPaymentToBank($user, $modeforaddpayment, $labelforaddpayment, $fk_bank_account, '', '', 0, '', $addbankurl);
723 }
724
725 if ($result < 0) {
726 $error++;
727 $this->error = $paiement->error;
728 $this->errors = $paiement->errors;
729 dol_syslog(get_class($this) . "::set_infocredit AddPaymentToBank Error " . $this->error);
730 }
731 }
732 }
733
734 // Update withdrawal line
735 // TODO: Translate to ligneprelevement.class.php
736 if (!$error) {
737 $sql = " UPDATE " . MAIN_DB_PREFIX . "prelevement_lignes";
738 $sql .= " SET statut = 2";
739 $sql .= " WHERE fk_prelevement_bons = " . ((int) $this->id);
740
741 if (!$this->db->query($sql)) {
742 dol_syslog(get_class($this) . "::set_infocredit Update lines Error");
743 $error++;
744 }
745 }
746 } else {
747 $this->error = $this->db->lasterror();
748 dol_syslog(get_class($this) . "::set_infocredit Update Bons Error");
749 $error++;
750 }
751
752 // End of procedure
753 if ($error == 0) {
754 $this->date_credit = $date; // date credit or debit
755 $this->statut = self::STATUS_CREDITED;
756 $this->status = self::STATUS_CREDITED;
757
758 $this->db->commit();
759 return 0;
760 } else {
761 $this->db->rollback();
762 return -1;
763 }
764 } else {
765 return -1026;
766 }
767 }
768
769 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
778 public function set_infotrans($user, $date, $method)
779 {
780 // phpcs:enable
781 global $conf, $langs;
782
783 $error = 0;
784
785 dol_syslog(get_class($this) . "::set_infotrans Start", LOG_INFO);
786
787 if ($this->db->begin()) {
788 $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_bons ";
789 $sql .= " SET fk_user_trans = " . $user->id;
790 $sql .= " , date_trans = '" . $this->db->idate($date) . "'";
791 $sql .= " , method_trans = " . ((int) $method);
792 $sql .= " , statut = " . self::STATUS_TRANSFERED;
793 $sql .= " WHERE rowid = " . ((int) $this->id);
794 $sql .= " AND entity = " . ((int) $conf->entity);
795 $sql .= " AND statut = " . self::STATUS_DRAFT;
796
797 if ($this->db->query($sql)) {
798 $this->method_trans = $method;
799 $langs->load('withdrawals');
800 $subject = $langs->trans("InfoTransSubject", $this->ref);
801 $message = $langs->trans("InfoTransMessage", $this->ref, dolGetFirstLastname($user->firstname, $user->lastname));
802 $message .= $langs->trans("InfoTransData", price($this->amount), $this->methodes_trans[$this->method_trans], dol_print_date($date, 'day'));
803
804 // TODO Call trigger to create a notification using notification module
805 } else {
806 $error++;
807 }
808
809 if ($error == 0) {
810 $this->date_trans = $date;
811 $this->statut = self::STATUS_TRANSFERED;
812 $this->status = self::STATUS_TRANSFERED;
813 $this->user_trans = $user->id;
814
815 $this->db->commit();
816
817 return 0;
818 } else {
819 $this->db->rollback();
820 dol_syslog(get_class($this) . "::set_infotrans ROLLBACK", LOG_ERR);
821
822 return -1;
823 }
824 } else {
825 dol_syslog(get_class($this) . "::set_infotrans Ouverture transaction SQL impossible", LOG_CRIT);
826 return -2;
827 }
828 }
829
838 private function getListInvoices($amounts = 0, $type = '')
839 {
840 global $conf;
841
842 $arr = array();
843
844 dol_syslog(get_class($this) . "::getListInvoices");
845
846 // Returns all invoices presented within same order
847 $sql = "SELECT ";
848 if ($this->type == 'bank-transfer') {
849 if ($type == 'salary') {
850 $sql .= " p.fk_salary";
851 } else {
852 $sql .= " p.fk_facture_fourn";
853 }
854 } else {
855 $sql .= " p.fk_facture";
856 }
857 if ($amounts) {
858 $sql .= ", SUM(pl.amount)";
859 }
860 $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons as pb,";
861 $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
862 $sql .= " " . MAIN_DB_PREFIX . "prelevement as p";
863 $sql .= " WHERE p.fk_prelevement_lignes = pl.rowid";
864 $sql .= " AND pl.fk_prelevement_bons = pb.rowid";
865 $sql .= " AND pb.rowid = " . ((int) $this->id);
866 $sql .= " AND pb.entity = " . ((int) $conf->entity);
867 if ($amounts) {
868 if ($this->type == 'bank-transfer') {
869 if ($type == 'salary') {
870 $sql .= " GROUP BY p.fk_salary";
871 } else {
872 $sql .= " GROUP BY p.fk_facture_fourn";
873 }
874 } else {
875 $sql .= " GROUP BY p.fk_facture";
876 }
877 }
878
879 $resql = $this->db->query($sql);
880 if ($resql) {
881 $num = $this->db->num_rows($resql);
882
883 if ($num) {
884 $i = 0;
885 while ($i < $num) {
886 $row = $this->db->fetch_row($resql);
887 if (!$amounts) {
888 $arr[$i] = $row[0];
889 } else {
890 $arr[$i] = array(
891 $row[0],
892 $row[1]
893 );
894 }
895 $i++;
896 }
897 }
898 $this->db->free($resql);
899 } else {
900 $this->error = $this->db->lasterror();
901 }
902
903 return $arr;
904 }
905
906 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
914 public function SommeAPrelever($mode = 'direct-debit', $type = '')
915 {
916 // phpcs:enable
917 $sql = "SELECT sum(pd.amount) as nb";
918 if ($type !== 'salary') {
919 if ($mode != 'bank-transfer') {
920 $sql .= " FROM " . MAIN_DB_PREFIX . "facture as f,";
921 } else {
922 $sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f,";
923 }
924 } else {
925 $sql .= " FROM " . MAIN_DB_PREFIX . "salary as s,";
926 }
927 $sql .= " " . MAIN_DB_PREFIX . "prelevement_demande as pd";
928 $sql .= ($type !== 'salary' ? " WHERE f.entity IN (" . getEntity('invoice') . ")" : " WHERE s.entity IN (" . getEntity('salary') . ")");
929 if (!getDolGlobalString('WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS')) {
930 $sql .= ($type !== 'salary' ? " AND f.fk_statut = " . Facture::STATUS_VALIDATED : " AND s.paye = " . Salary::STATUS_UNPAID);
931 }
932 if ($type !== 'salary') {
933 if ($mode != 'bank-transfer') {
934 $sql .= " AND f.rowid = pd.fk_facture";
935 } else {
936 $sql .= " AND f.rowid = pd.fk_facture_fourn";
937 }
938 } else {
939 $sql .= " AND s.rowid = pd.fk_salary";
940 }
941 $sql .= ($type !== 'salary' ? " AND f.paye = 0" : "");
942 $sql .= " AND pd.traite = 0";
943 $sql .= " AND pd.ext_payment_id IS NULL";
944 $sql .= ($type !== 'salary' ? " AND f.total_ttc > 0" : "");
945
946 $resql = $this->db->query($sql);
947 if ($resql) {
948 $obj = $this->db->fetch_object($resql);
949
950 $this->db->free($resql);
951
952 return $obj->nb;
953 } else {
954 $error = 1;
955 dol_syslog(get_class($this) . "::SommeAPrelever Erreur -1");
956 dol_syslog($this->db->error());
957
958 return -1;
959 }
960 }
961
969 public function nbOfInvoiceToPay($mode = 'direct-debit', $type = '')
970 {
971 if ($type === 'salary') {
972 return $this->NbFactureAPrelever($mode, 1);
973 } else {
974 return $this->NbFactureAPrelever($mode);
975 }
976 }
977
978 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
986 public function NbFactureAPrelever($type = 'direct-debit', $forsalary = 0)
987 {
988 // phpcs:enable
989 if ($forsalary == 1) {
990 $sql = "SELECT count(s.rowid) as nb";
991 $sql .= " FROM " . MAIN_DB_PREFIX . "salary as s";
992 } else {
993 $sql = "SELECT count(f.rowid) as nb";
994
995 if ($type == 'bank-transfer') {
996 $sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
997 } else {
998 $sql .= " FROM " . MAIN_DB_PREFIX . "facture as f";
999 }
1000 }
1001 $sql .= ", " . MAIN_DB_PREFIX . "prelevement_demande as pd";
1002 if ($forsalary == 1) {
1003 $sql .= " WHERE s.entity IN (" . getEntity('invoice') . ")";
1004 if (!getDolGlobalString('WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS')) {
1005 $sql .= " AND s.paye = 0";
1006 }
1007 } else {
1008 $sql .= " WHERE f.entity IN (" . getEntity('invoice') . ")";
1009 if (!getDolGlobalString('WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS')) {
1010 $sql .= " AND f.fk_statut = " . Facture::STATUS_VALIDATED;
1011 }
1012 }
1013 if ($forsalary == 1) {
1014 $sql .= " AND s.rowid = pd.fk_salary";
1015 } else {
1016 if ($type == 'bank-transfer') {
1017 $sql .= " AND f.rowid = pd.fk_facture_fourn";
1018 } else {
1019 $sql .= " AND f.rowid = pd.fk_facture";
1020 }
1021 }
1022 $sql .= " AND pd.traite = 0";
1023 $sql .= " AND pd.ext_payment_id IS NULL";
1024 if (!$forsalary == 1) {
1025 $sql .= " AND f.total_ttc > 0";
1026 } else {
1027 $sql .= " AND s.paye = 0";
1028 }
1029
1030 dol_syslog(get_class($this) . "::NbFactureAPrelever");
1031 $resql = $this->db->query($sql);
1032
1033 if ($resql) {
1034 $obj = $this->db->fetch_object($resql);
1035 $this->db->free($resql);
1036
1037 return $obj->nb;
1038 } else {
1039 $this->error = get_class($this) . "::NbFactureAPrelever Erreur -1 sql=" . $this->db->error();
1040 return -1;
1041 }
1042 }
1043
1044
1045 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1066 public function create($banque = 0, $agence = 0, $mode = 'real', $format = 'ALL', $executiondate = 0, $notrigger = 0, $type = 'direct-debit', $did = 0, $fk_bank_account = 0, $sourcetype = 'invoice')
1067 {
1068 // phpcs:enable
1069 global $conf, $langs, $user;
1070
1071 dol_syslog(__METHOD__ . " Bank=".$banque." Office=".$agence." mode=".$mode." format=".$format." type=".$type." did=".$did." fk_bank_account=".$fk_bank_account." sourcetype=".$sourcetype, LOG_DEBUG);
1072
1073 require_once DOL_DOCUMENT_ROOT . "/compta/facture/class/facture.class.php";
1074 require_once DOL_DOCUMENT_ROOT . "/societe/class/societe.class.php";
1075
1076 // Check params
1077 if ($type != 'bank-transfer') {
1078 if (empty($format)) {
1079 $this->error = 'ErrorBadParametersForDirectDebitFileCreate';
1080 return -1;
1081 }
1082 }
1083
1084 // Clean params
1085 if (empty($fk_bank_account)) {
1086 $fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
1087 }
1088
1089 $error = 0;
1090 // Pre-store some values into variables to simplify following sql requests
1091 if ($sourcetype != 'salary') {
1092 $entities = $type != 'bank-transfer' ? getEntity('invoice') : getEntity('supplier_invoice');
1093 $socOrUser = 'fk_soc';
1094 $societeOrUser = 'societe';
1095 } else {
1096 $entities = getEntity('salary');
1097 $sqlTable = 'salary';
1098 $socOrUser = 'fk_user';
1099 $societeOrUser = 'user';
1100 }
1101
1102 $sqlTable = $type != 'bank-transfer' ? "facture" : "facture_fourn";
1103
1104 $thirdpartyBANId = 0;
1105
1106 // Check if there is an iban associated to the bank transfer request or if we take the default
1107 if ($did > 0) {
1108 $sql = "SELECT pd.fk_societe_rib";
1109 $sql .= " FROM " . $this->db->prefix() . "prelevement_demande as pd";
1110 $sql .= " WHERE pd.rowid = ".((int) $did);
1111
1112 $resql = $this->db->query($sql);
1113
1114 if (!$resql) {
1115 $this->error = $this->db->lasterror();
1116 dol_syslog(__METHOD__ . " Read fk_societe_rib error " . $this->db->lasterror(), LOG_ERR);
1117 return -1;
1118 }
1119
1120 $obj = $this->db->fetch_object($resql);
1121 if ($obj) {
1122 $thirdpartyBANId = $obj->fk_societe_rib;
1123
1124 dol_syslog(__METHOD__ . " Found an BAN ID to use: ".$thirdpartyBANId);
1125 }
1126
1127 $this->db->free($resql);
1128 }
1129
1130 $datetimeprev = dol_now('gmt');
1131 // Choice of the date of the execution direct debit
1132 if (!empty($executiondate)) {
1133 $datetimeprev = $executiondate;
1134 }
1135
1136 $month = dol_print_date($datetimeprev, "%m", 'gmt');
1137 $year = dol_print_date($datetimeprev, "%Y", 'gmt');
1138
1139 $this->invoice_in_error = array();
1140 $this->thirdparty_in_error = array();
1141
1142 // Read invoices
1143 $factures = array();
1144 $factures_prev = array();
1145 $factures_result = array();
1146 $factures_prev_id = array();
1147 $factures_errors = array();
1148
1149 if (!$error) {
1150 dol_syslog(__METHOD__ . " Read invoices for did=" . ((int) $did), LOG_DEBUG);
1151
1152 $sql = "SELECT f.rowid, pd.rowid as pfdrowid";
1153 $sql .= ", f.".$this->db->sanitize($socOrUser); // fk_soc or fk_user
1154 $sql .= ", pd.code_banque, pd.code_guichet, pd.number, pd.cle_rib";
1155 $sql .= ", pd.amount";
1156 if ($sourcetype != 'salary') {
1157 $sql .= ", s.nom as name";
1158 $sql .= ", f.ref, sr.bic, sr.iban_prefix, sr.frstrecur";
1159 } else {
1160 $sql .= ", CONCAT(s.firstname,' ',s.lastname) as name";
1161 $sql .= ", f.ref, sr.bic, sr.iban_prefix, 'FRST' as frstrecur";
1162 }
1163 $sql .= " FROM " . $this->db->prefix() . $sqlTable . " as f";
1164 $sql .= " LEFT JOIN " . $this->db->prefix() . "prelevement_demande as pd ON f.rowid = pd.fk_".$this->db->sanitize($sqlTable);
1165 $sql .= " LEFT JOIN " . $this->db->prefix() . $this->db->sanitize($societeOrUser)." as s ON s.rowid = f.".$this->db->sanitize($socOrUser);
1166 $sql .= " LEFT JOIN " . $this->db->prefix() . $this->db->sanitize($societeOrUser."_rib")." as sr ON s.rowid = sr.".$this->db->sanitize($socOrUser);
1167 if ($sourcetype != 'salary') {
1168 if (!empty($thirdpartyBANId)) {
1169 $sql .= " AND sr.rowid = " . ((int) $thirdpartyBANId);
1170 } else {
1171 $sql .= " AND sr.default_rib = 1";
1172 }
1173 // TODO Add 'AND sr.default_rib = 1' in sourcetype salary too Note: the column has been created in v21 in llx_user_rib and default to 0
1174 // If we add a test on sr.default_rib = 1, we must also check we have a correct error management to stop if no default BAN is found.
1175 }
1176 $sql .= " WHERE f.entity IN (".$this->db->escape($entities).')';
1177 if ($sourcetype != 'salary') {
1178 $sql .= " AND f.fk_statut = 1"; // Invoice validated
1179 $sql .= " AND f.paye = 0";
1180 $sql .= " AND f.total_ttc > 0";
1181 } else {
1182 //$sql .= " AND f.fk_statut = 1"; // Invoice validated
1183 $sql .= " AND f.paye = 0";
1184 $sql .= " AND f.amount > 0";
1185 }
1186 $sql .= " AND pd.traite = 0";
1187 $sql .= " AND pd.ext_payment_id IS NULL";
1188 if ($sourcetype != 'salary') {
1189 $sql .= " AND sr.type = 'ban'"; // TODO Add AND sr.type = 'ban' for users too
1190 }
1191 if ($did > 0) {
1192 $sql .= " AND pd.rowid = " . ((int) $did);
1193 }
1194
1195 $resql = $this->db->query($sql);
1196 if ($resql) {
1197 $num = $this->db->num_rows($resql);
1198 $i = 0;
1199
1200 while ($i < $num) {
1201 $row = $this->db->fetch_row($resql); // TODO Replace with fetch_object()
1202 '@phan-var-force array<int<0,12>,string> $row';
1203
1204 // All fields: 0=rowid, 1=pfdrowid, 2=$socOrUser, 3=code_banque, 4=code_guichet, 5=number, 6=key, 7=amount, 8=name, 9=ref, 10=bic, 11=iban, 12=frstrecur
1205 $factures[$i] = $row;
1206
1207 // Decode BAN
1208 $factures[$i][11] = dolDecrypt($factures[$i][11]);
1209
1210 if ($row[7] == 0) {
1211 $error++;
1212 dol_syslog(__METHOD__ . " Read invoices/salary error Found a null amount", LOG_ERR);
1213 $this->invoice_in_error[$row[0]] = "Error for invoice or salary id " . $row[0] . ", found a null amount";
1214 break;
1215 }
1216 $i++;
1217 }
1218
1219 $this->db->free($resql);
1220 dol_syslog(__METHOD__ . " Read invoices/salary, " . $i . " invoices/salary to withdraw", LOG_DEBUG);
1221 } else {
1222 $this->error = $this->db->lasterror();
1223 dol_syslog(__METHOD__ . " Read invoices/salary error " . $this->db->lasterror(), LOG_ERR);
1224 return -1;
1225 }
1226 }
1227
1228 if (!$error) {
1229 // Make some checks
1230 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
1231 require_once DOL_DOCUMENT_ROOT . '/user/class/user.class.php';
1232 require_once DOL_DOCUMENT_ROOT . '/societe/class/companybankaccount.class.php';
1233 require_once DOL_DOCUMENT_ROOT . '/core/lib/bank.lib.php';
1234
1235 $tmpsoc = new Societe($this->db);
1236 $tmpuser = new User($this->db);
1237
1238 // Check BAN
1239 $i = 0;
1240 dol_syslog(__METHOD__ . " Check BAN for each invoices or salary", LOG_DEBUG);
1241
1242 if (count($factures) > 0) {
1243 foreach ($factures as $key => $fac) {
1244 // Check if $fac[8] s.nom is null
1245 if ($fac[8] != null) {
1246 if ($type != 'bank-transfer') {
1247 if ($format == 'FRST' && $fac[12] != 'FRST') {
1248 continue;
1249 }
1250 if ($format == 'RCUR' && $fac[12] != 'RCUR') {
1251 continue;
1252 }
1253 }
1254
1255 $verif = checkSwiftForAccount(null, $fac[10]);
1256 if ($verif || (empty($fac[10]) && getDolGlobalInt("WITHDRAWAL_WITHOUT_BIC"))) {
1257 dol_syslog(__METHOD__." now call checkIbanForAccount(null, ".$fac[11].")");
1258 $verif = checkIbanForAccount(null, $fac[11]);
1259 }
1260
1261 if ($verif) {
1262 $factures_prev[$i] = $fac;
1263 /* second array necessary for BonPrelevement */
1264 $factures_prev_id[$i] = $fac[0];
1265 $i++;
1266 //dol_syslog(__METHOD__."::RIB is ok", LOG_DEBUG);
1267 } else {
1268 if ($type != 'bank-transfer') {
1269 $tmpsoc->id = (int) $fac[2];
1270 $tmpsoc->name = $fac[8];
1271 $invoice_url = "<a href='" . DOL_URL_ROOT . '/compta/facture/card.php?facid=' . $fac[0] . "'>" . $fac[9] . "</a>";
1272 $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1273 $this->thirdparty_in_error[$tmpsoc->id] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1274 $error++;
1275 }
1276 if ($type == 'bank-transfer' && $sourcetype != 'salary') {
1277 $tmpsoc->id = (int) $fac[2];
1278 $tmpsoc->name = $fac[8];
1279 $invoice_url = "<a href='" . DOL_URL_ROOT . '/fourn/facture/card.php?facid=' . $fac[0] . "'>" . $fac[9] . "</a>";
1280 $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1281 $this->thirdparty_in_error[$tmpsoc->id] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1282 $error++;
1283 }
1284 if ($type == 'bank-transfer' && $sourcetype == 'salary') {
1285 $tmpuser->id = (int) $fac[2];
1286 $tmpuser->firstname = $fac[8];
1287 $salary_url = "<a href='" . DOL_URL_ROOT . '/salaries/card.php?id=' . $fac[0] . "'>" . $fac[0] . "</a>";
1288 $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for salary " . $salary_url . " for employee " . $tmpuser->getNomUrl(0);
1289 $this->thirdparty_in_error[$tmpuser->id] = "Error on default bank number IBAN/BIC for salary " . $salary_url . " for employee " . $tmpuser->getNomUrl(0);
1290 $error++;
1291 }
1292 dol_syslog(__METHOD__ . " Check BAN Error on default bank number IBAN/BIC reported by verif(): " . implode(', ', $fac), LOG_WARNING);
1293 }
1294 } else {
1295 dol_syslog(__METHOD__ . " Check BAN Failed to read company", LOG_WARNING);
1296 }
1297 /*
1298 } else {
1299 dol_syslog(__METHOD__." Check BAN Failed to read invoice", LOG_WARNING);
1300 }
1301 */
1302 }
1303 } else {
1304 dol_syslog(__METHOD__ . " Check BAN No invoice to process", LOG_WARNING);
1305 }
1306 }
1307
1308 $ok = 0;
1309
1310 // Withdraw invoices in factures_prev array
1311 $out = count($factures_prev) . " invoices or salaries will be included.";
1312 //print $out."\n";
1313 dol_syslog($out);
1314
1315 // Return warning
1316 /*$i=0;
1317 foreach ($this->thirdparty_in_error as $key => $val)
1318 {
1319 if ($i < 10) setEventMessages($val, null, 'warnings');
1320 else setEventMessages('More error were discarded...', null, 'warnings');
1321 $i++;
1322 }*/
1323
1324 if (count($factures_prev) > 0) {
1325 if ($mode == 'real') {
1326 $ok = 1;
1327 } else {
1328 print $langs->trans("ModeWarning"); // "Option for real mode was not set, we stop after this simulation\n";
1329 }
1330 }
1331 if ($ok) {
1332 /*
1333 * We are in real mode.
1334 * We create order and build file into disk
1335 */
1336 $this->db->begin();
1337
1338 $now = dol_now();
1339 $ref = '';
1340
1341 /*
1342 * Process order generation
1343 */
1344 if (!$error) {
1345 $ref = substr($year, -2) . $month;
1346
1347 // Get next free number for the ref of bon prelevement
1348 $sql = "SELECT substring(ref from char_length(ref) - 1)"; // To extract "YYMMXX" from "TYYMMXX"
1349 $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons";
1350 $sql .= " WHERE ref LIKE '_" . $this->db->escape($ref) . "%'";
1351 $sql .= " AND entity = " . ((int) $conf->entity);
1352 $sql .= " ORDER BY ref DESC LIMIT 1";
1353
1354 dol_syslog(get_class($this) . " get next free number", LOG_DEBUG);
1355 $resql = $this->db->query($sql);
1356
1357 if ($resql) {
1358 $row = $this->db->fetch_row($resql);
1359
1360 // Build the new ref
1361 $ref = "T" . $ref . sprintf("%02d", (intval($row[0]) + 1));
1362
1363 // $conf->abc->dir_output may be:
1364 // /home/ldestailleur/git/dolibarr_15.0/documents/abc/
1365 // or
1366 // /home/ldestailleur/git/dolibarr_15.0/documents/X/abc with X >= 2 with multicompany.
1367 if ($type != 'bank-transfer') {
1368 $dir = $conf->prelevement->dir_output . '/receipts';
1369 } else {
1370 $dir = $conf->paymentbybanktransfer->dir_output . '/receipts';
1371 }
1372 if (!is_dir($dir)) {
1373 dol_mkdir($dir);
1374 }
1375
1376 if (isModEnabled('multicompany')) {
1377 $labelentity = $conf->entity;
1378 $this->filename = $dir . '/' . $ref . '-' . $labelentity . '.xml';
1379 } else {
1380 $this->filename = $dir . '/' . $ref . '.xml';
1381 }
1382
1383 // Create withdraw order in database
1384 $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_bons (";
1385 $sql .= "ref, entity, datec, type, fk_bank_account";
1386 $sql .= ") VALUES (";
1387 $sql .= "'" . $this->db->escape($ref) . "'";
1388 $sql .= ", " . ((int) $conf->entity);
1389 $sql .= ", '" . $this->db->idate($now) . "'";
1390 $sql .= ", '" . ($type == 'bank-transfer' ? 'bank-transfer' : 'debit-order') . "'";
1391 $sql .= ", " . ((int) $fk_bank_account);
1392 $sql .= ")";
1393
1394 $resql = $this->db->query($sql);
1395
1396
1397 if ($resql) {
1398 $prev_id = $this->db->last_insert_id(MAIN_DB_PREFIX . "prelevement_bons");
1399 $this->id = $prev_id;
1400 $this->ref = $ref;
1401 } else {
1402 $error++;
1403 dol_syslog(__METHOD__ . " Create withdraw receipt " . $this->db->lasterror(), LOG_ERR);
1404 }
1405 } else {
1406 $error++;
1407 dol_syslog(__METHOD__ . " Get last withdraw receipt " . $this->db->lasterror(), LOG_ERR);
1408 }
1409 }
1410
1411 if (!$error) {
1412 dol_syslog(__METHOD__ . " Now loop on each document to insert them in llx_prelevement_demande");
1413
1414 // Add lines for the bon
1415 if (count($factures_prev) > 0) {
1416 foreach ($factures_prev as $fac) { // Add a link in database for each invoice ro salary
1417 /*
1418 * Add standing order. This add record into llx_prelevement_lignes and llx_prelevement
1419 *
1420 * $fac[0] : invoice_id
1421 * $fac[1] : ???
1422 * $fac[2] : third party id
1423 * $fac[3] : banque
1424 * $fac[4] : guichet
1425 * $fac[5] : number
1426 * $fac[6] : cle rib
1427 * $fac[7] : amount
1428 * $fac[8] : client nom
1429 * $fac[9] : Invoice ref
1430 * $fac[10] : BIC
1431 * $fac[11] : IBAN
1432 * $fac[12] : frstrcur
1433 */
1434 $ri = $this->AddFacture($fac[0], $fac[2], $fac[8], $fac[7], $fac[3], $fac[4], $fac[5], $fac[6], $type, $sourcetype);
1435
1436 if ($ri != 0) {
1437 $error++;
1438 }
1439
1440 // Update invoice requests as done
1441 $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_demande";
1442 $sql .= " SET traite = 1";
1443 $sql .= ", date_traite = '" . $this->db->idate($now) . "'";
1444 $sql .= ", fk_prelevement_bons = " . ((int) $this->id);
1445 $sql .= " WHERE rowid = " . ((int) $fac[1]);
1446
1447 $resql = $this->db->query($sql);
1448 if (!$resql) {
1449 $error++;
1450 $this->errors[] = $this->db->lasterror();
1451 dol_syslog(__METHOD__ . " Update Error=" . $this->db->lasterror(), LOG_ERR);
1452 }
1453 }
1454 }
1455 }
1456
1457 if (!$error) {
1458 /*
1459 * Create file of type='direct-debit' for direct debit order or type='bank-transfer' for credit transfer into a XML file
1460 */
1461
1462 dol_syslog(__METHOD__ . " Init direct debit or credit transfer file for " . count($factures_prev) . " invoices", LOG_DEBUG);
1463
1464 if (count($factures_prev) > 0) {
1465 $this->date_echeance = $datetimeprev;
1466 $this->reference_remise = $ref;
1467
1468 $account = new Account($this->db);
1469 if ($account->fetch($fk_bank_account) > 0) {
1470 $this->emetteur_code_banque = $account->code_banque;
1471 $this->emetteur_code_guichet = $account->code_guichet;
1472 $this->emetteur_numero_compte = $account->number;
1473 $this->emetteur_number_key = $account->cle_rib;
1474 $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
1475 $this->emetteur_iban = $account->iban;
1476 $this->emetteur_bic = $account->bic;
1477
1478 $this->emetteur_ics = (($type == 'bank-transfer' && getDolGlobalString("SEPA_USE_IDS")) ? $account->ics_transfer : $account->ics); // Example "FR78ZZZ123456"
1479
1480 $this->raison_sociale = $account->owner_name;
1481 }
1482 $this->factures = $factures_prev_id;
1483 $this->context['factures_prev'] = $factures_prev;
1484 // Generation of direct debit or credit transfer file $this->filename (May be a SEPA file for european countries)
1485 // This also set the property $this->total with amount that is included into file
1486 $userid = 0;
1487 if ($sourcetype == 'salary') {
1488 $userid = $this->context['factures_prev'][0][2];
1489 }
1490 $result = $this->generate($format, $executiondate, $type, $fk_bank_account, $userid, $thirdpartyBANId);
1491 if ($result < 0) {
1492 //var_dump($this->error);
1493 //var_dump($this->invoice_in_error);
1494 $error++;
1495 }
1496 }
1497 dol_syslog(__METHOD__ . " Bank order file has been generated under filename " . $this->filename, LOG_DEBUG);
1498 }
1499
1500
1501 /*
1502 * Update total defined after generation of file
1503 */
1504 if (!$error) {
1505 $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_bons";
1506 $sql .= " SET amount = " . price2num($this->total);
1507 $sql .= " WHERE rowid = " . ((int) $this->id);
1508 $sql .= " AND entity = " . ((int) $conf->entity);
1509 $resql = $this->db->query($sql);
1510
1511 if (!$resql) {
1512 $error++;
1513 dol_syslog(__METHOD__ . " Error update total: " . $this->db->error(), LOG_ERR);
1514 }
1515 }
1516
1517 if (!$error && !$notrigger) {
1518 $triggername = 'DIRECT_DEBIT_ORDER_CREATE';
1519 if ($type != 'bank-transfer') {
1520 $triggername = 'CREDIT_TRANSFER_ORDER_CREATE';
1521 }
1522
1523 // Call trigger
1524 $result = $this->call_trigger($triggername, $user);
1525 if ($result < 0) {
1526 $error++;
1527 }
1528 // End call triggers
1529 }
1530
1531 if (!$error) {
1532 $this->db->commit();
1533 return count($factures_prev); // The error of failed lines are into $this->invoice_in_error and $this->thirdparty_in_error
1534 } else {
1535 $this->db->rollback();
1536 return -1;
1537 }
1538 } else {
1539 return 0;
1540 }
1541 }
1542
1543
1551 public function delete($user = null, $notrigger = 0)
1552 {
1553 $this->db->begin();
1554
1555 $error = 0;
1556 $resql1 = $resql2 = $resql3 = $resql4 = 0;
1557
1558 if (!$notrigger) {
1559 $triggername = 'DIRECT_DEBIT_ORDER_DELETE';
1560 if ($this->type == 'bank-transfer') {
1561 $triggername = 'PAYMENTBYBANKTRANFER_DELETE';
1562 }
1563 // Call trigger
1564 $result = $this->call_trigger($triggername, $user);
1565 if ($result < 0) {
1566 $error++;
1567 }
1568 // End call triggers
1569 }
1570
1571 if (!$error) {
1572 $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) . ")";
1573 $resql1 = $this->db->query($sql);
1574 if (!$resql1) {
1575 dol_print_error($this->db);
1576 }
1577 }
1578
1579 if (!$error) {
1580 $sql = "DELETE FROM " . MAIN_DB_PREFIX . "prelevement_lignes WHERE fk_prelevement_bons = " . ((int) $this->id);
1581 $resql2 = $this->db->query($sql);
1582 if (!$resql2) {
1583 dol_print_error($this->db);
1584 }
1585 }
1586
1587 if (!$error) {
1588 $sql = "DELETE FROM " . MAIN_DB_PREFIX . "prelevement_bons WHERE rowid = " . ((int) $this->id);
1589 $resql3 = $this->db->query($sql);
1590 if (!$resql3) {
1591 dol_print_error($this->db);
1592 }
1593 }
1594
1595 if (!$error) {
1596 $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_demande SET fk_prelevement_bons = NULL, traite = 0 WHERE fk_prelevement_bons = " . ((int) $this->id);
1597 $resql4 = $this->db->query($sql);
1598 if (!$resql4) {
1599 dol_print_error($this->db);
1600 }
1601 }
1602
1603 if ($resql1 && $resql2 && $resql3 && $resql4 && !$error) {
1604 $this->db->commit();
1605 return 1;
1606 } else {
1607 $this->db->rollback();
1608 return -1;
1609 }
1610 }
1611
1612
1623 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1624 {
1625 global $conf, $langs, $hookmanager;
1626
1627 if (!empty($conf->dol_no_mouse_hover)) {
1628 $notooltip = 1; // Force disable tooltips
1629 }
1630
1631 $result = '';
1632
1633 $labeltoshow = 'PaymentByDirectDebit';
1634 if (!empty($this->type) && $this->type == 'bank-transfer') {
1635 $labeltoshow = 'PaymentByBankTransfer';
1636 }
1637
1638 $label = img_picto('', $this->picto) . ' <u>' . $langs->trans($labeltoshow) . '</u> ' . $this->getLibStatut(5);
1639 $label .= '<br>';
1640 $label .= '<b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
1641 if (isset($this->amount)) {
1642 $label .= '<br><b>' . $langs->trans("Amount") . ":</b> " . price($this->amount);
1643 }
1644 if (isset($this->date_trans)) {
1645 $label .= '<br><b>' . $langs->trans("TransData") . ":</b> " . dol_print_date($this->date_trans, 'dayhour', 'tzuserrel');
1646 }
1647 /*if (isset($this->date_credit)) {
1648 $label .= '<br><b>'.$langs->trans("TransData").":</b> ".dol_print_date($this->date_credit, 'dayhour', 'tzuserrel');
1649 }*/
1650
1651 $url = DOL_URL_ROOT . '/compta/prelevement/card.php?id=' . $this->id;
1652 if (!empty($this->type) && $this->type == 'bank-transfer') {
1653 $url = DOL_URL_ROOT . '/compta/prelevement/card.php?id=' . $this->id;
1654 }
1655
1656 if ($option != 'nolink') {
1657 // Add param to save lastsearch_values or not
1658 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1659 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1660 $add_save_lastsearch_values = 1;
1661 }
1662 if ($add_save_lastsearch_values) {
1663 $url .= '&save_lastsearch_values=1';
1664 }
1665 }
1666
1667 $linkclose = '';
1668 if (empty($notooltip)) {
1669 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1670 $label = $langs->trans("ShowMyObject");
1671 $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
1672 }
1673 $linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"';
1674 $linkclose .= ' class="classfortooltip' . ($morecss ? ' ' . $morecss : '') . '"';
1675 } else {
1676 $linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
1677 }
1678
1679 $linkstart = '<a href="' . $url . '"';
1680 $linkstart .= $linkclose . '>';
1681 $linkend = '</a>';
1682
1683 $result .= $linkstart;
1684 if ($withpicto) {
1685 $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);
1686 }
1687 if ($withpicto != 2) {
1688 $result .= $this->ref;
1689 }
1690 $result .= $linkend;
1691
1692 global $action, $hookmanager;
1693 $hookmanager->initHooks(array('banktransferdao'));
1694 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1695 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1696 if ($reshook > 0) {
1697 $result = $hookmanager->resPrint;
1698 } else {
1699 $result .= $hookmanager->resPrint;
1700 }
1701
1702 return $result;
1703 }
1704
1705
1712 public function deleteNotificationById($rowid)
1713 {
1714 $sql = "DELETE FROM " . MAIN_DB_PREFIX . "notify_def";
1715 $sql .= " WHERE rowid = " . ((int) $rowid);
1716
1717 if ($this->db->query($sql)) {
1718 return 0;
1719 } else {
1720 return -1;
1721 }
1722 }
1723
1731 public function deleteNotification($user, $action)
1732 {
1733 if (is_object($user)) {
1734 $userid = $user->id;
1735 } else { // If user is an id
1736 $userid = $user;
1737 }
1738
1739 $sql = "DELETE FROM " . MAIN_DB_PREFIX . "notify_def";
1740 $sql .= " WHERE fk_user=" . ((int) $userid) . " AND fk_action='" . $this->db->escape($action) . "'";
1741
1742 if ($this->db->query($sql)) {
1743 return 0;
1744 } else {
1745 return -1;
1746 }
1747 }
1748
1749 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1758 public function addNotification($db, $user, $action)
1759 {
1760 // phpcs:enable
1761 $result = 0;
1762
1763 if (is_object($user)) {
1764 $userid = $user->id;
1765 } else { // If user is an id
1766 $userid = $user;
1767 }
1768
1769 if ($this->deleteNotification($user, $action) == 0) {
1770 $now = dol_now();
1771
1772 $sql = "INSERT INTO " . MAIN_DB_PREFIX . "notify_def (datec,fk_user, fk_soc, fk_contact, fk_action)";
1773 $sql .= " VALUES ('" . $this->db->idate($now) . "', " . ((int) $userid) . ", 'NULL', 'NULL', '" . $this->db->escape($action) . "')";
1774
1775 dol_syslog("adnotiff: " . $sql);
1776 if ($this->db->query($sql)) {
1777 $result = 0;
1778 } else {
1779 $result = -1;
1780 dol_syslog(get_class($this) . "::addNotification Error $result");
1781 }
1782 }
1783
1784 return $result;
1785 }
1786
1787
1803 public function generate(string $format = 'ALL', int $executiondate = 0, string $type = 'direct-debit', int $fk_bank_account = 0, int $forsalary = 0, int $thirdpartyBANId = 0)
1804 {
1805 global $conf, $langs, $mysoc;
1806
1807 //TODO: Optimize code to read lines in a single function
1808
1809 // Clean params
1810 if (empty($fk_bank_account)) {
1811 $fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
1812 }
1813
1814 $result = 0;
1815
1816 dol_syslog(get_class($this) . "::generate build file=" . $this->filename . " type=" . $type);
1817
1818 $this->file = fopen($this->filename, "w");
1819 if ($this->file == false) {
1820 $this->error = $langs->trans('ErrorFailedToOpenFile', $this->filename);
1821 return -1;
1822 }
1823
1824 $found = 0;
1825 $this->total = 0;
1826
1827 // Build file for European countries
1828 if ($mysoc->isInEEC()) {
1829 $found++;
1830
1831 if ($type != 'bank-transfer') {
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 $fileDebiteurSection = '';
1850 $fileEmetteurSection = '';
1851 $i = 0;
1852
1853 /*
1854 * Section Debitor (sepa Debiteurs block lines)
1855 */
1856
1857 $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
1858 $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1859 $sql .= " f.ref as reffac, p.fk_facture as idfac,";
1860 $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
1861 $sql .= " FROM";
1862 $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1863 $sql .= " " . MAIN_DB_PREFIX . "facture as f,";
1864 $sql .= " " . MAIN_DB_PREFIX . "prelevement as p,";
1865 $sql .= " " . MAIN_DB_PREFIX . "societe as soc,";
1866 $sql .= " " . MAIN_DB_PREFIX . "c_country as c,";
1867 $sql .= " " . MAIN_DB_PREFIX . "societe_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_facture = f.rowid";
1871 $sql .= " AND f.fk_soc = soc.rowid";
1872 $sql .= " AND soc.fk_pays = c.rowid";
1873 $sql .= " AND rib.fk_soc = f.fk_soc";
1874 if (!empty($thirdpartyBANId)) {
1875 $sql .= " AND rib.rowid = " . ((int) $thirdpartyBANId);
1876 } else {
1877 $sql .= " AND rib.default_rib = 1";
1878 }
1879 $sql .= " AND rib.type = 'ban'";
1880
1881 // Define $fileDebiteurSection. One section DrctDbtTxInf per invoice.
1882 $resql = $this->db->query($sql);
1883 $nbtotalDrctDbtTxInf = -1;
1884 if ($resql) {
1885 $cachearraytotestduplicate = array();
1886
1887 $num = $this->db->num_rows($resql);
1888 while ($i < $num) {
1889 $obj = $this->db->fetch_object($resql);
1890
1891 if (!empty($cachearraytotestduplicate[$obj->idfac])) {
1892 $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
1893 $this->invoice_in_error[$obj->idfac] = $this->error;
1894 $result = -2;
1895 break;
1896 }
1897 $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
1898
1899 $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
1900 $iban = dolDecrypt($obj->iban);
1901
1902 $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, $iban, $obj->bic, $daterum, $obj->drum, $obj->rum, $type);
1903
1904 $this->total += $obj->somme;
1905 $i++;
1906 }
1907 $nbtotalDrctDbtTxInf = $i;
1908 } else {
1909 $this->error = $this->db->lasterror();
1910 fwrite($this->file, 'ERROR DEBITOR ' . $sql . $CrLf); // DEBITOR = Customers
1911 $result = -2;
1912 }
1913
1914 // Define $fileEmetteurSection. Start of block PmtInf. Will contains all $nbtotalDrctDbtTxInf
1915 if ($result != -2) {
1916 $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type, $fk_bank_account);
1917 }
1918
1919 if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) {
1920 $this->total = number_format((float) price2num($this->total, 'MT'), 2, ".", "");
1921 }
1922
1926 // SEPA File Header
1927 fwrite($this->file, '<' . '?xml version="1.0" encoding="UTF-8" standalone="yes"?' . '>' . $CrLf);
1928 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);
1929 fwrite($this->file, ' <CstmrDrctDbtInitn>' . $CrLf);
1930 // SEPA Group header
1931 fwrite($this->file, ' <GrpHdr>' . $CrLf);
1932 fwrite($this->file, ' <MsgId>' . ('DOL/' . $dateTime_YMD . '/DD' . $this->id) . '</MsgId>' . $CrLf);
1933 fwrite($this->file, ' <CreDtTm>' . $dateTime_ECMA . '</CreDtTm>' . $CrLf);
1934 fwrite($this->file, ' <NbOfTxs>' . $i . '</NbOfTxs>' . $CrLf);
1935 fwrite($this->file, ' <CtrlSum>' . $this->total . '</CtrlSum>' . $CrLf);
1936 fwrite($this->file, ' <InitgPty>' . $CrLf);
1937 fwrite($this->file, ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf);
1938 fwrite($this->file, ' <Id>' . $CrLf);
1939 fwrite($this->file, ' <PrvtId>' . $CrLf);
1940 fwrite($this->file, ' <Othr>' . $CrLf);
1941 fwrite($this->file, ' <Id>' . $this->emetteur_ics . '</Id>' . $CrLf);
1942 fwrite($this->file, ' </Othr>' . $CrLf);
1943 fwrite($this->file, ' </PrvtId>' . $CrLf);
1944 fwrite($this->file, ' </Id>' . $CrLf);
1945 fwrite($this->file, ' </InitgPty>' . $CrLf);
1946 fwrite($this->file, ' </GrpHdr>' . $CrLf);
1947 // SEPA File Emetteur
1948 if ($result != -2) {
1949 fwrite($this->file, $fileEmetteurSection);
1950 }
1951 // SEPA File Debiteurs
1952 if ($result != -2) {
1953 fwrite($this->file, $fileDebiteurSection);
1954 }
1955 // SEPA FILE FOOTER
1956 fwrite($this->file, ' </PmtInf>' . $CrLf);
1957 fwrite($this->file, ' </CstmrDrctDbtInitn>' . $CrLf);
1958 fwrite($this->file, '</Document>' . $CrLf);
1959 } else {
1963 // SEPA Initialisation
1964 $CrLf = "\n";
1965
1966 $now = dol_now();
1967
1968 $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S');
1969
1970 $date_actu = $now;
1971 if (!empty($executiondate)) {
1972 $date_actu = $executiondate;
1973 }
1974
1975 $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d');
1976 $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S');
1977 $fileCrediteurSection = '';
1978 $fileEmetteurSection = '';
1979 $i = 0;
1980
1981 /*
1982 * Section Creditor (sepa Crediteurs block lines)
1983 */
1984 if (!empty($forsalary)) {
1985 $sql = "SELECT u.rowid as userId, u.address, u.zip, u.town, c.code as country_code, CONCAT(u.firstname,' ',u.lastname) as nom,";
1986 $sql .= " pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1987 $sql .= " s.ref as reffac, p.fk_salary as idfac,";
1988 $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, '' as rum, '' as date_rum";
1989 $sql .= " FROM";
1990 $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1991 $sql .= " " . MAIN_DB_PREFIX . "salary as s,";
1992 $sql .= " " . MAIN_DB_PREFIX . "prelevement as p,";
1993 $sql .= " " . MAIN_DB_PREFIX . "user as u";
1994 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_country as c ON u.fk_country = c.rowid,";
1995 $sql .= " " . MAIN_DB_PREFIX . "user_rib as rib";
1996 $sql .= " WHERE pl.fk_prelevement_bons=" . ((int) $this->id);
1997 $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1998 $sql .= " AND p.fk_salary = s.rowid";
1999 $sql .= " AND s.fk_user = u.rowid";
2000 $sql .= " AND rib.fk_user = s.fk_user";
2001 } else {
2002 $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
2003 $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
2004 $sql .= " f.ref as reffac, f.ref_supplier as fac_ref_supplier, p.fk_facture_fourn as idfac,";
2005 $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
2006 $sql .= " FROM";
2007 $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
2008 $sql .= " " . MAIN_DB_PREFIX . "facture_fourn as f,";
2009 $sql .= " " . MAIN_DB_PREFIX . "prelevement as p,";
2010 $sql .= " " . MAIN_DB_PREFIX . "societe as soc";
2011 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_country as c ON soc.fk_pays = c.rowid,";
2012 $sql .= " " . MAIN_DB_PREFIX . "societe_rib as rib";
2013 $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
2014 $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
2015 $sql .= " AND p.fk_facture_fourn = f.rowid";
2016 $sql .= " AND f.fk_soc = soc.rowid";
2017 $sql .= " AND rib.fk_soc = f.fk_soc";
2018 if (!empty($thirdpartyBANId)) {
2019 $sql .= " AND rib.rowid = " . ((int) $thirdpartyBANId);
2020 } else {
2021 $sql .= " AND rib.default_rib = 1";
2022 }
2023 $sql .= " AND rib.type = 'ban'";
2024 }
2025 // Define $fileCrediteurSection. One section DrctDbtTxInf per invoice.
2026 $nbtotalDrctDbtTxInf = -1;
2027
2028 $resql = $this->db->query($sql);
2029 if ($resql) {
2030 $cachearraytotestduplicate = array();
2031
2032 $num = $this->db->num_rows($resql);
2033 while ($i < $num) {
2034 $obj = $this->db->fetch_object($resql);
2035 if (!empty($cachearraytotestduplicate[$obj->idfac])) {
2036 $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
2037 $this->invoice_in_error[$obj->idfac] = $this->error;
2038 $result = -2;
2039 break;
2040 }
2041 $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
2042
2043 $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
2044 $iban = dolDecrypt($obj->iban);
2045 $refobj = $obj->reffac;
2046 if (empty($refobj) && !empty($forsalary)) { // If ref of salary not defined, we force a value
2047 $refobj = "SAL" . $obj->idfac;
2048 }
2049
2050 $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, $iban, $obj->bic, $daterum, $obj->drum, $obj->rum, $type, $obj->fac_ref_supplier);
2051
2052 $this->total += $obj->somme;
2053 $i++;
2054 }
2055 $nbtotalDrctDbtTxInf = $i;
2056 } else {
2057 $this->error = $this->db->lasterror();
2058 fwrite($this->file, 'ERROR CREDITOR ' . $sql . $CrLf); // CREDITORS = Suppliers
2059 $result = -2;
2060 }
2061 // Define $fileEmetteurSection. Start of block PmtInf. Will contains all $nbtotalDrctDbtTxInf
2062 if ($result != -2) {
2063 $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type);
2064 }
2065
2066 if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) {
2067 $this->total = number_format((float) price2num($this->total, 'MT'), 2, ".", "");
2068 }
2069
2073 // SEPA File Header
2074 fwrite($this->file, '<' . '?xml version="1.0" encoding="UTF-8" standalone="yes"?' . '>' . $CrLf);
2075 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);
2076 fwrite($this->file, ' <CstmrCdtTrfInitn>' . $CrLf);
2077 // SEPA Group header
2078 fwrite($this->file, ' <GrpHdr>' . $CrLf);
2079 fwrite($this->file, ' <MsgId>' . ('DOL/' . $dateTime_YMD . '/CT' . $this->id) . '</MsgId>' . $CrLf);
2080 fwrite($this->file, ' <CreDtTm>' . $dateTime_ECMA . '</CreDtTm>' . $CrLf);
2081 fwrite($this->file, ' <NbOfTxs>' . $i . '</NbOfTxs>' . $CrLf);
2082 fwrite($this->file, ' <CtrlSum>' . $this->total . '</CtrlSum>' . $CrLf);
2083 fwrite($this->file, ' <InitgPty>' . $CrLf);
2084 fwrite($this->file, ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf);
2085 fwrite($this->file, ' <Id>' . $CrLf);
2086 fwrite($this->file, ' <PrvtId>' . $CrLf);
2087 fwrite($this->file, ' <Othr>' . $CrLf);
2088 fwrite($this->file, ' <Id>' . $this->emetteur_ics . '</Id>' . $CrLf);
2089 fwrite($this->file, ' </Othr>' . $CrLf);
2090 fwrite($this->file, ' </PrvtId>' . $CrLf);
2091 fwrite($this->file, ' </Id>' . $CrLf);
2092 fwrite($this->file, ' </InitgPty>' . $CrLf);
2093 fwrite($this->file, ' </GrpHdr>' . $CrLf);
2094 // SEPA File Emetteur (mycompany)
2095 if ($result != -2) {
2096 fwrite($this->file, $fileEmetteurSection);
2097 }
2098 // SEPA File Creditors
2099 if ($result != -2) {
2100 fwrite($this->file, $fileCrediteurSection);
2101 }
2102 // SEPA FILE FOOTER
2103 fwrite($this->file, ' </PmtInf>' . $CrLf);
2104 fwrite($this->file, ' </CstmrCdtTrfInitn>' . $CrLf);
2105 fwrite($this->file, '</Document>' . $CrLf);
2106 }
2107 }
2108
2109 // Build file for Other Countries with unknown format
2110 if (!$found) {
2111 if ($type != 'bank-transfer') {
2112 $sql = "SELECT pl.amount";
2113 $sql .= " FROM";
2114 $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
2115 $sql .= " " . MAIN_DB_PREFIX . "facture as f,";
2116 $sql .= " " . MAIN_DB_PREFIX . "prelevement as p";
2117 $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
2118 $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
2119 $sql .= " AND p.fk_facture = f.rowid";
2120
2121 // Lines
2122 $i = 0;
2123 $resql = $this->db->query($sql);
2124 if ($resql) {
2125 $num = $this->db->num_rows($resql);
2126
2127 while ($i < $num) {
2128 $obj = $this->db->fetch_object($resql);
2129 $this->total += $obj->amount;
2130
2131 // TODO Write record into file
2132 $i++;
2133 }
2134 } else {
2135 $result = -2;
2136 }
2137 } else {
2138 $sql = "SELECT pl.amount";
2139 $sql .= " FROM";
2140 $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
2141 $sql .= " " . MAIN_DB_PREFIX . "facture_fourn as f,";
2142 $sql .= " " . MAIN_DB_PREFIX . "prelevement as p";
2143 $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
2144 $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
2145 $sql .= " AND p.fk_facture_fourn = f.rowid";
2146 // Lines
2147 $i = 0;
2148 $resql = $this->db->query($sql);
2149 if ($resql) {
2150 $num = $this->db->num_rows($resql);
2151
2152 while ($i < $num) {
2153 $obj = $this->db->fetch_object($resql);
2154 $this->total += $obj->amount;
2155
2156 // TODO Write record into file
2157 $i++;
2158 }
2159 } else {
2160 $result = -2;
2161 }
2162 }
2163
2164 $langs->load('withdrawals');
2165
2166 // TODO Add here code to generate a generic file
2167 fwrite($this->file, $langs->transnoentitiesnoconv('WithdrawalFileNotCapable', $mysoc->country_code));
2168 }
2169
2170 fclose($this->file);
2171 dolChmod($this->filename);
2172
2173 return $result;
2174 }
2175
2176
2185 public static function buildRumNumber($row_code_client, $row_datec, $row_drum)
2186 {
2187 global $langs;
2188
2189 $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)
2190
2191 // 3 char + '-' + 12 + '-' + id + '-' + code Must be lower than 32.
2192 return $pre . '-' . dol_print_date($row_datec, 'dayhourlogsmall') . '-' . dol_trunc($row_drum . ($row_code_client ? '-' . $row_code_client : ''), 13, 'right', 'UTF-8', 1);
2193 }
2194
2195
2196 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2213 public function EnregDestinataire($rowid, $client_nom, $rib_banque, $rib_guichet, $rib_number, $amount, $ref, $facid, $rib_dom = '', $type = 'direct-debit')
2214 {
2215 // phpcs:enable
2216 fwrite($this->file, "06");
2217 fwrite($this->file, "08"); // Prelevement ordinaire
2218
2219 fwrite($this->file, " "); // Zone Reservee B2
2220
2221 fwrite($this->file, $this->emetteur_ics); // ICS
2222
2223 // Date d'echeance C1
2224
2225 fwrite($this->file, " ");
2226 fwrite($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
2227 fwrite($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
2228
2229 // Raison Sociale Destinataire C2
2230
2231 fwrite($this->file, substr(strtoupper($client_nom) . " ", 0, 24));
2232
2233 // Address optional D1
2234 $address = strtr($rib_dom, array(" " => "-", chr(13) => " ", chr(10) => ""));
2235 fwrite($this->file, substr($address . " ", 0, 24));
2236
2237 // Zone Reservee D2
2238
2239 fwrite($this->file, substr(" ", 0, 8));
2240
2241 // Code Guichet D3
2242
2243 fwrite($this->file, $rib_guichet);
2244
2245 // Numero de compte D4
2246
2247 fwrite($this->file, substr("000000000000000" . $rib_number, -11));
2248
2249 // Zone E Montant
2250
2251 $montant = (round($amount, 2) * 100);
2252
2253 fwrite($this->file, substr("000000000000000" . $montant, -16));
2254
2255 // Label F
2256
2257 fwrite($this->file, substr("*_" . $ref . "_RDVnet" . $rowid . " ", 0, 31));
2258
2259 // Code etablissement G1
2260
2261 fwrite($this->file, $rib_banque);
2262
2263 // Zone Reservee G2
2264
2265 fwrite($this->file, substr(" ", 0, 5));
2266
2267 fwrite($this->file, "\n");
2268 }
2269
2270
2271 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2297 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 = '')
2298 {
2299 // phpcs:enable
2300 global $conf, $mysoc;
2301
2302 if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) {
2303 $row_somme = number_format((float) price2num($row_somme, 'MT'), 2, ".", "");
2304 } else {
2305 $row_somme = round((float) $row_somme, 2);
2306 }
2307
2308 include_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php';
2309
2310 $CrLf = "\n";
2311 $Rowing = sprintf("%010d", $row_idfac);
2312
2313 // Define value for RUM
2314 // Example: RUM-CustomerCode-CustomerBankAccountId-01424448606 (note: Date is the timestamp of the date of creation of CustomerBankAccountId)
2315 $Rum = (empty($row_rum) ? $this->buildRumNumber($row_code_client, $row_datec, $row_drum) : $row_rum);
2316
2317 // Define date of RUM signature
2318 $DtOfSgntr = dol_print_date($row_datec, '%Y-%m-%d');
2319
2320 if ($type != 'bank-transfer') {
2321 // SEPA Paiement Information of buyer for Direct Debit
2322 $XML_DEBITOR = '';
2323 $XML_DEBITOR .= ' <DrctDbtTxInf>' . $CrLf;
2324 $XML_DEBITOR .= ' <PmtId>' . $CrLf;
2325 // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
2326 $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
2327 $XML_DEBITOR .= ' </PmtId>' . $CrLf;
2328 $XML_DEBITOR .= ' <InstdAmt Ccy="EUR">' . $row_somme . '</InstdAmt>' . $CrLf;
2329 $XML_DEBITOR .= ' <DrctDbtTx>' . $CrLf;
2330 $XML_DEBITOR .= ' <MndtRltdInf>' . $CrLf;
2331 $XML_DEBITOR .= ' <MndtId>' . $Rum . '</MndtId>' . $CrLf;
2332 $XML_DEBITOR .= ' <DtOfSgntr>' . $DtOfSgntr . '</DtOfSgntr>' . $CrLf;
2333 $XML_DEBITOR .= ' <AmdmntInd>false</AmdmntInd>' . $CrLf;
2334 $XML_DEBITOR .= ' </MndtRltdInf>' . $CrLf;
2335 $XML_DEBITOR .= ' </DrctDbtTx>' . $CrLf;
2336 $XML_DEBITOR .= ' <DbtrAgt>' . $CrLf;
2337 $XML_DEBITOR .= ' <FinInstnId>' . $CrLf;
2338 if (getDolGlobalInt('WITHDRAWAL_WITHOUT_BIC') == 0) {
2339 $XML_DEBITOR .= ' <BIC>' . $row_bic . '</BIC>' . $CrLf;
2340 }
2341 $XML_DEBITOR .= ' </FinInstnId>' . $CrLf;
2342 $XML_DEBITOR .= ' </DbtrAgt>' . $CrLf;
2343 $XML_DEBITOR .= ' <Dbtr>' . $CrLf;
2344 $XML_DEBITOR .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))) . '</Nm>' . $CrLf;
2345 $XML_DEBITOR .= ' <PstlAdr>' . $CrLf;
2346 $XML_DEBITOR .= ' <Ctry>' . $row_country_code . '</Ctry>' . $CrLf;
2347 $addressline1 = strtr($row_address, array(chr(13) => ", ", chr(10) => ""));
2348 $addressline2 = strtr($row_zip . (($row_zip && $row_town) ? ' ' : (string) $row_town), array(chr(13) => ", ", chr(10) => ""));
2349 if (trim($addressline1)) {
2350 $XML_DEBITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2351 }
2352 if (trim($addressline2)) {
2353 $XML_DEBITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2354 }
2355 $XML_DEBITOR .= ' </PstlAdr>' . $CrLf;
2356 $XML_DEBITOR .= ' </Dbtr>' . $CrLf;
2357 $XML_DEBITOR .= ' <DbtrAcct>' . $CrLf;
2358 $XML_DEBITOR .= ' <Id>' . $CrLf;
2359 $XML_DEBITOR .= ' <IBAN>' . preg_replace('/\s/', '', $row_iban) . '</IBAN>' . $CrLf;
2360 $XML_DEBITOR .= ' </Id>' . $CrLf;
2361 $XML_DEBITOR .= ' </DbtrAcct>' . $CrLf;
2362 $XML_DEBITOR .= ' <RmtInf>' . $CrLf;
2363
2364 // Structured data for Belgium
2365 if (getDolGlobalString('INVOICE_PAYMENT_ENABLE_STRUCTURED_COMMUNICATION') && $mysoc->country_code == 'BE') {
2366 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions_be.lib.php';
2367
2368 $invoicestatic = new Facture($this->db);
2369 $invoicestatic->fetch($row_idfac);
2370
2371 $invoicePaymentKey = dolBECalculateStructuredCommunication($invoicestatic->ref, $invoicestatic->type);
2372 $XML_DEBITOR .= ' <strd>' . $invoicePaymentKey . '</strd>' . $CrLf;
2373 } else {
2374 // A string with some information on payment - 140 max
2375 $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
2376 }
2377 $XML_DEBITOR .= ' </RmtInf>' . $CrLf;
2378 $XML_DEBITOR .= ' </DrctDbtTxInf>' . $CrLf;
2379 return $XML_DEBITOR;
2380 } else {
2381 // SEPA Payment Information of seller for Credit Transfer
2382 $XML_CREDITOR = '';
2383 $XML_CREDITOR .= ' <CdtTrfTxInf>' . $CrLf;
2384 $XML_CREDITOR .= ' <PmtId>' . $CrLf;
2385 // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
2386 $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
2387 $XML_CREDITOR .= ' </PmtId>' . $CrLf;
2388 if (!empty($this->sepa_xml_pti_in_ctti)) {
2389 $XML_CREDITOR .= ' <PmtTpInf>' . $CrLf;
2390
2391 // Can be 'NORM' for normal or 'HIGH' for high priority level
2392 if (getDolGlobalString('PAYMENTBYBANKTRANSFER_FORCE_HIGH_PRIORITY')) {
2393 $instrprty = 'HIGH';
2394 } else {
2395 $instrprty = 'NORM';
2396 }
2397 $XML_CREDITOR .= ' <InstrPrty>' . $instrprty . '</InstrPrty>' . $CrLf;
2398 $XML_CREDITOR .= ' <SvcLvl>' . $CrLf;
2399 $XML_CREDITOR .= ' <Cd>SEPA</Cd>' . $CrLf;
2400 $XML_CREDITOR .= ' </SvcLvl>' . $CrLf;
2401 $XML_CREDITOR .= ' <CtgyPurp>' . $CrLf;
2402 $XML_CREDITOR .= ' <Cd>CORE</Cd>' . $CrLf;
2403 $XML_CREDITOR .= ' </CtgyPurp>' . $CrLf;
2404 $XML_CREDITOR .= ' </PmtTpInf>' . $CrLf;
2405 }
2406 $XML_CREDITOR .= ' <Amt>' . $CrLf;
2407 $XML_CREDITOR .= ' <InstdAmt Ccy="EUR">'.round((float) $row_somme, 2).'</InstdAmt>'.$CrLf;
2408 $XML_CREDITOR .= ' </Amt>' . $CrLf;
2409 /*
2410 $XML_CREDITOR .= ' <DrctDbtTx>'.$CrLf;
2411 $XML_CREDITOR .= ' <MndtRltdInf>'.$CrLf;
2412 $XML_CREDITOR .= ' <MndtId>'.$Rum.'</MndtId>'.$CrLf;
2413 $XML_CREDITOR .= ' <DtOfSgntr>'.$DtOfSgntr.'</DtOfSgntr>'.$CrLf;
2414 $XML_CREDITOR .= ' <AmdmntInd>false</AmdmntInd>'.$CrLf;
2415 $XML_CREDITOR .= ' </MndtRltdInf>'.$CrLf;
2416 $XML_CREDITOR .= ' </DrctDbtTx>'.$CrLf;
2417 */
2418 //$XML_CREDITOR .= ' <ChrgBr>SLEV</ChrgBr>'.$CrLf;
2419 $XML_CREDITOR .= ' <CdtrAgt>' . $CrLf;
2420 $XML_CREDITOR .= ' <FinInstnId>' . $CrLf;
2421 $XML_CREDITOR .= ' <BIC>' . $row_bic . '</BIC>' . $CrLf;
2422 $XML_CREDITOR .= ' </FinInstnId>' . $CrLf;
2423 $XML_CREDITOR .= ' </CdtrAgt>' . $CrLf;
2424 $XML_CREDITOR .= ' <Cdtr>' . $CrLf;
2425 $XML_CREDITOR .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))) . '</Nm>' . $CrLf;
2426 $XML_CREDITOR .= ' <PstlAdr>' . $CrLf;
2427 $XML_CREDITOR .= ' <Ctry>' . $row_country_code . '</Ctry>' . $CrLf;
2428 $addressline1 = strtr($row_address, array(chr(13) => ", ", chr(10) => ""));
2429 $addressline2 = strtr($row_zip . (($row_zip && $row_town) ? ' ' : (string) $row_town), array(chr(13) => ", ", chr(10) => ""));
2430 if (trim($addressline1)) {
2431 $XML_CREDITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2432 }
2433 if (trim($addressline2)) {
2434 $XML_CREDITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2435 }
2436 $XML_CREDITOR .= ' </PstlAdr>' . $CrLf;
2437 $XML_CREDITOR .= ' </Cdtr>' . $CrLf;
2438 $XML_CREDITOR .= ' <CdtrAcct>' . $CrLf;
2439 $XML_CREDITOR .= ' <Id>' . $CrLf;
2440 $XML_CREDITOR .= ' <IBAN>' . preg_replace('/\s/', '', $row_iban) . '</IBAN>' . $CrLf;
2441 $XML_CREDITOR .= ' </Id>' . $CrLf;
2442 $XML_CREDITOR .= ' </CdtrAcct>' . $CrLf;
2443 $XML_CREDITOR .= ' <RmtInf>' . $CrLf;
2444 // A string with some information on payment - 140 max
2445 $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
2446 $XML_CREDITOR .= ' </RmtInf>' . $CrLf;
2447 $XML_CREDITOR .= ' </CdtTrfTxInf>' . $CrLf;
2448 return $XML_CREDITOR;
2449 }
2450 }
2451
2452
2453 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2462 public function EnregEmetteur($type = 'direct-debit')
2463 {
2464 // phpcs:enable
2465 fwrite($this->file, "03");
2466 fwrite($this->file, "08"); // Prelevement ordinaire
2467
2468 fwrite($this->file, " "); // Zone Reservee B2
2469
2470 fwrite($this->file, $this->emetteur_ics); // ICS
2471
2472 // Date d'echeance C1
2473
2474 fwrite($this->file, " ");
2475 fwrite($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
2476 fwrite($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
2477
2478 // Raison Sociale C2
2479
2480 fwrite($this->file, substr($this->raison_sociale . " ", 0, 24));
2481
2482 // Ref of thirdparty on 7 characters
2483
2484 fwrite($this->file, substr($this->reference_remise . " ", 0, 7));
2485
2486 // Zone Reservee D1-2
2487
2488 fwrite($this->file, substr(" ", 0, 17));
2489
2490 // Zone Reservee D2
2491
2492 fwrite($this->file, substr(" ", 0, 2));
2493 fwrite($this->file, "E");
2494 fwrite($this->file, substr(" ", 0, 5));
2495
2496 // Code Guichet D3
2497
2498 fwrite($this->file, $this->emetteur_code_guichet);
2499
2500 // Numero de compte D4
2501
2502 fwrite($this->file, substr("000000000000000" . $this->emetteur_numero_compte, -11));
2503
2504 // Zone Reservee E
2505
2506 fwrite($this->file, substr(" ", 0, 16));
2507
2508 // Zone Reservee F
2509
2510 fwrite($this->file, substr(" ", 0, 31));
2511
2512 // Code etablissement
2513
2514 fwrite($this->file, $this->emetteur_code_banque);
2515
2516 // Zone Reservee G
2517
2518 fwrite($this->file, substr(" ", 0, 5));
2519
2520 fwrite($this->file, "\n");
2521 }
2522
2523
2524 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2539 public function EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf = '\n', $format = 'FRST', $type = 'direct-debit', $fk_bank_account = 0)
2540 {
2541 // phpcs:enable
2542
2543 // Clean parameters
2544 $dateTime_YMD = dol_print_date($ladate, '%Y%m%d');
2545 $dateTime_ETAD = dol_print_date($ladate, '%Y-%m-%d');
2546 $dateTime_YMDHMS = dol_print_date($ladate, '%Y-%m-%dT%H:%M:%S');
2547
2548 // Clean params
2549 if (empty($fk_bank_account)) {
2550 $fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
2551 }
2552
2553 // Get data of bank account
2554 $account = new Account($this->db);
2555 if ($account->fetch($fk_bank_account) > 0) {
2556 $this->emetteur_code_banque = $account->code_banque;
2557 $this->emetteur_code_guichet = $account->code_guichet;
2558 $this->emetteur_numero_compte = $account->number;
2559 $this->emetteur_number_key = $account->cle_rib;
2560 $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
2561 $this->emetteur_iban = $account->iban;
2562 $this->emetteur_bic = $account->bic;
2563
2564 $this->emetteur_ics = (($type == 'bank-transfer' && getDolGlobalString("SEPA_USE_IDS")) ? $account->ics_transfer : $account->ics); // Ex: PRELEVEMENT_ICS = "FR78ZZZ123456";
2565
2566 $this->raison_sociale = $account->owner_name;
2567 }
2568
2569 // Get pending payments
2570 $sql = "SELECT rowid, ref";
2571 $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons as pb";
2572 $sql .= " WHERE pb.rowid = " . ((int) $this->id);
2573
2574 $resql = $this->db->query($sql);
2575 if ($resql) {
2576 $obj = $this->db->fetch_object($resql);
2577
2578 $country = explode(':', $configuration->global->MAIN_INFO_SOCIETE_COUNTRY);
2579 $IdBon = sprintf("%05d", $obj->rowid);
2580 $RefBon = $obj->ref;
2581
2582 if (!empty($configuration->global->SEPA_FORCE_TWO_DECIMAL)) {
2583 $total = number_format((float) price2num($total, 'MT'), 2, ".", "");
2584 }
2585
2586 if ($type != 'bank-transfer') {
2587 // SEPA Paiement Information of my company for Direct Debit
2588 $XML_SEPA_INFO = '';
2589 $XML_SEPA_INFO .= ' <PmtInf>' . $CrLf;
2590 $XML_SEPA_INFO .= ' <PmtInfId>' . ('DOL/' . $dateTime_YMD . '/DD' . $IdBon . '-' . $RefBon) . '</PmtInfId>' . $CrLf;
2591 $XML_SEPA_INFO .= ' <PmtMtd>DD</PmtMtd>' . $CrLf;
2592 $XML_SEPA_INFO .= ' <NbOfTxs>' . $nombre . '</NbOfTxs>' . $CrLf;
2593 $XML_SEPA_INFO .= ' <CtrlSum>' . $total . '</CtrlSum>' . $CrLf;
2594 $XML_SEPA_INFO .= ' <PmtTpInf>' . $CrLf;
2595 $XML_SEPA_INFO .= ' <SvcLvl>' . $CrLf;
2596 $XML_SEPA_INFO .= ' <Cd>SEPA</Cd>' . $CrLf;
2597 $XML_SEPA_INFO .= ' </SvcLvl>' . $CrLf;
2598 $XML_SEPA_INFO .= ' <LclInstrm>' . $CrLf;
2599 $XML_SEPA_INFO .= ' <Cd>CORE</Cd>' . $CrLf;
2600 $XML_SEPA_INFO .= ' </LclInstrm>' . $CrLf;
2601 $XML_SEPA_INFO .= ' <SeqTp>' . $format . '</SeqTp>' . $CrLf;
2602 $XML_SEPA_INFO .= ' </PmtTpInf>' . $CrLf;
2603 $XML_SEPA_INFO .= ' <ReqdColltnDt>' . $dateTime_ETAD . '</ReqdColltnDt>' . $CrLf;
2604 $XML_SEPA_INFO .= ' <Cdtr>' . $CrLf;
2605 $XML_SEPA_INFO .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf;
2606 $XML_SEPA_INFO .= ' <PstlAdr>' . $CrLf;
2607 $XML_SEPA_INFO .= ' <Ctry>' . $country[1] . '</Ctry>' . $CrLf;
2608 $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(chr(13) => ", ", chr(10) => ""));
2609 $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) => ""));
2610 if ($addressline1) {
2611 $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2612 }
2613 if ($addressline2) {
2614 $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2615 }
2616 $XML_SEPA_INFO .= ' </PstlAdr>' . $CrLf;
2617 $XML_SEPA_INFO .= ' </Cdtr>' . $CrLf;
2618 $XML_SEPA_INFO .= ' <CdtrAcct>' . $CrLf;
2619 $XML_SEPA_INFO .= ' <Id>' . $CrLf;
2620 $XML_SEPA_INFO .= ' <IBAN>' . preg_replace('/\s/', '', $this->emetteur_iban) . '</IBAN>' . $CrLf;
2621 $XML_SEPA_INFO .= ' </Id>' . $CrLf;
2622 $XML_SEPA_INFO .= ' </CdtrAcct>' . $CrLf;
2623 $XML_SEPA_INFO .= ' <CdtrAgt>' . $CrLf;
2624 $XML_SEPA_INFO .= ' <FinInstnId>' . $CrLf;
2625 $XML_SEPA_INFO .= ' <BIC>' . $this->emetteur_bic . '</BIC>' . $CrLf;
2626 $XML_SEPA_INFO .= ' </FinInstnId>' . $CrLf;
2627 $XML_SEPA_INFO .= ' </CdtrAgt>' . $CrLf;
2628 /* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf;
2629 $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2630 $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2631 $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2632 $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;
2633 $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;
2634 $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2635 $XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/
2636 $XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>' . $CrLf; // Field "Responsible of fees". Must be SLEV
2637 $XML_SEPA_INFO .= ' <CdtrSchmeId>' . $CrLf;
2638 $XML_SEPA_INFO .= ' <Id>' . $CrLf;
2639 $XML_SEPA_INFO .= ' <PrvtId>' . $CrLf;
2640 $XML_SEPA_INFO .= ' <Othr>' . $CrLf;
2641 $XML_SEPA_INFO .= ' <Id>' . $this->emetteur_ics . '</Id>' . $CrLf;
2642 $XML_SEPA_INFO .= ' <SchmeNm>' . $CrLf;
2643 $XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>' . $CrLf;
2644 $XML_SEPA_INFO .= ' </SchmeNm>' . $CrLf;
2645 $XML_SEPA_INFO .= ' </Othr>' . $CrLf;
2646 $XML_SEPA_INFO .= ' </PrvtId>' . $CrLf;
2647 $XML_SEPA_INFO .= ' </Id>' . $CrLf;
2648 $XML_SEPA_INFO .= ' </CdtrSchmeId>' . $CrLf;
2649 } else {
2650 // SEPA Paiement Information of my company for Credit Transfer
2651 $XML_SEPA_INFO = '';
2652 $XML_SEPA_INFO .= ' <PmtInf>' . $CrLf;
2653 $XML_SEPA_INFO .= ' <PmtInfId>' . ('DOL/' . $dateTime_YMD . '/CT' . $IdBon . '-' . $RefBon) . '</PmtInfId>' . $CrLf;
2654 $XML_SEPA_INFO .= ' <PmtMtd>TRF</PmtMtd>' . $CrLf;
2655 //$XML_SEPA_INFO .= ' <BtchBookg>False</BtchBookg>'.$CrLf;
2656 $XML_SEPA_INFO .= ' <NbOfTxs>' . $nombre . '</NbOfTxs>' . $CrLf;
2657 $XML_SEPA_INFO .= ' <CtrlSum>' . $total . '</CtrlSum>' . $CrLf;
2658 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.
2659 $XML_SEPA_INFO .= ' <PmtTpInf>' . $CrLf;
2660 $XML_SEPA_INFO .= ' <SvcLvl>' . $CrLf;
2661 $XML_SEPA_INFO .= ' <Cd>SEPA</Cd>' . $CrLf;
2662 $XML_SEPA_INFO .= ' </SvcLvl>' . $CrLf;
2663 $XML_SEPA_INFO .= ' <LclInstrm>' . $CrLf;
2664 $XML_SEPA_INFO .= ' <Cd>CORE</Cd>' . $CrLf;
2665 $XML_SEPA_INFO .= ' </LclInstrm>' . $CrLf;
2666 $XML_SEPA_INFO .= ' <SeqTp>' . $format . '</SeqTp>' . $CrLf;
2667 $XML_SEPA_INFO .= ' </PmtTpInf>' . $CrLf;
2668 }
2669 $XML_SEPA_INFO .= ' <ReqdExctnDt>' . dol_print_date($dateTime_ETAD, 'dayrfc') . '</ReqdExctnDt>' . $CrLf;
2670 $XML_SEPA_INFO .= ' <Dbtr>' . $CrLf;
2671 $XML_SEPA_INFO .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf;
2672 $XML_SEPA_INFO .= ' <PstlAdr>' . $CrLf;
2673 $XML_SEPA_INFO .= ' <Ctry>' . $country[1] . '</Ctry>' . $CrLf;
2674 $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(chr(13) => ", ", chr(10) => ""));
2675 $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) => ""));
2676 if ($addressline1) {
2677 $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2678 }
2679 if ($addressline2) {
2680 $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2681 }
2682 $XML_SEPA_INFO .= ' </PstlAdr>' . $CrLf;
2683 $XML_SEPA_INFO .= ' </Dbtr>' . $CrLf;
2684 $XML_SEPA_INFO .= ' <DbtrAcct>' . $CrLf;
2685 $XML_SEPA_INFO .= ' <Id>' . $CrLf;
2686 $XML_SEPA_INFO .= ' <IBAN>' . preg_replace('/\s/', '', $this->emetteur_iban) . '</IBAN>' . $CrLf;
2687 $XML_SEPA_INFO .= ' </Id>' . $CrLf;
2688 $XML_SEPA_INFO .= ' </DbtrAcct>' . $CrLf;
2689 $XML_SEPA_INFO .= ' <DbtrAgt>' . $CrLf;
2690 $XML_SEPA_INFO .= ' <FinInstnId>' . $CrLf;
2691 $XML_SEPA_INFO .= ' <BIC>' . $this->emetteur_bic . '</BIC>' . $CrLf;
2692 $XML_SEPA_INFO .= ' </FinInstnId>' . $CrLf;
2693 $XML_SEPA_INFO .= ' </DbtrAgt>' . $CrLf;
2694 /* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf;
2695 $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2696 $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2697 $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2698 $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;
2699 $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;
2700 $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2701 $XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/
2702 $XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>' . $CrLf; // Field "Responsible of fees". Must be SLEV
2703 /*$XML_SEPA_INFO .= ' <CdtrSchmeId>'.$CrLf;
2704 $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2705 $XML_SEPA_INFO .= ' <PrvtId>'.$CrLf;
2706 $XML_SEPA_INFO .= ' <Othr>'.$CrLf;
2707 $XML_SEPA_INFO .= ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf;
2708 $XML_SEPA_INFO .= ' <SchmeNm>'.$CrLf;
2709 $XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>'.$CrLf;
2710 $XML_SEPA_INFO .= ' </SchmeNm>'.$CrLf;
2711 $XML_SEPA_INFO .= ' </Othr>'.$CrLf;
2712 $XML_SEPA_INFO .= ' </PrvtId>'.$CrLf;
2713 $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2714 $XML_SEPA_INFO .= ' </CdtrSchmeId>'.$CrLf;*/
2715 }
2716 } else {
2717 fwrite($this->file, 'INCORRECT EMETTEUR ' . $this->raison_sociale . $CrLf);
2718 $XML_SEPA_INFO = '';
2719 }
2720 return $XML_SEPA_INFO;
2721 }
2722
2723 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2730 public function EnregTotal($total)
2731 {
2732 // phpcs:enable
2733 fwrite($this->file, "08");
2734 fwrite($this->file, "08"); // Prelevement ordinaire
2735
2736 fwrite($this->file, " "); // Zone Reservee B2
2737
2738 fwrite($this->file, $this->emetteur_ics); // ICS
2739
2740 // Reserve C1
2741
2742 fwrite($this->file, substr(" ", 0, 12));
2743
2744
2745 // Raison Sociale C2
2746
2747 fwrite($this->file, substr(" ", 0, 24));
2748
2749 // D1
2750
2751 fwrite($this->file, substr(" ", 0, 24));
2752
2753 // Zone Reservee D2
2754
2755 fwrite($this->file, substr(" ", 0, 8));
2756
2757 // Code Guichet D3
2758
2759 fwrite($this->file, substr(" ", 0, 5));
2760
2761 // Numero de compte D4
2762
2763 fwrite($this->file, substr(" ", 0, 11));
2764
2765 // Zone E Montant
2766
2767 $montant = ($total * 100);
2768
2769 fwrite($this->file, substr("000000000000000" . $montant, -16));
2770
2771 // Zone Reservee F
2772
2773 fwrite($this->file, substr(" ", 0, 31));
2774
2775 // Code etablissement
2776
2777 fwrite($this->file, substr(" ", 0, 5));
2778
2779 // Zone Reservee F
2780
2781 fwrite($this->file, substr(" ", 0, 5));
2782
2783 fwrite($this->file, "\n");
2784 }
2785
2792 public function getLibStatut($mode = 0)
2793 {
2794 return $this->LibStatut($this->statut, $mode);
2795 }
2796
2797 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2805 public function LibStatut($status, $mode = 0)
2806 {
2807 // phpcs:enable
2808 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
2809 global $langs;
2810 //$langs->load("mymodule");
2811 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2812 $this->labelStatus[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2813 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2814 $this->labelStatusShort[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2815 if ($this->type == 'bank-transfer') {
2816 $this->labelStatus[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2817 $this->labelStatusShort[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2818 } else {
2819 $this->labelStatus[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2820 $this->labelStatusShort[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2821 }
2822 }
2823
2824 $statusType = 'status1';
2825 if ($status == self::STATUS_TRANSFERED) {
2826 $statusType = 'status3';
2827 }
2828 if ($status == self::STATUS_CREDITED || $status == self::STATUS_DEBITED) {
2829 $statusType = 'status6';
2830 }
2831
2832 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
2833 }
2834
2835 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2843 public function load_board($user, $mode)
2844 {
2845 // phpcs:enable
2846 if ($user->socid) {
2847 return -1; // protection pour eviter appel par utilisateur externe
2848 }
2849
2850 /*
2851 if ($mode == 'direct_debit') {
2852 $sql = "SELECT b.rowid, f.datedue as datefin";
2853 $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
2854 $sql .= " WHERE f.entity IN (".getEntity('facture').")";
2855 $sql .= " AND f.total_ttc > 0";
2856 } else {
2857 $sql = "SELECT b.rowid, f.datedue as datefin";
2858 $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
2859 $sql .= " WHERE f.entity IN (".getEntity('facture_fourn').")";
2860 $sql .= " AND f.total_ttc > 0";
2861 }
2862
2863 $resql = $this->db->query($sql);
2864 if ($resql) {
2865 $langs->load("banks");
2866 $now = dol_now();
2867
2868 $response = new WorkboardResponse();
2869 if ($mode == 'direct_debit') {
2870 $response->warning_delay = $conf->prelevement->warning_delay / 60 / 60 / 24;
2871 $response->label = $langs->trans("PendingDirectDebitToComplete");
2872 $response->labelShort = $langs->trans("PendingDirectDebitToCompleteShort");
2873 $response->url = DOL_URL_ROOT.'/compta/prelevement/index.php?leftmenu=checks&mainmenu=bank';
2874 } else {
2875 $response->warning_delay = $conf->paymentbybanktransfer->warning_delay / 60 / 60 / 24;
2876 $response->label = $langs->trans("PendingCreditTransferToComplete");
2877 $response->labelShort = $langs->trans("PendingCreditTransferToCompleteShort");
2878 $response->url = DOL_URL_ROOT.'/compta/paymentbybanktransfer/index.php?leftmenu=checks&mainmenu=bank';
2879 }
2880 $response->img = img_object('', "payment");
2881
2882 while ($obj = $this->db->fetch_object($resql)) {
2883 $response->nbtodo++;
2884
2885 if ($this->db->jdate($obj->datefin) < ($now - $conf->withdraw->warning_delay)) {
2886 $response->nbtodolate++;
2887 }
2888 }
2889
2890 $response->nbtodo = 0;
2891 $response->nbtodolate = 0;
2892 // Return workboard only if quantity is not 0
2893 if ($response->nbtodo) {
2894 return $response;
2895 } else {
2896 return 0;
2897 }
2898 } else {
2899 dol_print_error($this->db);
2900 $this->error = $this->db->error();
2901 return -1;
2902 }
2903 */
2904 return 0;
2905 }
2906
2914 public function getKanbanView($option = '', $arraydata = null)
2915 {
2916 global $langs;
2917
2918 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2919
2920 $return = '<div class="box-flex-item box-flex-grow-zero">';
2921 $return .= '<div class="info-box info-box-sm">';
2922 $return .= '<span class="info-box-icon bg-infobox-action">';
2923 $return .= img_picto('', $this->picto);
2924 $return .= '</span>';
2925 $return .= '<div class="info-box-content">';
2926 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . (method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref) . '</span>';
2927 if ($selected >= 0) {
2928 $return .= '<input id="cb' . $this->id . '" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="' . $this->id . '"' . ($selected ? ' checked="checked"' : '') . '>';
2929 }
2930 if (property_exists($this, 'date_echeance')) {
2931 $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>';
2932 }
2933 if (property_exists($this, 'total')) {
2934 $return .= '<br><span class="opacitymedium">' . $langs->trans("Amount") . '</span> : <span class="amount">' . price($this->total) . '</span>';
2935 }
2936 if (method_exists($this, 'LibStatut')) {
2937 $return .= '<br><div class="info-box-status">' . $this->getLibStatut(3) . '</div>';
2938 }
2939 $return .= '</div>';
2940 $return .= '</div>';
2941 $return .= '</div>';
2942 return $return;
2943 }
2944
2951 {
2952 if (!empty($this->id)) {
2953 $id = $this->id;
2954 } else {
2955 return 0;
2956 }
2957 if ($id) {
2958 $sql = "SELECT COUNT(*) AS nb FROM " . MAIN_DB_PREFIX . "prelevement_lignes";
2959 $sql .= " WHERE fk_prelevement_bons = " . ((int) $id);
2960 $sql .= " AND fk_soc = 0"; // fk_soc can't be NULL
2961 $sql .= " AND fk_user IS NOT NULL";
2962
2963 $num = 0;
2964 $resql = $this->db->query($sql);
2965 if ($resql) {
2966 $obj = $this->db->fetch_object($resql);
2967 $num = $obj->nb;
2968 }
2969 if ($num > 0) {
2970 return 1;
2971 }
2972 } else {
2973 dol_print_error($this->db);
2974 }
2975
2976 return 0;
2977 }
2978}
checkIbanForAccount($account=null, $ibantocheck=null)
Check IBAN number information for a bank account.
Definition bank.lib.php:342
checkSwiftForAccount($account=null, $swift=null)
Check SWIFT information for a bank account.
Definition bank.lib.php:321
$object ref
Definition info.php:89
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.
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 clickable 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=0, $notrigger=0, $type='direct-debit', $did=0, $fk_bank_account=0, $sourcetype='invoice')
Create a BAN payment order:
generate(string $format='ALL', int $executiondate=0, string $type='direct-debit', int $fk_bank_account=0, int $forsalary=0, int $thirdpartyBANId=0)
Generate a direct debit or credit transfer file.
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.
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition index.php:171
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 a Dolibarr global constant string value.
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...
dolBECalculateStructuredCommunication($invoice_number, $invoice_type)
Calculate Structured Communication / BE Bank payment reference number.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:149
dolDecrypt($chain, $key='')
Decode a string with a symmetric encryption.