Continuing the integration of the new data model...

SVN:trunk[544]
This commit is contained in:
Denis Flaven
2010-07-04 08:05:12 +00:00
parent dbee38dfd1
commit 56a084cb7b
7 changed files with 243 additions and 75 deletions

View File

@@ -150,7 +150,7 @@ abstract class cmdbAbstractObject extends CMDBObject
$aParams = array(
'target_attr' => $oAttDef->GetExtKeyToMe(),
'object_id' => $this->GetKey(),
'menu' => false,
'menu' => true,
);
}
else
@@ -165,7 +165,7 @@ abstract class cmdbAbstractObject extends CMDBObject
'object_id' => $this->GetKey(),
'target_attr' => $oAttDef->GetExtKeyToRemote(),
'view_link' => false,
'menu' => false,
'menu' => true,
);
}
$oPage->p("<img src=\"".MetaModel::GetClassIcon($sTargetClass)."\" style=\"vertical-align:middle;\">&nbsp;".$oAttDef->GetDescription());

View File

@@ -1166,6 +1166,13 @@ class AttributeDateTime extends AttributeDBField
public function GetTypeDesc() {return "Date and time";}
public function GetEditClass() {return "DateTime";}
protected function GetSQLCol() {return "TIMESTAMP";}
public static function GetAsUnixSeconds($value)
{
$oDeadlineDateTime = new DateTime($value, self::$const_TIMEZONE);
$iUnixSeconds = $oDeadlineDateTime->format('U');
return $iUnixSeconds;
}
// #@# THIS HAS TO REVISED
// Having null not allowed was interpreted by mySQL
@@ -1294,7 +1301,63 @@ class AttributeDateTime extends AttributeDBField
return '"'.$sEscaped.'"';
}
}
/**
* A dead line stored as a date & time
* The only difference with the DateTime attribute is the display:
* relative to the current time
*/
class AttributeDeadline extends AttributeDateTime
{
public function GetAsHTML($value)
{
$sResult = '';
if ($value !== null)
{
$value = AttributeDateTime::GetAsUnixSeconds($value);
$difference = $value - time();
if ($difference >= 0)
{
$sResult = self::FormatDuration($difference);
}
else
{
$sResult = Dict::Format('UI:DeadlineMissedBy_duration', self::FormatDuration(-$difference));
}
}
return $sResult;
}
static function FormatDuration($duration)
{
$days = floor($duration / 86400);
$hours = floor(($duration - (86400*$days)) / 3600);
$minutes = floor(($duration - (86400*$days + 3600*$hours)) / 60);
$sResult = '';
if ($duration < 60)
{
// Less than 1 min
$sResult =Dict::S('UI:Deadline_LessThan1Min');
}
else if ($duration < 3600)
{
// less than 1 hour, display it in minutes
$sResult =Dict::Format('UI:Deadline_Minutes', $minutes);
}
else if ($duration < 86400)
{
// Less that 1 day, display it in hours/minutes
$sResult =Dict::Format('UI:Deadline_Hours_Minutes', $hours, $minutes);
}
else
{
// Less that 1 day, display it in hours/minutes
$sResult =Dict::Format('UI:Deadline_Days_Hours_Minutes', $days, $hours, $minutes);
}
return $sResult;
}
}
// Init static constant once for all (remove when PHP allows real static const)
AttributeDateTime::InitStatics();

View File

@@ -797,6 +797,12 @@ When associated with a trigger, each action is given an "order" number, specifyi
'UI:OpenDocumentInNewWindow_' => 'Open this document in a new window: %1$s',
'UI:DownloadDocument_' => 'Download this document: %1$s',
'UI:Document:NoPreview' => 'No preview is available for this type of document',
'UI:DeadlineMissedBy_duration' => 'Missed by %1$s',
'UI:Deadline_LessThan1Min' => '< 1 min',
'UI:Deadline_Minutes' => '%1$d min',
'UI:Deadline_Hours_Minutes' => '%1$dh %2$dmin',
'UI:Deadline_Days_Hours_Minutes' => '%1$dd %2$dh %3$dmin',
));

View File

@@ -799,6 +799,12 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé
'UI:iTopVersion:Short' => 'iTop version %1$s',
'UI:iTopVersion:Long' => 'iTop version %1$s-%2$s du %3$s',
'UI:DeadlineMissedBy_duration' => 'Passé de %1$s',
'UI:Deadline_LessThan1Min' => '< 1 min',
'UI:Deadline_Minutes' => '%1$d min',
'UI:Deadline_Hours_Minutes' => '%1$dh %2$dmin',
'UI:Deadline_Days_Hours_Minutes' => '%1$dj %2$dh %3$dmin',
));
?>

View File

@@ -26,6 +26,8 @@
require_once('../application/cmdbabstract.class.inc.php');
require_once('../application/template.class.inc.php');
MetaModel::RegisterRelation("impacts", array("description"=>"Objects impacted by", "verb_down"=>"impacts", "verb_up"=>"is impacted by"));
class Organization extends cmdbAbstractObject
{
@@ -660,6 +662,20 @@ abstract class FunctionalCI extends cmdbAbstractObject
MetaModel::Init_SetZListItems('standard_search', array('name', 'status', 'owner_id', 'importance'));
MetaModel::Init_SetZListItems('list', array('status', 'owner_id', 'importance'));
}
public static function GetRelationQueries($sRelCode)
{
switch ($sRelCode)
{
case "impacts":
$aRels = array(
"contact" => array("sQuery"=>"SELECT Contact AS c JOIN lnkCIToContact AS l1 ON l1.contact_id = c.id WHERE l1.ci_id = :this->id", "bPropagate"=>true, "iDistance"=>3),
"solution" => array("sQuery"=>"SELECT ApplicationSolution AS s JOIN lnkSolutionToCI AS l1 ON l1.solution_id = s.id WHERE l1.ci_id = :this->id", "bPropagate"=>true, "iDistance"=>2),
);
return array_merge($aRels, parent::GetRelationQueries($sRelCode));
}
}
}
class ApplicationInstance extends FunctionalCI
{
@@ -695,7 +711,21 @@ class ApplicationInstance extends FunctionalCI
MetaModel::Init_SetZListItems('standard_search', array('name', 'status', 'owner_id', 'importance', 'device_id', 'licence_id', 'application_id', 'version', 'description'));
MetaModel::Init_SetZListItems('list', array('status', 'owner_id', 'importance', 'device_id', 'licence_id', 'application_id', 'version', 'description'));
}
public static function GetRelationQueries($sRelCode)
{
switch ($sRelCode)
{
case "impacts":
$aRels = array(
// Actually this should be limited to the ApplicationInstances based on a DBServer Application type...
"db_instances" => array("sQuery"=>"SELECT DatabaseInstance AS db WHERE db.db_server_instance_id = :this->id", "bPropagate"=>true, "iDistance"=>5),
);
return array_merge($aRels, parent::GetRelationQueries($sRelCode));
}
}
}
class DatabaseInstance extends FunctionalCI
{
@@ -758,6 +788,18 @@ class ApplicationSolution extends FunctionalCI
MetaModel::Init_SetZListItems('standard_search', array('name', 'status', 'owner_id', 'importance', 'description'));
MetaModel::Init_SetZListItems('list', array('status', 'owner_id', 'importance', 'description'));
}
public static function GetRelationQueries($sRelCode)
{
switch ($sRelCode)
{
case "impacts":
$aRels = array(
"process" => array("sQuery"=>"SELECT BusinessProcess AS p JOIN lnkProcessToSolution AS l1 ON l1.process_id = p.id WHERE l1.solution_id = :this->id", "bPropagate"=>true, "iDistance"=>3),
);
return array_merge($aRels, parent::GetRelationQueries($sRelCode));
}
}
}
class BusinessProcess extends FunctionalCI
{
@@ -883,6 +925,18 @@ abstract class Device extends ConnectableCI
MetaModel::Init_SetZListItems('standard_search', array('name', 'status', 'owner_id', 'importance', 'brand', 'model', 'serial_number', 'asset_ref'));
MetaModel::Init_SetZListItems('list', array('status', 'owner_id', 'importance', 'brand', 'model', 'serial_number', 'asset_ref'));
}
public static function GetRelationQueries($sRelCode)
{
switch ($sRelCode)
{
case "impacts":
$aRels = array(
"applications" => array("sQuery"=>"SELECT ApplicationInstance AS app WHERE app.device_id = :this->id", "bPropagate"=>true, "iDistance"=>5),
);
return array_merge($aRels, parent::GetRelationQueries($sRelCode));
}
}
}
class PC extends Device
{

View File

@@ -202,14 +202,14 @@ class Incident extends Ticket
MetaModel::Init_AddAttribute(new AttributeDateTime("closure_date", array("allowed_values"=>null, "sql"=>"closure_date", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDateTime("last_update", array("allowed_values"=>null, "sql"=>"last_update", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDateTime("assignment_date", array("allowed_values"=>null, "sql"=>"assignment_date", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDateTime("escalation_deadline", array("allowed_values"=>null, "sql"=>"escalation_deadline", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDateTime("closure_deadline", array("allowed_values"=>null, "sql"=>"closure_deadline", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDeadline("escalation_deadline", array("allowed_values"=>null, "sql"=>"escalation_deadline", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDeadline("closure_deadline", array("allowed_values"=>null, "sql"=>"closure_deadline", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("resolution_code", array("allowed_values"=>new ValueSetEnum('fixed,duplicate,couldnotreproduce,irrelevant'), "sql"=>"resolution_code", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("solution", array("allowed_values"=>null, "sql"=>"solution", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("user_satisfaction", array("allowed_values"=>new ValueSetEnum('1,2,3,4'), "sql"=>"user_satisfaction", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("user_commment", array("allowed_values"=>null, "sql"=>"user_commment", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_SetZListItems('details', array('ref', 'title', 'ticket_log', 'start_date', 'document_list', 'ci_list', 'contact_list', 'status', 'caller_id', 'customer_id', 'service_id', 'servicesubcategory_id', 'product', 'impact', 'urgency', 'priority', 'workgroup_id', 'agent_id', 'agent_email', 'related_problem_id', 'related_change_id', 'closure_date', 'last_update', 'assignment_date', 'escalation_deadline', 'closure_deadline', 'resolution_code', 'solution', 'user_satisfaction', 'user_commment'));
MetaModel::Init_SetZListItems('details', array('ref', 'title', 'ticket_log', 'start_date', 'escalation_deadline', 'closure_deadline', 'document_list', 'ci_list', 'contact_list', 'status', 'caller_id', 'customer_id', 'service_id', 'servicesubcategory_id', 'product', 'impact', 'urgency', 'priority', 'workgroup_id', 'agent_id', 'agent_email', 'related_problem_id', 'related_change_id', 'closure_date', 'last_update', 'assignment_date', 'escalation_deadline', 'closure_deadline', 'resolution_code', 'solution', 'user_satisfaction', 'user_commment'));
MetaModel::Init_SetZListItems('advanced_search', array('ref', 'title', 'ticket_log', 'start_date', 'status', 'caller_id', 'customer_id', 'service_id', 'servicesubcategory_id', 'product', 'impact', 'urgency', 'priority', 'workgroup_id', 'agent_id', 'agent_email', 'related_problem_id', 'related_change_id', 'closure_date', 'last_update', 'assignment_date', 'escalation_deadline', 'closure_deadline', 'resolution_code', 'solution', 'user_satisfaction', 'user_commment'));
MetaModel::Init_SetZListItems('standard_search', array('ref', 'title', 'ticket_log', 'start_date', 'status', 'caller_id', 'customer_id', 'service_id', 'servicesubcategory_id', 'product', 'impact', 'urgency', 'priority', 'workgroup_id', 'agent_id', 'agent_email', 'related_problem_id', 'related_change_id', 'closure_date', 'last_update', 'assignment_date', 'escalation_deadline', 'closure_deadline', 'resolution_code', 'solution', 'user_satisfaction', 'user_commment'));
MetaModel::Init_SetZListItems('list', array('ref', 'title', 'ticket_log', 'start_date', 'status', 'caller_id', 'customer_id', 'service_id', 'servicesubcategory_id', 'product', 'impact', 'urgency', 'priority', 'workgroup_id', 'agent_id', 'agent_email', 'related_problem_id', 'related_change_id', 'closure_date', 'last_update', 'assignment_date', 'escalation_deadline', 'closure_deadline', 'resolution_code', 'solution', 'user_satisfaction', 'user_commment'));
@@ -225,7 +225,7 @@ class Incident extends Ticket
'start_date' => OPT_ATT_READONLY,
'last_update' => OPT_ATT_READONLY,
'assignment_date' => OPT_ATT_HIDDEN,
'escalation_deadline' => OPT_ATT_HIDDEN,
'escalation_deadline' => OPT_ATT_READONLY,
'closure_deadline' => OPT_ATT_HIDDEN,
'closure_date' => OPT_ATT_HIDDEN,
'customer_id' => OPT_ATT_MUSTCHANGE,
@@ -262,6 +262,8 @@ class Incident extends Ticket
'agent_id' => OPT_ATT_MANDATORY,
'related_problem_id' => OPT_ATT_NORMAL,
'related_change_id' => OPT_ATT_NORMAL,
'closure_deadline' => OPT_ATT_READONLY,
'escalation_deadline' => OPT_ATT_HIDDEN,
),
)
);
@@ -316,51 +318,97 @@ class Incident extends Ticket
MetaModel::Init_DefineTransition("resolved", "ev_close", array("target_state"=>"closed", "actions"=>array(), "user_restriction"=>null));
}
/**
* Determines the shortest SLT, for this ticket, for the given metric. Returns null is no SLT was found
* @param string $sMetric Type of metric 'TTO', 'TTR', etc as defined in the SLT class
* @return hash Array with 'SLT' => name of the SLT selected, 'value' => duration in seconds of the SLT metric, null if no SLT applies to this ticket
*/
public function ComputeSLT($sMetric = 'TTO')
{
$sOQL = "SELECT SLT JOIN lnkSLTToSLA AS L1 ON L1.slt_id=SLT.id JOIN SLA ON L1.sla_id = SLA.id JOIN lnkContractToSLA AS L2 ON L2.sla_id = SLA.id JOIN CustomerContract ON L2.contract_id = CustomerContract.id
WHERE SLT.ticket_priority = :priority AND SLA.service_id = :service_id AND SLT.metric = :metric AND CustomerContract.customer_id = :customer_id";
$oSLTSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),
array(),
array(
'priority' => $this->Get('priority'),
'service_id' => $this->Get('service_id'),
'metric' => $sMetric,
'customer_id' => $this->Get('customer_id'),
)
);
$iMinDuration = PHP_INT_MAX;
$sSLTName = '';
while($oSLT = $oSLTSet->Fetch())
$aResult = null;
if (MetaModel::IsValidClass('SLT'))
{
$iDuration = $oSLT->Get('value');
$sUnit = $oSLT->Get('value_unit');
switch($sUnit)
$sOQL = "SELECT SLT JOIN lnkSLTToSLA AS L1 ON L1.slt_id=SLT.id JOIN SLA ON L1.sla_id = SLA.id JOIN lnkContractToSLA AS L2 ON L2.sla_id = SLA.id JOIN CustomerContract ON L2.contract_id = CustomerContract.id
WHERE SLT.ticket_priority = :priority AND SLA.service_id = :service_id AND SLT.metric = :metric AND CustomerContract.customer_id = :customer_id";
$oSLTSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),
array(),
array(
'priority' => $this->Get('priority'),
'service_id' => $this->Get('service_id'),
'metric' => $sMetric,
'customer_id' => $this->Get('customer_id'),
)
);
$iMinDuration = PHP_INT_MAX;
$sSLTName = '';
while($oSLT = $oSLTSet->Fetch())
{
case 'days':
$iDuration = $iDuration * 24; // 24 hours in 1 days
// Fall though
case 'hours':
$iDuration = $iDuration * 60; // 60 minutes in 1 hour
// Fall though
case 'minutes':
$iDuration = $iDuration * 60;
$iDuration = $oSLT->Get('value');
$sUnit = $oSLT->Get('value_unit');
switch($sUnit)
{
case 'days':
$iDuration = $iDuration * 24; // 24 hours in 1 days
// Fall though
case 'hours':
$iDuration = $iDuration * 60; // 60 minutes in 1 hour
// Fall though
case 'minutes':
$iDuration = $iDuration * 60;
}
if ($iDuration < $iMinDuration)
{
$iMinDuration = $iDuration;
$sSLTName = $oSLT->GetName();
}
}
if ($iDuration < $iMinDuration)
if ($iMinDuration == PHP_INT_MAX)
{
$iMinDuration = $iDuration;
$sSLTName = $oSLT->GetName();
$aResult = null;
}
else
{
array('SLT' => $sSLTName, 'value' => $iMinDuration);
}
}
if ($iMinDuration == PHP_INT_MAX) $iMinDuration = null;
return array('SLT' => $sSLTName, 'value' => $iMinDuration);
return $aResult;
}
/**
* Compute the priority of the ticket based on its impact and urgency
* @return integer The priority of the ticket 1(high) .. 3(low)
*/
public function ComputePriority()
{
// priority[impact][urgency]
$aPriorities = array(
// single person
1 => array(
1 => 1,
2 => 1,
3 => 2,
),
// a group
2 => array(
1 => 1,
2 => 2,
3 => 3,
),
// a departement!
3 => array(
1 => 2,
2 => 3,
3 => 3,
),
);
$iPriority = $aPriorities[(int)$this->Get('impact')][(int)$this->Get('urgency')];
return $iPriority;
}
public function ComputeValues()
{
$iKey = $this->GetKey();
@@ -371,42 +419,33 @@ class Incident extends Ticket
}
$sName = sprintf('I-%06d', $iKey);
$this->Set('ref', $sName);
// priority[impact][urgency]
$aPriorities = array(
// single person
1 => array(
1 => 1,
2 => 1,
3 => 2,
),
// a group
2 => array(
1 => 1,
2 => 2,
3 => 3,
),
// a departement!
3 => array(
1 => 2,
2 => 3,
3 => 3,
),
);
$iPriority = $aPriorities[$this->Get('impact')][$this->Get('urgency')];
$this->Set('priority', $iPriority);
// Compute the SLA deadlines
// Compute the priority of the ticket
$this->Set('priority', $this->ComputePriority());
// Compute the SLA deadlines, if any is applicable to this ticket
$aSLT = $this->ComputeSLT('TTO');
$iStartDate = $this->Get('start_date');
//echo "<p>TTO: SLT found: {$aSLT['SLT']}, value: {$aSLT['value']}</p>\n";
$this->Set('escalation_deadline', $iStartDate + $aSLT['value']);
if ($aSLT != null)
{
//echo "<p>TTO: SLT found: {$aSLT['SLT']}, value: {$aSLT['value']}</p>\n";
$iStartDate = AttributeDateTime::GetAsUnixSeconds($this->Get('start_date'));
$this->Set('escalation_deadline', $iStartDate + $aSLT['value']);
}
else
{
$this->Set('escalation_deadline', null);
}
$aSLT = $this->ComputeSLT('TTR');
//echo "<p>TTR: SLT found: {$aSLT['SLT']}, value: {$aSLT['value']}</p>\n";
$iStartDate = $this->Get('start_date');
$this->Set('closure_deadline', $iStartDate + $aSLT['value']);
if ($aSLT != null)
{
//echo "<p>TTR: SLT found: {$aSLT['SLT']}, value: {$aSLT['value']}</p>\n";
$iStartDate = AttributeDateTime::GetAsUnixSeconds($this->Get('start_date'));
$this->Set('closure_deadline', $iStartDate + $aSLT['value']);
}
else
{
$this->Set('closure_deadline', null);
}
}
}
class Change extends Ticket

View File

@@ -1342,7 +1342,7 @@ EOF
////MetaModel::ShowQueryTrace();
$oP->output();
}
catch(CoreException $e)
catch(ZCoreException $e)
{
require_once('../setup/setuppage.class.inc.php');
$oP = new SetupWebPage(Dict::S('UI:PageTitle:FatalError'));
@@ -1371,7 +1371,7 @@ catch(CoreException $e)
// For debugging only
//throw $e;
}
catch(Exception $e)
catch(ZException $e)
{
require_once('../setup/setuppage.class.inc.php');
$oP = new SetupWebPage(Dict::S('UI:PageTitle:FatalError'));