MuteResolve Redux

From Request Tracker Wiki
Jump to navigation Jump to search

I like the idea of MuteResolve, but it doesn't work quite right as it is tied to the final transaction, which isn't guaranteed to be present. We already had another method we used for this based on an alternate resolved status 'resolvedq', but it always bugged me that we'd have both that and 'resolved' in the system, which causes subtle problems elsewhere (e.g., the 'Resolve' link displays for tickets marked as 'resolvedq').

To fix this, I took the essence of the MuteResolve idea and merged it into our resolvedq InactiveStatuscode. The complete solution follows.

Status Code

Create a new status code in

Set(@InactiveStatus,qw(resolved resolvedq rejected deleted));

This change may require a restart of RT, and may require sessions to logout and login to see the new status option.

Custom Field

Create the CustomField MuteResolve just like in that article, but make it a Ticket CF, not a TicketTransaction CF. We also do not set the SeeCustomField right on this field so it is hidden. If you allow SeeCustomField globally, there is no way to hide it, though. Since this is really an internal ticket flag, there's no benefit to seeing it and potentially some harm or confusion, so if you can hide it, do that. Note that the Validation field here is really not needed, but left in place as an extra layer of protection.

Name: MuteResolve
Description: If Yes, don't send email on resolve
Applies To: Tickets
Validation: (?#YesNo)^(Yes|No|\z)$

For Values, just add one 'Yes' with no special sort order.

NOTE: Using the "resolveq" status, it's also possible to achieve this without any custom field. See script below.


As with the MuteResolve scrip, we will be changing the normal OnResolve Notify Requestors, but in this case we will be using the MuteResolve CF as a flag combined with the resolvedq status code. When someone uses resolvedq as the status, this scrip will see that, set the MuteResolve flag and then change the status back to resolved. The code is a bit longer than needed mainly due to debug statements. The overall Scrip should be changed so the Condition field is 'User Defined', and the 'Custom Condition' field should be set to the code below.

my $scrip = 'Scrip:MuteResolve';

# is this a resolve-type transaction?
my $trans = $self->TransactionObj;
return 0 unless $trans->Type eq "Status";
return 0 unless $trans->NewValue =~ /^resolvedq?$/;

my $ticket = $self->TicketObj;

if ($trans->NewValue eq "resolvedq") {
    # mark ticket as muted and set back to resolved
    $RT::Logger->debug("$scrip: handling resolvedq status");
    $ticket->AddCustomFieldValue(Field => 'MuteResolve', Value => 'Yes');
} elsif ($trans->NewValue eq "resolved") {
    # skip if notification if muted
    $RT::Logger->debug("$scrip: checking for muted resolve");
    return 0 if $ticket->FirstCustomFieldValue('MuteResolve') eq 'Yes';
    # normal resolve
    $RT::Logger->debug("$scrip: unmuted resolve");
    return 1;
  1. this should never be reached, but just in case....
return 0;

NOTE: While the scrip above may work with a custom field, it's also possible to do away with the custom field altogether. Simply check if status is resolvedq, change it to resolved, and if it was resolvedq and is now resolved, don't send a notification email. Like so:

my $scrip = 'Scrip:QuietResolve';
my $txn = $self->TransactionObj;
my $type = $txn->Type;

return 0 unless $type eq "Status" || ( $type eq 'Set' && $txn->Field eq 'Status');
return 0 unless $txn->NewValue =~ /^resolvedq?$/;

my $ticket = $self->TicketObj;
if ($txn->NewValue eq "resolvedq") {
    $RT::Logger->debug("$scrip: flagging quiet resolve");
} elsif ($txn->NewValue eq "resolved") {
    $RT::Logger->debug("$scrip: checking for quiet resolve");
    if ($txn->OldValue eq 'resolvedq') {
        $RT::Logger->debug("$scrip: resolvedq to resolved means quiet resolve, do not notify");
        return 0;
    $RT::Logger->debug("$scrip: not a quiet resolve, notify");
    return 1;
# this should never be reached, but just in case....
return 0;


Your RT will now allow use of resolvedq to indicate a quiet resolution, but retain only the resolved status on those tickets.

Note: because the MuteResolve flag is set the first time resolvedq is seen, if that ticket is ever reopened and resolved, it will never send a resolution message again. We use ForkIntoNewTicket to avoid re-opening resolved tickets, which works out very well.