import rt 3.6.4
[freeside.git] / rt / html / Search / Bulk.html
index f9eef26..9742df5 100644 (file)
@@ -2,7 +2,7 @@
 %# 
 %# COPYRIGHT:
 %#  
-%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC 
+%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC 
 %#                                          <jesse@bestpractical.com>
 %# 
 %# (Except where explicitly superseded by other copyright notices)
@@ -22,7 +22,9 @@
 %# 
 %# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+%# 02110-1301 or visit their web page on the internet at
+%# http://www.gnu.org/copyleft/gpl.html.
 %# 
 %# 
 %# CONTRIBUTION SUBMISSION POLICY:
 %# those contributions and any derivatives thereof.
 %# 
 %# END BPS TAGGED BLOCK }}}
-<& /Elements/Header, Title => loc("Bulk ticket update") &>
-<& /Elements/Tabs, Title => loc("Bulk ticket update") &>
+<& /Elements/Header, Title => $title &>
+<& /Ticket/Elements/Tabs, 
+    current_tab => "Search/Bulk.html",
+    Title => $title,
+    Format => $ARGS{'Format'}, # we don't want the locally modified one
+    Query => $Query,
+    Rows => $Rows,
+    OrderBy => $OrderBy,
+    Order => $Order &>
 
 <& /Elements/ListActions, actions => \@results &>
-<FORM METHOD="POST" ACTION="<%$RT::WebPath%>/Search/Bulk.html" >
-<input type="hidden" name="Query" value="<%$ARGS{'Query'}%>">
-<TABLE WIDTH=100% border=0 cellpadding=3 CELLSPACING=0>
-<TR>
-<TH><&|/l&>Update</&></TH>
-%foreach my $col (@cols) {
-% my $colalias = $col;
-% $colalias =~ s/(Obj\-\>|)(Name|AsString)//;
-
-<TH><% loc($colalias) %>&nbsp;</TH>
+<form method="post" action="<%$RT::WebPath%>/Search/Bulk.html" enctype="multipart/form-data">
+% foreach my $var qw(Query Format OrderBy Order Rows Page) {
+<input type="hidden" class="hidden" name="<%$var%>" value="<%$ARGS{$var}%>" />
 %}
-</TR>
-
-<%PERL>
-
-my $i;
-
-$Tickets->RedoSearch();
-while (my $Ticket = $Tickets->Next) {
- $i++;
- if ($i % 2) {
-     $bgcolor = "#dddddd";
- }
- else {
-     $bgcolor = "#ffffff";
- }
-      </%PERL>
-<TR bgcolor="<%$bgcolor%>">
-<TD><input type=checkbox name="UpdateTicket<%$Ticket->Id%>" value="1" CHECKED></TD>
-%foreach my $col (@cols) {
-<TD>
-% if ($col eq 'id') {
-<A HREF="<% $RT::WebPath%>/Ticket/Display.html?id=<%$Ticket->Id%>"><%$Ticket->Id()%></A>
-% }
-%else {
-<% eval "\$Ticket->$col()" %>&nbsp;
-%}
-</TD>
-%}
-</TR>
-%}
-
-
-
-</TABLE>
-
-<HR>
-
-
-<& /Elements/TitleBoxStart, title => loc('Update selected tickets') &>
-<TABLE>
-<TR>
-<TD VALIGN=TOP>
+<& /Elements/TicketList, Query => $Query,
+    DisplayFormat => $Format,
+    Format => $ARGS{'Format'},
+    Verbatim => 1,
+    AllowSorting => 1,
+    OrderBy => $OrderBy,
+    Order => $Order,
+    Rows => $Rows,
+    Page => $Page,
+    BaseURL => $RT::WebPath."/Search/Bulk.html?"
+   &>
+
+<hr>
+
+<& /Elements/Submit, Label => loc('Update'), CheckAll => 1, ClearAll => 1 &>
+<br />
+<&|/Widgets/TitleBox, title => $title &>
+<table>
+<tr>
+<td valign="top">
 <table>
-<tr><td class=label> <&|/l&>Make Owner</&>: </td>
-<td class=value> <& /Elements/SelectOwner, Name => "Owner" &> (<input type=checkbox name="ForceOwnerChange"> <&|/l&>Force change</&>) </td></tr>
-<tr><td class=label> <&|/l&>Add Requestor</&>: </td>
-<td class=value> <INPUT Name="AddRequestor" SIZE=20> </td></tr>
-<tr><td class=label> <&|/l&>Remove Requestor</&>: </td>
-<td class=value> <INPUT Name="DeleteRequestor" SIZE=20> </td></tr>
-<tr><td class=label> <&|/l&>Add Cc</&>: </td>
-<td class=value> <INPUT Name="AddCc" SIZE=20> </td></tr>
-<tr><td class=label> <&|/l&>Remove Cc</&>: </td>
-<td class=value> <INPUT Name="DeleteCc" SIZE=20> </td></tr>
-<tr><td class=label> <&|/l&>Add AdminCc</&>: </td>
-<td class=value> <INPUT Name="AddAdminCc" SIZE=20> </td></tr>
-<tr><td class=label> <&|/l&>Remove AdminCc</&>: </td>
-<td class=value> <INPUT Name="DeleteAdminCc" SIZE=20> </td></tr>
+<tr><td class="label"> <&|/l&>Make Owner</&>: </td>
+<td class="value"> <& /Elements/SelectOwner, Name => "Owner" &> (<input type="checkbox" class="checkbox" name="ForceOwnerChange" /> <&|/l&>Force change</&>) </td></tr>
+<tr><td class="label"> <&|/l&>Add Requestor</&>: </td>
+<td class="value"> <input name="AddRequestor" size="20" /> </td></tr>
+<tr><td class="label"> <&|/l&>Remove Requestor</&>: </td>
+<td class="value"> <input name="DeleteRequestor" size="20" /> </td></tr>
+<tr><td class="label"> <&|/l&>Add Cc</&>: </td>
+<td class="value"> <input name="AddCc" size="20" /> </td></tr>
+<tr><td class="label"> <&|/l&>Remove Cc</&>: </td>
+<td class="value"> <input name="DeleteCc" size="20" /> </td></tr>
+<tr><td class="label"> <&|/l&>Add AdminCc</&>: </td>
+<td class="value"> <input name="AddAdminCc" size="20" /> </td></tr>
+<tr><td class="label"> <&|/l&>Remove AdminCc</&>: </td>
+<td class="value"> <input name="DeleteAdminCc" size="20" /> </td></tr>
 </table>
-</TD>
-<TD VALIGN=TOP>
+</td>
+<td valign="top">
 <table>
-<tr><td class=label> <&|/l&>Make subject</&>: </td>
-<td class=value> <INPUT Name="Subject" SIZE=20> </td></tr>
-<tr><td class=label> <&|/l&>Make priority</&>: </td>
-<td class=value> <INPUT Name="Priority" SIZE=4> </td></tr>
-<tr><td class=label> <&|/l&>Make queue</&>: </td>
-<td class=value> <& /Elements/SelectQueue, Name => "Queue" &> </td></tr>
-<tr><td class=label> <&|/l&>Make Status</&>: </td>
-<td class=value> <& /Elements/SelectStatus, Name => "Status" &> </td></tr>
-<tr><td class=label> <&|/l&>Make date Starts</&>: </td>
-<td class=value> <& /Elements/SelectDate, Name => "Starts_Date", ShowTime => 0, Default => '' &> </td></tr>
-<tr><td class=label> <&|/l&>Make date Started</&>: </td>
-<td class=value> <& /Elements/SelectDate, Name => "Started_Date", ShowTime => 0, Default => '' &> </td></tr>
-<tr><td class=label> <&|/l&>Make date Told</&>: </td>
-<td class=value> <& /Elements/SelectDate, Name => "Told_Date", ShowTime => 0, Default => '' &> </td></tr>
-<tr><td class=label> <&|/l&>Make date Due</&>: </td>
-<td class=value> <& /Elements/SelectDate, Name => "Due_Date", ShowTime => 0, Default => '' &> </td></tr>
-<tr><td class=label> <&|/l&>Make date Resolved</&>: </td>
-<td class=value> <& /Elements/SelectDate, Name => "Resolved_Date", ShowTime => 0, Default => '' &> </td></tr>
+<tr><td class="label"> <&|/l&>Make subject</&>: </td>
+<td class="value"> <input name="Subject" size="20" /> </td></tr>
+<tr><td class="label"> <&|/l&>Make priority</&>: </td>
+<td class="value"> <input name="Priority" size="4" /> </td></tr>
+<tr><td class="label"> <&|/l&>Make queue</&>: </td>
+<td class="value"> <& /Elements/SelectQueue, Name => "Queue" &> </td></tr>
+<tr><td class="label"> <&|/l&>Make Status</&>: </td>
+<td class="value"> <& /Elements/SelectStatus, Name => "Status" &> </td></tr>
+<tr><td class="label"> <&|/l&>Make date Starts</&>: </td>
+<td class="value"> <& /Elements/SelectDate, Name => "Starts_Date", ShowTime => 0, Default => '' &> </td></tr>
+<tr><td class="label"> <&|/l&>Make date Started</&>: </td>
+<td class="value"> <& /Elements/SelectDate, Name => "Started_Date", ShowTime => 0, Default => '' &> </td></tr>
+<tr><td class="label"> <&|/l&>Make date Told</&>: </td>
+<td class="value"> <& /Elements/SelectDate, Name => "Told_Date", ShowTime => 0, Default => '' &> </td></tr>
+<tr><td class="label"> <&|/l&>Make date Due</&>: </td>
+<td class="value"> <& /Elements/SelectDate, Name => "Due_Date", ShowTime => 0, Default => '' &> </td></tr>
+<tr><td class="label"> <&|/l&>Make date Resolved</&>: </td>
+<td class="value"> <& /Elements/SelectDate, Name => "Resolved_Date", ShowTime => 0, Default => '' &> </td></tr>
 </table>
 
-</TD>
-</TR>
+</td>
+</tr>
 </table>
-<& /Elements/TitleBoxEnd&>
-<& /Elements/TitleBoxStart, title => loc('Add comments or replies to selected tickets') &>
+</&>
+<&| /Widgets/TitleBox, title => loc('Add comments or replies to selected tickets') &>
 <table>
-<tr><td align=right><&|/l&>Update Type</&>:</td>
+<tr><td align="right"><&|/l&>Update Type</&>:</td>
 <td><select name="UpdateType">
   <option value="private" ><&|/l&>Comments (not sent to requestors)</&></option>
 <option value="response" ><&|/l&>Reply to requestors</&></option>
 </select> 
 </td></tr>
-<tr><td align=right><&|/l&>Subject</&>:</td><td> <input name="UpdateSubject" size=60 value=""></td></tr>
+<tr><td align="right"><&|/l&>Subject</&>:</td><td> <input name="UpdateSubject" size="60" value="" /></td></tr>
 % while (my $CF = $TxnCFs->Next()) {
-<TR>
-<TD ALIGN=RIGHT><% $CF->Name %>:</TD>
-<TD><& /Elements/EditCustomField, 
+<tr>
+<td align="right"><% $CF->Name %>:</td>
+<td><& /Elements/EditCustomField, 
     CustomField => $CF, 
     NamePrefix => "Object-RT::Transaction--CustomField-"
-    &><em><% $CF->FriendlyType %></em></TD>
-</TD></TR>
+    &><em><% $CF->FriendlyType %></em></td>
+</td></tr>
 % } # end if while
- <tr><td align=right><&|/l&>Attach</&>:</td><td><input name="UpdateAttachment" type="file"></td></tr>
- <tr><td class=labeltop><&|/l&>Message</&>:</td><td>
+ <tr><td align="right"><&|/l&>Attach</&>:</td><td><input name="UpdateAttachment" type="file" /></td></tr>
+ <tr><td class="labeltop"><&|/l&>Message</&>:</td><td>
  <& /Elements/MessageBox, Name=>"UpdateContent"&>
  </td></tr>
  </table>
 
-<& /Elements/TitleBoxEnd &>
-
+</&>
+<&|/Widgets/TitleBox, title => loc('Edit Custom Fields'), color => "#336633"&>
+<%perl>
+my $cfs = RT::CustomFields->new($session{'CurrentUser'});
+$cfs->LimitToGlobal();
+$cfs->LimitToQueue($_) for keys %$seen_queues;
+</%perl>
+<table>
+<tr>
+<th><&|/l&>Name</&></th>
+<th><&|/l&>Add values</&></th>
+<th><&|/l&>Delete values</&></th>
+</tr>
+% while (my $cf = $cfs->Next()) {
+<tr>
+<td class="label"><%$cf->Name%><br />
+<em>(<%$cf->FriendlyType%>)</em></td>
+% my $rows = 5;
+% my @add = (NamePrefix => 'Bulk-Add-CustomField-', CustomField => $cf, Rows => $rows, Multiple => ($cf->MaxValues ==1 ? 0 : 1) , Cols => 25);
+% my @del = (NamePrefix => 'Bulk-Delete-CustomField-', CustomField => $cf, Rows => $rows, Multiple => 1, Cols => 25);
+% if ($cf->Type eq 'Select') {
+<td><& /Elements/EditCustomFieldSelect, @add &></td>
+<td><& /Elements/EditCustomFieldSelect, @del &></td>
+% } elsif ($cf->Type eq 'Combobox') {
+<td><& /Elements/EditCustomFieldCombobox, @add &></td>
+<td><& /Elements/EditCustomFieldCombobox, @del &></td>
+% } elsif ($cf->Type eq 'Freeform') {
+<td><& /Elements/EditCustomFieldFreeform, @add &></td>
+<td><& /Elements/EditCustomFieldFreeform, @del &></td>
+% } elsif ($cf->Type eq 'Text') {
+<td><& /Elements/EditCustomFieldText, @add &></td>
+<td>&nbsp;</td>
+% } else {
+%   $RT::Logger->crit("Unknown CustomField type: " . $cf->Type);
+% }
+</tr>
+% }
+</table>
+</&>
 
-<& /Elements/TitleBoxStart, title => loc('Edit Links'), color => "#336633"&>
-<i><&|/l&>Enter tickets or URIs to link tickets to. Separate multiple entries with spaces.</&></i><br>
+<&|/Widgets/TitleBox, title => loc('Edit Links'), color => "#336633"&>
+<em><&|/l&>Enter tickets or URIs to link tickets to. Separate multiple entries with spaces.</&></em><br />
 <& /Ticket/Elements/BulkLinks &>
-<& /Elements/TitleBoxEnd &>
+</&>
+
+<& /Elements/Submit, Label => loc('Update') &>
+
 
-<& /Elements/Submit, Label => loc('Update All') &>
+</form>
 
 
-</FORM>
 <%INIT>
+my $title = loc("Update multiple tickets");
 
 # Iterate through the ARGS hash and remove anything with a null value.
-map ($ARGS{$_} =~ /^$/ && (delete $ARGS{$_}), keys %ARGS);
-
-my ($bgcolor, @results);
-my @cols = qw(id Status Priority Subject QueueObj->Name OwnerObj->Name RequestorAddresses DueAsString );
-
-
-my $Tickets = RT::Tickets->new($session{'CurrentUser'});
-$Tickets->FromSQL($ARGS{'Query'});
-
-Abort(loc("No search to operate on.")) unless ($Tickets);
-
-my %allcfs;
-my %cfqnames;
-my %cfqs;
-my $count = 0;
-while (my $Ticket = $Tickets->Next) {
-    my $cfq = $Ticket->QueueObj;
-    my $cfqid = $cfq->Id;
-    my $cfqn = $cfq->Name;
-    unless ( exists $cfqs{$cfqid} ) {
-       $cfqs{$cfqid} = 1;
-       $count++;
-       my $cfs = $cfq->TicketCustomFields;
-       while (my $cf = $cfs->Next) {
-           $allcfs{$cf->Id} = $cf;
-           $cfqnames{$cf->Id} = $cfqn;
-       }
+map ( $ARGS{$_} =~ /^$/ && ( delete $ARGS{$_} ), keys %ARGS );
+
+my (@results);
+
+$Page ||= 1;
+
+$Format ||= $RT::DefaultSearchResultFormat;
+
+# inject _CHECKBOX to the first field.
+$Format =~ s/'?([^']+)'?,/'___CHECKBOX__$1',/;
+
+my $Tickets = RT::Tickets->new( $session{'CurrentUser'} );
+$Tickets->FromSQL($Query);
+if ( $OrderBy =~ /\|/ ) {
+
+  # Multiple Sorts
+  my @OrderBy = split /\|/, $OrderBy;
+  my @Order   = split /\|/, $Order;
+  $Tickets->OrderByCols(
+    map { { FIELD => $OrderBy[$_], ORDER => $Order[$_] } }
+      ( 0 .. $#OrderBy ) );
+}
+else {
+  $Tickets->OrderBy( FIELD => $OrderBy, ORDER => $Order );
+}
+
+$Tickets->RowsPerPage($Rows) if ($Rows);
+$Tickets->GotoPage( $Page - 1 );    # SB uses page 0 as the first page
+
+Abort( loc("No search to operate on.") ) unless ($Tickets);
+
+# build up a list of all custom fields for tickets that we're displaying, so
+# we can display sane edit widgets.
+
+my $fields      = {};
+my $seen_queues = {};
+while ( my $ticket = $Tickets->Next ) {
+    next if $seen_queues->{ $ticket->Queue }++;
+
+    my $custom_fields = $ticket->QueueObj->TicketCustomFields;
+    while ( my $field = $custom_fields->Next ) {
+        $fields->{ $field->id } = $field;
     }
 }
 
-my $do_comment_reply=0;
+my $do_comment_reply = 0;
+
 # Prepare for ticket updates
-$ARGS{'UpdateContent'} =~ s/\r\n/\n/g;
-chomp ($ARGS{'UpdateContent'}) ;
-
-if ($ARGS{'UpdateContent'} &&
-    $ARGS{'UpdateContent'} ne '' &&
-    $ARGS{'UpdateContent'} ne  "-- \n" .
-    $session{'CurrentUser'}->UserObj->Signature) {
-            $do_comment_reply=1;
+if ($ARGS{'UpdateContent'}) {
+    $ARGS{'UpdateContent'} =~ s/\r\n/\n/g;
+    chomp( $ARGS{'UpdateContent'} );
+
+    if ($ARGS{'UpdateContent'} ne ''
+        && $ARGS{'UpdateContent'} ne "-- \n"
+        . $session{'CurrentUser'}->UserObj->Signature ) {
+        $do_comment_reply = 1;
+    }
 }
 
 #Iterate through each ticket we've been handed
@@ -229,50 +266,131 @@ my @linkresults;
 my %queues;
 
 $Tickets->RedoSearch();
-while (my $Ticket = $Tickets->Next) {
-    $queues{$Ticket->QueueObj->Id}++;
-    $RT::Logger->debug( "Checking Ticket ".$Ticket->Id ."\n");
-    next unless ($ARGS{"UpdateTicket".$Ticket->Id});
-    $RT::Logger->debug ("Matched\n");
-    my @updateresults; 
+
+# pull out the labels for any custom fields we want to update
+
+my $cf_del_keys;
+@$cf_del_keys = grep { /^Bulk-Delete-CustomField/ } keys %ARGS;
+my $cf_add_keys;
+@$cf_add_keys = grep { /^Bulk-Add-CustomField/ } keys %ARGS;
+
+
+while ( my $Ticket = $Tickets->Next ) {
+    next unless ( $ARGS{ "UpdateTicket" . $Ticket->Id } );
+
+    #Update the links
+    $ARGS{'id'} = $Ticket->id;
+    $queues{ $Ticket->QueueObj->Id }++;
+
+    my @updateresults;
     if ($do_comment_reply) {
-       ProcessUpdateMessage(TicketObj => $Ticket, ARGSRef => \%ARGS, Actions => \@updateresults); 
+        ProcessUpdateMessage(
+            TicketObj => $Ticket,
+            ARGSRef   => \%ARGS,
+            Actions   => \@updateresults
+        );
     }
 
     #Update the basics.
-    my @basicresults = ProcessTicketBasics(TicketObj => $Ticket, ARGSRef => \%ARGS);
-    my @dateresults = ProcessTicketDates(TicketObj => $Ticket, ARGSRef => \%ARGS);
+    my @basicresults =
+      ProcessTicketBasics( TicketObj => $Ticket, ARGSRef => \%ARGS );
+    my @dateresults =
+      ProcessTicketDates( TicketObj => $Ticket, ARGSRef => \%ARGS );
+
     #Update the watchers
-    my @watchresults = ProcessTicketWatchers(TicketObj => $Ticket, ARGSRef => \%ARGS);    
+    my @watchresults =
+      ProcessTicketWatchers( TicketObj => $Ticket, ARGSRef => \%ARGS );
 
+    foreach my $type qw(MergeInto DependsOn MemberOf RefersTo) {
+        $ARGS{ $Ticket->id . "-" . $type } = $ARGS{"Ticket-$type"};
+        $ARGS{ $type . "-" . $Ticket->id } = $ARGS{"$type-Ticket"};
+    }
+    @linkresults =
+      ProcessTicketLinks( TicketObj => $Ticket, ARGSRef => \%ARGS );
+    foreach my $type qw(MergeInto DependsOn MemberOf RefersTo) {
+        delete $ARGS{ $type . "-" . $Ticket->id };
+        delete $ARGS{ $Ticket->id . "-" . $type };
+    }
 
-    #Update the links
-    $ARGS{'id'} = $Ticket;
-    $ARGS{$Ticket->Id.'-MergeInto'} = $ARGS{'Ticket-MergeInto'};
-    $ARGS{$Ticket->Id.'-DependsOn'} = $ARGS{'Ticket-DependsOn'};
-    $ARGS{'DependsOn-'.$Ticket->Id} = $ARGS{'DependsOn-Ticket'};
-    $ARGS{$Ticket->Id.'-MemberOf'} = $ARGS{'Ticket-MemberOf'};
-    $ARGS{'MemberOf-'.$Ticket->Id} = $ARGS{'MemberOf-Ticket'};
-    $ARGS{$Ticket->Id.'-RefersTo'} = $ARGS{'Ticket-RefersTo'};
-    $ARGS{'RefersTo-'.$Ticket->Id} = $ARGS{'RefersTo-Ticket'};
-    @linkresults = ProcessTicketLinks( TicketObj => $Ticket, ARGSRef => \%ARGS);
-    delete $ARGS{'id'};
-    delete $ARGS{$Ticket->Id.'-MergeInto'};
-    delete $ARGS{$Ticket->Id.'-DependsOn'};
-    delete $ARGS{'DependsOn-'.$Ticket->Id};
-    delete $ARGS{$Ticket->Id.'-MemberOf'};
-    delete $ARGS{'MemberOf-'.$Ticket->Id};
-    delete $ARGS{$Ticket->Id.'-RefersTo'};
-    delete $ARGS{'RefersTo-'.$Ticket->Id};
-    my @tempresults = (@watchresults, @basicresults, @dateresults,
-    @updateresults, @linkresults);
-    @tempresults = map { loc("Ticket [_1]: [_2]",$Ticket->Id,$_) } @tempresults;
-
-    @results = (@results, @tempresults);
+    my @cfresults;
+
+    foreach my $list ( $cf_add_keys, $cf_del_keys ) {
+        next unless $list->[0];
+
+
+        my $op;
+        if ( $list->[0] =~ /Add/ ) {
+            $op = 'add';
+
+        }
+        elsif ( $list->[0] =~ /Del/ ) {
+            $op = 'del';
+        }
+        else {
+            $RT::Logger->crit(
+                "Got an op that was neither add nor delete. can never happen"
+                  . $list->[0] );
+            last;
+        }
+
+        foreach my $key (@$list) {
+            my ( $cfid, $cf );
+            if ( $key =~ /CustomField-(\d+)-/ ) {
+                $cfid = $1;
+                $cf   = RT::CustomField->new( $session{'CurrentUser'} );
+                $cf->Load($cfid);
+            }
+            else {next}
+            my @values =
+              ref( $ARGS{$key} ) eq 'ARRAY'
+              ? @{ $ARGS{$key} }
+              : ( $ARGS{$key} );
+            map { s/(\r\n|\r)/\n/g; } @values;    # fix the newlines
+                 # now break the multiline values into multivalues
+            @values = map { split( /\n/, $_ ) } @values
+              unless ( $cf->SingleValue );
+
+            my $current_values = $Ticket->CustomFieldValues($cfid);
+            foreach my $value (@values) {
+                if ( $op eq 'del' && $current_values->HasEntry($value) ) {
+                    my ( $id, $msg ) = $Ticket->DeleteCustomFieldValue(
+                        Field => $cfid,
+                        Value => $value
+                    );
+                    push @cfresults, $msg;
+                }
+
+                elsif ( $op eq 'add' && !$current_values->HasEntry($value) ) {
+                    my ( $id, $msg ) = $Ticket->AddCustomFieldValue(
+                        Field => $cfid,
+                        Value => $value
+                    );
+                    push @cfresults, $msg;
+                }
+            }
+        }
+    }
+    my @tempresults = (
+        @watchresults,  @basicresults, @dateresults,
+        @updateresults, @linkresults,  @cfresults
+    );
+
+    @tempresults =
+      map { loc( "Ticket [_1]: [_2]", $Ticket->Id, $_ ) } @tempresults;
+
+    @results = ( @results, @tempresults );
 }
 
-my $TxnCFs = RT::CustomFields->new($session{CurrentUser});
-$TxnCFs->LimitToLookupType("RT::Queue-RT::Ticket-RT::Transaction");
-$TxnCFs->LimitToGlobalOrObjectId(sort keys %queues);
+my $TxnCFs = RT::CustomFields->new( $session{CurrentUser} );
+$TxnCFs->LimitToLookupType( RT::Transaction->CustomFieldLookupType );
+$TxnCFs->LimitToGlobalOrObjectId( sort keys %queues );
 
 </%INIT>
+<%args>
+$Format => undef
+$Page => 1
+$Rows => undef
+$Order => 'ASC'
+$OrderBy => 'id'
+$Query => undef
+</%args>