Linux server.jmdstrack.com 3.10.0-1160.119.1.el7.tuxcare.els10.x86_64 #1 SMP Fri Oct 11 21:40:41 UTC 2024 x86_64
/ home/ jmdstrac/ public_html/ devices/ src/ |
|
<?php /** * --------------------------------------------------------------------- * * GLPI - Gestionnaire Libre de Parc Informatique * * http://glpi-project.org * * @copyright 2015-2023 Teclib' and contributors. * @copyright 2003-2014 by the INDEPNET Development Team. * @licence https://www.gnu.org/licenses/gpl-3.0.html * * --------------------------------------------------------------------- * * LICENSE * * This file is part of GLPI. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. * * --------------------------------------------------------------------- */ use Glpi\Application\View\TemplateRenderer; /** * Infocom class **/ class Infocom extends CommonDBChild { // From CommonDBChild public static $itemtype = 'itemtype'; public static $items_id = 'items_id'; public $dohistory = true; public $auto_message_on_action = false; // Link in message can't work' public static $logs_for_parent = false; public static $rightname = 'infocom'; //Option to automatically fill dates const ON_STATUS_CHANGE = 'STATUS'; const COPY_WARRANTY_DATE = 1; const COPY_BUY_DATE = 2; const COPY_ORDER_DATE = 3; const COPY_DELIVERY_DATE = 4; const ON_ASSET_IMPORT = 5; /** * Check if given object can have Infocom * * @since 0.85 * * @param string|object $item an object or a string * * @return boolean true if $object is an object that can have Infocom * **/ public static function canApplyOn($item) { global $CFG_GLPI; // All devices are subjects to infocom ! if (is_a($item, 'Item_Devices', true)) { return true; } // We also allow direct items to check if ($item instanceof CommonGLPI) { $item = $item->getType(); } if (in_array($item, $CFG_GLPI['infocom_types'])) { return true; } return false; } /** * Get all the types that can have an infocom * * @since 0.85 * * @return array of the itemtypes **/ public static function getItemtypesThatCanHave() { global $CFG_GLPI; $types = array_merge( $CFG_GLPI['infocom_types'], Item_Devices::getDeviceTypes() ); return array_unique($types); } public static function getTypeName($nb = 0) { //TRANS: Always plural return __('Financial and administrative information'); } public function post_getEmpty() { if (isset($_SESSION['glpiactive_entity'])) { $this->fields["alert"] = Entity::getUsedConfig( "use_infocoms_alert", $_SESSION['glpiactive_entity'], "default_infocom_alert", 0 ); } } public function getLogTypeID() { return [$this->fields['itemtype'], $this->fields['items_id']]; } public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { // Can exists on template if (Session::haveRight(self::$rightname, READ)) { $nb = 0; switch ($item->getType()) { case 'Supplier': if ($_SESSION['glpishow_count_on_tabs']) { $nb = self::countForSupplier($item); } return self::createTabEntry(_n('Item', 'Items', Session::getPluralNumber()), $nb); default: if ($_SESSION['glpishow_count_on_tabs']) { $nb = countElementsInTable( 'glpi_infocoms', ['itemtype' => $item->getType(), 'items_id' => $item->getID() ] ); } return self::createTabEntry(__('Management'), $nb); } } return ''; } /** * @param $item CommonGLPI object * @param $tabnum (default 1) * @param $withtemplate (default 0) **/ public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { switch ($item->getType()) { case 'Supplier': $item->showInfocoms(); break; default: self::showForItem($item, $withtemplate); } return true; } /** * @param $item Supplier object **/ public static function countForSupplier(Supplier $item) { return countElementsInTable( 'glpi_infocoms', [ 'suppliers_id' => $item->getField('id'), 'NOT' => ['itemtype' => ['ConsumableItem', 'CartridgeItem', 'Software']] ] + getEntitiesRestrictCriteria('glpi_infocoms', '', $_SESSION['glpiactiveentities']) ); } public static function getSpecificValueToDisplay($field, $values, array $options = []) { if (!is_array($values)) { $values = [$field => $values]; } switch ($field) { case 'sink_type': return self::getAmortTypeName($values[$field]); case 'alert': return self::getAlertName($values[$field]); } return parent::getSpecificValueToDisplay($field, $values, $options); } /** * @since 0.84 * * @param $field * @param $name (default '') * @param $values (default '') * @param $options array **/ public static function getSpecificValueToSelect($field, $name = '', $values = '', array $options = []) { if (!is_array($values)) { $values = [$field => $values]; } $options['display'] = false; switch ($field) { case "sink_type": return self::dropdownAmortType($name, $values[$field], false); case "alert": $options['name'] = $name; $options['value'] = $values[$field]; return self::dropdownAlert($options); } return parent::getSpecificValueToSelect($field, $name, $values, $options); } /** * Retrieve an item from the database for a device * * @param string $itemtype type of the device to retrieve infocom * @param integer $ID ID of the device to retrieve infocom * * @return boolean true if succeed else false **/ public function getFromDBforDevice($itemtype, $ID) { if ( $this->getFromDBByCrit([ $this->getTable() . '.items_id' => $ID, $this->getTable() . '.itemtype' => $itemtype ]) ) { return true; } $this->getEmpty(); $this->fields["items_id"] = $ID; $this->fields["itemtype"] = $itemtype; return false; } public function prepareInputForAdd($input) { if (!$this->getFromDBforDevice($input['itemtype'], $input['items_id'])) { if ($item = static::getItemFromArray(static::$itemtype, static::$items_id, $input)) { $input['alert'] = Entity::getUsedConfig('default_infocom_alert', $item->getEntityID()); return parent::prepareInputForAdd($input); } } return false; } /** * Fill, if necessary, automatically some dates when status changes * * @param item CommonDBTM object: the item whose status have changed * @param action_add true if object is added, false if updated (true by default) * * @return void **/ public static function manageDateOnStatusChange(CommonDBTM $item, $action_add = true) { $itemtype = get_class($item); $changes = $item->fields; //Autofill date on item's status change ? $infocom = new self(); $infocom->getFromDB($changes['id']); $tmp = ['itemtype' => $itemtype, 'items_id' => $changes['id'] ]; $add_or_update = false; //For each date that can be automatically filled foreach (self::getAutoManagemendDatesFields() as $date => $date_field) { $resp = []; $result = Entity::getUsedConfig($date, $changes['entities_id']); //Date must be filled if status corresponds to the one defined in the config if ( preg_match('/' . self::ON_STATUS_CHANGE . '_(.*)/', $result, $values) && ($values[1] == $changes['states_id']) ) { $add_or_update = true; $tmp[$date_field] = $_SESSION["glpi_currenttime"]; } } //One date or more has changed if ($add_or_update) { if (!$infocom->getFromDBforDevice($itemtype, $changes['id'])) { $infocom->add($tmp); } else { $tmp['id'] = $infocom->fields['id']; $infocom->update($tmp); } } } /** * Automatically manage copying one date to another is necessary * * @param infocoms array of item's infocom to modify * @param field the date to modify (default '') * @param action the action to peform (copy from another date) (default 0) * @param params array of additional parameters needed to perform the task * * @return void **/ public static function autofillDates(&$infocoms = [], $field = '', $action = 0, $params = []) { if (isset($infocoms[$field])) { switch ($action) { default: case 0: break; case self::COPY_WARRANTY_DATE: if (isset($infocoms['warranty_date'])) { $infocoms[$field] = $infocoms['warranty_date']; } break; case self::COPY_BUY_DATE: if (isset($infocoms['buy_date'])) { $infocoms[$field] = $infocoms['buy_date']; } break; case self::COPY_ORDER_DATE: if (isset($infocoms['order_date'])) { $infocoms[$field] = $infocoms['order_date']; } break; case self::COPY_DELIVERY_DATE: if (isset($infocoms['delivery_date'])) { $infocoms[$field] = $infocoms['delivery_date']; } break; } } } /** * Return all infocom dates that could be automaticall filled * * @return array with all dates (configuration field & real field) **/ public static function getAutoManagemendDatesFields() { return ['autofill_buy_date' => 'buy_date', 'autofill_use_date' => 'use_date', 'autofill_delivery_date' => 'delivery_date', 'autofill_warranty_date' => 'warranty_date', 'autofill_order_date' => 'order_date', 'autofill_decommission_date' => 'decommission_date' ]; } public function prepareInputForUpdate($input) { //Check if one or more dates needs to be updated foreach (self::getAutoManagemendDatesFields() as $key => $field) { $result = Entity::getUsedConfig($key, $this->fields['entities_id']); //Only update date if it's empty in DB. Otherwise do nothing if ( ($result > 0) && !isset($this->fields[$field]) ) { self::autofillDates($input, $field, $result); } } return parent::prepareInputForUpdate($input); } public function pre_updateInDB() { // Clean end alert if warranty_date is after old one // Or if duration is greater than old one if ( (isset($this->oldvalues['warranty_date']) && ($this->oldvalues['warranty_date'] < $this->fields['warranty_date'])) || (isset($this->oldvalues['warranty_duration']) && ($this->oldvalues['warranty_duration'] < $this->fields['warranty_duration'])) ) { $alert = new Alert(); $alert->clear($this->getType(), $this->fields['id'], Alert::END); } // Check budgets link validity if ( (in_array('budgets_id', $this->updates) || in_array('buy_date', $this->updates)) && $this->fields['budgets_id'] && ($budget = getItemForItemtype('Budget')) && $budget->getFromDB($this->fields['budgets_id']) ) { if ( (!is_null($budget->fields['begin_date']) && $this->fields['buy_date'] < $budget->fields['begin_date']) || (!is_null($budget->fields['end_date']) && ($this->fields['buy_date'] > $budget->fields['end_date'])) ) { $msg = sprintf( __('Purchase date incompatible with the associated budget. %1$s not in budget period: %2$s / %3$s'), Html::convDate($this->fields['buy_date']), Html::convDate($budget->fields['begin_date']), Html::convDate($budget->fields['end_date']) ); Session::addMessageAfterRedirect($msg, false, ERROR); } } } /** * @since 0.84 **/ public function cleanDBonPurge() { $class = new Alert(); $class->cleanDBonItemDelete($this->getType(), $this->fields['id']); } /** * @param $name **/ public static function cronInfo($name) { return ['description' => __('Send alarms on financial and administrative information')]; } /** * Cron action on infocom : alert on expired warranty * * @param CronTask $task to log, if NULL use display (default NULL) * * @return integer 0 : nothing to do 1 : done with success **/ public static function cronInfocom($task = null) { global $DB, $CFG_GLPI; if (!$CFG_GLPI["use_notifications"]) { return 0; } $message = []; $cron_status = 0; $items_infos = []; $items_messages = []; foreach (Entity::getEntitiesToNotify('use_infocoms_alert') as $entity => $value) { $before = Entity::getUsedConfig('send_infocoms_alert_before_delay', $entity); $table = self::getTable(); $iterator = $DB->request([ 'SELECT' => "$table.*", 'FROM' => $table, 'LEFT JOIN' => [ 'glpi_alerts' => [ 'ON' => [ 'glpi_alerts' => 'items_id', $table => 'id', [ 'AND' => [ 'glpi_alerts.itemtype' => self::getType(), 'glpi_alerts.type' => Alert::END ] ] ] ] ], 'WHERE' => [ new \QueryExpression( '(' . $DB->quoteName('glpi_infocoms.alert') . ' & ' . pow(2, Alert::END) . ') > 0' ), "$table.entities_id" => $entity, "$table.warranty_duration" => ['>', 0], 'NOT' => ["$table.warranty_date" => null], new \QueryExpression( 'DATEDIFF(ADDDATE(' . $DB->quoteName('glpi_infocoms.warranty_date') . ', INTERVAL (' . $DB->quoteName('glpi_infocoms.warranty_duration') . ') MONTH), CURDATE() ) <= ' . $DB->quoteValue($before) ), 'glpi_alerts.date' => null ] ]); foreach ($iterator as $data) { if ($item_infocom = getItemForItemtype($data["itemtype"])) { if ($item_infocom->getFromDB($data["items_id"])) { $entity = $data['entities_id']; $warranty = self::getWarrantyExpir($data["warranty_date"], $data["warranty_duration"]); //TRANS: %1$s is a type, %2$s is a name (used in croninfocom) $name = sprintf( __('%1$s - %2$s'), $item_infocom->getTypeName(1), $item_infocom->getName() ); //TRANS: %1$s is the warranty end date and %2$s the name of the item $message = sprintf( __('Item reaching the end of warranty on %1$s: %2$s'), $warranty, $name ) . "<br>"; $data['warrantyexpiration'] = $warranty; $data['item_name'] = $item_infocom->getName(); $items_infos[$entity][$data['id']] = $data; if (!isset($items_messages[$entity])) { $items_messages[$entity] = __('No item reaching the end of warranty.') . "<br>"; } $items_messages[$entity] .= $message; } } } } foreach ($items_infos as $entity => $items) { if ( NotificationEvent::raiseEvent("alert", new self(), ['entities_id' => $entity, 'items' => $items ]) ) { $message = $items_messages[$entity]; $cron_status = 1; if ($task) { $task->log(sprintf( __('%1$s: %2$s') . "\n", Dropdown::getDropdownName("glpi_entities", $entity), $message )); $task->addVolume(1); } else { Session::addMessageAfterRedirect(sprintf( __('%1$s: %2$s'), Dropdown::getDropdownName( "glpi_entities", $entity ), $message )); } $alert = new Alert(); $input["itemtype"] = 'Infocom'; $input["type"] = Alert::END; foreach ($items as $id => $item) { $input["items_id"] = $id; $alert->add($input); unset($alert->fields['id']); } } else { $entityname = Dropdown::getDropdownName('glpi_entities', $entity); //TRANS: %s is entity name $msg = sprintf(__('%1$s: %2$s'), $entityname, __('send infocom alert failed')); if ($task) { $task->log($msg); } else { Session::addMessageAfterRedirect($msg, false, ERROR); } } } return $cron_status; } /** * Get the possible value for infocom alert * * @since 0.84 (before in alert.class) * * @param integer|string|null $val if not set, ask for all values, else for 1 value (default NULL) * * @return array|string **/ public static function getAlertName($val = null) { $tmp[0] = Dropdown::EMPTY_VALUE; $tmp[pow(2, Alert::END)] = __('Warranty expiration date'); if (is_null($val)) { return $tmp; } // Default value for display $tmp[0] = ' '; if (isset($tmp[$val])) { return $tmp[$val]; } // If not set and is a string return value if (is_string($val)) { return $val; } return NOT_AVAILABLE; } /** * @param $options array **/ public static function dropdownAlert($options) { $p['name'] = 'alert'; $p['value'] = 0; $p['display'] = true; $p['inherit_parent'] = false; if (count($options)) { foreach ($options as $key => $val) { $p[$key] = $val; } } $tab = []; if ($p['inherit_parent']) { $tab[Entity::CONFIG_PARENT] = __('Inheritance of the parent entity'); } $tab += self::getAlertName(); return Dropdown::showFromArray($p['name'], $tab, $p); } /** * Dropdown of amortissement type for infocoms * * @param string $name select name * @param integer $value default value (default 0) * @param boolean $display display or get string (true by default) **/ public static function dropdownAmortType($name, $value = 0, $display = true) { $values = [ 2 => __('Linear'), 1 => __('Decreasing') ]; return Dropdown::showFromArray($name, $values, [ 'value' => $value, 'display' => $display, 'display_emptychoice' => true, 'width' => '100%', ]); } /** * Get amortissement type name for infocoms * * @param integer $value status ID **/ public static function getAmortTypeName($value) { switch ($value) { case 2: return __('Linear'); case 1: return __('Decreasing'); case 0: return " "; } } /** * Calculate TCO and TCO by month for an item * * @param string|number $ticket_tco Tco part of tickets * @param number $value * @param string $date_achat (default '') * * @return float **/ public static function showTco($ticket_tco, $value, $date_achat = "") { if ($ticket_tco == NOT_AVAILABLE) { return '-'; } // Affiche le TCO ou le TCO mensuel pour un mat??riel $totalcost = $ticket_tco; if ($date_achat) { // on veut donc le TCO mensuel // just to avoid IDE warning $date_Y = $date_m = $date_d = 0; sscanf($date_achat, "%4s-%2s-%2s", $date_Y, $date_m, $date_d); $timestamp2 = mktime(0, 0, 0, $date_m, $date_d, $date_Y); $timestamp = mktime(0, 0, 0, date("m"), date("d"), date("Y")); $diff = floor(($timestamp - $timestamp2) / (MONTH_TIMESTAMP)); // Mois d'utilisation if ($diff) { return Html::formatNumber((($totalcost + $value) / $diff)); // TCO mensuel } return ""; } return Html::formatNumber(($totalcost + $value)); // TCO } /** * Show infocom link to display modal * * @param $itemtype integer item type * @param $device_id integer item ID * * @return void **/ public static function showDisplayLink($itemtype, $device_id) { global $DB, $CFG_GLPI; if ( !Session::haveRight(self::$rightname, READ) || !($item = getItemForItemtype($itemtype)) ) { return; } $result = $DB->request([ 'COUNT' => 'cpt', 'FROM' => 'glpi_infocoms', 'WHERE' => [ 'itemtype' => $itemtype, 'items_id' => $device_id ] ])->current(); $add = "add"; $text = __('Add'); if ($result['cpt'] > 0) { $add = ""; $text = _x('button', 'Show'); } else if (!Infocom::canUpdate()) { return; } if ($item->canView()) { echo "<span data-bs-toggle='modal' data-bs-target='#infocom$itemtype$device_id' style='cursor:pointer'> <img src=\"" . $CFG_GLPI["root_doc"] . "/pics/dollar$add.png\" alt=\"$text\" title=\"$text\"> </span>"; Ajax::createIframeModalWindow( 'infocom' . $itemtype . $device_id, Infocom::getFormURL() . "?itemtype=$itemtype&items_id=$device_id", ['height' => 600] ); } } /** * Calculate amortization values * * @param number $value Purchase value * @param number $duration Amortise duration * @param string $fiscaldate Begin of fiscal excercise * @param number $buydate Buy date * @param number $usedate Date of use * * @return array|boolean */ public static function linearAmortise($value, $duration, $fiscaldate, $buydate = '', $usedate = '') { //Set timezone to UTC; see https://stackoverflow.com/a/40358744 $TZ = 'UTC'; try { if ($fiscaldate == '') { throw new \RuntimeException('Empty date'); } $fiscaldate = new \DateTime($fiscaldate, new DateTimeZone($TZ)); } catch (\Throwable $e) { Session::addMessageAfterRedirect( __('Please fill you fiscal year date in preferences.'), false, ERROR ); return false; } //get begin date. Work on use date if provided. try { if ($buydate == '' && $usedate == '') { throw new \RuntimeException('Empty date'); } if ($usedate != '') { $usedate = new \DateTime($usedate, new DateTimeZone($TZ)); } else { $usedate = new \DateTime($buydate, new DateTimeZone($TZ)); } } catch (\Throwable $e) { Session::addMessageAfterRedirect( __('Please fill either buy or use date in preferences.'), false, ERROR ); return false; } $now = new \DateTime('now', new DateTimeZone($TZ)); $elapsed_years = $now->format('Y') - $usedate->format('Y'); $annuity = 0; if ($duration) { $annuity = $value * (1 / $duration); } $years = []; for ($i = 0; $i <= $elapsed_years; ++$i) { $begin_value = $value; $current_annuity = $annuity; $fiscal_end = new \DateTime( $fiscaldate->format('d-m-') . ($usedate->format('Y') + $i), new DateTimeZone($TZ) ); if ($i == 0) { //first year, calculate prorata if ($fiscal_end < $usedate) { $fiscal_end->modify('+1 year'); } $days = $fiscal_end->diff($usedate); $days = $days->format('%m') * 30 + $days->format('%d'); $current_annuity = $annuity * $days / 360; } else if ($i == $duration) { $current_annuity = $value; } if ($i > $duration) { $value = 0; $current_annuity = 0; } else { //calculate annuity //full year case $value -= $current_annuity; } $years[$usedate->format('Y') + $i] = [ 'start_value' => (double)$begin_value, 'value' => $value, 'annuity' => $current_annuity ]; } return $years; } /** * Maps new amortise format to old one... * To not rewrite all the old method. * * @param array $values New format amortise values * @param boolean $current True to get only current year, false to get the whole array * * @return array|double */ public static function mapOldAmortiseFormat($values, $current = true) { if ($current === true) { return $values[date('Y')]['value']; } $old = [ 'annee' => [], 'annuite' => [], 'vcnetdeb' => [], 'vcnetfin' => [] ]; foreach ($values as $year => $value) { $old['annee'][] = $year; $old['annuite'][] = $value['annuity']; $old['vcnetdeb'][] = $value['start_value']; $old['vcnetfin'][] = $value['value']; } return $old; } /** * Calculate amortissement for an item * * @param integer $type_amort type d'amortisssment "lineaire=2" ou "degressif=1" * @param number $va valeur d'acquisition * @param number $duree duree d'amortissement * @param number $coef coefficient d'amortissement * @param string|null $date_achat Date d'achat * @param string|null $date_use Date d'utilisation * @param string|null $date_tax date du debut de l'annee fiscale * @param string $view "n" pour l'annee en cours ou "all" pour le tableau complet (default 'n') * * @return float|array **/ public static function Amort( $type_amort, $va, $duree, $coef, $date_achat, $date_use, $date_tax, $view = "n" ) { // By Jean-Mathieu Doleans qui s'est un peu pris le chou :p // Attention date mise en service/dateachat ->amort lineaire et $prorata en jour !! // amort degressif au prorata du nombre de mois. // Son point de depart est le 1er jour du mois d'acquisition et non date de mise en service if ($type_amort == "2") { $values = self::linearAmortise($va, $duree, $date_tax, $date_achat, $date_use); if ($values == false) { return '-'; } return self::mapOldAmortiseFormat($values, $view != 'all'); } $prorata = 0; $ecartfinmoiscourant = 0; $ecartmoisexercice = 0; $date_Y = $date_m = $date_d = $date_H = $date_i = $date_s = 0; sscanf( ($date_achat ?? ""), "%4s-%2s-%2s %2s:%2s:%2s", $date_Y, $date_m, $date_d, $date_H, $date_i, $date_s ); // un traitement sur la date mysql pour recuperer l'annee // un traitement sur la date mysql pour les infos necessaires $date_Y2 = $date_m2 = $date_d2 = $date_H2 = $date_i2 = $date_s2 = 0; sscanf( ($date_tax ?? ""), "%4s-%2s-%2s %2s:%2s:%2s", $date_Y2, $date_m2, $date_d2, $date_H2, $date_i2, $date_s2 ); $date_Y2 = date("Y"); switch ($type_amort) { case "1": //########################### Calcul amortissement degressif ########################### if ( ($va > 0) && ($duree > 0) && ($coef > 1) && !empty($date_achat) ) { //## calcul du prorata temporis en mois ## // si l'annee fiscale debute au dela de l'annee courante if ($date_m > $date_m2) { $date_m2 = $date_m2 + 12; } $ecartmois = ($date_m2 - $date_m) + 1; // calcul ecart entre mois d'acquisition // et debut annee fiscale $prorata = $ecartfinmoiscourant + $ecartmois - $ecartmoisexercice; // calcul tableau d'amortissement ## $txlineaire = (100 / $duree); // calcul du taux lineaire virtuel $txdegressif = $txlineaire * $coef; // calcul du taux degressif $dureelineaire = (int) (100 / $txdegressif); // calcul de la duree de l'amortissement // en mode lineaire $dureedegressif = $duree - $dureelineaire; // calcul de la duree de l'amortissement // en mode degressif $mrt = $va; $tab = [ 'annee' => [], 'vcnetdeb' => [], 'vcnetfin' => [], 'annuite' => [], ]; // amortissement degressif pour les premieres annees for ($i = 1; $i <= $dureedegressif; $i++) { $tab['annee'][$i] = $date_Y + $i - 1; $tab['vcnetdeb'][$i] = $mrt; // Pour chaque annee on calcule la valeur comptable nette // de debut d'exercice $tab['annuite'][$i] = $tab['vcnetdeb'][$i] * $txdegressif / 100; $tab['vcnetfin'][$i] = $mrt - $tab['annuite'][$i]; //Pour chaque annee on calcule la valeur //comptable nette de fin d'exercice // calcul de la premiere annuite si prorata temporis if ($prorata > 0) { $tab['annuite'][1] = ($va * $txdegressif / 100) * ($prorata / 12); $tab['vcnetfin'][1] = $va - $tab['annuite'][1]; } $mrt = $tab['vcnetfin'][$i]; } // amortissement en lineaire pour les derneres annees if ($dureelineaire != 0) { $txlineaire = (100 / $dureelineaire); // calcul du taux lineaire } else { $txlineaire = 100; } $annuite = ($tab['vcnetfin'][$dureedegressif] * $txlineaire) / 100; // calcul de l'annuite $mrt = $tab['vcnetfin'][$dureedegressif]; for ($i = $dureedegressif + 1; $i <= $dureedegressif + $dureelineaire; $i++) { $tab['annee'][$i] = $date_Y + $i - 1; $tab['annuite'][$i] = $annuite; $tab['vcnetdeb'][$i] = $mrt; // Pour chaque annee on calcule la valeur comptable nette // de debut d'exercice $tab['vcnetfin'][$i] = abs(($mrt - $annuite)); // Pour chaque annee on calcule la valeur // comptable nette de fin d'exercice $mrt = $tab['vcnetfin'][$i]; } // calcul de la derniere annuite si prorata temporis if ($prorata > 0) { $tab['annuite'][$duree] = $tab['vcnetdeb'][$duree]; if (isset($tab['vcnetfin'][$duree - 1])) { $tab['vcnetfin'][$duree] = ($tab['vcnetfin'][$duree - 1] - $tab['annuite'][$duree]); } else { $tab['vcnetfin'][$duree] = 0; } } } else { return "-"; } break; default: return "-"; } // le return if ($view == "all") { // on retourne le tableau complet return $tab; } // on retourne juste la valeur residuelle // si on ne trouve pas l'annee en cours dans le tableau d'amortissement dans le tableau, // le materiel est amorti if (!array_search(date("Y"), $tab["annee"])) { $vnc = 0; } else if ( mktime(0, 0, 0, $date_m2, $date_d2, date("Y")) - mktime(0, 0, 0, date("m"), date("d"), date("Y")) < 0 ) { // on a depasse la fin d'exercice de l'annee en cours //on prend la valeur residuelle de l'annee en cours $vnc = $tab["vcnetfin"][array_search(date("Y"), $tab["annee"])]; } else { // on se situe avant la fin d'exercice // on prend la valeur residuelle de l'annee n-1 $vnc = $tab["vcnetdeb"][array_search(date("Y"), $tab["annee"])]; } return $vnc; } /** * Show Infocom form for an item (not a standard showForm) * * @param $item CommonDBTM object * @param $withtemplate integer template or basic item (default 0) **/ public static function showForItem(CommonDBTM $item, $withtemplate = 0) { // Show Infocom or blank form if (!self::canView()) { return false; } if (!$item) { echo "<div class='spaced'>" . __('Requested item not found') . "</div>"; } else { $dev_ID = $item->getField('id'); $ic = new self(); if ( !strpos($_SERVER['PHP_SELF'], "infocoms-show") && in_array($item->getType(), self::getExcludedTypes()) ) { echo "<div class='firstbloc center'>" . __('For this type of item, the financial and administrative information are only a model for the items which you should add.') . "</div>"; } $ic->getFromDBforDevice($item->getType(), $dev_ID); $can_input = [ 'itemtype' => $item->getType(), 'items_id' => $dev_ID, 'entities_id' => $item->getEntityID() ]; TemplateRenderer::getInstance()->display('components/infocom.html.twig', [ 'item' => $item, 'infocom' => $ic, 'withtemplate' => $withtemplate, 'can_create' => $ic->can(-1, CREATE, $can_input), 'can_edit' => ($ic->canEdit($ic->fields['id']) && ($withtemplate != 2)), 'can_global_update' => Session::haveRight(self::$rightname, UPDATE), 'can_global_purge' => Session::haveRight(self::$rightname, PURGE), ]); } } public static function addPluginInfos(CommonDBTM $item) { Plugin::doHookFunction("infocom", $item); } /** * @param $itemtype **/ public static function rawSearchOptionsToAdd($itemtype = null) { $specific_itemtype = ''; $beforejoin = []; switch ($itemtype) { case 'CartridgeItem': // Return the infocom linked to the license, not the template linked to the software $beforejoin = ['table' => 'glpi_cartridges', 'joinparams' => ['jointype' => 'child'] ]; $specific_itemtype = 'Cartridge'; break; case 'ConsumableItem': // Return the infocom linked to the license, not the template linked to the software $beforejoin = ['table' => 'glpi_consumables', 'joinparams' => ['jointype' => 'child'] ]; $specific_itemtype = 'Consumable'; break; } $joinparams = ['jointype' => 'itemtype_item', 'specific_itemtype' => $specific_itemtype ]; $complexjoinparams = []; if (count($beforejoin)) { $complexjoinparams['beforejoin'][] = $beforejoin; $joinparams['beforejoin'] = $beforejoin; } $complexjoinparams['beforejoin'][] = ['table' => 'glpi_infocoms', 'joinparams' => $joinparams ]; $tab = []; $tab[] = [ 'id' => 'financial', 'name' => __('Financial and administrative information') ]; $tab[] = [ 'id' => '25', 'table' => 'glpi_infocoms', 'field' => 'immo_number', 'name' => __('Immobilization number'), 'forcegroupby' => true, 'joinparams' => $joinparams, 'datatype' => 'string' ]; $tab[] = [ 'id' => '26', 'table' => 'glpi_infocoms', 'field' => 'order_number', 'name' => __('Order number'), 'forcegroupby' => true, 'joinparams' => $joinparams, 'datatype' => 'string' ]; $tab[] = [ 'id' => '27', 'table' => 'glpi_infocoms', 'field' => 'delivery_number', 'name' => __('Delivery form'), 'forcegroupby' => true, 'joinparams' => $joinparams, 'datatype' => 'string' ]; $tab[] = [ 'id' => '28', 'table' => 'glpi_infocoms', 'field' => 'bill', 'name' => __('Invoice number'), 'forcegroupby' => true, 'joinparams' => $joinparams, 'datatype' => 'string' ]; $tab[] = [ 'id' => '37', 'table' => 'glpi_infocoms', 'field' => 'buy_date', 'name' => __('Date of purchase'), 'datatype' => 'date', 'forcegroupby' => true, 'joinparams' => $joinparams ]; $tab[] = [ 'id' => '38', 'table' => 'glpi_infocoms', 'field' => 'use_date', 'name' => __('Startup date'), 'datatype' => 'date', 'forcegroupby' => true, 'joinparams' => $joinparams ]; $tab[] = [ 'id' => '142', 'table' => 'glpi_infocoms', 'field' => 'delivery_date', 'name' => __('Delivery date'), 'datatype' => 'date', 'forcegroupby' => true, 'joinparams' => $joinparams ]; $tab[] = [ 'id' => '124', 'table' => 'glpi_infocoms', 'field' => 'order_date', 'name' => __('Order date'), 'datatype' => 'date', 'forcegroupby' => true, 'joinparams' => $joinparams ]; $tab[] = [ 'id' => '123', 'table' => 'glpi_infocoms', 'field' => 'warranty_date', 'name' => __('Start date of warranty'), 'datatype' => 'date', 'forcegroupby' => true, 'joinparams' => $joinparams ]; $tab[] = [ 'id' => '125', 'table' => 'glpi_infocoms', 'field' => 'inventory_date', 'name' => __('Date of last physical inventory'), 'datatype' => 'date', 'forcegroupby' => true, 'joinparams' => $joinparams ]; $tab[] = [ 'id' => '50', 'table' => 'glpi_budgets', 'field' => 'name', 'datatype' => 'dropdown', 'name' => Budget::getTypeName(1), 'forcegroupby' => true, 'joinparams' => $complexjoinparams ]; $tab[] = [ 'id' => '51', 'table' => 'glpi_infocoms', 'field' => 'warranty_duration', 'name' => __('Warranty duration'), 'forcegroupby' => true, 'joinparams' => $joinparams, 'datatype' => 'number', 'unit' => 'month', 'max' => '120', 'toadd' => [ '-1' => __('Lifelong') ] ]; $tab[] = [ 'id' => '52', 'table' => 'glpi_infocoms', 'field' => 'warranty_info', 'name' => __('Warranty information'), 'forcegroupby' => true, 'joinparams' => $joinparams, 'datatype' => 'string', ]; $tab[] = [ 'id' => '120', 'table' => 'glpi_infocoms', 'field' => 'end_warranty', 'name' => __('Warranty expiration date'), 'datatype' => 'date_delay', 'datafields' => [ '1' => 'warranty_date', '2' => 'warranty_duration' ], 'searchunit' => 'MONTH', 'delayunit' => 'MONTH', 'maybefuture' => true, 'forcegroupby' => true, 'massiveaction' => false, 'joinparams' => $joinparams ]; $tab[] = [ 'id' => '53', 'table' => 'glpi_suppliers', 'field' => 'name', 'datatype' => 'dropdown', 'name' => Supplier::getTypeName(1), 'forcegroupby' => true, 'joinparams' => $complexjoinparams ]; $tab[] = [ 'id' => '54', 'table' => 'glpi_infocoms', 'field' => 'value', 'name' => _x('price', 'Value'), 'datatype' => 'decimal', 'forcegroupby' => true, 'joinparams' => $joinparams ]; $tab[] = [ 'id' => '55', 'table' => 'glpi_infocoms', 'field' => 'warranty_value', 'name' => __('Warranty extension value'), 'datatype' => 'decimal', 'forcegroupby' => true, 'joinparams' => $joinparams ]; $tab[] = [ 'id' => '56', 'table' => 'glpi_infocoms', 'field' => 'sink_time', 'name' => __('Amortization duration'), 'forcegroupby' => true, 'joinparams' => $joinparams, 'datatype' => 'number', 'max' => '15', 'unit' => 'year' ]; $tab[] = [ 'id' => '57', 'table' => 'glpi_infocoms', 'field' => 'sink_type', 'name' => __('Amortization type'), 'forcegroupby' => true, 'joinparams' => $joinparams, 'datatype' => 'specific', 'searchequalsonfield' => 'specific', 'searchtype' => ['equals', 'notequals'] ]; $tab[] = [ 'id' => '58', 'table' => 'glpi_infocoms', 'field' => 'sink_coeff', 'name' => __('Amortization coefficient'), 'forcegroupby' => true, 'joinparams' => $joinparams, 'datatype' => 'decimal', ]; $tab[] = [ 'id' => '59', 'table' => 'glpi_infocoms', 'field' => 'alert', 'name' => __('Email alarms'), 'forcegroupby' => true, 'joinparams' => $joinparams, 'datatype' => 'specific' ]; $tab[] = [ 'id' => '122', 'table' => 'glpi_infocoms', 'field' => 'comment', 'name' => __('Comments on financial and administrative information'), 'datatype' => 'text', 'forcegroupby' => true, 'joinparams' => $joinparams ]; $tab[] = [ 'id' => '173', 'table' => 'glpi_businesscriticities', 'field' => 'completename', 'name' => _n('Business criticity', 'Business criticities', 1), 'datatype' => 'dropdown', 'forcegroupby' => true, 'joinparams' => $complexjoinparams ]; $tab[] = [ 'id' => '159', 'table' => 'glpi_infocoms', 'field' => 'decommission_date', 'name' => __('Decommission date'), 'datatype' => 'date', 'maybefuture' => true, 'forcegroupby' => true, 'joinparams' => $joinparams ]; return $tab; } public function rawSearchOptions() { $tab = []; $tab[] = [ 'id' => 'common', 'name' => __('Characteristics') ]; $tab[] = [ 'id' => '2', 'table' => $this->getTable(), 'field' => 'id', 'name' => __('ID'), 'massiveaction' => false, 'datatype' => 'number' ]; $tab[] = [ 'id' => '4', 'table' => $this->getTable(), 'field' => 'buy_date', 'name' => __('Date of purchase'), 'datatype' => 'date' ]; $tab[] = [ 'id' => '5', 'table' => $this->getTable(), 'field' => 'use_date', 'name' => __('Startup date'), 'datatype' => 'date' ]; $tab[] = [ 'id' => '24', 'table' => $this->getTable(), 'field' => 'delivery_date', 'name' => __('Delivery date'), 'datatype' => 'date', 'forcegroupby' => true ]; $tab[] = [ 'id' => '23', 'table' => $this->getTable(), 'field' => 'order_date', 'name' => __('Order date'), 'datatype' => 'date', 'forcegroupby' => true ]; $tab[] = [ 'id' => '25', 'table' => $this->getTable(), 'field' => 'warranty_date', 'name' => __('Start date of warranty'), 'datatype' => 'date', 'forcegroupby' => true ]; $tab[] = [ 'id' => '27', 'table' => $this->getTable(), 'field' => 'inventory_date', 'name' => __('Date of last physical inventory'), 'datatype' => 'date', 'forcegroupby' => true ]; $tab[] = [ 'id' => '28', 'table' => $this->getTable(), 'field' => 'decommission_date', 'name' => __('Decommission date'), 'maybefuture' => true, 'datatype' => 'date', 'forcegroupby' => true ]; $tab[] = [ 'id' => '6', 'table' => $this->getTable(), 'field' => 'warranty_duration', 'name' => __('Warranty duration'), 'datatype' => 'number', 'unit' => 'month', 'max' => '120', 'toadd' => [ '-1' => __('Lifelong') ] ]; $tab[] = [ 'id' => '7', 'table' => $this->getTable(), 'field' => 'warranty_info', 'name' => __('Warranty information'), 'datatype' => 'string' ]; $tab[] = [ 'id' => '8', 'table' => $this->getTable(), 'field' => 'warranty_value', 'name' => __('Warranty extension value'), 'datatype' => 'decimal' ]; $tab[] = [ 'id' => '9', 'table' => 'glpi_suppliers', 'field' => 'name', 'name' => Supplier::getTypeName(1), 'datatype' => 'dropdown' ]; $tab[] = [ 'id' => '10', 'table' => $this->getTable(), 'field' => 'order_number', 'name' => __('Order number'), 'datatype' => 'string', ]; $tab[] = [ 'id' => '11', 'table' => $this->getTable(), 'field' => 'delivery_number', 'name' => __('Delivery form'), 'datatype' => 'string', ]; $tab[] = [ 'id' => '12', 'table' => $this->getTable(), 'field' => 'immo_number', 'name' => __('Immobilization number'), 'datatype' => 'string', ]; $tab[] = [ 'id' => '13', 'table' => $this->getTable(), 'field' => 'value', 'name' => _x('price', 'Value'), 'datatype' => 'decimal' ]; $tab[] = [ 'id' => '14', 'table' => $this->getTable(), 'field' => 'sink_time', 'name' => __('Amortization duration'), 'datatype' => 'number', 'max' => '15', 'unit' => 'year' ]; $tab[] = [ 'id' => '15', 'table' => $this->getTable(), 'field' => 'sink_type', 'name' => __('Amortization type'), 'datatype' => 'specific', 'searchtype' => ['equals', 'notequals'] ]; $tab[] = [ 'id' => '16', 'table' => $this->getTable(), 'field' => 'comment', 'name' => __('Comments'), 'datatype' => 'text' ]; $tab[] = [ 'id' => '17', 'table' => $this->getTable(), 'field' => 'sink_coeff', 'name' => __('Amortization coefficient'), 'datatype' => 'decimal' ]; $tab[] = [ 'id' => '18', 'table' => $this->getTable(), 'field' => 'bill', 'name' => __('Invoice number'), 'datatype' => 'string', ]; $tab[] = [ 'id' => '19', 'table' => 'glpi_budgets', 'field' => 'name', 'name' => Budget::getTypeName(1), 'datatype' => 'itemlink' ]; $tab[] = [ 'id' => '20', 'table' => $this->getTable(), 'field' => 'itemtype', 'name' => _n('Type', 'Types', 1), 'datatype' => 'itemtypename', 'itemtype_list' => 'infocom_types', 'massiveaction' => false ]; $tab[] = [ 'id' => '21', 'table' => $this->getTable(), 'field' => 'items_id', 'name' => __('ID'), 'datatype' => 'integer', 'massiveaction' => false ]; $tab[] = [ 'id' => '22', 'table' => $this->getTable(), 'field' => 'alert', 'name' => __('Alarms on financial and administrative information'), 'datatype' => 'integer' ]; $tab[] = [ 'id' => '80', 'table' => 'glpi_entities', 'field' => 'completename', 'name' => Entity::getTypeName(1), 'massiveaction' => false, 'datatype' => 'dropdown' ]; $tab[] = [ 'id' => '86', 'table' => $this->getTable(), 'field' => 'is_recursive', 'name' => __('Child entities'), 'datatype' => 'bool' ]; $tab[] = [ 'id' => '173', 'table' => 'glpi_businesscriticities', 'field' => 'completename', 'name' => _n('Business criticity', 'Business criticities', 1), 'datatype' => 'dropdown' ]; return $tab; } /** * Display debug information for infocom of current object **/ public function showDebug() { $item = ['item_name' => '', 'warrantyexpiration' => '', 'itemtype' => $this->fields['itemtype'], 'items_id' => $this->fields['items_id'] ]; $options['entities_id'] = $this->getEntityID(); $options['items'] = [$item]; NotificationEvent::debugEvent($this, $options); } /** * Get date using a begin date and a period in month * * @param string $from begin date * @param integer $addwarranty period in months * @param integer $deletenotice period in months of notice (default 0) * @param boolean $color if show expire date in red color (false by default) * @param boolean $auto_renew * * @return string expiration date **/ public static function getWarrantyExpir($from, $addwarranty, $deletenotice = 0, $color = false, $auto_renew = false) { // Life warranty if ( ($addwarranty == -1) && ($deletenotice == 0) ) { return __('Never'); } if (empty($from)) { return ""; } $timestamp = strtotime("$from+$addwarranty month -$deletenotice month"); if ($auto_renew && $addwarranty > 0) { while ($timestamp < time()) { $datetime = new DateTime(); $datetime->setTimestamp($timestamp); $timestamp = strtotime($datetime->format("Y-m-d H:i:s") . "+$addwarranty month"); } } if ($color && ($timestamp < time())) { return "<span class='red'>" . Html::convDate(date("Y-m-d", $timestamp)) . "</span>"; } return Html::convDate(date("Y-m-d", $timestamp)); } public static function getMassiveActionsForItemtype( array &$actions, $itemtype, $is_deleted = 0, CommonDBTM $checkitem = null ) { $action_name = __CLASS__ . MassiveAction::CLASS_ACTION_SEPARATOR . 'activate'; if ( Infocom::canApplyOn($itemtype) && static::canCreate() ) { $actions[$action_name] = "<i class='fa-fw " . self::getIcon() . "'></i>" . __('Enable the financial and administrative information'); } } public static function processMassiveActionsForOneItemtype( MassiveAction $ma, CommonDBTM $item, array $ids ) { switch ($ma->getAction()) { case 'activate': $ic = new self(); if ($ic->canCreate()) { $itemtype = $item->getType(); foreach ($ids as $key) { if (!$ic->getFromDBforDevice($itemtype, $key)) { $input = ['itemtype' => $itemtype, 'items_id' => $key ]; if ($ic->can(-1, CREATE, $input)) { if ($ic->add($input)) { $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_OK); } else { $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_KO); $ma->addMessage($ic->getErrorMessage(ERROR_ON_ACTION)); } } else { $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_NORIGHT); $ma->addMessage($ic->getErrorMessage(ERROR_RIGHT)); } } else { // Infocom already exists for this item, nothing to do. $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_OK); } } } return; } parent::processMassiveActionsForOneItemtype($ma, $item, $ids); } /** * @since 9.1.7 * @see CommonDBChild::canUpdateItem() **/ public function canUpdateItem() { return Session::haveRight(static::$rightname, UPDATE); } /** * @since 9.1.7 * @see CommonDBChild::canPurgeItem() **/ public function canPurgeItem() { return Session::haveRight(static::$rightname, PURGE); } /** * @since 9.1.7 * @see CommonDBChild::canCreateItem() **/ public function canCreateItem() { return Session::haveRight(static::$rightname, CREATE); } /** * Get item types * * @since 9.3.1 * * @param array $where Where clause * * @return DBmysqlIterator */ public static function getTypes($where) { global $DB; $types_iterator = $DB->request([ 'SELECT' => 'itemtype', 'DISTINCT' => true, 'FROM' => 'glpi_infocoms', 'WHERE' => [ 'NOT' => ['itemtype' => self::getExcludedTypes()] ] + $where, 'ORDER' => 'itemtype' ]); return $types_iterator; } /** * Get excluded itemtypes * * @since 9.3.1 * * @return array */ public static function getExcludedTypes() { return ['ConsumableItem', 'CartridgeItem', 'Software']; } public static function getIcon() { return "fas fa-wallet"; } }