dolibarr 21.0.0-alpha
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-2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
4 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
5 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
27require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
28
32class Asset extends CommonObject
33{
37 public $module = 'asset';
38
42 public $element = 'asset';
43
47 public $table_element = 'asset';
48
52 public $picto = 'asset';
53
54 const STATUS_DRAFT = 0; // In progress
55 const STATUS_DISPOSED = 9; // Disposed
56
88 public $fields = array(
89 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => "Id"),
90 'ref' => array('type' => 'varchar(128)', 'label' => 'Ref', 'enabled' => 1, 'position' => 20, 'notnull' => 1, 'visible' => 1, 'noteditable' => 0, 'index' => 1, 'searchall' => 1, 'showoncombobox' => 1, 'validate' => 1, 'comment' => "Reference of object"),
91 'label' => array('type' => 'varchar(255)', 'label' => 'Label', 'enabled' => 1, 'position' => 30, 'notnull' => 1, 'visible' => 1, 'searchall' => 1, 'css' => 'minwidth300', 'cssview' => 'wordbreak', 'showoncombobox' => '2', 'validate' => 1,),
92 '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,),
93 'qty' => array('type' => 'real', 'label' => 'Qty', 'enabled' => 1, 'position' => 50, 'notnull' => 1, 'visible' => 0, 'default' => '1', 'isameasure' => 1, 'css' => 'maxwidth75imp', 'validate' => 1,),
94 'acquisition_type' => array('type' => 'smallint', 'label' => 'AssetAcquisitionType', 'enabled' => 1, 'position' => 60, 'notnull' => 1, 'visible' => 1, 'arrayofkeyval' => array('0' => 'AssetAcquisitionTypeNew', '1' => 'AssetAcquisitionTypeOccasion'), 'validate' => 1,),
95 '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,),
96 'not_depreciated' => array('type' => 'boolean', 'label' => 'AssetNotDepreciated', 'enabled' => 1, 'position' => 80, 'notnull' => 0, 'default' => '0', 'visible' => 1, 'validate' => 1,),
97 'date_acquisition' => array('type' => 'date', 'label' => 'AssetDateAcquisition', 'enabled' => 1, 'position' => 90, 'notnull' => 1, 'visible' => 1,),
98 'date_start' => array('type' => 'date', 'label' => 'AssetDateStart', 'enabled' => 1, 'position' => 100, 'notnull' => 0, 'visible' => -1,),
99 'acquisition_value_ht' => array('type' => 'price', 'label' => 'AssetAcquisitionValueHT', 'enabled' => 1, 'position' => 110, 'notnull' => 1, 'visible' => 1, 'isameasure' => 1, 'validate' => 1,),
100 'recovered_vat' => array('type' => 'price', 'label' => 'AssetRecoveredVAT', 'enabled' => 1, 'position' => 120, 'notnull' => 0, 'visible' => 1, 'isameasure' => 1, 'validate' => 1,),
101 'reversal_date' => array('type' => 'date', 'label' => 'AssetReversalDate', 'enabled' => 1, 'position' => 130, 'notnull' => 0, 'visible' => 1,),
102 'reversal_amount_ht' => array('type' => 'price', 'label' => 'AssetReversalAmountHT', 'enabled' => 1, 'position' => 140, 'notnull' => 0, 'visible' => 1, 'isameasure' => 1, 'validate' => 1,),
103 'disposal_date' => array('type' => 'date', 'label' => 'AssetDisposalDate', 'enabled' => 1, 'position' => 200, 'notnull' => 0, 'visible' => -2,),
104 'disposal_amount_ht' => array('type' => 'price', 'label' => 'AssetDisposalAmount', 'enabled' => 1, 'position' => 210, 'notnull' => 0, 'visible' => -2, 'default' => '0', 'isameasure' => 1, 'validate' => 1,),
105 '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,),
106 'disposal_depreciated' => array('type' => 'boolean', 'label' => 'AssetDisposalDepreciated', 'enabled' => 1, 'position' => 230, 'notnull' => 0, 'default' => '0', 'visible' => -2, 'validate' => 1,),
107 'disposal_subject_to_vat' => array('type' => 'boolean', 'label' => 'AssetDisposalSubjectToVat', 'enabled' => 1, 'position' => 240, 'notnull' => 0, 'default' => '0', 'visible' => -2, 'validate' => 1,),
108 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'position' => 300, 'notnull' => 0, 'visible' => 0, 'validate' => 1,),
109 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'position' => 301, 'notnull' => 0, 'visible' => 0, 'validate' => 1,),
110 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -2,),
111 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => -2,),
112 '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',),
113 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2,),
114 'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'LastMainDoc', 'enabled' => 1, 'position' => 600, 'notnull' => 0, 'visible' => 0,),
115 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'position' => 1000, 'notnull' => -1, 'visible' => -2,),
116 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'position' => 1010, 'notnull' => -1, 'visible' => 0,),
117 '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,),
118 );
119 public $rowid;
120 public $ref;
121 public $label;
122 public $fk_asset_model;
123 public $reversal_amount_ht;
124 public $acquisition_value_ht;
125 public $recovered_vat;
126 public $reversal_date;
127 public $date_acquisition;
128 public $date_start;
129 public $qty;
130 public $acquisition_type;
131 public $asset_type;
132 public $not_depreciated;
133 public $disposal_date;
134 public $disposal_amount_ht;
135 public $fk_disposal_type;
136 public $disposal_depreciated;
137 public $disposal_subject_to_vat;
138 public $supplier_invoice_id;
139 public $note_public;
140 public $note_private;
141 public $fk_user_creat;
142 public $fk_user_modif;
143 public $last_main_doc;
144 public $import_key;
145 public $model_pdf;
146 public $status;
147
151 public $oldcopy;
152
153
157 public $asset_depreciation_options;
158 public $asset_accountancy_codes;
162 public $depreciation_lines = array();
163
169 public function __construct(DoliDB $db)
170 {
171 global $conf, $langs;
172
173 $this->db = $db;
174
175 $this->ismultientitymanaged = 1;
176 $this->isextrafieldmanaged = 1;
177
178 if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
179 $this->fields['rowid']['visible'] = 0;
180 }
181 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
182 $this->fields['entity']['enabled'] = 0;
183 }
184
185 // Unset fields that are disabled
186 foreach ($this->fields as $key => $val) {
187 if (isset($val['enabled']) && empty($val['enabled'])) {
188 unset($this->fields[$key]);
189 }
190 }
191
192 // Translate some data of arrayofkeyval
193 if (is_object($langs)) {
194 foreach ($this->fields as $key => $val) {
195 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
196 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
197 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
198 }
199 }
200 }
201 }
202 }
203
211 public function create(User $user, $notrigger = 0)
212 {
213 if (!isset($this->date_start) || $this->date_start === "") {
214 $this->date_start = $this->date_acquisition;
215 }
216
217 $this->db->begin();
218
219 $result = $result_create = $this->createCommon($user, $notrigger);
220 if ($result > 0 && $this->fk_asset_model > 0) {
221 $result = $this->setDataFromAssetModel($user, $notrigger);
222 }
223 if ($result > 0) {
224 if ($this->supplier_invoice_id > 0) {
225 $this->add_object_linked('invoice_supplier', $this->supplier_invoice_id);
226 }
227 }
228
229 if ($result < 0) {
230 $this->db->rollback();
231 } else {
232 $this->db->commit();
233 }
234
235 return $result > 0 ? $result_create : $result;
236 }
237
245 public function createFromClone(User $user, $fromid)
246 {
247 global $langs, $extrafields;
248 $error = 0;
249
250 dol_syslog(__METHOD__, LOG_DEBUG);
251
252 // $object = new self($this->db);
253 //
254 // $this->db->begin();
255 //
256 // // Load source object
257 // $result = $object->fetchCommon($fromid);
258 // if ($result > 0 && !empty($object->table_element_line)) {
259 // $object->fetchLines();
260 // }
261 //
262 // // get lines so they will be clone
263 // //foreach($this->lines as $line)
264 // // $line->fetch_optionals();
265 //
266 // // Reset some properties
267 // unset($object->id);
268 // unset($object->fk_user_creat);
269 // unset($object->import_key);
270 //
271 // // Clear fields
272 // if (property_exists($object, 'ref')) {
273 // $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
274 // }
275 // if (property_exists($object, 'label')) {
276 // $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
277 // }
278 // if (property_exists($object, 'status')) {
279 // $object->status = self::STATUS_DRAFT;
280 // }
281 // if (property_exists($object, 'date_creation')) {
282 // $object->date_creation = dol_now();
283 // }
284 // if (property_exists($object, 'date_modification')) {
285 // $object->date_modification = null;
286 // }
287 // // ...
288 // // Clear extrafields that are unique
289 // if (is_array($object->array_options) && count($object->array_options) > 0) {
290 // $extrafields->fetch_name_optionals_label($this->table_element);
291 // foreach ($object->array_options as $key => $option) {
292 // $shortkey = preg_replace('/options_/', '', $key);
293 // if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
294 // //var_dump($key); var_dump($clonedObj->array_options[$key]); exit;
295 // unset($object->array_options[$key]);
296 // }
297 // }
298 // }
299 //
300 // // Create clone
301 // $object->context['createfromclone'] = 'createfromclone';
302 // $result = $object->createCommon($user);
303 // if ($result < 0) {
304 // $error++;
305 // $this->error = $object->error;
306 // $this->errors = $object->errors;
307 // }
308 //
309 // if (!$error) {
310 // // copy internal contacts
311 // if ($this->copy_linked_contact($object, 'internal') < 0) {
312 // $error++;
313 // }
314 // }
315 //
316 // if (!$error) {
317 // // copy external contacts if same company
318 // if (property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) {
319 // if ($this->copy_linked_contact($object, 'external') < 0) {
320 // $error++;
321 // }
322 // }
323 // }
324 //
325 // unset($object->context['createfromclone']);
326 //
327 // // End
328 // if (!$error) {
329 // $this->db->commit();
330 // return $object;
331 // } else {
332 // $this->db->rollback();
333 // return -1;
334 // }
335 return -1;
336 }
337
345 public function fetch($id, $ref = null)
346 {
347 $result = $this->fetchCommon($id, $ref);
348 if ($result > 0) {
349 if (!empty($this->table_element_line)) {
350 $this->fetchLines();
351 }
352
353 $res = $this->hasDepreciationLinesInBookkeeping();
354 if ($res < 0) {
355 return -1;
356 } elseif ($res > 0) {
357 $this->fields['date_acquisition']['noteditable'] = '1';
358 $this->fields['date_start']['noteditable'] = '1';
359 $this->fields['acquisition_value_ht']['noteditable'] = '1';
360 $this->fields['recovered_vat']['noteditable'] = '1';
361 $this->fields['reversal_date']['noteditable'] = '1';
362 $this->fields['reversal_amount_ht']['noteditable'] = '1';
363 }
364 }
365 return $result;
366 }
367
373 public function fetchLines()
374 {
375 $this->lines = array();
376
377 return 1;
378 }
379
380
393 public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
394 {
395 dol_syslog(__METHOD__, LOG_DEBUG);
396
397 $records = array();
398
399 $sql = "SELECT ";
400 $sql .= $this->getFieldList('t');
401 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t";
402 if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
403 $sql .= " WHERE t.entity IN (".getEntity($this->element).")";
404 } else {
405 $sql .= " WHERE 1 = 1";
406 }
407
408 // Manage filter
409 $errormessage = '';
410 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
411 if ($errormessage) {
412 $this->errors[] = $errormessage;
413 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
414
415 return -1;
416 }
417
418 if (!empty($sortfield)) {
419 $sql .= $this->db->order($sortfield, $sortorder);
420 }
421 if (!empty($limit)) {
422 $sql .= $this->db->plimit($limit, $offset);
423 }
424
425 $resql = $this->db->query($sql);
426 if ($resql) {
427 $num = $this->db->num_rows($resql);
428 $i = 0;
429 while ($i < ($limit ? min($limit, $num) : $num)) {
430 $obj = $this->db->fetch_object($resql);
431
432 $record = new self($this->db);
433 $record->setVarsFromFetchObj($obj);
434
435 $records[$record->id] = $record;
436
437 $i++;
438 }
439 $this->db->free($resql);
440
441 return $records;
442 } else {
443 $this->errors[] = 'Error '.$this->db->lasterror();
444 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
445
446 return -1;
447 }
448 }
449
457 public function update(User $user, $notrigger = 0)
458 {
459 if (!isset($this->date_start) || $this->date_start === "") {
460 $this->date_start = $this->date_acquisition;
461 }
462
463 $this->db->begin();
464
465 $result = $this->updateCommon($user, $notrigger);
466 if ($result > 0 && $this->fk_asset_model > 0 && $this->fk_asset_model != $this->oldcopy->fk_asset_model) {
467 $result = $this->setDataFromAssetModel($user, $notrigger);
468 }
469 if ($result > 0 && (
470 $this->date_start != $this->oldcopy->date_start ||
471 $this->acquisition_value_ht != $this->oldcopy->acquisition_value_ht ||
472 $this->reversal_date != $this->oldcopy->reversal_date ||
473 $this->reversal_amount_ht != $this->oldcopy->reversal_amount_ht ||
474 ($this->fk_asset_model > 0 && $this->fk_asset_model != $this->oldcopy->fk_asset_model)
475 )
476 ) {
477 $result = $this->calculationDepreciation();
478 }
479
480 if ($result < 0) {
481 $this->db->rollback();
482 } else {
483 $this->db->commit();
484 }
485
486 return $result;
487 }
488
496 public function delete(User $user, $notrigger = 0)
497 {
498 return $this->deleteCommon($user, $notrigger);
499 //return $this->deleteCommon($user, $notrigger, 1);
500 }
501
509 public function setDataFromAssetModel(User $user, $notrigger = 0)
510 {
511 global $langs;
512 $langs->load('assets');
513
514 // Clean parameters
515 $this->id = $this->id > 0 ? $this->id : 0;
516 $this->fk_asset_model = $this->fk_asset_model > 0 ? $this->fk_asset_model : 0;
517
518 // Check parameters
519 $error = 0;
520 if (empty($this->id)) {
521 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Asset") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')');
522 $error++;
523 }
524 if (empty($this->fk_asset_model)) {
525 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("AssetModel") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')');
526 $error++;
527 }
528 if ($error) {
529 return -1;
530 }
531
532 $this->db->begin();
533
534 // Get depreciation options
535 //---------------------------
536 require_once DOL_DOCUMENT_ROOT . '/asset/class/assetdepreciationoptions.class.php';
537 $options_model = new AssetDepreciationOptions($this->db);
538 $result = $options_model->fetchDeprecationOptions(0, $this->fk_asset_model);
539 if ($result < 0) {
540 $this->error = $options_model->error;
541 $this->errors = $options_model->errors;
542 $error++;
543 } elseif ($result > 0) {
544 $options = new AssetDepreciationOptions($this->db);
545 $result = $options->fetchDeprecationOptions($this->id);
546 if ($result < 0) {
547 $this->error = $options->error;
548 $this->errors = $options->errors;
549 $error++;
550 }
551
552 if (!$error) {
553 foreach ($options_model->deprecation_options as $mode_key => $fields) {
554 foreach ($fields as $field_key => $value) {
555 $options->deprecation_options[$mode_key][$field_key] = $value;
556 }
557 }
558
559 $result = $options->updateDeprecationOptions($user, $this->id, 0, $notrigger);
560 if ($result < 0) {
561 $this->error = $options->error;
562 $this->errors = $options->errors;
563 $error++;
564 }
565 }
566 }
567
568 // Get accountancy codes
569 //---------------------------
570 if (!$error) {
571 require_once DOL_DOCUMENT_ROOT . '/asset/class/assetaccountancycodes.class.php';
572 $accountancy_codes_model = new AssetAccountancyCodes($this->db);
573 $result = $accountancy_codes_model->fetchAccountancyCodes(0, $this->fk_asset_model);
574 if ($result < 0) {
575 $this->error = $accountancy_codes_model->error;
576 $this->errors = $accountancy_codes_model->errors;
577 $error++;
578 } elseif ($result > 0) {
579 $accountancy_codes = new AssetAccountancyCodes($this->db);
580 $result = $accountancy_codes->fetchAccountancyCodes($this->id);
581 if ($result < 0) {
582 $this->error = $accountancy_codes->error;
583 $this->errors = $accountancy_codes->errors;
584 $error++;
585 }
586
587 if (!$error) {
588 foreach ($accountancy_codes_model->accountancy_codes as $mode_key => $fields) {
589 foreach ($fields as $field_key => $value) {
590 $accountancy_codes->accountancy_codes[$mode_key][$field_key] = $value;
591 }
592 }
593
594 $result = $accountancy_codes->updateAccountancyCodes($user, $this->id, 0, $notrigger);
595 if ($result < 0) {
596 $this->error = $accountancy_codes->error;
597 $this->errors = $accountancy_codes->errors;
598 $error++;
599 }
600 }
601 }
602 }
603
604 if ($error) {
605 $this->db->rollback();
606 return -1;
607 } else {
608 $this->db->commit();
609 return 1;
610 }
611 }
612
618 public function fetchDepreciationLines()
619 {
620 global $langs;
621 $langs->load('assets');
622 $this->depreciation_lines = array();
623
624 // Clean parameters
625 $this->id = $this->id > 0 ? $this->id : 0;
626
627 // Check parameters
628 $error = 0;
629 if (empty($this->id)) {
630 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Asset") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')');
631 $error++;
632 }
633 if ($error) {
634 return -1;
635 }
636
637 // Old request with 'WITH'
638 /*
639 $sql = "WITH in_accounting_bookkeeping(fk_docdet) AS (";
640 $sql .= " SELECT DISTINCT fk_docdet";
641 $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping";
642 $sql .= " WHERE doc_type = 'asset'";
643 $sql .= ")";
644 $sql .= "SELECT ad.rowid, ad.depreciation_mode, ad.ref, ad.depreciation_date, ad.depreciation_ht, ad.cumulative_depreciation_ht";
645 $sql .= ", " . $this->db->ifsql('iab.fk_docdet IS NOT NULL', 1, 0) . " AS bookkeeping";
646 $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation AS ad";
647 $sql .= " LEFT JOIN in_accounting_bookkeeping as iab ON iab.fk_docdet = ad.rowid";
648 $sql .= " WHERE ad.fk_asset = " . (int) $this->id;
649 $sql .= " ORDER BY ad.depreciation_date ASC";
650 */
651
652 $sql = "SELECT ad.rowid, ad.depreciation_mode, ad.ref, ad.depreciation_date, ad.depreciation_ht, ad.cumulative_depreciation_ht";
653 $sql .= ", " . $this->db->ifsql('iab.fk_docdet IS NOT NULL', 1, 0) . " AS bookkeeping";
654 $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation AS ad";
655 $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";
656 $sql .= " WHERE ad.fk_asset = " . (int) $this->id;
657 $sql .= " ORDER BY ad.depreciation_date ASC";
658
659 $resql = $this->db->query($sql);
660 if (!$resql) {
661 $this->errors[] = $langs->trans('AssetErrorFetchDepreciationLines') . ': ' . $this->db->lasterror();
662 return -1;
663 }
664
665 while ($obj = $this->db->fetch_object($resql)) {
666 if (!isset($this->depreciation_lines[$obj->depreciation_mode])) {
667 $this->depreciation_lines[$obj->depreciation_mode] = array();
668 }
669 $this->depreciation_lines[$obj->depreciation_mode][] = array(
670 'id' => $obj->rowid,
671 'ref' => $obj->ref,
672 'depreciation_date' => $this->db->jdate($obj->depreciation_date),
673 'depreciation_ht' => $obj->depreciation_ht,
674 'cumulative_depreciation_ht' => $obj->cumulative_depreciation_ht,
675 'bookkeeping' => $obj->bookkeeping,
676 );
677 }
678
679 return 1;
680 }
681
688 {
689 global $langs;
690 $langs->load('assets');
691
692 // Clean parameters
693 $this->id = $this->id > 0 ? $this->id : 0;
694
695 // Check parameters
696 $error = 0;
697 if (empty($this->id)) {
698 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Asset") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')');
699 $error++;
700 }
701 if ($error) {
702 return -1;
703 }
704
705 // Old request with 'WITH'
706 /*
707 $sql = "WITH in_accounting_bookkeeping(fk_docdet) AS (";
708 $sql .= " SELECT DISTINCT fk_docdet";
709 $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping";
710 $sql .= " WHERE doc_type = 'asset'";
711 $sql .= ")";
712 $sql .= "SELECT COUNT(*) AS has_bookkeeping";
713 $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation AS ad";
714 $sql .= " LEFT JOIN in_accounting_bookkeeping as iab ON iab.fk_docdet = ad.rowid";
715 $sql .= " WHERE ad.fk_asset = " . (int) $this->id;
716 $sql .= " AND iab.fk_docdet IS NOT NULL";
717 */
718
719 $sql = "SELECT COUNT(*) AS has_bookkeeping";
720 $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation AS ad";
721 $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";
722 $sql .= " WHERE ad.fk_asset = " . (int) $this->id;
723 $sql .= " AND iab.fk_docdet IS NOT NULL";
724
725 $resql = $this->db->query($sql);
726 if (!$resql) {
727 $this->errors[] = $langs->trans('AssetErrorFetchDepreciationLines') . ': ' . $this->db->lasterror();
728 return -1;
729 }
730
731 if ($obj = $this->db->fetch_object($resql)) {
732 return $obj->has_bookkeeping > 0 ? 1 : 0;
733 }
734
735 return 0;
736 }
737
750 public function addDepreciationLine($mode, $ref, $depreciation_date, $depreciation_ht, $cumulative_depreciation_ht, $accountancy_code_debit, $accountancy_code_credit)
751 {
752 global $langs;
753 $langs->load('assets');
754
755 // Clean parameters
756 $this->id = $this->id > 0 ? $this->id : 0;
757 $mode = strtolower(trim($mode));
758 $ref = trim($ref);
759 $accountancy_code_debit = trim($accountancy_code_debit);
760 $accountancy_code_credit = trim($accountancy_code_credit);
761
762 // Check parameters
763 $error = 0;
764 if (empty($this->id)) {
765 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Asset") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')');
766 $error++;
767 }
768 if ($error) {
769 return -1;
770 }
771
772 $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)";
773 $sql .= " VALUES ( ";
774 $sql .= " " . (int) $this->id;
775 $sql .= ", '" . $this->db->escape($mode) . "'";
776 $sql .= ", '" . $this->db->escape($ref) . "'";
777 $sql .= ", '" . $this->db->idate($depreciation_date) . "'";
778 $sql .= ", " . (float) $depreciation_ht;
779 $sql .= ", " . (float) $cumulative_depreciation_ht;
780 $sql .= ", '" . $this->db->escape($accountancy_code_debit) . "'";
781 $sql .= ", '" . $this->db->escape($accountancy_code_credit) . "'";
782 $sql .= ")";
783
784 $resql = $this->db->query($sql);
785 if (!$resql) {
786 $this->errors[] = $langs->trans('AssetErrorAddDepreciationLine') . ': ' . $this->db->lasterror();
787 return -1;
788 }
789
790 return 1;
791 }
792
798 public function calculationDepreciation()
799 {
800 global $conf, $langs;
801 $langs->load('assets');
802
803 // Clean parameters
804 $this->id = $this->id > 0 ? $this->id : 0;
805
806 // Check parameters
807 $error = 0;
808 if (empty($this->id)) {
809 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Asset") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')');
810 $error++;
811 }
812 if ($error) {
813 return -1;
814 }
815
816 // Get depreciation options
817 //---------------------------
818 require_once DOL_DOCUMENT_ROOT . '/asset/class/assetdepreciationoptions.class.php';
819 $options = new AssetDepreciationOptions($this->db);
820 $result = $options->fetchDeprecationOptions($this->id);
821 if ($result < 0) {
822 $this->error = $options->error;
823 $this->errors = $options->errors;
824 return -1;
825 }
826
827 // Get accountancy codes
828 //---------------------------
829 require_once DOL_DOCUMENT_ROOT . '/asset/class/assetaccountancycodes.class.php';
830 $accountancy_codes = new AssetAccountancyCodes($this->db);
831 $result = $accountancy_codes->fetchAccountancyCodes($this->id);
832 if ($result < 0) {
833 $this->error = $accountancy_codes->error;
834 $this->errors = $accountancy_codes->errors;
835 return -1;
836 }
837
838 $this->db->begin();
839
840 // Delete old lines
841 $modes = array();
842 foreach ($options->deprecation_options as $mode_key => $fields) {
843 $modes[$mode_key] = $this->db->escape($mode_key);
844 }
845 $sql = "DELETE FROM " . MAIN_DB_PREFIX . "asset_depreciation";
846 $sql .= " WHERE fk_asset = " . (int) $this->id;
847 $sql .= " AND depreciation_mode NOT IN ('" . $this->db->sanitize(implode("', '", $modes)) . "')";
848
849 $resql = $this->db->query($sql);
850 if (!$resql) {
851 $this->errors[] = $langs->trans('AssetErrorClearDepreciationLines') . ': ' . $this->db->lasterror();
852 $error++;
853 }
854
855 if (!$error) {
856 // Get fiscal period
857 require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
858 require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php';
859 $dates = getCurrentPeriodOfFiscalYear($this->db, $conf, $this->date_start > $this->date_acquisition ? $this->date_start : $this->date_acquisition);
860 $init_fiscal_period_start = $dates['date_start'];
861 $init_fiscal_period_end = $dates['date_end'];
862 if (empty($init_fiscal_period_start) || empty($init_fiscal_period_end)) {
863 $pastmonthyear = $dates['pastmonthyear'];
864 $pastmonth = $dates['pastmonth'];
865 $init_fiscal_period_start = dol_get_first_day($pastmonthyear, $pastmonth, false);
866 $init_fiscal_period_end = dol_get_last_day($pastmonthyear, $pastmonth, false);
867 }
868
869 foreach ($options->deprecation_options as $mode_key => $fields) {
870 // Get last depreciation lines save in bookkeeping
871 //-----------------------------------------------------
872
873 // Old request with 'WITH'
874 /*
875 $sql = "WITH in_accounting_bookkeeping(fk_docdet) AS (";
876 $sql .= " SELECT fk_docdet";
877 $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping";
878 $sql .= " WHERE doc_type = 'asset'";
879 $sql .= ")";
880 $sql .= "SELECT ad.depreciation_date, ad.cumulative_depreciation_ht";
881 $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation AS ad";
882 $sql .= " LEFT JOIN in_accounting_bookkeeping as iab ON iab.fk_docdet = ad.rowid";
883 $sql .= " WHERE ad.fk_asset = " . (int) $this->id;
884 $sql .= " AND ad.depreciation_mode = '" . $this->db->escape($mode_key) . "'";
885 $sql .= " AND iab.fk_docdet IS NOT NULL";
886 $sql .= " ORDER BY ad.depreciation_date DESC";
887 $sql .= " LIMIT 1";
888 */
889
890 $sql = "SELECT ad.depreciation_date, ad.cumulative_depreciation_ht";
891 $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation AS ad";
892 $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";
893 $sql .= " WHERE ad.fk_asset = " . (int) $this->id;
894 $sql .= " AND ad.depreciation_mode = '" . $this->db->escape($mode_key) . "'";
895 $sql .= " AND iab.fk_docdet IS NOT NULL";
896 $sql .= " ORDER BY ad.depreciation_date DESC";
897 $sql .= " LIMIT 1";
898
899 $resql = $this->db->query($sql);
900 if (!$resql) {
901 $this->errors[] = $langs->trans('AssetErrorFetchMaxDepreciationDateForMode', $mode_key) . ': ' . $this->db->lasterror();
902 $error++;
903 break;
904 }
905 $last_depreciation_date = '';
906 $last_cumulative_depreciation_ht = $this->reversal_amount_ht;
907 if ($obj = $this->db->fetch_object($resql)) {
908 $last_depreciation_date = $this->db->jdate($obj->depreciation_date);
909 $last_cumulative_depreciation_ht = $obj->cumulative_depreciation_ht;
910 }
911
912 // Set last cumulative depreciation
913 $sql = "UPDATE " . MAIN_DB_PREFIX . $options->deprecation_options_fields[$mode_key]['table'];
914 $sql .= " SET total_amount_last_depreciation_ht = " . (empty($last_cumulative_depreciation_ht) ? 0 : $last_cumulative_depreciation_ht);
915 $sql .= " WHERE fk_asset = " . (int) $this->id;
916 $resql = $this->db->query($sql);
917 if (!$resql) {
918 $this->errors[] = $langs->trans('AssetErrorSetLastCumulativeDepreciation') . ': ' . $this->db->lasterror();
919 $error++;
920 break;
921 }
922
923 // Delete old lines
924 $sql = "DELETE " . MAIN_DB_PREFIX . "asset_depreciation FROM " . MAIN_DB_PREFIX . "asset_depreciation";
925 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_bookkeeping as ab ON ab.doc_type = 'asset' AND ab.fk_docdet = " . MAIN_DB_PREFIX . "asset_depreciation.rowid";
926 $sql .= " WHERE " . MAIN_DB_PREFIX . "asset_depreciation.fk_asset = " . (int) $this->id;
927 $sql .= " AND " . MAIN_DB_PREFIX . "asset_depreciation.depreciation_mode = '" . $this->db->escape($mode_key) . "'";
928 $sql .= " AND ab.fk_docdet IS NULL";
929 if ($last_depreciation_date !== "") {
930 $sql .= " AND " . MAIN_DB_PREFIX . "asset_depreciation.ref != ''";
931 }
932 $resql = $this->db->query($sql);
933 if (!$resql) {
934 $this->errors[] = $langs->trans('AssetErrorClearDepreciationLines') . ': ' . $this->db->lasterror();
935 $error++;
936 break;
937 }
938
939 // Get depreciation period
940 $depreciation_date_start = $this->date_start > $this->date_acquisition ? $this->date_start : $this->date_acquisition;
941 $depreciation_date_end = dol_time_plus_duree($depreciation_date_start, $fields['duration'], $fields['duration_type'] == 1 ? 'm' : ($fields['duration_type'] == 2 ? 'd' : 'y'));
942 $depreciation_amount = $fields['amount_base_depreciation_ht'];
943 if ($fields['duration_type'] == 2) { // Daily
944 $fiscal_period_start = $depreciation_date_start;
945 $fiscal_period_end = $depreciation_date_start;
946 } elseif ($fields['duration_type'] == 1) { // Monthly
947 $date_temp = dol_getdate($depreciation_date_start);
948 $fiscal_period_start = dol_get_first_day($date_temp['year'], $date_temp['mon'], false);
949 $fiscal_period_end = dol_get_last_day($date_temp['year'], $date_temp['mon'], false);
950 } else { // Annually
951 $fiscal_period_start = $init_fiscal_period_start;
952 $fiscal_period_end = $init_fiscal_period_end;
953 }
954 $cumulative_depreciation_ht = $last_cumulative_depreciation_ht;
955 $depreciation_period_amount = $depreciation_amount - $this->reversal_amount_ht;
956 $start_date = $depreciation_date_start;
957 $disposal_date = isset($this->disposal_date) && $this->disposal_date !== "" ? $this->disposal_date : "";
958 $finish_date = $disposal_date !== "" ? $disposal_date : $depreciation_date_end;
959 $accountancy_code_depreciation_debit_key = $accountancy_codes->accountancy_codes_fields[$mode_key]['depreciation_debit'];
960 $accountancy_code_depreciation_debit = $accountancy_codes->accountancy_codes[$mode_key][$accountancy_code_depreciation_debit_key];
961 $accountancy_code_depreciation_credit_key = $accountancy_codes->accountancy_codes_fields[$mode_key]['depreciation_credit'];
962 $accountancy_code_credit = $accountancy_codes->accountancy_codes[$mode_key][$accountancy_code_depreciation_credit_key];
963
964 // Reversal depreciation line
965 //-----------------------------------------------------
966 if ($last_depreciation_date === "" && ($depreciation_date_start < $fiscal_period_start || is_numeric($this->reversal_date))) {
967 if (is_numeric($this->reversal_date)) {
968 if ($this->reversal_date < $fiscal_period_start) {
969 $this->errors[] = $langs->trans('AssetErrorReversalDateNotGreaterThanCurrentBeginFiscalDateForMode', $mode_key);
970 $error++;
971 break;
972 }
973
974 if (empty($this->reversal_amount_ht)) {
975 $this->errors[] = $langs->trans('AssetErrorReversalAmountNotProvidedForMode', $mode_key);
976 $error++;
977 break;
978 }
979
980 $start_date = $this->reversal_date;
981 $result = $this->addDepreciationLine($mode_key, '', $start_date, $this->reversal_amount_ht, $this->reversal_amount_ht, $accountancy_code_depreciation_debit, $accountancy_code_credit);
982 if ($result < 0) {
983 $error++;
984 break;
985 }
986 } else {
987 $this->errors[] = $langs->trans('AssetErrorReversalDateNotProvidedForMode', $mode_key);
988 $error++;
989 break;
990 }
991 }
992
993 // futures depreciation lines
994 //-----------------------------------------------------
995 $nb_days_in_year = getDolGlobalInt('ASSET_DEPRECIATION_DURATION_PER_YEAR', 360);
996 $nb_days_in_month = getDolGlobalInt('ASSET_DEPRECIATION_DURATION_PER_MONTH', 30);
997 $period_amount = (float) price2num($depreciation_period_amount / $fields['duration'], 'MT');
998 $first_period_found = false;
999 // TODO fix declaration of $begin_period
1000 $first_period_date = isset($begin_period) && $begin_period > $fiscal_period_start ? $begin_period : $fiscal_period_start;
1001
1002 $ref_date_format = "%Y" . ($fields['duration_type'] == 1 || $fields['duration_type'] == 2 ? '-%m' : '') . ($fields['duration_type'] == 2 ? '-%d' : '');
1003
1004 // Loop security
1005 $idx_loop = 0;
1006 $max_loop = $fields['duration'] + 2;
1007 do {
1008 // Loop security
1009 $idx_loop++;
1010 if ($idx_loop > $max_loop) {
1011 break;
1012 }
1013
1014 if ($last_depreciation_date < $fiscal_period_end && ($first_period_date <= $start_date || $first_period_found)) {
1015 // Disposal not depreciated
1016 if ($fiscal_period_start <= $disposal_date && $disposal_date <= $fiscal_period_end && empty($this->disposal_depreciated)) {
1017 break;
1018 }
1019
1020 $first_period_found = true;
1021
1022 $period_begin = dol_print_date($fiscal_period_start, $ref_date_format);
1023 $period_end = dol_print_date($fiscal_period_end, $ref_date_format);
1024 $ref = $period_begin . ($period_begin != $period_end ? ' - ' . $period_end : '');
1025 if ($fiscal_period_start <= $disposal_date && $disposal_date <= $fiscal_period_end) {
1026 $ref .= ' - ' . $langs->transnoentitiesnoconv('AssetDisposal');
1027 }
1028
1029 $begin_date = $fiscal_period_start < $start_date && $start_date <= $fiscal_period_end ? $start_date : $fiscal_period_start;
1030 $end_date = $fiscal_period_start < $finish_date && $finish_date <= $fiscal_period_end ? $finish_date : $fiscal_period_end;
1031 if ($fields['duration_type'] == 2) { // Daily
1032 $depreciation_ht = $period_amount;
1033 } elseif ($fields['duration_type'] == 1) { // Monthly
1034 $nb_days = min($nb_days_in_month, num_between_day($begin_date, $end_date, 1));
1035 if ($nb_days >= 28) {
1036 $date_temp = dol_getdate($begin_date);
1037 if ($date_temp['mon'] == 2) {
1038 $nb_days = 30;
1039 }
1040 }
1041 $depreciation_ht = (float) price2num($period_amount * $nb_days / $nb_days_in_month, 'MT');
1042 } else { // Annually
1043 $nb_days = min($nb_days_in_year, num_between_day($begin_date, $end_date, 1));
1044 $depreciation_ht = (float) price2num($period_amount * $nb_days / $nb_days_in_year, 'MT');
1045 }
1046
1047 if ($fiscal_period_start <= $depreciation_date_end && $depreciation_date_end <= $fiscal_period_end) { // last period
1048 $depreciation_ht = (float) price2num($depreciation_amount - $cumulative_depreciation_ht, 'MT');
1049 $cumulative_depreciation_ht = $depreciation_amount;
1050 } else {
1051 $cumulative_depreciation_ht += $depreciation_ht;
1052 }
1053
1054 $result = $this->addDepreciationLine($mode_key, $ref, $fiscal_period_end, $depreciation_ht, $cumulative_depreciation_ht, $accountancy_code_depreciation_debit, $accountancy_code_credit);
1055 if ($result < 0) {
1056 $error++;
1057 break;
1058 }
1059 }
1060
1061 // Next fiscal period (+1 day/month/year)
1062 $fiscal_period_start = dol_time_plus_duree($fiscal_period_end, 1, 'd');
1063 if ($fields['duration_type'] == 2) { // Daily
1064 $fiscal_period_end = $fiscal_period_start;
1065 } elseif ($fields['duration_type'] == 1) { // Monthly
1066 $fiscal_period_end = dol_time_plus_duree(dol_time_plus_duree($fiscal_period_start, 1, 'm'), -1, 'd');
1067 } else { // Annually
1068 $fiscal_period_end = dol_time_plus_duree(dol_time_plus_duree($fiscal_period_start, 1, 'y'), -1, 'd');
1069 }
1070 $last_period_date = $disposal_date !== "" && $disposal_date < $depreciation_date_end ? $disposal_date : $depreciation_date_end;
1071 } while ($fiscal_period_start < $last_period_date);
1072
1073 if ($error) {
1074 break;
1075 }
1076 }
1077 }
1078
1079 if ($error) {
1080 $this->db->rollback();
1081 return -1;
1082 } else {
1083 $this->db->commit();
1084 return 1;
1085 }
1086 }
1087
1094 public function setLastCumulativeDepreciation($asset_depreciation_id)
1095 {
1096 global $langs;
1097 $langs->load('assets');
1098
1099 // Clean parameters
1100 $asset_depreciation_id = $asset_depreciation_id > 0 ? $asset_depreciation_id : 0;
1101
1102 // Check parameters
1103 $error = 0;
1104 if (empty($asset_depreciation_id)) {
1105 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("AssetDepreciation") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')');
1106 $error++;
1107 }
1108 if ($error) {
1109 return -1;
1110 }
1111
1112 $this->db->begin();
1113
1114 require_once DOL_DOCUMENT_ROOT . '/asset/class/assetdepreciationoptions.class.php';
1115 $options = new AssetDepreciationOptions($this->db);
1116
1117 // Get last depreciation lines save in bookkeeping
1118 //-----------------------------------------------------
1119 $sql = "SELECT fk_asset, depreciation_mode, cumulative_depreciation_ht";
1120 $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation";
1121 $sql .= " WHERE rowid = " . (int) $asset_depreciation_id;
1122 $resql = $this->db->query($sql);
1123 if (!$resql) {
1124 $this->errors[] = $langs->trans('AssetErrorFetchCumulativeDepreciation') . ': ' . $this->db->lasterror();
1125 $error++;
1126 } else {
1127 if ($obj = $this->db->fetch_object($resql)) {
1128 $mode_key = $obj->depreciation_mode;
1129 if (!empty($options->deprecation_options_fields[$mode_key])) {
1130 $sql = "UPDATE " . MAIN_DB_PREFIX . $options->deprecation_options_fields[$mode_key]['table'];
1131 $sql .= " SET total_amount_last_depreciation_ht = " . $obj->cumulative_depreciation_ht;
1132 $sql .= " WHERE fk_asset = " . (int) $obj->fk_asset;
1133 $resql = $this->db->query($sql);
1134 if (!$resql) {
1135 $this->errors[] = $langs->trans('AssetErrorSetLastCumulativeDepreciation') . ': ' . $this->db->lasterror();
1136 $error++;
1137 }
1138 }
1139 }
1140 }
1141
1142 if ($error) {
1143 $this->db->rollback();
1144 return -1;
1145 } else {
1146 $this->db->commit();
1147 return 1;
1148 }
1149 }
1150
1159 public function dispose($user, $disposal_invoice_id, $notrigger = 0)
1160 {
1161 global $conf, $langs;
1162
1163 // Protection
1164 if ($this->status != self::STATUS_DRAFT || $this->status == self::STATUS_DISPOSED) {
1165 return 0;
1166 }
1167
1168 $this->db->begin();
1169
1170 $required_fields = array('disposal_date', 'disposal_date', 'fk_disposal_type');
1171 foreach ($required_fields as $field) {
1172 $this->fields[$field]['notnull'] = 1;
1173 }
1174 $result = $this->update($user, 1);
1175 foreach ($required_fields as $field) {
1176 $this->fields[$field]['notnull'] = 0;
1177 }
1178 if ($result > 0) {
1179 if ($disposal_invoice_id > 0) {
1180 $this->add_object_linked('facture', $disposal_invoice_id);
1181 }
1182 $result = $this->setStatusCommon($user, self::STATUS_DISPOSED, $notrigger, 'ASSET_DISPOSED');
1183 }
1184 if ($result > 0) {
1185 $result = $this->calculationDepreciation();
1186 }
1187
1188 if ($result < 0) {
1189 $this->db->rollback();
1190 } else {
1191 $this->db->commit();
1192 }
1193
1194 // Define output language
1195 if ($result > 0 && !getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1196 if (method_exists($this, 'generateDocument')) {
1197 global $hidedetails, $hidedesc, $hideref;
1198 $outputlangs = $langs;
1199 $newlang = '';
1200 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
1201 $newlang = GETPOST('lang_id', 'aZ09');
1202 }
1203 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1204 $newlang = $this->thirdparty->default_lang;
1205 }
1206 if (!empty($newlang)) {
1207 $outputlangs = new Translate("", $conf);
1208 $outputlangs->setDefaultLang($newlang);
1209 }
1210 $model = $this->model_pdf;
1211 $ret = $this->fetch($this->id); // Reload to get new records
1212
1213 $this->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
1214 }
1215 }
1216
1217 return $result;
1218 }
1219
1227 public function reopen($user, $notrigger = 0)
1228 {
1229 global $conf, $langs;
1230
1231 // Protection
1232 if ($this->status != self::STATUS_DISPOSED || $this->status == self::STATUS_DRAFT) {
1233 return 0;
1234 }
1235
1236
1237 $this->db->begin();
1238
1239 $this->disposal_date = null;
1240 $this->disposal_amount_ht = null;
1241 $this->fk_disposal_type = null;
1242 $this->disposal_depreciated = null;
1243 $this->disposal_subject_to_vat = null;
1244 $result = $this->update($user, 1);
1245 if ($result > 0) {
1246 $this->deleteObjectLinked(null, 'facture');
1247 $result = $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'ASSET_REOPEN');
1248 }
1249 if ($result > 0) {
1250 $result = $this->calculationDepreciation();
1251 }
1252
1253 if ($result < 0) {
1254 $this->db->rollback();
1255 } else {
1256 $this->db->commit();
1257 }
1258
1259 // Define output language
1260 if ($result > 0 && !getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1261 if (method_exists($this, 'generateDocument')) {
1262 global $hidedetails, $hidedesc, $hideref;
1263 $outputlangs = $langs;
1264 $newlang = '';
1265 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
1266 $newlang = GETPOST('lang_id', 'aZ09');
1267 }
1268 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1269 $newlang = $this->thirdparty->default_lang;
1270 }
1271 if (!empty($newlang)) {
1272 $outputlangs = new Translate("", $conf);
1273 $outputlangs->setDefaultLang($newlang);
1274 }
1275 $model = $this->model_pdf;
1276 $ret = $this->fetch($this->id); // Reload to get new records
1277
1278 $this->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
1279 }
1280 }
1281
1282 return $result;
1283 }
1284
1296 public function getNomUrl($withpicto = 0, $option = '', $maxlen = 0, $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1297 {
1298 global $db, $conf, $langs, $hookmanager;
1299 global $dolibarr_main_authentication, $dolibarr_main_demo;
1300 global $menumanager;
1301
1302 if (!empty($conf->dol_no_mouse_hover)) {
1303 $notooltip = 1; // Force disable tooltips
1304 }
1305
1306 $result = '';
1307
1308 $label = img_picto('', $this->picto).' <u>'.$langs->trans("Asset").'</u>';
1309 if (isset($this->status)) {
1310 $label .= ' '.$this->getLibStatut(5);
1311 }
1312 $label .= '<br>';
1313 $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
1314
1315 $url = dol_buildpath('/asset/card.php', 1).'?id='.$this->id;
1316
1317 if ($option != 'nolink') {
1318 // Add param to save lastsearch_values or not
1319 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1320 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1321 $add_save_lastsearch_values = 1;
1322 }
1323 if ($add_save_lastsearch_values) {
1324 $url .= '&save_lastsearch_values=1';
1325 }
1326 }
1327
1328 $linkclose = '';
1329 if (empty($notooltip)) {
1330 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1331 $label = $langs->trans("ShowAsset");
1332 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
1333 }
1334 $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
1335 $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
1336 } else {
1337 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1338 }
1339
1340 if ($option == 'nolink') {
1341 $linkstart = '<span';
1342 } else {
1343 $linkstart = '<a href="'.$url.'"';
1344 }
1345 $linkstart .= $linkclose.'>';
1346 if ($option == 'nolink') {
1347 $linkend = '</span>';
1348 } else {
1349 $linkend = '</a>';
1350 }
1351
1352 $result .= $linkstart;
1353
1354 if (empty($this->showphoto_on_popup)) {
1355 if ($withpicto) {
1356 $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);
1357 }
1358 } else {
1359 if ($withpicto) {
1360 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1361
1362 list($class, $module) = explode('@', $this->picto);
1363 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
1364 $filearray = dol_dir_list($upload_dir, "files");
1365 $filename = $filearray[0]['name'];
1366 if (!empty($filename)) {
1367 $pospoint = strpos($filearray[0]['name'], '.');
1368
1369 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
1370 if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
1371 $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>';
1372 } else {
1373 $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>';
1374 }
1375
1376 $result .= '</div>';
1377 } else {
1378 $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);
1379 }
1380 }
1381 }
1382
1383 if ($withpicto != 2) {
1384 $name = $this->ref;
1385 if ($option == 'label') {
1386 $name = $this->label;
1387 } elseif ($option == 'with_label') {
1388 $name .= ' - ' . $this->label;
1389 }
1390 $result .= dol_escape_htmltag($maxlen ? dol_trunc($name, $maxlen) : $name);
1391 }
1392
1393 $result .= $linkend;
1394 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
1395
1396 global $action;
1397 $hookmanager->initHooks(array($this->element . 'dao'));
1398 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1399 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1400 if ($reshook > 0) {
1401 $result = $hookmanager->resPrint;
1402 } else {
1403 $result .= $hookmanager->resPrint;
1404 }
1405 return $result;
1406 }
1407
1414 public function getLabelStatus($mode = 0)
1415 {
1416 return $this->LibStatut($this->status, $mode);
1417 }
1418
1425 public function getLibStatut($mode = 0)
1426 {
1427 return $this->LibStatut($this->status, $mode);
1428 }
1429
1430 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1438 public function LibStatut($status, $mode = 0)
1439 {
1440 // phpcs:enable
1441 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
1442 global $langs;
1443 //$langs->load("assets");
1444 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('AssetInProgress');
1445 $this->labelStatus[self::STATUS_DISPOSED] = $langs->transnoentitiesnoconv('AssetDisposed');
1446 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('AssetInProgress');
1447 $this->labelStatusShort[self::STATUS_DISPOSED] = $langs->transnoentitiesnoconv('AssetDisposed');
1448 }
1449
1450 $statusType = 'status4';
1451 if ($status == self::STATUS_DISPOSED) {
1452 $statusType = 'status6';
1453 }
1454
1455 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
1456 }
1457
1464 public function info($id)
1465 {
1466 $sql = "SELECT rowid, date_creation as datec, tms as datem,";
1467 $sql .= " fk_user_creat, fk_user_modif";
1468 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t";
1469 $sql .= " WHERE t.rowid = ".((int) $id);
1470
1471 $result = $this->db->query($sql);
1472 if ($result) {
1473 if ($this->db->num_rows($result)) {
1474 $obj = $this->db->fetch_object($result);
1475 $this->id = $obj->rowid;
1476
1477 $this->user_creation_id = $obj->fk_user_creat;
1478 $this->user_modification_id = $obj->fk_user_modif;
1479 $this->date_creation = $this->db->jdate($obj->datec);
1480 $this->date_modification = $this->db->jdate($obj->datem);
1481 }
1482
1483 $this->db->free($result);
1484 } else {
1485 dol_print_error($this->db);
1486 }
1487 }
1488
1495 public function initAsSpecimen()
1496 {
1497 // Set here init that are not commonf fields
1498 // $this->property1 = ...
1499 // $this->property2 = ...
1500
1501 return $this->initAsSpecimenCommon();
1502 }
1503
1509 public function getLinesArray()
1510 {
1511 $this->lines = array();
1512
1513 return $this->lines;
1514 }
1515
1521 public function getNextNumRef()
1522 {
1523 global $langs, $conf;
1524 $langs->load("assets");
1525
1526 if (!getDolGlobalString('ASSET_ASSET_ADDON')) {
1527 $conf->global->ASSET_ASSET_ADDON = 'mod_asset_standard';
1528 }
1529
1530 if (getDolGlobalString('ASSET_ASSET_ADDON')) {
1531 $mybool = false;
1532
1533 $file = getDolGlobalString('ASSET_ASSET_ADDON') . ".php";
1534 $classname = getDolGlobalString('ASSET_ASSET_ADDON');
1535
1536 // Include file with class
1537 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1538 foreach ($dirmodels as $reldir) {
1539 $dir = dol_buildpath($reldir."core/modules/asset/");
1540
1541 // Load file with numbering class (if found)
1542 $mybool = ((bool) @include_once $dir.$file) || $mybool;
1543 }
1544
1545 if ($mybool === false) {
1546 dol_print_error(null, "Failed to include file ".$file);
1547 return '';
1548 }
1549
1550 if (class_exists($classname)) {
1551 $obj = new $classname();
1552 $numref = $obj->getNextValue($this);
1553
1554 if ($numref != '' && $numref != '-1') {
1555 return $numref;
1556 } else {
1557 $this->error = $obj->error;
1558 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1559 return "";
1560 }
1561 } else {
1562 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1563 return "";
1564 }
1565 } else {
1566 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1567 return "";
1568 }
1569 }
1570}
getCurrentPeriodOfFiscalYear($db, $conf, $from_time=null)
Get current period of fiscal year.
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition security.php:626
$object ref
Definition info.php:79
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.
getLinesArray()
Create an array of lines.
dispose($user, $disposal_invoice_id, $notrigger=0)
Set dispose status.
createFromClone(User $user, $fromid)
Clone an object into another one.
calculationDepreciation()
Calculation depreciation lines (reversal and future) for each mode.
fetchLines()
Load object lines in memory from the database.
__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.
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.
getNextNumRef()
Returns the reference to the following non used object depending on the active numbering module.
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.
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition date.lib.php:594
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:124
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:613
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:63
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
forgeSQLFromUniversalSearchCriteria
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
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...