[Rt-commit] rt branch, 4.4/total-time-worked, created. rt-4.4.1-310-g247ee20

Dave Goehrig dave at bestpractical.com
Mon Mar 6 11:07:57 EST 2017


The branch, 4.4/total-time-worked has been created
        at  247ee2012d26ca53355d14f5705060340cd62cae (commit)

- Log -----------------------------------------------------------------
commit 247ee2012d26ca53355d14f5705060340cd62cae
Author: Dave Goehrig <dave at bestpractical.com>
Date:   Thu Feb 23 11:51:47 2017 -0500

    adding total time worked
    
    This adds a new recursive total time worked function to Ticket.pm
    and adds a COLUMN_MAP entry so that it can be displayed in reports.
    
    The code is optional and requires setting a $DisplayTotalTimeWorked
    in RT_SiteConfig.pm.  Also before creating tickets using this one needs
    to disable the  'On TimeWorked Change Update Parent TimeWorked' scrip
    which mutates the value of time worked on the parent tickets.
    
    It should be noted running this on an existing database will report
    invalid results for all tickets where that scrip was active as it will
    double count all of the child time worked in the parent tickets.

diff --git a/lib/RT/Ticket.pm b/lib/RT/Ticket.pm
index f2581de..1aeb0f8 100644
--- a/lib/RT/Ticket.pm
+++ b/lib/RT/Ticket.pm
@@ -1411,8 +1411,36 @@ sub TimeEstimatedAsString {
     return $self->_DurationAsString( $self->TimeEstimated );
 }
 
+=head2 TotalTimeWorked
 
+Returns the amount of time worked on this ticket and all child tickets
 
+=cut
+
+sub TotalTimeWorked {
+    my $self = shift;
+    my $seen = shift || {};
+    my $time = $self->TimeWorked;
+    my $links = $self->Members;
+    LINK: while (my $link = $links->Next) {
+        my $obj = $link->BaseObj;
+        next LINK if $seen->{$obj->Id};
+        $seen->{ $obj->Id } = 1;
+        $time += $obj->TotalTimeWorked($seen);
+    }
+    return $time;
+}
+
+=head2 TotalTimeWorkedAsString
+
+Returns the amount of time worked on this ticket and all its children as a formatted duration string
+
+=cut
+
+sub TotalTimeWorkedAsString {
+    my $self = shift;
+    return $self->_DurationAsString( $self->TotalTimeWorked );
+}
 
 =head2 Comment
 
diff --git a/share/html/Elements/RT__Ticket/ColumnMap b/share/html/Elements/RT__Ticket/ColumnMap
index 2db1149..089ccea 100644
--- a/share/html/Elements/RT__Ticket/ColumnMap
+++ b/share/html/Elements/RT__Ticket/ColumnMap
@@ -342,6 +342,16 @@ unless (RT->Config->Get('Crypt')->{'Enable'}) {
     $COLUMN_MAP->{KeyRequestors} = $GenericMap->{Requestors};
 }
 
+if(RT->Config->Get('DisplayTotalTimeWorked')) {
+  $COLUMN_MAP->{TotalTimeWorked} = {
+        attribute => 'TotalTimeWorked',
+        title => 'Total Time Worked',
+        value => sub {
+            return $_[0]->TotalTimeWorkedAsString;
+        },
+    }
+}
+
 $m->callback( GenericMap => $GenericMap, COLUMN_MAP => $COLUMN_MAP, CallbackName => 'Once', CallbackOnce => 1 );
 return GetColumnMapEntry( Map => $COLUMN_MAP, Name => $Name, Attribute => $Attr );
 </%init>
diff --git a/share/html/Search/Elements/BuildFormatString b/share/html/Search/Elements/BuildFormatString
index 1bf71b1..4bea321 100644
--- a/share/html/Search/Elements/BuildFormatString
+++ b/share/html/Search/Elements/BuildFormatString
@@ -101,6 +101,9 @@ my @fields = qw(
     NBSP
 ); # loc_qw
 
+# Total time worked is an optional ColumnMap enabled for rolling up child timeworked
+push @fields, 'TotalTimeWorked' if (RT->Config->Get('DisplayTotalTimeWorked'));
+
 my $CustomFields = RT::CustomFields->new( $session{'CurrentUser'});
 foreach my $id (keys %queues) {
     # Gotta load up the $queue object, since queues get stored by name now.
diff --git a/share/html/Ticket/Elements/ShowBasics b/share/html/Ticket/Elements/ShowBasics
index 0a06f02..78cf152 100644
--- a/share/html/Ticket/Elements/ShowBasics
+++ b/share/html/Ticket/Elements/ShowBasics
@@ -74,6 +74,12 @@
     <td class="value"><& ShowTime, minutes => $Ticket->TimeWorked &></td>
   </tr>
 % }
+% if (RT->Config->Get('DisplayTotalTimeWorked') && $Ticket->TotalTimeWorked) {
+  <tr class="project time worked sum">
+    <td class="label"><&|/l&>Total Time Worked</&>:</td>
+    <td class="value"><& ShowTime, minutes => $Ticket->TotalTimeWorked &></td>
+  </tr>
+% }
 % if ( keys %$time_worked ) {
 <tr class="time worked by-user">
   <td class="label"><&|/l&>Users</&>:</td>
diff --git a/t/api/total-time-worked.t b/t/api/total-time-worked.t
new file mode 100644
index 0000000..87a96d2
--- /dev/null
+++ b/t/api/total-time-worked.t
@@ -0,0 +1,120 @@
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => undef;
+
+diag("Test tickets project time worked");
+{
+    my $scrip = RT::Scrip->new(RT->SystemUser);
+    $scrip->LoadByCols(Description => 'On TimeWorked Change Update Parent TimeWorked');
+    $scrip->SetDisabled(1);
+
+    my $t1 = RT::Ticket->new(RT->SystemUser);
+    my ($ok1) = $t1->Create(
+        Queue => 'general',
+        Subject => 'project time worked test parent',
+    );
+
+    my $t2 = RT::Ticket->new(RT->SystemUser);
+    my ($ok2) = $t2->Create(
+        Queue => 'general',
+        Subject => 'project time worked test child',
+    );
+
+    my $t3 = RT::Ticket->new(RT->SystemUser);
+    my ($ok3) = $t3->Create(
+        Queue => 'general',
+        Subject => 'project time worked test child child',
+    );
+
+    my ($status1,$msg1) = $t1->AddLink(
+        Type => 'MemberOf',
+        Base => $t2->id,
+    );
+
+    my ($status2,$msg2) = $t2->AddLink(
+        Type => 'MemberOf',
+        Base => $t3->id,
+    );
+
+    my $t4 = RT::Ticket->new(RT->SystemUser);
+    my ($ok4) = $t4->Create(
+        Queue => 'general',
+        Subject => 'project time worked test other child child',
+    );
+
+    my ($status4,$msg4) = $t2->AddLink(
+        Type => 'MemberOf',
+        Base => $t4->id,
+    );
+
+    $t1->SetTimeWorked(10);
+    $t2->SetTimeWorked(20);
+    $t3->SetTimeWorked(40);
+    $t4->SetTimeWorked(50);
+
+    is $t4->TimeWorked, 50, 'set other child child time worked';
+    is $t4->TimeWorked, 50, 'check other child child time worked';
+    is $t3->TimeWorked, 40, 'check child child time worked';
+    is $t2->TimeWorked, 20, 'check child time worked';
+    is $t1->TimeWorked, 10, 'check parent time worked';
+
+    is $t1->TotalTimeWorked, 120, 'check parent project time worked';
+    is $t2->TotalTimeWorked, 110, 'check child project time worked';
+    is $t3->TotalTimeWorked, 40, 'check child child project time worked';
+    is $t4->TotalTimeWorked, 50, 'check other child child project time worked';
+
+    is $t1->TotalTimeWorkedAsString, '2 hours (120 minutes)', 'check parent project time worked as string';
+    is $t3->TotalTimeWorkedAsString, '40 minutes', 'check child child project time workd as string';
+}
+
+diag("Test multiple inheritance project time worked");
+{
+    my $scrip = RT::Scrip->new(RT->SystemUser);
+    $scrip->LoadByCols(Description => 'On TimeWorked Change Update Parent TimeWorked');
+    $scrip->SetDisabled(1);
+
+    my $t1 = RT::Ticket->new(RT->SystemUser);
+    my ($ok1) = $t1->Create(
+        Queue => 'general',
+        Subject => 'project time worked test parent',
+    );
+
+    my $t2 = RT::Ticket->new(RT->SystemUser);
+    my ($ok2) = $t2->Create(
+        Queue => 'general',
+        Subject => 'project time worked test child',
+    );
+
+    my $t3 = RT::Ticket->new(RT->SystemUser);
+    my ($ok3) = $t3->Create(
+        Queue => 'general',
+        Subject => 'project time worked test child child, and test child',
+    );
+
+    $t1->SetTimeWorked(10);
+    $t2->SetTimeWorked(20);
+    $t3->SetTimeWorked(40);
+
+    my ($status1,$msg1) = $t1->AddLink(
+        Type => 'MemberOf',
+        Base => $t2->id,
+    );
+
+    my ($status2,$msg2) = $t2->AddLink(
+        Type => 'MemberOf',
+        Base => $t3->id,
+    );
+
+     my ($status3,$msg3) = $t1->AddLink(
+        Type => 'MemberOf',
+        Base => $t3->id,
+    );
+
+    is $t1->TotalTimeWorked, 70, 'check parent project time worked';
+    is $t2->TotalTimeWorked, 60, 'check child project time worked';
+    is $t3->TotalTimeWorked, 40, 'check child child project time worked';
+
+}
+
+done_testing;

-----------------------------------------------------------------------


More information about the rt-commit mailing list