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