[Rt-commit] rt branch 5.0/sla-violation-report created. rt-5.0.2-39-g757df4d4ca
BPS Git Server
git at git.bestpractical.com
Mon Dec 6 22:34:27 UTC 2021
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "rt".
The branch, 5.0/sla-violation-report has been created
at 757df4d4caf63304b6089d068e7d75071345adbd (commit)
- Log -----------------------------------------------------------------
commit 757df4d4caf63304b6089d068e7d75071345adbd
Author: sunnavy <sunnavy at bestpractical.com>
Date: Sat Dec 4 05:35:42 2021 +0800
Add SLAViolation event support
As the event is saved in transactions, it shows up in ticket history and
transaction searches automatically. The following new transaction
columns are added for convenience:
SLAViolationDuration
SLAViolationDurationAsString
SLAViolationBusinessDuration
SLAViolationBusinessDurationAsString
diff --git a/lib/RT/Action/CreateEventSLAViolation.pm b/lib/RT/Action/CreateEventSLAViolation.pm
new file mode 100644
index 0000000000..cfe20128c9
--- /dev/null
+++ b/lib/RT/Action/CreateEventSLAViolation.pm
@@ -0,0 +1,115 @@
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2021 Best Practical Solutions, LLC
+# <sales at bestpractical.com>
+#
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
+#
+# This work is made available to you under the terms of Version 2 of
+# the GNU General Public License. A copy of that license should have
+# been provided with this software, but in any event can be snarfed
+# from www.gnu.org.
+#
+# This work 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
+#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
+
+use strict;
+use warnings;
+
+package RT::Action::CreateEventSLAViolation;
+
+use base qw(RT::Action);
+
+=head2 Prepare
+
+Checks if the ticket has service level defined.
+
+=cut
+
+sub Prepare {
+ my $self = shift;
+
+ my $ticket = $self->TicketObj;
+
+ for my $field (qw/SLA Due/) {
+ if ( !$ticket->$field ) {
+ RT->Logger->error( 'CreateEventSLAViolation scrip has been applied to ticket #'
+ . $ticket->Id
+ . " that has no $field defined" );
+ return 0;
+ }
+ }
+
+ if ( $ticket->DueObj->Diff > 0 ) {
+ RT->Logger->error(
+ 'CreateEventSLAViolation scrip has been applied to ticket #' . $ticket->Id . ' that is not overdue' );
+ return 0;
+ }
+
+ if ( $ticket->LifecycleObj->IsInactive( $ticket->Status ) ) {
+ RT->Logger->error(
+ 'CreateEventSLAViolation scrip has been applied to ticket #' . $ticket->Id . ' that is inactive' );
+ return 0;
+ }
+
+ # Don't repetitively create the event.
+ my $txns = $ticket->Transactions;
+ $txns->Limit( FIELD => 'Type', VALUE => 'Event' );
+ $txns->Limit( FIELD => 'Field', VALUE => 'SLAViolation' );
+ $txns->Limit( FIELD => 'NewValue', VALUE => $ticket->Due );
+ $txns->OrderByCols( { FIELD => 'id', ORDER => 'DESC' } );
+ return 0 if $txns->First;
+ return 1;
+}
+
+=head2 Commit
+
+Set the Due date accordingly to SLA.
+
+=cut
+
+sub Commit {
+ my $self = shift;
+ $self->TicketObj->_NewTransaction(
+ Type => 'Event',
+ Field => 'SLAViolation',
+ OldValue => $self->TicketObj->SLA,
+ NewValue => $self->TicketObj->Due,
+ );
+ return;
+}
+
+1;
diff --git a/lib/RT/Transaction.pm b/lib/RT/Transaction.pm
index e6a5746ce0..c2d12b96c4 100644
--- a/lib/RT/Transaction.pm
+++ b/lib/RT/Transaction.pm
@@ -1438,7 +1438,23 @@ sub _CanonicalizeRoleName {
DeleteConfig => sub {
my $self = shift;
return ('[_1] deleted', $self->Field); #loc()
- }
+ },
+ Event => sub {
+ my $self = shift;
+ if ( $self->Field eq 'SLAViolation' ) {
+ my $due = RT::Date->new( $self->CurrentUser );
+ $due->Set( Value => $self->NewValue, Format => 'sql' );
+ return (
+ 'Exceeded SLA for [_2] in real time, [_3] in business hours',
+ $self->Field,
+ $self->SLAViolationDurationAsString,
+ $self->SLAViolationBusinessDurationAsString,
+ );
+ }
+ else {
+ return ( 'Event [_1]', $self->Field );
+ }
+ },
);
@@ -2253,6 +2269,68 @@ sub PreInflate {
return $class->SUPER::PreInflate( $importer, $uid, $data );
}
+sub SLAViolationEndedObj {
+ my $self = shift;
+ return '' unless $self->Type eq 'Event' && $self->Field eq 'SLAViolation';
+
+ my $ticket = $self->Object;
+ my $txns = RT::Transactions->new( $self->CurrentUser );
+ $txns->FromSQL(
+ sprintf q{ObjectType = '%s' AND ObjectId = %d AND id > %d AND
+ ( (Type = 'Set' AND Field = 'Due') OR (Type = 'Event' AND Field = 'SLAViolation') )},
+ map { $self->$_ } qw/ObjectType ObjectId Id/
+ );
+ my $txn = $txns->First;
+ my $date;
+ if ($txn) {
+ $date = $txn->CreatedObj;
+ }
+ else {
+ $date = RT::Date->new( $self->CurrentUser );
+ $date->SetToNow();
+ }
+ return $date;
+}
+
+sub SLAViolationDuration {
+ my $self = shift;
+ my $date = $self->SLAViolationEndedObj or return '';
+ return $date->Diff( $self->CreatedObj );
+}
+
+sub SLAViolationDurationAsString {
+ my $self = shift;
+ my $date = $self->SLAViolationEndedObj or return '';
+ return $date->DiffAsString( $self->CreatedObj );
+}
+
+sub SLAViolationBusinessDuration {
+ my $self = shift;
+ my $date = $self->SLAViolationEndedObj or return '';
+ my $agreement = RT::SLA->Agreement( Level => $self->OldValue ) or return '';
+ my $bh_name = $agreement->{BusinessHours} or return '';
+
+ local $ENV{'TZ'} = $ENV{'TZ'};
+ if ( $agreement->{'Timezone'} && $agreement->{'Timezone'} ne ( $ENV{'TZ'} || '' ) ) {
+ $ENV{'TZ'} = $agreement->{'Timezone'};
+ require POSIX;
+ POSIX::tzset();
+ }
+
+ my $bh = RT::SLA->BusinessHours($bh_name);
+
+ # Business::Hours takes time between (12345, 12346) as 2 seconds instead of 1 second.
+ # Here we +1 to make it consistent with how we calculate real time duration.
+ return $bh->between( $self->CreatedObj->Unix + 1, $date->Unix );
+}
+
+sub SLAViolationBusinessDurationAsString {
+ my $self = shift;
+ my $time = $self->SLAViolationBusinessDuration;
+ return '' unless defined $time && length $time;
+ return RT::Date->new( $self->CurrentUser )->DurationAsString($time);
+}
+
RT::Base->_ImportOverlays();
1;
diff --git a/share/html/Elements/RT__Transaction/ColumnMap b/share/html/Elements/RT__Transaction/ColumnMap
index e3f6567791..2386443646 100644
--- a/share/html/Elements/RT__Transaction/ColumnMap
+++ b/share/html/Elements/RT__Transaction/ColumnMap
@@ -122,6 +122,22 @@ my $COLUMN_MAP = {
title => 'Content', # loc
value => sub { return \$_[0]->Content( Type => 'text/html' ) },
},
+ SLAViolationDuration => {
+ title => 'SLA Violation Duration',
+ value => sub { return $_[0]->SLAViolationDuration },
+ },
+ SLAViolationDurationAsString => {
+ title => 'SLA Violation Duration As String',
+ value => sub { return $_[0]->SLAViolationDurationAsString },
+ },
+ SLAViolationBusinessDuration => {
+ title => 'SLA Violation Business Duration',
+ value => sub { return $_[0]->SLAViolationBusinessDuration },
+ },
+ SLAViolationBusinessDurationAsString => {
+ title => 'SLA Violation Business Duration As String',
+ value => sub { return $_[0]->SLAViolationBusinessDurationAsString },
+ },
TicketId => {
title => 'Ticket ID', # loc
value => $get_ticket_value->( @_, sub { $_[0]->Object->id } ),
diff --git a/share/html/Search/Elements/BuildFormatString b/share/html/Search/Elements/BuildFormatString
index 58776688cd..502b16a375 100644
--- a/share/html/Search/Elements/BuildFormatString
+++ b/share/html/Search/Elements/BuildFormatString
@@ -84,6 +84,8 @@ if ( $Class eq 'RT::Transactions' ) {
TicketLastUpdatedBy TicketCreated TicketStarted TicketResolved
TicketTold TicketLastUpdated TicketDue
TicketPriority TicketInitialPriority TicketFinalPriority
+ SLAViolationDuration SLAViolationDurationAsString
+ SLAViolationBusinessDuration SLAViolationBusinessDurationAsString
NEWLINE NBSP ); # loc_qw
my $CustomFields = RT::CustomFields->new( $session{'CurrentUser'} );
-----------------------------------------------------------------------
hooks/post-receive
--
rt
More information about the rt-commit
mailing list