dolibarr 24.0.1
asset.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2018-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
4 * Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
5 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
6 * Copyright (C) 2024 Jose MARTINEZ <jose.martinez@pichinov.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
28require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
29
33class Asset extends CommonObject
34{
38 public $module = 'asset';
39
43 public $element = 'asset';
44
48 public $table_element = 'asset';
49
53 public $picto = 'asset';
54
59 public $fk_element = 'fk_asset';
60
67 protected $childtablesoncascade = array(
68 '@AssetAccountancyCodes:/asset/class/assetaccountancycodes.class.php:fk_asset',
69 '@AssetAccountancyCodesFiscal:/asset/class/assetaccountancycodesfiscal.class.php:fk_asset'
70 );
71
72
73 const STATUS_DRAFT = 0; // Draft
74 const STATUS_VALIDATED = 1; // In progress
75 const STATUS_DISPOSED = 9; // Disposed
76
108 public $fields = array(
109 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => "Id"),
110 'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => 1, 'visible' => 0, 'notnull' => 1, 'default' => '1', 'index' => 1, 'position' => 5),
111 'ref' => array('type' => 'varchar(128)', 'label' => 'Ref', 'enabled' => 1, 'position' => 20, 'notnull' => 1, 'visible' => 4, 'noteditable' => 0, 'default' => '(PROV)', 'index' => 1, 'searchall' => 1, 'showoncombobox' => 1, 'validate' => 1, 'comment' => "Reference of object", "css" => "maxwidth150"),
112 'label' => array('type' => 'varchar(255)', 'label' => 'Label', 'enabled' => 1, 'position' => 30, 'notnull' => 1, 'visible' => 1, 'searchall' => 1, 'csslist' => 'tdoverflowmax125', 'css' => 'minwidth300', 'cssview' => 'wordbreak', 'showoncombobox' => 2, 'validate' => 1,),
113 'fk_asset_model' => array('type' => 'integer:AssetModel:asset/class/assetmodel.class.php:1:((status:=:1) and (entity:IN:__SHARED_ENTITIES__))', 'label' => 'AssetModel', 'enabled' => 1, 'position' => 40, 'notnull' => 0, 'visible' => 1, 'index' => 1, 'validate' => 1, 'csslist' => 'tdoverflowmax75', 'css' => 'maxwidth300'),
114 'qty' => array('type' => 'real', 'label' => 'Qty', 'enabled' => 1, 'position' => 50, 'notnull' => 1, 'visible' => 0, 'default' => '1', 'isameasure' => 1, 'css' => 'maxwidth75imp', 'validate' => 1,),
115 'acquisition_type' => array('type' => 'smallint', 'label' => 'AssetAcquisitionType', 'enabled' => 1, 'position' => 60, 'notnull' => 1, 'visible' => 1, 'arrayofkeyval' => array(0 => 'AssetAcquisitionTypeNew', 1 => 'AssetAcquisitionTypeOccasion'), 'validate' => 1, 'csslist' => 'tdoverflowmax75'),
116 'asset_type' => array('type' => 'smallint', 'label' => 'AssetType', 'enabled' => 1, 'position' => 70, 'notnull' => 1, 'visible' => 1, 'arrayofkeyval' => array(0 => 'AssetTypeIntangible', 1 => 'AssetTypeTangible', 2 => 'AssetTypeInProgress', 3 => 'AssetTypeFinancial'), 'validate' => 1, 'csslist' => 'tdoverflowmax75'),
117 'not_depreciated' => array('type' => 'boolean', 'label' => 'AssetNotDepreciated', 'enabled' => 1, 'position' => 80, 'notnull' => 0, 'default' => '0', 'visible' => 1, 'validate' => 1, 'csslist' => 'maxwidth50 tdoverflowmax50', 'css' => 'maxwidth50imp'),
118 'date_acquisition' => array('type' => 'date', 'label' => 'AssetDateAcquisition', 'enabled' => 1, 'position' => 90, 'notnull' => 1, 'visible' => 1,),
119 'date_start' => array('type' => 'date', 'label' => 'AssetDateStart', 'enabled' => 1, 'position' => 100, 'notnull' => 0, 'visible' => -1,),
120 'acquisition_value_ht' => array('type' => 'price', 'label' => 'AssetAcquisitionValueHT', 'enabled' => 1, 'position' => 110, 'notnull' => 1, 'visible' => 1, 'isameasure' => 1, 'validate' => 1,),
121 'recovered_vat' => array('type' => 'price', 'label' => 'AssetRecoveredVAT', 'enabled' => 1, 'position' => 120, 'notnull' => 0, 'visible' => 1, 'isameasure' => 1, 'validate' => 1,),
122 'reversal_date' => array('type' => 'date', 'label' => 'AssetReversalDate', 'enabled' => 1, 'position' => 130, 'notnull' => 0, 'visible' => 1,),
123 'reversal_amount_ht' => array('type' => 'price', 'label' => 'AssetReversalAmountHT', 'enabled' => 1, 'position' => 140, 'notnull' => 0, 'visible' => 1, 'isameasure' => 1, 'validate' => 1, 'csslist' => 'maxwidth50'),
124 'disposal_date' => array('type' => 'date', 'label' => 'AssetDisposalDate', 'enabled' => 1, 'position' => 200, 'notnull' => 0, 'visible' => -2,),
125 'disposal_amount_ht' => array('type' => 'price', 'label' => 'AssetDisposalAmount', 'enabled' => 1, 'position' => 210, 'notnull' => 0, 'visible' => -2, 'default' => '0', 'isameasure' => 1, 'validate' => 1,),
126 'fk_disposal_type' => array('type' => 'sellist:c_asset_disposal_type:label:rowid::active=1', 'label' => 'AssetDisposalType', 'enabled' => 1, 'position' => 220, 'notnull' => 0, 'visible' => -2, 'index' => 1, 'validate' => 1,),
127 'disposal_depreciated' => array('type' => 'boolean', 'label' => 'AssetDisposalDepreciated', 'enabled' => 1, 'position' => 230, 'notnull' => 0, 'default' => '0', 'visible' => -2, 'validate' => 1,),
128 'disposal_subject_to_vat' => array('type' => 'boolean', 'label' => 'AssetDisposalSubjectToVat', 'enabled' => 1, 'position' => 240, 'notnull' => 0, 'default' => '0', 'visible' => -2, 'validate' => 1,),
129 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'position' => 300, 'notnull' => 0, 'visible' => 0, 'validate' => 1,),
130 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'position' => 301, 'notnull' => 0, 'visible' => 0, 'validate' => 1,),
131 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -2,),
132 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => -2,),
133 'date_valid' => array('type' => 'datetime', 'label' => 'DateValidation', 'enabled' => 1, 'visible' => -2, 'position' => 502, 'notnull' => 0,),
134 'fk_user_creat' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserAuthor', 'enabled' => 1, 'position' => 510, 'notnull' => 1, 'visible' => -2, 'foreignkey' => 'user.rowid',),
135 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2,),
136 'fk_user_valid' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserValidation', 'picto' => 'user', 'enabled' => 1, 'visible' => -2, 'position' => 512, 'notnull' => 0, 'csslist' => 'tdoverflowmax100'),
137 'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'LastMainDoc', 'enabled' => 1, 'position' => 600, 'notnull' => 0, 'visible' => 0,),
138 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'position' => 1000, 'notnull' => -1, 'visible' => -2,),
139 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'position' => 1010, 'notnull' => -1, 'visible' => 0,),
140 'status' => array('type' => 'smallint', 'label' => 'Status', 'enabled' => 1, 'position' => 1000, 'notnull' => 1, 'default' => '0', 'visible' => 2, 'index' => 1, 'arrayofkeyval' => array(0 => 'Draft', 1 => 'Validated', 9 => 'Canceled'), 'validate' => 1,),
141 );
142
146 public $rowid;
150 public $ref;
154 public $label;
158 public $fk_asset_model;
162 public $reversal_amount_ht;
166 public $acquisition_value_ht;
170 public $recovered_vat;
174 public $reversal_date;
178 public $date_acquisition;
182 public $date_start;
186 public $qty;
190 public $acquisition_type;
194 public $asset_type;
198 public $not_depreciated;
202 public $disposal_date;
206 public $disposal_amount_ht;
210 public $fk_disposal_type;
214 public $disposal_depreciated;
218 public $disposal_subject_to_vat;
222 public $supplier_invoice_id;
226 public $note_public;
230 public $note_private;
234 public $date_valid;
238 public $fk_user_creat;
242 public $fk_user_modif;
246 public $fk_user_valid;
250 public $last_main_doc;
251
255 public $import_key;
259 public $model_pdf;
260
264 public $status;
265
269 public $asset_depreciation_options;
270
274 public $asset_accountancy_codes;
275
279 public $depreciation_lines = array();
280
281
287 public function __construct(DoliDB $db)
288 {
289 global $langs;
290
291 $this->db = $db;
292
293 $this->ismultientitymanaged = 1;
294 $this->isextrafieldmanaged = 1;
295
296 if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
297 $this->fields['rowid']['visible'] = 0;
298 }
299 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
300 $this->fields['entity']['enabled'] = 0;
301 }
302
303 // Unset fields that are disabled
304 foreach ($this->fields as $key => $val) {
305 if (isset($val['enabled']) && empty($val['enabled'])) {
306 unset($this->fields[$key]);
307 }
308 }
309
310 // Translate some data of arrayofkeyval
311 if (is_object($langs)) {
312 foreach ($this->fields as $key => $val) {
313 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
314 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
315 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
316 }
317 }
318 }
319 }
320 }
321
329 public function create(User $user, $notrigger = 0)
330 {
331 if (!isset($this->date_start) || $this->date_start === "") {
332 $this->date_start = $this->date_acquisition;
333 }
334
335 $this->db->begin();
336
337 $result = $result_create = $this->createCommon($user, $notrigger);
338 if ($result > 0 && $this->fk_asset_model > 0) {
339 $result = $this->setDataFromAssetModel($user, $notrigger);
340 }
341 if ($result > 0) {
342 if ($this->supplier_invoice_id > 0) {
343 $this->add_object_linked('invoice_supplier', $this->supplier_invoice_id);
344 }
345 }
346
347 if ($result < 0) {
348 $this->db->rollback();
349 } else {
350 $this->db->commit();
351 }
352
353 return $result > 0 ? $result_create : $result;
354 }
355
363 public function createFromClone(User $user, $fromid)
364 {
365 //global $langs, $extrafields;
366 //$error = 0;
367
368 dol_syslog(__METHOD__, LOG_DEBUG);
369
370 // $object = new self($this->db);
371 //
372 // $this->db->begin();
373 //
374 // // Load source object
375 // $result = $object->fetchCommon($fromid);
376 //
377 //
378 // // Reset some properties
379 // unset($object->id);
380 // unset($object->fk_user_creat);
381 // unset($object->import_key);
382 //
383 // // Clear fields
384 // if (property_exists($object, 'ref')) {
385 // $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
386 // }
387 // if (property_exists($object, 'label')) {
388 // $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
389 // }
390 // if (property_exists($object, 'status')) {
391 // $object->status = self::STATUS_DRAFT;
392 // }
393 // if (property_exists($object, 'date_creation')) {
394 // $object->date_creation = dol_now();
395 // }
396 // if (property_exists($object, 'date_modification')) {
397 // $object->date_modification = null;
398 // }
399 // // ...
400 // // Clear extrafields that are unique
401 // if (is_array($object->array_options) && count($object->array_options) > 0) {
402 // $extrafields->fetch_name_optionals_label($this->table_element);
403 // foreach ($object->array_options as $key => $option) {
404 // $shortkey = preg_replace('/options_/', '', $key);
405 // if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
406 // //var_dump($key); var_dump($clonedObj->array_options[$key]); exit;
407 // unset($object->array_options[$key]);
408 // }
409 // }
410 // }
411 //
412 // // Create clone
413 // $object->context['createfromclone'] = 'createfromclone';
414 // $result = $object->createCommon($user);
415 // if ($result < 0) {
416 // $error++;
417 // $this->error = $object->error;
418 // $this->errors = $object->errors;
419 // }
420 //
421 // if (!$error) {
422 // // copy internal contacts
423 // if ($this->copy_linked_contact($object, 'internal') < 0) {
424 // $error++;
425 // }
426 // }
427 //
428 // if (!$error) {
429 // // copy external contacts if same company
430 // if (property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) {
431 // if ($this->copy_linked_contact($object, 'external') < 0) {
432 // $error++;
433 // }
434 // }
435 // }
436 //
437 // unset($object->context['createfromclone']);
438 //
439 // // End
440 // if (!$error) {
441 // $this->db->commit();
442 // return $object;
443 // } else {
444 // $this->db->rollback();
445 // return -1;
446 // }
447
448 return -1;
449 }
450
458 public function fetch($id, $ref = null)
459 {
460 $result = $this->fetchCommon($id, $ref);
461 if ($result > 0) {
462 $res = $this->hasDepreciationLinesInBookkeeping();
463 if ($res < 0) {
464 return -1;
465 } elseif ($res > 0) {
466 $this->fields['date_acquisition']['noteditable'] = 1;
467 $this->fields['date_start']['noteditable'] = 1;
468 $this->fields['acquisition_value_ht']['noteditable'] = 1;
469 $this->fields['recovered_vat']['noteditable'] = 1;
470 $this->fields['reversal_date']['noteditable'] = 1;
471 $this->fields['reversal_amount_ht']['noteditable'] = 1;
472 }
473 }
474
475 return $result;
476 }
477
478
491 public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
492 {
493 dol_syslog(__METHOD__, LOG_DEBUG);
494
495 $records = array();
496
497 $sql = "SELECT ";
498 $sql .= $this->getFieldList('t');
499 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t";
500 if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
501 $sql .= " WHERE t.entity IN (".getEntity($this->element).")";
502 } else {
503 $sql .= " WHERE 1 = 1";
504 }
505
506 // Manage filter
507 $errormessage = '';
508 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
509 if ($errormessage) {
510 $this->errors[] = $errormessage;
511 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
512
513 return -1;
514 }
515
516 if (!empty($sortfield)) {
517 $sql .= $this->db->order($sortfield, $sortorder);
518 }
519 if (!empty($limit)) {
520 $sql .= $this->db->plimit($limit, $offset);
521 }
522
523 $resql = $this->db->query($sql);
524 if ($resql) {
525 $num = $this->db->num_rows($resql);
526 $i = 0;
527 while ($i < ($limit ? min($limit, $num) : $num)) {
528 $obj = $this->db->fetch_object($resql);
529
530 $record = new self($this->db);
531 $record->setVarsFromFetchObj($obj);
532
533 $records[$record->id] = $record;
534
535 $i++;
536 }
537 $this->db->free($resql);
538
539 return $records;
540 } else {
541 $this->errors[] = 'Error '.$this->db->lasterror();
542 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
543
544 return -1;
545 }
546 }
547
555 public function update(User $user, $notrigger = 0)
556 {
557 if (!isset($this->date_start) || $this->date_start === "") {
558 $this->date_start = $this->date_acquisition;
559 }
560
561 $this->db->begin();
562
563 $result = $this->updateCommon($user, $notrigger);
564 if ($result > 0 && $this->fk_asset_model > 0 && $this->fk_asset_model != $this->oldcopy->fk_asset_model) {
565 $result = $this->setDataFromAssetModel($user, $notrigger);
566 }
567 if ($result > 0 && is_object($this->oldcopy) && (
568 $this->date_start != $this->oldcopy->date_start ||
569 $this->acquisition_value_ht != $this->oldcopy->acquisition_value_ht ||
570 $this->reversal_date != $this->oldcopy->reversal_date ||
571 $this->reversal_amount_ht != $this->oldcopy->reversal_amount_ht ||
572 ($this->fk_asset_model > 0 && $this->fk_asset_model != $this->oldcopy->fk_asset_model)
573 )) {
574 $result = $this->calculationDepreciation();
575 }
576
577 if ($result < 0) {
578 $this->db->rollback();
579 } else {
580 $this->db->commit();
581 }
582
583 return $result;
584 }
585
593 public function delete(User $user, $notrigger = 0)
594 {
595 $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'asset_depreciation_codes_economic WHERE fk_asset = '.((int) $this->id);
596 $this->db->query($sql);
597
598 $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'asset_depreciation_codes_fiscal WHERE fk_asset = '.((int) $this->id);
599 $this->db->query($sql);
600
601 $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'asset_depreciation_options_fiscal WHERE fk_asset = '.((int) $this->id);
602 $this->db->query($sql);
603
604 $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'asset_depreciation_options_economic WHERE fk_asset = '.((int) $this->id);
605 $this->db->query($sql);
606
607 $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'asset_depreciation WHERE fk_asset = '.((int) $this->id);
608 $this->db->query($sql);
609
610 return $this->deleteCommon($user, $notrigger);
611 //return $this->deleteCommon($user, $notrigger, 1);
612 }
613
621 public function setDataFromAssetModel(User $user, $notrigger = 0)
622 {
623 global $langs;
624 $langs->load('assets');
625
626 // Clean parameters
627 $this->id = $this->id > 0 ? $this->id : 0;
628 $this->fk_asset_model = $this->fk_asset_model > 0 ? $this->fk_asset_model : 0;
629
630 // Check parameters
631 $error = 0;
632 if (empty($this->id)) {
633 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Asset") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')');
634 $error++;
635 }
636 if (empty($this->fk_asset_model)) {
637 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("AssetModel") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')');
638 $error++;
639 }
640 if ($error) {
641 return -1;
642 }
643
644 $this->db->begin();
645
646 // Get depreciation options
647 //---------------------------
648 require_once DOL_DOCUMENT_ROOT . '/asset/class/assetdepreciationoptions.class.php';
649 $options_model = new AssetDepreciationOptions($this->db);
650 $result = $options_model->fetchDeprecationOptions(0, $this->fk_asset_model);
651 if ($result < 0) {
652 $this->error = $options_model->error;
653 $this->errors = $options_model->errors;
654 $error++;
655 } elseif ($result > 0) {
656 $options = new AssetDepreciationOptions($this->db);
657 $result = $options->fetchDeprecationOptions($this->id);
658 if ($result < 0) {
659 $this->error = $options->error;
660 $this->errors = $options->errors;
661 $error++;
662 }
663
664 if (!$error) {
665 foreach ($options_model->deprecation_options as $mode_key => $fields) {
666 foreach ($fields as $field_key => $value) {
667 $options->deprecation_options[$mode_key][$field_key] = $value;
668 }
669 }
670
671 $result = $options->updateDeprecationOptions($user, $this->id, 0, $notrigger);
672 if ($result < 0) {
673 $this->error = $options->error;
674 $this->errors = $options->errors;
675 $error++;
676 }
677 }
678 }
679
680 // Get accountancy codes
681 //---------------------------
682 if (!$error) {
683 require_once DOL_DOCUMENT_ROOT . '/asset/class/assetaccountancycodes.class.php';
684 $accountancy_codes_model = new AssetAccountancyCodes($this->db);
685 $result = $accountancy_codes_model->fetchAccountancyCodes(0, $this->fk_asset_model);
686 if ($result < 0) {
687 $this->error = $accountancy_codes_model->error;
688 $this->errors = $accountancy_codes_model->errors;
689 $error++;
690 } elseif ($result > 0) {
691 $accountancy_codes = new AssetAccountancyCodes($this->db);
692 $result = $accountancy_codes->fetchAccountancyCodes($this->id);
693 if ($result < 0) {
694 $this->error = $accountancy_codes->error;
695 $this->errors = $accountancy_codes->errors;
696 $error++;
697 }
698
699 if (!$error) {
700 foreach ($accountancy_codes_model->accountancy_codes as $mode_key => $fields) {
701 foreach ($fields as $field_key => $value) {
702 $accountancy_codes->accountancy_codes[$mode_key][$field_key] = $value;
703 }
704 }
705
706 $result = $accountancy_codes->updateAccountancyCodes($user, $this->id, 0, $notrigger);
707 if ($result < 0) {
708 $this->error = $accountancy_codes->error;
709 $this->errors = $accountancy_codes->errors;
710 $error++;
711 }
712 }
713 }
714 }
715
716 if ($error) {
717 $this->db->rollback();
718 return -1;
719 } else {
720 $this->db->commit();
721 return 1;
722 }
723 }
724
730 public function fetchDepreciationLines()
731 {
732 global $langs;
733 $langs->load('assets');
734 $this->depreciation_lines = array();
735
736 // Clean parameters
737 $this->id = $this->id > 0 ? $this->id : 0;
738
739 // Check parameters
740 $error = 0;
741 if (empty($this->id)) {
742 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Asset") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')');
743 $error++;
744 }
745 if ($error) {
746 return -1;
747 }
748
749 $sql = "SELECT ad.rowid, ad.depreciation_mode, ad.ref, ad.depreciation_date, ad.depreciation_ht, ad.cumulative_depreciation_ht,";
750 $sql .= " " . $this->db->ifsql('EXISTS (SELECT fk_docdet FROM ' . MAIN_DB_PREFIX . 'accounting_bookkeeping as ab WHERE ab.doc_type = \'asset\' AND ab.fk_docdet = ad.rowid)', '1', '0') . " AS bookkeeping";
751 $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation AS ad";
752 $sql .= " WHERE ad.fk_asset = " . (int) $this->id;
753 $sql .= " ORDER BY ad.depreciation_date ASC";
754
755 $resql = $this->db->query($sql);
756 if (!$resql) {
757 $this->errors[] = $langs->trans('AssetErrorFetchDepreciationLines') . ': ' . $this->db->lasterror();
758 return -1;
759 }
760
761 while ($obj = $this->db->fetch_object($resql)) {
762 if (!isset($this->depreciation_lines[$obj->depreciation_mode])) {
763 $this->depreciation_lines[$obj->depreciation_mode] = array();
764 }
765 $this->depreciation_lines[$obj->depreciation_mode][] = array(
766 'id' => $obj->rowid,
767 'ref' => $obj->ref,
768 'depreciation_date' => $this->db->jdate($obj->depreciation_date),
769 'depreciation_ht' => $obj->depreciation_ht,
770 'cumulative_depreciation_ht' => $obj->cumulative_depreciation_ht,
771 'bookkeeping' => $obj->bookkeeping,
772 );
773 }
774
775 return 1;
776 }
777
784 {
785 global $langs;
786 $langs->load('assets');
787
788 // Clean parameters
789 $this->id = $this->id > 0 ? $this->id : 0;
790
791 // Check parameters
792 $error = 0;
793 if (empty($this->id)) {
794 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Asset") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')');
795 $error++;
796 }
797 if ($error) {
798 return -1;
799 }
800
801 // Old request with 'WITH'
802 /*
803 $sql = "WITH in_accounting_bookkeeping(fk_docdet) AS (";
804 $sql .= " SELECT DISTINCT fk_docdet";
805 $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping";
806 $sql .= " WHERE doc_type = 'asset'";
807 $sql .= ")";
808 $sql .= "SELECT COUNT(*) AS has_bookkeeping";
809 $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation AS ad";
810 $sql .= " LEFT JOIN in_accounting_bookkeeping as iab ON iab.fk_docdet = ad.rowid";
811 $sql .= " WHERE ad.fk_asset = " . (int) $this->id;
812 $sql .= " AND iab.fk_docdet IS NOT NULL";
813 */
814
815 $sql = "SELECT COUNT(*) AS has_bookkeeping";
816 $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation AS ad";
817 $sql .= " LEFT JOIN (SELECT DISTINCT fk_docdet FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping WHERE doc_type = 'asset') AS iab ON iab.fk_docdet = ad.rowid";
818 $sql .= " WHERE ad.fk_asset = " . (int) $this->id;
819 $sql .= " AND iab.fk_docdet IS NOT NULL";
820
821 $resql = $this->db->query($sql);
822 if (!$resql) {
823 $this->errors[] = $langs->trans('AssetErrorFetchDepreciationLines') . ': ' . $this->db->lasterror();
824 return -1;
825 }
826
827 if ($obj = $this->db->fetch_object($resql)) {
828 return $obj->has_bookkeeping > 0 ? 1 : 0;
829 }
830
831 return 0;
832 }
833
846 public function addDepreciationLine($mode, $ref, $depreciation_date, $depreciation_ht, $cumulative_depreciation_ht, $accountancy_code_debit, $accountancy_code_credit)
847 {
848 global $langs;
849 $langs->load('assets');
850
851 // Clean parameters
852 $this->id = $this->id > 0 ? $this->id : 0;
853 $mode = strtolower(trim($mode));
854 $ref = trim($ref);
855 $accountancy_code_debit = trim($accountancy_code_debit);
856 $accountancy_code_credit = trim($accountancy_code_credit);
857
858 // Check parameters
859 $error = 0;
860 if (empty($this->id)) {
861 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Asset") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')');
862 $error++;
863 }
864 if ($error) {
865 return -1;
866 }
867
868 $sql = "INSERT INTO " . MAIN_DB_PREFIX . "asset_depreciation(fk_asset, depreciation_mode, ref, depreciation_date, depreciation_ht, cumulative_depreciation_ht, accountancy_code_debit, accountancy_code_credit)";
869 $sql .= " VALUES ( ";
870 $sql .= " " . (int) $this->id;
871 $sql .= ", '" . $this->db->escape($mode) . "'";
872 $sql .= ", '" . $this->db->escape($ref) . "'";
873 $sql .= ", '" . $this->db->idate($depreciation_date) . "'";
874 $sql .= ", " . (float) $depreciation_ht;
875 $sql .= ", " . (float) $cumulative_depreciation_ht;
876 $sql .= ", '" . $this->db->escape($accountancy_code_debit) . "'";
877 $sql .= ", '" . $this->db->escape($accountancy_code_credit) . "'";
878 $sql .= ")";
879
880 $resql = $this->db->query($sql);
881 if (!$resql) {
882 $this->errors[] = $langs->trans('AssetErrorAddDepreciationLine') . ': ' . $this->db->lasterror();
883 return -1;
884 }
885
886 return 1;
887 }
888
894 public function calculationDepreciation()
895 {
896 global $conf, $langs;
897 $langs->load('assets');
898
899 // Clean parameters
900 $this->id = $this->id > 0 ? $this->id : 0;
901
902 // Check parameters
903 $error = 0;
904 if (empty($this->id)) {
905 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Asset") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')');
906 $error++;
907 }
908 if ($error) {
909 return -1;
910 }
911
912 if (! empty($this->not_depreciated)) {
913 return 1;
914 }
915
916 // Get depreciation options
917 //---------------------------
918 require_once DOL_DOCUMENT_ROOT . '/asset/class/assetdepreciationoptions.class.php';
919 $options = new AssetDepreciationOptions($this->db);
920 $result = $options->fetchDeprecationOptions($this->id);
921 if ($result < 0) {
922 $this->error = $options->error;
923 $this->errors = $options->errors;
924 return -1;
925 }
926
927 // Get accountancy codes
928 //---------------------------
929 require_once DOL_DOCUMENT_ROOT . '/asset/class/assetaccountancycodes.class.php';
930 $accountancy_codes = new AssetAccountancyCodes($this->db);
931 $result = $accountancy_codes->fetchAccountancyCodes($this->id);
932 if ($result < 0) {
933 $this->error = $accountancy_codes->error;
934 $this->errors = $accountancy_codes->errors;
935 return -1;
936 }
937
938 $this->db->begin();
939
940 // Delete old lines
941 $modes = array();
942 foreach ($options->deprecation_options as $mode_key => $fields) {
943 $modes[$mode_key] = $this->db->escape($mode_key);
944 }
945 $sql = "DELETE FROM " . MAIN_DB_PREFIX . "asset_depreciation";
946 $sql .= " WHERE fk_asset = " . (int) $this->id;
947 $sql .= " AND depreciation_mode NOT IN ('" . $this->db->sanitize(implode("', '", $modes)) . "')";
948
949 $resql = $this->db->query($sql);
950 if (!$resql) {
951 $this->errors[] = $langs->trans('AssetErrorClearDepreciationLines') . ': ' . $this->db->lasterror();
952 $error++;
953 }
954
955 if (!$error) {
956 // Get fiscal period
957 require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
958 require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php';
959
960 // @FIXME getCurrentPeriodOfFiscalYear return the first period found. What if there is several ? And what if not closed ? And what if end date not yet defined.
961 $dates = getCurrentPeriodOfFiscalYear($this->db, $conf, $this->date_start > $this->date_acquisition ? $this->date_start : $this->date_acquisition);
962 $init_fiscal_period_start = $dates['date_start'];
963 $init_fiscal_period_end = $dates['date_end'];
964 /*
965 if (empty($init_fiscal_period_start) || empty($init_fiscal_period_end)) {
966 $pastmonthyear = $dates['pastmonthyear'];
967 $pastmonth = $dates['pastmonth'];
968 $init_fiscal_period_start = dol_get_first_day((int) $pastmonthyear, (int) $pastmonth, false);
969 $init_fiscal_period_end = dol_get_last_day((int) $pastmonthyear, (int) $pastmonth, false);
970 }
971 */
972
973 foreach ($options->deprecation_options as $mode_key => $fields) {
974 // Get last depreciation lines save in bookkeeping
975 //-----------------------------------------------------
976
977 // Old request with 'WITH'
978 /*
979 $sql = "WITH in_accounting_bookkeeping(fk_docdet) AS (";
980 $sql .= " SELECT fk_docdet";
981 $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping";
982 $sql .= " WHERE doc_type = 'asset'";
983 $sql .= ")";
984 $sql .= "SELECT ad.depreciation_date, ad.cumulative_depreciation_ht";
985 $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation AS ad";
986 $sql .= " LEFT JOIN in_accounting_bookkeeping as iab ON iab.fk_docdet = ad.rowid";
987 $sql .= " WHERE ad.fk_asset = " . (int) $this->id;
988 $sql .= " AND ad.depreciation_mode = '" . $this->db->escape($mode_key) . "'";
989 $sql .= " AND iab.fk_docdet IS NOT NULL";
990 $sql .= " ORDER BY ad.depreciation_date DESC";
991 $sql .= " LIMIT 1";
992 */
993
994 $sql = "SELECT ad.depreciation_date, ad.cumulative_depreciation_ht";
995 $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation AS ad";
996 $sql .= " LEFT JOIN (SELECT DISTINCT fk_docdet FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping WHERE doc_type = 'asset') AS iab ON iab.fk_docdet = ad.rowid";
997 $sql .= " WHERE ad.fk_asset = " . (int) $this->id;
998 $sql .= " AND ad.depreciation_mode = '" . $this->db->escape($mode_key) . "'";
999 $sql .= " AND iab.fk_docdet IS NOT NULL";
1000 $sql .= " ORDER BY ad.depreciation_date DESC";
1001 $sql .= " LIMIT 1";
1002
1003 $resql = $this->db->query($sql);
1004 if (!$resql) {
1005 $this->errors[] = $langs->trans('AssetErrorFetchMaxDepreciationDateForMode', $mode_key) . ': ' . $this->db->lasterror();
1006 $error++;
1007 break;
1008 }
1009 $last_depreciation_date = '';
1010 $last_cumulative_depreciation_ht = $this->reversal_amount_ht;
1011 if ($obj = $this->db->fetch_object($resql)) {
1012 $last_depreciation_date = $this->db->jdate($obj->depreciation_date);
1013 $last_cumulative_depreciation_ht = $obj->cumulative_depreciation_ht;
1014 }
1015
1016 // Set last cumulative depreciation
1017 $sql = "UPDATE " . MAIN_DB_PREFIX . $this->db->sanitize($options->deprecation_options_fields[$mode_key]['table']);
1018 $sql .= " SET total_amount_last_depreciation_ht = " . ((float) (empty($last_cumulative_depreciation_ht) ? 0 : $last_cumulative_depreciation_ht));
1019 $sql .= " WHERE fk_asset = " . (int) $this->id;
1020 $resql = $this->db->query($sql);
1021 if (!$resql) {
1022 $this->errors[] = $langs->trans('AssetErrorSetLastCumulativeDepreciation') . ': ' . $this->db->lasterror();
1023 $error++;
1024 break;
1025 }
1026
1027 // Delete old lines
1028 $sql = "DELETE FROM " . MAIN_DB_PREFIX . "asset_depreciation";
1029 $sql .= " WHERE fk_asset = " . (int) $this->id;
1030 $sql .= " AND depreciation_mode = '" . $this->db->escape($mode_key) . "'";
1031 $sql .= " AND NOT EXISTS (SELECT fk_docdet FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping WHERE doc_type = 'asset' AND fk_docdet = " . MAIN_DB_PREFIX . "asset_depreciation.rowid)";
1032 if ($last_depreciation_date !== "") {
1033 $sql .= " AND ref <> ''";
1034 }
1035 $resql = $this->db->query($sql);
1036 if (!$resql) {
1037 $this->errors[] = $langs->trans('AssetErrorClearDepreciationLines') . ': ' . $this->db->lasterror();
1038 $error++;
1039 break;
1040 }
1041
1042 // Get depreciation period
1043 $depreciation_date_start = $this->date_start > $this->date_acquisition ? $this->date_start : $this->date_acquisition;
1044 $depreciation_date_end = dol_time_plus_duree(dol_time_plus_duree((int) $depreciation_date_start, (float) $fields['duration'], $fields['duration_type'] == 1 ? 'm' : ($fields['duration_type'] == 2 ? 'd' : 'y')), -1, 'd');
1045 $depreciation_amount = $fields['amount_base_depreciation_ht'];
1046 if ($fields['duration_type'] == 2) { // Daily
1047 $fiscal_period_start = $depreciation_date_start;
1048 $fiscal_period_end = $depreciation_date_start;
1049 } elseif ($fields['duration_type'] == 1) { // Monthly
1050 $date_temp = dol_getdate((int) $depreciation_date_start);
1051 $fiscal_period_start = dol_get_first_day($date_temp['year'], $date_temp['mon'], false);
1052 $fiscal_period_end = dol_get_last_day($date_temp['year'], $date_temp['mon'], false);
1053 } else { // Annually
1054 $fiscal_period_start = $init_fiscal_period_start;
1055 $fiscal_period_end = $init_fiscal_period_end;
1056 }
1057 $cumulative_depreciation_ht = (float) $last_cumulative_depreciation_ht;
1058 $depreciation_period_amount = $depreciation_amount - (float) $this->reversal_amount_ht;
1059 $start_date = $depreciation_date_start;
1060 $disposal_date = isset($this->disposal_date) && $this->disposal_date !== "" ? $this->disposal_date : "";
1061 $finish_date = $disposal_date !== "" ? $disposal_date : $depreciation_date_end;
1062 $accountancy_code_depreciation_debit_key = $accountancy_codes->accountancy_codes_fields[$mode_key]['depreciation_debit'];
1063 $accountancy_code_depreciation_debit = $accountancy_codes->accountancy_codes[$mode_key][$accountancy_code_depreciation_debit_key];
1064 $accountancy_code_depreciation_credit_key = $accountancy_codes->accountancy_codes_fields[$mode_key]['depreciation_credit'];
1065 $accountancy_code_credit = $accountancy_codes->accountancy_codes[$mode_key][$accountancy_code_depreciation_credit_key];
1066
1067 // Reversal depreciation line
1068 //-----------------------------------------------------
1069 if ($last_depreciation_date === "" && ($depreciation_date_start < $fiscal_period_start || is_numeric($this->reversal_date))) {
1070 if (is_numeric($this->reversal_date)) {
1071 if ($this->reversal_date < $fiscal_period_start) {
1072 $this->errors[] = $langs->trans('AssetErrorReversalDateNotGreaterThanCurrentBeginFiscalDateForMode', $mode_key);
1073 $error++;
1074 break;
1075 }
1076
1077 if (empty($this->reversal_amount_ht)) {
1078 $this->errors[] = $langs->trans('AssetErrorReversalAmountNotProvidedForMode', $mode_key);
1079 $error++;
1080 break;
1081 }
1082
1083 $start_date = $this->reversal_date;
1084 $result = $this->addDepreciationLine($mode_key, '', $start_date, (float) $this->reversal_amount_ht, (float) $this->reversal_amount_ht, $accountancy_code_depreciation_debit, $accountancy_code_credit);
1085 if ($result < 0) {
1086 $error++;
1087 break;
1088 }
1089 } else {
1090 $this->errors[] = $langs->trans('AssetErrorReversalDateNotProvidedForMode', $mode_key);
1091 $error++;
1092 break;
1093 }
1094 }
1095
1096 // futures depreciation lines
1097 //-----------------------------------------------------
1098 $nb_days_in_year = getDolGlobalInt('ASSET_DEPRECIATION_DURATION_PER_YEAR', 360);
1099 $nb_days_in_month = getDolGlobalInt('ASSET_DEPRECIATION_DURATION_PER_MONTH', 30);
1100 $period_amount = (float) ($fields['duration'] > 0 ? price2num($depreciation_period_amount / $fields['duration'], 'MT') : 0);
1101 $first_period_found = false;
1102
1103 //$first_period_date = isset($begin_period) && $begin_period > $fiscal_period_start ? $begin_period : $fiscal_period_start;
1104 $first_period_date = $fiscal_period_start;
1105
1106 $ref_date_format = "%Y" . ($fields['duration_type'] == 1 || $fields['duration_type'] == 2 ? '-%m' : '') . ($fields['duration_type'] == 2 ? '-%d' : '');
1107
1108 // Loop security
1109 $idx_loop = 0;
1110 $max_loop = $fields['duration'] + 2;
1111 do {
1112 // Loop security
1113 $idx_loop++;
1114 if ($idx_loop > $max_loop) {
1115 break;
1116 }
1117
1118 if ($last_depreciation_date < $fiscal_period_end && ($first_period_date <= $start_date || $first_period_found)) {
1119 // Disposal not depreciated
1120 if ($fiscal_period_start <= $disposal_date && $disposal_date <= $fiscal_period_end && empty($this->disposal_depreciated)) {
1121 break;
1122 }
1123
1124 $first_period_found = true;
1125
1126 $period_begin = dol_print_date($fiscal_period_start, $ref_date_format);
1127 $period_end = dol_print_date($fiscal_period_end, $ref_date_format);
1128 $ref = $period_begin . ($period_begin != $period_end ? ' - ' . $period_end : '');
1129 if ($fiscal_period_start <= $disposal_date && $disposal_date <= $fiscal_period_end) {
1130 $ref .= ' - ' . $langs->transnoentitiesnoconv('AssetDisposal');
1131 }
1132
1133 $begin_date = $fiscal_period_start < $start_date && $start_date <= $fiscal_period_end ? $start_date : $fiscal_period_start;
1134 $end_date = $fiscal_period_start < $finish_date && $finish_date <= $fiscal_period_end ? $finish_date : $fiscal_period_end;
1135 if ($fields['duration_type'] == 2) { // Daily
1136 $depreciation_ht = $period_amount;
1137 } elseif ($fields['duration_type'] == 1) { // Monthly
1138 $nb_days = min($nb_days_in_month, num_between_day($begin_date, $end_date, 1));
1139 if ($nb_days >= 28) {
1140 $date_temp = dol_getdate($begin_date);
1141 if ($date_temp['mon'] == 2) {
1142 $nb_days = 30;
1143 }
1144 }
1145 $depreciation_ht = (float) price2num($period_amount * $nb_days / $nb_days_in_month, 'MT');
1146 } else { // Annually, taking care for adjustments to shortened or extended periods (e.g., fiscal years of 9 or 15 months)
1147 $nb_days_real = num_between_day($begin_date, $end_date, 1);
1148 if (($nb_days_real > 366) || (num_between_day($fiscal_period_start, $fiscal_period_end, 1) < $nb_days_in_year)) { // FY Period changed
1149 $nb_days = $nb_days_real;
1150 } else {
1151 $nb_days = min($nb_days_in_year, $nb_days_real);
1152 }
1153 $depreciation_ht = (float) price2num($period_amount * $nb_days / $nb_days_in_year, 'MT');
1154 }
1155 if (getDolGlobalInt('ASSET_ROUND_INTEGER_NUMBER_UPWARDS') == 1) {
1156 if ($idx_loop < $max_loop) { // avoid last depreciation value
1157 $depreciation_ht = ceil($depreciation_ht);
1158 }
1159 }
1160
1161 if ($fiscal_period_start <= $depreciation_date_end && $depreciation_date_end <= $fiscal_period_end) { // last period
1162 $depreciation_ht = (float) price2num($depreciation_amount - (float) $cumulative_depreciation_ht, 'MT');
1163 $cumulative_depreciation_ht = $depreciation_amount;
1164 } else {
1165 $cumulative_depreciation_ht += $depreciation_ht;
1166 }
1167
1168 $result = $this->addDepreciationLine($mode_key, $ref, $fiscal_period_end, $depreciation_ht, (float) $cumulative_depreciation_ht, $accountancy_code_depreciation_debit, $accountancy_code_credit);
1169 if ($result < 0) {
1170 $error++;
1171 break;
1172 }
1173 }
1174
1175 // Next fiscal period (+1 day/month/year)
1176 $fiscal_period_start = dol_time_plus_duree($fiscal_period_end, 1, 'd');
1177
1178 if ($fields['duration_type'] == 0) { // Annually - use fiscal year-end
1179 // Search for the NEXT fiscal year
1180 $next_fy = getNextFiscalYear($this->db, $fiscal_period_end, 'gmt');
1181
1182 if ($next_fy !== null) {
1183 // Exercise found in database
1184 $fiscal_period_start = $next_fy['date_start'];
1185 $fiscal_period_end = $next_fy['date_end'];
1186 } else {
1187 // If there is no subsequent fiscal year in the database, a one-year fiscal year is automatically generated.
1188 // based on the structure of the current fiscal year
1189 $current_fy_start_parts = dol_getdate($fiscal_period_start);
1190
1191 // Calculate the end: 1 year minus 1 day from the start
1192 $fiscal_period_end = dol_time_plus_duree(dol_time_plus_duree($fiscal_period_start, 1, 'y'), -1, 'd');
1193
1194 // If the amortization end date is exceeded, there is no need to continue after that.
1195 // The loop will end naturally with the while condition.
1196 }
1197 } elseif ($fields['duration_type'] == 1) { // Monthly
1198 $fiscal_period_end = dol_time_plus_duree(dol_time_plus_duree($fiscal_period_start, 1, 'm'), -1, 'd');
1199 } else { // Daily
1200 $fiscal_period_end = $fiscal_period_start;
1201 }
1202 $last_period_date = $disposal_date !== "" && $disposal_date < $depreciation_date_end ? $disposal_date : $depreciation_date_end;
1203 } while ($fiscal_period_start < $last_period_date);
1204
1205 if ($error) {
1206 break;
1207 }
1208 }
1209 }
1210
1211 if ($error) {
1212 $this->db->rollback();
1213 return -1;
1214 } else {
1215 $this->db->commit();
1216 return 1;
1217 }
1218 }
1219
1226 public function setLastCumulativeDepreciation($asset_depreciation_id)
1227 {
1228 global $langs;
1229 $langs->load('assets');
1230
1231 // Clean parameters
1232 $asset_depreciation_id = $asset_depreciation_id > 0 ? $asset_depreciation_id : 0;
1233
1234 // Check parameters
1235 $error = 0;
1236 if (empty($asset_depreciation_id)) {
1237 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("AssetDepreciation") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')');
1238 $error++;
1239 }
1240 if ($error) {
1241 return -1;
1242 }
1243
1244 $this->db->begin();
1245
1246 require_once DOL_DOCUMENT_ROOT . '/asset/class/assetdepreciationoptions.class.php';
1247 $options = new AssetDepreciationOptions($this->db);
1248
1249 // Get last depreciation lines save in bookkeeping
1250 //-----------------------------------------------------
1251 $sql = "SELECT fk_asset, depreciation_mode, cumulative_depreciation_ht";
1252 $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation";
1253 $sql .= " WHERE rowid = " . (int) $asset_depreciation_id;
1254 $resql = $this->db->query($sql);
1255 if (!$resql) {
1256 $this->errors[] = $langs->trans('AssetErrorFetchCumulativeDepreciation') . ': ' . $this->db->lasterror();
1257 $error++;
1258 } else {
1259 if ($obj = $this->db->fetch_object($resql)) {
1260 $mode_key = $obj->depreciation_mode;
1261 if (!empty($options->deprecation_options_fields[$mode_key])) {
1262 $sql = "UPDATE " . MAIN_DB_PREFIX . $this->db->sanitize($options->deprecation_options_fields[$mode_key]['table']);
1263 $sql .= " SET total_amount_last_depreciation_ht = " . ((float) $obj->cumulative_depreciation_ht);
1264 $sql .= " WHERE fk_asset = " . (int) $obj->fk_asset;
1265 $resql = $this->db->query($sql);
1266 if (!$resql) {
1267 $this->errors[] = $langs->trans('AssetErrorSetLastCumulativeDepreciation') . ': ' . $this->db->lasterror();
1268 $error++;
1269 }
1270 }
1271 }
1272 }
1273
1274 if ($error) {
1275 $this->db->rollback();
1276 return -1;
1277 } else {
1278 $this->db->commit();
1279 return 1;
1280 }
1281 }
1282
1291 public function dispose($user, $disposal_invoice_id, $notrigger = 0)
1292 {
1293 global $conf, $langs;
1294
1295 // Protection
1296 if ($this->status == self::STATUS_DISPOSED) {
1297 return 0;
1298 }
1299
1300 $this->db->begin();
1301
1302 $required_fields = array('disposal_date', 'disposal_date', 'fk_disposal_type');
1303 foreach ($required_fields as $field) {
1304 $this->fields[$field]['notnull'] = 1;
1305 }
1306 $result = $this->update($user, 1);
1307 foreach ($required_fields as $field) {
1308 $this->fields[$field]['notnull'] = 0;
1309 }
1310 if ($result > 0) {
1311 if ($disposal_invoice_id > 0) {
1312 $this->add_object_linked('facture', $disposal_invoice_id);
1313 }
1314 $result = $this->setStatusCommon($user, self::STATUS_DISPOSED, $notrigger, 'ASSET_DISPOSED');
1315 }
1316 if ($result > 0) {
1317 $result = $this->calculationDepreciation();
1318 }
1319
1320 if ($result < 0) {
1321 $this->db->rollback();
1322 } else {
1323 $this->db->commit();
1324 }
1325
1326 // Define output language
1327 if ($result > 0 && !getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1328 if (method_exists($this, 'generateDocument')) {
1329 global $hidedetails, $hidedesc, $hideref;
1330 $outputlangs = $langs;
1331 $newlang = '';
1332 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
1333 $newlang = GETPOST('lang_id', 'aZ09');
1334 }
1335 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1336 $newlang = $this->thirdparty->default_lang;
1337 }
1338 if (!empty($newlang)) {
1339 $outputlangs = new Translate("", $conf);
1340 $outputlangs->setDefaultLang($newlang);
1341 }
1342 $model = $this->model_pdf;
1343 $ret = $this->fetch($this->id); // Reload to get new records
1344
1345 $this->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
1346 }
1347 }
1348
1349 return $result;
1350 }
1351
1359 public function reopen($user, $notrigger = 0)
1360 {
1361 global $conf, $langs;
1362
1363 // Protection
1364 if ($this->status != self::STATUS_DISPOSED) {
1365 return 0;
1366 }
1367
1368
1369 $this->db->begin();
1370
1371 $this->disposal_date = null;
1372 $this->disposal_amount_ht = null;
1373 $this->fk_disposal_type = null;
1374 $this->disposal_depreciated = 0;
1375 $this->disposal_subject_to_vat = 0;
1376 $result = $this->update($user, 1);
1377 if ($result > 0) {
1378 $this->deleteObjectLinked(null, 'facture');
1379 $result = $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'ASSET_REOPEN');
1380 }
1381 if ($result > 0) {
1382 $result = $this->calculationDepreciation();
1383 }
1384
1385 if ($result < 0) {
1386 $this->db->rollback();
1387 } else {
1388 $this->db->commit();
1389 }
1390
1391 // Define output language
1392 if ($result > 0 && !getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1393 if (method_exists($this, 'generateDocument')) {
1394 global $hidedetails, $hidedesc, $hideref;
1395 $outputlangs = $langs;
1396 $newlang = '';
1397 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
1398 $newlang = GETPOST('lang_id', 'aZ09');
1399 }
1400 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1401 $newlang = $this->thirdparty->default_lang;
1402 }
1403 if (!empty($newlang)) {
1404 $outputlangs = new Translate("", $conf);
1405 $outputlangs->setDefaultLang($newlang);
1406 }
1407 $model = $this->model_pdf;
1408 $ret = $this->fetch($this->id); // Reload to get new records
1409
1410 $this->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
1411 }
1412 }
1413
1414 return $result;
1415 }
1416
1428 public function getNomUrl($withpicto = 0, $option = '', $maxlen = 0, $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1429 {
1430 global $db, $conf, $langs, $hookmanager;
1431 global $dolibarr_main_authentication, $dolibarr_main_demo;
1432 global $menumanager;
1433
1434 if (!empty($conf->dol_no_mouse_hover)) {
1435 $notooltip = 1; // Force disable tooltips
1436 }
1437
1438 $result = '';
1439
1440 $label = img_picto('', $this->picto).' <u>'.$langs->trans("Asset").'</u>';
1441 if (isset($this->status)) {
1442 $label .= ' '.$this->getLibStatut(5);
1443 }
1444 $label .= '<br>';
1445 $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
1446
1447 $url = dol_buildpath('/asset/card.php', 1).'?id='.$this->id;
1448
1449 if ($option != 'nolink') {
1450 // Add param to save lastsearch_values or not
1451 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1452 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1453 $add_save_lastsearch_values = 1;
1454 }
1455 if ($add_save_lastsearch_values) {
1456 $url .= '&save_lastsearch_values=1';
1457 }
1458 }
1459
1460 $linkclose = '';
1461 if (empty($notooltip)) {
1462 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1463 $label = $langs->trans("ShowAsset");
1464 $linkclose .= ' alt="'.dolPrintHTMLForAttribute($label).'"';
1465 }
1466 $linkclose .= ' title="'.dolPrintHTMLForAttribute($label).'"';
1467 $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
1468 } else {
1469 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1470 }
1471
1472 if ($option == 'nolink') {
1473 $linkstart = '<span';
1474 } else {
1475 $linkstart = '<a href="'.$url.'"';
1476 }
1477 $linkstart .= $linkclose.'>';
1478 if ($option == 'nolink') {
1479 $linkend = '</span>';
1480 } else {
1481 $linkend = '</a>';
1482 }
1483
1484 $result .= $linkstart;
1485
1486 if (empty($this->showphoto_on_popup)) {
1487 if ($withpicto) {
1488 $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);
1489 }
1490 } else {
1491 if ($withpicto) {
1492 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1493
1494 list($class, $module) = explode('@', $this->picto);
1495 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
1496 $filearray = dol_dir_list($upload_dir, "files");
1497 $filename = $filearray[0]['name'];
1498 if (!empty($filename)) {
1499 $pospoint = strpos($filearray[0]['name'], '.');
1500
1501 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
1502 if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
1503 $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref"><img class="photo'.$module.'" alt="No photo" border="0" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$module.'&entity='.$conf->entity.'&file='.urlencode($pathtophoto).'"></div></div>';
1504 } else {
1505 $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photouserphoto userphoto" alt="No photo" border="0" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$module.'&entity='.$conf->entity.'&file='.urlencode($pathtophoto).'"></div>';
1506 }
1507
1508 $result .= '</div>';
1509 } else {
1510 $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);
1511 }
1512 }
1513 }
1514
1515 if ($withpicto != 2) {
1516 $name = $this->ref;
1517 if ($option == 'label') {
1518 $name = $this->label;
1519 } elseif ($option == 'with_label') {
1520 $name .= ' - ' . $this->label;
1521 }
1522 $result .= dol_escape_htmltag($maxlen ? dol_trunc($name, $maxlen) : $name);
1523 }
1524
1525 $result .= $linkend;
1526 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
1527
1528 global $action;
1529 $hookmanager->initHooks(array($this->element . 'dao'));
1530 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1531 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1532 if ($reshook > 0) {
1533 $result = $hookmanager->resPrint;
1534 } else {
1535 $result .= $hookmanager->resPrint;
1536 }
1537 return $result;
1538 }
1539
1546 public function getLabelStatus($mode = 0)
1547 {
1548 return $this->LibStatut((int) $this->status, $mode);
1549 }
1550
1557 public function getLibStatut($mode = 0)
1558 {
1559 return $this->LibStatut((int) $this->status, $mode);
1560 }
1561
1562 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1570 public function LibStatut($status, $mode = 0)
1571 {
1572 // phpcs:enable
1573 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
1574 global $langs;
1575 //$langs->load("assets");
1576 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('AssetInDraft');
1577 $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('AssetInProgress');
1578 $this->labelStatus[self::STATUS_DISPOSED] = $langs->transnoentitiesnoconv('AssetDisposed');
1579 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('AssetInDraft');
1580 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('AssetInProgress');
1581 $this->labelStatusShort[self::STATUS_DISPOSED] = $langs->transnoentitiesnoconv('AssetDisposed');
1582 }
1583
1584 $statusType = 'status'.$status;
1585 if ($status == self::STATUS_VALIDATED) {
1586 $statusType = 'status4';
1587 }
1588 if ($status == self::STATUS_DISPOSED) {
1589 $statusType = 'status6';
1590 }
1591
1592 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
1593 }
1594
1601 public function info($id)
1602 {
1603 $sql = "SELECT rowid, date_creation as datec, tms as datem, date_valid as datev,";
1604 $sql .= " fk_user_creat, fk_user_modif, fk_user_valid";
1605 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t";
1606 $sql .= " WHERE t.rowid = ".((int) $id);
1607
1608 $result = $this->db->query($sql);
1609 if ($result) {
1610 if ($this->db->num_rows($result)) {
1611 $obj = $this->db->fetch_object($result);
1612 $this->id = $obj->rowid;
1613
1614 $this->user_creation_id = $obj->fk_user_creat;
1615 $this->user_modification_id = $obj->fk_user_modif;
1616 $this->user_validation_id = $obj->fk_user_valid;
1617 $this->date_creation = $this->db->jdate($obj->datec);
1618 $this->date_modification = $this->db->jdate($obj->datem);
1619 $this->date_validation = $this->db->jdate($obj->datev);
1620 }
1621
1622 $this->db->free($result);
1623 } else {
1624 dol_print_error($this->db);
1625 }
1626 }
1627
1634 public function initAsSpecimen()
1635 {
1636 // Set here init that are not commonf fields
1637 // $this->property1 = ...
1638 // $this->property2 = ...
1639
1640 return $this->initAsSpecimenCommon();
1641 }
1642
1648 public function getNextNumRef()
1649 {
1650 global $langs, $conf;
1651 $langs->load("assets");
1652
1653 if (!getDolGlobalString('ASSET_ASSET_ADDON')) {
1654 $conf->global->ASSET_ASSET_ADDON = 'mod_asset_standard';
1655 }
1656
1657 if (getDolGlobalString('ASSET_ASSET_ADDON')) {
1658 $mybool = false;
1659
1660 $file = getDolGlobalString('ASSET_ASSET_ADDON') . ".php";
1661 $classname = getDolGlobalString('ASSET_ASSET_ADDON');
1662
1663 // Include file with class
1664 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1665 foreach ($dirmodels as $reldir) {
1666 $dir = dol_buildpath($reldir."core/modules/asset/");
1667
1668 // Load file with numbering class (if found)
1669 $mybool = ((bool) @include_once $dir.$file) || $mybool;
1670 }
1671
1672 if (!$mybool) {
1673 dol_print_error(null, "Failed to include file ".$file);
1674 return '';
1675 }
1676
1677 if (class_exists($classname)) {
1678 $obj = new $classname();
1679
1680 '@phan-var-force ModeleNumRefAsset $obj';
1683 $numref = $obj->getNextValue($this);
1684
1685 if ($numref != '' && $numref != '-1') {
1686 return $numref;
1687 } else {
1688 $this->error = $obj->error;
1689 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1690 return "";
1691 }
1692 } else {
1693 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1694 return "";
1695 }
1696 } else {
1697 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1698 return "";
1699 }
1700 }
1701
1709 public function validate($user, $notrigger = 0)
1710 {
1711 global $conf;
1712
1713 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1714
1715 $error = 0;
1716
1717 // Protection
1718 if ($this->status == self::STATUS_VALIDATED) {
1719 dol_syslog(get_class($this)."::validate action abandoned: already validated", LOG_WARNING);
1720 return 0;
1721 }
1722
1723 $now = dol_now();
1724
1725 $this->db->begin();
1726
1727 // Define new ref
1728 if (/* !$error && */ (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
1729 $num = $this->getNextNumRef();
1730 } else {
1731 $num = (string) $this->ref;
1732 }
1733 $this->newref = dol_sanitizeFileName($num);
1734
1735 // Validate
1736 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
1737 $sql .= " SET ref = '".$this->db->escape($num)."',";
1738 $sql .= " status = ".self::STATUS_VALIDATED.",";
1739 $sql .= " date_valid='".$this->db->idate($now)."',";
1740 $sql .= " fk_user_valid = ".((int) $user->id);
1741 $sql .= " WHERE rowid = ".((int) $this->id);
1742
1743 dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
1744 $resql = $this->db->query($sql);
1745 if (!$resql) {
1746 dol_print_error($this->db);
1747 $this->error = $this->db->lasterror();
1748 $error++;
1749 }
1750
1751 if (!$error && !$notrigger) {
1752 // Call trigger
1753 $result = $this->call_trigger('ASSET_VALIDATE', $user);
1754 if ($result < 0) {
1755 $error++;
1756 }
1757 // End call triggers
1758 }
1759
1760 if (!$error) {
1761 $this->oldref = $this->ref;
1762
1763 // Rename directory if dir was a temporary ref
1764 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
1765 // Now we rename also files into index
1766 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'asset/".$this->db->escape($this->newref)."'";
1767 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'asset/".$this->db->escape($this->ref)."' and entity = ".((int) $conf->entity);
1768 $resql = $this->db->query($sql);
1769 if (!$resql) {
1770 $error++;
1771 $this->error = $this->db->lasterror();
1772 }
1773 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'asset/".$this->db->escape($this->newref)."'";
1774 $sql .= " WHERE filepath = 'asset/".$this->db->escape($this->ref)."' and entity = ".((int) $conf->entity);
1775 $resql = $this->db->query($sql);
1776 if (!$resql) {
1777 $error++;
1778 $this->error = $this->db->lasterror();
1779 }
1780
1781 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
1782 $oldref = dol_sanitizeFileName($this->ref);
1783 $newref = dol_sanitizeFileName($num);
1784 $dirsource = $conf->asset->dir_output.'/'.$oldref;
1785 $dirdest = $conf->asset->dir_output.'/'.$newref;
1786 if (!$error && file_exists($dirsource)) {
1787 dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
1788
1789 if (@rename($dirsource, $dirdest)) {
1790 dol_syslog("Rename ok");
1791 // Rename docs starting with $oldref with $newref
1792 $listoffiles = dol_dir_list($conf->asset->dir_output.'/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
1793 foreach ($listoffiles as $fileentry) {
1794 $dirsource = $fileentry['name'];
1795 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
1796 $dirsource = $fileentry['path'].'/'.$dirsource;
1797 $dirdest = $fileentry['path'].'/'.$dirdest;
1798 @rename($dirsource, $dirdest);
1799 }
1800 }
1801 }
1802 }
1803 }
1804
1805 // Set new ref and current status
1806 if (!$error) {
1807 $this->ref = $num;
1808 $this->status = self::STATUS_VALIDATED;
1809 }
1810
1811 if (!$error) {
1812 $this->db->commit();
1813 return 1;
1814 } else {
1815 $this->db->rollback();
1816 return -1;
1817 }
1818 }
1819
1827 public function setDraft($user, $notrigger = 0)
1828 {
1829 // Protection
1830 if ($this->status <= self::STATUS_DRAFT) {
1831 return 0;
1832 }
1833
1834 return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'ASSET_UNVALIDATE');
1835 }
1836}
getCurrentPeriodOfFiscalYear($db, $conf, $from_time=null, $gm='tzserver', $withenddateonly=1)
Get current period of fiscal year?
getNextFiscalYear($db, $after_date, $gm='tzserver')
Get next fiscal year period after a given date.
$object ref
Definition info.php:90
Class for AssetAccountancyCodes.
Class for AssetDepreciationOptions.
Class for Asset.
getNomUrl($withpicto=0, $option='', $maxlen=0, $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Return a link to the object card (with optionally the picto)
hasDepreciationLinesInBookkeeping()
If has depreciation lines in bookkeeping.
setDraft($user, $notrigger=0)
Set draft status.
dispose($user, $disposal_invoice_id, $notrigger=0)
Set dispose status.
validate($user, $notrigger=0)
Validate asset.
createFromClone(User $user, $fromid)
Clone an object into another one.
calculationDepreciation()
Calculation depreciation lines (reversal and future) for each mode.
__construct(DoliDB $db)
Constructor.
create(User $user, $notrigger=0)
Create object into database.
info($id)
Load the info information in the object.
getLabelStatus($mode=0)
Return the label of the status.
fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, $filter='', $filtermode='AND')
Load list of objects in memory from the database.
fetch($id, $ref=null)
Load object in memory from the database.
LibStatut($status, $mode=0)
Return the status.
reopen($user, $notrigger=0)
Set back to validated status if disposed status.
getLibStatut($mode=0)
Return the label of the status.
initAsSpecimen()
Initialise object with example values Id must be 0 if object instance is a specimen.
addDepreciationLine($mode, $ref, $depreciation_date, $depreciation_ht, $cumulative_depreciation_ht, $accountancy_code_debit, $accountancy_code_credit)
Add depreciation line for a mode.
fetchDepreciationLines()
Fetch depreciation lines for each mode in $this->depreciation_lines (sort by depreciation date)
setLastCumulativeDepreciation($asset_depreciation_id)
Set last cumulative depreciation for each mode.
update(User $user, $notrigger=0)
Update object into database.
setDataFromAssetModel(User $user, $notrigger=0)
Set asset model.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
add_object_linked($origin=null, $origin_id=null, $f_user=null, $notrigger=0)
Add an object link into llx_element_element.
deleteObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $rowid=0, $f_user=null, $notrigger=0)
Delete all links between an object $this.
createCommon(User $user, $notrigger=0)
Create object in the database.
getFieldList($alias='', $excludefields=array())
Function to concat keys of fields.
updateCommon(User $user, $notrigger=0)
Update object into database.
setStatusCommon($user, $status, $notrigger=0, $triggercode='')
Set to a status.
initAsSpecimenCommon()
Initialise object with example values Id must be 0 if object instance is a specimen.
fetchCommon($id, $ref=null, $morewhere='', $noextrafields=0)
Load object in memory from the database.
deleteCommon(User $user, $notrigger=0, $forcechilddeletion=0)
Delete object in database.
Class to manage Dolibarr database access.
Class to manage translations.
Class to manage Dolibarr users.
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition index.php:169
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition date.lib.php:605
num_between_day($timestampStart, $timestampEnd, $lastday=0)
Function to return number of days between two dates (date must be UTC date !) Example: 2012-01-01 201...
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:126
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:624
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition files.lib.php:64
dol_now($mode='gmt')
Return date for now.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0, $forbiddenfields=array())
forgeSQLFromUniversalSearchCriteria
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '...' if string larger than length.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php