dolibarr 21.0.0-alpha
bonprelevement.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2004-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
4 * Copyright (C) 2010-2015 Juanjo Menent <jmenent@2byte.es>
5 * Copyright (C) 2010-2014 Laurent Destailleur <eldy@users.sourceforge.net>
6 * Copyright (C) 2014-2016 Ferran Marcet <fmarcet@2byte.es>
7 * Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
8 * Copyright (C) 2019 JC Prieto <jcprieto@virtual20.com><prietojc@gmail.com>
9 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
10 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <https://www.gnu.org/licenses/>.
24 */
25
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 = '', $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, 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 $entity = $type != 'bank-transfer' ? getEntity('invoice') : getEntity('supplier_invoice');
1093 $socOrUser = 'fk_soc';
1094 $societeOrUser = 'societe';
1095 } else {
1096 $entity = getEntity('salary');
1097 $sqlTable = 'salary';
1098 $socOrUser = 'fk_user';
1099 $societeOrUser = 'user';
1100 }
1101
1102 $sqlTable = $type != 'bank-transfer' ? "facture" : "facture_fourn";
1103
1104 // Check if there is an iban associated to bank transfer or if we take the default
1105 $sql = "SELECT fk_societe_rib";
1106 $sql .= " FROM " . $this->db->prefix() . "prelevement_demande as pd";
1107 $sql .= " LEFT JOIN " . $this->db->prefix() . $this->db->escape($sqlTable) . " as f ON f.rowid = pd.fk_".$this->db->escape($sqlTable);
1108 $sql .= " WHERE f.entity IN (" . $this->db->escape($entity) . ')';
1109
1110 $resql = $this->db->query($sql);
1111
1112 if (!$resql) {
1113 $this->error = $this->db->lasterror();
1114 dol_syslog(__METHOD__ . " Read fk_societe_rib error " . $this->db->lasterror(), LOG_ERR);
1115 return -1;
1116 }
1117 $societeRibID = 0;
1118 if ($resql->num_rows) {
1119 $obj = $this->db->fetch_object($resql);
1120 $societeRibID = $obj->fk_societe_rib;
1121 $this->db->free($resql);
1122 }
1123
1124 $datetimeprev = dol_now('gmt');
1125 // Choice of the date of the execution direct debit
1126 if (!empty($executiondate)) {
1127 $datetimeprev = $executiondate;
1128 }
1129
1130 $month = dol_print_date($datetimeprev, "%m", 'gmt');
1131 $year = dol_print_date($datetimeprev, "%Y", 'gmt');
1132
1133 $this->invoice_in_error = array();
1134 $this->thirdparty_in_error = array();
1135
1136 // Read invoices
1137 $factures = array();
1138 $factures_prev = array();
1139 $factures_result = array();
1140 $factures_prev_id = array();
1141 $factures_errors = array();
1142
1143 if (!$error) {
1144 dol_syslog(__METHOD__ . " Read invoices for did=" . ((int) $did), LOG_DEBUG);
1145
1146 $sql = "SELECT f.rowid, pd.rowid as pfdrowid";
1147 $sql .= ", f.".$this->db->escape($socOrUser);
1148 $sql .= ", pd.code_banque, pd.code_guichet, pd.number, pd.cle_rib";
1149 $sql .= ", pd.amount";
1150 if ($sourcetype != 'salary') {
1151 $sql .= ", s.nom as name";
1152 $sql .= ", f.ref, sr.bic, sr.iban_prefix, sr.frstrecur";
1153 } else {
1154 $sql .= ", CONCAT(s.firstname,' ',s.lastname) as name";
1155 $sql .= ", f.ref, sr.bic, sr.iban_prefix, 'FRST' as frstrecur";
1156 }
1157 $sql .= " FROM " . $this->db->prefix() . $sqlTable . " as f";
1158 $sql .= " LEFT JOIN " . $this->db->prefix() . "prelevement_demande as pd ON f.rowid = pd.fk_".$this->db->escape($sqlTable);
1159 $sql .= " LEFT JOIN " . $this->db->prefix() . $societeOrUser." as s ON s.rowid = f.".$this->db->escape($socOrUser);
1160 $sql .= " LEFT JOIN " . $this->db->prefix() . $societeOrUser."_rib as sr ON s.rowid = sr.".$this->db->escape($socOrUser);
1161 if ($sourcetype != 'salary') {
1162 if (!empty($societeRibID)) {
1163 $sql .= " AND sr.rowid = " . intval($societeRibID);
1164 } else {
1165 $sql .= " AND sr.default_rib = 1";
1166 }
1167 // 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
1168 // 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.
1169 }
1170 $sql .= " WHERE f.entity IN (" . $this->db->escape($entity) . ')';
1171 if ($sourcetype != 'salary') {
1172 $sql .= " AND f.fk_statut = 1"; // Invoice validated
1173 $sql .= " AND f.paye = 0";
1174 $sql .= " AND f.total_ttc > 0";
1175 } else {
1176 //$sql .= " AND f.fk_statut = 1"; // Invoice validated
1177 $sql .= " AND f.paye = 0";
1178 $sql .= " AND f.amount > 0";
1179 }
1180 $sql .= " AND pd.traite = 0";
1181 $sql .= " AND pd.ext_payment_id IS NULL";
1182 if ($sourcetype != 'salary') {
1183 $sql .= " AND sr.type = 'ban'"; // TODO Add AND sr.type = 'ban' for users too
1184 }
1185 if ($did > 0) {
1186 $sql .= " AND pd.rowid = " . ((int) $did);
1187 }
1188
1189 $resql = $this->db->query($sql);
1190 if ($resql) {
1191 $num = $this->db->num_rows($resql);
1192 $i = 0;
1193
1194 while ($i < $num) {
1195 $row = $this->db->fetch_row($resql); // TODO Replace with fetch_object()
1196 '@phan-var-force array<int<0,12>,string> $row';
1197 $factures[$i] = $row; // All fields
1198
1199 if ($row[7] == 0) {
1200 $error++;
1201 dol_syslog(__METHOD__ . " Read invoices/salary error Found a null amount", LOG_ERR);
1202 $this->invoice_in_error[$row[0]] = "Error for invoice or salary id " . $row[0] . ", found a null amount";
1203 break;
1204 }
1205 $i++;
1206 }
1207
1208 $this->db->free($resql);
1209 dol_syslog(__METHOD__ . " Read invoices/salary, " . $i . " invoices/salary to withdraw", LOG_DEBUG);
1210 } else {
1211 $this->error = $this->db->lasterror();
1212 dol_syslog(__METHOD__ . " Read invoices/salary error " . $this->db->lasterror(), LOG_ERR);
1213 return -1;
1214 }
1215 }
1216
1217 if (!$error) {
1218 // Make some checks
1219 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
1220 require_once DOL_DOCUMENT_ROOT . '/user/class/user.class.php';
1221 require_once DOL_DOCUMENT_ROOT . '/societe/class/companybankaccount.class.php';
1222 require_once DOL_DOCUMENT_ROOT . '/core/lib/bank.lib.php';
1223
1224 $tmpsoc = new Societe($this->db);
1225 $tmpuser = new User($this->db);
1226
1227 // Check BAN
1228 $i = 0;
1229 dol_syslog(__METHOD__ . " Check BAN", LOG_DEBUG);
1230
1231 if (count($factures) > 0) {
1232 foreach ($factures as $key => $fac) {
1233 /*
1234 if ($type != 'bank-transfer') {
1235 $tmpinvoice = new Facture($this->db);
1236 } else {
1237 $tmpinvoice = new FactureFournisseur($this->db);
1238 }
1239 $resfetch = $tmpinvoice->fetch($fac[0]);
1240 if ($resfetch >= 0) { // Field 0 of $fac is rowid of invoice
1241 */
1242
1243 // Check if $fac[8] s.nom is null
1244 if ($fac[8] != null) {
1245 if ($type != 'bank-transfer') {
1246 if ($format == 'FRST' && $fac[12] != 'FRST') {
1247 continue;
1248 }
1249 if ($format == 'RCUR' && $fac[12] != 'RCUR') {
1250 continue;
1251 }
1252 }
1253
1254 $verif = checkSwiftForAccount(null, $fac[10]);
1255 if ($verif || (empty($fac[10]) && getDolGlobalInt("WITHDRAWAL_WITHOUT_BIC"))) {
1256 $verif = checkIbanForAccount(null, $fac[11]);
1257 }
1258
1259 if ($verif) {
1260 $factures_prev[$i] = $fac;
1261 /* second array necessary for BonPrelevement */
1262 $factures_prev_id[$i] = $fac[0];
1263 $i++;
1264 //dol_syslog(__METHOD__."::RIB is ok", LOG_DEBUG);
1265 } else {
1266 if ($type != 'bank-transfer') {
1267 $tmpsoc->id = (int) $fac[2];
1268 $tmpsoc->name = $fac[8];
1269 $invoice_url = "<a href='" . DOL_URL_ROOT . '/compta/facture/card.php?facid=' . $fac[0] . "'>" . $fac[9] . "</a>";
1270 $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1271 $this->thirdparty_in_error[$tmpsoc->id] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1272 $error++;
1273 }
1274 if ($type == 'bank-transfer' && $sourcetype != 'salary') {
1275 $tmpsoc->id = (int) $fac[2];
1276 $tmpsoc->name = $fac[8];
1277 $invoice_url = "<a href='" . DOL_URL_ROOT . '/fourn/facture/card.php?facid=' . $fac[0] . "'>" . $fac[9] . "</a>";
1278 $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1279 $this->thirdparty_in_error[$tmpsoc->id] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1280 $error++;
1281 }
1282 if ($type == 'bank-transfer' && $sourcetype == 'salary') {
1283 $tmpuser->id = (int) $fac[2];
1284 $tmpuser->firstname = $fac[8];
1285 $salary_url = "<a href='" . DOL_URL_ROOT . '/salaries/card.php?id=' . $fac[0] . "'>" . $fac[0] . "</a>";
1286 $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for salary " . $salary_url . " for employee " . $tmpuser->getNomUrl(0);
1287 $this->thirdparty_in_error[$tmpuser->id] = "Error on default bank number IBAN/BIC for salary " . $salary_url . " for employee " . $tmpuser->getNomUrl(0);
1288 $error++;
1289 }
1290 dol_syslog(__METHOD__ . " Check BAN Error on default bank number IBAN/BIC reported by verif(): " . implode(', ', $fac), LOG_WARNING);
1291 }
1292 } else {
1293 dol_syslog(__METHOD__ . " Check BAN Failed to read company", LOG_WARNING);
1294 }
1295 /*
1296 } else {
1297 dol_syslog(__METHOD__." Check BAN Failed to read invoice", LOG_WARNING);
1298 }
1299 */
1300 }
1301 } else {
1302 dol_syslog(__METHOD__ . " Check BAN No invoice to process", LOG_WARNING);
1303 }
1304 }
1305
1306 $ok = 0;
1307
1308 // Withdraw invoices in factures_prev array
1309 $out = count($factures_prev) . " invoices will be included.";
1310 //print $out."\n";
1311 dol_syslog($out);
1312
1313 // Return warning
1314 /*$i=0;
1315 foreach ($this->thirdparty_in_error as $key => $val)
1316 {
1317 if ($i < 10) setEventMessages($val, null, 'warnings');
1318 else setEventMessages('More error were discarded...', null, 'warnings');
1319 $i++;
1320 }*/
1321
1322 if (count($factures_prev) > 0) {
1323 if ($mode == 'real') {
1324 $ok = 1;
1325 } else {
1326 print $langs->trans("ModeWarning"); // "Option for real mode was not set, we stop after this simulation\n";
1327 }
1328 }
1329 if ($ok) {
1330 /*
1331 * We are in real mode.
1332 * We create order and build file into disk
1333 */
1334 $this->db->begin();
1335
1336 $now = dol_now();
1337 $ref = '';
1338
1339 /*
1340 * Process order generation
1341 */
1342 if (!$error) {
1343 $ref = substr($year, -2) . $month;
1344
1345 // Get next free number for the ref of bon prelevement
1346 $sql = "SELECT substring(ref from char_length(ref) - 1)"; // To extract "YYMMXX" from "TYYMMXX"
1347 $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons";
1348 $sql .= " WHERE ref LIKE '_" . $this->db->escape($ref) . "%'";
1349 $sql .= " AND entity = " . ((int) $conf->entity);
1350 $sql .= " ORDER BY ref DESC LIMIT 1";
1351
1352 dol_syslog(get_class($this) . " get next free number", LOG_DEBUG);
1353 $resql = $this->db->query($sql);
1354
1355 if ($resql) {
1356 $row = $this->db->fetch_row($resql);
1357
1358 // Build the new ref
1359 $ref = "T" . $ref . sprintf("%02d", (intval($row[0]) + 1));
1360
1361 // $conf->abc->dir_output may be:
1362 // /home/ldestailleur/git/dolibarr_15.0/documents/abc/
1363 // or
1364 // /home/ldestailleur/git/dolibarr_15.0/documents/X/abc with X >= 2 with multicompany.
1365 if ($type != 'bank-transfer') {
1366 $dir = $conf->prelevement->dir_output . '/receipts';
1367 } else {
1368 $dir = $conf->paymentbybanktransfer->dir_output . '/receipts';
1369 }
1370 if (!is_dir($dir)) {
1371 dol_mkdir($dir);
1372 }
1373
1374 if (isModEnabled('multicompany')) {
1375 $labelentity = $conf->entity;
1376 $this->filename = $dir . '/' . $ref . '-' . $labelentity . '.xml';
1377 } else {
1378 $this->filename = $dir . '/' . $ref . '.xml';
1379 }
1380
1381 // Create withdraw order in database
1382 $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_bons (";
1383 $sql .= "ref, entity, datec, type, fk_bank_account";
1384 $sql .= ") VALUES (";
1385 $sql .= "'" . $this->db->escape($ref) . "'";
1386 $sql .= ", " . ((int) $conf->entity);
1387 $sql .= ", '" . $this->db->idate($now) . "'";
1388 $sql .= ", '" . ($type == 'bank-transfer' ? 'bank-transfer' : 'debit-order') . "'";
1389 $sql .= ", " . ((int) $fk_bank_account);
1390 $sql .= ")";
1391
1392 $resql = $this->db->query($sql);
1393
1394
1395 if ($resql) {
1396 $prev_id = $this->db->last_insert_id(MAIN_DB_PREFIX . "prelevement_bons");
1397 $this->id = $prev_id;
1398 $this->ref = $ref;
1399 } else {
1400 $error++;
1401 dol_syslog(__METHOD__ . " Create withdraw receipt " . $this->db->lasterror(), LOG_ERR);
1402 }
1403 } else {
1404 $error++;
1405 dol_syslog(__METHOD__ . " Get last withdraw receipt " . $this->db->lasterror(), LOG_ERR);
1406 }
1407 }
1408
1409 if (!$error) {
1410 dol_syslog(__METHOD__ . " Now loop on each document to insert them in llx_prelevement_demande");
1411
1412 // Add lines for the bon
1413 if (count($factures_prev) > 0) {
1414 foreach ($factures_prev as $fac) { // Add a link in database for each invoice ro salary
1415 /*
1416 * Add standing order. This add record into llx_prelevement_lignes and llx_prelevement
1417 *
1418 * $fac[0] : invoice_id
1419 * $fac[1] : ???
1420 * $fac[2] : third party id
1421 * $fac[3] : banque
1422 * $fac[4] : guichet
1423 * $fac[5] : number
1424 * $fac[6] : cle rib
1425 * $fac[7] : amount
1426 * $fac[8] : client nom
1427 * $fac[9] : Invoice ref
1428 * $fac[10] : BIC
1429 * $fac[11] : IBAN
1430 * $fac[12] : frstrcur
1431 */
1432 $ri = $this->AddFacture($fac[0], $fac[2], $fac[8], $fac[7], $fac[3], $fac[4], $fac[5], $fac[6], $type, $sourcetype);
1433
1434 if ($ri != 0) {
1435 $error++;
1436 }
1437
1438 // Update invoice requests as done
1439 $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_demande";
1440 $sql .= " SET traite = 1";
1441 $sql .= ", date_traite = '" . $this->db->idate($now) . "'";
1442 $sql .= ", fk_prelevement_bons = " . ((int) $this->id);
1443 $sql .= " WHERE rowid = " . ((int) $fac[1]);
1444
1445 $resql = $this->db->query($sql);
1446 if (!$resql) {
1447 $error++;
1448 $this->errors[] = $this->db->lasterror();
1449 dol_syslog(__METHOD__ . " Update Error=" . $this->db->lasterror(), LOG_ERR);
1450 }
1451 }
1452 }
1453 }
1454
1455 if (!$error) {
1456 /*
1457 * Create file of type='direct-debit' for direct debit order or type='bank-transfer' for credit transfer into a XML file
1458 */
1459
1460 dol_syslog(__METHOD__ . " Init direct debit or credit transfer file for " . count($factures_prev) . " invoices", LOG_DEBUG);
1461
1462 if (count($factures_prev) > 0) {
1463 $this->date_echeance = $datetimeprev;
1464 $this->reference_remise = $ref;
1465
1466 $account = new Account($this->db);
1467 if ($account->fetch($fk_bank_account) > 0) {
1468 $this->emetteur_code_banque = $account->code_banque;
1469 $this->emetteur_code_guichet = $account->code_guichet;
1470 $this->emetteur_numero_compte = $account->number;
1471 $this->emetteur_number_key = $account->cle_rib;
1472 $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
1473 $this->emetteur_iban = $account->iban;
1474 $this->emetteur_bic = $account->bic;
1475
1476 $this->emetteur_ics = (($type == 'bank-transfer' && getDolGlobalString("SEPA_USE_IDS")) ? $account->ics_transfer : $account->ics); // Example "FR78ZZZ123456"
1477
1478 $this->raison_sociale = $account->owner_name;
1479 }
1480 $this->factures = $factures_prev_id;
1481 $this->context['factures_prev'] = $factures_prev;
1482 // Generation of direct debit or credit transfer file $this->filename (May be a SEPA file for european countries)
1483 // This also set the property $this->total with amount that is included into file
1484 $userid = 0;
1485 if ($sourcetype == 'salary') {
1486 $userid = $this->context['factures_prev'][0][2];
1487 }
1488 $result = $this->generate($format, $executiondate, $type, $fk_bank_account, $userid, $societeRibID);
1489 if ($result < 0) {
1490 //var_dump($this->error);
1491 //var_dump($this->invoice_in_error);
1492 $error++;
1493 }
1494 }
1495 dol_syslog(__METHOD__ . " Bank order file has been generated under filename " . $this->filename, LOG_DEBUG);
1496 }
1497
1498
1499 /*
1500 * Update total defined after generation of file
1501 */
1502 if (!$error) {
1503 $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_bons";
1504 $sql .= " SET amount = " . price2num($this->total);
1505 $sql .= " WHERE rowid = " . ((int) $this->id);
1506 $sql .= " AND entity = " . ((int) $conf->entity);
1507 $resql = $this->db->query($sql);
1508
1509 if (!$resql) {
1510 $error++;
1511 dol_syslog(__METHOD__ . " Error update total: " . $this->db->error(), LOG_ERR);
1512 }
1513 }
1514
1515 if (!$error && !$notrigger) {
1516 $triggername = 'DIRECT_DEBIT_ORDER_CREATE';
1517 if ($type != 'bank-transfer') {
1518 $triggername = 'CREDIT_TRANSFER_ORDER_CREATE';
1519 }
1520
1521 // Call trigger
1522 $result = $this->call_trigger($triggername, $user);
1523 if ($result < 0) {
1524 $error++;
1525 }
1526 // End call triggers
1527 }
1528
1529 if (!$error) {
1530 $this->db->commit();
1531 return count($factures_prev); // The error of failed lines are into $this->invoice_in_error and $this->thirdparty_in_error
1532 } else {
1533 $this->db->rollback();
1534 return -1;
1535 }
1536 } else {
1537 return 0;
1538 }
1539 }
1540
1541
1549 public function delete($user = null, $notrigger = 0)
1550 {
1551 $this->db->begin();
1552
1553 $error = 0;
1554 $resql1 = $resql2 = $resql3 = $resql4 = 0;
1555
1556 if (!$notrigger) {
1557 $triggername = 'DIRECT_DEBIT_ORDER_DELETE';
1558 if ($this->type == 'bank-transfer') {
1559 $triggername = 'PAYMENTBYBANKTRANFER_DELETE';
1560 }
1561 // Call trigger
1562 $result = $this->call_trigger($triggername, $user);
1563 if ($result < 0) {
1564 $error++;
1565 }
1566 // End call triggers
1567 }
1568
1569 if (!$error) {
1570 $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) . ")";
1571 $resql1 = $this->db->query($sql);
1572 if (!$resql1) {
1573 dol_print_error($this->db);
1574 }
1575 }
1576
1577 if (!$error) {
1578 $sql = "DELETE FROM " . MAIN_DB_PREFIX . "prelevement_lignes WHERE fk_prelevement_bons = " . ((int) $this->id);
1579 $resql2 = $this->db->query($sql);
1580 if (!$resql2) {
1581 dol_print_error($this->db);
1582 }
1583 }
1584
1585 if (!$error) {
1586 $sql = "DELETE FROM " . MAIN_DB_PREFIX . "prelevement_bons WHERE rowid = " . ((int) $this->id);
1587 $resql3 = $this->db->query($sql);
1588 if (!$resql3) {
1589 dol_print_error($this->db);
1590 }
1591 }
1592
1593 if (!$error) {
1594 $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_demande SET fk_prelevement_bons = NULL, traite = 0 WHERE fk_prelevement_bons = " . ((int) $this->id);
1595 $resql4 = $this->db->query($sql);
1596 if (!$resql4) {
1597 dol_print_error($this->db);
1598 }
1599 }
1600
1601 if ($resql1 && $resql2 && $resql3 && $resql4 && !$error) {
1602 $this->db->commit();
1603 return 1;
1604 } else {
1605 $this->db->rollback();
1606 return -1;
1607 }
1608 }
1609
1610
1621 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1622 {
1623 global $conf, $langs, $hookmanager;
1624
1625 if (!empty($conf->dol_no_mouse_hover)) {
1626 $notooltip = 1; // Force disable tooltips
1627 }
1628
1629 $result = '';
1630
1631 $labeltoshow = 'PaymentByDirectDebit';
1632 if (!empty($this->type) && $this->type == 'bank-transfer') {
1633 $labeltoshow = 'PaymentByBankTransfer';
1634 }
1635
1636 $label = img_picto('', $this->picto) . ' <u>' . $langs->trans($labeltoshow) . '</u> ' . $this->getLibStatut(5);
1637 $label .= '<br>';
1638 $label .= '<b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
1639 if (isset($this->amount)) {
1640 $label .= '<br><b>' . $langs->trans("Amount") . ":</b> " . price($this->amount);
1641 }
1642 if (isset($this->date_trans)) {
1643 $label .= '<br><b>' . $langs->trans("TransData") . ":</b> " . dol_print_date($this->date_trans, 'dayhour', 'tzuserrel');
1644 }
1645 /*if (isset($this->date_credit)) {
1646 $label .= '<br><b>'.$langs->trans("TransData").":</b> ".dol_print_date($this->date_credit, 'dayhour', 'tzuserrel');
1647 }*/
1648
1649 $url = DOL_URL_ROOT . '/compta/prelevement/card.php?id=' . $this->id;
1650 if (!empty($this->type) && $this->type == 'bank-transfer') {
1651 $url = DOL_URL_ROOT . '/compta/prelevement/card.php?id=' . $this->id;
1652 }
1653
1654 if ($option != 'nolink') {
1655 // Add param to save lastsearch_values or not
1656 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1657 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1658 $add_save_lastsearch_values = 1;
1659 }
1660 if ($add_save_lastsearch_values) {
1661 $url .= '&save_lastsearch_values=1';
1662 }
1663 }
1664
1665 $linkclose = '';
1666 if (empty($notooltip)) {
1667 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1668 $label = $langs->trans("ShowMyObject");
1669 $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
1670 }
1671 $linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"';
1672 $linkclose .= ' class="classfortooltip' . ($morecss ? ' ' . $morecss : '') . '"';
1673 } else {
1674 $linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
1675 }
1676
1677 $linkstart = '<a href="' . $url . '"';
1678 $linkstart .= $linkclose . '>';
1679 $linkend = '</a>';
1680
1681 $result .= $linkstart;
1682 if ($withpicto) {
1683 $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);
1684 }
1685 if ($withpicto != 2) {
1686 $result .= $this->ref;
1687 }
1688 $result .= $linkend;
1689
1690 global $action, $hookmanager;
1691 $hookmanager->initHooks(array('banktransferdao'));
1692 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1693 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1694 if ($reshook > 0) {
1695 $result = $hookmanager->resPrint;
1696 } else {
1697 $result .= $hookmanager->resPrint;
1698 }
1699
1700 return $result;
1701 }
1702
1703
1710 public function deleteNotificationById($rowid)
1711 {
1712 $sql = "DELETE FROM " . MAIN_DB_PREFIX . "notify_def";
1713 $sql .= " WHERE rowid = " . ((int) $rowid);
1714
1715 if ($this->db->query($sql)) {
1716 return 0;
1717 } else {
1718 return -1;
1719 }
1720 }
1721
1729 public function deleteNotification($user, $action)
1730 {
1731 if (is_object($user)) {
1732 $userid = $user->id;
1733 } else { // If user is an id
1734 $userid = $user;
1735 }
1736
1737 $sql = "DELETE FROM " . MAIN_DB_PREFIX . "notify_def";
1738 $sql .= " WHERE fk_user=" . ((int) $userid) . " AND fk_action='" . $this->db->escape($action) . "'";
1739
1740 if ($this->db->query($sql)) {
1741 return 0;
1742 } else {
1743 return -1;
1744 }
1745 }
1746
1747 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1756 public function addNotification($db, $user, $action)
1757 {
1758 // phpcs:enable
1759 $result = 0;
1760
1761 if (is_object($user)) {
1762 $userid = $user->id;
1763 } else { // If user is an id
1764 $userid = $user;
1765 }
1766
1767 if ($this->deleteNotification($user, $action) == 0) {
1768 $now = dol_now();
1769
1770 $sql = "INSERT INTO " . MAIN_DB_PREFIX . "notify_def (datec,fk_user, fk_soc, fk_contact, fk_action)";
1771 $sql .= " VALUES ('" . $this->db->idate($now) . "', " . ((int) $userid) . ", 'NULL', 'NULL', '" . $this->db->escape($action) . "')";
1772
1773 dol_syslog("adnotiff: " . $sql);
1774 if ($this->db->query($sql)) {
1775 $result = 0;
1776 } else {
1777 $result = -1;
1778 dol_syslog(get_class($this) . "::addNotification Error $result");
1779 }
1780 }
1781
1782 return $result;
1783 }
1784
1785
1801 public function generate(string $format = 'ALL', int $executiondate = 0, string $type = 'direct-debit', int $fk_bank_account = 0, int $forsalary = 0, string $societeRibID = '')
1802 {
1803 global $conf, $langs, $mysoc;
1804
1805 //TODO: Optimize code to read lines in a single function
1806
1807 // Clean params
1808 if (empty($fk_bank_account)) {
1809 $fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
1810 }
1811
1812 $result = 0;
1813
1814 dol_syslog(get_class($this) . "::generate build file=" . $this->filename . " type=" . $type);
1815
1816 $this->file = fopen($this->filename, "w");
1817 if ($this->file == false) {
1818 $this->error = $langs->trans('ErrorFailedToOpenFile', $this->filename);
1819 return -1;
1820 }
1821
1822 $found = 0;
1823 $this->total = 0;
1824
1825 // Build file for European countries
1826 if ($mysoc->isInEEC()) {
1827 $found++;
1828
1829 if ($type != 'bank-transfer') {
1833 // SEPA Initialisation
1834 $CrLf = "\n";
1835
1836 $now = dol_now();
1837
1838 $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S');
1839
1840 $date_actu = $now;
1841 if (!empty($executiondate)) {
1842 $date_actu = $executiondate;
1843 }
1844
1845 $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d');
1846 $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S');
1847 $fileDebiteurSection = '';
1848 $fileEmetteurSection = '';
1849 $i = 0;
1850
1851 /*
1852 * Section Debitor (sepa Debiteurs block lines)
1853 */
1854
1855 $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
1856 $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1857 $sql .= " f.ref as reffac, p.fk_facture as idfac,";
1858 $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
1859 $sql .= " FROM";
1860 $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1861 $sql .= " " . MAIN_DB_PREFIX . "facture as f,";
1862 $sql .= " " . MAIN_DB_PREFIX . "prelevement as p,";
1863 $sql .= " " . MAIN_DB_PREFIX . "societe as soc,";
1864 $sql .= " " . MAIN_DB_PREFIX . "c_country as c,";
1865 $sql .= " " . MAIN_DB_PREFIX . "societe_rib as rib";
1866 $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
1867 $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1868 $sql .= " AND p.fk_facture = f.rowid";
1869 $sql .= " AND f.fk_soc = soc.rowid";
1870 $sql .= " AND soc.fk_pays = c.rowid";
1871 $sql .= " AND rib.fk_soc = f.fk_soc";
1872 if (!empty($societeRibID)) {
1873 $sql .= " AND rib.rowid = " . intval($societeRibID);
1874 } else {
1875 $sql .= " AND rib.default_rib = 1";
1876 }
1877 $sql .= " AND rib.type = 'ban'";
1878
1879 // Define $fileDebiteurSection. One section DrctDbtTxInf per invoice.
1880 $resql = $this->db->query($sql);
1881 $nbtotalDrctDbtTxInf = -1;
1882 if ($resql) {
1883 $cachearraytotestduplicate = array();
1884
1885 $num = $this->db->num_rows($resql);
1886 while ($i < $num) {
1887 $obj = $this->db->fetch_object($resql);
1888
1889 if (!empty($cachearraytotestduplicate[$obj->idfac])) {
1890 $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
1891 $this->invoice_in_error[$obj->idfac] = $this->error;
1892 $result = -2;
1893 break;
1894 }
1895 $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
1896
1897 $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
1898
1899 $fileDebiteurSection .= $this->EnregDestinataireSEPA($obj->code, $obj->nom, $obj->address, $obj->zip, $obj->town, $obj->country_code, $obj->cb, $obj->cg, $obj->cc, $obj->somme, $obj->reffac, $obj->idfac, $obj->iban, $obj->bic, $daterum, $obj->drum, $obj->rum, $type);
1900
1901 $this->total += $obj->somme;
1902 $i++;
1903 }
1904 $nbtotalDrctDbtTxInf = $i;
1905 } else {
1906 $this->error = $this->db->lasterror();
1907 fwrite($this->file, 'ERROR DEBITOR ' . $sql . $CrLf); // DEBITOR = Customers
1908 $result = -2;
1909 }
1910
1911 // Define $fileEmetteurSection. Start of block PmtInf. Will contains all $nbtotalDrctDbtTxInf
1912 if ($result != -2) {
1913 $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type, $fk_bank_account);
1914 }
1915
1916 if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) {
1917 $this->total = number_format((float) price2num($this->total, 'MT'), 2, ".", "");
1918 }
1919
1923 // SEPA File Header
1924 fwrite($this->file, '<' . '?xml version="1.0" encoding="UTF-8" standalone="yes"?' . '>' . $CrLf);
1925 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);
1926 fwrite($this->file, ' <CstmrDrctDbtInitn>' . $CrLf);
1927 // SEPA Group header
1928 fwrite($this->file, ' <GrpHdr>' . $CrLf);
1929 fwrite($this->file, ' <MsgId>' . ('DD/' . $dateTime_YMD . '/REF' . $this->id) . '</MsgId>' . $CrLf);
1930 fwrite($this->file, ' <CreDtTm>' . $dateTime_ECMA . '</CreDtTm>' . $CrLf);
1931 fwrite($this->file, ' <NbOfTxs>' . $i . '</NbOfTxs>' . $CrLf);
1932 fwrite($this->file, ' <CtrlSum>' . $this->total . '</CtrlSum>' . $CrLf);
1933 fwrite($this->file, ' <InitgPty>' . $CrLf);
1934 fwrite($this->file, ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf);
1935 fwrite($this->file, ' <Id>' . $CrLf);
1936 fwrite($this->file, ' <PrvtId>' . $CrLf);
1937 fwrite($this->file, ' <Othr>' . $CrLf);
1938 fwrite($this->file, ' <Id>' . $this->emetteur_ics . '</Id>' . $CrLf);
1939 fwrite($this->file, ' </Othr>' . $CrLf);
1940 fwrite($this->file, ' </PrvtId>' . $CrLf);
1941 fwrite($this->file, ' </Id>' . $CrLf);
1942 fwrite($this->file, ' </InitgPty>' . $CrLf);
1943 fwrite($this->file, ' </GrpHdr>' . $CrLf);
1944 // SEPA File Emetteur
1945 if ($result != -2) {
1946 fwrite($this->file, $fileEmetteurSection);
1947 }
1948 // SEPA File Debiteurs
1949 if ($result != -2) {
1950 fwrite($this->file, $fileDebiteurSection);
1951 }
1952 // SEPA FILE FOOTER
1953 fwrite($this->file, ' </PmtInf>' . $CrLf);
1954 fwrite($this->file, ' </CstmrDrctDbtInitn>' . $CrLf);
1955 fwrite($this->file, '</Document>' . $CrLf);
1956 } else {
1960 // SEPA Initialisation
1961 $CrLf = "\n";
1962
1963 $now = dol_now();
1964
1965 $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S');
1966
1967 $date_actu = $now;
1968 if (!empty($executiondate)) {
1969 $date_actu = $executiondate;
1970 }
1971
1972 $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d');
1973 $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S');
1974 $fileCrediteurSection = '';
1975 $fileEmetteurSection = '';
1976 $i = 0;
1977
1978 /*
1979 * Section Creditor (sepa Crediteurs block lines)
1980 */
1981 if (!empty($forsalary)) {
1982 $sql = "SELECT u.rowid as userId, u.address, u.zip, u.town, c.code as country_code, CONCAT(u.firstname,' ',u.lastname) as nom,";
1983 $sql .= " pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1984 $sql .= " s.ref as reffac, p.fk_salary as idfac,";
1985 $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, '' as rum, '' as date_rum";
1986 $sql .= " FROM";
1987 $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1988 $sql .= " " . MAIN_DB_PREFIX . "salary as s,";
1989 $sql .= " " . MAIN_DB_PREFIX . "prelevement as p,";
1990 $sql .= " " . MAIN_DB_PREFIX . "user as u";
1991 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_country as c ON u.fk_country = c.rowid,";
1992 $sql .= " " . MAIN_DB_PREFIX . "user_rib as rib";
1993 $sql .= " WHERE pl.fk_prelevement_bons=" . ((int) $this->id);
1994 $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1995 $sql .= " AND p.fk_salary = s.rowid";
1996 $sql .= " AND s.fk_user = u.rowid";
1997 $sql .= " AND rib.fk_user = s.fk_user";
1998 } else {
1999 $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
2000 $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
2001 $sql .= " f.ref as reffac, f.ref_supplier as fac_ref_supplier, p.fk_facture_fourn as idfac,";
2002 $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
2003 $sql .= " FROM";
2004 $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
2005 $sql .= " " . MAIN_DB_PREFIX . "facture_fourn as f,";
2006 $sql .= " " . MAIN_DB_PREFIX . "prelevement as p,";
2007 $sql .= " " . MAIN_DB_PREFIX . "societe as soc";
2008 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_country as c ON soc.fk_pays = c.rowid,";
2009 $sql .= " " . MAIN_DB_PREFIX . "societe_rib as rib";
2010 $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
2011 $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
2012 $sql .= " AND p.fk_facture_fourn = f.rowid";
2013 $sql .= " AND f.fk_soc = soc.rowid";
2014 $sql .= " AND rib.fk_soc = f.fk_soc";
2015 if (!empty($societeRibID)) {
2016 $sql .= " AND rib.rowid = " . intval($societeRibID);
2017 } else {
2018 $sql .= " AND rib.default_rib = 1";
2019 }
2020 $sql .= " AND rib.type = 'ban'";
2021 }
2022 // Define $fileCrediteurSection. One section DrctDbtTxInf per invoice.
2023 $nbtotalDrctDbtTxInf = -1;
2024
2025 $resql = $this->db->query($sql);
2026 if ($resql) {
2027 $cachearraytotestduplicate = array();
2028
2029 $num = $this->db->num_rows($resql);
2030 while ($i < $num) {
2031 $obj = $this->db->fetch_object($resql);
2032 if (!empty($cachearraytotestduplicate[$obj->idfac])) {
2033 $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
2034 $this->invoice_in_error[$obj->idfac] = $this->error;
2035 $result = -2;
2036 break;
2037 }
2038 $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
2039
2040 $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
2041 $refobj = $obj->reffac;
2042 if (empty($refobj) && !empty($forsalary)) { // If ref of salary not defined, we force a value
2043 $refobj = "SAL" . $obj->idfac;
2044 }
2045
2046 $fileCrediteurSection .= $this->EnregDestinataireSEPA($obj->code, $obj->nom, $obj->address, $obj->zip, $obj->town, $obj->country_code, $obj->cb, $obj->cg, $obj->cc, $obj->somme, $refobj, $obj->idfac, $obj->iban, $obj->bic, $daterum, $obj->drum, $obj->rum, $type, $obj->fac_ref_supplier);
2047
2048 $this->total += $obj->somme;
2049 $i++;
2050 }
2051 $nbtotalDrctDbtTxInf = $i;
2052 } else {
2053 $this->error = $this->db->lasterror();
2054 fwrite($this->file, 'ERROR CREDITOR ' . $sql . $CrLf); // CREDITORS = Suppliers
2055 $result = -2;
2056 }
2057 // Define $fileEmetteurSection. Start of block PmtInf. Will contains all $nbtotalDrctDbtTxInf
2058 if ($result != -2) {
2059 $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type);
2060 }
2061
2062 if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) {
2063 $this->total = number_format((float) price2num($this->total, 'MT'), 2, ".", "");
2064 }
2065
2069 // SEPA File Header
2070 fwrite($this->file, '<' . '?xml version="1.0" encoding="UTF-8" standalone="yes"?' . '>' . $CrLf);
2071 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);
2072 fwrite($this->file, ' <CstmrCdtTrfInitn>' . $CrLf);
2073 // SEPA Group header
2074 fwrite($this->file, ' <GrpHdr>' . $CrLf);
2075 fwrite($this->file, ' <MsgId>' . ('TRF/' . $dateTime_YMD . '/REF' . $this->id) . '</MsgId>' . $CrLf);
2076 fwrite($this->file, ' <CreDtTm>' . $dateTime_ECMA . '</CreDtTm>' . $CrLf);
2077 fwrite($this->file, ' <NbOfTxs>' . $i . '</NbOfTxs>' . $CrLf);
2078 fwrite($this->file, ' <CtrlSum>' . $this->total . '</CtrlSum>' . $CrLf);
2079 fwrite($this->file, ' <InitgPty>' . $CrLf);
2080 fwrite($this->file, ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf);
2081 fwrite($this->file, ' <Id>' . $CrLf);
2082 fwrite($this->file, ' <PrvtId>' . $CrLf);
2083 fwrite($this->file, ' <Othr>' . $CrLf);
2084 fwrite($this->file, ' <Id>' . $this->emetteur_ics . '</Id>' . $CrLf);
2085 fwrite($this->file, ' </Othr>' . $CrLf);
2086 fwrite($this->file, ' </PrvtId>' . $CrLf);
2087 fwrite($this->file, ' </Id>' . $CrLf);
2088 fwrite($this->file, ' </InitgPty>' . $CrLf);
2089 fwrite($this->file, ' </GrpHdr>' . $CrLf);
2090 // SEPA File Emetteur (mycompany)
2091 if ($result != -2) {
2092 fwrite($this->file, $fileEmetteurSection);
2093 }
2094 // SEPA File Creditors
2095 if ($result != -2) {
2096 fwrite($this->file, $fileCrediteurSection);
2097 }
2098 // SEPA FILE FOOTER
2099 fwrite($this->file, ' </PmtInf>' . $CrLf);
2100 fwrite($this->file, ' </CstmrCdtTrfInitn>' . $CrLf);
2101 fwrite($this->file, '</Document>' . $CrLf);
2102 }
2103 }
2104
2105 // Build file for Other Countries with unknown format
2106 if (!$found) {
2107 if ($type != 'bank-transfer') {
2108 $sql = "SELECT pl.amount";
2109 $sql .= " FROM";
2110 $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
2111 $sql .= " " . MAIN_DB_PREFIX . "facture as f,";
2112 $sql .= " " . MAIN_DB_PREFIX . "prelevement as p";
2113 $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
2114 $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
2115 $sql .= " AND p.fk_facture = f.rowid";
2116
2117 // Lines
2118 $i = 0;
2119 $resql = $this->db->query($sql);
2120 if ($resql) {
2121 $num = $this->db->num_rows($resql);
2122
2123 while ($i < $num) {
2124 $obj = $this->db->fetch_object($resql);
2125 $this->total += $obj->amount;
2126
2127 // TODO Write record into file
2128 $i++;
2129 }
2130 } else {
2131 $result = -2;
2132 }
2133 } else {
2134 $sql = "SELECT pl.amount";
2135 $sql .= " FROM";
2136 $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
2137 $sql .= " " . MAIN_DB_PREFIX . "facture_fourn as f,";
2138 $sql .= " " . MAIN_DB_PREFIX . "prelevement as p";
2139 $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
2140 $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
2141 $sql .= " AND p.fk_facture_fourn = f.rowid";
2142 // Lines
2143 $i = 0;
2144 $resql = $this->db->query($sql);
2145 if ($resql) {
2146 $num = $this->db->num_rows($resql);
2147
2148 while ($i < $num) {
2149 $obj = $this->db->fetch_object($resql);
2150 $this->total += $obj->amount;
2151
2152 // TODO Write record into file
2153 $i++;
2154 }
2155 } else {
2156 $result = -2;
2157 }
2158 }
2159
2160 $langs->load('withdrawals');
2161
2162 // TODO Add here code to generate a generic file
2163 fwrite($this->file, $langs->transnoentitiesnoconv('WithdrawalFileNotCapable', $mysoc->country_code));
2164 }
2165
2166 fclose($this->file);
2167 dolChmod($this->filename);
2168
2169 return $result;
2170 }
2171
2172
2181 public static function buildRumNumber($row_code_client, $row_datec, $row_drum)
2182 {
2183 global $langs;
2184
2185 $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)
2186
2187 // 3 char + '-' + 12 + '-' + id + '-' + code Must be lower than 32.
2188 return $pre . '-' . dol_print_date($row_datec, 'dayhourlogsmall') . '-' . dol_trunc($row_drum . ($row_code_client ? '-' . $row_code_client : ''), 13, 'right', 'UTF-8', 1);
2189 }
2190
2191
2192 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2209 public function EnregDestinataire($rowid, $client_nom, $rib_banque, $rib_guichet, $rib_number, $amount, $ref, $facid, $rib_dom = '', $type = 'direct-debit')
2210 {
2211 // phpcs:enable
2212 fwrite($this->file, "06");
2213 fwrite($this->file, "08"); // Prelevement ordinaire
2214
2215 fwrite($this->file, " "); // Zone Reservee B2
2216
2217 fwrite($this->file, $this->emetteur_ics); // ICS
2218
2219 // Date d'echeance C1
2220
2221 fwrite($this->file, " ");
2222 fwrite($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
2223 fwrite($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
2224
2225 // Raison Sociale Destinataire C2
2226
2227 fwrite($this->file, substr(strtoupper($client_nom) . " ", 0, 24));
2228
2229 // Address optional D1
2230 $address = strtr($rib_dom, array(" " => "-", chr(13) => " ", chr(10) => ""));
2231 fwrite($this->file, substr($address . " ", 0, 24));
2232
2233 // Zone Reservee D2
2234
2235 fwrite($this->file, substr(" ", 0, 8));
2236
2237 // Code Guichet D3
2238
2239 fwrite($this->file, $rib_guichet);
2240
2241 // Numero de compte D4
2242
2243 fwrite($this->file, substr("000000000000000" . $rib_number, -11));
2244
2245 // Zone E Montant
2246
2247 $montant = (round($amount, 2) * 100);
2248
2249 fwrite($this->file, substr("000000000000000" . $montant, -16));
2250
2251 // Label F
2252
2253 fwrite($this->file, substr("*_" . $ref . "_RDVnet" . $rowid . " ", 0, 31));
2254
2255 // Code etablissement G1
2256
2257 fwrite($this->file, $rib_banque);
2258
2259 // Zone Reservee G2
2260
2261 fwrite($this->file, substr(" ", 0, 5));
2262
2263 fwrite($this->file, "\n");
2264 }
2265
2266
2267 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2293 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 = '')
2294 {
2295 // phpcs:enable
2296 global $conf, $mysoc;
2297
2298 if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) {
2299 $row_somme = number_format((float) price2num($row_somme, 'MT'), 2, ".", "");
2300 } else {
2301 $row_somme = round((float) $row_somme, 2);
2302 }
2303
2304 include_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php';
2305
2306 $CrLf = "\n";
2307 $Rowing = sprintf("%010d", $row_idfac);
2308
2309 // Define value for RUM
2310 // Example: RUM-CustomerCode-CustomerBankAccountId-01424448606 (note: Date is the timestamp of the date of creation of CustomerBankAccountId)
2311 $Rum = (empty($row_rum) ? $this->buildRumNumber($row_code_client, $row_datec, $row_drum) : $row_rum);
2312
2313 // Define date of RUM signature
2314 $DtOfSgntr = dol_print_date($row_datec, '%Y-%m-%d');
2315
2316 if ($type != 'bank-transfer') {
2317 // SEPA Paiement Information of buyer for Direct Debit
2318 $XML_DEBITOR = '';
2319 $XML_DEBITOR .= ' <DrctDbtTxInf>' . $CrLf;
2320 $XML_DEBITOR .= ' <PmtId>' . $CrLf;
2321 // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
2322 $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
2323 $XML_DEBITOR .= ' </PmtId>' . $CrLf;
2324 $XML_DEBITOR .= ' <InstdAmt Ccy="EUR">' . $row_somme . '</InstdAmt>' . $CrLf;
2325 $XML_DEBITOR .= ' <DrctDbtTx>' . $CrLf;
2326 $XML_DEBITOR .= ' <MndtRltdInf>' . $CrLf;
2327 $XML_DEBITOR .= ' <MndtId>' . $Rum . '</MndtId>' . $CrLf;
2328 $XML_DEBITOR .= ' <DtOfSgntr>' . $DtOfSgntr . '</DtOfSgntr>' . $CrLf;
2329 $XML_DEBITOR .= ' <AmdmntInd>false</AmdmntInd>' . $CrLf;
2330 $XML_DEBITOR .= ' </MndtRltdInf>' . $CrLf;
2331 $XML_DEBITOR .= ' </DrctDbtTx>' . $CrLf;
2332 $XML_DEBITOR .= ' <DbtrAgt>' . $CrLf;
2333 $XML_DEBITOR .= ' <FinInstnId>' . $CrLf;
2334 if (getDolGlobalInt('WITHDRAWAL_WITHOUT_BIC') == 0) {
2335 $XML_DEBITOR .= ' <BIC>' . $row_bic . '</BIC>' . $CrLf;
2336 }
2337 $XML_DEBITOR .= ' </FinInstnId>' . $CrLf;
2338 $XML_DEBITOR .= ' </DbtrAgt>' . $CrLf;
2339 $XML_DEBITOR .= ' <Dbtr>' . $CrLf;
2340 $XML_DEBITOR .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))) . '</Nm>' . $CrLf;
2341 $XML_DEBITOR .= ' <PstlAdr>' . $CrLf;
2342 $XML_DEBITOR .= ' <Ctry>' . $row_country_code . '</Ctry>' . $CrLf;
2343 $addressline1 = strtr($row_address, array(chr(13) => ", ", chr(10) => ""));
2344 $addressline2 = strtr($row_zip . (($row_zip && $row_town) ? ' ' : (string) $row_town), array(chr(13) => ", ", chr(10) => ""));
2345 if (trim($addressline1)) {
2346 $XML_DEBITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2347 }
2348 if (trim($addressline2)) {
2349 $XML_DEBITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2350 }
2351 $XML_DEBITOR .= ' </PstlAdr>' . $CrLf;
2352 $XML_DEBITOR .= ' </Dbtr>' . $CrLf;
2353 $XML_DEBITOR .= ' <DbtrAcct>' . $CrLf;
2354 $XML_DEBITOR .= ' <Id>' . $CrLf;
2355 $XML_DEBITOR .= ' <IBAN>' . preg_replace('/\s/', '', $row_iban) . '</IBAN>' . $CrLf;
2356 $XML_DEBITOR .= ' </Id>' . $CrLf;
2357 $XML_DEBITOR .= ' </DbtrAcct>' . $CrLf;
2358 $XML_DEBITOR .= ' <RmtInf>' . $CrLf;
2359
2360 // Structured data for Belgium
2361 if (getDolGlobalString('INVOICE_PAYMENT_ENABLE_STRUCTURED_COMMUNICATION') && $mysoc->country_code == 'BE') {
2362 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions_be.lib.php';
2363
2364 $invoicestatic = new Facture($this->db);
2365 $invoicestatic->fetch($row_idfac);
2366
2367 $invoicePaymentKey = dolBECalculateStructuredCommunication($invoicestatic->ref, $invoicestatic->type);
2368 $XML_DEBITOR .= ' <strd>' . $invoicePaymentKey . '</strd>' . $CrLf;
2369 } else {
2370 // A string with some information on payment - 140 max
2371 $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
2372 }
2373 $XML_DEBITOR .= ' </RmtInf>' . $CrLf;
2374 $XML_DEBITOR .= ' </DrctDbtTxInf>' . $CrLf;
2375 return $XML_DEBITOR;
2376 } else {
2377 // SEPA Payment Information of seller for Credit Transfer
2378 $XML_CREDITOR = '';
2379 $XML_CREDITOR .= ' <CdtTrfTxInf>' . $CrLf;
2380 $XML_CREDITOR .= ' <PmtId>' . $CrLf;
2381 // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
2382 $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
2383 $XML_CREDITOR .= ' </PmtId>' . $CrLf;
2384 if (!empty($this->sepa_xml_pti_in_ctti)) {
2385 $XML_CREDITOR .= ' <PmtTpInf>' . $CrLf;
2386
2387 // Can be 'NORM' for normal or 'HIGH' for high priority level
2388 if (getDolGlobalString('PAYMENTBYBANKTRANSFER_FORCE_HIGH_PRIORITY')) {
2389 $instrprty = 'HIGH';
2390 } else {
2391 $instrprty = 'NORM';
2392 }
2393 $XML_CREDITOR .= ' <InstrPrty>' . $instrprty . '</InstrPrty>' . $CrLf;
2394 $XML_CREDITOR .= ' <SvcLvl>' . $CrLf;
2395 $XML_CREDITOR .= ' <Cd>SEPA</Cd>' . $CrLf;
2396 $XML_CREDITOR .= ' </SvcLvl>' . $CrLf;
2397 $XML_CREDITOR .= ' <CtgyPurp>' . $CrLf;
2398 $XML_CREDITOR .= ' <Cd>CORE</Cd>' . $CrLf;
2399 $XML_CREDITOR .= ' </CtgyPurp>' . $CrLf;
2400 $XML_CREDITOR .= ' </PmtTpInf>' . $CrLf;
2401 }
2402 $XML_CREDITOR .= ' <Amt>' . $CrLf;
2403 $XML_CREDITOR .= ' <InstdAmt Ccy="EUR">'.round((float) $row_somme, 2).'</InstdAmt>'.$CrLf;
2404 $XML_CREDITOR .= ' </Amt>' . $CrLf;
2405 /*
2406 $XML_CREDITOR .= ' <DrctDbtTx>'.$CrLf;
2407 $XML_CREDITOR .= ' <MndtRltdInf>'.$CrLf;
2408 $XML_CREDITOR .= ' <MndtId>'.$Rum.'</MndtId>'.$CrLf;
2409 $XML_CREDITOR .= ' <DtOfSgntr>'.$DtOfSgntr.'</DtOfSgntr>'.$CrLf;
2410 $XML_CREDITOR .= ' <AmdmntInd>false</AmdmntInd>'.$CrLf;
2411 $XML_CREDITOR .= ' </MndtRltdInf>'.$CrLf;
2412 $XML_CREDITOR .= ' </DrctDbtTx>'.$CrLf;
2413 */
2414 //$XML_CREDITOR .= ' <ChrgBr>SLEV</ChrgBr>'.$CrLf;
2415 $XML_CREDITOR .= ' <CdtrAgt>' . $CrLf;
2416 $XML_CREDITOR .= ' <FinInstnId>' . $CrLf;
2417 $XML_CREDITOR .= ' <BIC>' . $row_bic . '</BIC>' . $CrLf;
2418 $XML_CREDITOR .= ' </FinInstnId>' . $CrLf;
2419 $XML_CREDITOR .= ' </CdtrAgt>' . $CrLf;
2420 $XML_CREDITOR .= ' <Cdtr>' . $CrLf;
2421 $XML_CREDITOR .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))) . '</Nm>' . $CrLf;
2422 $XML_CREDITOR .= ' <PstlAdr>' . $CrLf;
2423 $XML_CREDITOR .= ' <Ctry>' . $row_country_code . '</Ctry>' . $CrLf;
2424 $addressline1 = strtr($row_address, array(chr(13) => ", ", chr(10) => ""));
2425 $addressline2 = strtr($row_zip . (($row_zip && $row_town) ? ' ' : (string) $row_town), array(chr(13) => ", ", chr(10) => ""));
2426 if (trim($addressline1)) {
2427 $XML_CREDITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2428 }
2429 if (trim($addressline2)) {
2430 $XML_CREDITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2431 }
2432 $XML_CREDITOR .= ' </PstlAdr>' . $CrLf;
2433 $XML_CREDITOR .= ' </Cdtr>' . $CrLf;
2434 $XML_CREDITOR .= ' <CdtrAcct>' . $CrLf;
2435 $XML_CREDITOR .= ' <Id>' . $CrLf;
2436 $XML_CREDITOR .= ' <IBAN>' . preg_replace('/\s/', '', $row_iban) . '</IBAN>' . $CrLf;
2437 $XML_CREDITOR .= ' </Id>' . $CrLf;
2438 $XML_CREDITOR .= ' </CdtrAcct>' . $CrLf;
2439 $XML_CREDITOR .= ' <RmtInf>' . $CrLf;
2440 // A string with some information on payment - 140 max
2441 $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
2442 $XML_CREDITOR .= ' </RmtInf>' . $CrLf;
2443 $XML_CREDITOR .= ' </CdtTrfTxInf>' . $CrLf;
2444 return $XML_CREDITOR;
2445 }
2446 }
2447
2448
2449 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2457 public function EnregEmetteur($type = 'direct-debit')
2458 {
2459 // phpcs:enable
2460 fwrite($this->file, "03");
2461 fwrite($this->file, "08"); // Prelevement ordinaire
2462
2463 fwrite($this->file, " "); // Zone Reservee B2
2464
2465 fwrite($this->file, $this->emetteur_ics); // ICS
2466
2467 // Date d'echeance C1
2468
2469 fwrite($this->file, " ");
2470 fwrite($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
2471 fwrite($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
2472
2473 // Raison Sociale C2
2474
2475 fwrite($this->file, substr($this->raison_sociale . " ", 0, 24));
2476
2477 // Ref of thirdparty on 7 characters
2478
2479 fwrite($this->file, substr($this->reference_remise . " ", 0, 7));
2480
2481 // Zone Reservee D1-2
2482
2483 fwrite($this->file, substr(" ", 0, 17));
2484
2485 // Zone Reservee D2
2486
2487 fwrite($this->file, substr(" ", 0, 2));
2488 fwrite($this->file, "E");
2489 fwrite($this->file, substr(" ", 0, 5));
2490
2491 // Code Guichet D3
2492
2493 fwrite($this->file, $this->emetteur_code_guichet);
2494
2495 // Numero de compte D4
2496
2497 fwrite($this->file, substr("000000000000000" . $this->emetteur_numero_compte, -11));
2498
2499 // Zone Reservee E
2500
2501 fwrite($this->file, substr(" ", 0, 16));
2502
2503 // Zone Reservee F
2504
2505 fwrite($this->file, substr(" ", 0, 31));
2506
2507 // Code etablissement
2508
2509 fwrite($this->file, $this->emetteur_code_banque);
2510
2511 // Zone Reservee G
2512
2513 fwrite($this->file, substr(" ", 0, 5));
2514
2515 fwrite($this->file, "\n");
2516 }
2517
2518
2519 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2535 public function EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf = '\n', $format = 'FRST', $type = 'direct-debit', $fk_bank_account = 0)
2536 {
2537 // phpcs:enable
2538
2539 // Clean parameters
2540 $dateTime_YMD = dol_print_date($ladate, '%Y%m%d');
2541 $dateTime_ETAD = dol_print_date($ladate, '%Y-%m-%d');
2542 $dateTime_YMDHMS = dol_print_date($ladate, '%Y-%m-%dT%H:%M:%S');
2543
2544 // Clean params
2545 if (empty($fk_bank_account)) {
2546 $fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
2547 }
2548
2549 // Get data of bank account
2550 $account = new Account($this->db);
2551 if ($account->fetch($fk_bank_account) > 0) {
2552 $this->emetteur_code_banque = $account->code_banque;
2553 $this->emetteur_code_guichet = $account->code_guichet;
2554 $this->emetteur_numero_compte = $account->number;
2555 $this->emetteur_number_key = $account->cle_rib;
2556 $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
2557 $this->emetteur_iban = $account->iban;
2558 $this->emetteur_bic = $account->bic;
2559
2560 $this->emetteur_ics = (($type == 'bank-transfer' && getDolGlobalString("SEPA_USE_IDS")) ? $account->ics_transfer : $account->ics); // Ex: PRELEVEMENT_ICS = "FR78ZZZ123456";
2561
2562 $this->raison_sociale = $account->owner_name;
2563 }
2564
2565 // Get pending payments
2566 $sql = "SELECT rowid, ref";
2567 $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons as pb";
2568 $sql .= " WHERE pb.rowid = " . ((int) $this->id);
2569
2570 $resql = $this->db->query($sql);
2571 if ($resql) {
2572 $obj = $this->db->fetch_object($resql);
2573
2574 $country = explode(':', $configuration->global->MAIN_INFO_SOCIETE_COUNTRY);
2575 $IdBon = sprintf("%05d", $obj->rowid);
2576 $RefBon = $obj->ref;
2577
2578 if (!empty($configuration->global->SEPA_FORCE_TWO_DECIMAL)) {
2579 $total = number_format((float) price2num($total, 'MT'), 2, ".", "");
2580 }
2581
2582 if ($type != 'bank-transfer') {
2583 // SEPA Paiement Information of my company for Direct Debit
2584 $XML_SEPA_INFO = '';
2585 $XML_SEPA_INFO .= ' <PmtInf>' . $CrLf;
2586 $XML_SEPA_INFO .= ' <PmtInfId>' . ('DD/' . $dateTime_YMD . '/ID' . $IdBon . '-' . $RefBon) . '</PmtInfId>' . $CrLf;
2587 $XML_SEPA_INFO .= ' <PmtMtd>DD</PmtMtd>' . $CrLf;
2588 $XML_SEPA_INFO .= ' <NbOfTxs>' . $nombre . '</NbOfTxs>' . $CrLf;
2589 $XML_SEPA_INFO .= ' <CtrlSum>' . $total . '</CtrlSum>' . $CrLf;
2590 $XML_SEPA_INFO .= ' <PmtTpInf>' . $CrLf;
2591 $XML_SEPA_INFO .= ' <SvcLvl>' . $CrLf;
2592 $XML_SEPA_INFO .= ' <Cd>SEPA</Cd>' . $CrLf;
2593 $XML_SEPA_INFO .= ' </SvcLvl>' . $CrLf;
2594 $XML_SEPA_INFO .= ' <LclInstrm>' . $CrLf;
2595 $XML_SEPA_INFO .= ' <Cd>CORE</Cd>' . $CrLf;
2596 $XML_SEPA_INFO .= ' </LclInstrm>' . $CrLf;
2597 $XML_SEPA_INFO .= ' <SeqTp>' . $format . '</SeqTp>' . $CrLf;
2598 $XML_SEPA_INFO .= ' </PmtTpInf>' . $CrLf;
2599 $XML_SEPA_INFO .= ' <ReqdColltnDt>' . $dateTime_ETAD . '</ReqdColltnDt>' . $CrLf;
2600 $XML_SEPA_INFO .= ' <Cdtr>' . $CrLf;
2601 $XML_SEPA_INFO .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf;
2602 $XML_SEPA_INFO .= ' <PstlAdr>' . $CrLf;
2603 $XML_SEPA_INFO .= ' <Ctry>' . $country[1] . '</Ctry>' . $CrLf;
2604 $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(chr(13) => ", ", chr(10) => ""));
2605 $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) => ""));
2606 if ($addressline1) {
2607 $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2608 }
2609 if ($addressline2) {
2610 $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2611 }
2612 $XML_SEPA_INFO .= ' </PstlAdr>' . $CrLf;
2613 $XML_SEPA_INFO .= ' </Cdtr>' . $CrLf;
2614 $XML_SEPA_INFO .= ' <CdtrAcct>' . $CrLf;
2615 $XML_SEPA_INFO .= ' <Id>' . $CrLf;
2616 $XML_SEPA_INFO .= ' <IBAN>' . preg_replace('/\s/', '', $this->emetteur_iban) . '</IBAN>' . $CrLf;
2617 $XML_SEPA_INFO .= ' </Id>' . $CrLf;
2618 $XML_SEPA_INFO .= ' </CdtrAcct>' . $CrLf;
2619 $XML_SEPA_INFO .= ' <CdtrAgt>' . $CrLf;
2620 $XML_SEPA_INFO .= ' <FinInstnId>' . $CrLf;
2621 $XML_SEPA_INFO .= ' <BIC>' . $this->emetteur_bic . '</BIC>' . $CrLf;
2622 $XML_SEPA_INFO .= ' </FinInstnId>' . $CrLf;
2623 $XML_SEPA_INFO .= ' </CdtrAgt>' . $CrLf;
2624 /* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf;
2625 $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2626 $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2627 $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2628 $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;
2629 $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;
2630 $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2631 $XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/
2632 $XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>' . $CrLf; // Field "Responsible of fees". Must be SLEV
2633 $XML_SEPA_INFO .= ' <CdtrSchmeId>' . $CrLf;
2634 $XML_SEPA_INFO .= ' <Id>' . $CrLf;
2635 $XML_SEPA_INFO .= ' <PrvtId>' . $CrLf;
2636 $XML_SEPA_INFO .= ' <Othr>' . $CrLf;
2637 $XML_SEPA_INFO .= ' <Id>' . $this->emetteur_ics . '</Id>' . $CrLf;
2638 $XML_SEPA_INFO .= ' <SchmeNm>' . $CrLf;
2639 $XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>' . $CrLf;
2640 $XML_SEPA_INFO .= ' </SchmeNm>' . $CrLf;
2641 $XML_SEPA_INFO .= ' </Othr>' . $CrLf;
2642 $XML_SEPA_INFO .= ' </PrvtId>' . $CrLf;
2643 $XML_SEPA_INFO .= ' </Id>' . $CrLf;
2644 $XML_SEPA_INFO .= ' </CdtrSchmeId>' . $CrLf;
2645 } else {
2646 // SEPA Paiement Information of my company for Credit Transfer
2647 $XML_SEPA_INFO = '';
2648 $XML_SEPA_INFO .= ' <PmtInf>' . $CrLf;
2649 $XML_SEPA_INFO .= ' <PmtInfId>' . ('TRF/' . $dateTime_YMD . '/ID' . $IdBon . '-' . $RefBon) . '</PmtInfId>' . $CrLf;
2650 $XML_SEPA_INFO .= ' <PmtMtd>TRF</PmtMtd>' . $CrLf;
2651 //$XML_SEPA_INFO .= ' <BtchBookg>False</BtchBookg>'.$CrLf;
2652 $XML_SEPA_INFO .= ' <NbOfTxs>' . $nombre . '</NbOfTxs>' . $CrLf;
2653 $XML_SEPA_INFO .= ' <CtrlSum>' . $total . '</CtrlSum>' . $CrLf;
2654 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.
2655 $XML_SEPA_INFO .= ' <PmtTpInf>' . $CrLf;
2656 $XML_SEPA_INFO .= ' <SvcLvl>' . $CrLf;
2657 $XML_SEPA_INFO .= ' <Cd>SEPA</Cd>' . $CrLf;
2658 $XML_SEPA_INFO .= ' </SvcLvl>' . $CrLf;
2659 $XML_SEPA_INFO .= ' <LclInstrm>' . $CrLf;
2660 $XML_SEPA_INFO .= ' <Cd>CORE</Cd>' . $CrLf;
2661 $XML_SEPA_INFO .= ' </LclInstrm>' . $CrLf;
2662 $XML_SEPA_INFO .= ' <SeqTp>' . $format . '</SeqTp>' . $CrLf;
2663 $XML_SEPA_INFO .= ' </PmtTpInf>' . $CrLf;
2664 }
2665 $XML_SEPA_INFO .= ' <ReqdExctnDt>' . dol_print_date($dateTime_ETAD, 'dayrfc') . '</ReqdExctnDt>' . $CrLf;
2666 $XML_SEPA_INFO .= ' <Dbtr>' . $CrLf;
2667 $XML_SEPA_INFO .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf;
2668 $XML_SEPA_INFO .= ' <PstlAdr>' . $CrLf;
2669 $XML_SEPA_INFO .= ' <Ctry>' . $country[1] . '</Ctry>' . $CrLf;
2670 $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(chr(13) => ", ", chr(10) => ""));
2671 $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) => ""));
2672 if ($addressline1) {
2673 $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2674 }
2675 if ($addressline2) {
2676 $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2677 }
2678 $XML_SEPA_INFO .= ' </PstlAdr>' . $CrLf;
2679 $XML_SEPA_INFO .= ' </Dbtr>' . $CrLf;
2680 $XML_SEPA_INFO .= ' <DbtrAcct>' . $CrLf;
2681 $XML_SEPA_INFO .= ' <Id>' . $CrLf;
2682 $XML_SEPA_INFO .= ' <IBAN>' . preg_replace('/\s/', '', $this->emetteur_iban) . '</IBAN>' . $CrLf;
2683 $XML_SEPA_INFO .= ' </Id>' . $CrLf;
2684 $XML_SEPA_INFO .= ' </DbtrAcct>' . $CrLf;
2685 $XML_SEPA_INFO .= ' <DbtrAgt>' . $CrLf;
2686 $XML_SEPA_INFO .= ' <FinInstnId>' . $CrLf;
2687 $XML_SEPA_INFO .= ' <BIC>' . $this->emetteur_bic . '</BIC>' . $CrLf;
2688 $XML_SEPA_INFO .= ' </FinInstnId>' . $CrLf;
2689 $XML_SEPA_INFO .= ' </DbtrAgt>' . $CrLf;
2690 /* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf;
2691 $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2692 $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2693 $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2694 $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;
2695 $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;
2696 $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2697 $XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/
2698 $XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>' . $CrLf; // Field "Responsible of fees". Must be SLEV
2699 /*$XML_SEPA_INFO .= ' <CdtrSchmeId>'.$CrLf;
2700 $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2701 $XML_SEPA_INFO .= ' <PrvtId>'.$CrLf;
2702 $XML_SEPA_INFO .= ' <Othr>'.$CrLf;
2703 $XML_SEPA_INFO .= ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf;
2704 $XML_SEPA_INFO .= ' <SchmeNm>'.$CrLf;
2705 $XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>'.$CrLf;
2706 $XML_SEPA_INFO .= ' </SchmeNm>'.$CrLf;
2707 $XML_SEPA_INFO .= ' </Othr>'.$CrLf;
2708 $XML_SEPA_INFO .= ' </PrvtId>'.$CrLf;
2709 $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2710 $XML_SEPA_INFO .= ' </CdtrSchmeId>'.$CrLf;*/
2711 }
2712 } else {
2713 fwrite($this->file, 'INCORRECT EMETTEUR ' . $this->raison_sociale . $CrLf);
2714 $XML_SEPA_INFO = '';
2715 }
2716 return $XML_SEPA_INFO;
2717 }
2718
2719 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2726 public function EnregTotal($total)
2727 {
2728 // phpcs:enable
2729 fwrite($this->file, "08");
2730 fwrite($this->file, "08"); // Prelevement ordinaire
2731
2732 fwrite($this->file, " "); // Zone Reservee B2
2733
2734 fwrite($this->file, $this->emetteur_ics); // ICS
2735
2736 // Reserve C1
2737
2738 fwrite($this->file, substr(" ", 0, 12));
2739
2740
2741 // Raison Sociale C2
2742
2743 fwrite($this->file, substr(" ", 0, 24));
2744
2745 // D1
2746
2747 fwrite($this->file, substr(" ", 0, 24));
2748
2749 // Zone Reservee D2
2750
2751 fwrite($this->file, substr(" ", 0, 8));
2752
2753 // Code Guichet D3
2754
2755 fwrite($this->file, substr(" ", 0, 5));
2756
2757 // Numero de compte D4
2758
2759 fwrite($this->file, substr(" ", 0, 11));
2760
2761 // Zone E Montant
2762
2763 $montant = ($total * 100);
2764
2765 fwrite($this->file, substr("000000000000000" . $montant, -16));
2766
2767 // Zone Reservee F
2768
2769 fwrite($this->file, substr(" ", 0, 31));
2770
2771 // Code etablissement
2772
2773 fwrite($this->file, substr(" ", 0, 5));
2774
2775 // Zone Reservee F
2776
2777 fwrite($this->file, substr(" ", 0, 5));
2778
2779 fwrite($this->file, "\n");
2780 }
2781
2788 public function getLibStatut($mode = 0)
2789 {
2790 return $this->LibStatut($this->statut, $mode);
2791 }
2792
2793 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2801 public function LibStatut($status, $mode = 0)
2802 {
2803 // phpcs:enable
2804 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
2805 global $langs;
2806 //$langs->load("mymodule");
2807 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2808 $this->labelStatus[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2809 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2810 $this->labelStatusShort[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2811 if ($this->type == 'bank-transfer') {
2812 $this->labelStatus[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2813 $this->labelStatusShort[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2814 } else {
2815 $this->labelStatus[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2816 $this->labelStatusShort[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2817 }
2818 }
2819
2820 $statusType = 'status1';
2821 if ($status == self::STATUS_TRANSFERED) {
2822 $statusType = 'status3';
2823 }
2824 if ($status == self::STATUS_CREDITED || $status == self::STATUS_DEBITED) {
2825 $statusType = 'status6';
2826 }
2827
2828 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
2829 }
2830
2831 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2839 public function load_board($user, $mode)
2840 {
2841 // phpcs:enable
2842 if ($user->socid) {
2843 return -1; // protection pour eviter appel par utilisateur externe
2844 }
2845
2846 /*
2847 if ($mode == 'direct_debit') {
2848 $sql = "SELECT b.rowid, f.datedue as datefin";
2849 $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
2850 $sql .= " WHERE f.entity IN (".getEntity('facture').")";
2851 $sql .= " AND f.total_ttc > 0";
2852 } else {
2853 $sql = "SELECT b.rowid, f.datedue as datefin";
2854 $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
2855 $sql .= " WHERE f.entity IN (".getEntity('facture_fourn').")";
2856 $sql .= " AND f.total_ttc > 0";
2857 }
2858
2859 $resql = $this->db->query($sql);
2860 if ($resql) {
2861 $langs->load("banks");
2862 $now = dol_now();
2863
2864 $response = new WorkboardResponse();
2865 if ($mode == 'direct_debit') {
2866 $response->warning_delay = $conf->prelevement->warning_delay / 60 / 60 / 24;
2867 $response->label = $langs->trans("PendingDirectDebitToComplete");
2868 $response->labelShort = $langs->trans("PendingDirectDebitToCompleteShort");
2869 $response->url = DOL_URL_ROOT.'/compta/prelevement/index.php?leftmenu=checks&mainmenu=bank';
2870 } else {
2871 $response->warning_delay = $conf->paymentbybanktransfer->warning_delay / 60 / 60 / 24;
2872 $response->label = $langs->trans("PendingCreditTransferToComplete");
2873 $response->labelShort = $langs->trans("PendingCreditTransferToCompleteShort");
2874 $response->url = DOL_URL_ROOT.'/compta/paymentbybanktransfer/index.php?leftmenu=checks&mainmenu=bank';
2875 }
2876 $response->img = img_object('', "payment");
2877
2878 while ($obj = $this->db->fetch_object($resql)) {
2879 $response->nbtodo++;
2880
2881 if ($this->db->jdate($obj->datefin) < ($now - $conf->withdraw->warning_delay)) {
2882 $response->nbtodolate++;
2883 }
2884 }
2885
2886 $response->nbtodo = 0;
2887 $response->nbtodolate = 0;
2888 // Return workboard only if quantity is not 0
2889 if ($response->nbtodo) {
2890 return $response;
2891 } else {
2892 return 0;
2893 }
2894 } else {
2895 dol_print_error($this->db);
2896 $this->error = $this->db->error();
2897 return -1;
2898 }
2899 */
2900 return 0;
2901 }
2902
2910 public function getKanbanView($option = '', $arraydata = null)
2911 {
2912 global $langs;
2913
2914 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2915
2916 $return = '<div class="box-flex-item box-flex-grow-zero">';
2917 $return .= '<div class="info-box info-box-sm">';
2918 $return .= '<span class="info-box-icon bg-infobox-action">';
2919 $return .= img_picto('', $this->picto);
2920 $return .= '</span>';
2921 $return .= '<div class="info-box-content">';
2922 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . (method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref) . '</span>';
2923 if ($selected >= 0) {
2924 $return .= '<input id="cb' . $this->id . '" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="' . $this->id . '"' . ($selected ? ' checked="checked"' : '') . '>';
2925 }
2926 if (property_exists($this, 'date_echeance')) {
2927 $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>';
2928 }
2929 if (property_exists($this, 'total')) {
2930 $return .= '<br><span class="opacitymedium">' . $langs->trans("Amount") . '</span> : <span class="amount">' . price($this->total) . '</span>';
2931 }
2932 if (method_exists($this, 'LibStatut')) {
2933 $return .= '<br><div class="info-box-status">' . $this->getLibStatut(3) . '</div>';
2934 }
2935 $return .= '</div>';
2936 $return .= '</div>';
2937 $return .= '</div>';
2938 return $return;
2939 }
2940
2947 {
2948 if (!empty($this->id)) {
2949 $id = $this->id;
2950 } else {
2951 return 0;
2952 }
2953 if ($id) {
2954 $sql = "SELECT COUNT(*) AS nb FROM " . MAIN_DB_PREFIX . "prelevement_lignes";
2955 $sql .= " WHERE fk_prelevement_bons = " . ((int) $id);
2956 $sql .= " AND fk_soc = 0"; // fk_soc can't be NULL
2957 $sql .= " AND fk_user IS NOT NULL";
2958
2959 $num = 0;
2960 $resql = $this->db->query($sql);
2961 if ($resql) {
2962 $obj = $this->db->fetch_object($resql);
2963 $num = $obj->nb;
2964 }
2965 if ($num > 0) {
2966 return 1;
2967 }
2968 } else {
2969 dol_print_error($this->db);
2970 }
2971
2972 return 0;
2973 }
2974}
checkIbanForAccount($account=null, $ibantocheck=null)
Check IBAN number information for a bank account.
Definition bank.lib.php:305
checkSwiftForAccount($account=null, $swift=null)
Check SWIFT information for a bank account.
Definition bank.lib.php:284
$object ref
Definition info.php:79
Class to manage bank accounts.
Class to manage withdrawal receipts.
load_board($user, $mode)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
SommeAPrelever($mode='direct-debit', $type='')
Returns amount waiting for direct debit payment or credit transfer payment.
static buildRumNumber($row_code_client, $row_datec, $row_drum)
Generate dynamically a RUM number for a customer bank account.
EnregEmetteur($type='direct-debit')
Write sender of request (me).
checkIfSalaryBonPrelevement()
Check if is bon prelevement for salary invoice.
EnregTotal($total)
Write end.
NbFactureAPrelever($type='direct-debit', $forsalary=0)
Get number of invoices to pay.
fetch($rowid, $ref='')
Get object and lines from database.
getListInvoices($amounts=0, $type='')
Get invoice or salary list (with amount or not)
generate(string $format='ALL', int $executiondate=0, string $type='direct-debit', int $fk_bank_account=0, int $forsalary=0, string $societeRibID='')
Generate a direct debit or credit transfer file.
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='', $notrigger=0, $type='direct-debit', $did=0, $fk_bank_account=0, $sourcetype='invoice')
Create a BAN payment order:
deleteNotification($user, $action)
Delete a notification.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
updateCommon(User $user, $notrigger=0)
Update object into database.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Class to manage suppliers invoices.
Class to manage invoices.
const STATUS_VALIDATED
Validated (need to be paid)
Class to manage payments for supplier invoices.
Class to manage payments of customer invoices.
Class to manage payments of salaries.
Class to manage salary payments.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage Dolibarr users.
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:162
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.
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.
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:137