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