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