I was able to patch the system to send close notifications to agents who have the ticket’s queue selected as one of their custom queues, but to do this requires modifications in a couple of places.
First, in the defaults.pm file, I added the ‘CloseNotify’ option to the following code at the end of the mail management options:
$Self->{PreferencesView} = {
'Mail Management' => [
'NewTicketNotify', 'FollowUpNotify', 'LockTimeoutNotify', 'MoveNotify', 'CloseNotify',
],
Frontend => [
'Language', 'Theme', 'QueueViewShownTickets', 'QueueView', 'RefreshTime', 'CreateNextMask',
],
'Other Options' => [
'Password', 'CustomQueue', 'SpellDict', 'FreeText', 'Comment',
],
};
Later in this same file you will need to define this option as such:
$Self->{PreferencesGroups}->{CloseNotify} = {
Colum => 'Mail Management',
Label => 'Close Notification',
Desc => 'Send me a notification if a ticket in my custom queues is closed.',
Type => 'Generic',
Data => $Self->Get('YesNoOptions'),
PrefKey => 'UserSendCloseNotification',
Activ => 1,
};
In the AAAPreferences.dtl file, you should add the following code so that the new option is displayed on the preferences page:
$Text{"Close notification"}
$Text{"Send me a notification if a ticket in my custom queues is closed."}
Finally, in the AgentClose.pm file, I added this code to the run subroutine:
foreach($Self->{QueueObject}->GetAllUserIDsByQueueID(QueueID => $QueueID)) {
my %UserData = $Self->{UserObject}->GetUserData(UserID => $_);
if ($UserData{UserSendCloseNotification}) {
$Self->{TicketObject}->SendNotification (
Type => 'Close',
UserData => \%UserData,
CustomerMessageParams => { Queue => $Self->{QueueObject}->QueueLookup(QueueID => $QueueID) },
TicketID => $Self->{TicketID},
UserID => $Self->{UserID},
);
}
}
The entire run subroutine as it exists on my system is shown below so you can see where I inserted this:
sub Run {
my $Self = shift;
my %Param = @_;
my $Output;
# check needed stuff
if (!$Self->{TicketID}) {
# error page
$Output .= $Self->{LayoutObject}->Header(Title => 'Error');
$Output .= $Self->{LayoutObject}->Error(
Message => "Can't close Ticket, no TicketID is given!",
Comment => 'Please contact the admin.',
);
$Output .= $Self->{LayoutObject}->Footer();
return $Output;
}
# check permissions
if (!$Self->{TicketObject}->Permission(
Type => 'close',
TicketID => $Self->{TicketID},
UserID => $Self->{UserID})) {
# error screen, don't show ticket
return $Self->{LayoutObject}->NoPermission(WithHeader => 'yes');
}
my $Tn = $Self->{TicketObject}->GetTNOfId(ID => $Self->{TicketID});
my $QueueID = $Self->{TicketObject}->GetQueueIDOfTicketID(TicketID => $Self->{TicketID});
if ($Self->{Subaction} eq '' || !$Self->{Subaction}) {
# get next states
my %NextStates = $Self->{StateObject}->StateGetStatesByType(
Type => 'DefaultCloseNext',
Result => 'HASH',
);
# get possible notes
my %DefaultNoteTypes = %{$Self->{ConfigObject}->Get('DefaultNoteTypes')};
my %NoteTypes = $Self->{DBObject}->GetTableData(
Table => 'article_type',
Valid => 1,
What => 'id, name'
);
foreach (keys %NoteTypes) {
if (!$DefaultNoteTypes{$NoteTypes{$_}}) {
delete $NoteTypes{$_};
}
}
# move queues
my $SelectedMoveQueue = $Self->{TicketObject}->GetQueueIDOfTicketID(
TicketID => $Self->{TicketID},
);
my %MoveQueues = $Self->{QueueObject}->GetAllQueues(
UserID => $Self->{UserID},
Type => 'move',
);
# --
# html header
# --
$Output .= $Self->{LayoutObject}->Header(Area => 'Agent', Title => 'Close');
# --
# get lock state
# --
if (!$Self->{TicketObject}->IsTicketLocked(TicketID => $Self->{TicketID})) {
$Self->{TicketObject}->SetLock(
TicketID => $Self->{TicketID},
Lock => 'lock',
UserID => $Self->{UserID}
);
if ($Self->{TicketObject}->SetOwner(
TicketID => $Self->{TicketID},
UserID => $Self->{UserID},
NewUserID => $Self->{UserID},
)) {
# show lock state
$Output .= $Self->{LayoutObject}->TicketLocked(TicketID => $Self->{TicketID});
}
}
else {
my ($OwnerID, $OwnerLogin) = $Self->{TicketObject}->CheckOwner(
TicketID => $Self->{TicketID},
);
if ($OwnerID != $Self->{UserID}) {
$Output .= $Self->{LayoutObject}->Warning(
Message => "Sorry, the current owner is $OwnerLogin!",
Comment => 'Please change the owner first.',
);
$Output .= $Self->{LayoutObject}->Footer();
return $Output;
}
}
# --
# print form ...
# --
#Added by Chris Peterson, 10.04.2004
#
#Code to generate close notifications for all agents
#that have subscribed to the custom queue in which the
#ticket is located
foreach($Self->{QueueObject}->GetAllUserIDsByQueueID(QueueID => $QueueID)) {
my %UserData = $Self->{UserObject}->GetUserData(UserID => $_);
if ($UserData{UserSendCloseNotification}) {
$Self->{TicketObject}->SendNotification (
Type => 'Close',
UserData => \%UserData,
CustomerMessageParams => { Queue => $Self->{QueueObject}->QueueLookup(QueueID => $QueueID) },
TicketID => $Self->{TicketID},
UserID => $Self->{UserID},
);
}
}
#End of 10.04.2004 addition
$Output .= $Self->_Mask(
TicketID => $Self->{TicketID},
TicketNumber => $Tn,
QueueID => $QueueID,
NextStatesStrg => \%NextStates,
NoteTypesStrg => \%NoteTypes,
MoveQueues => \%MoveQueues,
SelectedMoveQueue => $SelectedMoveQueue,
);
$Output .= $Self->{LayoutObject}->Footer();
return $Output;
}
elsif ($Self->{Subaction} eq 'Store') {
# store action
my $StateID = $Self->{ParamObject}->GetParam(Param => 'CloseStateID');
my $NoteID = $Self->{ParamObject}->GetParam(Param => 'CloseNoteID');
my $Subject = $Self->{ParamObject}->GetParam(Param => 'Subject') || '';
my $Text = $Self->{ParamObject}->GetParam(Param => 'Text') ||
$Self->{ParamObject}->GetParam(Param => 'Body');
my $TimeUnits = $Self->{ParamObject}->GetParam(Param => 'TimeUnits') || 0;
my $DestQueueID = $Self->{ParamObject}->GetParam(Param => 'DestQueueID') || '';
if (my $ArticleID = $Self->{TicketObject}->CreateArticle(
TicketID => $Self->{TicketID},
ArticleTypeID => $NoteID,
SenderType => 'agent',
>From => "$Self->{UserFirstname} $Self->{UserLastname} <$Self->{UserEmail}>",
Subject => $Subject,
Body => $Text,
ContentType => "text/plain; charset=$Self->{LayoutObject}->{'UserCharset'}",
UserID => $Self->{UserID},
HistoryType => 'AddNote',
HistoryComment => 'Close Note added.',
)) {
# time accounting
if ($TimeUnits) {
$Self->{TicketObject}->AccountTime(
TicketID => $Self->{TicketID},
ArticleID => $ArticleID,
TimeUnit => $TimeUnits,
UserID => $Self->{UserID},
);
}
# set state
$Self->{TicketObject}->SetState(
UserID => $Self->{UserID},
TicketID => $Self->{TicketID},
ArticleID => $ArticleID,
StateID => $StateID,
);
# set queue
if ($DestQueueID) {
$Self->{TicketObject}->MoveByTicketID(
TicketID => => $Self->{TicketID},
UserID => $Self->{UserID},
QueueID => $DestQueueID,
);
}
# set lock
$Self->{TicketObject}->SetLock(
UserID => $Self->{UserID},
TicketID => $Self->{TicketID},
Lock => 'unlock'
);
# redirect
my %StateData = $Self->{TicketObject}->{StateObject}->StateGet(
ID => $StateID,
);
if ($StateData{TypeName} =~ /^close/i) {
return $Self->{LayoutObject}->Redirect(OP => $Self->{LastScreenQueue});
}
else {
return $Self->{LayoutObject}->Redirect(OP => $Self->{LastScreen});
}
}
else {
# error screen
$Output .= $Self->{LayoutObject}->Header();
$Output .= $Self->{LayoutObject}->Error(
Comment => 'Please contact your admin'
);
$Output .= $Self->{LayoutObject}->Footer();
return $Output;
}
}
else {
# error screen
$Output .= $Self->{LayoutObject}->Header();
$Output .= $Self->{LayoutObject}->Error(
Message => 'Wrong Subaction!!',
Comment => 'Please contact your admin'
);
$Output .= $Self->{LayoutObject}->Footer();
return $Output;
}
}
These are all the modifications that you should need to make to the code. You will need to add a new notification to the notifications table – you should enter Agent::Close in the notification_type field.
The downside of modifying the code this way, as I discovered after making these changes is that the close notification is sent when the agent accesses the close ticket page, not when they actually close the ticket. Therefore, if they go to this page and do not actually close the ticket, a false notification will be sent. Perhaps someone else could suggest a cleaner way to implement this. I’m on a tight schedule though, and this was a sufficient fix for my company, so I don’t have time to go back and review this code. Hope this helps.
Christopher J. Peterson
Compulit, Inc
(616)285-9590
cpeterso@compulit.com