I've been playing with getting the system to work around the ticket last
updated time (change_time) instead of Age.
Basically because it makes sense for our purposes to do so.
I've searched this list a lot in the past week or so and I've seen
people with much the same question, but without any real answers.
I'm attaching (and I hope it comes through) a text file with the
location and changes needed in the various files to center the system
around the last updated time.
I've broken it down piecemeal, so you can use what you like.
Changes include:
Printing Last Update Time On The Agent Ticket Queue View
Sort Agent Ticket Queue View By Last Updated Time
Updating Last Updated Time When A Note Is Added To A Ticket
Updating Last Updated Time When A Phone Reply Is Added To A Ticket
Display Accounted Time Units On Customer Screen
Printing Last Update Time On The Customer Ticket Zoom
Printing Last Update Time On The Customer Screen
Show Latest Update (regardless of who its by) on Agent Ticket Queue View
I really like this system and this list has been a great source of
information for me, so I hope this will help someone!
--
Isaac Dawson
----------------------------------------------------------------------------------------------------
::Printing Last Update Time On The Agent Ticket Queue View::
----------------------------------------------------------------------------------------------------
----------
Locate:
----------
Kernel\Output\HTML\Standard\AgentTicketQueueTicketView.dtl
----------
Look for:
----------
$Env{"Box0"}$Text{"Age"}: $Data{"Age"}$Env{"Box1"}
----------
Change to:
----------
$Env{"Box0"}$Text{"LastUpdated"}: $Data{"LastUpdated"}$Env{"Box1"}
----------
Look for:
----------
<tr>
<td class="mainkey">$Text{"Created"}:</td>
<td class="mainvalue"> $TimeLong{"$Data{"AgeCreated"}"}</td>
</tr>
----------
Change to:
----------
<tr>
<td class="mainkey">$Text{"Age"}:</td>
<td class="mainvalue"> $Data{"Age"} </td>
<td> </td>
<td class="mainkey">$Text{"Created"}:</td>
<td class="mainvalue"> $TimeLong{"$Data{"AgeCreated"}"}</td>
</tr>
----------
Locate:
----------
Kernel\Output\HTML\Standard\AgentTicketZoom.dtl
----------
Look for:
----------
<td align="right" width="30%" class="mainhead">
$Env{"Box0"}$Text{"Age"}: $Data{"Age"}$Env{"Box1"}
</td>
----------
Change to:
----------
<td align="right" width="30%" class="mainhead">
$Env{"Box0"}$Text{"Updated"}:
$TimeLong{"$Data{"LastUpdated"}"}$Env{"Box1"}
</td>
----------
Look for:
----------
<td align="right" width="30%" class="menu">
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td class="mainkey">$Text{"Created"}:</td>
<td class="mainvalue"> $TimeLong{"$Data{"Created"}"}</td>
</tr>
</table>
</td>
----------
Change to:
----------
<td align="right" width="30%" class="menu">
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td class="mainkey">$Text{"Age"}:</td>
<td class="mainvalue"> $Data{"Age"} </td>
<td> </td>
<td class="mainkey">$Text{"Created"}:</td>
<td class="mainvalue"> $TimeLong{"$Data{"Created"}"}</td>
</tr>
</table>
</td>
----------
Locate:
----------
Kernel\System\Ticket\Article.pm
----------
Look for:
----------
. ' st.escalation_solution_time, st.escalation_time '
----------
Change to:
----------
. ' st.escalation_solution_time, st.escalation_time, st.change_time '
----------
Look for:
----------
$Data{SLAID} = $Row[75];
$Ticket{SLAID} = $Row[75];
----------
Change to:
----------
$Data{SLAID} = $Row[75];
$Ticket{SLAID} = $Row[75];
$Data{LastUpdated} = $Row[79];
$Ticket{LastUpdated} = $Data{LastUpdated};
$Data{AgeCreated} =
$Self->{TimeObject}->SystemTime2TimeStamp( SystemTime => $Row[8] );
$Ticket{AgeCreated} = $Data{AgeCreated};
----------
Locate:
----------
Kernel\System\Ticket.pm
----------
Look for:
----------
$Ticket{TicketFreeTime6} = defined( $Row[53] ) ? $Row[53] : '';
----------
Change to:
----------
$Ticket{TicketFreeTime6} = defined( $Row[53] ) ? $Row[53] : '';
$Ticket{LastUpdated} = $Row[54];
$Ticket{AgeCreated} =
$Self->{TimeObject}->SystemTime2TimeStamp( SystemTime => $Row[7] );
----------------------------------------------------------------------------------------------------
::Sort Agent Ticket Queue View By Last Updated Time::
----------------------------------------------------------------------------------------------------
----------
Locate:
----------
Kernel\Modules\AgentTicketQueue.pm
----------
Look for:
----------
TicketFreeText16 => 'st.freetext16'
----------
Change to:
----------
TicketFreeText16 => 'st.freetext16',
LastUpdated => 'st.change_time'
----------
Locate:
----------
Kernel\Config\Files\Ticket.xml
----------
Look for:
----------
<SubGroup>Frontend::Agent::Ticket::ViewQueue</SubGroup>
<Setting>
<Option SelectedID="Age">
<Item Key="Age">Age</Item>
----------
Change to:
----------
<SubGroup>Frontend::Agent::Ticket::ViewQueue</SubGroup>
<Setting>
<Option SelectedID="Age">
<Item Key="Age">Age</Item>
<Item Key="LastUpdated">LastUpdated</Item>
----------
Note!
----------
Then select the LastUpdated option in the web interface.
Its under Admin->SysConfig->Ticket->Frontend::Agent::Ticket::ViewQueue->
Ticket::Frontend::AgentTicketQueue###SortBy::Default:
----------------------------------------------------------------------------------------------------
::Updating Last Updated Time When A Note Is Added To A Ticket::
----------------------------------------------------------------------------------------------------
----------
Locate:
----------
Kernel\Modules\AgentTicketNote.pm
----------
Look for:
----------
# redirect to last screen overview on closed tickets
if ( $StateData{TypeName} =~ /^close/i ) {
return $Self->{LayoutObject}->Redirect( OP =>
$Self->{LastScreenOverview} );
}
----------
Change to:
----------
# redirect to last screen overview on closed tickets
if ( $StateData{TypeName} =~ /^close/i ) {
return $Self->{LayoutObject}->Redirect( OP =>
$Self->{LastScreenOverview} );
}
$Self->{TicketObject}->TicketUpdateTimeSet(
UserID => $Self->{UserID},
TicketID => $Self->{TicketID},
%GetParam,
);
----------
Locate:
----------
Kernel\System\Ticket.pm
----------
Look for:
----------
=item TicketAclActionData()
return the current ACL action data hash after TicketAcl()
my %AclAction = $TicketObject->TicketAclActionData();
=cut
sub TicketAclActionData {
my ( $Self, %Param ) = @_;
if ( $Self->{TicketAclActionData} ) {
return %{ $Self->{TicketAclActionData} };
}
else {
return %{ $Self->{ConfigObject}->Get('TicketACL::Default::Action') };
}
}
----------
Change to:
----------
=item TicketAclActionData()
return the current ACL action data hash after TicketAcl()
my %AclAction = $TicketObject->TicketAclActionData();
=cut
sub TicketAclActionData {
my ( $Self, %Param ) = @_;
if ( $Self->{TicketAclActionData} ) {
return %{ $Self->{TicketAclActionData} };
}
else {
return %{ $Self->{ConfigObject}->Get('TicketACL::Default::Action') };
}
}
=item TicketUpdateTimeSet()
set ticket update time
$TicketObject->TicketUpdateTimeSet(
Year => 2003,
Month => 08,
Day => 14,
Hour => 22,
Minute => 05,
TicketID => 123,
UserID => 23,
);
or use a time stamp
$TicketObject->TicketUpdateTimeSet(
String => '2003-08-14 22:05:00',
TicketID => 123,
UserID => 23,
);
=cut
sub TicketUpdateTimeSet {
my ( $Self, %Param ) = @_;
my $Time;
# check needed stuff
if ( !$Param{String} ) {
for (qw(Year Month Day Hour Minute TicketID UserID)) {
if ( !defined $Param{$_} ) {
$Self->{LogObject}->Log( Priority => 'error', Message => "Need
$_!" );
return;
}
}
}
# get system time from string/params
if ( $Param{String} ) {
$Time = $Self->{TimeObject}->TimeStamp2SystemTime( String =>
$Param{String}, );
( $Param{Sec}, $Param{Minute}, $Param{Hour}, $Param{Day},
$Param{Month}, $Param{Year} )
= $Self->{TimeObject}->SystemTime2Date( SystemTime => $Time, );
}
else {
$Time = $Self->{TimeObject}->TimeStamp2SystemTime(
String => "$Param{Year}-$Param{Month}-$Param{Day}
$Param{Hour}:$Param{Minute}:00",
);
}
# return if no convert is possible
if ( !$Time ) {
return;
}
# db update
return if !$Self->{DBObject}->Do(
SQL => 'UPDATE ticket SET '
. ' change_time = current_timestamp, change_by = ? WHERE id = ?',
Bind => [ \$Param{UserID}, \$Param{TicketID} ],
);
# clear ticket cache
delete $Self->{ 'Cache::GetTicket' . $Param{TicketID} };
# ticket event
$Self->TicketEventHandlerPost(
Event => 'TicketUpdateTimeUpdate',
UserID => $Param{UserID},
TicketID => $Param{TicketID},
);
return 1;
}
----------
Look for:
----------
=item TicketEventHandlerPost()
call ticket event post handler, returns true if it's executed successfully
$TicketObject->TicketEventHandlerPost(
TicketID => 123,
Event => 'TicketStateUpdate',
UserID => 123,
);
events available:
TicketCreate, TicketDelete, TicketTitleUpdate, TicketUnlockTimeoutUpdate,
TicketQueueUpdate, TicketTypeUpdate, TicketServiceUpdate,
TicketSLAUpdate, TicketCustomerUpdate, TicketFreeTextUpdate,
TicketFreeTimeUpdate,
TicketPendingTimeUpdate, TicketLockUpdate, TicketStateUpdate, TicketOwnerUpdate,
TicketResponsibleUpdate, TicketPriorityUpdate, HistoryAdd, HistoryDelete,
TicketAccountTime, TicketMerge, ArticleCreate, ArticleFreeTextUpdate,
ArticleUpdate, ArticleSend, ArticleBounce, ArticleAgentNotification,
ArticleCustomerNotification, ArticleAutoResponse, ArticleFlagSet,
ArticleFlagDelete;
----------
Change to:
----------
=item TicketEventHandlerPost()
call ticket event post handler, returns true if it's executed successfully
$TicketObject->TicketEventHandlerPost(
TicketID => 123,
Event => 'TicketStateUpdate',
UserID => 123,
);
events available:
TicketCreate, TicketDelete, TicketTitleUpdate, TicketUnlockTimeoutUpdate,
TicketQueueUpdate, TicketTypeUpdate, TicketServiceUpdate,
TicketSLAUpdate, TicketCustomerUpdate, TicketFreeTextUpdate,
TicketFreeTimeUpdate,
TicketPendingTimeUpdate, TicketLockUpdate, TicketStateUpdate, TicketOwnerUpdate,
TicketResponsibleUpdate, TicketPriorityUpdate, HistoryAdd, HistoryDelete,
TicketAccountTime, TicketMerge, ArticleCreate, ArticleFreeTextUpdate,
ArticleUpdate, ArticleSend, ArticleBounce, ArticleAgentNotification,
ArticleCustomerNotification, ArticleAutoResponse, ArticleFlagSet,
ArticleFlagDelete, TicketUpdateTimeUpdate;
----------
Look for:
----------
elsif ( $Param{Event} eq 'ArticleAutoResponse' ) {
$Param{Event} = 'SendAutoResponse';
}
else {
return 1;
}
----------
Change to:
----------
elsif ( $Param{Event} eq 'ArticleAutoResponse' ) {
$Param{Event} = 'SendAutoResponse';
}
elsif ( $Param{Event} eq 'TicketUpdateTimeUpdate' ) {
$Param{Event} = 'TicketUpdateTimeSet';
}
else {
return 1;
}
----------------------------------------------------------------------------------------------------
::Updating Last Updated Time When A Phone Reply Is Added To A Ticket::
----------------------------------------------------------------------------------------------------
----------
Locate:
----------
Kernel\Modules\AgentTicketPhoneOutbound.pm
----------
Look for:
----------
# should i set an unlock? yes if the ticket is closed
----------
Change to:
----------
# set last updated time
$Self->{TicketObject}->TicketUpdateTimeSet(
UserID => $Self->{UserID},
TicketID => $Self->{TicketID},
%GetParam,
);
# should i set an unlock? yes if the ticket is closed
----------------------------------------------------------------------------------------------------
::Display Accounted Time Units On Customer Screen::
----------------------------------------------------------------------------------------------------
----------
Locate:
----------
Kernel\Modules\CustomerTicketOverview.pm
----------
Look for:
----------
# condense down the subject
----------
Change to:
----------
my $WorkTime = $Self->{TicketObject}->TicketAccountedTimeGet(TicketID =>
$Param{TicketID});
# condense down the subject
----------
Look for:
----------
# add block
$Self->{LayoutObject}->Block(
Name => 'Record',
Data => {
%Article,
Subject => $Subject,
%Param,
----------
Change to:
----------
# add block
$Self->{LayoutObject}->Block(
Name => 'Record',
Data => {
%Article,
Subject => $Subject,
WorkTime => $WorkTime,
%Param,
----------
Locate:
----------
Kernel\Output\HTML\Standard\CustomerStatusView.dtl
----------
Look for:
----------
<th width="10%">$Text{"Owner"}<br/>
<a
href="$Env{"Baselink"}Action=$Env{"Action"}&SortBy=Owner&Order=Up&Limit=$Data{"Limit"}&ShowClosedTickets=$Data{"ShowClosed"}&Type=$Data{"Type"}"
onmouseover="window.status='$JSText{"sort upward"}'; return true;"
onmouseout="window.status='';"><img border="0" src="$Env{"Images"}up-small.png"
alt="$Text{"up"}"></a> /
<a
href="$Env{"Baselink"}Action=$Env{"Action"}&SortBy=Owner&Order=Down&Limit=$Data{"Limit"}&ShowClosedTickets=$Data{"ShowClosed"}&Type=$Data{"Type"}"
onmouseover="window.status='$JSText{"sort downward"}'; return true;"
onmouseout="window.status='';"><img border="0"
src="$Env{"Images"}down-small.png" alt="$Text{"down"}"></a>
</th>
----------
Change to:
----------
<th width="5%">$Text{"Owner"}<br/>
<a
href="$Env{"Baselink"}Action=$Env{"Action"}&SortBy=Owner&Order=Up&Limit=$Data{"Limit"}&ShowClosedTickets=$Data{"ShowClosed"}&Type=$Data{"Type"}"
onmouseover="window.status='$JSText{"sort upward"}'; return true;"
onmouseout="window.status='';"><img border="0" src="$Env{"Images"}up-small.png"
alt="$Text{"up"}"></a> /
<a
href="$Env{"Baselink"}Action=$Env{"Action"}&SortBy=Owner&Order=Down&Limit=$Data{"Limit"}&ShowClosedTickets=$Data{"ShowClosed"}&Type=$Data{"Type"}"
onmouseover="window.status='$JSText{"sort downward"}'; return true;"
onmouseout="window.status='';"><img border="0"
src="$Env{"Images"}down-small.png" alt="$Text{"down"}"></a>
</th>
<th width="5%">$Text{"Time"}</th>
----------
Look for:
----------
<td class="$Env{"Color"}"><div
title="$Quote{"$Data{"Owner"}"}">$Quote{"$Data{"Owner"}","18"}</div></td>
----------
Change to:
----------
<td class="$Env{"Color"}"><div
title="$Quote{"$Data{"Owner"}"}">$Quote{"$Data{"Owner"}","18"}</div></td>
<td class="$Env{"Color"}">$QData{"WorkTime"}</td>
----------------------------------------------------------------------------------------------------
::Printing Last Update Time On The Customer Ticket Zoom::
----------------------------------------------------------------------------------------------------
----------
Locate:
----------
Kernel\Output\HTML\Standard\CustomerTicketZoom.dtl
----------
Look for:
----------
<table border="0" width="100%" cellspacing="0" cellpadding="3">
<tr>
<td width="50%" class="mainhead">
$Env{"Box0"}$Text{"Zoom"} $Config{"Ticket::Hook"}:
$Data{"TicketNumber"}$Env{"Box1"}
</td>
<td align="right" width="50%" class="mainhead">
$Env{"Box0"}$Text{"Age"}: $Data{"Age"}$Env{"Box1"}
</td>
</tr>
</table>
<table border="0" width="100%" cellspacing="0" cellpadding="3">
<tr>
<td width="70%" class="menu">
<a
href="$Env{"Baselink"}Action=CustomerTicketPrint&TicketID=$QData{"TicketID"}"
onmouseover="window.status='$JSText{"Print Ticket"}'; return true;"
onmouseout="window.status='';" target="_blank">$Text{"Print"}</a>
</td>
<td align="right" width="30%" class="menu">
<b>$Text{"Created"}:</b> $TimeLong{"$Data{"Created"}"}
</td>
</tr>
</table>
----------
Change to:
----------
<table border="0" width="100%" cellspacing="0" cellpadding="3">
<tr>
<td width="50%" class="mainhead">
$Env{"Box0"}$Text{"Zoom"} $Config{"Ticket::Hook"}:
$Data{"TicketNumber"}$Env{"Box1"}
</td>
<td align="right" width="50%" class="mainhead">
$Env{"Box0"}$Text{"Updated"}:
$TimeLong{"$Data{"LastUpdated"}"}$Env{"Box1"}
</td>
</tr>
</table>
<table border="0" width="100%" cellspacing="0" cellpadding="3">
<tr>
<td width="60%" class="menu">
<a
href="$Env{"Baselink"}Action=CustomerTicketPrint&TicketID=$QData{"TicketID"}"
onmouseover="window.status='$JSText{"Print Ticket"}'; return true;"
onmouseout="window.status='';" target="_blank">$Text{"Print"}</a>
</td>
<td align="right" width="40%" class="menu">
<b>$Text{"Age"}:</b> $Data{"Age"} <b>$Text{"Created"}:</b>
$TimeLong{"$Data{"Created"}"}
</td>
</tr>
</table>
----------------------------------------------------------------------------------------------------
::Printing Last Update Time On The Customer Screen::
----------------------------------------------------------------------------------------------------
----------
Locate:
----------
Kernel\Output\HTML\Standard\CustomerStatusView.dtl
----------
Look for:
----------
<th width="20%">$Text{"Age"}<br/>
----------
Change to:
----------
<th width="20%">$Text{"Updated"}<br/>
----------
Look for:
----------
<td class="$Env{"Color"}">$QData{"Age","20"}</td>
----------
Change to:
----------
<td class="$Env{"Color"}">$TimeLong{"$QData{"LastUpdated","20"}"}</td>
----------------------------------------------------------------------------------------------------
::Show Latest Update (regardless of who its by) on Agent Ticket Queue View::
----------------------------------------------------------------------------------------------------
----------
Locate:
----------
Kernel\System\Ticket\Article.pm
----------
Look for:
----------
# check if latest article is sent to customer
elsif (
$Param{SenderType} eq 'agent'
&& $Param{ArticleType} =~ /email-ext|phone|fax|sms|note-ext/
----------
Change to:
----------
# check if latest article is sent to customer
elsif (
$Param{SenderType} eq 'agent'
# && $Param{ArticleType} =~ /email-ext|phone|fax|sms|note-ext/
#NOTE: I don't remember why this needed to be removed, but it works this way
----------
Look for:
----------
# return ArticleID
return $ArticleID;
}
# just for internal use
----------
Change to:
----------
$Self->{DBObject}->Do(
SQL => 'UPDATE ticket SET change_time = current_timestamp WHERE id = ?',
Bind => [ \$Param{TicketID} ],
);
# return ArticleID
return $ArticleID;
}
# just for internal use
----------
Look for:
----------
# if we got no internal article, return the latest one
return $Self->ArticleGet( ArticleID => $Index[-1] );
}
----------
Change to:
----------
# if we got no internal article, return the latest one
return $Self->ArticleGet( ArticleID => $Index[-1] );
}
=item ArticleLastArticle()
get last customer article
my %Article = $TicketObject->ArticleLastArticle(
TicketID => 123,
);
=cut
sub ArticleLastArticle {
my ( $Self, %Param ) = @_;
# check needed stuff
if ( !$Param{TicketID} ) {
$Self->{LogObject}->Log( Priority => 'error', Message => "Need
TicketID!" );
return;
}
# get article index
my @Index = $Self->ArticleIndex( TicketID => $Param{TicketID} );
# get article data
return $Self->ArticleGet( ArticleID => $Index[-1] ) if @Index;
@Index = $Self->ArticleIndex( TicketID => $Param{TicketID} );
if ( [EMAIL PROTECTED] ) {
$Self->{LogObject}->Log(
Priority => 'error',
Message => "No article found for TicketID $Param{TicketID}!",
);
return;
}
# return latest non internal article
return $Self->ArticleGet( ArticleID => $Index[-1] );
}
----------
Locate:
----------
Kernel\Modules\AgentTicketQueue.pm
----------
Look for:
----------
# get last article
my %Article = $Self->{TicketObject}->ArticleLastCustomerArticle( TicketID
=> $TicketID );
----------
Change to:
----------
# get last article
my %Article = $Self->{TicketObject}->ArticleLastArticle( TicketID =>
$TicketID );
_______________________________________________
OTRS mailing list: otrs - Webpage: http://otrs.org/
Archive: http://lists.otrs.org/pipermail/otrs
To unsubscribe: http://lists.otrs.org/cgi-bin/listinfo/otrs