[% META title = "Ticket Due Dates" %]
This is where we get into a custom scrip that will be run each time you update a ticket.
The Due date of the ticket is the total elapsed operational time for a ticket. This is all the time the ticket is New or Open. This means that a ticket can be stalled, and it doesn tcount against your SLA. A ticket should be stalled if it is waiting for an external party, such as the requestor.
return 0 if ( $self->TicketObj->Status =~ /^resolved|deleted|rejected$/);
return 1 if ($self->TransactionObj->Field eq "Status" && ($self->TransactionObj->OldValue eq "stalled" || $self->TransactionObj->NewValue eq "stalled" || $self->TransactionObj->NewValue eq "new"));
return 0 unless ($self->TransactionObj->Type eq "CustomField");
my $CustomField_severity = RT::CustomField->new($RT::SystemUser);
my $CustomField_service = RT::CustomField->new($RT::SystemUser);
$CustomField_severity->LoadByName(Name => "Severity");
$CustomField_service->LoadByName(Name => "Service");
# Only proceed if we have status change, or updating our Service custom fields
return 0 unless ($self->TransactionObj->Field eq $CustomField_service->id || $self->TransactionObj->Field eq $CustomField_severity->id);
return 1;
return 1;
my $classification_timeouts = {
gold => {
critical => [ '1 hour', '24 hour' ],
normal => [ '1 hour', '168 hour' ],
minor => [ undef, '744 hour' ],
},
silver => {
critical => [ '2 global business hour', '32 global business hour' ],
normal => [ '2 global business hour', '112 global business hour' ],
minor => [ undef, '480 global business hour' ],
},
bronze => {
critical => [ '2 local business hour', '24 local business hour' ],
normal => [ '2 local business hour', '56 local business hour' ],
minor => [ undef, undef ],
},
};
my $service_classification = {
'crm' => 'silver',
'email' => 'gold',
'general it' => 'silver',
'internet access' => 'bronze',
'mobile devices' => 'bronze',
'office telephones' => 'bronze',
'printing' => 'bronze',
'vpn' => 'gold',
'crm' => 'gold',
'production infrastructure' => 'gold',
'web sites' => 'gold',
};
# get ticket object
my $ticket = $self->TicketObj;
# If we're stalled, then the Due is not set, return
$ticket->SetDue(0) and return 1 if ($ticket->Status eq "stalled");
my $service;
my $severity;
my $CustomFields = $ticket->QueueObj->TicketCustomFields();
while (my $CustomField = $CustomFields->Next) {
my $CustomFieldValues = $ticket->CustomFieldValues($CustomField->Id);
while (my $CustomFieldValue = $CustomFieldValues->Next()) {
$severity = lc($CustomFieldValue->Content) if ($CustomField->Name eq "Severity" && $CustomFieldValue->Content ne "");
$service = lc($CustomFieldValue->Content) if ($CustomField->Name eq "Service");
}
}
my $timeouts = $classification_timeouts->{$service_classification->{$service}}{$severity};
$RT::Logger->debug("Service is $service, severity is $severity, timeout is " . $timeouts->[1]);
if (not defined $timeouts->[1]) {
$RT::Logger->warning("Due set to 0; no timeout for this service/severity");
$ticket->SetDue(0);
return 1;
}
# Has there been any "stall" time?
my $stalled_time = 0;
my $previous_time = RT::Date->new( $RT::SystemUser );
my $this_time = RT::Date->new( $RT::SystemUser );
$previous_time->Set(Format => "ISO", Value => $ticket->Created);
my $transactions = $ticket->Transactions();
while (my $transaction = $transactions->Next()) {
if ($transaction->Field eq "Status") {
if (($transaction->OldValue eq "stalled") || ($transaction->OldValue eq "deleted") || ($transaction->OldValue eq "resolved") || ($transaction->OldValue eq "rejected")) {
$this_time->Set(Format => "ISO", Value => $transaction->Created);
$stalled_time+=$this_time->Diff($previous_time);
}
# Update previous time
$previous_time->Set(Format => "ISO", Value => $transaction->Created );
}
}
$RT::Logger->debug("Stall time is " . $stalled_time );
# Now set the Due date/time
my $created_date = RT::Date->new( $RT::SystemUser );
my $due_date = RT::Date->new( $RT::SystemUser );
$created_date->Set(Format => "ISO", Value => $ticket->Created);
$due_date->Set(Format => "ISO", Value => $ticket->Created);
if ($timeouts->[1] =~ /^(\d+) (hour|minute|second)s?$/) {
my $multiplier = ($2 == "hour" ? 3600 : $2 == "minute" ? 60 : 1);
my $seconds_to_add = $1 * $multiplier;
$due_date->AddSeconds($seconds_to_add + $stalled_time);
$RT::Logger->debug( "Adding $seconds_to_add elapsed + $stalled_time stalled seconds to create date " . scalar(localtime($created_date->Unix)) . " should be due " . scalar(localtime($due_date->Unix)));
} elsif ($timeouts->[1] =~ /^(\d+) local business (hour|minute|second)s?$/)
{
my $multiplier = ($2 == "hour" ? 3600 : $2 == "minute" ? 60 : 1);
my $seconds_to_add = $1 * $multiplier;
use Business::Hours;
my $bh = Business::Hours->new;
my $end = $bh->add_seconds($created_date->Unix, $seconds_to_add + $stalled_time);
$RT::Logger->debug( "Adding $1 local business hours ($seconds_to_add + $stalled_time secs) makes this " . scalar(localtime($end)));
$due_date->Set(Format => 'unix', Value => $end);
} elsif ($timeouts->[1] =~ /^(\d+) global business (hour|minute|second)s?$/)
{
my $multiplier = ($2 == "hour" ? 3600 : $2 == "minute" ? 60 : 1);
my $seconds_to_add = $1 * $multiplier;
use Business::Hours;
my $bh = Business::Hours->new;
$bh->business_hours(
1 => { Start => '08:00', End => '23:59' },
2 => { Start => '08:00', End => '23:59' },
3 => { Start => '08:00', End => '23:59' },
4 => { Start => '08:00', End => '23:59' },
5 => { Start => '08:00', End => '23:59' },
);
my $end = $bh->add_seconds($created_date->Unix, $seconds_to_add + $stalled_time);
$RT::Logger->debug( "Adding $1 global business hours ($seconds_to_add + $stalled_time secs) makes this " . scalar(localtime($end)));
$due_date->Set(Format => 'unix', Value => $end);
}
$RT::Logger->info("Due date set to " . $due_date->ISO );
return $ticket->SetDue($due_date->ISO);