%PDF- %PDF-
Direktori : /var/www/projetos/suporte.iigd.com.br/src/ |
Current File : /var/www/projetos/suporte.iigd.com.br/src/Budget.php |
<?php /** * --------------------------------------------------------------------- * * GLPI - Gestionnaire Libre de Parc Informatique * * http://glpi-project.org * * @copyright 2015-2024 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/>. * * --------------------------------------------------------------------- */ /** * Budget class */ class Budget extends CommonDropdown { use Glpi\Features\Clonable; // From CommonDBTM public $dohistory = true; public static $rightname = 'budget'; protected $usenotepad = true; public $can_be_translated = false; public function getCloneRelations(): array { return [ Document_Item::class ]; } public static function getTypeName($nb = 0) { return _n('Budget', 'Budgets', $nb); } public function defineTabs($options = []) { $ong = []; $this->addDefaultFormTab($ong); $this->addStandardTab(__CLASS__, $ong, $options); $this->addStandardTab('Document_Item', $ong, $options); $this->addStandardTab('KnowbaseItem_Item', $ong, $options); $this->addStandardTab('ManualLink', $ong, $options); $this->addStandardTab('Notepad', $ong, $options); $this->addStandardTab('Log', $ong, $options); return $ong; } public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { if (!$withtemplate) { switch ($item->getType()) { case __CLASS__: return [1 => __('Main'), 2 => _n('Item', 'Items', Session::getPluralNumber()) ]; } } return ''; } public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { if ($item instanceof self) { switch ($tabnum) { case 1: $item->showValuesByEntity(); break; case 2: $item->showItems(); break; } } return true; } /** * Print the contact form * * @param integer $ID Integer ID of the item * @param array $options Array of possible options: * - target for the Form * - withtemplate : template or basic item * * @return void|boolean (display) Returns false if there is a rights error. **/ public function showForm($ID, array $options = []) { $rowspan = 3; if ($ID > 0) { $rowspan++; } $this->initForm($ID, $options); $this->showFormHeader($options); echo "<tr class='tab_bg_1'>"; echo "<td>" . __('Name') . "</td>"; echo "<td>"; echo Html::input('name', ['value' => $this->fields['name']]); echo "</td>"; echo "<td>" . _n('Type', 'Types', 1) . "</td>"; echo "<td>"; Dropdown::show('BudgetType', ['value' => $this->fields['budgettypes_id']]); echo "</td></tr>"; echo "<tr class='tab_bg_1'>"; echo "<td>" . _x('price', 'Value') . "</td>"; echo "<td><input type='text' name='value' size='14' value='" . Html::formatNumber($this->fields["value"], true) . "' class='form-control'></td>"; echo "<td rowspan='$rowspan' class='middle right'>" . __('Comments') . "</td>"; echo "<td class='center middle' rowspan='$rowspan'>" . "<textarea class='form-control' name='comment' >" . $this->fields["comment"] . "</textarea>" . "</td></tr>"; echo "<tr class='tab_bg_1'>"; echo "<td>" . __('Start date') . "</td>"; echo "<td>"; Html::showDateField("begin_date", ['value' => $this->fields["begin_date"]]); echo "</td></tr>"; echo "<tr class='tab_bg_1'>"; echo "<td>" . __('End date') . "</td>"; echo "<td>"; Html::showDateField("end_date", ['value' => $this->fields["end_date"]]); echo "</td></tr>"; echo "<tr class='tab_bg_1'>"; echo "<td>" . Location::getTypeName(1) . "</td>"; echo "<td>"; Location::dropdown(['value' => $this->fields["locations_id"], 'entity' => $this->fields["entities_id"] ]); echo "</td><td colspan='2'></td></tr>"; $this->showFormButtons($options); return true; } public function prepareInputForAdd($input) { if (isset($input["id"]) && ($input["id"] > 0)) { $input["_oldID"] = $input["id"]; } unset($input['id']); unset($input['withtemplate']); return $input; } public function rawSearchOptions() { $tab = []; $tab[] = [ 'id' => 'common', 'name' => __('Characteristics') ]; $tab[] = [ 'id' => '1', 'table' => $this->getTable(), 'field' => 'name', 'name' => __('Name'), 'datatype' => 'itemlink', 'massiveaction' => false, ]; $tab[] = [ 'id' => '2', 'table' => $this->getTable(), 'field' => 'id', 'name' => __('ID'), 'massiveaction' => false, 'datatype' => 'number' ]; $tab[] = [ 'id' => '19', 'table' => $this->getTable(), 'field' => 'date_mod', 'name' => __('Last update'), 'datatype' => 'datetime', 'massiveaction' => false ]; $tab[] = [ 'id' => '121', 'table' => $this->getTable(), 'field' => 'date_creation', 'name' => __('Creation date'), 'datatype' => 'datetime', 'massiveaction' => false ]; $tab[] = [ 'id' => '4', 'table' => 'glpi_budgettypes', 'field' => 'name', 'name' => _n('Type', 'Types', 1), 'datatype' => 'dropdown' ]; $tab[] = [ 'id' => '5', 'table' => $this->getTable(), 'field' => 'begin_date', 'name' => __('Start date'), 'datatype' => 'date' ]; $tab[] = [ 'id' => '6', 'table' => $this->getTable(), 'field' => 'end_date', 'name' => __('End date'), 'datatype' => 'date' ]; $tab[] = [ 'id' => '7', 'table' => $this->getTable(), 'field' => 'value', 'name' => _x('price', 'Value'), 'datatype' => 'decimal', 'searchtype' => ['contains', 'notcontains', 'equals', 'notequals'], ]; $tab[] = [ 'id' => '16', 'table' => $this->getTable(), 'field' => 'comment', 'name' => __('Comments'), 'datatype' => 'text' ]; $tab[] = [ 'id' => '50', 'table' => $this->getTable(), 'field' => 'template_name', 'name' => __('Template name'), 'datatype' => 'text', 'massiveaction' => false, 'nosearch' => true, 'nodisplay' => true, ]; $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' ]; // add objectlock search options $tab = array_merge($tab, ObjectLock::rawSearchOptionsToAdd(get_class($this))); $tab = array_merge($tab, Location::rawSearchOptionsToAdd()); $tab = array_merge($tab, Notepad::rawSearchOptionsToAdd()); return $tab; } /** * Print the HTML array of Items on a budget * * @return void **/ public function showItems() { /** @var \DBmysql $DB */ global $DB; $budgets_id = $this->fields['id']; if (!$this->can($budgets_id, READ)) { return false; } $iterator = $DB->request([ 'SELECT' => 'itemtype', 'DISTINCT' => true, 'FROM' => 'glpi_infocoms', 'WHERE' => [ 'budgets_id' => $budgets_id, 'NOT' => ['itemtype' => ['ConsumableItem', 'CartridgeItem', 'Software']] ], 'ORDER' => 'itemtype' ]); $number = count($iterator); echo "<div class='spaced'><table class='tab_cadre_fixe'>"; echo "<tr><th colspan='2'>"; Html::printPagerForm(); echo "</th><th colspan='4'>"; if ($number == 0) { echo __('No associated item'); } else { echo _n('Associated item', 'Associated items', $number); } echo "</th></tr>"; echo "<tr><th>" . _n('Type', 'Types', 1) . "</th>"; echo "<th>" . Entity::getTypeName(1) . "</th>"; echo "<th>" . __('Name') . "</th>"; echo "<th>" . __('Serial number') . "</th>"; echo "<th>" . __('Inventory number') . "</th>"; echo "<th>" . _x('price', 'Value') . "</th>"; echo "</tr>"; $num = 0; $itemtypes = []; foreach ($iterator as $row) { $itemtypes[] = $row['itemtype']; } $itemtypes[] = 'Contract'; $itemtypes[] = 'Ticket'; $itemtypes[] = 'Problem'; $itemtypes[] = 'Change'; $itemtypes[] = 'Project'; foreach ($itemtypes as $itemtype) { if (!($item = getItemForItemtype($itemtype))) { continue; } if ($item->canView()) { switch ($itemtype) { case 'Contract': $criteria = [ 'SELECT' => [ $item->getTable() . '.id', $item->getTable() . '.entities_id', 'SUM' => 'glpi_contractcosts.cost AS value' ], 'FROM' => 'glpi_contractcosts', 'INNER JOIN' => [ $item->getTable() => [ 'ON' => [ $item->getTable() => 'id', 'glpi_contractcosts' => 'contracts_id' ] ] ], 'WHERE' => [ 'glpi_contractcosts.budgets_id' => $budgets_id, $item->getTable() . '.is_template' => 0 ] + getEntitiesRestrictCriteria($item->getTable()), 'GROUPBY' => [ $item->getTable() . '.id', $item->getTable() . '.entities_id' ], 'ORDERBY' => [ $item->getTable() . '.entities_id', $item->getTable() . '.name' ] ]; break; case 'Ticket': case 'Problem': case 'Change': $costtable = getTableForItemType($item->getType() . 'Cost'); $sum = new QueryExpression( "SUM(" . $DB->quoteName("$costtable.actiontime") . " * " . $DB->quoteName("$costtable.cost_time") . "/" . HOUR_TIMESTAMP . " + " . $DB->quoteName("$costtable.cost_fixed") . " + " . $DB->quoteName("$costtable.cost_material") . ") AS " . $DB->quoteName('value') ); $criteria = [ 'SELECT' => [ $item->getTable() . '.id', $item->getTable() . '.entities_id', $sum ], 'FROM' => $costtable, 'INNER JOIN' => [ $item->getTable() => [ 'ON' => [ $item->getTable() => 'id', $costtable => $item->getForeignKeyField() ] ] ], 'WHERE' => [ $costtable . '.budgets_id' => $budgets_id ] + getEntitiesRestrictCriteria($item->getTable()), 'GROUPBY' => [ $item->getTable() . '.id', $item->getTable() . '.entities_id' ], 'ORDERBY' => [ $item->getTable() . '.entities_id', $item->getTable() . '.name' ] ]; break; case 'Project': $criteria = [ 'SELECT' => [ $item->getTable() . '.id', $item->getTable() . '.entities_id', 'SUM' => 'glpi_projectcosts.cost AS value' ], 'FROM' => 'glpi_projectcosts', 'INNER JOIN' => [ $item->getTable() => [ 'ON' => [ $item->getTable() => 'id', 'glpi_projectcosts' => 'projects_id' ] ] ], 'WHERE' => [ 'glpi_projectcosts.budgets_id' => $budgets_id ] + getEntitiesRestrictCriteria($item->getTable()), 'GROUPBY' => [ $item->getTable() . '.id', $item->getTable() . '.entities_id' ], 'ORDERBY' => [ $item->getTable() . '.entities_id', $item->getTable() . '.name' ] ]; break; case 'Cartridge': $criteria = [ 'SELECT' => [ $item->getTable() . '.*', 'glpi_cartridgeitems.name', 'glpi_infocoms.value' ], 'FROM' => 'glpi_infocoms', 'INNER JOIN' => [ $item->getTable() => [ 'ON' => [ $item->getTable() => 'id', 'glpi_infocoms' => 'items_id' ] ], 'glpi_cartridgeitems' => [ 'ON' => [ $item->getTable() => 'cartridgeitems_id', 'glpi_cartridgeitems' => 'id' ] ] ], 'WHERE' => [ 'glpi_infocoms.itemtype' => $itemtype, 'glpi_infocoms.budgets_id' => $budgets_id ] + getEntitiesRestrictCriteria($item->getTable()), 'ORDERBY' => [ 'entities_id', 'glpi_cartridgeitems.name' ] ]; break; case 'Consumable': $criteria = [ 'SELECT' => [ $item->getTable() . '.*', 'glpi_consumableitems.name', 'glpi_infocoms.value' ], 'FROM' => 'glpi_infocoms', 'INNER JOIN' => [ $item->getTable() => [ 'ON' => [ $item->getTable() => 'id', 'glpi_infocoms' => 'items_id' ] ], 'glpi_consumableitems' => [ 'ON' => [ $item->getTable() => 'consumableitems_id', 'glpi_consumableitems' => 'id' ] ] ], 'WHERE' => [ 'glpi_infocoms.itemtype' => $itemtype, 'glpi_infocoms.budgets_id' => $budgets_id ] + getEntitiesRestrictCriteria($item->getTable()), 'ORDERBY' => [ 'entities_id', 'glpi_consumableitems.name' ] ]; break; default: $criteria = [ 'SELECT' => [ $item->getTable() . '.*', 'glpi_infocoms.value', ], 'FROM' => 'glpi_infocoms', 'INNER JOIN' => [ $item->getTable() => [ 'ON' => [ $item->getTable() => 'id', 'glpi_infocoms' => 'items_id' ] ] ], 'WHERE' => [ 'glpi_infocoms.itemtype' => $itemtype, 'glpi_infocoms.budgets_id' => $budgets_id ] + getEntitiesRestrictCriteria($item->getTable()), 'ORDERBY' => [ $item->getTable() . '.entities_id' ] ]; if ($item->maybeTemplate()) { $criteria['WHERE'][$item->getTable() . '.is_template'] = 0; } if ($item instanceof Item_Devices) { $criteria['ORDERBY'][] = $item->getTable() . '.itemtype'; } else { $criteria['ORDERBY'][] = $item->getTable() . '.name'; } break; } $iterator = $DB->request($criteria); $nb = count($iterator); if ($nb > $_SESSION['glpilist_limit']) { echo "<tr class='tab_bg_1'>"; $name = $item->getTypeName($nb); //TRANS: %1$s is a name, %2$s is a number echo "<td class='center'>" . sprintf(__('%1$s: %2$s'), $name, $nb) . "</td>"; echo "<td class='center' colspan='2'>"; $opt = ['order' => 'ASC', 'is_deleted' => 0, 'reset' => 'reset', 'start' => 0, 'sort' => 80, 'criteria' => [0 => ['value' => '$$$$' . $budgets_id, 'searchtype' => 'contains', 'field' => 50 ] ] ]; echo "<a href='" . $item->getSearchURL() . "?" . Toolbox::append_params($opt) . "'>" . __('Device list') . "</a></td>"; echo "<td class='center'>-</td><td class='center'>-</td><td class='center'>-" . "</td></tr>"; } else if ($nb) { for ($prem = true; $iterator->valid(); $prem = false) { $data = $iterator->current(); $name = NOT_AVAILABLE; if ($item->getFromDB($data["id"])) { if ($item instanceof Item_Devices) { $tmpitem = new $item::$itemtype_2(); if ($tmpitem->getFromDB($data[$item::$items_id_2])) { $name = $tmpitem->getLink(['additional' => true]); } } else { $name = $item->getLink(['additional' => true]); } } echo "<tr class='tab_bg_1'>"; if ($prem) { $typename = $item->getTypeName($nb); echo "<td class='center top' rowspan='$nb'>" . ($nb > 1 ? sprintf(__('%1$s: %2$s'), $typename, $nb) : $typename) . "</td>"; } echo "<td class='center'>" . Dropdown::getDropdownName( "glpi_entities", $data["entities_id"] ); echo "</td><td class='center"; echo (isset($data['is_deleted']) && $data['is_deleted'] ? " tab_bg_2_2'" : "'"); echo ">" . $name . "</td>"; echo "<td class='center'>" . (isset($data["serial"]) ? "" . $data["serial"] . "" : "-"); echo "</td>"; echo "<td class='center'>" . (isset($data["otherserial"]) ? "" . $data["otherserial"] . "" : "-") . "</td>"; echo "<td class='center'>" . (isset($data["value"]) ? "" . Html::formatNumber($data["value"], true) . "" : "-"); echo "</td></tr>"; $iterator->next(); } } $num += $nb; } } if ($num > 0) { echo "<tr class='tab_bg_2'>"; echo "<td class='center b'>" . sprintf(__('%1$s = %2$s'), __('Total'), $num) . "</td>"; echo "<td colspan='5'> </td></tr> "; } echo "</table></div>"; } /** * Print the HTML array of value consumed for a budget * * @return void **/ public function showValuesByEntity() { /** @var \DBmysql $DB */ global $DB; $budgets_id = $this->fields['id']; if (!$this->can($budgets_id, READ)) { return false; } $types_iterator = Infocom::getTypes( [ 'budgets_id' => $budgets_id ] + getEntitiesRestrictCriteria('glpi_infocoms', 'entities_id') ); $total = 0; $totalbytypes = []; $itemtypes = []; $entities_values = []; $entitiestype_values = []; $found_types = []; foreach ($types_iterator as $types) { $itemtypes[] = $types['itemtype']; } $itemtypes[] = 'Contract'; $itemtypes[] = 'Ticket'; $itemtypes[] = 'Problem'; $itemtypes[] = 'Project'; $itemtypes[] = 'Change'; foreach ($itemtypes as $itemtype) { if (!($item = getItemForItemtype($itemtype))) { continue; } $table = getTableForItemType($itemtype); switch ($itemtype) { case 'Contract': $criteria = [ 'SELECT' => [ $table . '.entities_id', 'SUM' => 'glpi_contractcosts.cost AS sumvalue' ], 'FROM' => 'glpi_contractcosts', 'INNER JOIN' => [ $table => [ 'ON' => [ $table => 'id', 'glpi_contractcosts' => 'contracts_id' ] ] ], 'WHERE' => [ 'glpi_contractcosts.budgets_id' => $budgets_id ], 'GROUPBY' => [ $table . '.entities_id' ] ]; break; case 'Project': $costtable = getTableForItemType($item->getType() . 'Cost'); $criteria = [ 'SELECT' => [ $table . '.entities_id', 'SUM' => 'glpi_projectcosts.cost AS sumvalue' ], 'FROM' => 'glpi_projectcosts', 'INNER JOIN' => [ $table => [ 'ON' => [ $table => 'id', 'glpi_projectcosts' => 'projects_id' ] ] ], 'WHERE' => [ 'glpi_projectcosts.budgets_id' => $budgets_id ], 'GROUPBY' => [ $item->getTable() . '.entities_id' ] ]; break; case 'Ticket': case 'Problem': case 'Change': $costtable = getTableForItemType($item->getType() . 'Cost'); $sum = new QueryExpression( "SUM(" . $DB->quoteName("$costtable.actiontime") . " * " . $DB->quoteName("$costtable.cost_time") . "/" . HOUR_TIMESTAMP . " + " . $DB->quoteName("$costtable.cost_fixed") . " + " . $DB->quoteName("$costtable.cost_material") . ") AS " . $DB->quoteName('sumvalue') ); $criteria = [ 'SELECT' => [ $item->getTable() . '.entities_id', $sum ], 'FROM' => $costtable, 'INNER JOIN' => [ $table => [ 'ON' => [ $table => 'id', $costtable => $item->getForeignKeyField() ] ] ], 'WHERE' => [ $costtable . '.budgets_id' => $budgets_id ], 'GROUPBY' => [ $item->getTable() . '.entities_id' ] ]; break; default: $criteria = [ 'SELECT' => [ $table . '.entities_id', 'SUM' => 'glpi_infocoms.value AS sumvalue', ], 'FROM' => $table, 'INNER JOIN' => [ 'glpi_infocoms' => [ 'ON' => [ $table => 'id', 'glpi_infocoms' => 'items_id' ] ] ], 'WHERE' => [ 'glpi_infocoms.itemtype' => $itemtype, 'glpi_infocoms.budgets_id' => $budgets_id ], 'GROUPBY' => [ $table . '.entities_id' ] ]; if ($item->maybeTemplate()) { $criteria['WHERE'][$table . '.is_template'] = 0; } break; } $iterator = $DB->request($criteria); $nb = count($iterator); if ($nb) { $found_types[$itemtype] = $item->getTypeName(1); $totalbytypes[$itemtype] = 0; //Store, for each entity, the budget spent foreach ($iterator as $values) { if (in_array($values['entities_id'], $_SESSION['glpiactiveentities'])) { if (!isset($entities_values[$values['entities_id']])) { $entities_values[$values['entities_id']] = 0; } if (!isset($entitiestype_values[$values['entities_id']][$itemtype])) { $entitiestype_values[$values['entities_id']][$itemtype] = 0; } $entities_values[$values['entities_id']] += $values['sumvalue']; $entitiestype_values[$values['entities_id']][$itemtype] += $values['sumvalue']; $totalbytypes[$itemtype] += $values['sumvalue']; } else { if (!isset($entities_values[-1])) { $entities_values[-1] = 0; } $entities_values[-1] += $values['sumvalue']; $entitiestype_values[-1][$itemtype] = '-'; } $total += $values['sumvalue']; } } } $budget = new self(); $budget->getFromDB($budgets_id); $colspan = count($found_types) + 2; echo "<div class='spaced'><table class='tab_cadre_fixehov'>"; echo "<tr class='noHover'><th colspan='$colspan'>" . __('Total spent on the budget') . "</th></tr>"; echo "<tr><th>" . Entity::getTypeName(1) . "</th>"; if (count($found_types)) { foreach ($found_types as $type => $typename) { echo "<th class='right'>$typename</th>"; } } echo "<th class='right'>" . __('Total') . "</th>"; echo "</tr>"; // get all entities ordered by names $allentities = getAllDataFromTable('glpi_entities', ['ORDER' => 'completename'], true); $allentities[-1] = -1; ksort($allentities); foreach (array_keys($allentities) as $entity) { if (isset($entities_values[$entity])) { echo "<tr class='tab_bg_1'>"; echo "<td class='b'>"; if ($entity == -1) { echo __('Other entities'); } else { echo Dropdown::getDropdownName('glpi_entities', $entity); } echo "</td>"; if (count($found_types)) { foreach ($found_types as $type => $typename) { echo "<td class='numeric'>"; $typevalue = 0; if (isset($entitiestype_values[$entity][$type])) { $typevalue = $entitiestype_values[$entity][$type]; } echo Html::formatNumber($typevalue); echo "</td>"; } } echo "<td class='right b'>" . Html::formatNumber($entities_values[$entity]) . "</td>"; echo "</tr>"; } } if (count($found_types)) { echo "<tr class='tab_bg_1'>"; echo "<td class='right b'>" . __('Total') . "</td>"; foreach ($found_types as $type => $typename) { echo "<td class='numeric b'>"; echo Html::formatNumber($totalbytypes[$type]); echo "</td>"; } echo "<td class='numeric b'>" . Html::formatNumber($total) . "</td>"; echo "</tr>"; } echo "<tr class='tab_bg_1 noHover'><th colspan='$colspan'><br></th></tr>"; echo "<tr class='tab_bg_1 noHover'>"; echo "<td class='right' colspan='" . ($colspan - 1) . "'>" . __('Total spent on the budget') . "</td>"; echo "<td class='numeric b'>" . Html::formatNumber($total) . "</td></tr>"; echo "<tr class='tab_bg_1 noHover'>"; echo "<td class='right' colspan='" . ($colspan - 1) . "'>" . __('Total remaining on the budget') . "</td>"; echo "<td class='numeric b'>" . Html::formatNumber($budget->fields['value'] - $total) . "</td></tr>"; echo "</table></div>"; } public static function getIcon() { return "ti ti-calculator"; } }