dolibarr 20.0.0
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 $facs = array();
519 $amounts = array();
520 $amountsperthirdparty = array();
521
522 $facs = $this->getListInvoices(1, $type);
523 if ($this->error) {
524 $error++;
525 }
526
527 // Loop on each invoice or salary.
528 // $facs should be array(0=>id, 1=>amount requested)
529 $num = count($facs);
530 for ($i = 0; $i < $num; $i++) {
531 if ($this->type == 'bank-transfer') {
532 if ($type == 'salary') {
533 $fac = new Salary($this->db);
534 } else {
535 $fac = new FactureFournisseur($this->db);
536 }
537 } else {
538 $fac = new Facture($this->db);
539 }
540
541 $result = $fac->fetch($facs[$i][0]);
542
543 $amounts[$fac->id] = $facs[$i][1];
544 if ($this->type == 'bank-transfer') {
545 if ($type == 'salary') {
546 $amountsperthirdparty[$fac->fk_user][$fac->id] = $facs[$i][1];
547 } else {
548 $amountsperthirdparty[$fac->socid][$fac->id] = $facs[$i][1];
549 }
550 } else {
551 $amountsperthirdparty[$fac->socid][$fac->id] = $facs[$i][1];
552 }
553
554 $totalpaid = $fac->getSommePaiement();
555 $totalcreditnotes = 0;
556 if (method_exists($fac, 'getSumCreditNotesUsed')) {
557 $totalcreditnotes = $fac->getSumCreditNotesUsed();
558 }
559 $totaldeposits = 0;
560 if (method_exists($fac, 'getSumDepositsUsed')) {
561 $totaldeposits = $fac->getSumDepositsUsed();
562 }
563 $alreadypayed = $totalpaid + $totalcreditnotes + $totaldeposits;
564
565 // Set the main document to pay with status Paid.
566 // @TODO Move this after creation of payments done after
567 $amountofdocument = $fac->total_ttc;
568 if ($type == 'salary') {
569 $amountofdocument = $fac->amount;
570 }
571 if (price2num($alreadypayed + $facs[$i][1], 'MT') == price2num($amountofdocument, 'MT')) {
572 $result = $fac->setPaid($user);
573 if ($result < 0) {
574 $this->error = $fac->error;
575 $this->errors = $fac->errors;
576 }
577 }
578 }
579
580 // Make one payment per customer or employee
581 foreach ($amountsperthirdparty as $thirdpartyid => $cursoramounts) {
582 if ($this->type == 'bank-transfer') {
583 if ($type == 'salary') {
584 $paiement = new PaymentSalary($this->db);
585 } else {
586 $paiement = new PaiementFourn($this->db);
587 }
588 } else {
589 $paiement = new Paiement($this->db);
590 }
591 $paiement->datepaye = $date;
592 $paiement->amounts = $cursoramounts; // Array with detail of dispatching of payments for each invoice
593
594 if ($this->type == 'bank-transfer') {
595 if ($type == 'salary') {
596 $paiement->datep = $date;
597
598 $paiement->paiementid = 2;
599 $paiement->fk_typepayment = 2;
600 $paiement->paiementcode = 'VIR';
601 } else {
602 $paiement->paiementid = 2;
603 $paiement->paiementcode = 'VIR';
604 }
605 } else {
606 $paiement->paiementid = 3;
607 $paiement->paiementcode = 'PRE';
608 }
609
610 $paiement->num_payment = $this->ref; // Set ref of direct debit note
611 $paiement->id_prelevement = $this->id;
612
613 $result = $paiement->create($user); // This use ->paiementid, that is ID of payment mode
614
615 if ($result < 0) {
616 $error++;
617 $this->error = $paiement->error;
618 $this->errors = $paiement->errors;
619 dol_syslog(get_class($this) . "::set_infocredit AddPayment Error " . $this->error);
620 } else {
621 if ($this->type == 'bank-transfer') {
622 if ($type == 'salary') {
623 $modeforaddpayment = 'payment_salary';
624 $labelforaddpayment = '(SalaryPayment)';
625 $addbankurl = 'credit-transfer';
626 } else {
627 $modeforaddpayment = 'payment_supplier';
628 $labelforaddpayment = '(SupplierInvoicePayment)';
629 $addbankurl = 'credit-transfer';
630 }
631 } else {
632 $modeforaddpayment = 'payment';
633 $labelforaddpayment = '(CustomerInvoicePayment)';
634 $addbankurl = 'direct-debit'; // = 'directdebit'
635 }
636
637 $result = $paiement->addPaymentToBank($user, $modeforaddpayment, $labelforaddpayment, $fk_bank_account, '', '', 0, '', $addbankurl);
638
639 if ($result < 0) {
640 $error++;
641 $this->error = $paiement->error;
642 $this->errors = $paiement->errors;
643 dol_syslog(get_class($this) . "::set_infocredit AddPaymentToBank Error " . $this->error);
644 }
645 }
646 }
647
648 // Update withdrawal line
649 // TODO: Translate to ligneprelevement.class.php
650 if (!$error) {
651 $sql = " UPDATE " . MAIN_DB_PREFIX . "prelevement_lignes";
652 $sql .= " SET statut = 2";
653 $sql .= " WHERE fk_prelevement_bons = " . ((int) $this->id);
654
655 if (!$this->db->query($sql)) {
656 dol_syslog(get_class($this) . "::set_infocredit Update lines Error");
657 $error++;
658 }
659 }
660 } else {
661 $this->error = $this->db->lasterror();
662 dol_syslog(get_class($this) . "::set_infocredit Update Bons Error");
663 $error++;
664 }
665
666 // End of procedure
667 if ($error == 0) {
668 $this->date_credit = $date; // date credit or debit
669 $this->statut = self::STATUS_CREDITED;
670 $this->status = self::STATUS_CREDITED;
671
672 $this->db->commit();
673 return 0;
674 } else {
675 $this->db->rollback();
676 return -1;
677 }
678 } else {
679 return -1026;
680 }
681 }
682
683 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
692 public function set_infotrans($user, $date, $method)
693 {
694 // phpcs:enable
695 global $conf, $langs;
696
697 $error = 0;
698
699 dol_syslog(get_class($this) . "::set_infotrans Start", LOG_INFO);
700
701 if ($this->db->begin()) {
702 $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_bons ";
703 $sql .= " SET fk_user_trans = " . $user->id;
704 $sql .= " , date_trans = '" . $this->db->idate($date) . "'";
705 $sql .= " , method_trans = " . ((int) $method);
706 $sql .= " , statut = " . self::STATUS_TRANSFERED;
707 $sql .= " WHERE rowid = " . ((int) $this->id);
708 $sql .= " AND entity = " . ((int) $conf->entity);
709 $sql .= " AND statut = " . self::STATUS_DRAFT;
710
711 if ($this->db->query($sql)) {
712 $this->method_trans = $method;
713 $langs->load('withdrawals');
714 $subject = $langs->trans("InfoTransSubject", $this->ref);
715 $message = $langs->trans("InfoTransMessage", $this->ref, dolGetFirstLastname($user->firstname, $user->lastname));
716 $message .= $langs->trans("InfoTransData", price($this->amount), $this->methodes_trans[$this->method_trans], dol_print_date($date, 'day'));
717
718 // TODO Call trigger to create a notification using notification module
719 } else {
720 $error++;
721 }
722
723 if ($error == 0) {
724 $this->date_trans = $date;
725 $this->statut = self::STATUS_TRANSFERED;
726 $this->status = self::STATUS_TRANSFERED;
727 $this->user_trans = $user->id;
728
729 $this->db->commit();
730
731 return 0;
732 } else {
733 $this->db->rollback();
734 dol_syslog(get_class($this) . "::set_infotrans ROLLBACK", LOG_ERR);
735
736 return -1;
737 }
738 } else {
739 dol_syslog(get_class($this) . "::set_infotrans Ouverture transaction SQL impossible", LOG_CRIT);
740 return -2;
741 }
742 }
743
751 private function getListInvoices($amounts = 0, $type = '')
752 {
753 global $conf;
754
755 $arr = array();
756
757 dol_syslog(get_class($this) . "::getListInvoices");
758
759 // Returns all invoices presented within same order
760 $sql = "SELECT ";
761 if ($this->type == 'bank-transfer') {
762 if ($type == 'salary') {
763 $sql .= " p.fk_salary";
764 } else {
765 $sql .= " p.fk_facture_fourn";
766 }
767 } else {
768 $sql .= " p.fk_facture";
769 }
770 if ($amounts) {
771 $sql .= ", SUM(pl.amount)";
772 }
773 $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons as pb,";
774 $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
775 $sql .= " " . MAIN_DB_PREFIX . "prelevement as p";
776 $sql .= " WHERE p.fk_prelevement_lignes = pl.rowid";
777 $sql .= " AND pl.fk_prelevement_bons = pb.rowid";
778 $sql .= " AND pb.rowid = " . ((int) $this->id);
779 $sql .= " AND pb.entity = " . ((int) $conf->entity);
780 if ($amounts) {
781 if ($this->type == 'bank-transfer') {
782 if ($type == 'salary') {
783 $sql .= " GROUP BY p.fk_salary";
784 } else {
785 $sql .= " GROUP BY p.fk_facture_fourn";
786 }
787 } else {
788 $sql .= " GROUP BY p.fk_facture";
789 }
790 }
791
792 $resql = $this->db->query($sql);
793 if ($resql) {
794 $num = $this->db->num_rows($resql);
795
796 if ($num) {
797 $i = 0;
798 while ($i < $num) {
799 $row = $this->db->fetch_row($resql);
800 if (!$amounts) {
801 $arr[$i] = $row[0];
802 } else {
803 $arr[$i] = array(
804 $row[0],
805 $row[1]
806 );
807 }
808 $i++;
809 }
810 }
811 $this->db->free($resql);
812 } else {
813 $this->error = $this->db->lasterror();
814 }
815
816 return $arr;
817 }
818
819 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
827 public function SommeAPrelever($mode = 'direct-debit', $type = '')
828 {
829 // phpcs:enable
830 $sql = "SELECT sum(pd.amount) as nb";
831 if ($type !== 'salary') {
832 if ($mode != 'bank-transfer') {
833 $sql .= " FROM " . MAIN_DB_PREFIX . "facture as f,";
834 } else {
835 $sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f,";
836 }
837 } else {
838 $sql .= " FROM " . MAIN_DB_PREFIX . "salary as s,";
839 }
840 $sql .= " " . MAIN_DB_PREFIX . "prelevement_demande as pd";
841 $sql .= ($type !== 'salary' ? " WHERE f.entity IN (" . getEntity('invoice') . ")" : " WHERE s.entity IN (" . getEntity('salary') . ")");
842 if (!getDolGlobalString('WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS')) {
843 $sql .= ($type !== 'salary' ? " AND f.fk_statut = " . Facture::STATUS_VALIDATED : " AND s.paye = " . Salary::STATUS_UNPAID);
844 }
845 if ($type !== 'salary') {
846 if ($mode != 'bank-transfer') {
847 $sql .= " AND f.rowid = pd.fk_facture";
848 } else {
849 $sql .= " AND f.rowid = pd.fk_facture_fourn";
850 }
851 } else {
852 $sql .= " AND s.rowid = pd.fk_salary";
853 }
854 $sql .= ($type !== 'salary' ? " AND f.paye = 0" : "");
855 $sql .= " AND pd.traite = 0";
856 $sql .= " AND pd.ext_payment_id IS NULL";
857 $sql .= ($type !== 'salary' ? " AND f.total_ttc > 0" : "");
858
859 $resql = $this->db->query($sql);
860 if ($resql) {
861 $obj = $this->db->fetch_object($resql);
862
863 $this->db->free($resql);
864
865 return $obj->nb;
866 } else {
867 $error = 1;
868 dol_syslog(get_class($this) . "::SommeAPrelever Erreur -1");
869 dol_syslog($this->db->error());
870
871 return -1;
872 }
873 }
874
882 public function nbOfInvoiceToPay($mode = 'direct-debit', $type = '')
883 {
884 if ($type === 'salary') {
885 return $this->NbFactureAPrelever($mode, 1);
886 } else {
887 return $this->NbFactureAPrelever($mode);
888 }
889 }
890
891 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
899 public function NbFactureAPrelever($type = 'direct-debit', $forsalary = 0)
900 {
901 // phpcs:enable
902 if ($forsalary == 1) {
903 $sql = "SELECT count(s.rowid) as nb";
904 $sql .= " FROM " . MAIN_DB_PREFIX . "salary as s";
905 } else {
906 $sql = "SELECT count(f.rowid) as nb";
907
908 if ($type == 'bank-transfer') {
909 $sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
910 } else {
911 $sql .= " FROM " . MAIN_DB_PREFIX . "facture as f";
912 }
913 }
914 $sql .= ", " . MAIN_DB_PREFIX . "prelevement_demande as pd";
915 if ($forsalary == 1) {
916 $sql .= " WHERE s.entity IN (" . getEntity('invoice') . ")";
917 if (!getDolGlobalString('WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS')) {
918 $sql .= " AND s.paye = 0";
919 }
920 } else {
921 $sql .= " WHERE f.entity IN (" . getEntity('invoice') . ")";
922 if (!getDolGlobalString('WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS')) {
923 $sql .= " AND f.fk_statut = " . Facture::STATUS_VALIDATED;
924 }
925 }
926 if ($forsalary == 1) {
927 $sql .= " AND s.rowid = pd.fk_salary";
928 } else {
929 if ($type == 'bank-transfer') {
930 $sql .= " AND f.rowid = pd.fk_facture_fourn";
931 } else {
932 $sql .= " AND f.rowid = pd.fk_facture";
933 }
934 }
935 $sql .= " AND pd.traite = 0";
936 $sql .= " AND pd.ext_payment_id IS NULL";
937 if (!$forsalary == 1) {
938 $sql .= " AND f.total_ttc > 0";
939 } else {
940 $sql .= " AND s.paye = 0";
941 }
942
943 dol_syslog(get_class($this) . "::NbFactureAPrelever");
944 $resql = $this->db->query($sql);
945
946 if ($resql) {
947 $obj = $this->db->fetch_object($resql);
948 $this->db->free($resql);
949
950 return $obj->nb;
951 } else {
952 $this->error = get_class($this) . "::NbFactureAPrelever Erreur -1 sql=" . $this->db->error();
953 return -1;
954 }
955 }
956
957
958 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
979 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')
980 {
981 // phpcs:enable
982 global $conf, $langs, $user;
983
984 dol_syslog(__METHOD__ . " Bank=" . $banque . " Office=" . $agence . " mode=" . $mode . " format=" . $format, LOG_DEBUG);
985
986 require_once DOL_DOCUMENT_ROOT . "/compta/facture/class/facture.class.php";
987 require_once DOL_DOCUMENT_ROOT . "/societe/class/societe.class.php";
988
989 // Check params
990 if ($type != 'bank-transfer') {
991 if (empty($format)) {
992 $this->error = 'ErrorBadParametersForDirectDebitFileCreate';
993 return -1;
994 }
995 }
996
997 // Clean params
998 if (empty($fk_bank_account)) {
999 $fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
1000 }
1001
1002 $error = 0;
1003
1004 $datetimeprev = dol_now('gmt');
1005 // Choice the date of the execution direct debit
1006 if (!empty($executiondate)) {
1007 $datetimeprev = $executiondate;
1008 }
1009
1010 $month = dol_print_date($datetimeprev, "%m", 'gmt');
1011 $year = dol_print_date($datetimeprev, "%Y", 'gmt');
1012
1013 $this->invoice_in_error = array();
1014 $this->thirdparty_in_error = array();
1015
1016 // Read invoices
1017 $factures = array();
1018 $factures_prev = array();
1019 $factures_result = array();
1020 $factures_prev_id = array();
1021 $factures_errors = array();
1022 if (!$error) {
1023 dol_syslog(__METHOD__ . " Read invoices for did=" . ((int) $did), LOG_DEBUG);
1024
1025 $sql = "SELECT f.rowid, pd.rowid as pfdrowid";
1026 if ($sourcetype != 'salary') {
1027 $sql .= ", f.fk_soc";
1028 } else {
1029 $sql .= ", f.fk_user";
1030 }
1031 $sql .= ", pd.code_banque, pd.code_guichet, pd.number, pd.cle_rib";
1032 $sql .= ", pd.amount";
1033 if ($sourcetype != 'salary') {
1034 $sql .= ", s.nom as name";
1035 $sql .= ", f.ref, sr.bic, sr.iban_prefix, sr.frstrecur";
1036 } else {
1037 $sql .= ", CONCAT(s.firstname,' ',s.lastname) as name";
1038 $sql .= ", f.ref, sr.bic, sr.iban_prefix, 'FRST' as frstrecur";
1039 }
1040 if ($sourcetype != 'salary') {
1041 if ($type != 'bank-transfer') {
1042 $sql .= " FROM " . MAIN_DB_PREFIX . "facture as f";
1043 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "prelevement_demande as pd ON f.rowid = pd.fk_facture";
1044 } else {
1045 $sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
1046 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "prelevement_demande as pd ON f.rowid = pd.fk_facture_fourn";
1047 }
1048 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe as s ON s.rowid = f.fk_soc";
1049 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe_rib as sr ON s.rowid = sr.fk_soc AND sr.default_rib = 1";
1050 } else {
1051 $sql .= " FROM " . MAIN_DB_PREFIX . "salary as f";
1052 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "prelevement_demande as pd ON f.rowid = pd.fk_salary";
1053 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "user as s ON s.rowid = f.fk_user";
1054 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "user_rib as sr ON s.rowid = sr.fk_user"; // TODO Add AND sr.default_rib = 1 here
1055 }
1056 if ($sourcetype != 'salary') {
1057 if ($type != 'bank-transfer') {
1058 $sql .= " WHERE f.entity IN (" . getEntity('invoice') . ')';
1059 } else {
1060 $sql .= " WHERE f.entity IN (" . getEntity('supplier_invoice') . ')';
1061 }
1062 } else {
1063 $sql .= " WHERE f.entity IN (" . getEntity('salary') . ')';
1064 }
1065 if ($sourcetype != 'salary') {
1066 $sql .= " AND f.fk_statut = 1"; // Invoice validated
1067 $sql .= " AND f.paye = 0";
1068 $sql .= " AND f.total_ttc > 0";
1069 } else {
1070 //$sql .= " AND f.fk_statut = 1"; // Invoice validated
1071 $sql .= " AND f.paye = 0";
1072 $sql .= " AND f.amount > 0";
1073 }
1074 $sql .= " AND pd.traite = 0";
1075 $sql .= " AND pd.ext_payment_id IS NULL";
1076 if ($sourcetype != 'salary') {
1077 $sql .= " AND sr.type = 'ban'"; // TODO Add AND sr.type = 'ban' for users too
1078 }
1079 if ($did > 0) {
1080 $sql .= " AND pd.rowid = " . ((int) $did);
1081 }
1082
1083 $resql = $this->db->query($sql);
1084 if ($resql) {
1085 $num = $this->db->num_rows($resql);
1086 $i = 0;
1087
1088 while ($i < $num) {
1089 $row = $this->db->fetch_row($resql); // TODO Replace with fetch_object()
1090 $factures[$i] = $row; // All fields
1091
1092 if ($row[7] == 0) {
1093 $error++;
1094 dol_syslog(__METHOD__ . " Read invoices/salary error Found a null amount", LOG_ERR);
1095 $this->invoice_in_error[$row[0]] = "Error for invoice or salary id " . $row[0] . ", found a null amount";
1096 break;
1097 }
1098 $i++;
1099 }
1100
1101 $this->db->free($resql);
1102 dol_syslog(__METHOD__ . " Read invoices/salary, " . $i . " invoices/salary to withdraw", LOG_DEBUG);
1103 } else {
1104 $error++;
1105 $this->error = $this->db->lasterror();
1106 dol_syslog(__METHOD__ . " Read invoices/salary error " . $this->db->lasterror(), LOG_ERR);
1107 return -1;
1108 }
1109 }
1110
1111 if (!$error) {
1112 // Make some checks
1113 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
1114 require_once DOL_DOCUMENT_ROOT . '/user/class/user.class.php';
1115 require_once DOL_DOCUMENT_ROOT . '/societe/class/companybankaccount.class.php';
1116 require_once DOL_DOCUMENT_ROOT . '/core/lib/bank.lib.php';
1117
1118 $tmpsoc = new Societe($this->db);
1119 $tmpuser = new User($this->db);
1120
1121 // Check BAN
1122 $i = 0;
1123 dol_syslog(__METHOD__ . " Check BAN", LOG_DEBUG);
1124
1125 if (count($factures) > 0) {
1126 foreach ($factures as $key => $fac) {
1127 /*
1128 if ($type != 'bank-transfer') {
1129 $tmpinvoice = new Facture($this->db);
1130 } else {
1131 $tmpinvoice = new FactureFournisseur($this->db);
1132 }
1133 $resfetch = $tmpinvoice->fetch($fac[0]);
1134 if ($resfetch >= 0) { // Field 0 of $fac is rowid of invoice
1135 */
1136
1137 // Check if $fac[8] s.nom is null
1138 if ($fac[8] != null) {
1139 if ($type != 'bank-transfer') {
1140 if ($format == 'FRST' && $fac[12] != 'FRST') {
1141 continue;
1142 }
1143 if ($format == 'RCUR' && $fac[12] != 'RCUR') {
1144 continue;
1145 }
1146 }
1147
1148 $verif = checkSwiftForAccount(null, $fac[10]);
1149 if ($verif) {
1150 $verif = checkIbanForAccount(null, $fac[11]);
1151 }
1152
1153 if ($verif) {
1154 $factures_prev[$i] = $fac;
1155 /* second array necessary for BonPrelevement */
1156 $factures_prev_id[$i] = $fac[0];
1157 $i++;
1158 //dol_syslog(__METHOD__."::RIB is ok", LOG_DEBUG);
1159 } else {
1160 if ($type != 'bank-transfer') {
1161 $tmpsoc->id = $fac[2];
1162 $tmpsoc->name = $fac[8];
1163 $invoice_url = "<a href='" . DOL_URL_ROOT . '/compta/facture/card.php?facid=' . $fac[0] . "'>" . $fac[9] . "</a>";
1164 $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1165 $this->thirdparty_in_error[$tmpsoc->id] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1166 $error++;
1167 }
1168 if ($type == 'bank-transfer' && $sourcetype != 'salary') {
1169 $tmpsoc->id = $fac[2];
1170 $tmpsoc->name = $fac[8];
1171 $invoice_url = "<a href='" . DOL_URL_ROOT . '/fourn/facture/card.php?facid=' . $fac[0] . "'>" . $fac[9] . "</a>";
1172 $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1173 $this->thirdparty_in_error[$tmpsoc->id] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1174 $error++;
1175 }
1176 if ($type == 'bank-transfer' && $sourcetype == 'salary') {
1177 $tmpuser->id = $fac[2];
1178 $tmpuser->firstname = $fac[8];
1179 $salary_url = "<a href='" . DOL_URL_ROOT . '/salaries/card.php?id=' . $fac[0] . "'>" . $fac[0] . "</a>";
1180 $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for salary " . $salary_url . " for employee " . $tmpuser->getNomUrl(0);
1181 $this->thirdparty_in_error[$tmpuser->id] = "Error on default bank number IBAN/BIC for salary " . $salary_url . " for employee " . $tmpuser->getNomUrl(0);
1182 $error++;
1183 }
1184 dol_syslog(__METHOD__ . " Check BAN Error on default bank number IBAN/BIC reported by verif(): " . implode(', ', $fac), LOG_WARNING);
1185 }
1186 } else {
1187 dol_syslog(__METHOD__ . " Check BAN Failed to read company", LOG_WARNING);
1188 }
1189 /*
1190 } else {
1191 dol_syslog(__METHOD__." Check BAN Failed to read invoice", LOG_WARNING);
1192 }
1193 */
1194 }
1195 } else {
1196 dol_syslog(__METHOD__ . " Check BAN No invoice to process", LOG_WARNING);
1197 }
1198 }
1199
1200 $ok = 0;
1201
1202 // Withdraw invoices in factures_prev array
1203 $out = count($factures_prev) . " invoices will be included.";
1204 //print $out."\n";
1205 dol_syslog($out);
1206
1207 // Return warning
1208 /*$i=0;
1209 foreach ($this->thirdparty_in_error as $key => $val)
1210 {
1211 if ($i < 10) setEventMessages($val, null, 'warnings');
1212 else setEventMessages('More error were discarded...', null, 'warnings');
1213 $i++;
1214 }*/
1215
1216 if (count($factures_prev) > 0) {
1217 if ($mode == 'real') {
1218 $ok = 1;
1219 } else {
1220 print $langs->trans("ModeWarning"); // "Option for real mode was not set, we stop after this simulation\n";
1221 }
1222 }
1223 if ($ok) {
1224 /*
1225 * We are in real mode.
1226 * We create order and build file into disk
1227 */
1228 $this->db->begin();
1229
1230 $now = dol_now();
1231 $ref = '';
1232
1233 /*
1234 * Process order generation
1235 */
1236 if (!$error) {
1237 $ref = substr($year, -2) . $month;
1238
1239 // Get next free number for the ref of bon prelevement
1240 $sql = "SELECT substring(ref from char_length(ref) - 1)"; // To extract "YYMMXX" from "TYYMMXX"
1241 $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons";
1242 $sql .= " WHERE ref LIKE '_" . $this->db->escape($ref) . "%'";
1243 $sql .= " AND entity = " . ((int) $conf->entity);
1244 $sql .= " ORDER BY ref DESC LIMIT 1";
1245
1246 dol_syslog(get_class($this) . " get next free number", LOG_DEBUG);
1247 $resql = $this->db->query($sql);
1248
1249 if ($resql) {
1250 $row = $this->db->fetch_row($resql);
1251
1252 // Build the new ref
1253 $ref = "T" . $ref . sprintf("%02d", (intval($row[0]) + 1));
1254
1255 // $conf->abc->dir_output may be:
1256 // /home/ldestailleur/git/dolibarr_15.0/documents/abc/
1257 // or
1258 // /home/ldestailleur/git/dolibarr_15.0/documents/X/abc with X >= 2 with multicompany.
1259 if ($type != 'bank-transfer') {
1260 $dir = $conf->prelevement->dir_output . '/receipts';
1261 } else {
1262 $dir = $conf->paymentbybanktransfer->dir_output . '/receipts';
1263 }
1264 if (!is_dir($dir)) {
1265 dol_mkdir($dir);
1266 }
1267
1268 if (isModEnabled('multicompany')) {
1269 $labelentity = $conf->entity;
1270 $this->filename = $dir . '/' . $ref . '-' . $labelentity . '.xml';
1271 } else {
1272 $this->filename = $dir . '/' . $ref . '.xml';
1273 }
1274
1275 // Create withdraw order in database
1276 $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_bons (";
1277 $sql .= "ref, entity, datec, type, fk_bank_account";
1278 $sql .= ") VALUES (";
1279 $sql .= "'" . $this->db->escape($ref) . "'";
1280 $sql .= ", " . ((int) $conf->entity);
1281 $sql .= ", '" . $this->db->idate($now) . "'";
1282 $sql .= ", '" . ($type == 'bank-transfer' ? 'bank-transfer' : 'debit-order') . "'";
1283 $sql .= ", " . ((int) $fk_bank_account);
1284 $sql .= ")";
1285
1286 $resql = $this->db->query($sql);
1287
1288
1289 if ($resql) {
1290 $prev_id = $this->db->last_insert_id(MAIN_DB_PREFIX . "prelevement_bons");
1291 $this->id = $prev_id;
1292 $this->ref = $ref;
1293 } else {
1294 $error++;
1295 dol_syslog(__METHOD__ . " Create withdraw receipt " . $this->db->lasterror(), LOG_ERR);
1296 }
1297 } else {
1298 $error++;
1299 dol_syslog(__METHOD__ . " Get last withdraw receipt " . $this->db->lasterror(), LOG_ERR);
1300 }
1301 }
1302
1303 if (!$error) {
1304 dol_syslog(__METHOD__ . " Now loop on each document to insert them in llx_prelevement_demande");
1305
1306 // Add lines for the bon
1307 if (count($factures_prev) > 0) {
1308 foreach ($factures_prev as $fac) { // Add a link in database for each invoice ro salary
1309 /*
1310 * Add standing order. This add record into llx_prelevement_lignes and llx_prelevement
1311 *
1312 * $fac[0] : invoice_id
1313 * $fac[1] : ???
1314 * $fac[2] : third party id
1315 * $fac[3] : banque
1316 * $fac[4] : guichet
1317 * $fac[5] : number
1318 * $fac[6] : cle rib
1319 * $fac[7] : amount
1320 * $fac[8] : client nom
1321 * $fac[9] : Invoice ref
1322 * $fac[10] : BIC
1323 * $fac[11] : IBAN
1324 * $fac[12] : frstrcur
1325 */
1326 $ri = $this->AddFacture($fac[0], $fac[2], $fac[8], $fac[7], $fac[3], $fac[4], $fac[5], $fac[6], $type, $sourcetype);
1327
1328 if ($ri != 0) {
1329 $error++;
1330 }
1331
1332 // Update invoice requests as done
1333 $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_demande";
1334 $sql .= " SET traite = 1";
1335 $sql .= ", date_traite = '" . $this->db->idate($now) . "'";
1336 $sql .= ", fk_prelevement_bons = " . ((int) $this->id);
1337 $sql .= " WHERE rowid = " . ((int) $fac[1]);
1338
1339 $resql = $this->db->query($sql);
1340 if (!$resql) {
1341 $error++;
1342 $this->errors[] = $this->db->lasterror();
1343 dol_syslog(__METHOD__ . " Update Error=" . $this->db->lasterror(), LOG_ERR);
1344 }
1345 }
1346 }
1347 }
1348
1349 if (!$error) {
1350 /*
1351 * Create file of type='direct-debit' for direct debit order or type='bank-transfer' for credit transfer into a XML file
1352 */
1353
1354 dol_syslog(__METHOD__ . " Init direct debit or credit transfer file for " . count($factures_prev) . " invoices", LOG_DEBUG);
1355
1356 if (count($factures_prev) > 0) {
1357 $this->date_echeance = $datetimeprev;
1358 $this->reference_remise = $ref;
1359
1360 $account = new Account($this->db);
1361 if ($account->fetch($fk_bank_account) > 0) {
1362 $this->emetteur_code_banque = $account->code_banque;
1363 $this->emetteur_code_guichet = $account->code_guichet;
1364 $this->emetteur_numero_compte = $account->number;
1365 $this->emetteur_number_key = $account->cle_rib;
1366 $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
1367 $this->emetteur_iban = $account->iban;
1368 $this->emetteur_bic = $account->bic;
1369
1370 $this->emetteur_ics = (($type == 'bank-transfer' && getDolGlobalString("SEPA_USE_IDS")) ? $account->ics_transfer : $account->ics); // Example "FR78ZZZ123456"
1371
1372 $this->raison_sociale = $account->proprio;
1373 }
1374 $this->factures = $factures_prev_id;
1375 $this->context['factures_prev'] = $factures_prev;
1376 // Generation of direct debit or credit transfer file $this->filename (May be a SEPA file for european countries)
1377 // This also set the property $this->total with amount that is included into file
1378 $userid = 0;
1379 if ($sourcetype == 'salary') {
1380 $userid = $this->context['factures_prev'][0][2];
1381 }
1382 $result = $this->generate($format, $executiondate, $type, $fk_bank_account, $userid);
1383 if ($result < 0) {
1384 //var_dump($this->error);
1385 //var_dump($this->invoice_in_error);
1386 $error++;
1387 }
1388 }
1389 dol_syslog(__METHOD__ . " Bank order file has been generated under filename " . $this->filename, LOG_DEBUG);
1390 }
1391
1392
1393 /*
1394 * Update total defined after generation of file
1395 */
1396 if (!$error) {
1397 $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_bons";
1398 $sql .= " SET amount = " . price2num($this->total);
1399 $sql .= " WHERE rowid = " . ((int) $this->id);
1400 $sql .= " AND entity = " . ((int) $conf->entity);
1401 $resql = $this->db->query($sql);
1402
1403 if (!$resql) {
1404 $error++;
1405 dol_syslog(__METHOD__ . " Error update total: " . $this->db->error(), LOG_ERR);
1406 }
1407 }
1408
1409 if (!$error && !$notrigger) {
1410 $triggername = 'DIRECT_DEBIT_ORDER_CREATE';
1411 if ($type != 'bank-transfer') {
1412 $triggername = 'CREDIT_TRANSFER_ORDER_CREATE';
1413 }
1414
1415 // Call trigger
1416 $result = $this->call_trigger($triggername, $user);
1417 if ($result < 0) {
1418 $error++;
1419 }
1420 // End call triggers
1421 }
1422
1423 if (!$error) {
1424 $this->db->commit();
1425 return count($factures_prev); // The error of failed lines are into $this->invoice_in_error and $this->thirdparty_in_error
1426 } else {
1427 $this->db->rollback();
1428 return -1;
1429 }
1430 } else {
1431 return 0;
1432 }
1433 }
1434
1435
1443 public function delete($user = null, $notrigger = 0)
1444 {
1445 $this->db->begin();
1446
1447 $error = 0;
1448 $resql1 = $resql2 = $resql3 = $resql4 = 0;
1449
1450 if (!$notrigger) {
1451 $triggername = 'DIRECT_DEBIT_ORDER_DELETE';
1452 if ($this->type == 'bank-transfer') {
1453 $triggername = 'PAYMENTBYBANKTRANFER_DELETE';
1454 }
1455 // Call trigger
1456 $result = $this->call_trigger($triggername, $user);
1457 if ($result < 0) {
1458 $error++;
1459 }
1460 // End call triggers
1461 }
1462
1463 if (!$error) {
1464 $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) . ")";
1465 $resql1 = $this->db->query($sql);
1466 if (!$resql1) {
1467 dol_print_error($this->db);
1468 }
1469 }
1470
1471 if (!$error) {
1472 $sql = "DELETE FROM " . MAIN_DB_PREFIX . "prelevement_lignes WHERE fk_prelevement_bons = " . ((int) $this->id);
1473 $resql2 = $this->db->query($sql);
1474 if (!$resql2) {
1475 dol_print_error($this->db);
1476 }
1477 }
1478
1479 if (!$error) {
1480 $sql = "DELETE FROM " . MAIN_DB_PREFIX . "prelevement_bons WHERE rowid = " . ((int) $this->id);
1481 $resql3 = $this->db->query($sql);
1482 if (!$resql3) {
1483 dol_print_error($this->db);
1484 }
1485 }
1486
1487 if (!$error) {
1488 $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_demande SET fk_prelevement_bons = NULL, traite = 0 WHERE fk_prelevement_bons = " . ((int) $this->id);
1489 $resql4 = $this->db->query($sql);
1490 if (!$resql4) {
1491 dol_print_error($this->db);
1492 }
1493 }
1494
1495 if ($resql1 && $resql2 && $resql3 && $resql4 && !$error) {
1496 $this->db->commit();
1497 return 1;
1498 } else {
1499 $this->db->rollback();
1500 return -1;
1501 }
1502 }
1503
1504
1515 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1516 {
1517 global $conf, $langs, $hookmanager;
1518
1519 if (!empty($conf->dol_no_mouse_hover)) {
1520 $notooltip = 1; // Force disable tooltips
1521 }
1522
1523 $result = '';
1524
1525 $labeltoshow = 'PaymentByDirectDebit';
1526 if (!empty($this->type) && $this->type == 'bank-transfer') {
1527 $labeltoshow = 'PaymentByBankTransfer';
1528 }
1529
1530 $label = img_picto('', $this->picto) . ' <u>' . $langs->trans($labeltoshow) . '</u> ' . $this->getLibStatut(5);
1531 $label .= '<br>';
1532 $label .= '<b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
1533 if (isset($this->amount)) {
1534 $label .= '<br><b>' . $langs->trans("Amount") . ":</b> " . price($this->amount);
1535 }
1536 if (isset($this->date_trans)) {
1537 $label .= '<br><b>' . $langs->trans("TransData") . ":</b> " . dol_print_date($this->date_trans, 'dayhour', 'tzuserrel');
1538 }
1539 /*if (isset($this->date_credit)) {
1540 $label .= '<br><b>'.$langs->trans("TransData").":</b> ".dol_print_date($this->date_credit, 'dayhour', 'tzuserrel');
1541 }*/
1542
1543 $url = DOL_URL_ROOT . '/compta/prelevement/card.php?id=' . $this->id;
1544 if (!empty($this->type) && $this->type == 'bank-transfer') {
1545 $url = DOL_URL_ROOT . '/compta/prelevement/card.php?id=' . $this->id;
1546 }
1547
1548 if ($option != 'nolink') {
1549 // Add param to save lastsearch_values or not
1550 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1551 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1552 $add_save_lastsearch_values = 1;
1553 }
1554 if ($add_save_lastsearch_values) {
1555 $url .= '&save_lastsearch_values=1';
1556 }
1557 }
1558
1559 $linkclose = '';
1560 if (empty($notooltip)) {
1561 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1562 $label = $langs->trans("ShowMyObject");
1563 $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
1564 }
1565 $linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"';
1566 $linkclose .= ' class="classfortooltip' . ($morecss ? ' ' . $morecss : '') . '"';
1567 } else {
1568 $linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
1569 }
1570
1571 $linkstart = '<a href="' . $url . '"';
1572 $linkstart .= $linkclose . '>';
1573 $linkend = '</a>';
1574
1575 $result .= $linkstart;
1576 if ($withpicto) {
1577 $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);
1578 }
1579 if ($withpicto != 2) {
1580 $result .= $this->ref;
1581 }
1582 $result .= $linkend;
1583
1584 global $action, $hookmanager;
1585 $hookmanager->initHooks(array('banktransferdao'));
1586 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1587 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1588 if ($reshook > 0) {
1589 $result = $hookmanager->resPrint;
1590 } else {
1591 $result .= $hookmanager->resPrint;
1592 }
1593
1594 return $result;
1595 }
1596
1597
1604 public function deleteNotificationById($rowid)
1605 {
1606 $sql = "DELETE FROM " . MAIN_DB_PREFIX . "notify_def";
1607 $sql .= " WHERE rowid = " . ((int) $rowid);
1608
1609 if ($this->db->query($sql)) {
1610 return 0;
1611 } else {
1612 return -1;
1613 }
1614 }
1615
1623 public function deleteNotification($user, $action)
1624 {
1625 if (is_object($user)) {
1626 $userid = $user->id;
1627 } else { // If user is an id
1628 $userid = $user;
1629 }
1630
1631 $sql = "DELETE FROM " . MAIN_DB_PREFIX . "notify_def";
1632 $sql .= " WHERE fk_user=" . ((int) $userid) . " AND fk_action='" . $this->db->escape($action) . "'";
1633
1634 if ($this->db->query($sql)) {
1635 return 0;
1636 } else {
1637 return -1;
1638 }
1639 }
1640
1641 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1650 public function addNotification($db, $user, $action)
1651 {
1652 // phpcs:enable
1653 $result = 0;
1654
1655 if (is_object($user)) {
1656 $userid = $user->id;
1657 } else { // If user is an id
1658 $userid = $user;
1659 }
1660
1661 if ($this->deleteNotification($user, $action) == 0) {
1662 $now = dol_now();
1663
1664 $sql = "INSERT INTO " . MAIN_DB_PREFIX . "notify_def (datec,fk_user, fk_soc, fk_contact, fk_action)";
1665 $sql .= " VALUES ('" . $this->db->idate($now) . "', " . ((int) $userid) . ", 'NULL', 'NULL', '" . $this->db->escape($action) . "')";
1666
1667 dol_syslog("adnotiff: " . $sql);
1668 if ($this->db->query($sql)) {
1669 $result = 0;
1670 } else {
1671 $result = -1;
1672 dol_syslog(get_class($this) . "::addNotification Error $result");
1673 }
1674 }
1675
1676 return $result;
1677 }
1678
1679
1694 public function generate($format = 'ALL', $executiondate = 0, $type = 'direct-debit', $fk_bank_account = 0, $forsalary = 0)
1695 {
1696 global $conf, $langs, $mysoc;
1697
1698 //TODO: Optimize code to read lines in a single function
1699
1700 // Clean params
1701 if (empty($fk_bank_account)) {
1702 $fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
1703 }
1704
1705 $result = 0;
1706
1707 dol_syslog(get_class($this) . "::generate build file=" . $this->filename . " type=" . $type);
1708
1709 $this->file = fopen($this->filename, "w");
1710 if ($this->file == false) {
1711 $this->error = $langs->trans('ErrorFailedToOpenFile', $this->filename);
1712 return -1;
1713 }
1714
1715 $found = 0;
1716 $this->total = 0;
1717
1718 // Build file for European countries
1719 if ($mysoc->isInEEC()) {
1720 $found++;
1721
1722 if ($type != 'bank-transfer') {
1726 // SEPA Initialisation
1727 $CrLf = "\n";
1728
1729 $now = dol_now();
1730
1731 $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S');
1732
1733 $date_actu = $now;
1734 if (!empty($executiondate)) {
1735 $date_actu = $executiondate;
1736 }
1737
1738 $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d');
1739 $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S');
1740 $fileDebiteurSection = '';
1741 $fileEmetteurSection = '';
1742 $i = 0;
1743
1744 /*
1745 * Section Debitor (sepa Debiteurs block lines)
1746 */
1747
1748 $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
1749 $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1750 $sql .= " f.ref as reffac, p.fk_facture as idfac,";
1751 $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
1752 $sql .= " FROM";
1753 $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1754 $sql .= " " . MAIN_DB_PREFIX . "facture as f,";
1755 $sql .= " " . MAIN_DB_PREFIX . "prelevement as p,";
1756 $sql .= " " . MAIN_DB_PREFIX . "societe as soc,";
1757 $sql .= " " . MAIN_DB_PREFIX . "c_country as c,";
1758 $sql .= " " . MAIN_DB_PREFIX . "societe_rib as rib";
1759 $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
1760 $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1761 $sql .= " AND p.fk_facture = f.rowid";
1762 $sql .= " AND f.fk_soc = soc.rowid";
1763 $sql .= " AND soc.fk_pays = c.rowid";
1764 $sql .= " AND rib.fk_soc = f.fk_soc";
1765 $sql .= " AND rib.default_rib = 1";
1766 $sql .= " AND rib.type = 'ban'";
1767
1768 // Define $fileDebiteurSection. One section DrctDbtTxInf per invoice.
1769 $resql = $this->db->query($sql);
1770 if ($resql) {
1771 $cachearraytotestduplicate = array();
1772
1773 $num = $this->db->num_rows($resql);
1774 while ($i < $num) {
1775 $obj = $this->db->fetch_object($resql);
1776
1777 if (!empty($cachearraytotestduplicate[$obj->idfac])) {
1778 $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
1779 $this->invoice_in_error[$obj->idfac] = $this->error;
1780 $result = -2;
1781 break;
1782 }
1783 $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
1784
1785 $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
1786
1787 $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);
1788
1789 $this->total = $this->total + $obj->somme;
1790 $i++;
1791 }
1792 $nbtotalDrctDbtTxInf = $i;
1793 } else {
1794 $this->error = $this->db->lasterror();
1795 fwrite($this->file, 'ERROR DEBITOR ' . $sql . $CrLf); // DEBITOR = Customers
1796 $result = -2;
1797 }
1798
1799 // Define $fileEmetteurSection. Start of block PmtInf. Will contains all $nbtotalDrctDbtTxInf
1800 if ($result != -2) {
1801 $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type, $fk_bank_account);
1802 }
1803
1804 if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) {
1805 $this->total = number_format((float) price2num($this->total, 'MT'), 2, ".", "");
1806 }
1807
1811 // SEPA File Header
1812 fwrite($this->file, '<' . '?xml version="1.0" encoding="UTF-8" standalone="yes"?' . '>' . $CrLf);
1813 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);
1814 fwrite($this->file, ' <CstmrDrctDbtInitn>' . $CrLf);
1815 // SEPA Group header
1816 fwrite($this->file, ' <GrpHdr>' . $CrLf);
1817 fwrite($this->file, ' <MsgId>' . ('DD/' . $dateTime_YMD . '/REF' . $this->id) . '</MsgId>' . $CrLf);
1818 fwrite($this->file, ' <CreDtTm>' . $dateTime_ECMA . '</CreDtTm>' . $CrLf);
1819 fwrite($this->file, ' <NbOfTxs>' . $i . '</NbOfTxs>' . $CrLf);
1820 fwrite($this->file, ' <CtrlSum>' . $this->total . '</CtrlSum>' . $CrLf);
1821 fwrite($this->file, ' <InitgPty>' . $CrLf);
1822 fwrite($this->file, ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf);
1823 fwrite($this->file, ' <Id>' . $CrLf);
1824 fwrite($this->file, ' <PrvtId>' . $CrLf);
1825 fwrite($this->file, ' <Othr>' . $CrLf);
1826 fwrite($this->file, ' <Id>' . $this->emetteur_ics . '</Id>' . $CrLf);
1827 fwrite($this->file, ' </Othr>' . $CrLf);
1828 fwrite($this->file, ' </PrvtId>' . $CrLf);
1829 fwrite($this->file, ' </Id>' . $CrLf);
1830 fwrite($this->file, ' </InitgPty>' . $CrLf);
1831 fwrite($this->file, ' </GrpHdr>' . $CrLf);
1832 // SEPA File Emetteur
1833 if ($result != -2) {
1834 fwrite($this->file, $fileEmetteurSection);
1835 }
1836 // SEPA File Debiteurs
1837 if ($result != -2) {
1838 fwrite($this->file, $fileDebiteurSection);
1839 }
1840 // SEPA FILE FOOTER
1841 fwrite($this->file, ' </PmtInf>' . $CrLf);
1842 fwrite($this->file, ' </CstmrDrctDbtInitn>' . $CrLf);
1843 fwrite($this->file, '</Document>' . $CrLf);
1844 } else {
1848 // SEPA Initialisation
1849 $CrLf = "\n";
1850
1851 $now = dol_now();
1852
1853 $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S');
1854
1855 $date_actu = $now;
1856 if (!empty($executiondate)) {
1857 $date_actu = $executiondate;
1858 }
1859
1860 $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d');
1861 $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S');
1862 $fileCrediteurSection = '';
1863 $fileEmetteurSection = '';
1864 $i = 0;
1865
1866 /*
1867 * Section Creditor (sepa Crediteurs block lines)
1868 */
1869 if (!empty($forsalary)) {
1870 $sql = "SELECT u.rowid as userId, u.address, u.zip, u.town, c.code as country_code, CONCAT(u.firstname,' ',u.lastname) as nom,";
1871 $sql .= " pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1872 $sql .= " s.ref as reffac, p.fk_salary as idfac,";
1873 $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, '' as rum, '' as date_rum";
1874 $sql .= " FROM";
1875 $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1876 $sql .= " " . MAIN_DB_PREFIX . "salary as s,";
1877 $sql .= " " . MAIN_DB_PREFIX . "prelevement as p,";
1878 $sql .= " " . MAIN_DB_PREFIX . "user as u";
1879 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_country as c ON u.fk_country = c.rowid,";
1880 $sql .= " " . MAIN_DB_PREFIX . "user_rib as rib";
1881 $sql .= " WHERE pl.fk_prelevement_bons=" . ((int) $this->id);
1882 $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1883 $sql .= " AND p.fk_salary = s.rowid";
1884 $sql .= " AND s.fk_user = u.rowid";
1885 $sql .= " AND rib.fk_user = s.fk_user";
1886 } else {
1887 $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
1888 $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1889 $sql .= " f.ref as reffac, f.ref_supplier as fac_ref_supplier, p.fk_facture_fourn as idfac,";
1890 $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
1891 $sql .= " FROM";
1892 $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1893 $sql .= " " . MAIN_DB_PREFIX . "facture_fourn as f,";
1894 $sql .= " " . MAIN_DB_PREFIX . "prelevement as p,";
1895 $sql .= " " . MAIN_DB_PREFIX . "societe as soc";
1896 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_country as c ON soc.fk_pays = c.rowid,";
1897 $sql .= " " . MAIN_DB_PREFIX . "societe_rib as rib";
1898 $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
1899 $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1900 $sql .= " AND p.fk_facture_fourn = f.rowid";
1901 $sql .= " AND f.fk_soc = soc.rowid";
1902 $sql .= " AND rib.fk_soc = f.fk_soc";
1903 $sql .= " AND rib.default_rib = 1";
1904 $sql .= " AND rib.type = 'ban'";
1905 }
1906 // Define $fileCrediteurSection. One section DrctDbtTxInf per invoice.
1907 $resql = $this->db->query($sql);
1908 if ($resql) {
1909 $cachearraytotestduplicate = array();
1910
1911 $num = $this->db->num_rows($resql);
1912 while ($i < $num) {
1913 $obj = $this->db->fetch_object($resql);
1914 if (!empty($cachearraytotestduplicate[$obj->idfac])) {
1915 $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
1916 $this->invoice_in_error[$obj->idfac] = $this->error;
1917 $result = -2;
1918 break;
1919 }
1920 $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
1921
1922 $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
1923 $refobj = $obj->reffac;
1924 if (empty($refobj) && !empty($forsalary)) { // If ref of salary not defined, we force a value
1925 $refobj = "SAL" . $obj->idfac;
1926 }
1927
1928 $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);
1929
1930 $this->total = $this->total + $obj->somme;
1931 $i++;
1932 }
1933 $nbtotalDrctDbtTxInf = $i;
1934 } else {
1935 $this->error = $this->db->lasterror();
1936 fwrite($this->file, 'ERROR CREDITOR ' . $sql . $CrLf); // CREDITORS = Suppliers
1937 $result = -2;
1938 }
1939 // Define $fileEmetteurSection. Start of block PmtInf. Will contains all $nbtotalDrctDbtTxInf
1940 if ($result != -2) {
1941 $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type);
1942 }
1943
1944 if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) {
1945 $this->total = number_format((float) price2num($this->total, 'MT'), 2, ".", "");
1946 }
1947
1951 // SEPA File Header
1952 fwrite($this->file, '<' . '?xml version="1.0" encoding="UTF-8" standalone="yes"?' . '>' . $CrLf);
1953 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);
1954 fwrite($this->file, ' <CstmrCdtTrfInitn>' . $CrLf);
1955 // SEPA Group header
1956 fwrite($this->file, ' <GrpHdr>' . $CrLf);
1957 fwrite($this->file, ' <MsgId>' . ('TRF/' . $dateTime_YMD . '/REF' . $this->id) . '</MsgId>' . $CrLf);
1958 fwrite($this->file, ' <CreDtTm>' . $dateTime_ECMA . '</CreDtTm>' . $CrLf);
1959 fwrite($this->file, ' <NbOfTxs>' . $i . '</NbOfTxs>' . $CrLf);
1960 fwrite($this->file, ' <CtrlSum>' . $this->total . '</CtrlSum>' . $CrLf);
1961 fwrite($this->file, ' <InitgPty>' . $CrLf);
1962 fwrite($this->file, ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf);
1963 fwrite($this->file, ' <Id>' . $CrLf);
1964 fwrite($this->file, ' <PrvtId>' . $CrLf);
1965 fwrite($this->file, ' <Othr>' . $CrLf);
1966 fwrite($this->file, ' <Id>' . $this->emetteur_ics . '</Id>' . $CrLf);
1967 fwrite($this->file, ' </Othr>' . $CrLf);
1968 fwrite($this->file, ' </PrvtId>' . $CrLf);
1969 fwrite($this->file, ' </Id>' . $CrLf);
1970 fwrite($this->file, ' </InitgPty>' . $CrLf);
1971 fwrite($this->file, ' </GrpHdr>' . $CrLf);
1972 // SEPA File Emetteur (mycompany)
1973 if ($result != -2) {
1974 fwrite($this->file, $fileEmetteurSection);
1975 }
1976 // SEPA File Creditors
1977 if ($result != -2) {
1978 fwrite($this->file, $fileCrediteurSection);
1979 }
1980 // SEPA FILE FOOTER
1981 fwrite($this->file, ' </PmtInf>' . $CrLf);
1982 fwrite($this->file, ' </CstmrCdtTrfInitn>' . $CrLf);
1983 fwrite($this->file, '</Document>' . $CrLf);
1984 }
1985 }
1986
1987 // Build file for Other Countries with unknown format
1988 if (!$found) {
1989 if ($type != 'bank-transfer') {
1990 $sql = "SELECT pl.amount";
1991 $sql .= " FROM";
1992 $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1993 $sql .= " " . MAIN_DB_PREFIX . "facture as f,";
1994 $sql .= " " . MAIN_DB_PREFIX . "prelevement as p";
1995 $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
1996 $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1997 $sql .= " AND p.fk_facture = f.rowid";
1998
1999 // Lines
2000 $i = 0;
2001 $resql = $this->db->query($sql);
2002 if ($resql) {
2003 $num = $this->db->num_rows($resql);
2004
2005 while ($i < $num) {
2006 $obj = $this->db->fetch_object($resql);
2007 $this->total = $this->total + $obj->amount;
2008
2009 // TODO Write record into file
2010 $i++;
2011 }
2012 } else {
2013 $result = -2;
2014 }
2015 } else {
2016 $sql = "SELECT pl.amount";
2017 $sql .= " FROM";
2018 $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
2019 $sql .= " " . MAIN_DB_PREFIX . "facture_fourn as f,";
2020 $sql .= " " . MAIN_DB_PREFIX . "prelevement as p";
2021 $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
2022 $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
2023 $sql .= " AND p.fk_facture_fourn = f.rowid";
2024 // Lines
2025 $i = 0;
2026 $resql = $this->db->query($sql);
2027 if ($resql) {
2028 $num = $this->db->num_rows($resql);
2029
2030 while ($i < $num) {
2031 $obj = $this->db->fetch_object($resql);
2032 $this->total = $this->total + $obj->amount;
2033
2034 // TODO Write record into file
2035 $i++;
2036 }
2037 } else {
2038 $result = -2;
2039 }
2040 }
2041
2042 $langs->load('withdrawals');
2043
2044 // TODO Add here code to generate a generic file
2045 fwrite($this->file, $langs->transnoentitiesnoconv('WithdrawalFileNotCapable', $mysoc->country_code));
2046 }
2047
2048 fclose($this->file);
2049 dolChmod($this->filename);
2050
2051 return $result;
2052 }
2053
2054
2063 public static function buildRumNumber($row_code_client, $row_datec, $row_drum)
2064 {
2065 global $langs;
2066
2067 $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)
2068
2069 // 3 char + '-' + 12 + '-' + id + '-' + code Must be lower than 32.
2070 return $pre . '-' . dol_print_date($row_datec, 'dayhourlogsmall') . '-' . dol_trunc($row_drum . ($row_code_client ? '-' . $row_code_client : ''), 13, 'right', 'UTF-8', 1);
2071 }
2072
2073
2074 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2091 public function EnregDestinataire($rowid, $client_nom, $rib_banque, $rib_guichet, $rib_number, $amount, $ref, $facid, $rib_dom = '', $type = 'direct-debit')
2092 {
2093 // phpcs:enable
2094 fwrite($this->file, "06");
2095 fwrite($this->file, "08"); // Prelevement ordinaire
2096
2097 fwrite($this->file, " "); // Zone Reservee B2
2098
2099 fwrite($this->file, $this->emetteur_ics); // ICS
2100
2101 // Date d'echeance C1
2102
2103 fwrite($this->file, " ");
2104 fwrite($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
2105 fwrite($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
2106
2107 // Raison Sociale Destinataire C2
2108
2109 fwrite($this->file, substr(strtoupper($client_nom) . " ", 0, 24));
2110
2111 // Address optional D1
2112 $address = strtr($rib_dom, array(" " => "-", chr(13) => " ", chr(10) => ""));
2113 fwrite($this->file, substr($address . " ", 0, 24));
2114
2115 // Zone Reservee D2
2116
2117 fwrite($this->file, substr(" ", 0, 8));
2118
2119 // Code Guichet D3
2120
2121 fwrite($this->file, $rib_guichet);
2122
2123 // Numero de compte D4
2124
2125 fwrite($this->file, substr("000000000000000" . $rib_number, -11));
2126
2127 // Zone E Montant
2128
2129 $montant = (round($amount, 2) * 100);
2130
2131 fwrite($this->file, substr("000000000000000" . $montant, -16));
2132
2133 // Label F
2134
2135 fwrite($this->file, substr("*_" . $ref . "_RDVnet" . $rowid . " ", 0, 31));
2136
2137 // Code etablissement G1
2138
2139 fwrite($this->file, $rib_banque);
2140
2141 // Zone Reservee G2
2142
2143 fwrite($this->file, substr(" ", 0, 5));
2144
2145 fwrite($this->file, "\n");
2146 }
2147
2148
2149 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2175 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 = '')
2176 {
2177 // phpcs:enable
2178 global $conf;
2179
2180 if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) {
2181 $row_somme = number_format((float) price2num($row_somme, 'MT'), 2, ".", "");
2182 } else {
2183 $row_somme = round((float) $row_somme, 2);
2184 }
2185
2186 include_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php';
2187
2188 $CrLf = "\n";
2189 $Rowing = sprintf("%010d", $row_idfac);
2190
2191 // Define value for RUM
2192 // Example: RUM-CustomerCode-CustomerBankAccountId-01424448606 (note: Date is the timestamp of the date of creation of CustomerBankAccountId)
2193 $Rum = (empty($row_rum) ? $this->buildRumNumber($row_code_client, $row_datec, $row_drum) : $row_rum);
2194
2195 // Define date of RUM signature
2196 $DtOfSgntr = dol_print_date($row_datec, '%Y-%m-%d');
2197
2198 if ($type != 'bank-transfer') {
2199 // SEPA Paiement Information of buyer for Direct Debit
2200 $XML_DEBITOR = '';
2201 $XML_DEBITOR .= ' <DrctDbtTxInf>' . $CrLf;
2202 $XML_DEBITOR .= ' <PmtId>' . $CrLf;
2203 // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
2204 $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
2205 $XML_DEBITOR .= ' </PmtId>' . $CrLf;
2206 $XML_DEBITOR .= ' <InstdAmt Ccy="EUR">' . $row_somme . '</InstdAmt>' . $CrLf;
2207 $XML_DEBITOR .= ' <DrctDbtTx>' . $CrLf;
2208 $XML_DEBITOR .= ' <MndtRltdInf>' . $CrLf;
2209 $XML_DEBITOR .= ' <MndtId>' . $Rum . '</MndtId>' . $CrLf;
2210 $XML_DEBITOR .= ' <DtOfSgntr>' . $DtOfSgntr . '</DtOfSgntr>' . $CrLf;
2211 $XML_DEBITOR .= ' <AmdmntInd>false</AmdmntInd>' . $CrLf;
2212 $XML_DEBITOR .= ' </MndtRltdInf>' . $CrLf;
2213 $XML_DEBITOR .= ' </DrctDbtTx>' . $CrLf;
2214 $XML_DEBITOR .= ' <DbtrAgt>' . $CrLf;
2215 $XML_DEBITOR .= ' <FinInstnId>' . $CrLf;
2216 $XML_DEBITOR .= ' <BIC>' . $row_bic . '</BIC>' . $CrLf;
2217 $XML_DEBITOR .= ' </FinInstnId>' . $CrLf;
2218 $XML_DEBITOR .= ' </DbtrAgt>' . $CrLf;
2219 $XML_DEBITOR .= ' <Dbtr>' . $CrLf;
2220 $XML_DEBITOR .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))) . '</Nm>' . $CrLf;
2221 $XML_DEBITOR .= ' <PstlAdr>' . $CrLf;
2222 $XML_DEBITOR .= ' <Ctry>' . $row_country_code . '</Ctry>' . $CrLf;
2223 $addressline1 = strtr($row_address, array(chr(13) => ", ", chr(10) => ""));
2224 $addressline2 = strtr($row_zip . (($row_zip && $row_town) ? ' ' : (string) $row_town), array(chr(13) => ", ", chr(10) => ""));
2225 if (trim($addressline1)) {
2226 $XML_DEBITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2227 }
2228 if (trim($addressline2)) {
2229 $XML_DEBITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2230 }
2231 $XML_DEBITOR .= ' </PstlAdr>' . $CrLf;
2232 $XML_DEBITOR .= ' </Dbtr>' . $CrLf;
2233 $XML_DEBITOR .= ' <DbtrAcct>' . $CrLf;
2234 $XML_DEBITOR .= ' <Id>' . $CrLf;
2235 $XML_DEBITOR .= ' <IBAN>' . preg_replace('/\s/', '', $row_iban) . '</IBAN>' . $CrLf;
2236 $XML_DEBITOR .= ' </Id>' . $CrLf;
2237 $XML_DEBITOR .= ' </DbtrAcct>' . $CrLf;
2238 $XML_DEBITOR .= ' <RmtInf>' . $CrLf;
2239 // A string with some information on payment - 140 max
2240 $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
2241 $XML_DEBITOR .= ' </RmtInf>' . $CrLf;
2242 $XML_DEBITOR .= ' </DrctDbtTxInf>' . $CrLf;
2243 return $XML_DEBITOR;
2244 } else {
2245 // SEPA Payment Information of seller for Credit Transfer
2246 $XML_CREDITOR = '';
2247 $XML_CREDITOR .= ' <CdtTrfTxInf>' . $CrLf;
2248 $XML_CREDITOR .= ' <PmtId>' . $CrLf;
2249 // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
2250 $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
2251 $XML_CREDITOR .= ' </PmtId>' . $CrLf;
2252 if (!empty($this->sepa_xml_pti_in_ctti)) {
2253 $XML_CREDITOR .= ' <PmtTpInf>' . $CrLf;
2254
2255 // Can be 'NORM' for normal or 'HIGH' for high priority level
2256 if (getDolGlobalString('PAYMENTBYBANKTRANSFER_FORCE_HIGH_PRIORITY')) {
2257 $instrprty = 'HIGH';
2258 } else {
2259 $instrprty = 'NORM';
2260 }
2261 $XML_CREDITOR .= ' <InstrPrty>' . $instrprty . '</InstrPrty>' . $CrLf;
2262 $XML_CREDITOR .= ' <SvcLvl>' . $CrLf;
2263 $XML_CREDITOR .= ' <Cd>SEPA</Cd>' . $CrLf;
2264 $XML_CREDITOR .= ' </SvcLvl>' . $CrLf;
2265 $XML_CREDITOR .= ' <CtgyPurp>' . $CrLf;
2266 $XML_CREDITOR .= ' <Cd>CORE</Cd>' . $CrLf;
2267 $XML_CREDITOR .= ' </CtgyPurp>' . $CrLf;
2268 $XML_CREDITOR .= ' </PmtTpInf>' . $CrLf;
2269 }
2270 $XML_CREDITOR .= ' <Amt>' . $CrLf;
2271 $XML_CREDITOR .= ' <InstdAmt Ccy="EUR">'.round((float) $row_somme, 2).'</InstdAmt>'.$CrLf;
2272 $XML_CREDITOR .= ' </Amt>' . $CrLf;
2273 /*
2274 $XML_CREDITOR .= ' <DrctDbtTx>'.$CrLf;
2275 $XML_CREDITOR .= ' <MndtRltdInf>'.$CrLf;
2276 $XML_CREDITOR .= ' <MndtId>'.$Rum.'</MndtId>'.$CrLf;
2277 $XML_CREDITOR .= ' <DtOfSgntr>'.$DtOfSgntr.'</DtOfSgntr>'.$CrLf;
2278 $XML_CREDITOR .= ' <AmdmntInd>false</AmdmntInd>'.$CrLf;
2279 $XML_CREDITOR .= ' </MndtRltdInf>'.$CrLf;
2280 $XML_CREDITOR .= ' </DrctDbtTx>'.$CrLf;
2281 */
2282 //$XML_CREDITOR .= ' <ChrgBr>SLEV</ChrgBr>'.$CrLf;
2283 $XML_CREDITOR .= ' <CdtrAgt>' . $CrLf;
2284 $XML_CREDITOR .= ' <FinInstnId>' . $CrLf;
2285 $XML_CREDITOR .= ' <BIC>' . $row_bic . '</BIC>' . $CrLf;
2286 $XML_CREDITOR .= ' </FinInstnId>' . $CrLf;
2287 $XML_CREDITOR .= ' </CdtrAgt>' . $CrLf;
2288 $XML_CREDITOR .= ' <Cdtr>' . $CrLf;
2289 $XML_CREDITOR .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))) . '</Nm>' . $CrLf;
2290 $XML_CREDITOR .= ' <PstlAdr>' . $CrLf;
2291 $XML_CREDITOR .= ' <Ctry>' . $row_country_code . '</Ctry>' . $CrLf;
2292 $addressline1 = strtr($row_address, array(chr(13) => ", ", chr(10) => ""));
2293 $addressline2 = strtr($row_zip . (($row_zip && $row_town) ? ' ' : (string) $row_town), array(chr(13) => ", ", chr(10) => ""));
2294 if (trim($addressline1)) {
2295 $XML_CREDITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2296 }
2297 if (trim($addressline2)) {
2298 $XML_CREDITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2299 }
2300 $XML_CREDITOR .= ' </PstlAdr>' . $CrLf;
2301 $XML_CREDITOR .= ' </Cdtr>' . $CrLf;
2302 $XML_CREDITOR .= ' <CdtrAcct>' . $CrLf;
2303 $XML_CREDITOR .= ' <Id>' . $CrLf;
2304 $XML_CREDITOR .= ' <IBAN>' . preg_replace('/\s/', '', $row_iban) . '</IBAN>' . $CrLf;
2305 $XML_CREDITOR .= ' </Id>' . $CrLf;
2306 $XML_CREDITOR .= ' </CdtrAcct>' . $CrLf;
2307 $XML_CREDITOR .= ' <RmtInf>' . $CrLf;
2308 // A string with some information on payment - 140 max
2309 $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
2310 $XML_CREDITOR .= ' </RmtInf>' . $CrLf;
2311 $XML_CREDITOR .= ' </CdtTrfTxInf>' . $CrLf;
2312 return $XML_CREDITOR;
2313 }
2314 }
2315
2316
2317 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2325 public function EnregEmetteur($type = 'direct-debit')
2326 {
2327 // phpcs:enable
2328 fwrite($this->file, "03");
2329 fwrite($this->file, "08"); // Prelevement ordinaire
2330
2331 fwrite($this->file, " "); // Zone Reservee B2
2332
2333 fwrite($this->file, $this->emetteur_ics); // ICS
2334
2335 // Date d'echeance C1
2336
2337 fwrite($this->file, " ");
2338 fwrite($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
2339 fwrite($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
2340
2341 // Raison Sociale C2
2342
2343 fwrite($this->file, substr($this->raison_sociale . " ", 0, 24));
2344
2345 // Reference de la remise creancier D1 sur 7 caracteres
2346
2347 fwrite($this->file, substr($this->reference_remise . " ", 0, 7));
2348
2349 // Zone Reservee D1-2
2350
2351 fwrite($this->file, substr(" ", 0, 17));
2352
2353 // Zone Reservee D2
2354
2355 fwrite($this->file, substr(" ", 0, 2));
2356 fwrite($this->file, "E");
2357 fwrite($this->file, substr(" ", 0, 5));
2358
2359 // Code Guichet D3
2360
2361 fwrite($this->file, $this->emetteur_code_guichet);
2362
2363 // Numero de compte D4
2364
2365 fwrite($this->file, substr("000000000000000" . $this->emetteur_numero_compte, -11));
2366
2367 // Zone Reservee E
2368
2369 fwrite($this->file, substr(" ", 0, 16));
2370
2371 // Zone Reservee F
2372
2373 fwrite($this->file, substr(" ", 0, 31));
2374
2375 // Code etablissement
2376
2377 fwrite($this->file, $this->emetteur_code_banque);
2378
2379 // Zone Reservee G
2380
2381 fwrite($this->file, substr(" ", 0, 5));
2382
2383 fwrite($this->file, "\n");
2384 }
2385
2386
2387 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2403 public function EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf = '\n', $format = 'FRST', $type = 'direct-debit', $fk_bank_account = 0)
2404 {
2405 // phpcs:enable
2406
2407 // Clean parameters
2408 $dateTime_YMD = dol_print_date($ladate, '%Y%m%d');
2409 $dateTime_ETAD = dol_print_date($ladate, '%Y-%m-%d');
2410 $dateTime_YMDHMS = dol_print_date($ladate, '%Y-%m-%dT%H:%M:%S');
2411
2412 // Clean params
2413 if (empty($fk_bank_account)) {
2414 $fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
2415 }
2416
2417 // Get data of bank account
2418 $account = new Account($this->db);
2419 if ($account->fetch($fk_bank_account) > 0) {
2420 $this->emetteur_code_banque = $account->code_banque;
2421 $this->emetteur_code_guichet = $account->code_guichet;
2422 $this->emetteur_numero_compte = $account->number;
2423 $this->emetteur_number_key = $account->cle_rib;
2424 $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
2425 $this->emetteur_iban = $account->iban;
2426 $this->emetteur_bic = $account->bic;
2427
2428 $this->emetteur_ics = (($type == 'bank-transfer' && getDolGlobalString("SEPA_USE_IDS")) ? $account->ics_transfer : $account->ics); // Ex: PRELEVEMENT_ICS = "FR78ZZZ123456";
2429
2430 $this->raison_sociale = $account->proprio;
2431 }
2432
2433 // Get pending payments
2434 $sql = "SELECT rowid, ref";
2435 $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons as pb";
2436 $sql .= " WHERE pb.rowid = " . ((int) $this->id);
2437
2438 $resql = $this->db->query($sql);
2439 if ($resql) {
2440 $obj = $this->db->fetch_object($resql);
2441
2442 $country = explode(':', $configuration->global->MAIN_INFO_SOCIETE_COUNTRY);
2443 $IdBon = sprintf("%05d", $obj->rowid);
2444 $RefBon = $obj->ref;
2445
2446 if (!empty($configuration->global->SEPA_FORCE_TWO_DECIMAL)) {
2447 $total = number_format((float) price2num($total, 'MT'), 2, ".", "");
2448 }
2449
2450 if ($type != 'bank-transfer') {
2451 // SEPA Paiement Information of my company for Direct Debit
2452 $XML_SEPA_INFO = '';
2453 $XML_SEPA_INFO .= ' <PmtInf>' . $CrLf;
2454 $XML_SEPA_INFO .= ' <PmtInfId>' . ('DD/' . $dateTime_YMD . '/ID' . $IdBon . '-' . $RefBon) . '</PmtInfId>' . $CrLf;
2455 $XML_SEPA_INFO .= ' <PmtMtd>DD</PmtMtd>' . $CrLf;
2456 $XML_SEPA_INFO .= ' <NbOfTxs>' . $nombre . '</NbOfTxs>' . $CrLf;
2457 $XML_SEPA_INFO .= ' <CtrlSum>' . $total . '</CtrlSum>' . $CrLf;
2458 $XML_SEPA_INFO .= ' <PmtTpInf>' . $CrLf;
2459 $XML_SEPA_INFO .= ' <SvcLvl>' . $CrLf;
2460 $XML_SEPA_INFO .= ' <Cd>SEPA</Cd>' . $CrLf;
2461 $XML_SEPA_INFO .= ' </SvcLvl>' . $CrLf;
2462 $XML_SEPA_INFO .= ' <LclInstrm>' . $CrLf;
2463 $XML_SEPA_INFO .= ' <Cd>CORE</Cd>' . $CrLf;
2464 $XML_SEPA_INFO .= ' </LclInstrm>' . $CrLf;
2465 $XML_SEPA_INFO .= ' <SeqTp>' . $format . '</SeqTp>' . $CrLf;
2466 $XML_SEPA_INFO .= ' </PmtTpInf>' . $CrLf;
2467 $XML_SEPA_INFO .= ' <ReqdColltnDt>' . $dateTime_ETAD . '</ReqdColltnDt>' . $CrLf;
2468 $XML_SEPA_INFO .= ' <Cdtr>' . $CrLf;
2469 $XML_SEPA_INFO .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf;
2470 $XML_SEPA_INFO .= ' <PstlAdr>' . $CrLf;
2471 $XML_SEPA_INFO .= ' <Ctry>' . $country[1] . '</Ctry>' . $CrLf;
2472 $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(chr(13) => ", ", chr(10) => ""));
2473 $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) => ""));
2474 if ($addressline1) {
2475 $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2476 }
2477 if ($addressline2) {
2478 $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2479 }
2480 $XML_SEPA_INFO .= ' </PstlAdr>' . $CrLf;
2481 $XML_SEPA_INFO .= ' </Cdtr>' . $CrLf;
2482 $XML_SEPA_INFO .= ' <CdtrAcct>' . $CrLf;
2483 $XML_SEPA_INFO .= ' <Id>' . $CrLf;
2484 $XML_SEPA_INFO .= ' <IBAN>' . preg_replace('/\s/', '', $this->emetteur_iban) . '</IBAN>' . $CrLf;
2485 $XML_SEPA_INFO .= ' </Id>' . $CrLf;
2486 $XML_SEPA_INFO .= ' </CdtrAcct>' . $CrLf;
2487 $XML_SEPA_INFO .= ' <CdtrAgt>' . $CrLf;
2488 $XML_SEPA_INFO .= ' <FinInstnId>' . $CrLf;
2489 $XML_SEPA_INFO .= ' <BIC>' . $this->emetteur_bic . '</BIC>' . $CrLf;
2490 $XML_SEPA_INFO .= ' </FinInstnId>' . $CrLf;
2491 $XML_SEPA_INFO .= ' </CdtrAgt>' . $CrLf;
2492 /* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf;
2493 $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2494 $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2495 $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2496 $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;
2497 $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;
2498 $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2499 $XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/
2500 $XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>' . $CrLf; // Field "Responsible of fees". Must be SLEV
2501 $XML_SEPA_INFO .= ' <CdtrSchmeId>' . $CrLf;
2502 $XML_SEPA_INFO .= ' <Id>' . $CrLf;
2503 $XML_SEPA_INFO .= ' <PrvtId>' . $CrLf;
2504 $XML_SEPA_INFO .= ' <Othr>' . $CrLf;
2505 $XML_SEPA_INFO .= ' <Id>' . $this->emetteur_ics . '</Id>' . $CrLf;
2506 $XML_SEPA_INFO .= ' <SchmeNm>' . $CrLf;
2507 $XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>' . $CrLf;
2508 $XML_SEPA_INFO .= ' </SchmeNm>' . $CrLf;
2509 $XML_SEPA_INFO .= ' </Othr>' . $CrLf;
2510 $XML_SEPA_INFO .= ' </PrvtId>' . $CrLf;
2511 $XML_SEPA_INFO .= ' </Id>' . $CrLf;
2512 $XML_SEPA_INFO .= ' </CdtrSchmeId>' . $CrLf;
2513 } else {
2514 // SEPA Paiement Information of my company for Credit Transfer
2515 $XML_SEPA_INFO = '';
2516 $XML_SEPA_INFO .= ' <PmtInf>' . $CrLf;
2517 $XML_SEPA_INFO .= ' <PmtInfId>' . ('TRF/' . $dateTime_YMD . '/ID' . $IdBon . '-' . $RefBon) . '</PmtInfId>' . $CrLf;
2518 $XML_SEPA_INFO .= ' <PmtMtd>TRF</PmtMtd>' . $CrLf;
2519 //$XML_SEPA_INFO .= ' <BtchBookg>False</BtchBookg>'.$CrLf;
2520 $XML_SEPA_INFO .= ' <NbOfTxs>' . $nombre . '</NbOfTxs>' . $CrLf;
2521 $XML_SEPA_INFO .= ' <CtrlSum>' . $total . '</CtrlSum>' . $CrLf;
2522 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.
2523 $XML_SEPA_INFO .= ' <PmtTpInf>' . $CrLf;
2524 $XML_SEPA_INFO .= ' <SvcLvl>' . $CrLf;
2525 $XML_SEPA_INFO .= ' <Cd>SEPA</Cd>' . $CrLf;
2526 $XML_SEPA_INFO .= ' </SvcLvl>' . $CrLf;
2527 $XML_SEPA_INFO .= ' <LclInstrm>' . $CrLf;
2528 $XML_SEPA_INFO .= ' <Cd>CORE</Cd>' . $CrLf;
2529 $XML_SEPA_INFO .= ' </LclInstrm>' . $CrLf;
2530 $XML_SEPA_INFO .= ' <SeqTp>' . $format . '</SeqTp>' . $CrLf;
2531 $XML_SEPA_INFO .= ' </PmtTpInf>' . $CrLf;
2532 }
2533 $XML_SEPA_INFO .= ' <ReqdExctnDt>' . dol_print_date($dateTime_ETAD, 'dayrfc') . '</ReqdExctnDt>' . $CrLf;
2534 $XML_SEPA_INFO .= ' <Dbtr>' . $CrLf;
2535 $XML_SEPA_INFO .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf;
2536 $XML_SEPA_INFO .= ' <PstlAdr>' . $CrLf;
2537 $XML_SEPA_INFO .= ' <Ctry>' . $country[1] . '</Ctry>' . $CrLf;
2538 $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(chr(13) => ", ", chr(10) => ""));
2539 $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) => ""));
2540 if ($addressline1) {
2541 $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2542 }
2543 if ($addressline2) {
2544 $XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2545 }
2546 $XML_SEPA_INFO .= ' </PstlAdr>' . $CrLf;
2547 $XML_SEPA_INFO .= ' </Dbtr>' . $CrLf;
2548 $XML_SEPA_INFO .= ' <DbtrAcct>' . $CrLf;
2549 $XML_SEPA_INFO .= ' <Id>' . $CrLf;
2550 $XML_SEPA_INFO .= ' <IBAN>' . preg_replace('/\s/', '', $this->emetteur_iban) . '</IBAN>' . $CrLf;
2551 $XML_SEPA_INFO .= ' </Id>' . $CrLf;
2552 $XML_SEPA_INFO .= ' </DbtrAcct>' . $CrLf;
2553 $XML_SEPA_INFO .= ' <DbtrAgt>' . $CrLf;
2554 $XML_SEPA_INFO .= ' <FinInstnId>' . $CrLf;
2555 $XML_SEPA_INFO .= ' <BIC>' . $this->emetteur_bic . '</BIC>' . $CrLf;
2556 $XML_SEPA_INFO .= ' </FinInstnId>' . $CrLf;
2557 $XML_SEPA_INFO .= ' </DbtrAgt>' . $CrLf;
2558 /* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf;
2559 $XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2560 $XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf;
2561 $XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2562 $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;
2563 $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;
2564 $XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf;
2565 $XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/
2566 $XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>' . $CrLf; // Field "Responsible of fees". Must be SLEV
2567 /*$XML_SEPA_INFO .= ' <CdtrSchmeId>'.$CrLf;
2568 $XML_SEPA_INFO .= ' <Id>'.$CrLf;
2569 $XML_SEPA_INFO .= ' <PrvtId>'.$CrLf;
2570 $XML_SEPA_INFO .= ' <Othr>'.$CrLf;
2571 $XML_SEPA_INFO .= ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf;
2572 $XML_SEPA_INFO .= ' <SchmeNm>'.$CrLf;
2573 $XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>'.$CrLf;
2574 $XML_SEPA_INFO .= ' </SchmeNm>'.$CrLf;
2575 $XML_SEPA_INFO .= ' </Othr>'.$CrLf;
2576 $XML_SEPA_INFO .= ' </PrvtId>'.$CrLf;
2577 $XML_SEPA_INFO .= ' </Id>'.$CrLf;
2578 $XML_SEPA_INFO .= ' </CdtrSchmeId>'.$CrLf;*/
2579 }
2580 } else {
2581 fwrite($this->file, 'INCORRECT EMETTEUR ' . $this->raison_sociale . $CrLf);
2582 $XML_SEPA_INFO = '';
2583 }
2584 return $XML_SEPA_INFO;
2585 }
2586
2587 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2594 public function EnregTotal($total)
2595 {
2596 // phpcs:enable
2597 fwrite($this->file, "08");
2598 fwrite($this->file, "08"); // Prelevement ordinaire
2599
2600 fwrite($this->file, " "); // Zone Reservee B2
2601
2602 fwrite($this->file, $this->emetteur_ics); // ICS
2603
2604 // Reserve C1
2605
2606 fwrite($this->file, substr(" ", 0, 12));
2607
2608
2609 // Raison Sociale C2
2610
2611 fwrite($this->file, substr(" ", 0, 24));
2612
2613 // D1
2614
2615 fwrite($this->file, substr(" ", 0, 24));
2616
2617 // Zone Reservee D2
2618
2619 fwrite($this->file, substr(" ", 0, 8));
2620
2621 // Code Guichet D3
2622
2623 fwrite($this->file, substr(" ", 0, 5));
2624
2625 // Numero de compte D4
2626
2627 fwrite($this->file, substr(" ", 0, 11));
2628
2629 // Zone E Montant
2630
2631 $montant = ($total * 100);
2632
2633 fwrite($this->file, substr("000000000000000" . $montant, -16));
2634
2635 // Zone Reservee F
2636
2637 fwrite($this->file, substr(" ", 0, 31));
2638
2639 // Code etablissement
2640
2641 fwrite($this->file, substr(" ", 0, 5));
2642
2643 // Zone Reservee F
2644
2645 fwrite($this->file, substr(" ", 0, 5));
2646
2647 fwrite($this->file, "\n");
2648 }
2649
2656 public function getLibStatut($mode = 0)
2657 {
2658 return $this->LibStatut($this->statut, $mode);
2659 }
2660
2661 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2669 public function LibStatut($status, $mode = 0)
2670 {
2671 // phpcs:enable
2672 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
2673 global $langs;
2674 //$langs->load("mymodule");
2675 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2676 $this->labelStatus[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2677 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2678 $this->labelStatusShort[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2679 if ($this->type == 'bank-transfer') {
2680 $this->labelStatus[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2681 $this->labelStatusShort[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2682 } else {
2683 $this->labelStatus[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2684 $this->labelStatusShort[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2685 }
2686 }
2687
2688 $statusType = 'status1';
2689 if ($status == self::STATUS_TRANSFERED) {
2690 $statusType = 'status3';
2691 }
2692 if ($status == self::STATUS_CREDITED || $status == self::STATUS_DEBITED) {
2693 $statusType = 'status6';
2694 }
2695
2696 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
2697 }
2698
2699 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2707 public function load_board($user, $mode)
2708 {
2709 // phpcs:enable
2710 if ($user->socid) {
2711 return -1; // protection pour eviter appel par utilisateur externe
2712 }
2713
2714 /*
2715 if ($mode == 'direct_debit') {
2716 $sql = "SELECT b.rowid, f.datedue as datefin";
2717 $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
2718 $sql .= " WHERE f.entity IN (".getEntity('facture').")";
2719 $sql .= " AND f.total_ttc > 0";
2720 } else {
2721 $sql = "SELECT b.rowid, f.datedue as datefin";
2722 $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
2723 $sql .= " WHERE f.entity IN (".getEntity('facture_fourn').")";
2724 $sql .= " AND f.total_ttc > 0";
2725 }
2726
2727 $resql = $this->db->query($sql);
2728 if ($resql) {
2729 $langs->load("banks");
2730 $now = dol_now();
2731
2732 $response = new WorkboardResponse();
2733 if ($mode == 'direct_debit') {
2734 $response->warning_delay = $conf->prelevement->warning_delay / 60 / 60 / 24;
2735 $response->label = $langs->trans("PendingDirectDebitToComplete");
2736 $response->labelShort = $langs->trans("PendingDirectDebitToCompleteShort");
2737 $response->url = DOL_URL_ROOT.'/compta/prelevement/index.php?leftmenu=checks&mainmenu=bank';
2738 } else {
2739 $response->warning_delay = $conf->paymentbybanktransfer->warning_delay / 60 / 60 / 24;
2740 $response->label = $langs->trans("PendingCreditTransferToComplete");
2741 $response->labelShort = $langs->trans("PendingCreditTransferToCompleteShort");
2742 $response->url = DOL_URL_ROOT.'/compta/paymentbybanktransfer/index.php?leftmenu=checks&mainmenu=bank';
2743 }
2744 $response->img = img_object('', "payment");
2745
2746 while ($obj = $this->db->fetch_object($resql)) {
2747 $response->nbtodo++;
2748
2749 if ($this->db->jdate($obj->datefin) < ($now - $conf->withdraw->warning_delay)) {
2750 $response->nbtodolate++;
2751 }
2752 }
2753
2754 $response->nbtodo = 0;
2755 $response->nbtodolate = 0;
2756 // Return workboard only if quantity is not 0
2757 if ($response->nbtodo) {
2758 return $response;
2759 } else {
2760 return 0;
2761 }
2762 } else {
2763 dol_print_error($this->db);
2764 $this->error = $this->db->error();
2765 return -1;
2766 }
2767 */
2768 return 0;
2769 }
2770
2778 public function getKanbanView($option = '', $arraydata = null)
2779 {
2780 global $langs;
2781
2782 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2783
2784 $return = '<div class="box-flex-item box-flex-grow-zero">';
2785 $return .= '<div class="info-box info-box-sm">';
2786 $return .= '<span class="info-box-icon bg-infobox-action">';
2787 $return .= img_picto('', $this->picto);
2788 $return .= '</span>';
2789 $return .= '<div class="info-box-content">';
2790 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . (method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref) . '</span>';
2791 if ($selected >= 0) {
2792 $return .= '<input id="cb' . $this->id . '" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="' . $this->id . '"' . ($selected ? ' checked="checked"' : '') . '>';
2793 }
2794 if (property_exists($this, 'date_echeance')) {
2795 $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>';
2796 }
2797 if (property_exists($this, 'total')) {
2798 $return .= '<br><span class="opacitymedium">' . $langs->trans("Amount") . '</span> : <span class="amount">' . price($this->total) . '</span>';
2799 }
2800 if (method_exists($this, 'LibStatut')) {
2801 $return .= '<br><div class="info-box-status">' . $this->getLibStatut(3) . '</div>';
2802 }
2803 $return .= '</div>';
2804 $return .= '</div>';
2805 $return .= '</div>';
2806 return $return;
2807 }
2808
2815 {
2816 if (!empty($this->id)) {
2817 $id = $this->id;
2818 } else {
2819 return 0;
2820 }
2821 if ($id) {
2822 $sql = "SELECT COUNT(*) AS nb FROM " . MAIN_DB_PREFIX . "prelevement_lignes";
2823 $sql .= " WHERE fk_prelevement_bons = " . ((int) $id);
2824 $sql .= " AND fk_soc = 0"; // fk_soc can't be NULL
2825 $sql .= " AND fk_user IS NOT NULL";
2826
2827 $num = 0;
2828 $resql = $this->db->query($sql);
2829 if ($resql) {
2830 $obj = $this->db->fetch_object($resql);
2831 $num = $obj->nb;
2832 }
2833 if ($num > 0) {
2834 return 1;
2835 }
2836 } else {
2837 dol_print_error($this->db);
2838 }
2839
2840 return 0;
2841 }
2842}
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:637
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 clicable link of object (with eventually picto)
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Returns clickable name (with picto)
LibStatut($status, $mode=0)
Return status label for a status.
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 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:137
publicphonebutton2 phonegreen basiclayout basiclayout TotalHT VATCode TotalVAT TotalLT1 TotalLT2 TotalTTC TotalHT clearboth nowraponall TAKEPOS_SHOW_SUBPRICE right right right takeposterminal SELECT e e e e e statut
Definition invoice.php:1991