rt 4.2.13 ticket#13852
[freeside.git] / rt / lib / RT / Scrip.pm
index 9506616..48547cc 100755 (executable)
@@ -2,7 +2,7 @@
 #
 # COPYRIGHT:
 #
-# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2016 Best Practical Solutions, LLC
 #                                          <sales@bestpractical.com>
 #
 # (Except where explicitly superseded by other copyright notices)
@@ -67,13 +67,14 @@ package RT::Scrip;
 
 use strict;
 use warnings;
-
+use base 'RT::Record';
 
 use RT::Queue;
 use RT::Template;
 use RT::ScripCondition;
 use RT::ScripAction;
-use base 'RT::Record';
+use RT::Scrips;
+use RT::ObjectScrip;
 
 sub Table {'Scrips'}
 
@@ -104,7 +105,7 @@ sub Create {
     my $self = shift;
     my %args = (
         Queue                  => 0,
-        Template               => 0,                     # name or id
+        Template               => undef,                 # name or id
         ScripAction            => 0,                     # name or id
         ScripCondition         => 0,                     # name or id
         Stage                  => 'TransactionCreate',
@@ -112,8 +113,6 @@ sub Create {
         CustomPrepareCode      => undef,
         CustomCommitCode       => undef,
         CustomIsApplicableCode => undef,
-        ConditionRules         => undef,
-        ActionRules            => undef,
         @_
     );
 
@@ -147,7 +146,6 @@ sub Create {
 
     #TODO +++ validate input
 
-    require RT::ScripAction;
     return ( 0, $self->loc("Action is mandatory argument") )
         unless $args{'ScripAction'};
     my $action = RT::ScripAction->new( $self->CurrentUser );
@@ -155,15 +153,26 @@ sub Create {
     return ( 0, $self->loc( "Action '[_1]' not found", $args{'ScripAction'} ) ) 
         unless $action->Id;
 
-    require RT::Template;
     return ( 0, $self->loc("Template is mandatory argument") )
         unless $args{'Template'};
     my $template = RT::Template->new( $self->CurrentUser );
-    $template->Load( $args{'Template'} );
-    return ( 0, $self->loc( "Template '[_1]' not found", $args{'Template'} ) )
-        unless $template->Id;
+    if ( $args{'Template'} =~ /\D/ ) {
+        $template->LoadByName( Name => $args{'Template'}, Queue => $args{'Queue'} );
+        return ( 0, $self->loc( "Global template '[_1]' not found", $args{'Template'} ) )
+            if !$template->Id && !$args{'Queue'};
+        return ( 0, $self->loc( "Global or queue specific template '[_1]' not found", $args{'Template'} ) )
+            if !$template->Id;
+    } else {
+        $template->Load( $args{'Template'} );
+        return ( 0, $self->loc( "Template '[_1]' not found", $args{'Template'} ) )
+            unless $template->Id;
+
+        return (0, $self->loc( "Template '[_1]' is not global" ))
+            if !$args{'Queue'} && $template->Queue;
+        return (0, $self->loc( "Template '[_1]' is not global nor queue specific" ))
+            if $args{'Queue'} && $template->Queue && $template->Queue != $args{'Queue'};
+    }
 
-    require RT::ScripCondition;
     return ( 0, $self->loc("Condition is mandatory argument") )
         unless $args{'ScripCondition'};
     my $condition = RT::ScripCondition->new( $self->CurrentUser );
@@ -171,25 +180,33 @@ sub Create {
     return ( 0, $self->loc( "Condition '[_1]' not found", $args{'ScripCondition'} ) )
         unless $condition->Id;
 
+    if ( $args{'Stage'} eq 'Disabled' ) {
+        $RT::Logger->warning("Disabled Stage is deprecated");
+        $args{'Stage'} = 'TransactionCreate';
+        $args{'Disabled'} = 1;
+    }
+    $args{'Disabled'} ||= 0;
+
     my ( $id, $msg ) = $self->SUPER::Create(
-        Queue                  => $args{'Queue'},
-        Template               => $template->Id,
+        Template               => $template->Name,
         ScripCondition         => $condition->id,
-        Stage                  => $args{'Stage'},
         ScripAction            => $action->Id,
+        Disabled               => $args{'Disabled'},
         Description            => $args{'Description'},
         CustomPrepareCode      => $args{'CustomPrepareCode'},
         CustomCommitCode       => $args{'CustomCommitCode'},
         CustomIsApplicableCode => $args{'CustomIsApplicableCode'},
-        ConditionRules         => $args{'ConditionRules'},
-        ActionRules            => $args{'ActionRules'},
     );
-    if ( $id ) {
-        return ( $id, $self->loc('Scrip Created') );
-    }
-    else {
-        return ( $id, $msg );
-    }
+    return ( $id, $msg ) unless $id;
+
+    (my $status, $msg) = RT::ObjectScrip->new( $self->CurrentUser )->Add(
+        Scrip    => $self,
+        Stage    => $args{'Stage'},
+        ObjectId => $args{'Queue'},
+    );
+    $RT::Logger->error( "Couldn't add scrip: $msg" ) unless $status;
+
+    return ( $id, $self->loc('Scrip Created') );
 }
 
 
@@ -207,33 +224,158 @@ sub Delete {
         return ( 0, $self->loc('Permission Denied') );
     }
 
+    RT::ObjectScrip->new( $self->CurrentUser )->DeleteAll( Scrip => $self );
+
     return ( $self->SUPER::Delete(@_) );
 }
 
+sub IsGlobal { return shift->IsAdded(0) }
+
+sub IsAdded {
+    my $self = shift;
+    my $record = RT::ObjectScrip->new( $self->CurrentUser );
+    $record->LoadByCols( Scrip => $self->id, ObjectId => shift || 0 );
+    return undef unless $record->id;
+    return $record;
+}
+
+sub IsAddedToAny {
+    my $self = shift;
+    my $record = RT::ObjectScrip->new( $self->CurrentUser );
+    $record->LoadByCols( Scrip => $self->id );
+    return $record->id ? 1 : 0;
+}
+
+sub AddedTo {
+    my $self = shift;
+    return RT::ObjectScrip->new( $self->CurrentUser )
+        ->AddedTo( Scrip => $self );
+}
+
+sub NotAddedTo {
+    my $self = shift;
+    return RT::ObjectScrip->new( $self->CurrentUser )
+        ->NotAddedTo( Scrip => $self );
+}
+
+=head2 AddToObject
+
+Adds (applies) the current scrip to the provided queue (ObjectId).
 
+Accepts a param hash of:
 
-=head2 QueueObj
+=over
 
-Retuns an RT::Queue object with this Scrip's queue
+=item C<ObjectId>
+
+Queue name or id. 0 makes the scrip global.
+
+=item C<Stage>
+
+Stage to run in. Valid stages are TransactionCreate or
+TransactionBatch. Defaults to TransactionCreate. As of RT 4.2, Disabled
+is no longer a stage.
+
+=item C<Template>
+
+Name of global or queue-specific template for the scrip. Use 'Blank' for
+non-notification scrips.
+
+=item C<SortOrder>
+
+Number indicating the relative order the scrip should run in.
+
+=back
+
+Returns (val, message). If val is false, the message contains an error
+message.
 
 =cut
 
-sub QueueObj {
+sub AddToObject {
     my $self = shift;
+    my %args = @_%2? (ObjectId => @_) : (@_);
+
+    # Default Stage explicitly rather than in %args assignment to handle
+    # Stage coming in set to undef.
+    $args{'Stage'} //= 'TransactionCreate';
 
-    if ( !$self->{'QueueObj'} ) {
-        require RT::Queue;
-        $self->{'QueueObj'} = RT::Queue->new( $self->CurrentUser );
-        $self->{'QueueObj'}->Load( $self->__Value('Queue') );
+    my $queue;
+    if ( $args{'ObjectId'} ) {
+        $queue = RT::Queue->new( $self->CurrentUser );
+        $queue->Load( $args{'ObjectId'} );
+        return (0, $self->loc('Invalid queue'))
+            unless $queue->id;
+
+        $args{'ObjectId'} = $queue->id;
+    }
+    return ( 0, $self->loc('Permission Denied') )
+        unless $self->CurrentUser->PrincipalObj->HasRight(
+            Object => $queue || $RT::System, Right => 'ModifyScrips',
+        )
+    ;
+
+    my $tname = $self->Template;
+    my $template = RT::Template->new( $self->CurrentUser );
+    $template->LoadByName( Queue => $queue? $queue->id : 0, Name => $tname );
+    unless ( $template->id ) {
+        if ( $queue ) {
+            return (0, $self->loc('No template [_1] in queue [_2] or global',
+                    $tname, $queue->Name||$queue->id));
+        } else {
+            return (0, $self->loc('No global template [_1]', $tname));
+        }
     }
-    return ( $self->{'QueueObj'} );
+
+    my $rec = RT::ObjectScrip->new( $self->CurrentUser );
+    return $rec->Add( %args, Scrip => $self );
 }
 
+=head2 RemoveFromObject
+
+Removes the current scrip to the provided queue (ObjectId).
+
+Accepts a param hash of:
+
+=over
+
+=item C<ObjectId>
 
+Queue name or id. 0 makes the scrip global.
+
+=back
+
+Returns (val, message). If val is false, the message contains an error
+message.
+
+=cut
+
+sub RemoveFromObject {
+    my $self = shift;
+    my %args = @_%2? (ObjectId => @_) : (@_);
+
+    my $queue;
+    if ( $args{'ObjectId'} ) {
+        $queue = RT::Queue->new( $self->CurrentUser );
+        $queue->Load( $args{'ObjectId'} );
+        return (0, $self->loc('Invalid queue id'))
+            unless $queue->id;
+    }
+    return ( 0, $self->loc('Permission Denied') )
+        unless $self->CurrentUser->PrincipalObj->HasRight(
+            Object => $queue || $RT::System, Right => 'ModifyScrips',
+        )
+    ;
+
+    my $rec = RT::ObjectScrip->new( $self->CurrentUser );
+    $rec->LoadByCols( Scrip => $self->id, ObjectId => $args{'ObjectId'} );
+    return (0, $self->loc('Scrip is not added') ) unless $rec->id;
+    return $rec->Delete;
+}
 
 =head2 ActionObj
 
-Retuns an RT::Action object with this Scrip\'s Action
+Retuns an RT::Action object with this Scrip's Action
 
 =cut
 
@@ -242,12 +384,8 @@ sub ActionObj {
 
     unless ( defined $self->{'ScripActionObj'} ) {
         require RT::ScripAction;
-
         $self->{'ScripActionObj'} = RT::ScripAction->new( $self->CurrentUser );
-
-        #TODO: why are we loading Actions with templates like this.
-        # two separate methods might make more sense
-        $self->{'ScripActionObj'}->Load( $self->ScripAction, $self->Template );
+        $self->{'ScripActionObj'}->Load( $self->ScripAction );
     }
     return ( $self->{'ScripActionObj'} );
 }
@@ -285,23 +423,60 @@ sub LoadModules {
 
 =head2 TemplateObj
 
-Retuns an RT::Template object with this Scrip\'s Template
+Retuns an RT::Template object with this Scrip's Template
 
 =cut
 
 sub TemplateObj {
     my $self = shift;
+    my $queue = shift;
 
-    unless ( defined $self->{'TemplateObj'} ) {
-        require RT::Template;
-        $self->{'TemplateObj'} = RT::Template->new( $self->CurrentUser );
-        $self->{'TemplateObj'}->Load( $self->Template );
-    }
-    return ( $self->{'TemplateObj'} );
+    my $res = RT::Template->new( $self->CurrentUser );
+    $res->LoadByName( Queue => $queue, Name => $self->Template );
+    return $res;
 }
 
+=head2 Stage
+
+Takes TicketObj named argument and returns scrip's stage when
+added to ticket's queue.
+
+=cut
+
+sub Stage {
+    my $self = shift;
+    my %args = ( TicketObj => undef, @_ );
 
+    my $queue = $args{'TicketObj'}->Queue;
+    my $rec = RT::ObjectScrip->new( $self->CurrentUser );
+    $rec->LoadByCols( Scrip => $self->id, ObjectId => $queue );
+    return $rec->Stage if $rec->id;
 
+    $rec->LoadByCols( Scrip => $self->id, ObjectId => 0 );
+    return $rec->Stage if $rec->id;
+
+    return undef;
+}
+
+=head2 FriendlyStage($Stage)
+
+Helper function that returns a localized human-readable version of the
+C<$Stage> argument.
+
+=cut
+
+sub FriendlyStage {
+    my ( $class, $stage ) = @_;
+    my $stage_i18n_lookup = {
+        TransactionCreate => 'Normal', # loc
+        TransactionBatch => 'Batch', # loc
+        TransactionBatchDisabled => 'Batch (disabled by config)', # loc
+    };
+    $stage = 'TransactionBatchDisabled'
+        if $stage eq 'TransactionBatch'
+            and not RT->Config->Get('UseTransactionBatch');
+    return $stage_i18n_lookup->{$stage};
+}
 
 =head2 Apply { TicketObj => undef, TransactionObj => undef}
 
@@ -362,7 +537,7 @@ sub Apply {
 
 =head2 IsApplicable
 
-Calls the  Condition object\'s IsApplicable method
+Calls the  Condition object's IsApplicable method
 
 Upon success, returns the applicable Transaction object.
 Otherwise, undef is returned.
@@ -385,38 +560,46 @@ sub IsApplicable {
     my $return;
     eval {
 
-       my @Transactions;
+        my @Transactions;
 
-        if ( $self->Stage eq 'TransactionCreate') {
-           # Only look at our current Transaction
-           @Transactions = ( $args{'TransactionObj'} );
+        my $stage = $self->Stage( TicketObj => $args{'TicketObj'} );
+        unless ( $stage ) {
+            $RT::Logger->error(
+                "Scrip #". $self->id ." is not applied to"
+                ." queue #". $args{'TicketObj'}->Queue
+            );
+            return (undef);
         }
-        elsif ( $self->Stage eq 'TransactionBatch') {
-           # Look at all Transactions in this Batch
+        elsif ( $stage eq 'TransactionCreate') {
+            # Only look at our current Transaction
+            @Transactions = ( $args{'TransactionObj'} );
+        }
+        elsif ( $stage eq 'TransactionBatch') {
+            # Look at all Transactions in this Batch
             @Transactions = @{ $args{'TicketObj'}->TransactionBatch || [] };
         }
-       else {
-           $RT::Logger->error( "Unknown Scrip stage:" . $self->Stage );
-           return (undef);
-       }
-       my $ConditionObj = $self->ConditionObj;
-       foreach my $TransactionObj ( @Transactions ) {
-           # in TxnBatch stage we can select scrips that are not applicable to all txns
-           my $txn_type = $TransactionObj->Type;
-           next unless( $ConditionObj->ApplicableTransTypes =~ /(?:^|,)(?:Any|\Q$txn_type\E)(?:,|$)/i );
-           # Load the scrip's Condition object
-           $ConditionObj->LoadCondition(
-               ScripObj       => $self,
-               TicketObj      => $args{'TicketObj'},
-               TransactionObj => $TransactionObj,
-           );
+        else {
+            $RT::Logger->error( "Unknown Scrip stage: '$stage'" );
+            return (undef);
+        }
+        my $ConditionObj = $self->ConditionObj;
+        foreach my $TransactionObj ( @Transactions ) {
+            # in TxnBatch stage we can select scrips that are not applicable to all txns
+            my $txn_type = $TransactionObj->Type;
+            next unless( $ConditionObj->ApplicableTransTypes =~ /(?:^|,)(?:Any|\Q$txn_type\E)(?:,|$)/i );
+            # Load the scrip's Condition object
+            $ConditionObj->LoadCondition(
+                ScripObj       => $self,
+                TicketObj      => $args{'TicketObj'},
+                TransactionObj => $TransactionObj,
+            );
 
             if ( $ConditionObj->IsApplicable() ) {
-               # We found an application Transaction -- return it
+                # We found an application Transaction -- return it
                 $return = $TransactionObj;
                 last;
             }
-       }
+        }
     };
 
     if ($@) {
@@ -444,9 +627,11 @@ sub Prepare {
 
     my $return;
     eval {
-        $self->ActionObj->LoadAction( ScripObj       => $self,
-                                      TicketObj      => $args{'TicketObj'},
-                                      TransactionObj => $args{'TransactionObj'},
+        $self->ActionObj->LoadAction(
+            ScripObj       => $self,
+            TicketObj      => $args{'TicketObj'},
+            TransactionObj => $args{'TransactionObj'},
+            TemplateObj    => $self->TemplateObj( $args{'TicketObj'}->Queue ),
         );
 
         $return = $self->ActionObj->Prepare();
@@ -508,8 +693,7 @@ sub _Set {
     );
 
     unless ( $self->CurrentUserHasRight('ModifyScrips') ) {
-        $RT::Logger->debug(
-                 "CurrentUser can't modify Scrips for " . $self->Queue . "\n" );
+        $RT::Logger->debug( "CurrentUser can't modify Scrips" );
         return ( 0, $self->loc('Permission Denied') );
     }
 
@@ -545,7 +729,7 @@ sub _Set {
         }
     }
 
-    return $self->__Set(@_);
+    return $self->SUPER::_Set(@_);
 }
 
 
@@ -553,61 +737,22 @@ sub _Set {
 sub _Value {
     my $self = shift;
 
-    unless ( $self->CurrentUserHasRight('ShowScrips') ) {
-        $RT::Logger->debug( "CurrentUser can't modify Scrips for "
-                            . $self->__Value('Queue')
-                            . "\n" );
-        return (undef);
-    }
+    return unless $self->CurrentUserHasRight('ShowScrips');
 
     return $self->__Value(@_);
 }
 
+=head2 ACLEquivalenceObjects
 
-
-=head2 CurrentUserHasRight
-
-Helper menthod for HasRight. Presets Principal to CurrentUser then 
-calls HasRight.
-
-=cut
-
-sub CurrentUserHasRight {
-    my $self  = shift;
-    my $right = shift;
-    return ( $self->HasRight( Principal => $self->CurrentUser->UserObj,
-                              Right     => $right ) );
-
-}
-
-
-
-=head2 HasRight
-
-Takes a param-hash consisting of "Right" and "Principal"  Principal is 
-an RT::User object or an RT::CurrentUser object. "Right" is a textual
-Right string that applies to Scrips.
+Having rights on any of the queues the scrip applies to is equivalent to
+having rights on the scrip.
 
 =cut
 
-sub HasRight {
+sub ACLEquivalenceObjects {
     my $self = shift;
-    my %args = ( Right     => undef,
-                 Principal => undef,
-                 @_ );
-
-    if ( $self->SUPER::_Value('Queue') ) {
-        return $args{'Principal'}->HasRight(
-            Right  => $args{'Right'},
-            Object => $self->QueueObj
-        );
-    }
-    else {
-        return $args{'Principal'}->HasRight(
-            Object => $RT::System,
-            Right  => $args{'Right'},
-        );
-    }
+    return unless $self->id;
+    return @{ $self->AddedTo->ItemsArrayRef };
 }
 
 
@@ -633,7 +778,7 @@ sub CompileCheck {
 
         do {
             no strict 'vars';
-            eval "sub { $code }";
+            eval "sub { $code \n }";
         };
         next if !$@;
 
@@ -699,7 +844,7 @@ sub SetTemplate {
     return ( 0, $self->loc( "Template '[_1]' not found", $value ) )
       unless $template->Id;
 
-    return $self->_Set( Field => 'Template', Value => $template->Id );
+    return $self->_Set( Field => 'Template', Value => $template->Name );
 }
 
 1;
@@ -762,10 +907,10 @@ Returns the ScripCondition Object which has the id returned by ScripCondition
 =cut
 
 sub ScripConditionObj {
-       my $self = shift;
-       my $ScripCondition =  RT::ScripCondition->new($self->CurrentUser);
-       $ScripCondition->Load($self->__Value('ScripCondition'));
-       return($ScripCondition);
+        my $self = shift;
+        my $ScripCondition =  RT::ScripCondition->new($self->CurrentUser);
+        $ScripCondition->Load($self->__Value('ScripCondition'));
+        return($ScripCondition);
 }
 
 =head2 ScripAction
@@ -794,48 +939,12 @@ Returns the ScripAction Object which has the id returned by ScripAction
 =cut
 
 sub ScripActionObj {
-       my $self = shift;
-       my $ScripAction =  RT::ScripAction->new($self->CurrentUser);
-       $ScripAction->Load($self->__Value('ScripAction'));
-       return($ScripAction);
+        my $self = shift;
+        my $ScripAction =  RT::ScripAction->new($self->CurrentUser);
+        $ScripAction->Load($self->__Value('ScripAction'));
+        return($ScripAction);
 }
 
-=head2 ConditionRules
-
-Returns the current value of ConditionRules.
-(In the database, ConditionRules is stored as text.)
-
-
-
-=head2 SetConditionRules VALUE
-
-
-Set ConditionRules to VALUE.
-Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, ConditionRules will be stored as a text.)
-
-
-=cut
-
-
-=head2 ActionRules
-
-Returns the current value of ActionRules.
-(In the database, ActionRules is stored as text.)
-
-
-
-=head2 SetActionRules VALUE
-
-
-Set ActionRules to VALUE.
-Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, ActionRules will be stored as a text.)
-
-
-=cut
-
-
 =head2 CustomIsApplicableCode
 
 Returns the current value of CustomIsApplicableCode.
@@ -890,37 +999,19 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
 =cut
 
 
-=head2 Stage
-
-Returns the current value of Stage.
-(In the database, Stage is stored as varchar(32).)
-
-
-
-=head2 SetStage VALUE
-
-
-Set Stage to VALUE.
-Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, Stage will be stored as a varchar(32).)
-
-
-=cut
-
-
-=head2 Queue
+=head2 Disabled
 
-Returns the current value of Queue.
-(In the database, Queue is stored as int(11).)
+Returns the current value of Disabled.
+(In the database, Disabled is stored as smallint(6).)
 
 
 
-=head2 SetQueue VALUE
+=head2 SetDisabled VALUE
 
 
-Set Queue to VALUE.
+Set Disabled to VALUE.
 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, Queue will be stored as a int(11).)
+(In the database, Disabled will be stored as a smallint(6).)
 
 
 =cut
@@ -929,7 +1020,7 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
 =head2 Template
 
 Returns the current value of Template.
-(In the database, Template is stored as int(11).)
+(In the database, Template is stored as varchar(200).)
 
 
 
@@ -938,7 +1029,7 @@ Returns the current value of Template.
 
 Set Template to VALUE.
 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, Template will be stored as a int(11).)
+(In the database, Template will be stored as a varchar(200).)
 
 
 =cut
@@ -985,41 +1076,85 @@ sub _CoreAccessible {
     {
 
         id =>
-               {read => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => ''},
+                {read => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => ''},
         Description =>
-               {read => 1, write => 1, sql_type => 12, length => 255,  is_blob => 0,  is_numeric => 0,  type => 'varchar(255)', default => ''},
+                {read => 1, write => 1, sql_type => 12, length => 255,  is_blob => 0,  is_numeric => 0,  type => 'varchar(255)', default => ''},
         ScripCondition =>
-               {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
+                {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
         ScripAction =>
-               {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
-        ConditionRules =>
-               {read => 1, write => 1, sql_type => -4, length => 0,  is_blob => 1,  is_numeric => 0,  type => 'text', default => ''},
-        ActionRules =>
-               {read => 1, write => 1, sql_type => -4, length => 0,  is_blob => 1,  is_numeric => 0,  type => 'text', default => ''},
+                {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
         CustomIsApplicableCode =>
-               {read => 1, write => 1, sql_type => -4, length => 0,  is_blob => 1,  is_numeric => 0,  type => 'text', default => ''},
+                {read => 1, write => 1, sql_type => -4, length => 0,  is_blob => 1,  is_numeric => 0,  type => 'text', default => ''},
         CustomPrepareCode =>
-               {read => 1, write => 1, sql_type => -4, length => 0,  is_blob => 1,  is_numeric => 0,  type => 'text', default => ''},
+                {read => 1, write => 1, sql_type => -4, length => 0,  is_blob => 1,  is_numeric => 0,  type => 'text', default => ''},
         CustomCommitCode =>
-               {read => 1, write => 1, sql_type => -4, length => 0,  is_blob => 1,  is_numeric => 0,  type => 'text', default => ''},
-        Stage =>
-               {read => 1, write => 1, sql_type => 12, length => 32,  is_blob => 0,  is_numeric => 0,  type => 'varchar(32)', default => ''},
-        Queue =>
-               {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
+                {read => 1, write => 1, sql_type => -4, length => 0,  is_blob => 1,  is_numeric => 0,  type => 'text', default => ''},
+        Disabled =>
+                {read => 1, write => 1, sql_type => 5, length => 6,  is_blob => 0,  is_numeric => 1,  type => 'smallint(6)', default => '0'},
         Template =>
-               {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
+                {read => 1, write => 1, sql_type => 12, length => 200,  is_blob => 0,  is_numeric => 0,  type => 'varchar(200)', default => 'Blank'},
         Creator =>
-               {read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
+                {read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
         Created =>
-               {read => 1, auto => 1, sql_type => 11, length => 0,  is_blob => 0,  is_numeric => 0,  type => 'datetime', default => ''},
+                {read => 1, auto => 1, sql_type => 11, length => 0,  is_blob => 0,  is_numeric => 0,  type => 'datetime', default => ''},
         LastUpdatedBy =>
-               {read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
+                {read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
         LastUpdated =>
-               {read => 1, auto => 1, sql_type => 11, length => 0,  is_blob => 0,  is_numeric => 0,  type => 'datetime', default => ''},
+                {read => 1, auto => 1, sql_type => 11, length => 0,  is_blob => 0,  is_numeric => 0,  type => 'datetime', default => ''},
 
  }
 };
 
+sub FindDependencies {
+    my $self = shift;
+    my ($walker, $deps) = @_;
+
+    $self->SUPER::FindDependencies($walker, $deps);
+
+    my $applied = RT::ObjectScrips->new( $self->CurrentUser );
+    $applied->LimitToScrip( $self->id );
+    $deps->Add( in => $applied );
+
+    $deps->Add( out => $self->ScripConditionObj );
+    $deps->Add( out => $self->ScripActionObj );
+    $deps->Add( out => $self->TemplateObj );
+}
+
+sub __DependsOn {
+    my $self = shift;
+    my %args = (
+        Shredder => undef,
+        Dependencies => undef,
+        @_,
+    );
+    my $deps = $args{'Dependencies'};
+    my $list = [];
+
+    my $objs = RT::ObjectScrips->new( $self->CurrentUser );
+    $objs->LimitToScrip( $self->Id );
+    push @$list, $objs;
+
+    $deps->_PushDependencies(
+        BaseObject    => $self,
+        Flags         => RT::Shredder::Constants::DEPENDS_ON,
+        TargetObjects => $list,
+        Shredder      => $args{'Shredder'}
+    );
+
+    return $self->SUPER::__DependsOn( %args );
+}
+
+sub Serialize {
+    my $self = shift;
+    my %args = (@_);
+    my %store = $self->SUPER::Serialize(@_);
+
+    # Store the string, not a reference to the object
+    $store{Template} = $self->Template;
+
+    return %store;
+}
+
 RT::Base->_ImportOverlays();
 
 1;