dolibarr 18.0.6
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 " . MAIN_DB_PREFIX . "asset_depreciation FROM " . MAIN_DB_PREFIX . "asset_depreciation";
932 $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";
933 $sql .= " WHERE " . MAIN_DB_PREFIX . "asset_depreciation.fk_asset = " . (int) $this->id;
934 $sql .= " AND " . MAIN_DB_PREFIX . "asset_depreciation.depreciation_mode = '" . $this->db->escape($mode_key) . "'";
935 $sql .= " AND ab.fk_docdet IS NULL";
936 if ($last_depreciation_date !== "") $sql .= " AND " . MAIN_DB_PREFIX . "asset_depreciation.ref != ''";
937 $resql = $this->db->query($sql);
938 if (!$resql) {
939 $this->errors[] = $langs->trans('AssetErrorClearDepreciationLines') . ': ' . $this->db->lasterror();
940 $error++;
941 break;
942 }
943
944 // Get depreciation period
945 $depreciation_date_start = $this->date_start > $this->date_acquisition ? $this->date_start : $this->date_acquisition;
946 $depreciation_date_end = dol_time_plus_duree($depreciation_date_start, $fields['duration'], $fields['duration_type'] == 1 ? 'm' : ($fields['duration_type'] == 2 ? 'd' : 'y'));
947 $depreciation_amount = $fields['amount_base_depreciation_ht'];
948 if ($fields['duration_type'] == 2) { // Daily
949 $fiscal_period_start = $depreciation_date_start;
950 $fiscal_period_end = $depreciation_date_start;
951 } elseif ($fields['duration_type'] == 1) { // Monthly
952 $date_temp = dol_getdate($depreciation_date_start);
953 $fiscal_period_start = dol_get_first_day($date_temp['year'], $date_temp['mon'], false);
954 $fiscal_period_end = dol_get_last_day($date_temp['year'], $date_temp['mon'], false);
955 } else { // Annually
956 $fiscal_period_start = $init_fiscal_period_start;
957 $fiscal_period_end = $init_fiscal_period_end;
958 }
959 $cumulative_depreciation_ht = $last_cumulative_depreciation_ht;
960 $depreciation_period_amount = $depreciation_amount - $this->reversal_amount_ht;
961 $start_date = $depreciation_date_start;
962 $disposal_date = isset($this->disposal_date) && $this->disposal_date !== "" ? $this->disposal_date : "";
963 $finish_date = $disposal_date !== "" ? $disposal_date : $depreciation_date_end;
964 $accountancy_code_depreciation_debit_key = $accountancy_codes->accountancy_codes_fields[$mode_key]['depreciation_debit'];
965 $accountancy_code_depreciation_debit = $accountancy_codes->accountancy_codes[$mode_key][$accountancy_code_depreciation_debit_key];
966 $accountancy_code_depreciation_credit_key = $accountancy_codes->accountancy_codes_fields[$mode_key]['depreciation_credit'];
967 $accountancy_code_credit = $accountancy_codes->accountancy_codes[$mode_key][$accountancy_code_depreciation_credit_key];
968
969 // Reversal depreciation line
970 //-----------------------------------------------------
971 if ($last_depreciation_date === "" && ($depreciation_date_start < $fiscal_period_start || is_numeric($this->reversal_date))) {
972 if (is_numeric($this->reversal_date)) {
973 if ($this->reversal_date < $fiscal_period_start) {
974 $this->errors[] = $langs->trans('AssetErrorReversalDateNotGreaterThanCurrentBeginFiscalDateForMode', $mode_key);
975 $error++;
976 break;
977 }
978
979 if (empty($this->reversal_amount_ht)) {
980 $this->errors[] = $langs->trans('AssetErrorReversalAmountNotProvidedForMode', $mode_key);
981 $error++;
982 break;
983 }
984
985 $start_date = $this->reversal_date;
986 $result = $this->addDepreciationLine($mode_key, '', $start_date, $this->reversal_amount_ht, $this->reversal_amount_ht, $accountancy_code_depreciation_debit, $accountancy_code_credit);
987 if ($result < 0) {
988 $error++;
989 break;
990 }
991 } else {
992 $this->errors[] = $langs->trans('AssetErrorReversalDateNotProvidedForMode', $mode_key);
993 $error++;
994 break;
995 }
996 }
997
998 // futures depreciation lines
999 //-----------------------------------------------------
1000 $nb_days_in_year = !empty($conf->global->ASSET_DEPRECIATION_DURATION_PER_YEAR) ? $conf->global->ASSET_DEPRECIATION_DURATION_PER_YEAR : 365;
1001 $nb_days_in_month = !empty($conf->global->ASSET_DEPRECIATION_DURATION_PER_MONTH) ? $conf->global->ASSET_DEPRECIATION_DURATION_PER_MONTH : 30;
1002 $period_amount = (double) price2num($depreciation_period_amount / $fields['duration'], 'MT');
1003 $first_period_found = false;
1004 $first_period_date = isset($begin_period) && $begin_period > $fiscal_period_start ? $begin_period : $fiscal_period_start;
1005
1006 $ref_date_format = "%Y" . ($fields['duration_type'] == 1 || $fields['duration_type'] == 2 ? '-%m' : '') . ($fields['duration_type'] == 2 ? '-%d' : '');
1007
1008 // Loop security
1009 $idx_loop = 0;
1010 $max_loop = $fields['duration'] + 2;
1011 do {
1012 // Loop security
1013 $idx_loop++;
1014 if ($idx_loop > $max_loop) break;
1015
1016 if ($last_depreciation_date < $fiscal_period_end && ($first_period_date <= $start_date || $first_period_found)) {
1017 // Disposal not depreciated
1018 if ($fiscal_period_start <= $disposal_date && $disposal_date <= $fiscal_period_end && empty($this->disposal_depreciated)) {
1019 break;
1020 }
1021
1022 $first_period_found = true;
1023
1024 $period_begin = dol_print_date($fiscal_period_start, $ref_date_format);
1025 $period_end = dol_print_date($fiscal_period_end, $ref_date_format);
1026 $ref = $period_begin . ($period_begin != $period_end ? ' - ' . $period_end : '');
1027 if ($fiscal_period_start <= $disposal_date && $disposal_date <= $fiscal_period_end) {
1028 $ref .= ' - ' . $langs->transnoentitiesnoconv('AssetDisposal');
1029 }
1030
1031 $begin_date = $fiscal_period_start < $start_date && $start_date <= $fiscal_period_end ? $start_date : $fiscal_period_start;
1032 $end_date = $fiscal_period_start < $finish_date && $finish_date <= $fiscal_period_end ? $finish_date : $fiscal_period_end;
1033 if ($fields['duration_type'] == 2) { // Daily
1034 $depreciation_ht = $period_amount;
1035 } elseif ($fields['duration_type'] == 1) { // Monthly
1036 $nb_days = min($nb_days_in_month, num_between_day($begin_date, $end_date, 1));
1037 if ($nb_days >= 28) {
1038 $date_temp = dol_getdate($begin_date);
1039 if ($date_temp['mon'] == 2) {
1040 $nb_days = 30;
1041 }
1042 }
1043 $depreciation_ht = (double) price2num($period_amount * $nb_days / $nb_days_in_month, 'MT');
1044 } else { // Annually
1045 $nb_days = min($nb_days_in_year, num_between_day($begin_date, $end_date, 1));
1046 $depreciation_ht = (double) price2num($period_amount * $nb_days / $nb_days_in_year, 'MT');
1047 }
1048
1049 if ($fiscal_period_start <= $depreciation_date_end && $depreciation_date_end <= $fiscal_period_end) { // last period
1050 $depreciation_ht = (double) price2num($depreciation_amount - $cumulative_depreciation_ht, 'MT');
1051 $cumulative_depreciation_ht = $depreciation_amount;
1052 } else {
1053 $cumulative_depreciation_ht += $depreciation_ht;
1054 }
1055
1056 $result = $this->addDepreciationLine($mode_key, $ref, $fiscal_period_end, $depreciation_ht, $cumulative_depreciation_ht, $accountancy_code_depreciation_debit, $accountancy_code_credit);
1057 if ($result < 0) {
1058 $error++;
1059 break;
1060 }
1061 }
1062
1063 // Next fiscal period (+1 day/month/year)
1064 $fiscal_period_start = dol_time_plus_duree($fiscal_period_end, 1, 'd');
1065 if ($fields['duration_type'] == 2) { // Daily
1066 $fiscal_period_end = $fiscal_period_start;
1067 } elseif ($fields['duration_type'] == 1) { // Monthly
1068 $fiscal_period_end = dol_time_plus_duree(dol_time_plus_duree($fiscal_period_start, 1, 'm'), -1, 'd');
1069 } else { // Annually
1070 $fiscal_period_end = dol_time_plus_duree(dol_time_plus_duree($fiscal_period_start, 1, 'y'), -1, 'd');
1071 }
1072 $last_period_date = $disposal_date !== "" && $disposal_date < $depreciation_date_end ? $disposal_date : $depreciation_date_end;
1073 } while ($fiscal_period_start < $last_period_date);
1074
1075 if ($error) {
1076 break;
1077 }
1078 }
1079 }
1080
1081 if ($error) {
1082 $this->db->rollback();
1083 return -1;
1084 } else {
1085 $this->db->commit();
1086 return 1;
1087 }
1088 }
1089
1096 public function setLastCumulativeDepreciation($asset_depreciation_id)
1097 {
1098 global $langs;
1099 $langs->load('assets');
1100
1101 // Clean parameters
1102 $asset_depreciation_id = $asset_depreciation_id > 0 ? $asset_depreciation_id : 0;
1103
1104 // Check parameters
1105 $error = 0;
1106 if (empty($asset_depreciation_id)) {
1107 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("AssetDepreciation") . ' (' . $langs->transnoentitiesnoconv("TechnicalID") . ')');
1108 $error++;
1109 }
1110 if ($error) {
1111 return -1;
1112 }
1113
1114 $this->db->begin();
1115
1116 require_once DOL_DOCUMENT_ROOT . '/asset/class/assetdepreciationoptions.class.php';
1117 $options = new AssetDepreciationOptions($this->db);
1118
1119 // Get last depreciation lines save in bookkeeping
1120 //-----------------------------------------------------
1121 $sql = "SELECT fk_asset, depreciation_mode, cumulative_depreciation_ht";
1122 $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation";
1123 $sql .= " WHERE rowid = " . (int) $asset_depreciation_id;
1124 $resql = $this->db->query($sql);
1125 if (!$resql) {
1126 $this->errors[] = $langs->trans('AssetErrorFetchCumulativeDepreciation') . ': ' . $this->db->lasterror();
1127 $error++;
1128 } else {
1129 if ($obj = $this->db->fetch_object($resql)) {
1130 $mode_key = $obj->depreciation_mode;
1131 if (!empty($options->deprecation_options_fields[$mode_key])) {
1132 $sql = "UPDATE " . MAIN_DB_PREFIX . $options->deprecation_options_fields[$mode_key]['table'];
1133 $sql .= " SET total_amount_last_depreciation_ht = " . $obj->cumulative_depreciation_ht;
1134 $sql .= " WHERE fk_asset = " . (int) $obj->fk_asset;
1135 $resql = $this->db->query($sql);
1136 if (!$resql) {
1137 $this->errors[] = $langs->trans('AssetErrorSetLastCumulativeDepreciation') . ': ' . $this->db->lasterror();
1138 $error++;
1139 }
1140 }
1141 }
1142 }
1143
1144 if ($error) {
1145 $this->db->rollback();
1146 return -1;
1147 } else {
1148 $this->db->commit();
1149 return 1;
1150 }
1151 }
1152
1161 public function dispose($user, $disposal_invoice_id, $notrigger = 0)
1162 {
1163 global $conf, $langs;
1164
1165 // Protection
1166 if ($this->status != self::STATUS_DRAFT || $this->status == self::STATUS_DISPOSED) {
1167 return 0;
1168 }
1169
1170 $this->db->begin();
1171
1172 $required_fields = array('disposal_date', 'disposal_date', 'fk_disposal_type');
1173 foreach ($required_fields as $field) {
1174 $this->fields[$field]['notnull'] = 1;
1175 }
1176 $result = $this->update($user, 1);
1177 foreach ($required_fields as $field) {
1178 $this->fields[$field]['notnull'] = 0;
1179 }
1180 if ($result > 0) {
1181 if ($disposal_invoice_id > 0) $this->add_object_linked('facture', $disposal_invoice_id);
1182 $result = $this->setStatusCommon($user, self::STATUS_DISPOSED, $notrigger, 'ASSET_DISPOSED');
1183 }
1184 if ($result > 0) $result = $this->calculationDepreciation();
1185
1186 if ($result < 0) {
1187 $this->db->rollback();
1188 } else {
1189 $this->db->commit();
1190 }
1191
1192 // Define output language
1193 if ($result > 0 && empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
1194 if (method_exists($this, 'generateDocument')) {
1195 global $hidedetails, $hidedesc, $hideref;
1196 $outputlangs = $langs;
1197 $newlang = '';
1198 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
1199 $newlang = GETPOST('lang_id', 'aZ09');
1200 }
1201 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1202 $newlang = $this->thirdparty->default_lang;
1203 }
1204 if (!empty($newlang)) {
1205 $outputlangs = new Translate("", $conf);
1206 $outputlangs->setDefaultLang($newlang);
1207 }
1208 $model = $this->model_pdf;
1209 $ret = $this->fetch($this->id); // Reload to get new records
1210
1211 $this->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
1212 }
1213 }
1214
1215 return $result;
1216 }
1217
1225 public function reopen($user, $notrigger = 0)
1226 {
1227 global $conf, $langs;
1228
1229 // Protection
1230 if ($this->status != self::STATUS_DISPOSED || $this->status == self::STATUS_DRAFT) {
1231 return 0;
1232 }
1233
1234
1235 $this->db->begin();
1236
1237 $this->disposal_date = null;
1238 $this->disposal_amount_ht = null;
1239 $this->fk_disposal_type = null;
1240 $this->disposal_depreciated = null;
1241 $this->disposal_subject_to_vat = null;
1242 $result = $this->update($user, 1);
1243 if ($result > 0) {
1244 $this->deleteObjectLinked(null, 'facture');
1245 $result = $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'ASSET_REOPEN');
1246 }
1247 if ($result > 0) $result = $this->calculationDepreciation();
1248
1249 if ($result < 0) {
1250 $this->db->rollback();
1251 } else {
1252 $this->db->commit();
1253 }
1254
1255 // Define output language
1256 if ($result > 0 && empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
1257 if (method_exists($this, 'generateDocument')) {
1258 global $hidedetails, $hidedesc, $hideref;
1259 $outputlangs = $langs;
1260 $newlang = '';
1261 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
1262 $newlang = GETPOST('lang_id', 'aZ09');
1263 }
1264 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1265 $newlang = $this->thirdparty->default_lang;
1266 }
1267 if (!empty($newlang)) {
1268 $outputlangs = new Translate("", $conf);
1269 $outputlangs->setDefaultLang($newlang);
1270 }
1271 $model = $this->model_pdf;
1272 $ret = $this->fetch($this->id); // Reload to get new records
1273
1274 $this->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
1275 }
1276 }
1277
1278 return $result;
1279 }
1280
1292 public function getNomUrl($withpicto = 0, $option = '', $maxlen = 0, $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1293 {
1294 global $db, $conf, $langs, $hookmanager;
1295 global $dolibarr_main_authentication, $dolibarr_main_demo;
1296 global $menumanager;
1297
1298 if (!empty($conf->dol_no_mouse_hover)) {
1299 $notooltip = 1; // Force disable tooltips
1300 }
1301
1302 $result = '';
1303
1304 $label = img_picto('', $this->picto).' <u>'.$langs->trans("Asset").'</u>';
1305 if (isset($this->status)) {
1306 $label .= ' '.$this->getLibStatut(5);
1307 }
1308 $label .= '<br>';
1309 $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
1310
1311 $url = dol_buildpath('/asset/card.php', 1).'?id='.$this->id;
1312
1313 if ($option != 'nolink') {
1314 // Add param to save lastsearch_values or not
1315 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1316 if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1317 $add_save_lastsearch_values = 1;
1318 }
1319 if ($add_save_lastsearch_values) {
1320 $url .= '&save_lastsearch_values=1';
1321 }
1322 }
1323
1324 $linkclose = '';
1325 if (empty($notooltip)) {
1326 if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
1327 $label = $langs->trans("ShowAsset");
1328 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
1329 }
1330 $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
1331 $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
1332 } else {
1333 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1334 }
1335
1336 if ($option == 'nolink') {
1337 $linkstart = '<span';
1338 } else {
1339 $linkstart = '<a href="'.$url.'"';
1340 }
1341 $linkstart .= $linkclose.'>';
1342 if ($option == 'nolink') {
1343 $linkend = '</span>';
1344 } else {
1345 $linkend = '</a>';
1346 }
1347
1348 $result .= $linkstart;
1349
1350 if (empty($this->showphoto_on_popup)) {
1351 if ($withpicto) {
1352 $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);
1353 }
1354 } else {
1355 if ($withpicto) {
1356 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1357
1358 list($class, $module) = explode('@', $this->picto);
1359 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
1360 $filearray = dol_dir_list($upload_dir, "files");
1361 $filename = $filearray[0]['name'];
1362 if (!empty($filename)) {
1363 $pospoint = strpos($filearray[0]['name'], '.');
1364
1365 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
1366 if (empty($conf->global->{strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS'})) {
1367 $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>';
1368 } else {
1369 $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>';
1370 }
1371
1372 $result .= '</div>';
1373 } else {
1374 $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);
1375 }
1376 }
1377 }
1378
1379 if ($withpicto != 2) {
1380 $name = $this->ref;
1381 if ($option == 'label') $name = $this->label;
1382 elseif ($option == 'with_label') $name .= ' - ' . $this->label;
1383 $result .= dol_escape_htmltag($maxlen ? dol_trunc($name, $maxlen) : $name);
1384 }
1385
1386 $result .= $linkend;
1387 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
1388
1389 global $action;
1390 $hookmanager->initHooks(array($this->element . 'dao'));
1391 $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
1392 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1393 if ($reshook > 0) {
1394 $result = $hookmanager->resPrint;
1395 } else {
1396 $result .= $hookmanager->resPrint;
1397 }
1398 return $result;
1399 }
1400
1407 public function getLabelStatus($mode = 0)
1408 {
1409 return $this->LibStatut($this->status, $mode);
1410 }
1411
1418 public function getLibStatut($mode = 0)
1419 {
1420 return $this->LibStatut($this->status, $mode);
1421 }
1422
1423 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1431 public function LibStatut($status, $mode = 0)
1432 {
1433 // phpcs:enable
1434 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
1435 global $langs;
1436 //$langs->load("asset@asset");
1437 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('AssetInProgress');
1438 $this->labelStatus[self::STATUS_DISPOSED] = $langs->transnoentitiesnoconv('AssetDisposed');
1439 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('AssetInProgress');
1440 $this->labelStatusShort[self::STATUS_DISPOSED] = $langs->transnoentitiesnoconv('AssetDisposed');
1441 }
1442
1443 $statusType = 'status4';
1444 if ($status == self::STATUS_DISPOSED) {
1445 $statusType = 'status6';
1446 }
1447
1448 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
1449 }
1450
1457 public function info($id)
1458 {
1459 $sql = "SELECT rowid, date_creation as datec, tms as datem,";
1460 $sql .= " fk_user_creat, fk_user_modif";
1461 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t";
1462 $sql .= " WHERE t.rowid = ".((int) $id);
1463
1464 $result = $this->db->query($sql);
1465 if ($result) {
1466 if ($this->db->num_rows($result)) {
1467 $obj = $this->db->fetch_object($result);
1468 $this->id = $obj->rowid;
1469
1470 $this->user_creation_id = $obj->fk_user_author;
1471 $this->user_validation_id = $obj->fk_user_valid;
1472 $this->user_cloture_id = $obj->fk_user_cloture;
1473 $this->date_creation = $this->db->jdate($obj->datec);
1474 $this->date_modification = $this->db->jdate($obj->datem);
1475 $this->date_validation = $this->db->jdate($obj->datev);
1476 }
1477
1478 $this->db->free($result);
1479 } else {
1480 dol_print_error($this->db);
1481 }
1482 }
1483
1490 public function initAsSpecimen()
1491 {
1492 // Set here init that are not commonf fields
1493 // $this->property1 = ...
1494 // $this->property2 = ...
1495
1496 $this->initAsSpecimenCommon();
1497 }
1498
1504 public function getLinesArray()
1505 {
1506 $this->lines = array();
1507
1508 return $this->lines;
1509 }
1510
1516 public function getNextNumRef()
1517 {
1518 global $langs, $conf;
1519 $langs->load("asset@asset");
1520
1521 if (empty($conf->global->ASSET_ASSET_ADDON)) {
1522 $conf->global->ASSET_ASSET_ADDON = 'mod_asset_standard';
1523 }
1524
1525 if (!empty($conf->global->ASSET_ASSET_ADDON)) {
1526 $mybool = false;
1527
1528 $file = $conf->global->ASSET_ASSET_ADDON.".php";
1529 $classname = $conf->global->ASSET_ASSET_ADDON;
1530
1531 // Include file with class
1532 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1533 foreach ($dirmodels as $reldir) {
1534 $dir = dol_buildpath($reldir."core/modules/asset/");
1535
1536 // Load file with numbering class (if found)
1537 $mybool |= @include_once $dir.$file;
1538 }
1539
1540 if ($mybool === false) {
1541 dol_print_error('', "Failed to include file ".$file);
1542 return '';
1543 }
1544
1545 if (class_exists($classname)) {
1546 $obj = new $classname();
1547 $numref = $obj->getNextValue($this);
1548
1549 if ($numref != '' && $numref != '-1') {
1550 return $numref;
1551 } else {
1552 $this->error = $obj->error;
1553 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1554 return "";
1555 }
1556 } else {
1557 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1558 return "";
1559 }
1560 } else {
1561 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1562 return "";
1563 }
1564 }
1565
1577 // public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1578 // {
1579 // global $conf, $langs;
1580 //
1581 // $result = 0;
1582 // $includedocgeneration = 1;
1583 //
1584 // $langs->load("asset@asset");
1585 //
1586 // if (!dol_strlen($modele)) {
1587 // $modele = 'standard_asset';
1588 //
1589 // if (!empty($this->model_pdf)) {
1590 // $modele = $this->model_pdf;
1591 // } elseif (!empty($conf->global->ASSET_ADDON_PDF)) {
1592 // $modele = $conf->global->ASSET_ADDON_PDF;
1593 // }
1594 // }
1595 //
1596 // $modelpath = "core/modules/asset/doc/";
1597 //
1598 // if ($includedocgeneration && !empty($modele)) {
1599 // $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1600 // }
1601 //
1602 // return $result;
1603 // }
1604}
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:577
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:991
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:122
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:596
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'))