Current File : /home/escuelai/public_html/it/src/Budget.php |
<?php
/**
* ---------------------------------------------------------------------
*
* GLPI - Gestionnaire Libre de Parc Informatique
*
* http://glpi-project.org
*
* @copyright 2015-2022 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->getType() == __CLASS__) {
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'
];
$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()
{
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()
{
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
] + getEntitiesRestrictCriteria($table, 'entities_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
] + getEntitiesRestrictCriteria($table, 'entities_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
] + getEntitiesRestrictCriteria($table, 'entities_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
] + getEntitiesRestrictCriteria($table, 'entities_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 (!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'];
$total += $values['sumvalue'];
$totalbytypes[$itemtype] += $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>$typename</th>";
}
}
echo "<th>" . __('Total') . "</th>";
echo "</tr>";
// get all entities ordered by names
$allentities = getAllDataFromTable('glpi_entities', ['ORDER' => 'completename'], true);
foreach (array_keys($allentities) as $entity) {
if (isset($entities_values[$entity])) {
echo "<tr class='tab_bg_1'>";
echo "<td class='b'>" . Dropdown::getDropdownName('glpi_entities', $entity) . "</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>";
if ($_SESSION['glpiactive_entity'] == $budget->fields['entities_id']) {
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";
}
}