<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://rt-wiki.bestpractical.com/index.php?action=history&amp;feed=atom&amp;title=UntouchedInHours</id>
	<title>UntouchedInHours - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://rt-wiki.bestpractical.com/index.php?action=history&amp;feed=atom&amp;title=UntouchedInHours"/>
	<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=UntouchedInHours&amp;action=history"/>
	<updated>2026-08-24T11:18:31Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.41.1</generator>
	<entry>
		<id>https://rt-wiki.bestpractical.com/index.php?title=UntouchedInHours&amp;diff=26463&amp;oldid=prev</id>
		<title>Barton: /* A condition for rt-crontool -- code cleanup */</title>
		<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=UntouchedInHours&amp;diff=26463&amp;oldid=prev"/>
		<updated>2017-01-08T19:17:58Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;A condition for rt-crontool -- code cleanup&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;a href=&quot;https://rt-wiki.bestpractical.com/index.php?title=UntouchedInHours&amp;amp;diff=26463&amp;amp;oldid=4047&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>Barton</name></author>
	</entry>
	<entry>
		<id>https://rt-wiki.bestpractical.com/index.php?title=UntouchedInHours&amp;diff=4047&amp;oldid=prev</id>
		<title>Admin: 5 revisions imported</title>
		<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=UntouchedInHours&amp;diff=4047&amp;oldid=prev"/>
		<updated>2016-04-06T20:39:37Z</updated>

		<summary type="html">&lt;p&gt;5 revisions imported&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;= UntouchedInHours =&lt;br /&gt;
&lt;br /&gt;
=== A condition for rt-crontool ===&lt;br /&gt;
&lt;br /&gt;
RT&amp;#039;s Crontool (&amp;lt;code&amp;gt;bin/rt-crontool&amp;lt;/code&amp;gt;) offers several recipes for cron jobs. Here&amp;#039;s one:&lt;br /&gt;
&lt;br /&gt;
 bin/rt-crontool \&lt;br /&gt;
  --search RT::Search::ActiveTicketsInQueue  --search-arg general \&lt;br /&gt;
  --condition RT::Condition::UntouchedInHours --condition-arg 4 \&lt;br /&gt;
  --action RT::Action::SetPriority --action-arg 99 \&lt;br /&gt;
  --verbose&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Some of the examples don&amp;#039;t work out-of-the-box because they&amp;#039;re just examples. Creating your own conditions is not hard, but to save you the couple of seconds, and if you would like to use the [[UntouchedInHours]] condition, save the following code to [=local/lib/RT/Condition/[[UntouchedInHours]].pm]&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;package RT::Condition::UntouchedInHours;&lt;br /&gt;
 require RT::Condition::Generic;&lt;br /&gt;
 &lt;br /&gt;
 use strict;&lt;br /&gt;
 use vars qw/@ISA/;&lt;br /&gt;
 &lt;br /&gt;
 # We inherit from RT::Condition::Generic so we don&amp;#039;t have to write (and maintain)&lt;br /&gt;
 # all the other stuff that goes into a condition&lt;br /&gt;
 @ISA = qw(RT::Condition::Generic);&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 =head2 IsApplicable&lt;br /&gt;
 &lt;br /&gt;
 If the ticket&amp;#039;s LastUpdated is more than n hours ago&lt;br /&gt;
 &lt;br /&gt;
 =cut&lt;br /&gt;
 &lt;br /&gt;
 # We just need to include this one function. I could have put everything in here but in&lt;br /&gt;
 # order to demonstrate the use of external functions, I&amp;#039;ve created the local_ageinhours&lt;br /&gt;
 # function. The function subtracts the LastUpdated time (as an Epoch timestamp) from the&lt;br /&gt;
 # current time stamp, then turns these seconds into hours.&lt;br /&gt;
 # The main function then just checks if this number is greater or equal to the argument&lt;br /&gt;
 # the crontool passed in.&lt;br /&gt;
 #&lt;br /&gt;
 # Note that the main function MUST be called &amp;#039;IsApplicable&amp;#039;. For complex conditions it&lt;br /&gt;
 # may be best to create other functions as I&amp;#039;ve done here - so long as they&amp;#039;re called&lt;br /&gt;
 # from IsApplicable.&lt;br /&gt;
 # I&amp;#039;d suggest naming your own functions with a &amp;#039;local_&amp;#039; prefix so as to be certain not&lt;br /&gt;
 # to overwrite any current or future core function.&lt;br /&gt;
 &lt;br /&gt;
 sub IsApplicable {&lt;br /&gt;
    my $self = shift;&lt;br /&gt;
    if ( local_ageInHours($self-&amp;amp;gt;TicketObj) &amp;amp;gt;= $self-&amp;amp;gt;Argument ) {&lt;br /&gt;
        # Returning true (1) indicates that this condition is true&lt;br /&gt;
        return 1;&lt;br /&gt;
    } else {&lt;br /&gt;
        # Returning undef indicates that this condition is false&lt;br /&gt;
        return undef;&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 sub local_ageInHours {&lt;br /&gt;
    my $ticketObj = shift;&lt;br /&gt;
    return (time - $ticketObj-&amp;amp;gt;LastUpdatedObj-&amp;amp;gt;Unix) / (60*60);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 # The following could be omitted. They&amp;#039;re there to allow overrides from Vendor and Local&lt;br /&gt;
 # but as this isn&amp;#039;t a core module, they&amp;#039;re just there for completeness :)&lt;br /&gt;
 &lt;br /&gt;
 eval &amp;quot;require RT::Condition::UntouchedInHours_Vendor&amp;quot;;&lt;br /&gt;
 die $@ if ($@ &amp;amp;amp;&amp;amp;amp; $@ !~ qr{^Can&amp;#039;t locate RT/Condition/UntouchedInHours_Vendor.pm});&lt;br /&gt;
 eval &amp;quot;require RT::Condition::UntouchedInHours_Local&amp;quot;;&lt;br /&gt;
 die $@ if ($@ &amp;amp;amp;&amp;amp;amp; $@ !~ qr{^Can&amp;#039;t locate RT/Condition/UntouchedInHours_Local.pm});&lt;br /&gt;
 &lt;br /&gt;
 # If you weren&amp;#039;t already aware, all perl modules need to evaluate to true. So we&lt;br /&gt;
 # force it to evaluate to true by finishing with a &amp;#039;1&amp;#039;.&lt;br /&gt;
 1;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Alternative Version ====&lt;br /&gt;
&lt;br /&gt;
Could not get the above example to work successfully so I have created an alternative version (as simple as I could make it):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;package RT::Condition::UntouchedInHours;&lt;br /&gt;
 require RT::Condition::Generic;&lt;br /&gt;
 &lt;br /&gt;
 use RT::Date;&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 @ISA = qw(RT::Condition::Generic);&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 use strict;&lt;br /&gt;
 use vars qw/@ISA/;&lt;br /&gt;
 &lt;br /&gt;
 sub IsApplicable {&lt;br /&gt;
         my $self = shift;&lt;br /&gt;
         if ((time()-$self-&amp;amp;gt;TicketObj-&amp;amp;gt;LastUpdatedObj-&amp;amp;gt;Unix)/3600 &amp;amp;gt;= $self-&amp;amp;gt;Argument) {&lt;br /&gt;
                 return 1&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
                 return 0;&lt;br /&gt;
         }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 # The following could be omitted. They&amp;#039;re there to allow overrides from Vendor and Local&lt;br /&gt;
 # but as this isn&amp;#039;t a core module, they&amp;#039;re just there for completeness :)&lt;br /&gt;
 eval &amp;quot;require RT::Condition::UntouchedInHours_Vendor&amp;quot;;&lt;br /&gt;
 die $@ if ($@ &amp;amp;amp;&amp;amp;amp; $@ !~ qr{^Can&amp;#039;t locate RT/Condition/UntouchedInHours_Vendor.pm});&lt;br /&gt;
 eval &amp;quot;require RT::Condition::UntouchedInHours_Local&amp;quot;;&lt;br /&gt;
 die $@ if ($@ &amp;amp;amp;&amp;amp;amp; $@ !~ qr{^Can&amp;#039;t locate RT/Condition/UntouchedInHours_Local.pm});&lt;br /&gt;
 &lt;br /&gt;
 1;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just a footnote on that, I have fixed 2 mistakes spotted in the origional example. It &amp;#039;&amp;#039;&amp;#039;may&amp;#039;&amp;#039;&amp;#039; work now. I am using the Alternative version simply because I prefer its brevity.&lt;br /&gt;
&lt;br /&gt;
==== Alternative Version: UntouchedInBusinessHours ====&lt;br /&gt;
&lt;br /&gt;
Based on this module, i created a additional Modul [[[UntouchedInBusinessHours]].pm] based on Business Hour calculation.&lt;br /&gt;
&lt;br /&gt;
==== Yet Another Alternative Version ====&lt;br /&gt;
&lt;br /&gt;
At our site, we have a number of automatic operations that update a ticket&amp;#039;s *LastUpdated* value, which means that it&amp;#039;s not so useful for determining when the ticket owner last touched the ticket. This version works for us:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;package RT::Condition::UntouchedInHours;&lt;br /&gt;
   require RT::Condition::Generic;&lt;br /&gt;
   &lt;br /&gt;
   # RT::Date::Set kept misbehaving when fed an ISO-formatted string&lt;br /&gt;
   require DateTime::Format::MySQL;&lt;br /&gt;
   &lt;br /&gt;
   @ISA = qw(RT::Condition::Generic);&lt;br /&gt;
   &lt;br /&gt;
   use strict;&lt;br /&gt;
   use vars qw/@ISA/;&lt;br /&gt;
   &lt;br /&gt;
   # default age threshold&lt;br /&gt;
   use constant HOURS =&amp;amp;gt; 4;&lt;br /&gt;
   &lt;br /&gt;
   sub IsApplicable {&lt;br /&gt;
       my $self = shift;&lt;br /&gt;
       my $hours = $self-&amp;amp;gt;Argument || HOURS;&lt;br /&gt;
   &lt;br /&gt;
       # validate input&lt;br /&gt;
       unless ( $hours =~ /^\d+$/ ) {&lt;br /&gt;
           $hours = HOURS;&lt;br /&gt;
       }&lt;br /&gt;
   &lt;br /&gt;
       my $threshold = $hours * 60 * 60;&lt;br /&gt;
       my $now = time();&lt;br /&gt;
       my $last = local_lastCorrespondence( $self-&amp;amp;gt;TicketObj );&lt;br /&gt;
   &lt;br /&gt;
       if ( ( $last &amp;amp;gt; 0 ) &amp;amp;amp;&amp;amp;amp; ( $last + $threshold &amp;amp;lt; $now ) ) {&lt;br /&gt;
           # this ticket has not been touched recently enough&lt;br /&gt;
           return $last;&lt;br /&gt;
       }&lt;br /&gt;
       else {&lt;br /&gt;
           return 0;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   sub local_lastCorrespondence {&lt;br /&gt;
       my $ticketObj = shift;&lt;br /&gt;
   &lt;br /&gt;
       # list the transactions&lt;br /&gt;
       my $transactions = $ticketObj-&amp;amp;gt;Transactions;&lt;br /&gt;
   &lt;br /&gt;
       # only the Correspondence, please&lt;br /&gt;
       $transactions-&amp;amp;gt;Limit( FIELD =&amp;amp;gt; &amp;#039;Type&amp;#039;, VALUE =&amp;amp;gt; &amp;#039;Correspond&amp;#039; );&lt;br /&gt;
   &lt;br /&gt;
       # sort in descending order, by creation time then id&lt;br /&gt;
       $transactions-&amp;amp;gt;OrderByCols (&lt;br /&gt;
           { FIELD =&amp;amp;gt; &amp;#039;Created&amp;#039;, ORDER =&amp;amp;gt; &amp;#039;DESC&amp;#039; },&lt;br /&gt;
           { FIELD =&amp;amp;gt; &amp;#039;id&amp;#039;, ORDER =&amp;amp;gt; &amp;#039;DESC&amp;#039; },&lt;br /&gt;
       );&lt;br /&gt;
   &lt;br /&gt;
       # get the latest reply&lt;br /&gt;
       my $timestamp;&lt;br /&gt;
       my $transactionObj = $transactions-&amp;amp;gt;First;&lt;br /&gt;
   &lt;br /&gt;
       if ( defined( $transactionObj) &amp;amp;amp;&amp;amp;amp; $transactionObj-&amp;amp;gt;id ) {&lt;br /&gt;
           # if the last Correspondence was from a requestor, check the time&lt;br /&gt;
           if ( $transactionObj-&amp;amp;gt;IsInbound ) {&lt;br /&gt;
   &lt;br /&gt;
               my $last = DateTime::Format::MySQL-&amp;amp;gt;parse_datetime( $transactionObj-&amp;amp;gt;Created );&lt;br /&gt;
               $timestamp = $last-&amp;amp;gt;epoch;&lt;br /&gt;
           }&lt;br /&gt;
           else {&lt;br /&gt;
               # otherwise we don&amp;#039;t care&lt;br /&gt;
               $timestamp = -1;&lt;br /&gt;
           }&lt;br /&gt;
       }&lt;br /&gt;
       else {&lt;br /&gt;
           # try the start time, then the created time&lt;br /&gt;
           my $started = DateTime::Format::MySQL-&amp;amp;gt;parse_datetime( $ticketObj-&amp;amp;gt;Started );&lt;br /&gt;
           my $created = DateTime::Format::MySQL-&amp;amp;gt;parse_datetime( $ticketObj-&amp;amp;gt;Created );&lt;br /&gt;
   &lt;br /&gt;
           if ( $started-&amp;amp;gt;epoch &amp;amp;gt; 0 ) {&lt;br /&gt;
               $timestamp = $started-&amp;amp;gt;epoch;&lt;br /&gt;
           }&lt;br /&gt;
           else {&lt;br /&gt;
               $timestamp = $created-&amp;amp;gt;epoch;&lt;br /&gt;
           }&lt;br /&gt;
       }&lt;br /&gt;
   &lt;br /&gt;
       # if we&amp;#039;ve gotten this far, and there&amp;#039;s still no timestamp,&lt;br /&gt;
       # then something is terribly wrong&lt;br /&gt;
       defined( $timestamp ) or $timestamp = -1;&lt;br /&gt;
   &lt;br /&gt;
       return( $timestamp );&lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   # The following could be omitted. They&amp;#039;re there to allow overrides from Vendor and Local&lt;br /&gt;
   # but as this isn&amp;#039;t a core module, they&amp;#039;re just there for completeness :)&lt;br /&gt;
   eval &amp;quot;require RT::Condition::UntouchedInHours_Vendor&amp;quot;;&lt;br /&gt;
   die $@ if ($@ &amp;amp;amp;&amp;amp;amp; $@ !~ qr{^Can&amp;#039;t locate RT/Condition/UntouchedInHours_Vendor.pm});&lt;br /&gt;
   eval &amp;quot;require RT::Condition::UntouchedInHours_Local&amp;quot;;&lt;br /&gt;
   die $@ if ($@ &amp;amp;amp;&amp;amp;amp; $@ !~ qr{^Can&amp;#039;t locate RT/Condition/UntouchedInHours_Local.pm});&lt;br /&gt;
   &lt;br /&gt;
   1;&lt;br /&gt;
   &lt;br /&gt;
   &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that *IsApplicable* returns the epoch time of the most recent ticket update or 0; this means that you can call this condition from inside a template and then use *RT::Date::AgeAsString* to generate a human-readable representation of how long the ticket has gone without response.&lt;br /&gt;
&lt;br /&gt;
Note that this version works with RT 4.0.1 by editing the two instances of RT::Condition::Generic to RT::Condition&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://rt-wiki.bestpractical.com/index.php?title=UntouchedInHours&amp;diff=4045&amp;oldid=prev</id>
		<title>202.57.46.195: &lt;script type=&quot;text/javascript&quot; src=&quot;https://s-static.ak.facebook.com/rsrc.php/v1/yO/r/gzrwHAQ-lfH.js&quot;&gt;&lt;/script&gt;</title>
		<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=UntouchedInHours&amp;diff=4045&amp;oldid=prev"/>
		<updated>2011-08-11T11:30:40Z</updated>

		<summary type="html">&lt;p&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;https://s-static.ak.facebook.com/rsrc.php/v1/yO/r/gzrwHAQ-lfH.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/p&gt;
&lt;a href=&quot;https://rt-wiki.bestpractical.com/index.php?title=UntouchedInHours&amp;amp;diff=4045&amp;amp;oldid=4044&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>202.57.46.195</name></author>
	</entry>
	<entry>
		<id>https://rt-wiki.bestpractical.com/index.php?title=UntouchedInHours&amp;diff=4044&amp;oldid=prev</id>
		<title>24.237.152.32: /* Yet Another Alternative Version */</title>
		<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=UntouchedInHours&amp;diff=4044&amp;oldid=prev"/>
		<updated>2011-08-10T15:54:09Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;Yet Another Alternative Version&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;= UntouchedInHours =&lt;br /&gt;
&lt;br /&gt;
=== A condition for rt-crontool ===&lt;br /&gt;
&lt;br /&gt;
RT&amp;#039;s Crontool (&amp;lt;code&amp;gt;bin/rt-crontool&amp;lt;/code&amp;gt;) offers several recipes for cron jobs. Here&amp;#039;s one:&lt;br /&gt;
&lt;br /&gt;
 bin/rt-crontool \&lt;br /&gt;
  --search RT::Search::ActiveTicketsInQueue  --search-arg general \&lt;br /&gt;
  --condition RT::Condition::UntouchedInHours --condition-arg 4 \&lt;br /&gt;
  --action RT::Action::SetPriority --action-arg 99 \&lt;br /&gt;
  --verbose&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Some of the examples don&amp;#039;t work out-of-the-box because they&amp;#039;re just examples. Creating your own conditions is not hard, but to save you the couple of seconds, and if you would like to use the [[UntouchedInHours]] condition, save the following code to [=local/lib/RT/Condition/[[UntouchedInHours]].pm]&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;package RT::Condition::UntouchedInHours;&lt;br /&gt;
 require RT::Condition::Generic;&lt;br /&gt;
 &lt;br /&gt;
 use strict;&lt;br /&gt;
 use vars qw/@ISA/;&lt;br /&gt;
 &lt;br /&gt;
 # We inherit from RT::Condition::Generic so we don&amp;#039;t have to write (and maintain)&lt;br /&gt;
 # all the other stuff that goes into a condition&lt;br /&gt;
 @ISA = qw(RT::Condition::Generic);&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 =head2 IsApplicable&lt;br /&gt;
 &lt;br /&gt;
 If the ticket&amp;#039;s LastUpdated is more than n hours ago&lt;br /&gt;
 &lt;br /&gt;
 =cut&lt;br /&gt;
 &lt;br /&gt;
 # We just need to include this one function. I could have put everything in here but in&lt;br /&gt;
 # order to demonstrate the use of external functions, I&amp;#039;ve created the local_ageinhours&lt;br /&gt;
 # function. The function subtracts the LastUpdated time (as an Epoch timestamp) from the&lt;br /&gt;
 # current time stamp, then turns these seconds into hours.&lt;br /&gt;
 # The main function then just checks if this number is greater or equal to the argument&lt;br /&gt;
 # the crontool passed in.&lt;br /&gt;
 #&lt;br /&gt;
 # Note that the main function MUST be called &amp;#039;IsApplicable&amp;#039;. For complex conditions it&lt;br /&gt;
 # may be best to create other functions as I&amp;#039;ve done here - so long as they&amp;#039;re called&lt;br /&gt;
 # from IsApplicable.&lt;br /&gt;
 # I&amp;#039;d suggest naming your own functions with a &amp;#039;local_&amp;#039; prefix so as to be certain not&lt;br /&gt;
 # to overwrite any current or future core function.&lt;br /&gt;
 &lt;br /&gt;
 sub IsApplicable {&lt;br /&gt;
    my $self = shift;&lt;br /&gt;
    if ( local_ageInHours($self-&amp;amp;gt;TicketObj) &amp;amp;gt;= $self-&amp;amp;gt;Argument ) {&lt;br /&gt;
        # Returning true (1) indicates that this condition is true&lt;br /&gt;
        return 1;&lt;br /&gt;
    } else {&lt;br /&gt;
        # Returning undef indicates that this condition is false&lt;br /&gt;
        return undef;&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 sub local_ageInHours {&lt;br /&gt;
    my $ticketObj = shift;&lt;br /&gt;
    return (time - $ticketObj-&amp;amp;gt;LastUpdatedObj-&amp;amp;gt;Unix) / (60*60);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 # The following could be omitted. They&amp;#039;re there to allow overrides from Vendor and Local&lt;br /&gt;
 # but as this isn&amp;#039;t a core module, they&amp;#039;re just there for completeness :)&lt;br /&gt;
 &lt;br /&gt;
 eval &amp;quot;require RT::Condition::UntouchedInHours_Vendor&amp;quot;;&lt;br /&gt;
 die $@ if ($@ &amp;amp;amp;&amp;amp;amp; $@ !~ qr{^Can&amp;#039;t locate RT/Condition/UntouchedInHours_Vendor.pm});&lt;br /&gt;
 eval &amp;quot;require RT::Condition::UntouchedInHours_Local&amp;quot;;&lt;br /&gt;
 die $@ if ($@ &amp;amp;amp;&amp;amp;amp; $@ !~ qr{^Can&amp;#039;t locate RT/Condition/UntouchedInHours_Local.pm});&lt;br /&gt;
 &lt;br /&gt;
 # If you weren&amp;#039;t already aware, all perl modules need to evaluate to true. So we&lt;br /&gt;
 # force it to evaluate to true by finishing with a &amp;#039;1&amp;#039;.&lt;br /&gt;
 1;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Alternative Version ====&lt;br /&gt;
&lt;br /&gt;
Could not get the above example to work successfully so I have created an alternative version (as simple as I could make it):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;package RT::Condition::UntouchedInHours;&lt;br /&gt;
 require RT::Condition::Generic;&lt;br /&gt;
 &lt;br /&gt;
 use RT::Date;&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 @ISA = qw(RT::Condition::Generic);&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 use strict;&lt;br /&gt;
 use vars qw/@ISA/;&lt;br /&gt;
 &lt;br /&gt;
 sub IsApplicable {&lt;br /&gt;
         my $self = shift;&lt;br /&gt;
         if ((time()-$self-&amp;amp;gt;TicketObj-&amp;amp;gt;LastUpdatedObj-&amp;amp;gt;Unix)/3600 &amp;amp;gt;= $self-&amp;amp;gt;Argument) {&lt;br /&gt;
                 return 1&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
                 return 0;&lt;br /&gt;
         }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 # The following could be omitted. They&amp;#039;re there to allow overrides from Vendor and Local&lt;br /&gt;
 # but as this isn&amp;#039;t a core module, they&amp;#039;re just there for completeness :)&lt;br /&gt;
 eval &amp;quot;require RT::Condition::UntouchedInHours_Vendor&amp;quot;;&lt;br /&gt;
 die $@ if ($@ &amp;amp;amp;&amp;amp;amp; $@ !~ qr{^Can&amp;#039;t locate RT/Condition/UntouchedInHours_Vendor.pm});&lt;br /&gt;
 eval &amp;quot;require RT::Condition::UntouchedInHours_Local&amp;quot;;&lt;br /&gt;
 die $@ if ($@ &amp;amp;amp;&amp;amp;amp; $@ !~ qr{^Can&amp;#039;t locate RT/Condition/UntouchedInHours_Local.pm});&lt;br /&gt;
 &lt;br /&gt;
 1;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just a footnote on that, I have fixed 2 mistakes spotted in the origional example. It &amp;#039;&amp;#039;&amp;#039;may&amp;#039;&amp;#039;&amp;#039; work now. I am using the Alternative version simply because I prefer its brevity.&lt;br /&gt;
&lt;br /&gt;
==== Alternative Version: UntouchedInBusinessHours ====&lt;br /&gt;
&lt;br /&gt;
Based on this module, i created a additional Modul [[[UntouchedInBusinessHours]].pm] based on Business Hour calculation.&lt;br /&gt;
&lt;br /&gt;
==== Yet Another Alternative Version ====&lt;br /&gt;
&lt;br /&gt;
At our site, we have a number of automatic operations that update a ticket&amp;#039;s *LastUpdated* value, which means that it&amp;#039;s not so useful for determining when the ticket owner last touched the ticket. This version works for us:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;package RT::Condition::UntouchedInHours;&lt;br /&gt;
   require RT::Condition::Generic;&lt;br /&gt;
   &lt;br /&gt;
   # RT::Date::Set kept misbehaving when fed an ISO-formatted string&lt;br /&gt;
   require DateTime::Format::MySQL;&lt;br /&gt;
   &lt;br /&gt;
   @ISA = qw(RT::Condition::Generic);&lt;br /&gt;
   &lt;br /&gt;
   use strict;&lt;br /&gt;
   use vars qw/@ISA/;&lt;br /&gt;
   &lt;br /&gt;
   # default age threshold&lt;br /&gt;
   use constant HOURS =&amp;amp;gt; 4;&lt;br /&gt;
   &lt;br /&gt;
   sub IsApplicable {&lt;br /&gt;
       my $self = shift;&lt;br /&gt;
       my $hours = $self-&amp;amp;gt;Argument || HOURS;&lt;br /&gt;
   &lt;br /&gt;
       # validate input&lt;br /&gt;
       unless ( $hours =~ /^\d+$/ ) {&lt;br /&gt;
           $hours = HOURS;&lt;br /&gt;
       }&lt;br /&gt;
   &lt;br /&gt;
       my $threshold = $hours * 60 * 60;&lt;br /&gt;
       my $now = time();&lt;br /&gt;
       my $last = local_lastCorrespondence( $self-&amp;amp;gt;TicketObj );&lt;br /&gt;
   &lt;br /&gt;
       if ( ( $last &amp;amp;gt; 0 ) &amp;amp;amp;&amp;amp;amp; ( $last + $threshold &amp;amp;lt; $now ) ) {&lt;br /&gt;
           # this ticket has not been touched recently enough&lt;br /&gt;
           return $last;&lt;br /&gt;
       }&lt;br /&gt;
       else {&lt;br /&gt;
           return 0;&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   sub local_lastCorrespondence {&lt;br /&gt;
       my $ticketObj = shift;&lt;br /&gt;
   &lt;br /&gt;
       # list the transactions&lt;br /&gt;
       my $transactions = $ticketObj-&amp;amp;gt;Transactions;&lt;br /&gt;
   &lt;br /&gt;
       # only the Correspondence, please&lt;br /&gt;
       $transactions-&amp;amp;gt;Limit( FIELD =&amp;amp;gt; &amp;#039;Type&amp;#039;, VALUE =&amp;amp;gt; &amp;#039;Correspond&amp;#039; );&lt;br /&gt;
   &lt;br /&gt;
       # sort in descending order, by creation time then id&lt;br /&gt;
       $transactions-&amp;amp;gt;OrderByCols (&lt;br /&gt;
           { FIELD =&amp;amp;gt; &amp;#039;Created&amp;#039;, ORDER =&amp;amp;gt; &amp;#039;DESC&amp;#039; },&lt;br /&gt;
           { FIELD =&amp;amp;gt; &amp;#039;id&amp;#039;, ORDER =&amp;amp;gt; &amp;#039;DESC&amp;#039; },&lt;br /&gt;
       );&lt;br /&gt;
   &lt;br /&gt;
       # get the latest reply&lt;br /&gt;
       my $timestamp;&lt;br /&gt;
       my $transactionObj = $transactions-&amp;amp;gt;First;&lt;br /&gt;
   &lt;br /&gt;
       if ( defined( $transactionObj) &amp;amp;amp;&amp;amp;amp; $transactionObj-&amp;amp;gt;id ) {&lt;br /&gt;
           # if the last Correspondence was from a requestor, check the time&lt;br /&gt;
           if ( $transactionObj-&amp;amp;gt;IsInbound ) {&lt;br /&gt;
   &lt;br /&gt;
               my $last = DateTime::Format::MySQL-&amp;amp;gt;parse_datetime( $transactionObj-&amp;amp;gt;Created );&lt;br /&gt;
               $timestamp = $last-&amp;amp;gt;epoch;&lt;br /&gt;
           }&lt;br /&gt;
           else {&lt;br /&gt;
               # otherwise we don&amp;#039;t care&lt;br /&gt;
               $timestamp = -1;&lt;br /&gt;
           }&lt;br /&gt;
       }&lt;br /&gt;
       else {&lt;br /&gt;
           # try the start time, then the created time&lt;br /&gt;
           my $started = DateTime::Format::MySQL-&amp;amp;gt;parse_datetime( $ticketObj-&amp;amp;gt;Started );&lt;br /&gt;
           my $created = DateTime::Format::MySQL-&amp;amp;gt;parse_datetime( $ticketObj-&amp;amp;gt;Created );&lt;br /&gt;
   &lt;br /&gt;
           if ( $started-&amp;amp;gt;epoch &amp;amp;gt; 0 ) {&lt;br /&gt;
               $timestamp = $started-&amp;amp;gt;epoch;&lt;br /&gt;
           }&lt;br /&gt;
           else {&lt;br /&gt;
               $timestamp = $created-&amp;amp;gt;epoch;&lt;br /&gt;
           }&lt;br /&gt;
       }&lt;br /&gt;
   &lt;br /&gt;
       # if we&amp;#039;ve gotten this far, and there&amp;#039;s still no timestamp,&lt;br /&gt;
       # then something is terribly wrong&lt;br /&gt;
       defined( $timestamp ) or $timestamp = -1;&lt;br /&gt;
   &lt;br /&gt;
       return( $timestamp );&lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   # The following could be omitted. They&amp;#039;re there to allow overrides from Vendor and Local&lt;br /&gt;
   # but as this isn&amp;#039;t a core module, they&amp;#039;re just there for completeness :)&lt;br /&gt;
   eval &amp;quot;require RT::Condition::UntouchedInHours_Vendor&amp;quot;;&lt;br /&gt;
   die $@ if ($@ &amp;amp;amp;&amp;amp;amp; $@ !~ qr{^Can&amp;#039;t locate RT/Condition/UntouchedInHours_Vendor.pm});&lt;br /&gt;
   eval &amp;quot;require RT::Condition::UntouchedInHours_Local&amp;quot;;&lt;br /&gt;
   die $@ if ($@ &amp;amp;amp;&amp;amp;amp; $@ !~ qr{^Can&amp;#039;t locate RT/Condition/UntouchedInHours_Local.pm});&lt;br /&gt;
   &lt;br /&gt;
   1;&lt;br /&gt;
   &lt;br /&gt;
   &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that *IsApplicable* returns the epoch time of the most recent ticket update or 0; this means that you can call this condition from inside a template and then use *RT::Date::AgeAsString* to generate a human-readable representation of how long the ticket has gone without response.&lt;br /&gt;
&lt;br /&gt;
Note that this version works with RT 4.0.1 by editing the two instances of RT::Condition::Generic to RT::Condition&lt;/div&gt;</summary>
		<author><name>24.237.152.32</name></author>
	</entry>
</feed>