[Rt-commit] rt branch 5.0/sla-violation-report created. rt-5.0.2-39-ga57ddadccd

BPS Git Server git at git.bestpractical.com
Wed Dec 8 13:45:02 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  a57ddadccd25906d2ab1440d1300ff3a08667012 (commit)

- Log -----------------------------------------------------------------
commit a57ddadccd25906d2ab1440d1300ff3a08667012
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..c2442d5cc7 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,66 @@ 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);
+    # -1 is to not include the end time
+    return $bh->between( $self->CreatedObj->Unix, $date->Unix - 1 );
+}
+
+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