How to display value of user custom fields on a ticket update or display page

Hi All,

We are looking to develop a feature whereby we can display for support staff, a list of products that a customer has, what type of support plan they are on, etc. So that when the staff pull up a ticket it can influence what kind of support to give them.

What I need to figure out is: How can I take custom field values that I store in an RT user, and display those when rendering either the ticket display or update pages.

Or more specifically right now, I am struggling to figure out how to access the TicketObj or TransactionObj from the Ticket/Update.html/BeforeMessageBox callback.

We already have a mechanism whereby each customer is a user in RT, and we can store customer-wide data in there. And we already have a mechanism whereby there is a “Customer” custom field on ticket transactions that link the ticket to the relevant customer user. I am just not sure how to go about using that relationship to display info on the pages.

I think that using a Callback is my preferred approach, but I’ve tried using them and I’m not sure how to get started to access a user object via a callback.

Another approach idea I had was to simply add a read-only custom field to the ticket, and use a scrip to find the related customer, pull the info, and populate it in the field on ticket creation/update. And just rely on these read-only fields. But that seems overly clunky, and I’d really like to leverage callbacks so I can do custom formatting of the fields, add colour, etc.

Thanks!
Rhys.

OK I have a proof of concept mostly happening based on docs and examples I’ve found, but I have two major issues:

  • When there is a bug in the code the page goes blank, and I get no errors in the web server logs like I would with scrips. My RT logging and web server logs are set to debug verbosity. Where can I find these errors to debug properly?

  • Trying to use $RT::Logger seems to be breaking the callback code entirely. How can I add logging to my callback without breaking things?

Here’s what I have so far. I wasn’t able to figure out how to access the ticket object, only the ticket ID. So I loaded the ticket object again, and went from there.

%# We are displaying a message box if the timeWorked for a customer is near or at their limit
%# See example: https://wiki.gentoo.org/wiki/Request_Tracker/Password_Reset
%# See example: https://rt-wiki.bestpractical.com/wiki/ShowPerQueueInstructions
%# See example: https://rt-wiki.bestpractical.com/wiki/ToggleCFs

    <div class="error" style="text-align: left;">
        <div class="titlebox error">
            <div class="titlebox-title">
                <span class="left">Billable Time Alert</span>
                <span class="right-empty"> </span>
            </div>
            <div class="titlebox-content">
                <% $msg %>
                <hr class="clear" />
            </div>
        </div>
    </div>

<%INIT>
# This is the name of the Ticket Customer custom field
my $cf_customer_name = "Customer";
# This is the name of the User Billable custom field
my $cf_customer_billable = "Billable";

my $msg = "";
my $ticket = LoadTicket($ARGS{'id'});
# Pull the customer name from the ticket
my $customer_name = $ticket->FirstCustomFieldValue($cf_customer_name);

if ($customer_name eq undef)
{
        $customer_name = "";
}

# Based on that, find the relevant customer user
my $users = RT::Users->new($RT::SystemUser);
$users->LimitToPrivileged();


# Try and find matching RT User object
my $customer_user = undef;
while (my $user = $users->Next)
{
    if ($user->RealName() eq $customer_name)
    {
        $customer_user = $user;
        last;
    }
}

# No user found
if ($customer_user eq undef)
{
    #$RT::Logger->info($scrip . "Unable to find RT user for " . $customer_name);
    return;
}

# Then pull the billable CF from the user.
my $billable = "";
my $cf_billable_value = $customer_user->FirstCustomFieldValue($cf_customer_billable);
if ($cf_billable_value ne 'Yes')
{
    $billable = "No";
}
else
{
    $billable = "Yes";
}
$msg = "This customer (".$customer_name.") has reached their maximum billable time for the month. Billable: ".$billable;

</%INIT>
<%args>
$CustomFields => undef
$ARGS => undef
$Object => undef
</%args>


You don’t need the dollar in front of the RT::Logger->info call. Try removing that and then see what output you get.

Yes! Thank you, my callback no longer breaks with the logging statements. But I still don’t get any logs. I realised I am not seeing my scrips in the logs either.

I think that the logs are no longer working how I remember - so that’s for me to figure out. BUT - in your experience, should the call back logging be found in the same location as the scrip logs are?

We are using nginx with perl-fcgi and I just realised I don’t remember where it logs RT stuff to. I’m just hoping if I can find the scrip log entries, that the callback logs will be there.

Ah fantastic, just found the log entries - can confirm that scrip and callback logging is in the same spot. In my case, syslog.

root@rt4:/opt/rt4# grep -r "BillableTimeAlert#" /var/log/*
/var/log/syslog:Apr 14 19:13:27 rt4 RT: [19970] BillableTimeAlert#54214: Unable to find RT user for XX

One more question: How can I pass info around between multiple callbacks? I know some callbacks pass this in via arguments, but what about the ones that don’t, like “BeforeMessageBox”?

For example, in my current code that I’ve pasted here, I could only figure out how to access the ticket ID and so reloaded the entire ticket object. Surely there must be a way to execute logic via a callback and store a variable “globally” on the page so other callbacks can then access it? Or is this the only way to do it?

If I have multiple callbacks on a page it doesn’t make sense to have to re-load the same objects multiple times.

Thanks all!