AccountingAccount::getNomUrl()   F
last analyzed

Complexity

Conditions 32
Paths > 20000

Size

Total Lines 97
Code Lines 66

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 32
eloc 66
nc 491520
nop 8
dl 0
loc 97
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* Copyright (C) 2013-2014  Olivier Geffroy             <[email protected]>
4
 * Copyright (C) 2013-2024  Alexandre Spangaro          <[email protected]>
5
 * Copyright (C) 2013-2021  Florian Henry               <[email protected]>
6
 * Copyright (C) 2014       Juanjo Menent               <[email protected]>
7
 * Copyright (C) 2015       Ari Elbaz (elarifr)         <[email protected]>
8
 * Copyright (C) 2018-2024  Frédéric France             <[email protected]>
9
 * Copyright (C) 2024		MDW							<[email protected]>
10
 * Copyright (C) 2024       Rafael San José             <[email protected]>
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 3 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
24
 */
25
26
namespace Dolibarr\Code\Accountancy\Classes;
27
28
use Dolibarr\Code\Societe\Classes\Societe;
29
use Dolibarr\Core\Base\CommonObject;
30
31
/**
32
 *  \file       htdocs/accountancy/class/accountingaccount.class.php
33
 *  \ingroup    Accountancy (Double entries)
34
 *  \brief      File of class to manage accounting accounts
35
 */
36
37
/**
38
 * Class to manage accounting accounts
39
 */
40
class AccountingAccount extends CommonObject
41
{
42
    /**
43
     * @var string Name of element
44
     */
45
    public $element = 'accounting_account';
46
47
    /**
48
     * @var string Name of table without prefix where object is stored
49
     */
50
    public $table_element = 'accounting_account';
51
52
    /**
53
     * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
54
     */
55
    public $picto = 'billr';
56
57
    /**
58
     * 0=Default, 1=View may be restricted to sales representative only if no permission to see all or to company of external user if external user
59
     * @var integer
60
     */
61
    public $restrictiononfksoc = 1;
62
63
    /**
64
     * @var DoliDB Database handler.
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Accountancy\Classes\DoliDB was not found. Did you mean DoliDB? If so, make sure to prefix the type with \.
Loading history...
65
     */
66
    public $db;
67
68
    /**
69
     * @var int ID
70
     */
71
    public $id;
72
73
    /**
74
     * @var int ID
75
     */
76
    public $rowid;
77
78
    /**
79
     * Date creation record (datec)
80
     *
81
     * @var integer
82
     */
83
    public $datec;
84
85
    /**
86
     * @var string pcg version
87
     */
88
    public $fk_pcg_version;
89
90
    /**
91
     * @var string pcg type
92
     */
93
    public $pcg_type;
94
95
    /**
96
     * @var string account number
97
     */
98
    public $account_number;
99
100
    /**
101
     * @var int ID parent account
102
     */
103
    public $account_parent;
104
105
    /**
106
     * @var int ID category account
107
     */
108
    public $account_category;
109
110
    /**
111
     * @var int Label category account
112
     */
113
    public $account_category_label;
114
115
    /**
116
     * @var int Status
117
     */
118
    public $status;
119
120
    /**
121
     * @var string Label of account
122
     */
123
    public $label;
124
125
    /**
126
     * @var string Label short of account
127
     */
128
    public $labelshort;
129
130
    /**
131
     * @var int ID
132
     */
133
    public $fk_user_author;
134
135
    /**
136
     * @var int ID
137
     */
138
    public $fk_user_modif;
139
140
    /**
141
     * @var int active (duplicate with status)
142
     */
143
    public $active;
144
145
    /**
146
     * @var int reconcilable
147
     */
148
    public $reconcilable;
149
150
    /**
151
     * @var array cache array
152
     */
153
    private $accountingaccount_codetotid_cache = array();
154
155
156
    const STATUS_ENABLED = 1;
157
    const STATUS_DISABLED = 0;
158
159
160
    /**
161
     * Constructor
162
     *
163
     * @param DoliDB $db Database handle
164
     */
165
    public function __construct($db)
166
    {
167
        $this->db = $db;
168
169
        $this->ismultientitymanaged = 1;
170
        $this->next_prev_filter = "fk_pcg_version IN (SELECT pcg_version FROM " . MAIN_DB_PREFIX . "accounting_system WHERE rowid = " . ((int) getDolGlobalInt('CHARTOFACCOUNTS')) . ")"; // Used to add a filter in Form::showrefnav method
171
    }
172
173
    /**
174
     * Load record in memory
175
     *
176
     * @param   int             $rowid                      Id
177
     * @param   string|null     $account_number             Account number
178
     * @param   int|boolean     $limittocurrentchart        1 or true=Load record only if it is into current active chart of account
179
     * @param   string          $limittoachartaccount       'ABC'=Load record only if it is into chart account with code 'ABC' (better and faster than previous parameter if you have chart of account code).
180
     * @return  int                                         Return integer <0 if KO, 0 if not found, Id of record if OK and found
181
     */
182
    public function fetch($rowid = 0, $account_number = null, $limittocurrentchart = 0, $limittoachartaccount = '')
183
    {
184
        global $conf;
185
186
        if ($rowid || $account_number) {
187
            $sql  = "SELECT a.rowid as rowid, a.datec, a.tms, a.fk_pcg_version, a.pcg_type, a.account_number, a.account_parent, a.label, a.labelshort, a.fk_accounting_category, a.fk_user_author, a.fk_user_modif, a.active, a.reconcilable";
188
            $sql .= ", ca.label as category_label";
189
            $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as a";
190
            $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_accounting_category as ca ON a.fk_accounting_category = ca.rowid";
191
            $sql .= " WHERE";
192
            if ($rowid) {
193
                $sql .= " a.rowid = " . (int) $rowid;
194
            } elseif ($account_number) {
195
                $sql .= " a.account_number = '" . $this->db->escape($account_number) . "'";
196
                $sql .= " AND a.entity = " . $conf->entity;
197
            }
198
            if (!empty($limittocurrentchart)) {
199
                $sql .= ' AND a.fk_pcg_version IN (SELECT pcg_version FROM ' . MAIN_DB_PREFIX . 'accounting_system WHERE rowid = ' . ((int) getDolGlobalInt('CHARTOFACCOUNTS')) . ')';
200
            }
201
            if (!empty($limittoachartaccount)) {
202
                $sql .= " AND a.fk_pcg_version = '" . $this->db->escape($limittoachartaccount) . "'";
203
            }
204
205
            dol_syslog(get_only_class($this) . "::fetch rowid=" . $rowid . " account_number=" . $account_number, LOG_DEBUG);
206
207
            $result = $this->db->query($sql);
208
            if ($result) {
209
                $obj = $this->db->fetch_object($result);
210
211
                if ($obj) {
212
                    $this->id = $obj->rowid;
213
                    $this->rowid = $obj->rowid;
214
                    $this->ref = $obj->account_number;
215
                    $this->datec = $this->db->jdate($obj->datec);
216
                    $this->date_creation = $this->db->jdate($obj->datec);
217
                    $this->date_modification = $this->db->jdate($obj->tms);
218
                    //$this->tms = $this->datem;
219
                    $this->fk_pcg_version = $obj->fk_pcg_version;
220
                    $this->pcg_type = $obj->pcg_type;
221
                    $this->account_number = $obj->account_number;
222
                    $this->account_parent = $obj->account_parent;
223
                    $this->label = $obj->label;
224
                    $this->labelshort = $obj->labelshort;
225
                    $this->account_category = $obj->fk_accounting_category;
226
                    $this->account_category_label = $obj->category_label;
227
                    $this->fk_user_author = $obj->fk_user_author;
228
                    $this->fk_user_modif = $obj->fk_user_modif;
229
                    $this->active = $obj->active;
230
                    $this->status = $obj->active;
231
                    $this->reconcilable = $obj->reconcilable;
232
233
                    return $this->id;
234
                } else {
235
                    return 0;
236
                }
237
            } else {
238
                $this->error = "Error " . $this->db->lasterror();
239
                $this->errors[] = "Error " . $this->db->lasterror();
240
            }
241
        }
242
        return -1;
243
    }
244
245
    /**
246
     * Insert new accounting account in chart of accounts
247
     *
248
     * @param User $user User making action
249
     * @param int $notrigger Disable triggers
250
     * @return int                 Return integer <0 if KO, >0 if OK
251
     */
252
    public function create($user, $notrigger = 0)
253
    {
254
        global $conf;
255
        $error = 0;
256
        $now = dol_now();
257
258
        // Clean parameters
259
        if (isset($this->fk_pcg_version)) {
260
            $this->fk_pcg_version = trim($this->fk_pcg_version);
261
        }
262
        if (isset($this->pcg_type)) {
263
            $this->pcg_type = trim($this->pcg_type);
264
        }
265
        if (isset($this->account_number)) {
266
            $this->account_number = trim($this->account_number);
267
        }
268
        if (isset($this->label)) {
269
            $this->label = trim($this->label);
270
        }
271
        if (isset($this->labelshort)) {
272
            $this->labelshort = trim($this->labelshort);
273
        }
274
275
        if (empty($this->pcg_type) || $this->pcg_type == '-1') {
276
            $this->pcg_type = 'XXXXXX';
277
        }
278
        // Check parameters
279
        // Put here code to add control on parameters values
280
281
        // Insert request
282
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "accounting_account(";
283
        $sql .= "datec";
284
        $sql .= ", entity";
285
        $sql .= ", fk_pcg_version";
286
        $sql .= ", pcg_type";
287
        $sql .= ", account_number";
288
        $sql .= ", account_parent";
289
        $sql .= ", label";
290
        $sql .= ", labelshort";
291
        $sql .= ", fk_accounting_category";
292
        $sql .= ", fk_user_author";
293
        $sql .= ", active";
294
        $sql .= ", reconcilable";
295
        $sql .= ") VALUES (";
296
        $sql .= " '" . $this->db->idate($now) . "'";
297
        $sql .= ", " . ((int) $conf->entity);
298
        $sql .= ", " . (empty($this->fk_pcg_version) ? 'NULL' : "'" . $this->db->escape($this->fk_pcg_version) . "'");
299
        $sql .= ", " . (empty($this->pcg_type) ? 'NULL' : "'" . $this->db->escape($this->pcg_type) . "'");
300
        $sql .= ", " . (empty($this->account_number) ? 'NULL' : "'" . $this->db->escape($this->account_number) . "'");
301
        $sql .= ", " . (empty($this->account_parent) ? 0 : (int) $this->account_parent);
302
        $sql .= ", " . (empty($this->label) ? "''" : "'" . $this->db->escape($this->label) . "'");
303
        $sql .= ", " . (empty($this->labelshort) ? "''" : "'" . $this->db->escape($this->labelshort) . "'");
304
        $sql .= ", " . (empty($this->account_category) ? 0 : (int) $this->account_category);
305
        $sql .= ", " . ((int) $user->id);
306
        $sql .= ", " . (int) $this->active;
307
        $sql .= ", " . (int) $this->reconcilable;
308
        $sql .= ")";
309
310
        $this->db->begin();
311
312
        dol_syslog(get_only_class($this) . "::create", LOG_DEBUG);
313
        $resql = $this->db->query($sql);
314
        if (!$resql) {
315
            $error++;
316
            $this->errors[] = "Error " . $this->db->lasterror();
317
        }
318
319
        if (!$error) {
320
            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . "accounting_account");
321
322
            // Uncomment this and change MYOBJECT to your own tag if you
323
            // want this action to call a trigger.
324
            //if (! $error && ! $notrigger) {
325
326
            // // Call triggers
327
            // $result=$this->call_trigger('MYOBJECT_CREATE',$user);
328
            // if ($result < 0) $error++;
329
            // // End call triggers
330
            //}
331
        }
332
333
        // Commit or rollback
334
        if ($error) {
335
            foreach ($this->errors as $errmsg) {
336
                dol_syslog(get_only_class($this) . "::create " . $errmsg, LOG_ERR);
337
                $this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
338
            }
339
            $this->db->rollback();
340
            return -1 * $error;
341
        } else {
342
            $this->db->commit();
343
            return $this->id;
344
        }
345
    }
346
347
    /**
348
     * Update record
349
     *
350
     * @param User $user        User making update
351
     * @return int              Return integer <0 if KO (-2 = duplicate), >0 if OK
352
     */
353
    public function update($user)
354
    {
355
        // Check parameters
356
        if (empty($this->pcg_type) || $this->pcg_type == '-1') {
357
            $this->pcg_type = 'XXXXXX';
358
        }
359
360
        $this->db->begin();
361
362
        $sql = "UPDATE " . MAIN_DB_PREFIX . "accounting_account ";
363
        $sql .= " SET fk_pcg_version = " . ($this->fk_pcg_version ? "'" . $this->db->escape($this->fk_pcg_version) . "'" : "null");
364
        $sql .= " , pcg_type = " . ($this->pcg_type ? "'" . $this->db->escape($this->pcg_type) . "'" : "null");
365
        $sql .= " , account_number = '" . $this->db->escape($this->account_number) . "'";
366
        $sql .= " , account_parent = " . (int) $this->account_parent;
367
        $sql .= " , label = " . ($this->label ? "'" . $this->db->escape($this->label) . "'" : "''");
368
        $sql .= " , labelshort = " . ($this->labelshort ? "'" . $this->db->escape($this->labelshort) . "'" : "''");
369
        $sql .= " , fk_accounting_category = " . (empty($this->account_category) ? 0 : (int) $this->account_category);
370
        $sql .= " , fk_user_modif = " . ((int) $user->id);
371
        $sql .= " , active = " . (int) $this->active;
372
        $sql .= " , reconcilable = " . (int) $this->reconcilable;
373
        $sql .= " WHERE rowid = " . ((int) $this->id);
374
375
        dol_syslog(get_only_class($this) . "::update", LOG_DEBUG);
376
        $result = $this->db->query($sql);
377
        if ($result) {
378
            $this->db->commit();
379
            return 1;
380
        } else {
381
            if ($this->db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
382
                $this->error = $this->db->lasterror();
383
                $this->db->rollback();
384
                return -2;
385
            }
386
387
            $this->error = $this->db->lasterror();
388
            $this->db->rollback();
389
            return -1;
390
        }
391
    }
392
393
    /**
394
     * Check usage of accounting code
395
     *
396
     * @return int Return integer <0 if KO, >0 if OK
397
     */
398
    public function checkUsage()
399
    {
400
        global $langs;
401
402
        // TODO Looks a stupid check
403
        $sql = "(SELECT fk_code_ventilation FROM " . MAIN_DB_PREFIX . "facturedet";
404
        $sql .= " WHERE fk_code_ventilation=" . ((int) $this->id) . ")";
405
        $sql .= "UNION";
406
        $sql .= " (SELECT fk_code_ventilation FROM " . MAIN_DB_PREFIX . "facture_fourn_det";
407
        $sql .= " WHERE fk_code_ventilation=" . ((int) $this->id) . ")";
408
409
        dol_syslog(get_only_class($this) . "::checkUsage", LOG_DEBUG);
410
        $resql = $this->db->query($sql);
411
412
        if ($resql) {
413
            $num = $this->db->num_rows($resql);
414
            if ($num > 0) {
415
                $this->error = $langs->trans('ErrorAccountancyCodeIsAlreadyUse');
416
                return 0;
417
            } else {
418
                return 1;
419
            }
420
        } else {
421
            $this->error = $this->db->lasterror();
422
            return -1;
423
        }
424
    }
425
426
    /**
427
     * Delete object in database
428
     *
429
     * @param User $user User that deletes
430
     * @param int $notrigger 0=triggers after, 1=disable triggers
431
     * @return int Return integer <0 if KO, >0 if OK
432
     */
433
    public function delete($user, $notrigger = 0)
434
    {
435
        $error = 0;
436
437
        $result = $this->checkUsage();
438
439
        if ($result > 0) {
440
            $this->db->begin();
441
442
            if (!$error) {
443
                $sql = "DELETE FROM " . MAIN_DB_PREFIX . "accounting_account";
444
                $sql .= " WHERE rowid=" . ((int) $this->id);
445
446
                dol_syslog(get_only_class($this) . "::delete sql=" . $sql);
447
                $resql = $this->db->query($sql);
448
                if (!$resql) {
449
                    $error++;
450
                    $this->errors[] = "Error " . $this->db->lasterror();
451
                }
452
            }
453
454
            // Commit or rollback
455
            if ($error) {
456
                foreach ($this->errors as $errmsg) {
457
                    dol_syslog(get_only_class($this) . "::delete " . $errmsg, LOG_ERR);
458
                    $this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
459
                }
460
                $this->db->rollback();
461
                return -1 * $error;
462
            } else {
463
                $this->db->commit();
464
                return 1;
465
            }
466
        } else {
467
            return -1;
468
        }
469
    }
470
471
    /**
472
     * Return clicable name (with picto eventually)
473
     *
474
     * @param int $withpicto 0=No picto, 1=Include picto into link, 2=Only picto
475
     * @param int $withlabel 0=No label, 1=Include label of account
476
     * @param int $nourl 1=Disable url
477
     * @param string $moretitle Add more text to title tooltip
478
     * @param int $notooltip 1=Disable tooltip
479
     * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
480
     * @param int $withcompletelabel 0=Short label (field short label), 1=Complete label (field label)
481
     * @param string $option 'ledger', 'journals', 'accountcard'
482
     * @return  string    String with URL
483
     */
484
    public function getNomUrl($withpicto = 0, $withlabel = 0, $nourl = 0, $moretitle = '', $notooltip = 0, $save_lastsearch_value = -1, $withcompletelabel = 0, $option = '')
485
    {
486
        global $langs, $conf, $hookmanager;
487
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/accounting.lib.php';
488
489
        if (!empty($conf->dol_no_mouse_hover)) {
490
            $notooltip = 1; // Force disable tooltips
491
        }
492
493
        $result = '';
494
495
        $url = '';
496
        $labelurl = '';
497
        if (empty($option) || $option == 'ledger') {
498
            $url = constant('BASE_URL') . '/accountancy/bookkeeping/listbyaccount.php?search_accountancy_code_start=' . urlencode((isset($this->account_number) ? $this->account_number : '')) . '&search_accountancy_code_end=' . urlencode((isset($this->account_number) ? $this->account_number : ''));
499
            $labelurl = $langs->trans("ShowAccountingAccountInLedger");
500
        } elseif ($option == 'journals') {
501
            $url = constant('BASE_URL') . '/accountancy/bookkeeping/list.php?search_accountancy_code_start=' . urlencode($this->account_number) . '&search_accountancy_code_end=' . urlencode($this->account_number);
502
            $labelurl = $langs->trans("ShowAccountingAccountInJournals");
503
        } elseif ($option == 'accountcard') {
504
            $url = constant('BASE_URL') . '/accountancy/admin/card.php?id=' . urlencode((string) ($this->id));
505
            $labelurl = $langs->trans("ShowAccountingAccount");
506
        }
507
508
        // Add param to save lastsearch_values or not
509
        $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
510
        if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
511
            $add_save_lastsearch_values = 1;
512
        }
513
        if ($add_save_lastsearch_values) {
514
            $url .= '&save_lastsearch_values=1';
515
        }
516
517
        $picto = 'accounting_account';
518
        $label = '';
519
520
        if (empty($this->labelshort) || $withcompletelabel == 1) {
521
            $labeltoshow = $this->label;
522
        } else {
523
            $labeltoshow = $this->labelshort;
524
        }
525
526
        $label = '<u>' . $labelurl . '</u>';
527
        if (!empty($this->account_number)) {
528
            $label .= '<br><b>' . $langs->trans('AccountAccounting') . ':</b> ' . length_accountg($this->account_number);
529
        }
530
        if (!empty($labeltoshow)) {
531
            $label .= '<br><b>' . $langs->trans('Label') . ':</b> ' . $labeltoshow;
532
        }
533
        if ($moretitle) {
534
            $label .= ' - ' . $moretitle;
535
        }
536
537
        $linkclose = '';
538
        if (empty($notooltip)) {
539
            if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
540
                $label = $labelurl;
541
                $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
542
            }
543
            $linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"';
544
            $linkclose .= ' class="classfortooltip"';
545
        }
546
547
        $linkstart = '<a href="' . $url . '"';
548
        $linkstart .= $linkclose . '>';
549
        $linkend = '</a>';
550
551
        if ($nourl) {
552
            $linkstart = '';
553
            $linkclose = '';
554
            $linkend = '';
555
        }
556
557
        $label_link = length_accountg($this->account_number);
558
        if ($withlabel) {
559
            $label_link .= ' - ' . ($nourl ? '<span class="opacitymedium">' : '') . $labeltoshow . ($nourl ? '</span>' : '');
560
        }
561
562
        if ($withpicto) {
563
            $result .= ($linkstart . img_object(($notooltip ? '' : $label), $picto, ($notooltip ? '' : 'class="classfortooltip"'), 0, 0, $notooltip ? 0 : 1) . $linkend);
564
        }
565
        if ($withpicto && $withpicto != 2) {
566
            $result .= ' ';
567
        }
568
        if ($withpicto != 2) {
569
            $result .= $linkstart . $label_link . $linkend;
570
        }
571
        global $action;
572
        $hookmanager->initHooks(array($this->element . 'dao'));
573
        $parameters = array('id' => $this->id, 'getnomurl' => &$result);
574
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
575
        if ($reshook > 0) {
576
            $result = $hookmanager->resPrint;
577
        } else {
578
            $result .= $hookmanager->resPrint;
579
        }
580
        return $result;
581
    }
582
583
    /**
584
     * Information on record
585
     *
586
     * @param int   $id     ID of record
587
     * @return void
588
     */
589
    public function info($id)
590
    {
591
        $sql = 'SELECT a.rowid, a.datec, a.fk_user_author, a.fk_user_modif, a.tms as date_modification';
592
        $sql .= ' FROM ' . MAIN_DB_PREFIX . 'accounting_account as a';
593
        $sql .= ' WHERE a.rowid = ' . ((int) $id);
594
595
        dol_syslog(get_only_class($this) . '::info sql=' . $sql);
596
        $resql = $this->db->query($sql);
597
598
        if ($resql) {
599
            if ($this->db->num_rows($resql)) {
600
                $obj = $this->db->fetch_object($resql);
601
602
                $this->id = $obj->rowid;
603
604
                $this->user_creation_id = $obj->fk_user_author;
605
                $this->user_modification_id = $obj->fk_user_modif;
606
                $this->date_creation = $this->db->jdate($obj->datec);
607
                $this->date_modification = $this->db->jdate($obj->date_modification);
608
            }
609
            $this->db->free($resql);
610
        } else {
611
            dol_print_error($this->db);
612
        }
613
    }
614
615
    /**
616
     * Deactivate an account (for status active or status reconcilable)
617
     *
618
     * @param int $id Id
619
     * @param int $mode 0=field active, 1=field reconcilable
620
     * @return int              Return integer <0 if KO, >0 if OK
621
     */
622
    public function accountDeactivate($id, $mode = 0)
623
    {
624
        $result = $this->checkUsage();
625
626
        $fieldtouse = 'active';
627
        if ($mode == 1) {
628
            $fieldtouse = 'reconcilable';
629
        }
630
631
        if ($result > 0) {
632
            $this->db->begin();
633
634
            $sql = "UPDATE " . MAIN_DB_PREFIX . "accounting_account ";
635
            $sql .= "SET " . $this->db->sanitize($fieldtouse) . " = 0";
636
            $sql .= " WHERE rowid = " . ((int) $id);
637
638
            dol_syslog(get_only_class($this) . "::accountDeactivate " . $fieldtouse, LOG_DEBUG);
639
            $result = $this->db->query($sql);
640
641
            if ($result) {
642
                $this->db->commit();
643
                return 1;
644
            } else {
645
                $this->error = $this->db->lasterror();
646
                $this->db->rollback();
647
                return -1;
648
            }
649
        } else {
650
            return -1;
651
        }
652
    }
653
654
655
    /**
656
     * Account activated
657
     *
658
     * @param int $id Id
659
     * @param int $mode 0=field active, 1=field reconcilable
660
     * @return int              Return integer <0 if KO, >0 if OK
661
     */
662
    public function accountActivate($id, $mode = 0)
663
    {
664
        // phpcs:enable
665
        $this->db->begin();
666
667
        $fieldtouse = 'active';
668
        if ($mode == 1) {
669
            $fieldtouse = 'reconcilable';
670
        }
671
672
        $sql = "UPDATE " . MAIN_DB_PREFIX . "accounting_account";
673
        $sql .= " SET " . $this->db->sanitize($fieldtouse) . " = 1";
674
        $sql .= " WHERE rowid = " . ((int) $id);
675
676
        dol_syslog(get_only_class($this) . "::account_activate " . $fieldtouse, LOG_DEBUG);
677
        $result = $this->db->query($sql);
678
        if ($result) {
679
            $this->db->commit();
680
            return 1;
681
        } else {
682
            $this->error = $this->db->lasterror();
683
            $this->db->rollback();
684
            return -1;
685
        }
686
    }
687
688
    /**
689
     *  Return the label of the status
690
     *
691
     *  @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
692
     *  @return string                 Label of status
693
     */
694
    public function getLibStatut($mode = 0)
695
    {
696
        return $this->LibStatut($this->status, $mode);
697
    }
698
699
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
700
    /**
701
     *  Return the label of a given status
702
     *
703
     *  @param  int     $status        Id status
704
     *  @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
705
     *  @return string                 Label of status
706
     */
707
    public function LibStatut($status, $mode = 0)
708
    {
709
		// phpcs:enable
710
        if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
711
            global $langs;
712
            $langs->load("users");
713
            $this->labelStatus[self::STATUS_ENABLED] = $langs->transnoentitiesnoconv('Enabled');
714
            $this->labelStatus[self::STATUS_DISABLED] = $langs->transnoentitiesnoconv('Disabled');
715
            $this->labelStatusShort[self::STATUS_ENABLED] = $langs->transnoentitiesnoconv('Enabled');
716
            $this->labelStatusShort[self::STATUS_DISABLED] = $langs->transnoentitiesnoconv('Disabled');
717
        }
718
719
        $statusType = 'status4';
720
        if ($status == self::STATUS_DISABLED) {
721
            $statusType = 'status5';
722
        }
723
724
        return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
725
    }
726
727
    /**
728
     * Return a suggested account (from chart of accounts) to bind
729
     *
730
     * @param   Societe                             $buyer              Object buyer
731
     * @param   Societe                             $seller             Object seller
732
     * @param   Product                             $product            Product object sell or buy
733
     * @param   Facture|FactureFournisseur          $facture            Facture
734
     * @param   FactureLigne|SupplierInvoiceLine    $factureDet         Facture Det
735
     * @param   array                               $accountingAccount  Array of Accounting account
736
     * @param   string                              $type               Customer / Supplier
737
     * @return  array|int                                               Array of accounting accounts suggested or < 0 if technical error.
738
     *                                                                  'suggestedaccountingaccountbydefaultfor'=>Will be used for the label to show on tooltip for account by default on any product
739
     *                                                                  'suggestedaccountingaccountfor'=>Is the account suggested for this product
740
     */
741
    public function getAccountingCodeToBind(Societe $buyer, Societe $seller, Product $product, $facture, $factureDet, $accountingAccount = array(), $type = '')
742
    {
743
        global $hookmanager;
744
        // Instantiate hooks for external modules
745
        $hookmanager->initHooks(array('accountancyBindingCalculation'));
746
747
        // Execute hook accountancyBindingCalculation
748
        $parameters = array('buyer' => $buyer, 'seller' => $seller, 'product' => $product, 'facture' => $facture, 'factureDet' => $factureDet ,'accountingAccount' => $accountingAccount, 0 => $type);
749
        $reshook = $hookmanager->executeHooks('accountancyBindingCalculation', $parameters); // Note that $action and $object may have been modified by some hooks
750
751
        if (empty($reshook)) {
752
            $const_name = '';
753
            if ($type == 'customer') {
754
                $const_name = "SOLD";
755
            } elseif ($type == 'supplier') {
756
                $const_name = "BUY";
757
            }
758
759
            require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/company.lib.php';
760
            $isBuyerInEEC = isInEEC($buyer);
761
            $isSellerInEEC = isInEEC($seller);
762
            $code_l = '';   // Default value for generic product/service
763
            $code_p = '';   // Value for the product/service in parameter ($product)
764
            $code_t = '';   // Default value of product account for the thirdparty
765
            $suggestedid = '';
766
767
            // Level 1 (define $code_l): Search suggested default account for product/service
768
            $suggestedaccountingaccountbydefaultfor = '';
769
            if ($factureDet->product_type == 1) {
770
                if ($buyer->country_code == $seller->country_code || empty($buyer->country_code)) {  // If buyer in same country than seller (if not defined, we assume it is same country)
771
                    $code_l = getDolGlobalString('ACCOUNTING_SERVICE_' . $const_name . '_ACCOUNT');
772
                    $suggestedaccountingaccountbydefaultfor = '';
773
                } else {
774
                    if ($isSellerInEEC && $isBuyerInEEC && $factureDet->tva_tx != 0) {    // European intravat sale, but with a VAT
775
                        $code_l = getDolGlobalString('ACCOUNTING_SERVICE_' . $const_name . '_ACCOUNT');
776
                    } elseif ($isSellerInEEC && $isBuyerInEEC && empty($buyer->tva_intra)) {    // European intravat sale, without VAT intra community number
777
                        $code_l = getDolGlobalString('ACCOUNTING_SERVICE_' . $const_name . '_ACCOUNT');
778
                        $suggestedaccountingaccountbydefaultfor = 'eecwithoutvatnumber';
779
                    } elseif ($isSellerInEEC && $isBuyerInEEC) {    // European intravat sale
780
                        $code_l = getDolGlobalString('ACCOUNTING_SERVICE_' . $const_name . '_INTRA_ACCOUNT');
781
                        $suggestedaccountingaccountbydefaultfor = 'eec';
782
                    } else {                                        // Foreign sale
783
                        $code_l = getDolGlobalString('ACCOUNTING_SERVICE_' . $const_name . '_EXPORT_ACCOUNT');
784
                        $suggestedaccountingaccountbydefaultfor = 'export';
785
                    }
786
                }
787
            } elseif ($factureDet->product_type == 0) {
788
                if ($buyer->country_code == $seller->country_code || empty($buyer->country_code)) {  // If buyer in same country than seller (if not defined, we assume it is same country)
789
                    $code_l = getDolGlobalString('ACCOUNTING_PRODUCT_' . $const_name . '_ACCOUNT');
790
                    $suggestedaccountingaccountbydefaultfor = '';
791
                } else {
792
                    if ($isSellerInEEC && $isBuyerInEEC && $factureDet->tva_tx != 0) {    // European intravat sale, but with a VAT
793
                        $code_l = getDolGlobalString('ACCOUNTING_PRODUCT_' . $const_name . '_ACCOUNT');
794
                        $suggestedaccountingaccountbydefaultfor = 'eecwithvat';
795
                    } elseif ($isSellerInEEC && $isBuyerInEEC && empty($buyer->tva_intra)) {    // European intravat sale, without VAT intra community number
796
                        $code_l = getDolGlobalString('ACCOUNTING_PRODUCT_' . $const_name . '_ACCOUNT');
797
                        $suggestedaccountingaccountbydefaultfor = 'eecwithoutvatnumber';
798
                    } elseif ($isSellerInEEC && $isBuyerInEEC) {    // European intravat sale
799
                        $code_l = getDolGlobalString('ACCOUNTING_PRODUCT_' . $const_name . '_INTRA_ACCOUNT');
800
                        $suggestedaccountingaccountbydefaultfor = 'eec';
801
                    } else {
802
                        $code_l = getDolGlobalString('ACCOUNTING_PRODUCT_' . $const_name . '_EXPORT_ACCOUNT');
803
                        $suggestedaccountingaccountbydefaultfor = 'export';
804
                    }
805
                }
806
            }
807
            if ($code_l == -1) {
808
                $code_l = '';
809
            }
810
811
            // Level 2 (define $code_p): Search suggested account for product/service (similar code exists in page index.php to make automatic binding)
812
            $suggestedaccountingaccountfor = '';
813
            if ((($buyer->country_code == $seller->country_code) || empty($buyer->country_code))) {
814
                // If buyer in same country than seller (if not defined, we assume it is same country)
815
                if ($type == 'customer' && !empty($product->accountancy_code_sell)) {
816
                    $code_p = $product->accountancy_code_sell;
817
                } elseif ($type == 'supplier' && !empty($product->accountancy_code_buy)) {
818
                    $code_p = $product->accountancy_code_buy;
819
                }
820
                $suggestedid = $accountingAccount['dom'];
821
                $suggestedaccountingaccountfor = 'prodserv';
822
            } else {
823
                if ($isSellerInEEC && $isBuyerInEEC && $factureDet->tva_tx != 0) {
824
                    // European intravat sale, but with VAT
825
                    if ($type == 'customer' && !empty($product->accountancy_code_sell)) {
826
                        $code_p = $product->accountancy_code_sell;
827
                    } elseif ($type == 'supplier' && !empty($product->accountancy_code_buy)) {
828
                        $code_p = $product->accountancy_code_buy;
829
                    }
830
                    $suggestedid = $accountingAccount['dom'];
831
                    $suggestedaccountingaccountfor = 'eecwithvat';
832
                } elseif ($isSellerInEEC && $isBuyerInEEC && empty($buyer->tva_intra)) {
833
                    // European intravat sale, without VAT intra community number
834
                    if ($type == 'customer' && !empty($product->accountancy_code_sell)) {
835
                        $code_p = $product->accountancy_code_sell;
836
                    } elseif ($type == 'supplier' && !empty($product->accountancy_code_buy)) {
837
                        $code_p = $product->accountancy_code_buy;
838
                    }
839
                    $suggestedid = $accountingAccount['dom']; // There is a doubt for this case. Is it an error on vat or we just forgot to fill vat number ?
840
                    $suggestedaccountingaccountfor = 'eecwithoutvatnumber';
841
                } elseif ($isSellerInEEC && $isBuyerInEEC && (($type == 'customer' && !empty($product->accountancy_code_sell_intra)) || ($type == 'supplier' && !empty($product->accountancy_code_buy_intra)))) {
842
                    // European intravat sale
843
                    if ($type == 'customer' && !empty($product->accountancy_code_sell_intra)) {
844
                        $code_p = $product->accountancy_code_sell_intra;
845
                    } elseif ($type == 'supplier' && !empty($product->accountancy_code_buy_intra)) {
846
                        $code_p = $product->accountancy_code_buy_intra;
847
                    }
848
                    $suggestedid = $accountingAccount['intra'];
849
                    $suggestedaccountingaccountfor = 'eec';
850
                } else {
851
                    // Foreign sale
852
                    if ($type == 'customer' && !empty($product->accountancy_code_sell_export)) {
853
                        $code_p = $product->accountancy_code_sell_export;
854
                    } elseif ($type == 'supplier' && !empty($product->accountancy_code_buy_export)) {
855
                        $code_p = $product->accountancy_code_buy_export;
856
                    }
857
                    $suggestedid = $accountingAccount['export'];
858
                    $suggestedaccountingaccountfor = 'export';
859
                }
860
            }
861
862
            // Level 3 (define $code_t): Search suggested account for this thirdparty (similar code exists in page index.php to make automatic binding)
863
            if (getDolGlobalString('ACCOUNTANCY_USE_PRODUCT_ACCOUNT_ON_THIRDPARTY')) {
864
                if ($type == 'customer' && !empty($buyer->code_compta_product)) {
865
                    $code_t = $buyer->code_compta_product;
866
                    $suggestedid = $accountingAccount['thirdparty'];
867
                    $suggestedaccountingaccountfor = 'thirdparty';
868
                } elseif ($type == 'supplier' && !empty($seller->code_compta_product)) {
869
                    $code_t = $seller->code_compta_product;
870
                    $suggestedid = $accountingAccount['thirdparty'];
871
                    $suggestedaccountingaccountfor = 'thirdparty';
872
                }
873
            }
874
875
            // Manage Deposit
876
            if (getDolGlobalString('ACCOUNTING_ACCOUNT_' . strtoupper($type) . '_DEPOSIT')) {
877
                if ($factureDet->desc == "(DEPOSIT)" || $facture->type == $facture::TYPE_DEPOSIT) {
878
                    $accountdeposittoventilated = new self($this->db);
879
                    if ($type == 'customer') {
880
                        $result = $accountdeposittoventilated->fetch(0, getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT'), 1);
881
                    } elseif ($type == 'supplier') {
882
                        $result = $accountdeposittoventilated->fetch(0, getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER_DEPOSIT'), 1);
883
                    }
884
                    if (isset($result) && $result < 0) {
885
                        return -1;
886
                    }
887
888
                    $code_l = $accountdeposittoventilated->ref;
889
                    $code_p = '';
890
                    $code_t = '';
891
                    $suggestedid = $accountdeposittoventilated->rowid;
892
                    $suggestedaccountingaccountfor = 'deposit';
893
                }
894
895
                // For credit note invoice, if origin invoice is a deposit invoice, force also on specific customer/supplier deposit account
896
                if (!empty($facture->fk_facture_source)) {
897
                    $invoiceSource = new $facture($this->db);
898
                    $invoiceSource->fetch($facture->fk_facture_source);
899
900
                    if ($facture->type == $facture::TYPE_CREDIT_NOTE && $invoiceSource->type == $facture::TYPE_DEPOSIT) {
901
                        $accountdeposittoventilated = new self($this->db);
902
                        if ($type == 'customer') {
903
                            $accountdeposittoventilated->fetch(0, getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT'), 1);
904
                        } elseif ($type == 'supplier') {
905
                            $accountdeposittoventilated->fetch(0, getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER_DEPOSIT'), 1);
906
                        }
907
                        $code_l = $accountdeposittoventilated->ref;
908
                        $code_p = '';
909
                        $code_t = '';
910
                        $suggestedid = $accountdeposittoventilated->rowid;
911
                        $suggestedaccountingaccountfor = 'deposit';
912
                    }
913
                }
914
            }
915
916
            // If $suggestedid could not be guessed yet, we set it from the generic default accounting code $code_l
917
            if (empty($suggestedid) && empty($code_p) && !empty($code_l) && !getDolGlobalString('ACCOUNTANCY_DO_NOT_AUTOFILL_ACCOUNT_WITH_GENERIC')) {
918
                if (empty($this->accountingaccount_codetotid_cache[$code_l])) {
919
                    $tmpaccount = new self($this->db);
920
                    $result = $tmpaccount->fetch(0, $code_l, 1);
921
                    if ($result < 0) {
922
                        return -1;
923
                    }
924
                    if ($tmpaccount->id > 0) {
925
                        $suggestedid = $tmpaccount->id;
926
                    }
927
                    $this->accountingaccount_codetotid_cache[$code_l] = $tmpaccount->id;
928
                } else {
929
                    $suggestedid = $this->accountingaccount_codetotid_cache[$code_l];
930
                }
931
            }
932
            return array(
933
                'suggestedaccountingaccountbydefaultfor' => $suggestedaccountingaccountbydefaultfor,
934
                'suggestedaccountingaccountfor' => $suggestedaccountingaccountfor,
935
                'suggestedid' => $suggestedid,
936
                'code_l' => $code_l,
937
                'code_p' => $code_p,
938
                'code_t' => $code_t,
939
            );
940
        } else {
941
            if (is_array($hookmanager->resArray) && !empty($hookmanager->resArray)) {
942
                return $hookmanager->resArray;
943
            }
944
        }
945
946
        return -1;
947
    }
948
}
949