Passed
Pull Request — dev (#8)
by Rafael
58:47
created

BonPrelevement::set_infocredit()   F

Complexity

Conditions 29
Paths 40

Size

Total Lines 199
Code Lines 136

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 29
eloc 136
nc 40
nop 3
dl 0
loc 199
rs 3.3333
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/* Copyright (C) 2004-2005  Rodolphe Quiedeville        <[email protected]>
4
 * Copyright (C) 2005-2012  Regis Houssin               <[email protected]>
5
 * Copyright (C) 2010-2015  Juanjo Menent               <[email protected]>
6
 * Copyright (C) 2010-2014  Laurent Destailleur         <[email protected]>
7
 * Copyright (C) 2014-2016  Ferran Marcet               <[email protected]>
8
 * Copyright (C) 2018       Nicolas ZABOURI             <[email protected]>
9
 * Copyright (C) 2019       JC Prieto			        <[email protected]><[email protected]>
10
 * Copyright (C) 2024       MDW					        <[email protected]>
11
 * Copyright (C) 2024       Frédéric France             <[email protected]>
12
 * Copyright (C) 2024       Rafael San José             <[email protected]>
13
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation; either version 3 of the License, or
17
 * (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
26
 */
27
28
namespace Dolibarr\Code\Compta\Classes;
29
30
use Dolibarr\Code\Fourn\Classes\FactureFournisseur;
31
use Dolibarr\Code\Fourn\Classes\PaiementFourn;
32
use Dolibarr\Code\Salaries\Classes\PaymentSalary;
33
use Dolibarr\Code\Salaries\Classes\Salary;
34
use Dolibarr\Code\User\Classes\User;
35
use Dolibarr\Core\Base\CommonObject;
36
use Dolibarr\Code\Societe\Classes\Societe;
37
use DoliDB;
38
39
/**
40
 * \file       htdocs/compta/prelevement/class/bonprelevement.class.php
41
 * \ingroup    prelevement
42
 * \brief      File of withdrawal receipts class
43
 */
44
45
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/bank.lib.php';
46
47
/**
48
 *  Class to manage withdrawal receipts
49
 */
50
class BonPrelevement extends CommonObject
51
{
52
    /**
53
     * @var string ID to identify managed object
54
     */
55
    public $element = 'widthdraw';
56
57
    /**
58
     * @var string Name of table without prefix where object is stored
59
     */
60
    public $table_element = 'prelevement_bons';
61
62
    /**
63
     * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
64
     */
65
    public $picto = 'payment';
66
67
    public $date_echeance;
68
    public $raison_sociale;
69
    public $reference_remise;
70
    public $emetteur_code_guichet;
71
    public $emetteur_numero_compte;
72
    public $emetteur_code_banque;
73
    public $emetteur_number_key;
74
    public $sepa_xml_pti_in_ctti;
75
76
    public $emetteur_iban;
77
    public $emetteur_bic;
78
    public $emetteur_ics;
79
80
    public $user_trans;
81
    public $user_credit;
82
83
    public $total;
84
    public $fetched;
85
    public $labelStatus = array();
86
87
    public $factures = array();
88
89
    /**
90
     * @var array<int,string>
91
     */
92
    public $methodes_trans = array();
93
94
    public $invoice_in_error = array();
95
    public $thirdparty_in_error = array();
96
97
    /**
98
     * @var resource    Handler of the file for direct debit or credit transfer order
99
     */
100
    public $file;
101
102
    /**
103
     * @var string filename
104
     */
105
    public $filename;
106
107
    const STATUS_DRAFT = 0;
108
    const STATUS_TRANSFERED = 1;
109
    const STATUS_CREDITED = 2;      // STATUS_CREDITED and STATUS_DEBITED is same. Difference is in ->type
110
    const STATUS_DEBITED = 2;       // STATUS_CREDITED and STATUS_DEBITED is same. Difference is in ->type
111
112
113
    /**
114
     *  'type' field format:
115
     *      'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',
116
     *      'select' (list of values are in 'options'),
117
     *      'sellist:TableName:LabelFieldName[:KeyFieldName[:KeyFieldParent[:Filter[:Sortfield]]]]',
118
     *      'chkbxlst:...',
119
     *      'varchar(x)',
120
     *      'text', 'text:none', 'html',
121
     *      'double(24,8)', 'real', 'price',
122
     *      'date', 'datetime', 'timestamp', 'duration',
123
     *      'boolean', 'checkbox', 'radio', 'array',
124
     *      'mail', 'phone', 'url', 'password', 'ip'
125
     *      Note: Filter must be a Dolibarr filter syntax string. Example: "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.status:!=:0) or (t.nature:is:NULL)"
126
     *  'label' the translation key.
127
     *  'picto' is code of a picto to show before value in forms
128
     *  'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM' or 'isModEnabled("multicurrency")' ...)
129
     *  'position' is the sort order of field.
130
     *  'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0).
131
     *  'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing)
132
     *  'noteditable' says if field is not editable (1 or 0)
133
     *  'alwayseditable' says if field can be modified also when status is not draft ('1' or '0')
134
     *  'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created.
135
     *  'index' if we want an index in database.
136
     *  'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommended to name the field fk_...).
137
     *  'searchall' is 1 if we want to search in this field when making a search from the quick search button.
138
     *  'isameasure' must be set to 1 or 2 if field can be used for measure. Field type must be summable like integer or double(24,8). Use 1 in most cases, or 2 if you don't want to see the column total into list (for example for percentage)
139
     *  'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'cssview'=>'wordbreak', 'csslist'=>'tdoverflowmax200'
140
     *  'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click.
141
     *  'showoncombobox' if value of the field must be visible into the label of the combobox that list record
142
     *  'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code.
143
     *  'arrayofkeyval' to set a list of values if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel"). Note that type can be 'integer' or 'varchar'
144
     *  'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1.
145
     *  'comment' is not used. You can store here any text of your choice. It is not used by application.
146
     *  'validate' is 1 if need to validate with $this->validateField()
147
     *  'copytoclipboard' is 1 or 2 to allow to add a picto to copy value into clipboard (1=picto after label, 2=picto after value)
148
     *
149
     *  Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor.
150
     */
151
152
    // BEGIN MODULEBUILDER PROPERTIES
153
    /**
154
     * @var array<string,array{type:string,label:string,enabled:int<0,2>|string,position:int,notnull?:int,visible:int,noteditable?:int,default?:string,index?:int,foreignkey?:string,searchall?:int,isameasure?:int,css?:string,csslist?:string,help?:string,showoncombobox?:int,disabled?:int,arrayofkeyval?:array<int,string>,comment?:string}>  Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string,array{type:...ring>,comment?:string}> at position 16 could not be parsed: Expected '}' at position 16, but found 'int'.
Loading history...
155
     */
156
    public $fields = array(
157
        'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 10, 'notnull' => 1, 'visible' => 0,),
158
        'ref' => array('type' => 'varchar(12)', 'label' => 'Ref', 'enabled' => 1, 'position' => 15, 'notnull' => 0, 'visible' => -1, 'csslist' => 'tdoverflowmax150', 'showoncombobox' => 1,),
159
        'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 25, 'notnull' => 0, 'visible' => -1,),
160
        'amount' => array('type' => 'double(24,8)', 'label' => 'Amount', 'enabled' => 1, 'position' => 30, 'notnull' => 0, 'visible' => -1,),
161
        'statut' => array('type' => 'smallint(6)', 'label' => 'Statut', 'enabled' => 1, 'position' => 500, 'notnull' => 0, 'visible' => -1, 'arrayofkeyval' => array(0 => 'Wait', 1 => 'Transfered', 2 => 'Credited')),
162
        'credite' => array('type' => 'smallint(6)', 'label' => 'Credite', 'enabled' => 1, 'position' => 40, 'notnull' => 0, 'visible' => -1,),
163
        'note' => array('type' => 'text', 'label' => 'Note', 'enabled' => 1, 'position' => 45, 'notnull' => 0, 'visible' => -1,),
164
        'date_trans' => array('type' => 'datetime', 'label' => 'Datetrans', 'enabled' => 1, 'position' => 50, 'notnull' => 0, 'visible' => -1,),
165
        'method_trans' => array('type' => 'smallint(6)', 'label' => 'Methodtrans', 'enabled' => 1, 'position' => 55, 'notnull' => 0, 'visible' => -1,),
166
        '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',),
167
        'date_credit' => array('type' => 'datetime', 'label' => 'Datecredit', 'enabled' => 1, 'position' => 65, 'notnull' => 0, 'visible' => -1,),
168
        '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',),
169
        'type' => array('type' => 'varchar(16)', 'label' => 'Type', 'enabled' => 1, 'position' => 75, 'notnull' => 0, 'visible' => -1,),
170
        'fk_bank_account' => array('type' => 'integer', 'label' => 'Fkbankaccount', 'enabled' => 1, 'position' => 80, 'notnull' => 0, 'visible' => -1, 'css' => 'maxwidth500 widthcentpercentminusxx',),
171
    );
172
    public $rowid;
173
    public $ref;
174
    public $datec;
175
    public $amount;
176
177
    /**
178
     * @var int Status
179
     * @deprecated
180
     */
181
    public $statut;
182
    /**
183
     * @var int Status
184
     */
185
    public $status;
186
187
    public $credite;
188
    public $note;
189
    public $date_trans;
190
    /**
191
     * @var int Current transport method, index to $methodes_trans
192
     */
193
    public $method_trans;
194
    public $fk_user_trans;
195
    public $date_credit;
196
    public $fk_user_credit;
197
    public $type;
198
    public $fk_bank_account;
199
    // END MODULEBUILDER PROPERTIES
200
201
    /**
202
     *  Constructor
203
     *
204
     *  @param      DoliDB      $db         Database handler
205
     */
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
234
    /**
235
     * Add invoice to withdrawal
236
     *
237
     * @param   int     $invoice_id     ID of invoice to add or ID of salary to add
238
     * @param   int     $client_id      id invoice customer
239
     * @param   string  $client_nom     customer name
240
     * @param   int     $amount         amount of invoice
241
     * @param   string  $code_banque    code of bank withdrawal
242
     * @param   string  $code_guichet   code of bank's office
243
     * @param   string  $number bank    account number
244
     * @param   string  $number_key     number key of account number
245
     * @param   string  $type           'debit-order' or 'bank-transfer'
246
     * @param   string  $sourcetype     'salary' for salary, '' for invoices
247
     * @return  int                     >0 if OK, <0 if KO
248
     */
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
297
    /**
298
     *  Add line to withdrawal
299
     *
300
     *  @param  int     $line_id        ID of line added (returned parameter)
301
     *  @param  int     $client_id      ID of thirdparty for invoices, ID of user for salaries
302
     *  @param  string  $client_nom     customer name
303
     *  @param  int     $amount         amount of invoice
304
     *  @param  string  $code_banque    code of bank withdrawal
305
     *  @param  string  $code_guichet   code of bank's office
306
     *  @param  string  $number         bank account number
307
     *  @param  string  $number_key     number key of account number
308
     *  @param  string  $sourcetype     'salary' for salary, '' for invoices
309
     *  @return int                     >0 if OK, <0 if KO
310
     */
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
376
    /**
377
     *  Return error string
378
     *
379
     *  @param  int     $error       Id of error
380
     *  @return string               Error string
381
     */
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
393
    /**
394
     *  Get object and lines from database
395
     *
396
     *  @param  int     $rowid      Id of object to load
397
     *  @param  string  $ref        Ref of direct debit
398
     *  @return int                 >0 if OK, <0 if KO
399
     */
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 Erreur aucune ligne retournee");
452
                return -1;
453
            }
454
        } else {
455
            return -2;
456
        }
457
    }
458
459
    /**
460
     * Update object into database
461
     *
462
     * @param  User $user      User that modifies
463
     * @param  int  $notrigger 0=launch triggers after, 1=disable triggers
464
     * @return int             Return integer <0 if KO, >0 if OK
465
     */
466
    public function update(User $user, $notrigger = 0)
467
    {
468
        return $this->updateCommon($user, $notrigger);
469
    }
470
471
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
472
    /**
473
     *  Set direct debit or credit transfer order to "paid" status.
474
     *  Then create the payment for each invoice or salary of the prelemevement_bon.
475
     *
476
     *  @param  User    $user           Id of user
477
     *  @param  int     $date           date of action
478
     *  @param  string  $type           'salary' for type=salary
479
     *  @return int                     >0 if OK, <0 if KO
480
     */
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();
0 ignored issues
show
Bug introduced by
The method getSumCreditNotesUsed() does not exist on Dolibarr\Code\Salaries\Classes\Salary. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

557
                        /** @scrutinizer ignore-call */ 
558
                        $totalcreditnotes = $fac->getSumCreditNotesUsed();
Loading history...
558
                    }
559
                    $totaldeposits = 0;
560
                    if (method_exists($fac, 'getSumDepositsUsed')) {
561
                        $totaldeposits = $fac->getSumDepositsUsed();
0 ignored issues
show
Bug introduced by
The method getSumDepositsUsed() does not exist on Dolibarr\Code\Salaries\Classes\Salary. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

561
                        /** @scrutinizer ignore-call */ 
562
                        $totaldeposits = $fac->getSumDepositsUsed();
Loading history...
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;
0 ignored issues
show
Bug Best Practice introduced by
The property datep does not exist on Dolibarr\Code\Compta\Classes\Paiement. Since you implemented __set, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property datep does not exist on Dolibarr\Code\Fourn\Classes\PaiementFourn. Since you implemented __set, consider adding a @property annotation.
Loading history...
597
598
                            $paiement->paiementid = 2;
0 ignored issues
show
Bug Best Practice introduced by
The property paiementid does not exist on Dolibarr\Code\Salaries\Classes\PaymentSalary. Since you implemented __set, consider adding a @property annotation.
Loading history...
599
                            $paiement->fk_typepayment = 2;
0 ignored issues
show
Bug Best Practice introduced by
The property fk_typepayment does not exist on Dolibarr\Code\Compta\Classes\Paiement. Since you implemented __set, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property fk_typepayment does not exist on Dolibarr\Code\Fourn\Classes\PaiementFourn. Since you implemented __set, consider adding a @property annotation.
Loading history...
600
                            $paiement->paiementcode = 'VIR';
0 ignored issues
show
Bug Best Practice introduced by
The property paiementcode does not exist on Dolibarr\Code\Salaries\Classes\PaymentSalary. Since you implemented __set, consider adding a @property annotation.
Loading history...
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;
0 ignored issues
show
Bug Best Practice introduced by
The property id_prelevement does not exist on Dolibarr\Code\Salaries\Classes\PaymentSalary. Since you implemented __set, consider adding a @property annotation.
Loading history...
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
684
    /**
685
     *  Set withdrawal to transmitted status
686
     *
687
     *  @param  User        $user       Id of user
688
     *  @param  int         $date       Date of action
689
     *  @param  int         $method     Method of transmission to bank (0=Internet, 1=Api...)
690
     *  @return int                     >0 if OK, <0 if KO
691
     */
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
744
    /**
745
     *  Get invoice or salary list (with amount or not)
746
     *
747
     *  @param  int     $amounts    If you want to get the amount of the order for each invoice or salary
748
     *  @param  string  $type       'salary' for type=salary
749
     *  @return array               Array(Id of invoices/salary, Amount to pay)
750
     */
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
820
    /**
821
     *  Returns amount waiting for direct debit payment or credit transfer payment
822
     *
823
     *  @param  string  $mode       'direct-debit' or 'bank-transfer'
824
     *  @param  string  $type        for type=salary
825
     *  @return double              Return integer <O if KO, Total amount
826
     */
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
875
    /**
876
     *  Get number of invoices waiting for payment
877
     *
878
     *  @param  string  $mode       'direct-debit' or 'bank-transfer'
879
     *  @param  string  $type        for salary invoice
880
     *  @return int                 Return integer <O if KO, number of invoices if OK
881
     */
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
892
    /**
893
     *  Get number of invoices to pay
894
     *
895
     *  @param  string  $type       'direct-debit' or 'bank-transfer'
896
     *  @param  int     $forsalary  0= for facture & facture_supplier, 1=for salary
897
     *  @return int                 Return integer <O if KO, number of invoices if OK
898
     */
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
959
    /**
960
     *  Create a BAN payment order:
961
     *  - Select waiting requests from prelevement_demande (or use $did if provided)
962
     *  - Check BAN values
963
     *  - Then create a direct debit order or a credit transfer order
964
     *  - Link the order with the prelevement_demande lines
965
     *  TODO delete params banque and agence when not necessary
966
     *
967
     *  @param  int     $banque             dolibarr mysoc bank
968
     *  @param  int     $agence             dolibarr mysoc bank office (guichet)
969
     *  @param  string  $mode               real=do action, simu=test only
970
     *  @param  string  $format             FRST, RCUR or ALL
971
     *  @param  string  $executiondate      Date to execute the transfer
972
     *  @param  int     $notrigger          Disable triggers
973
     *  @param  string  $type               'direct-debit' or 'bank-transfer'
974
     *  @param  int     $did                ID of an existing payment request. If $did is defined, we use the existing payment request.
975
     *  @param  int     $fk_bank_account    Bank account ID the receipt is generated for. Will use the ID into the setup of module Direct Debit or Credit Transfer if 0.
976
     *  @param  string  $sourcetype         'invoice' or 'salary'
977
     *  @return int                         Return integer <0 if KO, No of invoice included into file if OK
978
     */
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
987
        // Check params
988
        if ($type != 'bank-transfer') {
989
            if (empty($format)) {
990
                $this->error = 'ErrorBadParametersForDirectDebitFileCreate';
991
                return -1;
992
            }
993
        }
994
995
        // Clean params
996
        if (empty($fk_bank_account)) {
997
            $fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
998
        }
999
1000
        $error = 0;
1001
1002
        $datetimeprev = dol_now('gmt');
1003
        // Choice the date of the execution direct debit
1004
        if (!empty($executiondate)) {
1005
            $datetimeprev = $executiondate;
1006
        }
1007
1008
        $month = dol_print_date($datetimeprev, "%m", 'gmt');
1009
        $year = dol_print_date($datetimeprev, "%Y", 'gmt');
1010
1011
        $this->invoice_in_error = array();
1012
        $this->thirdparty_in_error = array();
1013
1014
        // Read invoices
1015
        $factures = array();
1016
        $factures_prev = array();
1017
        $factures_result = array();
1018
        $factures_prev_id = array();
1019
        $factures_errors = array();
1020
        if (!$error) {
1021
            dol_syslog(__METHOD__ . " Read invoices for did=" . ((int) $did), LOG_DEBUG);
1022
1023
            $sql = "SELECT f.rowid, pd.rowid as pfdrowid";
1024
            if ($sourcetype != 'salary') {
1025
                $sql .= ", f.fk_soc";
1026
            } else {
1027
                $sql .= ", f.fk_user";
1028
            }
1029
            $sql .= ", pd.code_banque, pd.code_guichet, pd.number, pd.cle_rib";
1030
            $sql .= ", pd.amount";
1031
            if ($sourcetype != 'salary') {
1032
                $sql .= ", s.nom as name";
1033
                $sql .= ", f.ref, sr.bic, sr.iban_prefix, sr.frstrecur";
1034
            } else {
1035
                $sql .= ", CONCAT(s.firstname,' ',s.lastname) as name";
1036
                $sql .= ", f.ref, sr.bic, sr.iban_prefix, 'FRST' as frstrecur";
1037
            }
1038
            if ($sourcetype != 'salary') {
1039
                if ($type != 'bank-transfer') {
1040
                    $sql .= " FROM " . MAIN_DB_PREFIX . "facture as f";
1041
                    $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "prelevement_demande as pd ON f.rowid = pd.fk_facture";
1042
                } else {
1043
                    $sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f";
1044
                    $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "prelevement_demande as pd ON f.rowid = pd.fk_facture_fourn";
1045
                }
1046
                $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe as s ON s.rowid = f.fk_soc";
1047
                $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe_rib as sr ON s.rowid = sr.fk_soc AND sr.default_rib = 1";
1048
            } else {
1049
                $sql .= " FROM " . MAIN_DB_PREFIX . "salary as f";
1050
                $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "prelevement_demande as pd ON f.rowid = pd.fk_salary";
1051
                $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "user as s ON s.rowid = f.fk_user";
1052
                $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "user_rib as sr ON s.rowid = sr.fk_user";  // TODO Add AND sr.default_rib = 1 here
1053
            }
1054
            if ($sourcetype != 'salary') {
1055
                if ($type != 'bank-transfer') {
1056
                    $sql .= " WHERE f.entity IN (" . getEntity('invoice') . ')';
1057
                } else {
1058
                    $sql .= " WHERE f.entity IN (" . getEntity('supplier_invoice') . ')';
1059
                }
1060
            } else {
1061
                $sql .= " WHERE f.entity IN (" . getEntity('salary') . ')';
1062
            }
1063
            if ($sourcetype != 'salary') {
1064
                $sql .= " AND f.fk_statut = 1"; // Invoice validated
1065
                $sql .= " AND f.paye = 0";
1066
                $sql .= " AND f.total_ttc > 0";
1067
            } else {
1068
                //$sql .= " AND f.fk_statut = 1"; // Invoice validated
1069
                $sql .= " AND f.paye = 0";
1070
                $sql .= " AND f.amount > 0";
1071
            }
1072
            $sql .= " AND pd.traite = 0";
1073
            $sql .= " AND pd.ext_payment_id IS NULL";
1074
            if ($sourcetype != 'salary') {
1075
                $sql .= " AND sr.type = 'ban'";     // TODO Add AND sr.type = 'ban' for users too
1076
            }
1077
            if ($did > 0) {
1078
                $sql .= " AND pd.rowid = " . ((int) $did);
1079
            }
1080
1081
            $resql = $this->db->query($sql);
1082
            if ($resql) {
1083
                $num = $this->db->num_rows($resql);
1084
                $i = 0;
1085
1086
                while ($i < $num) {
1087
                    $row = $this->db->fetch_row($resql);    // TODO Replace with fetch_object()
1088
                    $factures[$i] = $row; // All fields
1089
1090
                    if ($row[7] == 0) {
1091
                        $error++;
1092
                        dol_syslog(__METHOD__ . " Read invoices/salary error Found a null amount", LOG_ERR);
1093
                        $this->invoice_in_error[$row[0]] = "Error for invoice or salary id " . $row[0] . ", found a null amount";
1094
                        break;
1095
                    }
1096
                    $i++;
1097
                }
1098
1099
                $this->db->free($resql);
1100
                dol_syslog(__METHOD__ . " Read invoices/salary, " . $i . " invoices/salary to withdraw", LOG_DEBUG);
1101
            } else {
1102
                $error++;
1103
                $this->error = $this->db->lasterror();
1104
                dol_syslog(__METHOD__ . " Read invoices/salary error " . $this->db->lasterror(), LOG_ERR);
1105
                return -1;
1106
            }
1107
        }
1108
1109
        if (!$error) {
1110
            require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/bank.lib.php';
1111
1112
            $tmpsoc = new Societe($this->db);
1113
            $tmpuser = new User($this->db);
1114
1115
            // Check BAN
1116
            $i = 0;
1117
            dol_syslog(__METHOD__ . " Check BAN", LOG_DEBUG);
1118
1119
            if (count($factures) > 0) {
1120
                foreach ($factures as $key => $fac) {
1121
                    /*
1122
                    if ($type != 'bank-transfer') {
1123
                        $tmpinvoice = new Facture($this->db);
1124
                    } else {
1125
                        $tmpinvoice = new FactureFournisseur($this->db);
1126
                    }
1127
                    $resfetch = $tmpinvoice->fetch($fac[0]);
1128
                    if ($resfetch >= 0) {       // Field 0 of $fac is rowid of invoice
1129
                    */
1130
1131
                    // Check if $fac[8] s.nom is null
1132
                    if ($fac[8] != null) {
1133
                        if ($type != 'bank-transfer') {
1134
                            if ($format == 'FRST' && $fac[12] != 'FRST') {
1135
                                continue;
1136
                            }
1137
                            if ($format == 'RCUR' && $fac[12] != 'RCUR') {
1138
                                continue;
1139
                            }
1140
                        }
1141
1142
                        $verif = checkSwiftForAccount(null, $fac[10]);
1143
                        if ($verif) {
1144
                            $verif = checkIbanForAccount(null, $fac[11]);
1145
                        }
1146
1147
                        if ($verif) {
1148
                            $factures_prev[$i] = $fac;
1149
                            /* second array necessary for BonPrelevement */
1150
                            $factures_prev_id[$i] = $fac[0];
1151
                            $i++;
1152
                            //dol_syslog(__METHOD__."::RIB is ok", LOG_DEBUG);
1153
                        } else {
1154
                            if ($type != 'bank-transfer') {
1155
                                $tmpsoc->id = $fac[2];
1156
                                $tmpsoc->name = $fac[8];
1157
                                $invoice_url = "<a href='" . constant('BASE_URL') . '/compta/facture/card.php?facid=' . $fac[0] . "'>" . $fac[9] . "</a>";
1158
                                $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1159
                                $this->thirdparty_in_error[$tmpsoc->id] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1160
                                $error++;
1161
                            }
1162
                            if ($type == 'bank-transfer' && $sourcetype != 'salary') {
1163
                                $tmpsoc->id = $fac[2];
1164
                                $tmpsoc->name = $fac[8];
1165
                                $invoice_url = "<a href='" . constant('BASE_URL') . '/fourn/facture/card.php?facid=' . $fac[0] . "'>" . $fac[9] . "</a>";
1166
                                $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1167
                                $this->thirdparty_in_error[$tmpsoc->id] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0);
1168
                                $error++;
1169
                            }
1170
                            if ($type == 'bank-transfer' && $sourcetype == 'salary') {
1171
                                $tmpuser->id = $fac[2];
1172
                                $tmpuser->firstname = $fac[8];
1173
                                $salary_url = "<a href='" . constant('BASE_URL') . '/salaries/card.php?id=' . $fac[0] . "'>" . $fac[0] . "</a>";
1174
                                $this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for salary " . $salary_url . " for employee " . $tmpuser->getNomUrl(0);
1175
                                $this->thirdparty_in_error[$tmpuser->id] = "Error on default bank number IBAN/BIC for salary " . $salary_url . " for employee " . $tmpuser->getNomUrl(0);
1176
                                $error++;
1177
                            }
1178
                            dol_syslog(__METHOD__ . " Check BAN Error on default bank number IBAN/BIC reported by verif(): " . implode(', ', $fac), LOG_WARNING);
1179
                        }
1180
                    } else {
1181
                        dol_syslog(__METHOD__ . " Check BAN Failed to read company", LOG_WARNING);
1182
                    }
1183
                    /*
1184
                    } else {
1185
                        dol_syslog(__METHOD__." Check BAN Failed to read invoice", LOG_WARNING);
1186
                    }
1187
                    */
1188
                }
1189
            } else {
1190
                dol_syslog(__METHOD__ . " Check BAN No invoice to process", LOG_WARNING);
1191
            }
1192
        }
1193
1194
        $ok = 0;
1195
1196
        // Withdraw invoices in factures_prev array
1197
        $out = count($factures_prev) . " invoices will be included.";
1198
        //print $out."\n";
1199
        dol_syslog($out);
1200
1201
        // Return warning
1202
        /*$i=0;
1203
         foreach ($this->thirdparty_in_error as $key => $val)
1204
         {
1205
         if ($i < 10) setEventMessages($val, null, 'warnings');
1206
         else setEventMessages('More error were discarded...', null, 'warnings');
1207
         $i++;
1208
         }*/
1209
1210
        if (count($factures_prev) > 0) {
1211
            if ($mode == 'real') {
1212
                $ok = 1;
1213
            } else {
1214
                print $langs->trans("ModeWarning"); // "Option for real mode was not set, we stop after this simulation\n";
1215
            }
1216
        }
1217
        if ($ok) {
1218
            /*
1219
             * We are in real mode.
1220
             * We create order and build file into disk
1221
             */
1222
            $this->db->begin();
1223
1224
            $now = dol_now();
1225
            $ref = '';
1226
1227
            /*
1228
             * Process order generation
1229
             */
1230
            if (!$error) {
1231
                $ref = substr($year, -2) . $month;
1232
1233
                // Get next free number for the ref of bon prelevement
1234
                $sql = "SELECT substring(ref from char_length(ref) - 1)";   // To extract "YYMMXX" from "TYYMMXX"
1235
                $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons";
1236
                $sql .= " WHERE ref LIKE '_" . $this->db->escape($ref) . "%'";
1237
                $sql .= " AND entity = " . ((int) $conf->entity);
1238
                $sql .= " ORDER BY ref DESC LIMIT 1";
1239
1240
                dol_syslog(get_class($this) . " get next free number", LOG_DEBUG);
1241
                $resql = $this->db->query($sql);
1242
1243
                if ($resql) {
1244
                    $row = $this->db->fetch_row($resql);
1245
1246
                    // Build the new ref
1247
                    $ref = "T" . $ref . sprintf("%02d", (intval($row[0]) + 1));
1248
1249
                    // $conf->abc->dir_output may be:
1250
                    // /home/ldestailleur/git/dolibarr_15.0/documents/abc/
1251
                    // or
1252
                    // /home/ldestailleur/git/dolibarr_15.0/documents/X/abc with X >= 2 with multicompany.
1253
                    if ($type != 'bank-transfer') {
1254
                        $dir = $conf->prelevement->dir_output . '/receipts';
1255
                    } else {
1256
                        $dir = $conf->paymentbybanktransfer->dir_output . '/receipts';
1257
                    }
1258
                    if (!is_dir($dir)) {
1259
                        dol_mkdir($dir);
1260
                    }
1261
1262
                    if (isModEnabled('multicompany')) {
1263
                        $labelentity = $conf->entity;
1264
                        $this->filename = $dir . '/' . $ref . '-' . $labelentity . '.xml';
1265
                    } else {
1266
                        $this->filename = $dir . '/' . $ref . '.xml';
1267
                    }
1268
1269
                    // Create withdraw order in database
1270
                    $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_bons (";
1271
                    $sql .= "ref, entity, datec, type, fk_bank_account";
1272
                    $sql .= ") VALUES (";
1273
                    $sql .= "'" . $this->db->escape($ref) . "'";
1274
                    $sql .= ", " . ((int) $conf->entity);
1275
                    $sql .= ", '" . $this->db->idate($now) . "'";
1276
                    $sql .= ", '" . ($type == 'bank-transfer' ? 'bank-transfer' : 'debit-order') . "'";
1277
                    $sql .= ", " . ((int) $fk_bank_account);
1278
                    $sql .= ")";
1279
1280
                    $resql = $this->db->query($sql);
1281
1282
1283
                    if ($resql) {
1284
                        $prev_id = $this->db->last_insert_id(MAIN_DB_PREFIX . "prelevement_bons");
1285
                        $this->id = $prev_id;
1286
                        $this->ref = $ref;
1287
                    } else {
1288
                        $error++;
1289
                        dol_syslog(__METHOD__ . " Create withdraw receipt " . $this->db->lasterror(), LOG_ERR);
1290
                    }
1291
                } else {
1292
                    $error++;
1293
                    dol_syslog(__METHOD__ . " Get last withdraw receipt " . $this->db->lasterror(), LOG_ERR);
1294
                }
1295
            }
1296
1297
            if (!$error) {
1298
                dol_syslog(__METHOD__ . " Now loop on each document to insert them in llx_prelevement_demande");
1299
1300
                // Add lines for the bon
1301
                if (count($factures_prev) > 0) {
1302
                    foreach ($factures_prev as $fac) {  // Add a link in database for each invoice ro salary
1303
                        /*
1304
                         * Add standing order. This add record into llx_prelevement_lignes and llx_prelevement
1305
                         *
1306
                         * $fac[0] : invoice_id
1307
                         * $fac[1] : ???
1308
                         * $fac[2] : third party id
1309
                         * $fac[3] : banque
1310
                         * $fac[4] : guichet
1311
                         * $fac[5] : number
1312
                         * $fac[6] : cle rib
1313
                         * $fac[7] : amount
1314
                         * $fac[8] : client nom
1315
                         * $fac[9] : Invoice ref
1316
                         * $fac[10] : BIC
1317
                         * $fac[11] : IBAN
1318
                         * $fac[12] : frstrcur
1319
                         */
1320
                        $ri = $this->AddFacture($fac[0], $fac[2], $fac[8], $fac[7], $fac[3], $fac[4], $fac[5], $fac[6], $type, $sourcetype);
1321
1322
                        if ($ri != 0) {
1323
                            $error++;
1324
                        }
1325
1326
                        // Update invoice requests as done
1327
                        $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_demande";
1328
                        $sql .= " SET traite = 1";
1329
                        $sql .= ", date_traite = '" . $this->db->idate($now) . "'";
1330
                        $sql .= ", fk_prelevement_bons = " . ((int) $this->id);
1331
                        $sql .= " WHERE rowid = " . ((int) $fac[1]);
1332
1333
                        $resql = $this->db->query($sql);
1334
                        if (!$resql) {
1335
                            $error++;
1336
                            $this->errors[] = $this->db->lasterror();
1337
                            dol_syslog(__METHOD__ . " Update Error=" . $this->db->lasterror(), LOG_ERR);
1338
                        }
1339
                    }
1340
                }
1341
            }
1342
1343
            if (!$error) {
1344
                /*
1345
                 * Create file of type='direct-debit' for direct debit order or type='bank-transfer' for credit transfer into a XML file
1346
                 */
1347
1348
                dol_syslog(__METHOD__ . " Init direct debit or credit transfer file for " . count($factures_prev) . " invoices", LOG_DEBUG);
1349
1350
                if (count($factures_prev) > 0) {
1351
                    $this->date_echeance = $datetimeprev;
1352
                    $this->reference_remise = $ref;
1353
1354
                    $account = new Account($this->db);
1355
                    if ($account->fetch($fk_bank_account) > 0) {
1356
                        $this->emetteur_code_banque        = $account->code_banque;
1357
                        $this->emetteur_code_guichet       = $account->code_guichet;
1358
                        $this->emetteur_numero_compte      = $account->number;
1359
                        $this->emetteur_number_key         = $account->cle_rib;
1360
                        $this->sepa_xml_pti_in_ctti        = (bool) $account->pti_in_ctti;
1361
                        $this->emetteur_iban               = $account->iban;
1362
                        $this->emetteur_bic                = $account->bic;
1363
1364
                        $this->emetteur_ics = (($type == 'bank-transfer' && getDolGlobalString("SEPA_USE_IDS")) ? $account->ics_transfer : $account->ics);  // Example "FR78ZZZ123456"
1365
1366
                        $this->raison_sociale = $account->proprio;
0 ignored issues
show
Bug Best Practice introduced by
The property $proprio is declared private in Dolibarr\Code\Compta\Classes\Account. Since you implement __get, consider adding a @property or @property-read.
Loading history...
1367
                    }
1368
                    $this->factures = $factures_prev_id;
1369
                    $this->context['factures_prev'] = $factures_prev;
1370
                    // Generation of direct debit or credit transfer file $this->filename (May be a SEPA file for european countries)
1371
                    // This also set the property $this->total with amount that is included into file
1372
                    $userid = 0;
1373
                    if ($sourcetype == 'salary') {
1374
                        $userid = $this->context['factures_prev'][0][2];
1375
                    }
1376
                    $result = $this->generate($format, $executiondate, $type, $fk_bank_account, $userid);
1377
                    if ($result < 0) {
1378
                        //var_dump($this->error);
1379
                        //var_dump($this->invoice_in_error);
1380
                        $error++;
1381
                    }
1382
                }
1383
                dol_syslog(__METHOD__ . " Bank order file has been generated under filename " . $this->filename, LOG_DEBUG);
1384
            }
1385
1386
1387
            /*
1388
             * Update total defined after generation of file
1389
             */
1390
            if (!$error) {
1391
                $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_bons";
1392
                $sql .= " SET amount = " . price2num($this->total);
1393
                $sql .= " WHERE rowid = " . ((int) $this->id);
1394
                $sql .= " AND entity = " . ((int) $conf->entity);
1395
                $resql = $this->db->query($sql);
1396
1397
                if (!$resql) {
1398
                    $error++;
1399
                    dol_syslog(__METHOD__ . " Error update total: " . $this->db->error(), LOG_ERR);
1400
                }
1401
            }
1402
1403
            if (!$error && !$notrigger) {
1404
                $triggername = 'DIRECT_DEBIT_ORDER_CREATE';
1405
                if ($type != 'bank-transfer') {
1406
                    $triggername = 'CREDIT_TRANSFER_ORDER_CREATE';
1407
                }
1408
1409
                // Call trigger
1410
                $result = $this->call_trigger($triggername, $user);
1411
                if ($result < 0) {
1412
                    $error++;
1413
                }
1414
                // End call triggers
1415
            }
1416
1417
            if (!$error) {
1418
                $this->db->commit();
1419
                return count($factures_prev);   // The error of failed lines are into $this->invoice_in_error and $this->thirdparty_in_error
1420
            } else {
1421
                $this->db->rollback();
1422
                return -1;
1423
            }
1424
        } else {
1425
            return 0;
1426
        }
1427
    }
1428
1429
1430
    /**
1431
     *  Get object and lines from database
1432
     *
1433
     *  @param  User    $user       Object user that delete
1434
     *  @param  int     $notrigger  1=Does not execute triggers, 0= execute triggers
1435
     *  @return int                 >0 if OK, <0 if KO
1436
     */
1437
    public function delete($user = null, $notrigger = 0)
1438
    {
1439
        $this->db->begin();
1440
1441
        $error = 0;
1442
        $resql1 = $resql2 = $resql3 = $resql4 = 0;
1443
1444
        if (!$notrigger) {
1445
            $triggername = 'DIRECT_DEBIT_ORDER_DELETE';
1446
            if ($this->type == 'bank-transfer') {
1447
                $triggername = 'PAYMENTBYBANKTRANFER_DELETE';
1448
            }
1449
            // Call trigger
1450
            $result = $this->call_trigger($triggername, $user);
1451
            if ($result < 0) {
1452
                $error++;
1453
            }
1454
            // End call triggers
1455
        }
1456
1457
        if (!$error) {
1458
            $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) . ")";
1459
            $resql1 = $this->db->query($sql);
1460
            if (!$resql1) {
1461
                dol_print_error($this->db);
1462
            }
1463
        }
1464
1465
        if (!$error) {
1466
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "prelevement_lignes WHERE fk_prelevement_bons = " . ((int) $this->id);
1467
            $resql2 = $this->db->query($sql);
1468
            if (!$resql2) {
1469
                dol_print_error($this->db);
1470
            }
1471
        }
1472
1473
        if (!$error) {
1474
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "prelevement_bons WHERE rowid = " . ((int) $this->id);
1475
            $resql3 = $this->db->query($sql);
1476
            if (!$resql3) {
1477
                dol_print_error($this->db);
1478
            }
1479
        }
1480
1481
        if (!$error) {
1482
            $sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_demande SET fk_prelevement_bons = NULL, traite = 0 WHERE fk_prelevement_bons = " . ((int) $this->id);
1483
            $resql4 = $this->db->query($sql);
1484
            if (!$resql4) {
1485
                dol_print_error($this->db);
1486
            }
1487
        }
1488
1489
        if ($resql1 && $resql2 && $resql3 && $resql4 && !$error) {
1490
            $this->db->commit();
1491
            return 1;
1492
        } else {
1493
            $this->db->rollback();
1494
            return -1;
1495
        }
1496
    }
1497
1498
1499
    /**
1500
     *  Returns clickable name (with picto)
1501
     *
1502
     *  @param  int     $withpicto                  Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto)
1503
     *  @param  string  $option                     On what the link point to ('nolink', ...)
1504
     *  @param  int     $notooltip                  1=Disable tooltip
1505
     *  @param  string  $morecss                    Add more css on link
1506
     *  @param  int     $save_lastsearch_value      -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
1507
     *  @return string                              URL of target
1508
     */
1509
    public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1510
    {
1511
        global $conf, $langs, $hookmanager;
1512
1513
        if (!empty($conf->dol_no_mouse_hover)) {
1514
            $notooltip = 1; // Force disable tooltips
1515
        }
1516
1517
        $result = '';
1518
1519
        $labeltoshow = 'PaymentByDirectDebit';
1520
        if (!empty($this->type) && $this->type == 'bank-transfer') {
1521
            $labeltoshow = 'PaymentByBankTransfer';
1522
        }
1523
1524
        $label = img_picto('', $this->picto) . ' <u>' . $langs->trans($labeltoshow) . '</u> ' . $this->getLibStatut(5);
1525
        $label .= '<br>';
1526
        $label .= '<b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
1527
        if (isset($this->amount)) {
1528
            $label .= '<br><b>' . $langs->trans("Amount") . ":</b> " . price($this->amount);
1529
        }
1530
        if (isset($this->date_trans)) {
1531
            $label .= '<br><b>' . $langs->trans("TransData") . ":</b> " . dol_print_date($this->date_trans, 'dayhour', 'tzuserrel');
1532
        }
1533
        /*if (isset($this->date_credit)) {
1534
            $label .= '<br><b>'.$langs->trans("TransData").":</b> ".dol_print_date($this->date_credit, 'dayhour', 'tzuserrel');
1535
        }*/
1536
1537
        $url = constant('BASE_URL') . '/compta/prelevement/card.php?id=' . $this->id;
1538
        if (!empty($this->type) && $this->type == 'bank-transfer') {
1539
            $url = constant('BASE_URL') . '/compta/prelevement/card.php?id=' . $this->id;
1540
        }
1541
1542
        if ($option != 'nolink') {
1543
            // Add param to save lastsearch_values or not
1544
            $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1545
            if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1546
                $add_save_lastsearch_values = 1;
1547
            }
1548
            if ($add_save_lastsearch_values) {
1549
                $url .= '&save_lastsearch_values=1';
1550
            }
1551
        }
1552
1553
        $linkclose = '';
1554
        if (empty($notooltip)) {
1555
            if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1556
                $label = $langs->trans("ShowMyObject");
1557
                $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
1558
            }
1559
            $linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"';
1560
            $linkclose .= ' class="classfortooltip' . ($morecss ? ' ' . $morecss : '') . '"';
1561
        } else {
1562
            $linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
1563
        }
1564
1565
        $linkstart = '<a href="' . $url . '"';
1566
        $linkstart .= $linkclose . '>';
1567
        $linkend = '</a>';
1568
1569
        $result .= $linkstart;
1570
        if ($withpicto) {
1571
            $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);
1572
        }
1573
        if ($withpicto != 2) {
1574
            $result .= $this->ref;
1575
        }
1576
        $result .= $linkend;
1577
1578
        global $action, $hookmanager;
1579
        $hookmanager->initHooks(array('banktransferdao'));
1580
        $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1581
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1582
        if ($reshook > 0) {
1583
            $result = $hookmanager->resPrint;
1584
        } else {
1585
            $result .= $hookmanager->resPrint;
1586
        }
1587
1588
        return $result;
1589
    }
1590
1591
1592
    /**
1593
     *  Delete a notification def by id
1594
     *
1595
     *  @param  int     $rowid      id of notification
1596
     *  @return int                 0 if OK, <0 if KO
1597
     */
1598
    public function deleteNotificationById($rowid)
1599
    {
1600
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "notify_def";
1601
        $sql .= " WHERE rowid = " . ((int) $rowid);
1602
1603
        if ($this->db->query($sql)) {
1604
            return 0;
1605
        } else {
1606
            return -1;
1607
        }
1608
    }
1609
1610
    /**
1611
     *  Delete a notification
1612
     *
1613
     *  @param  int|User    $user       notification user
1614
     *  @param  string      $action     notification action
1615
     *  @return int                     >0 if OK, <0 if KO
1616
     */
1617
    public function deleteNotification($user, $action)
1618
    {
1619
        if (is_object($user)) {
1620
            $userid = $user->id;
1621
        } else {    // If user is an id
1622
            $userid = $user;
1623
        }
1624
1625
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "notify_def";
1626
        $sql .= " WHERE fk_user=" . ((int) $userid) . " AND fk_action='" . $this->db->escape($action) . "'";
1627
1628
        if ($this->db->query($sql)) {
1629
            return 0;
1630
        } else {
1631
            return -1;
1632
        }
1633
    }
1634
1635
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1636
    /**
1637
     *  Add a notification
1638
     *
1639
     *  @param  DoliDB      $db         database handler
1640
     *  @param  int|User    $user       notification user
1641
     *  @param  string      $action     notification action
1642
     *  @return int                     0 if OK, <0 if KO
1643
     */
1644
    public function addNotification($db, $user, $action)
1645
    {
1646
		// phpcs:enable
1647
        $result = 0;
1648
1649
        if (is_object($user)) {
1650
            $userid = $user->id;
1651
        } else {    // If user is an id
1652
            $userid = $user;
1653
        }
1654
1655
        if ($this->deleteNotification($user, $action) == 0) {
1656
            $now = dol_now();
1657
1658
            $sql = "INSERT INTO " . MAIN_DB_PREFIX . "notify_def (datec,fk_user, fk_soc, fk_contact, fk_action)";
1659
            $sql .= " VALUES ('" . $this->db->idate($now) . "', " . ((int) $userid) . ", 'NULL', 'NULL', '" . $this->db->escape($action) . "')";
1660
1661
            dol_syslog("adnotiff: " . $sql);
1662
            if ($this->db->query($sql)) {
1663
                $result = 0;
1664
            } else {
1665
                $result = -1;
1666
                dol_syslog(get_class($this) . "::addNotification Error $result");
1667
            }
1668
        }
1669
1670
        return $result;
1671
    }
1672
1673
1674
    /**
1675
     * Generate a direct debit or credit transfer file.
1676
     * Generation Formats:
1677
     * - Europe: SEPA (France: CFONB no more supported, Spain: AEB19 if external module EsAEB is enabled)
1678
     * - Others countries: Warning message
1679
     * File is generated with name this->filename
1680
     *
1681
     * @param   string  $format             FRST, RCUR or ALL
1682
     * @param   int     $executiondate      Timestamp date to execute transfer
1683
     * @param   string  $type               'direct-debit' or 'bank-transfer'
1684
     * @param   int     $fk_bank_account    Bank account ID the receipt is generated for. Will use the ID into the setup of module Direct Debit or Credit Transfer if 0.
1685
     * @param   int     $forsalary          If the SEPA is to pay salaries
1686
     * @return  int                         >=0 if OK, <0 if KO
1687
     */
1688
    public function generate($format = 'ALL', $executiondate = 0, $type = 'direct-debit', $fk_bank_account = 0, $forsalary = 0)
1689
    {
1690
        global $conf, $langs, $mysoc;
1691
1692
        //TODO: Optimize code to read lines in a single function
1693
1694
        // Clean params
1695
        if (empty($fk_bank_account)) {
1696
            $fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
1697
        }
1698
1699
        $result = 0;
1700
1701
        dol_syslog(get_class($this) . "::generate build file=" . $this->filename . " type=" . $type);
1702
1703
        $this->file = fopen($this->filename, "w");
1704
        if ($this->file == false) {
1705
            $this->error = $langs->trans('ErrorFailedToOpenFile', $this->filename);
1706
            return -1;
1707
        }
1708
1709
        $found = 0;
1710
        $this->total = 0;
1711
1712
        // Build file for European countries
1713
        if ($mysoc->isInEEC()) {
1714
            $found++;
1715
1716
            if ($type != 'bank-transfer') {
1717
                /**
1718
                 * SECTION CREATION FICHIER SEPA - DIRECT DEBIT
1719
                 */
1720
                // SEPA Initialisation
1721
                $CrLf = "\n";
1722
1723
                $now = dol_now();
1724
1725
                $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S');
1726
1727
                $date_actu = $now;
1728
                if (!empty($executiondate)) {
1729
                    $date_actu = $executiondate;
1730
                }
1731
1732
                $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d');
1733
                $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S');
1734
                $fileDebiteurSection = '';
1735
                $fileEmetteurSection = '';
1736
                $i = 0;
1737
1738
                /*
1739
                 * Section Debitor (sepa Debiteurs block lines)
1740
                 */
1741
1742
                $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
1743
                $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1744
                $sql .= " f.ref as reffac, p.fk_facture as idfac,";
1745
                $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
1746
                $sql .= " FROM";
1747
                $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1748
                $sql .= " " . MAIN_DB_PREFIX . "facture as f,";
1749
                $sql .= " " . MAIN_DB_PREFIX . "prelevement as p,";
1750
                $sql .= " " . MAIN_DB_PREFIX . "societe as soc,";
1751
                $sql .= " " . MAIN_DB_PREFIX . "c_country as c,";
1752
                $sql .= " " . MAIN_DB_PREFIX . "societe_rib as rib";
1753
                $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
1754
                $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1755
                $sql .= " AND p.fk_facture = f.rowid";
1756
                $sql .= " AND f.fk_soc = soc.rowid";
1757
                $sql .= " AND soc.fk_pays = c.rowid";
1758
                $sql .= " AND rib.fk_soc = f.fk_soc";
1759
                $sql .= " AND rib.default_rib = 1";
1760
                $sql .= " AND rib.type = 'ban'";
1761
1762
                // Define $fileDebiteurSection. One section DrctDbtTxInf per invoice.
1763
                $resql = $this->db->query($sql);
1764
                if ($resql) {
1765
                    $cachearraytotestduplicate = array();
1766
1767
                    $num = $this->db->num_rows($resql);
1768
                    while ($i < $num) {
1769
                        $obj = $this->db->fetch_object($resql);
1770
1771
                        if (!empty($cachearraytotestduplicate[$obj->idfac])) {
1772
                            $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
1773
                            $this->invoice_in_error[$obj->idfac] = $this->error;
1774
                            $result = -2;
1775
                            break;
1776
                        }
1777
                        $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
1778
1779
                        $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
1780
1781
                        $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);
1782
1783
                        $this->total = $this->total + $obj->somme;
1784
                        $i++;
1785
                    }
1786
                    $nbtotalDrctDbtTxInf = $i;
1787
                } else {
1788
                    $this->error = $this->db->lasterror();
1789
                    fwrite($this->file, 'ERROR DEBITOR ' . $sql . $CrLf); // DEBITOR = Customers
1790
                    $result = -2;
1791
                }
1792
1793
                // Define $fileEmetteurSection. Start of block PmtInf. Will contains all $nbtotalDrctDbtTxInf
1794
                if ($result != -2) {
1795
                    $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type, $fk_bank_account);
1796
                }
1797
1798
                if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) {
1799
                    $this->total = number_format((float) price2num($this->total, 'MT'), 2, ".", "");
1800
                }
1801
1802
                /**
1803
                 * SECTION CREATION SEPA FILE - ISO200022
1804
                 */
1805
                // SEPA File Header
1806
                fwrite($this->file, '<' . '?xml version="1.0" encoding="UTF-8" standalone="yes"?' . '>' . $CrLf);
1807
                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);
1808
                fwrite($this->file, '	<CstmrDrctDbtInitn>' . $CrLf);
1809
                // SEPA Group header
1810
                fwrite($this->file, '		<GrpHdr>' . $CrLf);
1811
                fwrite($this->file, '			<MsgId>' . ('DD/' . $dateTime_YMD . '/REF' . $this->id) . '</MsgId>' . $CrLf);
1812
                fwrite($this->file, '			<CreDtTm>' . $dateTime_ECMA . '</CreDtTm>' . $CrLf);
1813
                fwrite($this->file, '			<NbOfTxs>' . $i . '</NbOfTxs>' . $CrLf);
1814
                fwrite($this->file, '			<CtrlSum>' . $this->total . '</CtrlSum>' . $CrLf);
1815
                fwrite($this->file, '			<InitgPty>' . $CrLf);
1816
                fwrite($this->file, '				<Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf);
1817
                fwrite($this->file, '				<Id>' . $CrLf);
1818
                fwrite($this->file, '				    <PrvtId>' . $CrLf);
1819
                fwrite($this->file, '					<Othr>' . $CrLf);
1820
                fwrite($this->file, '						<Id>' . $this->emetteur_ics . '</Id>' . $CrLf);
1821
                fwrite($this->file, '					</Othr>' . $CrLf);
1822
                fwrite($this->file, '				    </PrvtId>' . $CrLf);
1823
                fwrite($this->file, '				</Id>' . $CrLf);
1824
                fwrite($this->file, '			</InitgPty>' . $CrLf);
1825
                fwrite($this->file, '		</GrpHdr>' . $CrLf);
1826
                // SEPA File Emetteur
1827
                if ($result != -2) {
1828
                    fwrite($this->file, $fileEmetteurSection);
1829
                }
1830
                // SEPA File Debiteurs
1831
                if ($result != -2) {
1832
                    fwrite($this->file, $fileDebiteurSection);
1833
                }
1834
                // SEPA FILE FOOTER
1835
                fwrite($this->file, '		</PmtInf>' . $CrLf);
1836
                fwrite($this->file, '	</CstmrDrctDbtInitn>' . $CrLf);
1837
                fwrite($this->file, '</Document>' . $CrLf);
1838
            } else {
1839
                /**
1840
                 * SECTION CREATION FICHIER SEPA - CREDIT TRANSFER
1841
                 */
1842
                // SEPA Initialisation
1843
                $CrLf = "\n";
1844
1845
                $now = dol_now();
1846
1847
                $dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S');
1848
1849
                $date_actu = $now;
1850
                if (!empty($executiondate)) {
1851
                    $date_actu = $executiondate;
1852
                }
1853
1854
                $dateTime_YMD = dol_print_date($date_actu, '%Y%m%d');
1855
                $dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S');
1856
                $fileCrediteurSection = '';
1857
                $fileEmetteurSection = '';
1858
                $i = 0;
1859
1860
                /*
1861
                 * Section Creditor (sepa Crediteurs block lines)
1862
                 */
1863
                if (!empty($forsalary)) {
1864
                    $sql = "SELECT u.rowid as userId, u.address, u.zip, u.town, c.code as country_code, CONCAT(u.firstname,' ',u.lastname) as nom,";
1865
                    $sql .= " pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1866
                    $sql .= " s.ref as reffac, p.fk_salary as idfac,";
1867
                    $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, '' as rum, '' as date_rum";
1868
                    $sql .= " FROM";
1869
                    $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1870
                    $sql .= " " . MAIN_DB_PREFIX . "salary as s,";
1871
                    $sql .= " " . MAIN_DB_PREFIX . "prelevement as p,";
1872
                    $sql .= " " . MAIN_DB_PREFIX . "user as u";
1873
                    $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_country as c ON u.fk_country = c.rowid,";
1874
                    $sql .= " " . MAIN_DB_PREFIX . "user_rib as rib";
1875
                    $sql .= " WHERE pl.fk_prelevement_bons=" . ((int) $this->id);
1876
                    $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1877
                    $sql .= " AND p.fk_salary = s.rowid";
1878
                    $sql .= " AND s.fk_user = u.rowid";
1879
                    $sql .= " AND rib.fk_user = s.fk_user";
1880
                } else {
1881
                    $sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,";
1882
                    $sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,";
1883
                    $sql .= " f.ref as reffac, f.ref_supplier as fac_ref_supplier, p.fk_facture_fourn as idfac,";
1884
                    $sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum";
1885
                    $sql .= " FROM";
1886
                    $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1887
                    $sql .= " " . MAIN_DB_PREFIX . "facture_fourn as f,";
1888
                    $sql .= " " . MAIN_DB_PREFIX . "prelevement as p,";
1889
                    $sql .= " " . MAIN_DB_PREFIX . "societe as soc";
1890
                    $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_country as c ON soc.fk_pays = c.rowid,";
1891
                    $sql .= " " . MAIN_DB_PREFIX . "societe_rib as rib";
1892
                    $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
1893
                    $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1894
                    $sql .= " AND p.fk_facture_fourn = f.rowid";
1895
                    $sql .= " AND f.fk_soc = soc.rowid";
1896
                    $sql .= " AND rib.fk_soc = f.fk_soc";
1897
                    $sql .= " AND rib.default_rib = 1";
1898
                    $sql .= " AND rib.type = 'ban'";
1899
                }
1900
                // Define $fileCrediteurSection. One section DrctDbtTxInf per invoice.
1901
                $resql = $this->db->query($sql);
1902
                if ($resql) {
1903
                    $cachearraytotestduplicate = array();
1904
1905
                    $num = $this->db->num_rows($resql);
1906
                    while ($i < $num) {
1907
                        $obj = $this->db->fetch_object($resql);
1908
                        if (!empty($cachearraytotestduplicate[$obj->idfac])) {
1909
                            $this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid);
1910
                            $this->invoice_in_error[$obj->idfac] = $this->error;
1911
                            $result = -2;
1912
                            break;
1913
                        }
1914
                        $cachearraytotestduplicate[$obj->idfac] = $obj->rowid;
1915
1916
                        $daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec);
1917
                        $refobj = $obj->reffac;
1918
                        if (empty($refobj) && !empty($forsalary)) { // If ref of salary not defined, we force a value
1919
                            $refobj = "SAL" . $obj->idfac;
1920
                        }
1921
1922
                        $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);
1923
1924
                        $this->total = $this->total + $obj->somme;
1925
                        $i++;
1926
                    }
1927
                    $nbtotalDrctDbtTxInf = $i;
1928
                } else {
1929
                    $this->error = $this->db->lasterror();
1930
                    fwrite($this->file, 'ERROR CREDITOR ' . $sql . $CrLf); // CREDITORS = Suppliers
1931
                    $result = -2;
1932
                }
1933
                // Define $fileEmetteurSection. Start of block PmtInf. Will contains all $nbtotalDrctDbtTxInf
1934
                if ($result != -2) {
1935
                    $fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type);
1936
                }
1937
1938
                if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) {
1939
                    $this->total = number_format((float) price2num($this->total, 'MT'), 2, ".", "");
1940
                }
1941
1942
                /**
1943
                 * SECTION CREATION SEPA FILE - CREDIT TRANSFER - ISO200022
1944
                 */
1945
                // SEPA File Header
1946
                fwrite($this->file, '<' . '?xml version="1.0" encoding="UTF-8" standalone="yes"?' . '>' . $CrLf);
1947
                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);
1948
                fwrite($this->file, '	<CstmrCdtTrfInitn>' . $CrLf);
1949
                // SEPA Group header
1950
                fwrite($this->file, '		<GrpHdr>' . $CrLf);
1951
                fwrite($this->file, '			<MsgId>' . ('TRF/' . $dateTime_YMD . '/REF' . $this->id) . '</MsgId>' . $CrLf);
1952
                fwrite($this->file, '			<CreDtTm>' . $dateTime_ECMA . '</CreDtTm>' . $CrLf);
1953
                fwrite($this->file, '			<NbOfTxs>' . $i . '</NbOfTxs>' . $CrLf);
1954
                fwrite($this->file, '			<CtrlSum>' . $this->total . '</CtrlSum>' . $CrLf);
1955
                fwrite($this->file, '			<InitgPty>' . $CrLf);
1956
                fwrite($this->file, '				<Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf);
1957
                fwrite($this->file, '				<Id>' . $CrLf);
1958
                fwrite($this->file, '				    <PrvtId>' . $CrLf);
1959
                fwrite($this->file, '					<Othr>' . $CrLf);
1960
                fwrite($this->file, '						<Id>' . $this->emetteur_ics . '</Id>' . $CrLf);
1961
                fwrite($this->file, '					</Othr>' . $CrLf);
1962
                fwrite($this->file, '				    </PrvtId>' . $CrLf);
1963
                fwrite($this->file, '				</Id>' . $CrLf);
1964
                fwrite($this->file, '			</InitgPty>' . $CrLf);
1965
                fwrite($this->file, '		</GrpHdr>' . $CrLf);
1966
                // SEPA File Emetteur (mycompany)
1967
                if ($result != -2) {
1968
                    fwrite($this->file, $fileEmetteurSection);
1969
                }
1970
                // SEPA File Creditors
1971
                if ($result != -2) {
1972
                    fwrite($this->file, $fileCrediteurSection);
1973
                }
1974
                // SEPA FILE FOOTER
1975
                fwrite($this->file, '		</PmtInf>' . $CrLf);
1976
                fwrite($this->file, '	</CstmrCdtTrfInitn>' . $CrLf);
1977
                fwrite($this->file, '</Document>' . $CrLf);
1978
            }
1979
        }
1980
1981
        // Build file for Other Countries with unknown format
1982
        if (!$found) {
1983
            if ($type != 'bank-transfer') {
1984
                $sql = "SELECT pl.amount";
1985
                $sql .= " FROM";
1986
                $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
1987
                $sql .= " " . MAIN_DB_PREFIX . "facture as f,";
1988
                $sql .= " " . MAIN_DB_PREFIX . "prelevement as p";
1989
                $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
1990
                $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
1991
                $sql .= " AND p.fk_facture = f.rowid";
1992
1993
                // Lines
1994
                $i = 0;
1995
                $resql = $this->db->query($sql);
1996
                if ($resql) {
1997
                    $num = $this->db->num_rows($resql);
1998
1999
                    while ($i < $num) {
2000
                        $obj = $this->db->fetch_object($resql);
2001
                        $this->total = $this->total + $obj->amount;
2002
2003
                        // TODO Write record into file
2004
                        $i++;
2005
                    }
2006
                } else {
2007
                    $result = -2;
2008
                }
2009
            } else {
2010
                $sql = "SELECT pl.amount";
2011
                $sql .= " FROM";
2012
                $sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,";
2013
                $sql .= " " . MAIN_DB_PREFIX . "facture_fourn as f,";
2014
                $sql .= " " . MAIN_DB_PREFIX . "prelevement as p";
2015
                $sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id);
2016
                $sql .= " AND pl.rowid = p.fk_prelevement_lignes";
2017
                $sql .= " AND p.fk_facture_fourn = f.rowid";
2018
                // Lines
2019
                $i = 0;
2020
                $resql = $this->db->query($sql);
2021
                if ($resql) {
2022
                    $num = $this->db->num_rows($resql);
2023
2024
                    while ($i < $num) {
2025
                        $obj = $this->db->fetch_object($resql);
2026
                        $this->total = $this->total + $obj->amount;
2027
2028
                        // TODO Write record into file
2029
                        $i++;
2030
                    }
2031
                } else {
2032
                    $result = -2;
2033
                }
2034
            }
2035
2036
            $langs->load('withdrawals');
2037
2038
            // TODO Add here code to generate a generic file
2039
            fwrite($this->file, $langs->transnoentitiesnoconv('WithdrawalFileNotCapable', $mysoc->country_code));
2040
        }
2041
2042
        fclose($this->file);
2043
        dolChmod($this->filename);
2044
2045
        return $result;
2046
    }
2047
2048
2049
    /**
2050
     * Generate dynamically a RUM number for a customer bank account
2051
     *
2052
     * @param   string      $row_code_client    Customer code (soc.code_client)
2053
     * @param   int         $row_datec          Creation date of bank account (rib.datec)
2054
     * @param   string      $row_drum           Id of customer bank account (rib.rowid)
2055
     * @return  string      RUM number
2056
     */
2057
    public static function buildRumNumber($row_code_client, $row_datec, $row_drum)
2058
    {
2059
        global $langs;
2060
2061
        $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)
2062
2063
        // 3 char + '-' + 12 + '-' + id + '-' + code        Must be lower than 32.
2064
        return $pre . '-' . dol_print_date($row_datec, 'dayhourlogsmall') . '-' . dol_trunc($row_drum . ($row_code_client ? '-' . $row_code_client : ''), 13, 'right', 'UTF-8', 1);
2065
    }
2066
2067
2068
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2069
    /**
2070
     *  Write recipient of request (customer)
2071
     *
2072
     *  @param  int     $rowid          id of line
2073
     *  @param  string  $client_nom     name of customer
2074
     *  @param  string  $rib_banque     code of bank
2075
     *  @param  string  $rib_guichet    code of bank office
2076
     *  @param  string  $rib_number     bank account
2077
     *  @param  float   $amount         amount
2078
     *  @param  string  $ref        ref of invoice
2079
     *  @param  int     $facid          id of invoice
2080
     *  @param  string  $rib_dom        bank address
2081
     *  @param  string  $type           'direct-debit' or 'bank-transfer'
2082
     *  @return void
2083
     *  @see EnregDestinataireSEPA()
2084
     */
2085
    public function EnregDestinataire($rowid, $client_nom, $rib_banque, $rib_guichet, $rib_number, $amount, $ref, $facid, $rib_dom = '', $type = 'direct-debit')
2086
    {
2087
		// phpcs:enable
2088
        fwrite($this->file, "06");
2089
        fwrite($this->file, "08"); // Prelevement ordinaire
2090
2091
        fwrite($this->file, "        "); // Zone Reservee B2
2092
2093
        fwrite($this->file, $this->emetteur_ics); // ICS
2094
2095
        // Date d'echeance C1
2096
2097
        fwrite($this->file, "       ");
2098
        fwrite($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
2099
        fwrite($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
2100
2101
        // Raison Sociale Destinataire C2
2102
2103
        fwrite($this->file, substr(strtoupper($client_nom) . "                         ", 0, 24));
2104
2105
        // Address optional D1
2106
        $address = strtr($rib_dom, array(" " => "-", chr(13) => " ", chr(10) => ""));
2107
        fwrite($this->file, substr($address . "                         ", 0, 24));
2108
2109
        // Zone Reservee D2
2110
2111
        fwrite($this->file, substr("                             ", 0, 8));
2112
2113
        // Code Guichet  D3
2114
2115
        fwrite($this->file, $rib_guichet);
2116
2117
        // Numero de compte D4
2118
2119
        fwrite($this->file, substr("000000000000000" . $rib_number, -11));
2120
2121
        // Zone E Montant
2122
2123
        $montant = (round($amount, 2) * 100);
2124
2125
        fwrite($this->file, substr("000000000000000" . $montant, -16));
2126
2127
        // Label F
2128
2129
        fwrite($this->file, substr("*_" . $ref . "_RDVnet" . $rowid . "                               ", 0, 31));
2130
2131
        // Code etablissement G1
2132
2133
        fwrite($this->file, $rib_banque);
2134
2135
        // Zone Reservee G2
2136
2137
        fwrite($this->file, substr("                                        ", 0, 5));
2138
2139
        fwrite($this->file, "\n");
2140
    }
2141
2142
2143
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2144
    /**
2145
     *  Write recipient (thirdparty concerned by request)
2146
     *
2147
     *  @param  string      $row_code_client    soc.code_client as code,
2148
     *  @param  string      $row_nom            pl.client_nom AS name,
2149
     *  @param  string      $row_address        soc.address AS adr,
2150
     *  @param  string      $row_zip            soc.zip
2151
     *  @param  string      $row_town           soc.town
2152
     *  @param  string      $row_country_code   c.code AS country,
2153
     *  @param  string      $row_cb             pl.code_banque AS cb,       Not used for SEPA
2154
     *  @param  string      $row_cg             pl.code_guichet AS cg,      Not used for SEPA
2155
     *  @param  string      $row_cc             pl.number AS cc,            Not used for SEPA
2156
     *  @param  float       $row_somme          pl.amount AS somme,
2157
     *  @param  string      $row_ref            Invoice ref (f.ref) or Salary ref
2158
     *  @param  int         $row_idfac          p.fk_facture AS idfac or p.fk_facture_fourn or p.fk_salary,
2159
     *  @param  string      $row_iban           rib.iban_prefix AS iban,
2160
     *  @param  string      $row_bic            rib.bic AS bic,
2161
     *  @param  string      $row_datec          rib.datec,
2162
     *  @param  string      $row_drum           rib.rowid used to generate rum
2163
     *  @param  string      $row_rum            rib.rum Rum defined on company bank account
2164
     *  @param  string      $type               'direct-debit' or 'bank-transfer'
2165
     *  @param  string      $row_comment        A free text string for the Unstructured data field
2166
     *  @return string                          Return string with SEPA part DrctDbtTxInf
2167
     *  @see EnregDestinataire()
2168
     */
2169
    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 = '')
2170
    {
2171
		// phpcs:enable
2172
        global $conf;
2173
2174
        if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) {
2175
            $row_somme = number_format((float) price2num($row_somme, 'MT'), 2, ".", "");
2176
        } else {
2177
            $row_somme = round((float) $row_somme, 2);
2178
        }
2179
2180
        include_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php';
2181
2182
        $CrLf = "\n";
2183
        $Rowing = sprintf("%010d", $row_idfac);
2184
2185
        // Define value for RUM
2186
        // Example:  RUM-CustomerCode-CustomerBankAccountId-01424448606 (note: Date is the timestamp of the date of creation of CustomerBankAccountId)
2187
        $Rum = (empty($row_rum) ? $this->buildRumNumber($row_code_client, $row_datec, $row_drum) : $row_rum);
2188
2189
        // Define date of RUM signature
2190
        $DtOfSgntr = dol_print_date($row_datec, '%Y-%m-%d');
2191
2192
        if ($type != 'bank-transfer') {
2193
            // SEPA Paiement Information of buyer for Direct Debit
2194
            $XML_DEBITOR = '';
2195
            $XML_DEBITOR .= '			<DrctDbtTxInf>' . $CrLf;
2196
            $XML_DEBITOR .= '				<PmtId>' . $CrLf;
2197
            // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
2198
            $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
2199
            $XML_DEBITOR .= '				</PmtId>' . $CrLf;
2200
            $XML_DEBITOR .= '				<InstdAmt Ccy="EUR">' . $row_somme . '</InstdAmt>' . $CrLf;
2201
            $XML_DEBITOR .= '				<DrctDbtTx>' . $CrLf;
2202
            $XML_DEBITOR .= '					<MndtRltdInf>' . $CrLf;
2203
            $XML_DEBITOR .= '						<MndtId>' . $Rum . '</MndtId>' . $CrLf;
2204
            $XML_DEBITOR .= '						<DtOfSgntr>' . $DtOfSgntr . '</DtOfSgntr>' . $CrLf;
2205
            $XML_DEBITOR .= '						<AmdmntInd>false</AmdmntInd>' . $CrLf;
2206
            $XML_DEBITOR .= '					</MndtRltdInf>' . $CrLf;
2207
            $XML_DEBITOR .= '				</DrctDbtTx>' . $CrLf;
2208
            $XML_DEBITOR .= '				<DbtrAgt>' . $CrLf;
2209
            $XML_DEBITOR .= '					<FinInstnId>' . $CrLf;
2210
            $XML_DEBITOR .= '						<BIC>' . $row_bic . '</BIC>' . $CrLf;
2211
            $XML_DEBITOR .= '					</FinInstnId>' . $CrLf;
2212
            $XML_DEBITOR .= '				</DbtrAgt>' . $CrLf;
2213
            $XML_DEBITOR .= '				<Dbtr>' . $CrLf;
2214
            $XML_DEBITOR .= '					<Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))) . '</Nm>' . $CrLf;
2215
            $XML_DEBITOR .= '					<PstlAdr>' . $CrLf;
2216
            $XML_DEBITOR .= '						<Ctry>' . $row_country_code . '</Ctry>' . $CrLf;
2217
            $addressline1 = strtr($row_address, array(chr(13) => ", ", chr(10) => ""));
2218
            $addressline2 = strtr($row_zip . (($row_zip && $row_town) ? ' ' : (string) $row_town), array(chr(13) => ", ", chr(10) => ""));
2219
            if (trim($addressline1)) {
2220
                $XML_DEBITOR .= '						<AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2221
            }
2222
            if (trim($addressline2)) {
2223
                $XML_DEBITOR .= '						<AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2224
            }
2225
            $XML_DEBITOR .= '					</PstlAdr>' . $CrLf;
2226
            $XML_DEBITOR .= '				</Dbtr>' . $CrLf;
2227
            $XML_DEBITOR .= '				<DbtrAcct>' . $CrLf;
2228
            $XML_DEBITOR .= '					<Id>' . $CrLf;
2229
            $XML_DEBITOR .= '						<IBAN>' . preg_replace('/\s/', '', $row_iban) . '</IBAN>' . $CrLf;
2230
            $XML_DEBITOR .= '					</Id>' . $CrLf;
2231
            $XML_DEBITOR .= '				</DbtrAcct>' . $CrLf;
2232
            $XML_DEBITOR .= '				<RmtInf>' . $CrLf;
2233
            // A string with some information on payment - 140 max
2234
            $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
2235
            $XML_DEBITOR .= '				</RmtInf>' . $CrLf;
2236
            $XML_DEBITOR .= '			</DrctDbtTxInf>' . $CrLf;
2237
            return $XML_DEBITOR;
2238
        } else {
2239
            // SEPA Payment Information of seller for Credit Transfer
2240
            $XML_CREDITOR = '';
2241
            $XML_CREDITOR .= '			<CdtTrfTxInf>' . $CrLf;
2242
            $XML_CREDITOR .= '				<PmtId>' . $CrLf;
2243
            // Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum)
2244
            $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
2245
            $XML_CREDITOR .= '				</PmtId>' . $CrLf;
2246
            if (!empty($this->sepa_xml_pti_in_ctti)) {
2247
                $XML_CREDITOR .= '				<PmtTpInf>' . $CrLf;
2248
2249
                // Can be 'NORM' for normal or 'HIGH' for high priority level
2250
                if (getDolGlobalString('PAYMENTBYBANKTRANSFER_FORCE_HIGH_PRIORITY')) {
2251
                    $instrprty = 'HIGH';
2252
                } else {
2253
                    $instrprty = 'NORM';
2254
                }
2255
                $XML_CREDITOR .= '					<InstrPrty>' . $instrprty . '</InstrPrty>' . $CrLf;
2256
                $XML_CREDITOR .= '					<SvcLvl>' . $CrLf;
2257
                $XML_CREDITOR .= '						<Cd>SEPA</Cd>' . $CrLf;
2258
                $XML_CREDITOR .= '					</SvcLvl>' . $CrLf;
2259
                $XML_CREDITOR .= '					<CtgyPurp>' . $CrLf;
2260
                $XML_CREDITOR .= '						<Cd>CORE</Cd>' . $CrLf;
2261
                $XML_CREDITOR .= '					</CtgyPurp>' . $CrLf;
2262
                $XML_CREDITOR .= '				</PmtTpInf>' . $CrLf;
2263
            }
2264
            $XML_CREDITOR .= '				<Amt>' . $CrLf;
2265
            $XML_CREDITOR .= '				<InstdAmt Ccy="EUR">' . round((float) $row_somme, 2) . '</InstdAmt>' . $CrLf;
2266
            $XML_CREDITOR .= '				</Amt>' . $CrLf;
2267
            /*
2268
             $XML_CREDITOR .= '             <DrctDbtTx>'.$CrLf;
2269
             $XML_CREDITOR .= '                 <MndtRltdInf>'.$CrLf;
2270
             $XML_CREDITOR .= '                     <MndtId>'.$Rum.'</MndtId>'.$CrLf;
2271
             $XML_CREDITOR .= '                     <DtOfSgntr>'.$DtOfSgntr.'</DtOfSgntr>'.$CrLf;
2272
             $XML_CREDITOR .= '                     <AmdmntInd>false</AmdmntInd>'.$CrLf;
2273
             $XML_CREDITOR .= '                 </MndtRltdInf>'.$CrLf;
2274
             $XML_CREDITOR .= '             </DrctDbtTx>'.$CrLf;
2275
             */
2276
            //$XML_CREDITOR .= '                <ChrgBr>SLEV</ChrgBr>'.$CrLf;
2277
            $XML_CREDITOR .= '				<CdtrAgt>' . $CrLf;
2278
            $XML_CREDITOR .= '					<FinInstnId>' . $CrLf;
2279
            $XML_CREDITOR .= '						<BIC>' . $row_bic . '</BIC>' . $CrLf;
2280
            $XML_CREDITOR .= '					</FinInstnId>' . $CrLf;
2281
            $XML_CREDITOR .= '				</CdtrAgt>' . $CrLf;
2282
            $XML_CREDITOR .= '				<Cdtr>' . $CrLf;
2283
            $XML_CREDITOR .= '					<Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))) . '</Nm>' . $CrLf;
2284
            $XML_CREDITOR .= '					<PstlAdr>' . $CrLf;
2285
            $XML_CREDITOR .= '						<Ctry>' . $row_country_code . '</Ctry>' . $CrLf;
2286
            $addressline1 = strtr($row_address, array(chr(13) => ", ", chr(10) => ""));
2287
            $addressline2 = strtr($row_zip . (($row_zip && $row_town) ? ' ' : (string) $row_town), array(chr(13) => ", ", chr(10) => ""));
2288
            if (trim($addressline1)) {
2289
                $XML_CREDITOR .= '						<AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2290
            }
2291
            if (trim($addressline2)) {
2292
                $XML_CREDITOR .= '						<AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2293
            }
2294
            $XML_CREDITOR .= '					</PstlAdr>' . $CrLf;
2295
            $XML_CREDITOR .= '				</Cdtr>' . $CrLf;
2296
            $XML_CREDITOR .= '				<CdtrAcct>' . $CrLf;
2297
            $XML_CREDITOR .= '					<Id>' . $CrLf;
2298
            $XML_CREDITOR .= '						<IBAN>' . preg_replace('/\s/', '', $row_iban) . '</IBAN>' . $CrLf;
2299
            $XML_CREDITOR .= '					</Id>' . $CrLf;
2300
            $XML_CREDITOR .= '				</CdtrAcct>' . $CrLf;
2301
            $XML_CREDITOR .= '				<RmtInf>' . $CrLf;
2302
            // A string with some information on payment - 140 max
2303
            $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
2304
            $XML_CREDITOR .= '				</RmtInf>' . $CrLf;
2305
            $XML_CREDITOR .= '			</CdtTrfTxInf>' . $CrLf;
2306
            return $XML_CREDITOR;
2307
        }
2308
    }
2309
2310
2311
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2312
    /**
2313
     *  Write sender of request (me).
2314
     *
2315
     *  @param  string      $type               'direct-debit' or 'bank-transfer'
2316
     *  @return void
2317
     *  @see EnregEmetteurSEPA()
2318
     */
2319
    public function EnregEmetteur($type = 'direct-debit')
2320
    {
2321
		// phpcs:enable
2322
        fwrite($this->file, "03");
2323
        fwrite($this->file, "08"); // Prelevement ordinaire
2324
2325
        fwrite($this->file, "        "); // Zone Reservee B2
2326
2327
        fwrite($this->file, $this->emetteur_ics); // ICS
2328
2329
        // Date d'echeance C1
2330
2331
        fwrite($this->file, "       ");
2332
        fwrite($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt'));
2333
        fwrite($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1));
2334
2335
        // Raison Sociale C2
2336
2337
        fwrite($this->file, substr($this->raison_sociale . "                           ", 0, 24));
2338
2339
        // Reference de la remise creancier D1 sur 7 caracteres
2340
2341
        fwrite($this->file, substr($this->reference_remise . "                           ", 0, 7));
2342
2343
        // Zone Reservee D1-2
2344
2345
        fwrite($this->file, substr("                                    ", 0, 17));
2346
2347
        // Zone Reservee D2
2348
2349
        fwrite($this->file, substr("                             ", 0, 2));
2350
        fwrite($this->file, "E");
2351
        fwrite($this->file, substr("                             ", 0, 5));
2352
2353
        // Code Guichet  D3
2354
2355
        fwrite($this->file, $this->emetteur_code_guichet);
2356
2357
        // Numero de compte D4
2358
2359
        fwrite($this->file, substr("000000000000000" . $this->emetteur_numero_compte, -11));
2360
2361
        // Zone Reservee E
2362
2363
        fwrite($this->file, substr("                                        ", 0, 16));
2364
2365
        // Zone Reservee F
2366
2367
        fwrite($this->file, substr("                                        ", 0, 31));
2368
2369
        // Code etablissement
2370
2371
        fwrite($this->file, $this->emetteur_code_banque);
2372
2373
        // Zone Reservee G
2374
2375
        fwrite($this->file, substr("                                        ", 0, 5));
2376
2377
        fwrite($this->file, "\n");
2378
    }
2379
2380
2381
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2382
    /**
2383
     *  Write sender of request (me).
2384
     *  Note: The tag PmtInf is opened here but closed into caller
2385
     *
2386
     *  @param  Conf    $configuration      conf
2387
     *  @param  int     $ladate             Date
2388
     *  @param  int     $nombre             0 or 1
2389
     *  @param  float   $total              Total
2390
     *  @param  string  $CrLf               End of line character
2391
     *  @param  string  $format             FRST or RCUR or ALL
2392
     *  @param  string  $type               'direct-debit' or 'bank-transfer'
2393
     *  @param  int     $fk_bank_account    Bank account ID the receipt is generated for. Will use the ID into the setup of module Direct Debit or Credit Transfer if 0.
2394
     *  @return string                      String with SEPA Sender
2395
     *  @see EnregEmetteur()
2396
     */
2397
    public function EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf = '\n', $format = 'FRST', $type = 'direct-debit', $fk_bank_account = 0)
2398
    {
2399
		// phpcs:enable
2400
2401
        // Clean parameters
2402
        $dateTime_YMD = dol_print_date($ladate, '%Y%m%d');
2403
        $dateTime_ETAD = dol_print_date($ladate, '%Y-%m-%d');
2404
        $dateTime_YMDHMS = dol_print_date($ladate, '%Y-%m-%dT%H:%M:%S');
2405
2406
        // Clean params
2407
        if (empty($fk_bank_account)) {
2408
            $fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT'));
2409
        }
2410
2411
        // Get data of bank account
2412
        $account = new Account($this->db);
2413
        if ($account->fetch($fk_bank_account) > 0) {
2414
            $this->emetteur_code_banque = $account->code_banque;
2415
            $this->emetteur_code_guichet = $account->code_guichet;
2416
            $this->emetteur_numero_compte = $account->number;
2417
            $this->emetteur_number_key = $account->cle_rib;
2418
            $this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti;
2419
            $this->emetteur_iban = $account->iban;
2420
            $this->emetteur_bic = $account->bic;
2421
2422
            $this->emetteur_ics = (($type == 'bank-transfer' && getDolGlobalString("SEPA_USE_IDS")) ? $account->ics_transfer : $account->ics);  // Ex: PRELEVEMENT_ICS = "FR78ZZZ123456";
2423
2424
            $this->raison_sociale = $account->proprio;
0 ignored issues
show
Bug Best Practice introduced by
The property $proprio is declared private in Dolibarr\Code\Compta\Classes\Account. Since you implement __get, consider adding a @property or @property-read.
Loading history...
2425
        }
2426
2427
        // Get pending payments
2428
        $sql = "SELECT rowid, ref";
2429
        $sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons as pb";
2430
        $sql .= " WHERE pb.rowid = " . ((int) $this->id);
2431
2432
        $resql = $this->db->query($sql);
2433
        if ($resql) {
2434
            $obj = $this->db->fetch_object($resql);
2435
2436
            $country = explode(':', $configuration->global->MAIN_INFO_SOCIETE_COUNTRY);
2437
            $IdBon  = sprintf("%05d", $obj->rowid);
2438
            $RefBon = $obj->ref;
2439
2440
            if (!empty($configuration->global->SEPA_FORCE_TWO_DECIMAL)) {
2441
                $total = number_format((float) price2num($total, 'MT'), 2, ".", "");
2442
            }
2443
2444
            if ($type != 'bank-transfer') {
2445
                // SEPA Paiement Information of my company for Direct Debit
2446
                $XML_SEPA_INFO = '';
2447
                $XML_SEPA_INFO .= '		<PmtInf>' . $CrLf;
2448
                $XML_SEPA_INFO .= '			<PmtInfId>' . ('DD/' . $dateTime_YMD . '/ID' . $IdBon . '-' . $RefBon) . '</PmtInfId>' . $CrLf;
2449
                $XML_SEPA_INFO .= '			<PmtMtd>DD</PmtMtd>' . $CrLf;
2450
                $XML_SEPA_INFO .= '			<NbOfTxs>' . $nombre . '</NbOfTxs>' . $CrLf;
2451
                $XML_SEPA_INFO .= '			<CtrlSum>' . $total . '</CtrlSum>' . $CrLf;
2452
                $XML_SEPA_INFO .= '			<PmtTpInf>' . $CrLf;
2453
                $XML_SEPA_INFO .= '				<SvcLvl>' . $CrLf;
2454
                $XML_SEPA_INFO .= '					<Cd>SEPA</Cd>' . $CrLf;
2455
                $XML_SEPA_INFO .= '				</SvcLvl>' . $CrLf;
2456
                $XML_SEPA_INFO .= '				<LclInstrm>' . $CrLf;
2457
                $XML_SEPA_INFO .= '					<Cd>CORE</Cd>' . $CrLf;
2458
                $XML_SEPA_INFO .= '				</LclInstrm>' . $CrLf;
2459
                $XML_SEPA_INFO .= '				<SeqTp>' . $format . '</SeqTp>' . $CrLf;
2460
                $XML_SEPA_INFO .= '			</PmtTpInf>' . $CrLf;
2461
                $XML_SEPA_INFO .= '			<ReqdColltnDt>' . $dateTime_ETAD . '</ReqdColltnDt>' . $CrLf;
2462
                $XML_SEPA_INFO .= '			<Cdtr>' . $CrLf;
2463
                $XML_SEPA_INFO .= '				<Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf;
2464
                $XML_SEPA_INFO .= '				<PstlAdr>' . $CrLf;
2465
                $XML_SEPA_INFO .= '					<Ctry>' . $country[1] . '</Ctry>' . $CrLf;
2466
                $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(chr(13) => ", ", chr(10) => ""));
2467
                $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) => ""));
2468
                if ($addressline1) {
2469
                    $XML_SEPA_INFO .= '					<AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2470
                }
2471
                if ($addressline2) {
2472
                    $XML_SEPA_INFO .= '					<AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2473
                }
2474
                $XML_SEPA_INFO .= '				</PstlAdr>' . $CrLf;
2475
                $XML_SEPA_INFO .= '			</Cdtr>' . $CrLf;
2476
                $XML_SEPA_INFO .= '			<CdtrAcct>' . $CrLf;
2477
                $XML_SEPA_INFO .= '				<Id>' . $CrLf;
2478
                $XML_SEPA_INFO .= '					<IBAN>' . preg_replace('/\s/', '', $this->emetteur_iban) . '</IBAN>' . $CrLf;
2479
                $XML_SEPA_INFO .= '				</Id>' . $CrLf;
2480
                $XML_SEPA_INFO .= '			</CdtrAcct>' . $CrLf;
2481
                $XML_SEPA_INFO .= '			<CdtrAgt>' . $CrLf;
2482
                $XML_SEPA_INFO .= '				<FinInstnId>' . $CrLf;
2483
                $XML_SEPA_INFO .= '					<BIC>' . $this->emetteur_bic . '</BIC>' . $CrLf;
2484
                $XML_SEPA_INFO .= '				</FinInstnId>' . $CrLf;
2485
                $XML_SEPA_INFO .= '			</CdtrAgt>' . $CrLf;
2486
                /* $XML_SEPA_INFO .= '          <UltmtCdtr>'.$CrLf;
2487
                 $XML_SEPA_INFO .= '                <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2488
                 $XML_SEPA_INFO .= '                <PstlAdr>'.$CrLf;
2489
                 $XML_SEPA_INFO .= '                    <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2490
                 $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;
2491
                 $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;
2492
                 $XML_SEPA_INFO .= '                </PstlAdr>'.$CrLf;
2493
                 $XML_SEPA_INFO .= '            </UltmtCdtr>'.$CrLf;*/
2494
                $XML_SEPA_INFO .= '			<ChrgBr>SLEV</ChrgBr>' . $CrLf; // Field "Responsible of fees". Must be SLEV
2495
                $XML_SEPA_INFO .= '			<CdtrSchmeId>' . $CrLf;
2496
                $XML_SEPA_INFO .= '				<Id>' . $CrLf;
2497
                $XML_SEPA_INFO .= '					<PrvtId>' . $CrLf;
2498
                $XML_SEPA_INFO .= '						<Othr>' . $CrLf;
2499
                $XML_SEPA_INFO .= '							<Id>' . $this->emetteur_ics . '</Id>' . $CrLf;
2500
                $XML_SEPA_INFO .= '							<SchmeNm>' . $CrLf;
2501
                $XML_SEPA_INFO .= '								<Prtry>SEPA</Prtry>' . $CrLf;
2502
                $XML_SEPA_INFO .= '							</SchmeNm>' . $CrLf;
2503
                $XML_SEPA_INFO .= '						</Othr>' . $CrLf;
2504
                $XML_SEPA_INFO .= '					</PrvtId>' . $CrLf;
2505
                $XML_SEPA_INFO .= '				</Id>' . $CrLf;
2506
                $XML_SEPA_INFO .= '			</CdtrSchmeId>' . $CrLf;
2507
            } else {
2508
                // SEPA Paiement Information of my company for Credit Transfer
2509
                $XML_SEPA_INFO = '';
2510
                $XML_SEPA_INFO .= '		<PmtInf>' . $CrLf;
2511
                $XML_SEPA_INFO .= '			<PmtInfId>' . ('TRF/' . $dateTime_YMD . '/ID' . $IdBon . '-' . $RefBon) . '</PmtInfId>' . $CrLf;
2512
                $XML_SEPA_INFO .= '			<PmtMtd>TRF</PmtMtd>' . $CrLf;
2513
                //$XML_SEPA_INFO .= '           <BtchBookg>False</BtchBookg>'.$CrLf;
2514
                $XML_SEPA_INFO .= '			<NbOfTxs>' . $nombre . '</NbOfTxs>' . $CrLf;
2515
                $XML_SEPA_INFO .= '			<CtrlSum>' . $total . '</CtrlSum>' . $CrLf;
2516
                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.
2517
                    $XML_SEPA_INFO .= '			<PmtTpInf>' . $CrLf;
2518
                    $XML_SEPA_INFO .= '				<SvcLvl>' . $CrLf;
2519
                    $XML_SEPA_INFO .= '					<Cd>SEPA</Cd>' . $CrLf;
2520
                    $XML_SEPA_INFO .= '				</SvcLvl>' . $CrLf;
2521
                    $XML_SEPA_INFO .= '				<LclInstrm>' . $CrLf;
2522
                    $XML_SEPA_INFO .= '					<Cd>CORE</Cd>' . $CrLf;
2523
                    $XML_SEPA_INFO .= '				</LclInstrm>' . $CrLf;
2524
                    $XML_SEPA_INFO .= '				<SeqTp>' . $format . '</SeqTp>' . $CrLf;
2525
                    $XML_SEPA_INFO .= '			</PmtTpInf>' . $CrLf;
2526
                }
2527
                $XML_SEPA_INFO .= '			<ReqdExctnDt>' . dol_print_date($dateTime_ETAD, 'dayrfc') . '</ReqdExctnDt>' . $CrLf;
2528
                $XML_SEPA_INFO .= '			<Dbtr>' . $CrLf;
2529
                $XML_SEPA_INFO .= '				<Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf;
2530
                $XML_SEPA_INFO .= '				<PstlAdr>' . $CrLf;
2531
                $XML_SEPA_INFO .= '					<Ctry>' . $country[1] . '</Ctry>' . $CrLf;
2532
                $addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(chr(13) => ", ", chr(10) => ""));
2533
                $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) => ""));
2534
                if ($addressline1) {
2535
                    $XML_SEPA_INFO .= '					<AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2536
                }
2537
                if ($addressline2) {
2538
                    $XML_SEPA_INFO .= '					<AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf;
2539
                }
2540
                $XML_SEPA_INFO .= '				</PstlAdr>' . $CrLf;
2541
                $XML_SEPA_INFO .= '			</Dbtr>' . $CrLf;
2542
                $XML_SEPA_INFO .= '			<DbtrAcct>' . $CrLf;
2543
                $XML_SEPA_INFO .= '				<Id>' . $CrLf;
2544
                $XML_SEPA_INFO .= '					<IBAN>' . preg_replace('/\s/', '', $this->emetteur_iban) . '</IBAN>' . $CrLf;
2545
                $XML_SEPA_INFO .= '				</Id>' . $CrLf;
2546
                $XML_SEPA_INFO .= '			</DbtrAcct>' . $CrLf;
2547
                $XML_SEPA_INFO .= '			<DbtrAgt>' . $CrLf;
2548
                $XML_SEPA_INFO .= '				<FinInstnId>' . $CrLf;
2549
                $XML_SEPA_INFO .= '					<BIC>' . $this->emetteur_bic . '</BIC>' . $CrLf;
2550
                $XML_SEPA_INFO .= '				</FinInstnId>' . $CrLf;
2551
                $XML_SEPA_INFO .= '			</DbtrAgt>' . $CrLf;
2552
                /* $XML_SEPA_INFO .= '          <UltmtCdtr>'.$CrLf;
2553
                 $XML_SEPA_INFO .= '                <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf;
2554
                 $XML_SEPA_INFO .= '                <PstlAdr>'.$CrLf;
2555
                 $XML_SEPA_INFO .= '                    <Ctry>'.$country[1].'</Ctry>'.$CrLf;
2556
                 $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;
2557
                 $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;
2558
                 $XML_SEPA_INFO .= '                </PstlAdr>'.$CrLf;
2559
                 $XML_SEPA_INFO .= '            </UltmtCdtr>'.$CrLf;*/
2560
                $XML_SEPA_INFO .= '			<ChrgBr>SLEV</ChrgBr>' . $CrLf; // Field "Responsible of fees". Must be SLEV
2561
                /*$XML_SEPA_INFO .= '           <CdtrSchmeId>'.$CrLf;
2562
                 $XML_SEPA_INFO .= '                <Id>'.$CrLf;
2563
                 $XML_SEPA_INFO .= '                    <PrvtId>'.$CrLf;
2564
                 $XML_SEPA_INFO .= '                        <Othr>'.$CrLf;
2565
                 $XML_SEPA_INFO .= '                            <Id>'.$this->emetteur_ics.'</Id>'.$CrLf;
2566
                 $XML_SEPA_INFO .= '                            <SchmeNm>'.$CrLf;
2567
                 $XML_SEPA_INFO .= '                                <Prtry>SEPA</Prtry>'.$CrLf;
2568
                 $XML_SEPA_INFO .= '                            </SchmeNm>'.$CrLf;
2569
                 $XML_SEPA_INFO .= '                        </Othr>'.$CrLf;
2570
                 $XML_SEPA_INFO .= '                    </PrvtId>'.$CrLf;
2571
                 $XML_SEPA_INFO .= '                </Id>'.$CrLf;
2572
                 $XML_SEPA_INFO .= '            </CdtrSchmeId>'.$CrLf;*/
2573
            }
2574
        } else {
2575
            fwrite($this->file, 'INCORRECT EMETTEUR ' . $this->raison_sociale . $CrLf);
2576
            $XML_SEPA_INFO = '';
2577
        }
2578
        return $XML_SEPA_INFO;
2579
    }
2580
2581
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2582
    /**
2583
     *  Write end
2584
     *
2585
     *  @param  int     $total  total amount
2586
     *  @return void
2587
     */
2588
    public function EnregTotal($total)
2589
    {
2590
		// phpcs:enable
2591
        fwrite($this->file, "08");
2592
        fwrite($this->file, "08"); // Prelevement ordinaire
2593
2594
        fwrite($this->file, "        "); // Zone Reservee B2
2595
2596
        fwrite($this->file, $this->emetteur_ics); // ICS
2597
2598
        // Reserve C1
2599
2600
        fwrite($this->file, substr("                           ", 0, 12));
2601
2602
2603
        // Raison Sociale C2
2604
2605
        fwrite($this->file, substr("                           ", 0, 24));
2606
2607
        // D1
2608
2609
        fwrite($this->file, substr("                                    ", 0, 24));
2610
2611
        // Zone Reservee D2
2612
2613
        fwrite($this->file, substr("                             ", 0, 8));
2614
2615
        // Code Guichet  D3
2616
2617
        fwrite($this->file, substr("                             ", 0, 5));
2618
2619
        // Numero de compte D4
2620
2621
        fwrite($this->file, substr("                             ", 0, 11));
2622
2623
        // Zone E Montant
2624
2625
        $montant = ($total * 100);
2626
2627
        fwrite($this->file, substr("000000000000000" . $montant, -16));
2628
2629
        // Zone Reservee F
2630
2631
        fwrite($this->file, substr("                                        ", 0, 31));
2632
2633
        // Code etablissement
2634
2635
        fwrite($this->file, substr("                                        ", 0, 5));
2636
2637
        // Zone Reservee F
2638
2639
        fwrite($this->file, substr("                                        ", 0, 5));
2640
2641
        fwrite($this->file, "\n");
2642
    }
2643
2644
    /**
2645
     *  Return status label of object
2646
     *
2647
     *  @param  int     $mode       0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
2648
     *  @return string              Label
2649
     */
2650
    public function getLibStatut($mode = 0)
2651
    {
2652
        return $this->LibStatut($this->statut, $mode);
2653
    }
2654
2655
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2656
    /**
2657
     *  Return status label for a status
2658
     *
2659
     *  @param  int     $status     Id status
2660
     *  @param  int     $mode       0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
2661
     *  @return string              Label
2662
     */
2663
    public function LibStatut($status, $mode = 0)
2664
    {
2665
		// phpcs:enable
2666
        if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
2667
            global $langs;
2668
            //$langs->load("mymodule");
2669
            $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2670
            $this->labelStatus[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2671
            $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting');
2672
            $this->labelStatusShort[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans');
2673
            if ($this->type == 'bank-transfer') {
2674
                $this->labelStatus[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2675
                $this->labelStatusShort[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited');
2676
            } else {
2677
                $this->labelStatus[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2678
                $this->labelStatusShort[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited');
2679
            }
2680
        }
2681
2682
        $statusType = 'status1';
2683
        if ($status == self::STATUS_TRANSFERED) {
2684
            $statusType = 'status3';
2685
        }
2686
        if ($status == self::STATUS_CREDITED || $status == self::STATUS_DEBITED) {
2687
            $statusType = 'status6';
2688
        }
2689
2690
        return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
2691
    }
2692
2693
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2694
    /**
2695
     *      Load indicators for dashboard (this->nbtodo and this->nbtodolate)
2696
     *
2697
     *      @param      User    $user           Object user
2698
     *      @param      string  $mode           Mode 'direct_debit' or 'credit_transfer'
2699
     *      @return     WorkboardResponse|int   Return integer <0 if KO, WorkboardResponse if OK
2700
     */
2701
    public function load_board($user, $mode)
2702
    {
2703
		// phpcs:enable
2704
        if ($user->socid) {
2705
            return -1; // protection pour eviter appel par utilisateur externe
2706
        }
2707
2708
        /*
2709
         if ($mode == 'direct_debit') {
2710
         $sql = "SELECT b.rowid, f.datedue as datefin";
2711
         $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
2712
         $sql .= " WHERE f.entity IN (".getEntity('facture').")";
2713
         $sql .= " AND f.total_ttc > 0";
2714
         } else {
2715
         $sql = "SELECT b.rowid, f.datedue as datefin";
2716
         $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f";
2717
         $sql .= " WHERE f.entity IN (".getEntity('facture_fourn').")";
2718
         $sql .= " AND f.total_ttc > 0";
2719
         }
2720
2721
         $resql = $this->db->query($sql);
2722
         if ($resql) {
2723
         $langs->load("banks");
2724
         $now = dol_now();
2725
2726
         $response = new WorkboardResponse();
2727
         if ($mode == 'direct_debit') {
2728
         $response->warning_delay = $conf->prelevement->warning_delay / 60 / 60 / 24;
2729
         $response->label = $langs->trans("PendingDirectDebitToComplete");
2730
         $response->labelShort = $langs->trans("PendingDirectDebitToCompleteShort");
2731
         $response->url = DOL_URL_ROOT.'/compta/prelevement/index.php?leftmenu=checks&mainmenu=bank';
2732
         } else {
2733
         $response->warning_delay = $conf->paymentbybanktransfer->warning_delay / 60 / 60 / 24;
2734
         $response->label = $langs->trans("PendingCreditTransferToComplete");
2735
         $response->labelShort = $langs->trans("PendingCreditTransferToCompleteShort");
2736
         $response->url = DOL_URL_ROOT.'/compta/paymentbybanktransfer/index.php?leftmenu=checks&mainmenu=bank';
2737
         }
2738
         $response->img = img_object('', "payment");
2739
2740
         while ($obj = $this->db->fetch_object($resql)) {
2741
         $response->nbtodo++;
2742
2743
         if ($this->db->jdate($obj->datefin) < ($now - $conf->withdraw->warning_delay)) {
2744
         $response->nbtodolate++;
2745
         }
2746
         }
2747
2748
         $response->nbtodo = 0;
2749
         $response->nbtodolate = 0;
2750
         // Return workboard only if quantity is not 0
2751
         if ($response->nbtodo) {
2752
         return $response;
2753
         } else {
2754
         return 0;
2755
         }
2756
         } else {
2757
         dol_print_error($this->db);
2758
         $this->error = $this->db->error();
2759
         return -1;
2760
         }
2761
         */
2762
        return 0;
2763
    }
2764
2765
    /**
2766
     *  Return clicable link of object (with eventually picto)
2767
     *
2768
     *  @param      string      $option                 Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
2769
     *  @param      array       $arraydata              Array of data
2770
     *  @return     string                              HTML Code for Kanban thumb.
2771
     */
2772
    public function getKanbanView($option = '', $arraydata = null)
2773
    {
2774
        global $langs;
2775
2776
        $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
2777
2778
        $return = '<div class="box-flex-item box-flex-grow-zero">';
2779
        $return .= '<div class="info-box info-box-sm">';
2780
        $return .= '<span class="info-box-icon bg-infobox-action">';
2781
        $return .= img_picto('', $this->picto);
2782
        $return .= '</span>';
2783
        $return .= '<div class="info-box-content">';
2784
        $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . (method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref) . '</span>';
2785
        if ($selected >= 0) {
2786
            $return .= '<input id="cb' . $this->id . '" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="' . $this->id . '"' . ($selected ? ' checked="checked"' : '') . '>';
2787
        }
2788
        if (property_exists($this, 'date_echeance')) {
2789
            $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>';
2790
        }
2791
        if (property_exists($this, 'total')) {
2792
            $return .= '<br><span class="opacitymedium">' . $langs->trans("Amount") . '</span> : <span class="amount">' . price($this->total) . '</span>';
2793
        }
2794
        if (method_exists($this, 'LibStatut')) {
2795
            $return .= '<br><div class="info-box-status">' . $this->getLibStatut(3) . '</div>';
2796
        }
2797
        $return .= '</div>';
2798
        $return .= '</div>';
2799
        $return .= '</div>';
2800
        return $return;
2801
    }
2802
2803
    /**
2804
     * Check if is bon prelevement for salary invoice
2805
     *
2806
     * @return  int     1 if OK, O if K0
2807
     */
2808
    public function checkIfSalaryBonPrelevement()
2809
    {
2810
        if (!empty($this->id)) {
2811
            $id = $this->id;
2812
        } else {
2813
            return 0;
2814
        }
2815
        if ($id) {
2816
            $sql = "SELECT COUNT(*) AS nb FROM " . MAIN_DB_PREFIX . "prelevement_lignes";
2817
            $sql .= " WHERE fk_prelevement_bons = " . ((int) $id);
2818
            $sql .= " AND fk_soc = 0";  // fk_soc can't be NULL
2819
            $sql .= " AND fk_user IS NOT NULL";
2820
2821
            $num = 0;
2822
            $resql = $this->db->query($sql);
2823
            if ($resql) {
2824
                $obj = $this->db->fetch_object($resql);
2825
                $num = $obj->nb;
2826
            }
2827
            if ($num > 0) {
2828
                return 1;
2829
            }
2830
        } else {
2831
            dol_print_error($this->db);
2832
        }
2833
2834
        return 0;
2835
    }
2836
}
2837