[Rt-commit] rt branch, 4.4/timeworked-per-user, created. rt-4.2.11-131-gc123666

Todd Wade todd at bestpractical.com
Tue Aug 18 11:04:02 EDT 2015


The branch, 4.4/timeworked-per-user has been created
        at  c1236662481eec2f812d641041c58920b7a9fbb9 (commit)

- Log -----------------------------------------------------------------
commit 081f4d1b967d8162d9709cb85499db181763c83b
Author: Todd Wade <todd at bestpractical.com>
Date:   Wed Jul 8 01:01:12 2015 -0400

    add a way for tests to get ticket pages besides the display page

diff --git a/lib/RT/Test/Web.pm b/lib/RT/Test/Web.pm
index 1f44d3c..718744d 100644
--- a/lib/RT/Test/Web.pm
+++ b/lib/RT/Test/Web.pm
@@ -159,13 +159,14 @@ sub logout {
 sub goto_ticket {
     my $self = shift;
     my $id   = shift;
+    my $view = shift || 'Display';
     unless ( $id && int $id ) {
         Test::More::diag( "error: wrong id ". defined $id? $id : '(undef)' );
         return 0;
     }
 
     my $url = $self->rt_base_url;
-    $url .= "Ticket/Display.html?id=$id";
+    $url .= "Ticket/${ view }.html?id=$id";
     $self->get($url);
     unless ( $self->status == 200 ) {
         Test::More::diag( "error: status is ". $self->status );

commit 01f3b2fa70e82ba148c5a33663be1a707f9966e9
Author: Todd Wade <todd at bestpractical.com>
Date:   Thu Aug 13 11:52:40 2015 -0400

    Automatically update the timeworked field of a ticket's parent tickets
    
    Increment parent tickets TimeWorked field when a child ticket TimeWorked
    is set or upated via scrip.
    
    For new installs, default to the behavior enabled. For upgrades, install
    the scrip disabled.

diff --git a/etc/initialdata b/etc/initialdata
index dd1daf5..7771d8a 100644
--- a/etc/initialdata
+++ b/etc/initialdata
@@ -111,6 +111,10 @@
     { Name        => 'Send Forward',                 # loc
       Description => 'Send forwarded message',       # loc
       ExecModule  => 'SendForward', },
+    { Name        => 'Update Parent TimeWorked',     # loc
+      Description => 'Update Parent TimeWorked',     # loc
+      ExecModule  => 'UpdateParentTimeWorked',
+    },
 );
 
 @ScripConditions = (
@@ -219,6 +223,12 @@
        ApplicableTransTypes => 'Status,Set',
        ExecModule           => 'ReopenTicket',
     },
+    {
+       Name                 => 'On TimeWorked Change',                    # loc
+       Description          => 'When TimeWorked Change',                  # loc
+       ApplicableTransTypes => 'Any',
+       ExecModule           => 'TimeWorkedChange',
+    },
 
 );
 
@@ -792,6 +802,10 @@ Hour:         { $SubscriptionObj->SubValue('Hour') }
        ScripCondition => 'On Forward Ticket',
        ScripAction    => 'Send Forward',
        Template       => 'Forward Ticket' },
+    {  Description    => 'On TimeWorked Change Update Parent TimeWorked',
+       ScripCondition => 'On TimeWorked Change',
+       ScripAction    => 'Update Parent TimeWorked',
+       Template       => 'Blank' },
 );
 
 @ACL = (
diff --git a/etc/upgrade/4.3.8/content b/etc/upgrade/4.3.8/content
new file mode 100644
index 0000000..e9d5b12
--- /dev/null
+++ b/etc/upgrade/4.3.8/content
@@ -0,0 +1,31 @@
+use warnings;
+use strict;
+
+our @ScripActions = (
+    {
+        Name        => 'Update Parent TimeWorked',    # loc
+        Description => 'Update Parent TimeWorked',    # loc
+        ExecModule  => 'UpdateParentTimeWorked',
+    },
+);
+
+our @ScripConditions = (
+    {
+        Name                 => 'On TimeWorked Change',      # loc
+        Description          => 'When TimeWorked Change',    # loc
+        ApplicableTransTypes => 'Any',
+        ExecModule           => 'TimeWorkedChange',
+    },
+);
+
+our @Scrips = (
+    {
+        Description    => 'On TimeWorked Change Update Parent TimeWorked',
+        ScripCondition => 'On TimeWorked Change',
+        ScripAction    => 'Update Parent TimeWorked',
+        Template       => 'Blank',
+        Disabled       => 1,
+    },
+);
+
+1;
diff --git a/lib/RT/Action/UpdateParentTimeWorked.pm b/lib/RT/Action/UpdateParentTimeWorked.pm
new file mode 100644
index 0000000..6904f55
--- /dev/null
+++ b/lib/RT/Action/UpdateParentTimeWorked.pm
@@ -0,0 +1,112 @@
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2015 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::UpdateParentTimeWorked;
+use base 'RT::Action';
+
+=head1 NAME
+
+RT::Action::UpdateParentTimeWorked - RT's scrip action to set/update the time
+worked on a parent ticket when a child ticket's TimeWorked is added to.
+
+=head1 DESCRIPTION
+
+This action is used as an action for the 'On TimeWorked Change' condition.
+
+When it fires it finds a ticket's parent tickets and increments the time on
+those tickets along with the built in behavior of incrementing the TimeWorked
+on the current ticket.
+
+=cut
+
+sub Prepare {
+    my $self = shift;
+    my $ticket = $self->TicketObj;
+    return 0 unless $ticket->MemberOf->Count;
+    return 1;
+}
+
+sub Commit {
+    my $self   = shift;
+    my $ticket = $self->TicketObj;
+    my $txn    = $self->TransactionObj;
+
+    my $parents     = $ticket->MemberOf;
+    my $time_worked = $txn->TimeTaken
+      || ( $txn->NewValue - $txn->OldValue );
+
+    while ( my $parent = $parents->Next ) {
+        my $parent_ticket = $parent->TargetObj;
+        my $original_actor = RT::CurrentUser->new( $txn->Creator );
+        my $actor_parent_ticket = RT::Ticket->new( $original_actor );
+        $actor_parent_ticket->Load( $parent_ticket->Id );
+        unless ( $actor_parent_ticket->Id ) {
+            RT->Logger->error("Unable to load ".$parent_ticket->Id." as ".$txn->Creator->Name);
+            return 0;
+        }
+        my ( $ret, $msg ) = $actor_parent_ticket->_Set(
+            Field   => 'TimeWorked',
+            Value   => $parent_ticket->TimeWorked + $time_worked,
+        );
+        unless ($ret) {
+            RT->Logger->error(
+                "Failed to update parent ticket's TimeWorked: $msg");
+        }
+    }
+}
+
+=head1 AUTHOR
+
+Best Practical Solutions, LLC E<lt>modules at bestpractical.comE<gt>
+
+=cut
+
+1;
diff --git a/lib/RT/Condition/TimeWorkedChange.pm b/lib/RT/Condition/TimeWorkedChange.pm
new file mode 100644
index 0000000..469cb2b
--- /dev/null
+++ b/lib/RT/Condition/TimeWorkedChange.pm
@@ -0,0 +1,84 @@
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2015 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::Condition::TimeWorkedChange;
+use base 'RT::Condition';
+
+=head1 NAME
+
+RT::Condition::TimeWorkedChange - RT's scrip condition that fires when the
+TimeWorked field has a value at form submission.
+
+=head1 DESCRIPTION
+
+This condition is true when the transaction has a TimeTaken value or the
+TimeWorked field is being updated.
+
+=cut
+
+sub IsApplicable {
+    my $self = shift;
+    my $txn = $self->TransactionObj;
+    return 1 if $txn->TimeTaken;
+    return 1
+      if $txn->Type eq 'Set'
+          && $txn->Field eq 'TimeWorked'
+          && ( $txn->NewValue - $txn->OldValue );
+    return 0;
+}
+
+=head1 AUTHOR
+
+Best Practical Solutions, LLC E<lt>modules at bestpractical.comE<gt>
+
+=cut
+
+1;
diff --git a/t/web/ticket_timeworked.t b/t/web/ticket_timeworked.t
new file mode 100644
index 0000000..94754f3
--- /dev/null
+++ b/t/web/ticket_timeworked.t
@@ -0,0 +1,76 @@
+use strict;
+use warnings;
+use RT::Test tests => undef;
+
+my ( $baseurl, $m ) = RT::Test->started_ok;
+ok( $m->login, "Logged in" );
+
+my $queue = RT::Test->load_or_create_queue( Name => 'General' );
+ok( $queue->id, "loaded the General queue" );
+
+my ( $child1, $child2 ) = RT::Test->create_tickets(
+    { Queue   => 'General' },
+    { Subject => 'child ticket 1', },
+    { Subject => 'child ticket 2', },
+);
+
+my ( $child1_id, $child2_id ) = ( $child1->id, $child2->id );
+my $parent_id; # id of the parent ticket
+
+diag "add ticket links of type MemberOf base"; {
+    my $ticket = RT::Test->create_ticket(
+        Queue   => 'General',
+        Subject => "timeworked parent",
+    );
+    my $id = $parent_id = $ticket->id;
+
+    $m->goto_ticket($id);
+    $m->follow_link_ok( { text => 'Links' }, "Followed link to Links" );
+
+    ok( $m->form_with_fields("MemberOf-$id"), "found the form" );
+    $m->field( "MemberOf-$id", "$child1_id $child2_id" );
+
+    $m->submit;
+
+    $m->content_like(
+        qr{"DeleteLink-.*?ticket/$child1_id-MemberOf-"},
+        "base for MemberOf: has child1 ticket",
+    );
+    $m->content_like(
+        qr{"DeleteLink-.*?ticket/$child2_id-MemberOf-"},
+        "base for MemberOf: has child2 ticket",
+    );
+
+    $m->goto_ticket($id);
+    $m->content_like( qr{$child1_id:.*?\[new\]}, "has active ticket", );
+}
+
+my @updates = ({
+    id => $child1_id,
+    view => 'Modify',
+    field => 'TimeWorked',
+    form => 'TicketModify',
+    title => "Modify ticket #$child1_id",
+}, {
+    id => $child2_id,
+    view => 'Update',
+    field => 'UpdateTimeWorked',
+    form => 'TicketUpdate',
+    title => "Update ticket #$child2_id (child ticket 2)",
+});
+
+
+foreach my $update ( @updates ) {
+    $m->goto_ticket( $update->{id}, $update->{view} );
+    $m->title_is( $update->{title}, 'have child ticket page' );
+    ok( $m->form_name( $update->{form} ), 'found the form' );
+    $m->field( $update->{field}, 90 );
+    $m->submit_form( button => 'SubmitTicket' );
+}
+
+$m->goto_ticket( $parent_id );
+$m->title_is( "#$parent_id: timeworked parent");
+$m->content_like( qr{180 minutes}, "found expected minutes in parent ticket" );
+
+undef $m;
+done_testing();

commit c1236662481eec2f812d641041c58920b7a9fbb9
Author: Todd Wade <todd at bestpractical.com>
Date:   Thu Aug 13 12:16:44 2015 -0400

    Break out the time worked on a ticket per user
    
    Under the total time worked in the ticket basics on the ticket display
    page, display the time that each user has worked on the ticket. A scrip
    is used to cache the time worked per user in a ticket attribute.
    
    For new installs, default to the behavior enabled. For upgrades, install
    the scrip disabled.

diff --git a/etc/initialdata b/etc/initialdata
index 7771d8a..cd899e7 100644
--- a/etc/initialdata
+++ b/etc/initialdata
@@ -115,6 +115,10 @@
       Description => 'Update Parent TimeWorked',     # loc
       ExecModule  => 'UpdateParentTimeWorked',
     },
+    { Name        => 'Update User TimeWorked',       # loc
+      Description => 'Update User TimeWorked',       # loc
+      ExecModule  => 'UpdateUserTimeWorked',
+    },
 );
 
 @ScripConditions = (
@@ -806,6 +810,10 @@ Hour:         { $SubscriptionObj->SubValue('Hour') }
        ScripCondition => 'On TimeWorked Change',
        ScripAction    => 'Update Parent TimeWorked',
        Template       => 'Blank' },
+    {  Description    => 'On TimeWorked Change Update User TimeWorked',
+       ScripCondition => 'On TimeWorked Change',
+       ScripAction    => 'Update User TimeWorked',
+       Template       => 'Blank' },
 );
 
 @ACL = (
diff --git a/etc/upgrade/4.3.8/content b/etc/upgrade/4.3.8/content
index e9d5b12..7db3bef 100644
--- a/etc/upgrade/4.3.8/content
+++ b/etc/upgrade/4.3.8/content
@@ -7,8 +7,14 @@ our @ScripActions = (
         Description => 'Update Parent TimeWorked',    # loc
         ExecModule  => 'UpdateParentTimeWorked',
     },
+    {
+        Name        => 'Update User TimeWorked',    # loc
+        Description => 'Update User TimeWorked',    # loc
+        ExecModule  => 'UpdateUserTimeWorked',
+    },
 );
 
+
 our @ScripConditions = (
     {
         Name                 => 'On TimeWorked Change',      # loc
@@ -26,6 +32,13 @@ our @Scrips = (
         Template       => 'Blank',
         Disabled       => 1,
     },
+    {
+        Description    => 'On TimeWorked Change Update User TimeWorked',
+        ScripCondition => 'On TimeWorked Change',
+        ScripAction    => 'Update User TimeWorked',
+        Template       => 'Blank',
+        Disabled       => 1,
+    },
 );
 
 1;
diff --git a/lib/RT/Action/UpdateUserTimeWorked.pm b/lib/RT/Action/UpdateUserTimeWorked.pm
new file mode 100644
index 0000000..ddd221b
--- /dev/null
+++ b/lib/RT/Action/UpdateUserTimeWorked.pm
@@ -0,0 +1,95 @@
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2015 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::UpdateUserTimeWorked;
+use base 'RT::Action';
+
+=head1 NAME
+
+RT::Action::UpdateUserTimeWorked - RT's scrip action to set/update the time
+worked for a user each time they log time worked on a ticket
+
+=head1 DESCRIPTION
+
+This action is used as an action for the 'On TimeWorked Change' condition.
+
+When it fires, a ticket attribute stores the amount of time the user updating
+the ticket worked on it.
+
+=cut
+
+sub Prepare {
+    return 1;
+}
+
+sub Commit {
+    my $self   = shift;
+    my $ticket = $self->TicketObj;
+    my $txn    = $self->TransactionObj;
+
+    my $time_worked_attr = $ticket->FirstAttribute('TimeWorked');
+    # if the attribute is not defined, we will initialize it in the callback,
+    # so no need to handle it here
+    if ( $time_worked_attr ) {
+        my $time_worked = $time_worked_attr->Content;
+        $time_worked->{ $txn->CreatorObj->Name } += $txn->TimeTaken
+          || $txn->NewValue - $txn->OldValue;
+        $time_worked_attr->SetContent( $time_worked );
+    }
+}
+
+=head1 AUTHOR
+
+Best Practical Solutions, LLC E<lt>modules at bestpractical.comE<gt>
+
+=cut
+
+1;
diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index 193b2c2..3f288e0 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -3978,6 +3978,10 @@ our %SCRUBBER_ALLOWED_ATTRIBUTES = (
     }ix,
     dir    => qr/^(rtl|ltr)$/i,
     lang   => qr/^\w+(-\w+)?$/,
+
+    # timeworked per user attributes
+    'data-ticket-id'    => 1,
+    'data-ticket-class' => 1,
 );
 
 our %SCRUBBER_RULES = ();
diff --git a/share/html/Ticket/Elements/ShowBasics b/share/html/Ticket/Elements/ShowBasics
index 546f581..9c37eb3 100644
--- a/share/html/Ticket/Elements/ShowBasics
+++ b/share/html/Ticket/Elements/ShowBasics
@@ -62,11 +62,26 @@
 % }
 % $m->callback( %ARGS, CallbackName => 'AfterTimeEstimated', TicketObj => $Ticket );
 % if ($Ticket->TimeWorked) {
-  <tr class="time worked">
+  <tr class="time worked sum">
     <td class="label"><&|/l&>Worked</&>:</td>
     <td class="value"><& ShowTime, minutes => $Ticket->TimeWorked &></td>
   </tr>
 % }
+% if ( keys %$time_worked ) {
+<tr class="time worked by-user">
+  <td class="label"><&|/l&>Users</&>:</td>
+  <td>
+    <table>
+%   for my $user ( keys %$time_worked ) {
+      <tr>
+        <td class="value"><% $user %>:</td>
+        <td class="value"><& /Ticket/Elements/ShowTime, minutes => $time_worked->{$user} &></td>
+      </tr>
+%   }
+    </table>
+  </td>
+</tr>
+% }
 % $m->callback( %ARGS, CallbackName => 'AfterTimeWorked', TicketObj => $Ticket );
 % if ($Ticket->TimeLeft) {
   <tr class="time left">
@@ -95,3 +110,43 @@
 $Ticket => undef
 $UngroupedCFs => 0
 </%ARGS>
+<%init>
+my $time_worked;
+if ( $Ticket->TimeWorked ) {
+    my $time_worked_attr = $Ticket->FirstAttribute('TimeWorked');
+
+    if ($time_worked_attr) {
+        $time_worked = $time_worked_attr->Content;
+    } else {
+        $time_worked = {};
+        my $transactions = $Ticket->Transactions;
+        $transactions->Limit(
+            FIELD     => 'Type',
+            VALUE     => 'Set',
+            SUBCLAUSE => 'timeworked',
+        );
+
+        $transactions->Limit(
+            FIELD           => 'Field',
+            VALUE           => 'TimeWorked',
+            SUBCLAUSE       => 'timeworked',
+            ENTRYAGGREGATOR => 'AND',
+        );
+
+        $transactions->Limit(
+            FIELD           => 'TimeTaken',
+            VALUE           => 0,
+            OPERATOR        => '>',
+            SUBCLAUSE       => 'timeworked',
+            ENTRYAGGREGATOR => 'OR',
+        );
+
+        while ( my $txn = $transactions->Next ) {
+            $time_worked->{ $txn->CreatorObj->Name } += $txn->TimeTaken
+              || $txn->NewValue - $txn->OldValue;
+        }
+        $Ticket->SetAttribute( Name => 'TimeWorked', Content => $time_worked );
+    }
+}
+
+</%init>
diff --git a/t/web/ticket_timeworked.t b/t/web/ticket_timeworked.t
index 94754f3..4737bda 100644
--- a/t/web/ticket_timeworked.t
+++ b/t/web/ticket_timeworked.t
@@ -17,7 +17,7 @@ my ( $child1, $child2 ) = RT::Test->create_tickets(
 my ( $child1_id, $child2_id ) = ( $child1->id, $child2->id );
 my $parent_id; # id of the parent ticket
 
-diag "add ticket links of type MemberOf base"; {
+diag "add ticket links for timeworked tests"; {
     my $ticket = RT::Test->create_ticket(
         Queue   => 'General',
         Subject => "timeworked parent",
@@ -45,32 +45,106 @@ diag "add ticket links of type MemberOf base"; {
     $m->content_like( qr{$child1_id:.*?\[new\]}, "has active ticket", );
 }
 
-my @updates = ({
-    id => $child1_id,
-    view => 'Modify',
-    field => 'TimeWorked',
-    form => 'TicketModify',
-    title => "Modify ticket #$child1_id",
-}, {
-    id => $child2_id,
-    view => 'Update',
-    field => 'UpdateTimeWorked',
-    form => 'TicketUpdate',
-    title => "Update ticket #$child2_id (child ticket 2)",
-});
-
-
-foreach my $update ( @updates ) {
-    $m->goto_ticket( $update->{id}, $update->{view} );
-    $m->title_is( $update->{title}, 'have child ticket page' );
-    ok( $m->form_name( $update->{form} ), 'found the form' );
-    $m->field( $update->{field}, 90 );
-    $m->submit_form( button => 'SubmitTicket' );
+diag "adding timeworked values for child tickets"; {
+    my $user_a = RT::Test->load_or_create_user(
+        Name => 'user_a', Password => 'password',
+    );
+    ok $user_a && $user_a->id, 'loaded or created user';
+
+    my $user_b = RT::Test->load_or_create_user(
+        Name => 'user_b', Password => 'password',
+    );
+    ok $user_b && $user_b->id, 'loaded or created user';
+
+    ok( RT::Test->set_rights(
+        { Principal => $user_a, Right => [qw(SeeQueue ShowTicket ModifyTicket CommentOnTicket)] },
+        { Principal => $user_b, Right => [qw(SeeQueue ShowTicket ModifyTicket CommentOnTicket)] },
+    ), 'set rights');
+
+
+    my @updates = ({
+        id => $child1_id,
+        view => 'Modify',
+        field => 'TimeWorked',
+        form => 'TicketModify',
+        title => "Modify ticket #$child1_id",
+        time => 45,
+        user => 'user_a',
+    }, {
+        id => $child2_id,
+        view => 'Modify',
+        field => 'TimeWorked',
+        form => 'TicketModify',
+        title => "Modify ticket #$child2_id",
+        time => 35,
+        user => 'user_a',
+    }, {
+        id => $child2_id,
+        view => 'Update',
+        field => 'UpdateTimeWorked',
+        form => 'TicketUpdate',
+        title => "Update ticket #$child2_id (child ticket 2)",
+        time => 90,
+        user => 'user_b',
+    });
+
+    foreach my $update ( @updates ) {
+        my $agent = RT::Test::Web->new;
+        ok $agent->login($update->{user}, 'password'), 'logged in as user';
+        $agent->goto_ticket( $update->{id}, $update->{view} );
+        $agent->title_is( $update->{title}, 'have child ticket page' );
+        ok( $agent->form_name( $update->{form} ), 'found the form' );
+        $agent->field( $update->{field}, $update->{time} );
+        $agent->submit_form( button => 'SubmitTicket' );
+    }
+}
+
+diag "checking parent ticket for expected timeworked data"; {
+    $m->goto_ticket( $parent_id );
+    $m->title_is( "#$parent_id: timeworked parent");
+    $m->content_like(
+        qr{(?s)Worked:.+?value">2\.8 hours \(170 minutes\)},
+        "found expected total TimeWorked in parent ticket"
+    );
+    $m->content_like(
+        qr{(?s)user_a:.+?value">1\.3 hours \(80 minutes\)},
+        "found expected user_a TimeWorked in parent ticket"
+    );
+    $m->content_like(
+        qr{(?s)user_b:.+?value">1\.5 hours \(90 minutes\)},
+        "found expected user_b TimeWorked in parent ticket"
+    );
+}
+
+diag "checking child ticket 1 for expected timeworked data"; {
+    $m->goto_ticket( $child1_id );
+    $m->title_is( "#$child1_id: child ticket 1");
+    $m->content_like(
+        qr{(?s)Worked:.+?value">45 minutes},
+        "found expected total TimeWorked in child ticket 1"
+    );
+    $m->content_like(
+        qr{(?s)user_a:.+?value">45 minutes},
+        "found expected user_a TimeWorked in child ticket 1"
+    );
 }
 
-$m->goto_ticket( $parent_id );
-$m->title_is( "#$parent_id: timeworked parent");
-$m->content_like( qr{180 minutes}, "found expected minutes in parent ticket" );
+diag "checking child ticket 2 for expected timeworked data"; {
+    $m->goto_ticket( $child2_id );
+    $m->title_is( "#$child2_id: child ticket 2");
+    $m->content_like(
+        qr{(?s)Worked:.+?value">2\.1 hours \(125 minutes\)},
+        "found expected total TimeWorked in child ticket 2"
+    );
+    $m->content_like(
+        qr{(?s)user_a:.+?value">35 minutes},
+        "found expected user_a TimeWorked in child ticket 2"
+    );
+    $m->content_like(
+        qr{(?s)user_b:.+?value">1\.5 hours \(90 minutes\)},
+        "found expected user_b TimeWorked in child ticket 2"
+    );
+}
 
 undef $m;
 done_testing();

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


More information about the rt-commit mailing list