[Rt-commit] rt branch, 4.2/template-name-instead-of-id, created. rt-4.0.4-256-g0b4b543

Ruslan Zakirov ruz at bestpractical.com
Thu Sep 27 12:58:59 EDT 2012


The branch, 4.2/template-name-instead-of-id has been created
        at  0b4b5437d2298c73f1b905c78cda3d40f78e325f (commit)

- Log -----------------------------------------------------------------
commit dd0147b60e5e2b4b41642e617091ec872deebcb1
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Fri Apr 13 02:14:43 2012 +0400

    change Template column from id to Name

diff --git a/etc/schema.Oracle b/etc/schema.Oracle
index 039a646..69aa24e 100755
--- a/etc/schema.Oracle
+++ b/etc/schema.Oracle
@@ -141,7 +141,7 @@ CREATE TABLE Scrips (
 	CustomIsApplicableCode	CLOB,
 	CustomPrepareCode	CLOB,
 	CustomCommitCode	CLOB,
-	Template	NUMBER(11,0) DEFAULT 0 NOT NULL,
+	Template	VARCHAR2(200) NOT NULL,
   	Creator 	NUMBER(11,0) DEFAULT 0 NOT NULL,
   	Created 	DATE,
   	LastUpdatedBy 	NUMBER(11,0) DEFAULT 0 NOT NULL,
diff --git a/etc/schema.Pg b/etc/schema.Pg
index b4742fc..5af9167 100755
--- a/etc/schema.Pg
+++ b/etc/schema.Pg
@@ -230,7 +230,7 @@ CREATE TABLE Scrips (
   CustomIsApplicableCode text NULL  ,
   CustomPrepareCode text NULL  ,
   CustomCommitCode text NULL  ,
-  Template integer NOT NULL DEFAULT 0  ,
+  Template varchar(200) NOT NULL,
   Creator integer NOT NULL DEFAULT 0  ,
   Created TIMESTAMP NULL  ,
   LastUpdatedBy integer NOT NULL DEFAULT 0  ,
diff --git a/etc/schema.SQLite b/etc/schema.SQLite
index 8867b03..4130ddb 100755
--- a/etc/schema.SQLite
+++ b/etc/schema.SQLite
@@ -150,7 +150,7 @@ CREATE TABLE Scrips (
   CustomIsApplicableCode text NULL  ,
   CustomPrepareCode text NULL  ,
   CustomCommitCode text NULL  ,
-  Template integer NULL  ,
+  Template varchar(200) NOT NULL ,
   Creator integer NULL  ,
   Created DATETIME NULL  ,
   LastUpdatedBy integer NULL  ,
diff --git a/etc/schema.mysql b/etc/schema.mysql
index 44889a0..3646743 100755
--- a/etc/schema.mysql
+++ b/etc/schema.mysql
@@ -142,7 +142,7 @@ CREATE TABLE Scrips (
   CustomIsApplicableCode text NULL  ,
   CustomPrepareCode text NULL  ,
   CustomCommitCode text NULL  ,
-  Template integer NOT NULL DEFAULT 0  ,
+  Template varchar(200) NOT NULL  ,
   Creator integer NOT NULL DEFAULT 0  ,
   Created DATETIME NULL  ,
   LastUpdatedBy integer NOT NULL DEFAULT 0  ,
diff --git a/lib/RT/Scrip.pm b/lib/RT/Scrip.pm
index 3afde00..6f77df3 100644
--- a/lib/RT/Scrip.pm
+++ b/lib/RT/Scrip.pm
@@ -1004,7 +1004,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).)
 
 
 
@@ -1013,7 +1013,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
@@ -1078,7 +1078,7 @@ sub _CoreAccessible {
         CustomCommitCode =>
 		{read => 1, write => 1, sql_type => -4, length => 0,  is_blob => 1,  is_numeric => 0,  type => 'text', default => ''},
         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'},
         Created =>

commit c34351848711dd4d1112a542ab73af3c2f268259
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Sat Apr 14 00:55:00 2012 +0400

    we don't need `require`s as we have `use`s

diff --git a/lib/RT/Scrip.pm b/lib/RT/Scrip.pm
index 6f77df3..2ee4fec 100644
--- a/lib/RT/Scrip.pm
+++ b/lib/RT/Scrip.pm
@@ -148,7 +148,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 );
@@ -156,7 +155,6 @@ 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 );
@@ -164,7 +162,6 @@ sub Create {
     return ( 0, $self->loc( "Template '[_1]' not found", $args{'Template'} ) )
         unless $template->Id;
 
-    require RT::ScripCondition;
     return ( 0, $self->loc("Condition is mandatory argument") )
         unless $args{'ScripCondition'};
     my $condition = RT::ScripCondition->new( $self->CurrentUser );

commit fde79cece2242a7a094a6ff167690c4b691b58cd
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Sat Apr 14 01:29:58 2012 +0400

    merge test files

diff --git a/t/api/template-insert.t b/t/api/template-insert.t
deleted file mode 100644
index 1bf5fc3..0000000
--- a/t/api/template-insert.t
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/perl
-
-use warnings;
-use strict;
-
-
-use RT;
-use RT::Test tests => 7;
-
-
-
-# This tiny little test script triggers an interaction bug between DBD::Oracle 1.16, SB 1.15 and RT 3.4
-
-use_ok('RT::Template');
-my $template = RT::Template->new(RT->SystemUser);
-
-isa_ok($template, 'RT::Template');
-my ($val,$msg) = $template->Create(Queue => 1,
-                  Name => 'InsertTest',
-                  Content => 'This is template content');
-ok($val,$msg);
-is($template->Name, 'InsertTest');
-is($template->Content, 'This is template content', "We created the object right");
-($val, $msg) = $template->SetContent( 'This is new template content');
-ok($val,$msg);
-is($template->Content, 'This is new template content', "We managed to _Set_ the content");
diff --git a/t/api/template.t b/t/api/template.t
index 2fadede..93f839a 100644
--- a/t/api/template.t
+++ b/t/api/template.t
@@ -1,25 +1,34 @@
 
 use strict;
 use warnings;
-use RT;
-use RT::Test tests => 2;
 
+use RT::Test tests => 8;
 
-{
-
-ok(require RT::Template);
 
+use_ok('RT::Template');
 
+{
+    my $template = RT::Template->new(RT->SystemUser);
+    isa_ok($template, 'RT::Template');
+    my ($val,$msg) = $template->Create(
+        Queue => 1,
+        Name => 'InsertTest',
+        Content => 'This is template content'
+    );
+    ok($val,$msg);
+
+    is( $template->Name, 'InsertTest');
+    is( $template->Content, 'This is template content', "We created the object right");
+
+    ($val, $msg) = $template->SetContent( 'This is new template content');
+    ok($val,$msg);
+    is($template->Content, 'This is new template content', "We managed to _Set_ the content");
 }
 
 {
-
-my $t = RT::Template->new(RT->SystemUser);
-$t->Create(Name => "Foo", Queue => 1);
-my $t2 = RT::Template->new(RT->Nobody);
-$t2->Load($t->Id);
-ok($t2->QueueObj->id, "Got the template's queue objet");
-
-
+    my $t = RT::Template->new(RT->SystemUser);
+    $t->Create(Name => "Foo", Queue => 1);
+    my $t2 = RT::Template->new(RT->Nobody);
+    $t2->Load($t->Id);
+    ok($t2->QueueObj->id, "Got the template's queue objet");
 }
-

commit 3da558b0c72271aea82032fd76c15b5508d92de2
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Apr 16 15:50:36 2012 +0400

    make sure we can not create templates with duplicate names

diff --git a/lib/RT/Template.pm b/lib/RT/Template.pm
index 6f0251d..bcd6874 100644
--- a/lib/RT/Template.pm
+++ b/lib/RT/Template.pm
@@ -232,6 +232,16 @@ sub Create {
         $args{'Queue'} = $QueueObj->Id;
     }
 
+    return ( undef, $self->loc('Name is required') )
+        unless $args{Name};
+
+    {
+        my $tmp = $self->new( RT->SystemUser );
+        $tmp->LoadByCols( Name => $args{'Name'}, Queue => $args{'Queue'} );
+        return ( undef, $self->loc('Template with that name already exist') )
+            if $tmp->id;
+    }
+
     my $result = $self->SUPER::Create(
         Content     => $args{'Content'},
         Queue       => $args{'Queue'},
diff --git a/t/api/template.t b/t/api/template.t
index 93f839a..62f8b3e 100644
--- a/t/api/template.t
+++ b/t/api/template.t
@@ -4,20 +4,26 @@ use warnings;
 
 use RT::Test tests => 8;
 
-
 use_ok('RT::Template');
 
+my $queue = RT::Test->load_or_create_queue( Name => 'Templates' );
+ok $queue && $queue->id, 'loaded or created queue';
+
 {
     my $template = RT::Template->new(RT->SystemUser);
     isa_ok($template, 'RT::Template');
+}
+
+{
+    my $template = RT::Template->new(RT->SystemUser);
     my ($val,$msg) = $template->Create(
-        Queue => 1,
-        Name => 'InsertTest',
+        Queue => $queue->id,
+        Name => 'Test',
         Content => 'This is template content'
     );
     ok($val,$msg);
 
-    is( $template->Name, 'InsertTest');
+    is( $template->Name, 'Test');
     is( $template->Content, 'This is template content', "We created the object right");
 
     ($val, $msg) = $template->SetContent( 'This is new template content');
@@ -25,6 +31,17 @@ use_ok('RT::Template');
     is($template->Content, 'This is new template content', "We managed to _Set_ the content");
 }
 
+note "can not create template with duplicate name";
+{
+    clean_templates( Queue => $queue->id );
+    my $template = RT::Template->new( RT->SystemUser );
+    my ($val,$msg) = $template->Create( Queue => $queue->id, Name => 'Test' );
+    ok($val,$msg);
+
+    ($val,$msg) = $template->Create( Queue => $queue->id, Name => 'Test' );
+    ok(!$val,$msg);
+}
+
 {
     my $t = RT::Template->new(RT->SystemUser);
     $t->Create(Name => "Foo", Queue => 1);
@@ -32,3 +49,17 @@ use_ok('RT::Template');
     $t2->Load($t->Id);
     ok($t2->QueueObj->id, "Got the template's queue objet");
 }
+
+sub clean_templates {
+    my %args = (@_);
+
+    my $templates = RT::Templates->new( RT->SystemUser );
+    $templates->Limit( FIELD => 'Queue', VALUE => $args{'Queue'} )
+        if defined $args{'Queue'};
+    $templates->Limit( FIELD => 'Name', VALUE => $_ )
+        foreach ref $args{'Name'}? @{$args{'Name'}} : ($args{'Name'}||());
+    while ( my $t = $templates->Next ) {
+        $t->Delete;
+    }
+}
+

commit cd5bcd8ca5a2d8ed7a75364a8f02e33a063d3ddc
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Apr 16 15:52:32 2012 +0400

    make sure we can not create template without name

diff --git a/t/api/template.t b/t/api/template.t
index 62f8b3e..f22af69 100644
--- a/t/api/template.t
+++ b/t/api/template.t
@@ -31,6 +31,14 @@ ok $queue && $queue->id, 'loaded or created queue';
     is($template->Content, 'This is new template content', "We managed to _Set_ the content");
 }
 
+note "can not create template w/o Name";
+{
+    clean_templates( Queue => $queue->id );
+    my $template = RT::Template->new( RT->SystemUser );
+    my ($val,$msg) = $template->Create( Queue => $queue->id );
+    ok(!$val,$msg);
+}
+
 note "can not create template with duplicate name";
 {
     clean_templates( Queue => $queue->id );

commit b5ae7f32f0e7e27bbf9299ec3596810ac8d2e695
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Apr 16 16:13:53 2012 +0400

    test that we can change template name

diff --git a/t/api/template.t b/t/api/template.t
index f22af69..e6e8626 100644
--- a/t/api/template.t
+++ b/t/api/template.t
@@ -50,6 +50,18 @@ note "can not create template with duplicate name";
     ok(!$val,$msg);
 }
 
+note "change template's name";
+{
+    clean_templates( Queue => $queue->id );
+    my $template = RT::Template->new( RT->SystemUser );
+    my ($val,$msg) = $template->Create( Queue => $queue->id, Name => 'Test' );
+    ok($val,$msg);
+
+    ($val,$msg) = $template->SetName( 'Some' );
+    ($val,$msg);
+    is $template->Name, 'Some';
+}
+
 {
     my $t = RT::Template->new(RT->SystemUser);
     $t->Create(Name => "Foo", Queue => 1);

commit 40ad07d801c9cde5d301c52bc922cfe0e78083a0
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Apr 16 16:18:18 2012 +0400

    make sure tmpl's name can't be set to empty or duplicate

diff --git a/lib/RT/Template.pm b/lib/RT/Template.pm
index bcd6874..54c0959 100644
--- a/lib/RT/Template.pm
+++ b/lib/RT/Template.pm
@@ -607,6 +607,30 @@ sub CurrentUserHasQueueRight {
     return ( $self->QueueObj->CurrentUserHasRight(@_) );
 }
 
+=head2 SetName
+
+Change name of the template.
+
+=cut
+
+sub SetName {
+    my $self = shift;
+    my $value = shift;
+
+    return ( undef, $self->loc('Name is required') )
+        unless $value;
+
+    return $self->_Set( Field => 'Name', Value => $value )
+        if lc($self->Name) eq lc($value);
+
+    my $tmp = $self->new( RT->SystemUser );
+    $tmp->LoadByCols( Name => $value, Queue => $self->Queue );
+    return ( undef, $self->loc('Template with that name already exist') )
+        if $tmp->id;
+
+    return $self->_Set( Field => 'Name', Value => $value );
+}
+
 =head2 SetType
 
 If setting Type to Perl, require the ExecuteCode right.
diff --git a/t/api/template.t b/t/api/template.t
index e6e8626..b25e023 100644
--- a/t/api/template.t
+++ b/t/api/template.t
@@ -62,6 +62,30 @@ note "change template's name";
     is $template->Name, 'Some';
 }
 
+note "can not change name to empty";
+{
+    clean_templates( Queue => $queue->id );
+    my $template = RT::Template->new( RT->SystemUser );
+    my ($val,$msg) = $template->Create( Queue => $queue->id, Name => 'Test' );
+    ok($val,$msg);
+
+    ($val,$msg) = $template->Create( Queue => $queue->id, Name => '' );
+    ok(!$val,$msg);
+    ($val,$msg) = $template->Create( Queue => $queue->id, Name => undef );
+    ok(!$val,$msg);
+}
+
+note "can not change name to duplicate";
+{
+    clean_templates( Queue => $queue->id );
+    my $template = RT::Template->new( RT->SystemUser );
+    my ($val,$msg) = $template->Create( Queue => $queue->id, Name => 'Test' );
+    ok($val,$msg);
+
+    ($val,$msg) = $template->Create( Queue => $queue->id, Name => 'Some' );
+    ok($val,$msg);
+}
+
 {
     my $t = RT::Template->new(RT->SystemUser);
     $t->Create(Name => "Foo", Queue => 1);

commit 112773d6b6840013b30616e00e2b66fbf1150670
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Apr 16 16:40:37 2012 +0400

    make sure we can not change template's queue
    
    moving templates between queues gonna be too
    complicated

diff --git a/lib/RT/Template.pm b/lib/RT/Template.pm
index 54c0959..44f4e4a 100644
--- a/lib/RT/Template.pm
+++ b/lib/RT/Template.pm
@@ -607,6 +607,17 @@ sub CurrentUserHasQueueRight {
     return ( $self->QueueObj->CurrentUserHasRight(@_) );
 }
 
+=head2 SetQueue
+
+Changing queue is not implemented.
+
+=cut
+
+sub SetQueue {
+    my $self = shift;
+    return ( undef, $self->loc('Changing queue is not implemented') );
+}
+
 =head2 SetName
 
 Change name of the template.
diff --git a/t/api/template.t b/t/api/template.t
index b25e023..ec86b57 100644
--- a/t/api/template.t
+++ b/t/api/template.t
@@ -9,6 +9,9 @@ use_ok('RT::Template');
 my $queue = RT::Test->load_or_create_queue( Name => 'Templates' );
 ok $queue && $queue->id, 'loaded or created queue';
 
+my $alt_queue = RT::Test->load_or_create_queue( Name => 'Alternative' );
+ok $alt_queue && $alt_queue->id, 'loaded or created queue';
+
 {
     my $template = RT::Template->new(RT->SystemUser);
     isa_ok($template, 'RT::Template');
@@ -86,6 +89,17 @@ note "can not change name to duplicate";
     ok($val,$msg);
 }
 
+note "changing queue of template is not implemented";
+{
+    clean_templates( Queue => $queue->id );
+    my $template = RT::Template->new( RT->SystemUser );
+    my ($val,$msg) = $template->Create( Queue => $queue->id, Name => 'Test' );
+    ok($val,$msg);
+
+    ($val,$msg) = $template->SetQueue( $alt_queue->id );
+    ok(!$val,$msg);
+}
+
 {
     my $t = RT::Template->new(RT->SystemUser);
     $t->Create(Name => "Foo", Queue => 1);

commit cd04cbaab991e3db368cc59624a049522a41d777
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Apr 16 17:37:19 2012 +0400

    save Name in Template column of scrips

diff --git a/lib/RT/Scrip.pm b/lib/RT/Scrip.pm
index 2ee4fec..a15e828 100644
--- a/lib/RT/Scrip.pm
+++ b/lib/RT/Scrip.pm
@@ -170,7 +170,7 @@ sub Create {
         unless $condition->Id;
 
     my ( $id, $msg ) = $self->SUPER::Create(
-        Template               => $template->Id,
+        Template               => $template->Name,
         ScripCondition         => $condition->id,
         ScripAction            => $action->Id,
         Description            => $args{'Description'},
@@ -807,7 +807,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;
diff --git a/lib/RT/ScripAction.pm b/lib/RT/ScripAction.pm
index c679a91..df3a4e4 100644
--- a/lib/RT/ScripAction.pm
+++ b/lib/RT/ScripAction.pm
@@ -197,7 +197,7 @@ sub TemplateObj {
     return undef unless $self->{Template};
     if ( !$self->{'TemplateObj'} ) {
         $self->{'TemplateObj'} = RT::Template->new( $self->CurrentUser );
-        $self->{'TemplateObj'}->LoadById( $self->{'Template'} );
+        $self->{'TemplateObj'}->Load( $self->{'Template'} );
 
         if ( ( $self->{'TemplateObj'}->__Value('Queue') == 0 )
             && $self->{'_TicketObj'} ) {

commit ce8886112d56e58109e98240d35cbbcf416b155f
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Sep 12 20:26:52 2012 +0400

    use $scrip->Template rather than ->TemplateObj->Name
    
    Template column in scrips now holds Name.
    
    Since we apply scrips to multiple queues TemplateObj
    becomes ambiguous, the same scrip may use different
    template object depending on queue. The name stays
    the same.
    
    Old variant should still work, but I think it's better
    to avoid using TemplateObj without context.

diff --git a/lib/RT/Scrip.pm b/lib/RT/Scrip.pm
index a15e828..0f69425 100644
--- a/lib/RT/Scrip.pm
+++ b/lib/RT/Scrip.pm
@@ -265,7 +265,7 @@ sub AddToObject {
         )
     ;
 
-    my $tname = $self->TemplateObj->Name;
+    my $tname = $self->Template;
     my $template = RT::Template->new( $self->CurrentUser );
     $template->LoadQueueTemplate( Queue => $queue? $queue->id : 0, Name => $tname );
     $template->LoadGlobalTemplate( $tname ) if $queue && !$template->id;
diff --git a/lib/RT/Shredder/Plugin/Summary.pm b/lib/RT/Shredder/Plugin/Summary.pm
index 95f6d8f..53f4473 100644
--- a/lib/RT/Shredder/Plugin/Summary.pm
+++ b/lib/RT/Shredder/Plugin/Summary.pm
@@ -142,7 +142,7 @@ sub WriteDownScrip {
     my $props = $self->_MakeHash( $args{'Object'} );
     $props->{'Action'} = $args{'Object'}->ActionObj->Name;
     $props->{'Condition'} = $args{'Object'}->ConditionObj->Name;
-    $props->{'Template'} = $args{'Object'}->TemplateObj->Name;
+    $props->{'Template'} = $args{'Object'}->Template;
     $props->{'Queue'} = $args{'Object'}->QueueObj->Name || 'global';
 
     return $self->_WriteDownHash( $args{'Object'}, $props );
diff --git a/share/html/Admin/Scrips/Elements/SelectTemplate b/share/html/Admin/Scrips/Elements/SelectTemplate
index 99fe82a..f61ce2a 100755
--- a/share/html/Admin/Scrips/Elements/SelectTemplate
+++ b/share/html/Admin/Scrips/Elements/SelectTemplate
@@ -63,7 +63,7 @@ $Default => undef
 <%INIT>
 
 my $current;
-$current = $Scrip->TemplateObj->Name if $Scrip;
+$current = $Scrip->Template if $Scrip;
 
 my $global = RT::Templates->new($session{'CurrentUser'});
 $global->LimitToGlobal;
diff --git a/share/html/Elements/RT__Scrip/ColumnMap b/share/html/Elements/RT__Scrip/ColumnMap
index 25348d2..b8feabd 100644
--- a/share/html/Elements/RT__Scrip/ColumnMap
+++ b/share/html/Elements/RT__Scrip/ColumnMap
@@ -78,14 +78,14 @@ my $COLUMN_MAP = {
     },
     Template => {
         title     => 'Template', # loc
-        value     => sub { return $_[0]->loc( $_[0]->TemplateObj->Name ) },
+        value     => sub { return $_[0]->loc( $_[0]->Template ) },
     },
     AutoDescription => {
         title     => 'Condition, Action and Template', # loc
         value     => sub { return $_[0]->loc( "[_1] [_2] with template [_3]",
             $_[0]->loc($_[0]->ConditionObj->Name),
             $_[0]->loc($_[0]->ActionObj->Name),
-            $_[0]->loc($_[0]->TemplateObj->Name),
+            $_[0]->loc($_[0]->Template),
         ) },
     },
     Description => {
diff --git a/share/html/Ticket/Elements/PreviewScrips b/share/html/Ticket/Elements/PreviewScrips
index 8a3364e..d8dc541 100755
--- a/share/html/Ticket/Elements/PreviewScrips
+++ b/share/html/Ticket/Elements/PreviewScrips
@@ -67,7 +67,7 @@ return unless $Object;
 %                  @{$Object->Scrips->Prepared};
 %     for my $scrip (@scrips) {
           <b><% $scrip->Description || loc('Scrip #[_1]',$scrip->id) %></b><br />
-          <&|/l, loc($scrip->ConditionObj->Name), loc($scrip->ActionObj->Name), loc($scrip->TemplateObj->Name)&>[_1] [_2] with template [_3]</&>
+          <&|/l, loc($scrip->ConditionObj->Name), loc($scrip->ActionObj->Name), loc($scrip->Template)&>[_1] [_2] with template [_3]</&>
           <br />
 %         for my $type (qw(To Cc Bcc)) {
 %             my @addresses =  $scrip->ActionObj->Action->$type();

commit 6ec6058680fc33e3bfdad489ae307f30926af27b
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Thu Sep 13 13:10:48 2012 +0400

    RT::Template->LoadByName method
    
    Loads queue's or global template

diff --git a/lib/RT/Scrip.pm b/lib/RT/Scrip.pm
index 0f69425..a47b621 100644
--- a/lib/RT/Scrip.pm
+++ b/lib/RT/Scrip.pm
@@ -267,8 +267,7 @@ sub AddToObject {
 
     my $tname = $self->Template;
     my $template = RT::Template->new( $self->CurrentUser );
-    $template->LoadQueueTemplate( Queue => $queue? $queue->id : 0, Name => $tname );
-    $template->LoadGlobalTemplate( $tname ) if $queue && !$template->id;
+    $template->LoadByName( Queue => $queue? $queue->id : 0, Name => $tname );
     unless ( $template->id ) {
         if ( $queue ) {
             return (0, $self->loc('No template [_1] in the queue', $tname));
diff --git a/lib/RT/Template.pm b/lib/RT/Template.pm
index 44f4e4a..d1b2faf 100644
--- a/lib/RT/Template.pm
+++ b/lib/RT/Template.pm
@@ -127,7 +127,7 @@ Load a template, either by number or by name.
 Note that loading templates by name using this method B<is
 ambiguous>. Several queues may have template with the same name
 and as well global template with the same name may exist.
-Use L</LoadGlobalTemplate> and/or L<LoadQueueTemplate> to get
+Use L</LoadByName>, L</LoadGlobalTemplate> or L<LoadQueueTemplate> to get
 precise result.
 
 =cut
@@ -143,6 +143,37 @@ sub Load {
     return $self->LoadById( $identifier );
 }
 
+=head2 LoadByName
+
+Takes Name and Queue arguments. Tries to load queue specific template
+first, then global. If Queue argument is omitted then global template
+is tried, not template with the name in any queue.
+
+=cut
+
+sub LoadByName {
+    my $self = shift;
+    my %args = (
+        Queue => undef,
+        Name  => undef,
+        @_
+    );
+    my $queue = $args{'Queue'};
+    if ( blessed $queue ) {
+        $queue = $queue->id;
+    } elsif ( $queue =~ /\D/ ) {
+        my $tmp = RT::Queue->new( $self->CurrentUser );
+        $tmp->Load($queue);
+        $queue = $tmp->id;
+    }
+
+    return $self->LoadGlobalTemplate( $args{'Name'} ) unless $queue;
+
+    $self->LoadQueueTemplate( Queue => $queue, Name => $args{'Name'} );
+    return $self->id if $self->id;
+    return $self->LoadGlobalTemplate( $args{'Name'} );
+}
+
 =head2 LoadGlobalTemplate NAME
 
 Load the global template with the name NAME
@@ -161,18 +192,7 @@ sub LoadGlobalTemplate {
 Loads the Queue template named NAME for Queue QUEUE.
 
 Note that this method doesn't load a global template with the same name
-if template in the queue doesn't exist. THe following code can be used:
-
-    $template->LoadQueueTemplate( Queue => $queue_id, Name => $template_name );
-    unless ( $template->id ) {
-        $template->LoadGlobalTemplate( $template_name );
-        unless ( $template->id ) {
-            # no template
-            ...
-        }
-    }
-    # ok, template either queue's or global
-    ...
+if template in the queue doesn't exist. Use L</LoadByName>.
 
 =cut
 

commit 070ad6c0cf41e0bc1be7558b4a27246f8bd22cd0
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Thu Sep 13 13:11:31 2012 +0400

    more details in an error message

diff --git a/lib/RT/Scrip.pm b/lib/RT/Scrip.pm
index a47b621..952a409 100644
--- a/lib/RT/Scrip.pm
+++ b/lib/RT/Scrip.pm
@@ -270,7 +270,8 @@ sub AddToObject {
     $template->LoadByName( Queue => $queue? $queue->id : 0, Name => $tname );
     unless ( $template->id ) {
         if ( $queue ) {
-            return (0, $self->loc('No template [_1] in the queue', $tname));
+            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));
         }

commit 4129e765f5f0ec7ea18c2b0a08b0f9c30c259e40
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Thu Sep 13 13:12:19 2012 +0400

    undef as default Template arg in Scrip->Create, not 0

diff --git a/lib/RT/Scrip.pm b/lib/RT/Scrip.pm
index 952a409..9577d7b 100644
--- a/lib/RT/Scrip.pm
+++ b/lib/RT/Scrip.pm
@@ -107,7 +107,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',

commit 002fd2b4e53113181681f59d3fcff31fd7831b4d
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Nov 29 19:44:12 2011 +0400

    IsEmpty column map for templates

diff --git a/share/html/Elements/RT__Template/ColumnMap b/share/html/Elements/RT__Template/ColumnMap
index d9d55cf..b983d31 100644
--- a/share/html/Elements/RT__Template/ColumnMap
+++ b/share/html/Elements/RT__Template/ColumnMap
@@ -78,6 +78,10 @@ my $COLUMN_MAP = {
         title     => 'Queue', # loc
         value     => sub { $_[0]->Queue },
     },
+    IsEmpty => {
+        title     => 'Empty', # loc
+        value     => sub { $_[0]->IsEmpty? $_[0]->loc('Yes') : $_[0]->loc('No') },
+    },
 };
 
 </%ONCE>

commit c6e7341d649f1e9c8c1cc4a6e6e0ef2e42af7f16
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Nov 29 19:47:40 2011 +0400

    $tmpl->UsedBy, $scrips->LimitByTemplate methods and UsedBy ColumnMap
    
    $scrips->LimitByTemplate - limits to scrips that
    really use particular template, accounts that global
    templates can be overriden.
    
    $tmpl->UsedBy - sugar for above from template side.
    
    UsedBy column map for templates that shows links to
    scrips.

diff --git a/lib/RT/Scrips.pm b/lib/RT/Scrips.pm
index 94ebf41..a9925fd 100644
--- a/lib/RT/Scrips.pm
+++ b/lib/RT/Scrips.pm
@@ -159,6 +159,85 @@ sub LimitToEnabled {
     );
 }
 
+=head2 LimitByTemplate
+
+Takes a L<RT::Template> object and limits scrips to those that
+use the template.
+
+=cut
+
+sub LimitByTemplate {
+    my $self = shift;
+    my $template = shift;
+
+    $self->Limit( FIELD => 'Template', VALUE => $template->Name );
+
+    if ( $template->Queue ) {
+        # if template is local then we are interested in global and
+        # queue specific scrips
+        $self->LimitToQueue( $template->Queue );
+        $self->LimitToGlobal;
+    }
+    else { # template is global
+
+        # if every queue has a custom version then there
+        # is no scrip that uses the template
+        {
+            my $queues = RT::Queues->new( RT->SystemUser );
+            my $alias = $queues->Join(
+                TYPE   => 'LEFT',
+                ALIAS1 => 'main',
+                FIELD1 => 'id',
+                TABLE2 => 'Templates',
+                FIELD2 => 'Queue',
+            );
+            $queues->Limit(
+                LEFTJOIN   => $alias,
+                ALIAS      => $alias,
+                FIELD      => 'Name',
+                VALUE      => $template->Name,
+            );
+            $queues->Limit(
+                ALIAS      => $alias,
+                FIELD      => 'id',
+                OPERATOR   => 'IS',
+                VALUE      => 'NULL',
+            );
+            return $self->Limit( FIELD => 'id', VALUE => 0 )
+                unless $queues->Count;
+        }
+
+        # otherwise it's either a global scrip or application to
+        # a queue with custom version of the template.
+        my $os_alias = RT::ObjectScrips->new( $self->CurrentUser )
+            ->JoinTargetToThis( $self );
+        my $tmpl_alias = $self->Join(
+            TYPE   => 'LEFT',
+            ALIAS1 => $os_alias,
+            FIELD1 => 'ObjectId',
+            TABLE2 => 'Templates',
+            FIELD2 => 'Queue',
+        );
+        $self->Limit(
+            LEFTJOIN => $tmpl_alias, ALIAS => $tmpl_alias, FIELD => 'Name', VALUE => $template->Name,
+        );
+        $self->Limit(
+            LEFTJOIN => $tmpl_alias, ALIAS => $tmpl_alias, FIELD => 'Queue', OPERATOR => '!=', VALUE => 0,
+        );
+
+        $self->_OpenParen('UsedBy');
+        $self->Limit( SUBCLAUSE => 'UsedBy', ALIAS => $os_alias, FIELD => 'ObjectId', VALUE => 0 );
+        $self->Limit(
+            SUBCLAUSE => 'UsedBy',
+            ALIAS => $tmpl_alias,
+            FIELD => 'id',
+            OPERATOR => 'IS',
+            VALUE => 'NULL',
+        );
+        $self->_CloseParen('UsedBy');
+    }
+}
+
 sub ApplySortOrder {
     my $self = shift;
     my $order = shift || 'ASC';
diff --git a/lib/RT/Template.pm b/lib/RT/Template.pm
index d1b2faf..e18e6d7 100644
--- a/lib/RT/Template.pm
+++ b/lib/RT/Template.pm
@@ -290,6 +290,21 @@ sub Delete {
     return ( $self->SUPER::Delete(@_) );
 }
 
+=head2 UsedBy
+
+Returns L<RT::Scrips> limitted to scrips that use this template. Takes
+into account that template can be overriden in a queue.
+
+=cut
+
+sub UsedBy {
+    my $self = shift;
+
+    my $scrips = RT::Scrips->new( $self->CurrentUser );
+    $scrips->LimitByTemplate( $self );
+    return $scrips;
+}
+
 =head2 IsEmpty
 
 Returns true value if content of the template is empty, otherwise
diff --git a/share/html/Elements/RT__Template/ColumnMap b/share/html/Elements/RT__Template/ColumnMap
index b983d31..6c821a6 100644
--- a/share/html/Elements/RT__Template/ColumnMap
+++ b/share/html/Elements/RT__Template/ColumnMap
@@ -82,6 +82,20 @@ my $COLUMN_MAP = {
         title     => 'Empty', # loc
         value     => sub { $_[0]->IsEmpty? $_[0]->loc('Yes') : $_[0]->loc('No') },
     },
+    UsedBy => {
+        title     => 'Used by scrips', # loc
+        value     => sub {
+            my @res;
+            my $scrips = $_[0]->UsedBy;
+            while ( my $scrip = $scrips->Next ) {
+                push @res, ', ' if @res;
+                push @res, \'<a href="', RT->Config->Get('WebPath'), '/Admin/Scrips/Modify.html';
+                push @res, '?id='. $scrip->id;
+                push @res, \'" title="', $scrip->Description, \'">', $scrip->id, \'</a>';
+            }
+            return @res;
+        },
+    },
 };
 
 </%ONCE>

commit 8db8d63337be4200ec330d3678fac56373cd289a
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Nov 29 19:48:09 2011 +0400

    show UsedBy and IsEmpty columns in templates AdminUI

diff --git a/etc/RT_Config.pm.in b/etc/RT_Config.pm.in
index d8e8780..382f6d0 100755
--- a/etc/RT_Config.pm.in
+++ b/etc/RT_Config.pm.in
@@ -2473,7 +2473,7 @@ Set(%AdminSearchResultFormat,
     Templates =>
         q{'<a href="__WebPath__/__WebRequestPathDir__/Template.html?Queue=__QueueId__&Template=__id__">__id__</a>/TITLE:#'}
         .q{,'<a href="__WebPath__/__WebRequestPathDir__/Template.html?Queue=__QueueId__&Template=__id__">__Name__</a>/TITLE:Name'}
-        .q{,'__Description__'},
+        .q{,'__Description__','__UsedBy__','__IsEmpty__'},
     Classes =>
         q{ '<a href="__WebPath__/Admin/Articles/Classes/Modify.html?id=__id__">__id__</a>/TITLE:#'}
         .q{,'<a href="__WebPath__/Admin/Articles/Classes/Modify.html?id=__id__">__Name__</a>/TITLE:Name'}

commit 0edea32188c662d3e54f5eecf4185d885fabe079
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Thu Sep 13 13:41:21 2012 +0400

    tidy, no code change, tiny doc changes
    
    retab, indent, drop useless space only and empty lines,
    drop some comments, several very small doc changes

diff --git a/lib/RT/ScripAction.pm b/lib/RT/ScripAction.pm
index df3a4e4..84afd37 100644
--- a/lib/RT/ScripAction.pm
+++ b/lib/RT/ScripAction.pm
@@ -48,21 +48,13 @@
 
 =head1 NAME
 
-  RT::ScripAction - RT Action object
-
-=head1 SYNOPSIS
-
-  use RT::ScripAction;
-
+RT::ScripAction - RT Action object
 
 =head1 DESCRIPTION
 
-This module should never be called directly by client code. it's an internal module which
-should only be accessed through exported APIs in other modules.
-
-
-
-=head1 METHODS
+This module should never be called directly by client code. it's an
+internal module which should only be accessed through exported APIs
+in other modules.
 
 =cut
 
@@ -76,29 +68,29 @@ use base 'RT::Record';
 
 sub Table {'ScripActions'}
 
-
-
 use RT::Template;
 
 sub _Accessible  {
     my $self = shift;
-    my %Cols = ( Name  => 'read',
-		 Description => 'read',
-		 ExecModule  => 'read',
-		 Argument  => 'read',
-		 Creator => 'read/auto',
-		 Created => 'read/auto',
-		 LastUpdatedBy => 'read/auto',
-		 LastUpdated => 'read/auto'
-       );
+    my %Cols = (
+        Name  => 'read',
+        Description => 'read',
+        ExecModule  => 'read',
+        Argument  => 'read',
+        Creator => 'read/auto',
+        Created => 'read/auto',
+        LastUpdatedBy => 'read/auto',
+        LastUpdated => 'read/auto'
+    );
     return($self->SUPER::_Accessible(@_, %Cols));
 }
 
 
+=head1 METHODS
+
 =head2 Create
 
-Takes a hash. Creates a new Action entry.  should be better
-documented.
+Takes a hash. Creates a new Action entry.
 
 =cut
 
@@ -110,7 +102,6 @@ sub Create  {
 
 sub Delete  {
     my $self = shift;
-    
     return (0, "ScripAction->Delete not implemented");
 }
 
@@ -126,25 +117,23 @@ Returns: Id, Error Message
 sub Load  {
     my $self = shift;
     my $identifier = shift;
-    
+
     if (!$identifier) {
-	return (0, $self->loc('Input error'));
-    }	    
-    
+        return (0, $self->loc('Input error'));
+    }
+
     my ($ok, $msg);
     if ($identifier !~ /\D/) {
-	($ok, $msg) = $self->SUPER::Load($identifier);
+        ($ok, $msg) = $self->SUPER::Load($identifier);
     }
     else {
-	($ok, $msg) = $self->LoadByCol('Name', $identifier);
-	
+        ($ok, $msg) = $self->LoadByCol('Name', $identifier);
     }
 
     if (@_) {
-	# Set the template Id to the passed in template    
-	my $template = shift;
-	
-	$self->{'Template'} = $template;
+        # Set the template Id to the passed in template
+        my $template = shift;
+        $self->{'Template'} = $template;
     }
 
     return ($ok, $msg);
@@ -153,33 +142,36 @@ sub Load  {
 
 =head2 LoadAction HASH
 
-  Takes a hash consisting of TicketObj and TransactionObj.  Loads an RT::Action:: module.
+Takes a hash consisting of TicketObj and TransactionObj.  Loads an RT::Action:: module.
 
 =cut
 
 sub LoadAction  {
     my $self = shift;
-    my %args = ( TransactionObj => undef,
-		 TicketObj => undef,
-		 @_ );
+    my %args = (
+        TransactionObj => undef,
+        TicketObj => undef,
+        ScripObj => undef,
+        @_
+    );
 
     $self->{_TicketObj} = $args{TicketObj};
-    
-    #TODO: Put this in an eval  
+
     $self->ExecModule =~ /^(\w+)$/;
     my $module = $1;
     my $type = "RT::Action::". $module;
- 
+
     eval "require $type" || die "Require of $type failed.\n$@\n";
-    
-    $self->{'Action'}  = $type->new ( Argument => $self->Argument,
-                                      CurrentUser => $self->CurrentUser,
-                                      ScripActionObj => $self, 
-                                      ScripObj => $args{'ScripObj'},
-                                      TemplateObj => $self->TemplateObj,
-                                      TicketObj => $args{'TicketObj'},
-                                      TransactionObj => $args{'TransactionObj'},
-				    );
+
+    return $self->{'Action'} = $type->new(
+        Argument => $self->Argument,
+        CurrentUser => $self->CurrentUser,
+        ScripActionObj => $self,
+        ScripObj => $args{'ScripObj'},
+        TemplateObj => $self->TemplateObj,
+        TicketObj => $args{'TicketObj'},
+        TransactionObj => $args{'TransactionObj'},
+    );
 }
 
 
@@ -187,9 +179,6 @@ sub LoadAction  {
 
 Return this action's template object
 
-TODO: Why are we not using the Scrip's template object?
-
-
 =cut
 
 sub TemplateObj {
@@ -217,27 +206,20 @@ sub TemplateObj {
     return ( $self->{'TemplateObj'} );
 }
 
-# The following methods call the action object
-
-
 sub Prepare  {
     my $self = shift;
     $self->{_Message_ID} = 0;
-    return ($self->Action->Prepare());
-  
+    return $self->Action->Prepare();
 }
 
 sub Commit  {
     my $self = shift;
-    return($self->Action->Commit());
-    
-    
+    return $self->Action->Commit();
 }
 
 sub Describe  {
     my $self = shift;
-    return ($self->Action->Describe());
-    
+    return $self->Action->Describe();
 }
 
 =head2 Action
@@ -248,7 +230,7 @@ Return the actual RT::Action object for this scrip.
 
 sub Action {
     my $self = shift;
-    return ($self->{'Action'});
+    return $self->{'Action'};
 }
 
 sub DESTROY {
@@ -258,15 +240,6 @@ sub DESTROY {
     $self->{'TemplateObj'} = undef;
 }
 
-=head2 TODO
-
-Between this, RT::Scrip and RT::Action::*, we need to be able to get rid of a 
-class. This just reeks of too much complexity -- jesse
-
-=cut
-
-
-
 
 =head2 id
 
@@ -274,139 +247,98 @@ Returns the current value of id.
 (In the database, id is stored as int(11).)
 
 
-=cut
-
-
 =head2 Name
 
 Returns the current value of Name.
 (In the database, Name is stored as varchar(200).)
 
-
-
 =head2 SetName VALUE
 
-
 Set Name to VALUE.
 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
 (In the database, Name will be stored as a varchar(200).)
 
 
-=cut
-
-
 =head2 Description
 
 Returns the current value of Description.
 (In the database, Description is stored as varchar(255).)
 
-
-
 =head2 SetDescription VALUE
 
-
 Set Description to VALUE.
 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
 (In the database, Description will be stored as a varchar(255).)
 
 
-=cut
-
-
 =head2 ExecModule
 
 Returns the current value of ExecModule.
 (In the database, ExecModule is stored as varchar(60).)
 
-
-
 =head2 SetExecModule VALUE
 
-
 Set ExecModule to VALUE.
 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
 (In the database, ExecModule will be stored as a varchar(60).)
 
 
-=cut
-
-
 =head2 Argument
 
 Returns the current value of Argument.
 (In the database, Argument is stored as varbinary(255).)
 
-
-
 =head2 SetArgument VALUE
 
-
 Set Argument to VALUE.
 Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
 (In the database, Argument will be stored as a varbinary(255).)
 
 
-=cut
-
-
 =head2 Creator
 
 Returns the current value of Creator.
 (In the database, Creator is stored as int(11).)
 
-
-=cut
-
-
 =head2 Created
 
 Returns the current value of Created.
 (In the database, Created is stored as datetime.)
 
-
-=cut
-
-
 =head2 LastUpdatedBy
 
 Returns the current value of LastUpdatedBy.
 (In the database, LastUpdatedBy is stored as int(11).)
 
-
-=cut
-
-
 =head2 LastUpdated
 
 Returns the current value of LastUpdated.
 (In the database, LastUpdated is stored as datetime.)
 
-
 =cut
 
 
-
 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 => ''},
         Name =>
-		{read => 1, write => 1, sql_type => 12, length => 200,  is_blob => 0,  is_numeric => 0,  type => 'varchar(200)', default => ''},
+                {read => 1, write => 1, sql_type => 12, length => 200,  is_blob => 0,  is_numeric => 0,  type => 'varchar(200)', 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 => ''},
         ExecModule =>
-		{read => 1, write => 1, sql_type => 12, length => 60,  is_blob => 0,  is_numeric => 0,  type => 'varchar(60)', default => ''},
+                {read => 1, write => 1, sql_type => 12, length => 60,  is_blob => 0,  is_numeric => 0,  type => 'varchar(60)', default => ''},
         Argument =>
-		{read => 1, write => 1, sql_type => 12, length => 255,  is_blob => 0,  is_numeric => 0,  type => 'varbinary(255)', default => ''},
+                {read => 1, write => 1, sql_type => 12, length => 255,  is_blob => 0,  is_numeric => 0,  type => 'varbinary(255)', default => ''},
         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 => ''},
 
  }
 };

commit 1ca93fd4a98ca251ca772916c6ef078355f3b5a9
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Thu Sep 13 13:49:51 2012 +0400

    pass arguments further to Action

diff --git a/lib/RT/ScripAction.pm b/lib/RT/ScripAction.pm
index 84afd37..2123da6 100644
--- a/lib/RT/ScripAction.pm
+++ b/lib/RT/ScripAction.pm
@@ -209,17 +209,17 @@ sub TemplateObj {
 sub Prepare  {
     my $self = shift;
     $self->{_Message_ID} = 0;
-    return $self->Action->Prepare();
+    return $self->Action->Prepare( @_ );
 }
 
 sub Commit  {
     my $self = shift;
-    return $self->Action->Commit();
+    return $self->Action->Commit( @_ );
 }
 
 sub Describe  {
     my $self = shift;
-    return $self->Action->Describe();
+    return $self->Action->Describe( @_ );
 }
 
 =head2 Action

commit f3f32c321a916d4bcdf24fdf81da54d22e59fbf2
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Thu Sep 13 13:51:57 2012 +0400

    these DESTROY methods are useless
    
    It looks like an atempt to fix memory leak, but really
    it's impossible to fix circular references by sticking
    in custom DESTROY functions around. No object is
    destroyed in a cycle.

diff --git a/lib/RT/Action.pm b/lib/RT/Action.pm
index f05c191..2aa7439 100644
--- a/lib/RT/Action.pm
+++ b/lib/RT/Action.pm
@@ -179,19 +179,6 @@ sub IsApplicable  {
   return(undef);
 }
 
-sub DESTROY {
-    my $self = shift;
-
-    # We need to clean up all the references that might maybe get
-    # oddly circular
-    $self->{'ScripActionObj'} = undef;
-    $self->{'ScripObj'} = undef;
-    $self->{'TemplateObj'} =undef
-    $self->{'TicketObj'} = undef;
-    $self->{'TransactionObj'} = undef;
-}
-
-
 RT::Base->_ImportOverlays();
 
 1;
diff --git a/lib/RT/ScripAction.pm b/lib/RT/ScripAction.pm
index 2123da6..ad6ece2 100644
--- a/lib/RT/ScripAction.pm
+++ b/lib/RT/ScripAction.pm
@@ -233,14 +233,6 @@ sub Action {
     return $self->{'Action'};
 }
 
-sub DESTROY {
-    my $self=shift;
-    $self->{'_TicketObj'} = undef;
-    $self->{'Action'} = undef;
-    $self->{'TemplateObj'} = undef;
-}
-
-
 =head2 id
 
 Returns the current value of id.
diff --git a/lib/RT/ScripCondition.pm b/lib/RT/ScripCondition.pm
index 3f24f2e..cafc6e2 100644
--- a/lib/RT/ScripCondition.pm
+++ b/lib/RT/ScripCondition.pm
@@ -209,16 +209,6 @@ sub IsApplicable  {
 }
 
 
-sub DESTROY {
-    my $self=shift;
-    $self->{'Condition'} = undef;
-}
-
-
-
-
-
-
 
 =head2 id
 

commit b80774ffd1116d72953953415cd17cfabee3503b
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Thu Sep 13 17:01:17 2012 +0400

    drop RT::Action->IsApplicable
    
    This was never documented, never used, no code calls it.

diff --git a/lib/RT/Action.pm b/lib/RT/Action.pm
index 2aa7439..afe993a 100644
--- a/lib/RT/Action.pm
+++ b/lib/RT/Action.pm
@@ -172,13 +172,6 @@ sub Prepare  {
 }
 
 
-#If this rule applies to this transaction, return true.
-
-sub IsApplicable  {
-  my $self = shift;
-  return(undef);
-}
-
 RT::Base->_ImportOverlays();
 
 1;

commit 73afebfcb451939b4c82c8a2564aaff26943342e
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Thu Sep 13 17:11:57 2012 +0400

    we don't need to set $self->{'table'}
    
    Since we use Table class methods that return constant table names,
    we don't need to set $self->{'table'}

diff --git a/lib/RT/ScripCondition.pm b/lib/RT/ScripCondition.pm
index cafc6e2..92b726f 100644
--- a/lib/RT/ScripCondition.pm
+++ b/lib/RT/ScripCondition.pm
@@ -78,13 +78,6 @@ use base 'RT::Record';
 sub Table {'ScripConditions'}
 
 
-
-sub _Init  {
-    my $self = shift; 
-    $self->{'table'} = "ScripConditions";
-    return ($self->SUPER::_Init(@_));
-}
-
 sub _Accessible  {
     my $self = shift;
     my %Cols = ( Name  => 'read',

commit 07c50cd46c8b4a1920b49f9806da5e06fac6071e
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Fri Sep 14 21:39:19 2012 +0400

    upgrade step for Template column in Scrips table
    
    Convert type of the column in schema.* files and
    in content file turn number into Name.

diff --git a/etc/upgrade/4.1.3/content b/etc/upgrade/4.1.3/content
new file mode 100644
index 0000000..8e907ee
--- /dev/null
+++ b/etc/upgrade/4.1.3/content
@@ -0,0 +1,33 @@
+use strict; use warnings;
+
+our @Initial = (
+    # upgrade Template from id to name
+    sub {
+        require RT::Scrips;
+        my $scrips = RT::Scrips->new( RT->SystemUser );
+        $scrips->UnLimit;
+        while ( my $scrip = $scrips->Next ) {
+            my $id = $scrip->Template;
+            if ( $id =~ /\D/ ) {
+                $RT::Logger->info('Template column for scrip #'. $scrip->id .' already contains characters');
+                next;
+            }
+
+            my $name;
+
+            my $template = RT::Template->new( RT->SystemUser );
+            $template->Load( $id );
+            unless ( $template->id ) {
+                $RT::Logger->error("Scrip #". $scrip->id ." has template set to #$id, but it's not in DB, setting it 'Blank'");
+                $name = 'Blank';
+            } else {
+                $name = $template->Name;
+            }
+
+            my ($status, $msg) = $scrip->_Set( Field => 'Template', Value => $name );
+            unless ( $status ) {
+                $RT::Logger->error("Couldn't set template: $msg");
+            }
+        }
+    },
+);
diff --git a/etc/upgrade/4.1.3/schema.Oracle b/etc/upgrade/4.1.3/schema.Oracle
new file mode 100644
index 0000000..b0b4d4c
--- /dev/null
+++ b/etc/upgrade/4.1.3/schema.Oracle
@@ -0,0 +1,5 @@
+# Template column
+ALTER TABLE Scrips RENAME COLUMN Template TO TemplateOld;
+ALTER TABLE Scrips ADD COLUMN Template VARCHAR2(200) NOT NULL;
+UPDATE TABLE Scrips SET Template = CAST(TemplateOld AS varchar2);
+ALTER TABLE Scrips DROP COLUMN TemplateOld;
\ No newline at end of file
diff --git a/etc/upgrade/4.1.3/schema.Pg b/etc/upgrade/4.1.3/schema.Pg
new file mode 100644
index 0000000..3a12d4d
--- /dev/null
+++ b/etc/upgrade/4.1.3/schema.Pg
@@ -0,0 +1,2 @@
+# Template colum
+ALTER TABLE Scrips ALTER COLUMN Template TYPE varchar(200);
diff --git a/etc/upgrade/4.1.3/schema.mysql b/etc/upgrade/4.1.3/schema.mysql
new file mode 100644
index 0000000..d35d730
--- /dev/null
+++ b/etc/upgrade/4.1.3/schema.mysql
@@ -0,0 +1,2 @@
+# Template column
+ALTER TABLE Scrips CHANGE Template Template varchar(200) NOT NULL;

commit 62794cdb3f34ebb256d734ad547948f27353b731
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Fri Sep 14 23:27:03 2012 +0400

    change how we pass template to RT::Action::*
    
    New way is just passing correct Template object to LoadAction
    module along with other things RT::Actions have access to.
    
    Old way was to pass template name/id as second argument to
    ScripAction->Load (deprecated), then call ScripAction->TemplateObj
    method (deprecated) and call it only from LoadAction as it's only
    place where we have Ticket to get proper queue specific template.
    
    Old code is still there, but it gives warnings.

diff --git a/lib/RT/Rule.pm b/lib/RT/Rule.pm
index e2cd8e0..3642319 100644
--- a/lib/RT/Rule.pm
+++ b/lib/RT/Rule.pm
@@ -103,11 +103,10 @@ sub RunScripAction {
 
     my $action = $ScripAction->LoadAction( TransactionObj => $self->TransactionObj,
                                            TicketObj => $self->TicketObj,
+                                           TemplateObj => $template,
                                            %args,
                                        );
 
-    # XXX: fix template to allow additional arguments to be passed from here
-    $action->{'TemplateObj'} = $template;
     $action->{'ScripObj'} = RT::Scrip->new($self->CurrentUser); # Stub. sendemail action really wants a scripobj available
     $action->Prepare or return;
     $action->Commit;
diff --git a/lib/RT/Scrip.pm b/lib/RT/Scrip.pm
index 9577d7b..df21cac 100644
--- a/lib/RT/Scrip.pm
+++ b/lib/RT/Scrip.pm
@@ -315,12 +315,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'} );
 }
@@ -364,13 +360,11 @@ Retuns an RT::Template object with this Scrip\'s Template
 
 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
@@ -575,9 +569,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();
diff --git a/lib/RT/ScripAction.pm b/lib/RT/ScripAction.pm
index ad6ece2..c401d2d 100644
--- a/lib/RT/ScripAction.pm
+++ b/lib/RT/ScripAction.pm
@@ -131,9 +131,8 @@ sub Load  {
     }
 
     if (@_) {
-        # Set the template Id to the passed in template
-        my $template = shift;
-        $self->{'Template'} = $template;
+        $RT::Logger->warning("Passing in Template as second argument is deprecated");
+        $self->{'Template'} = shift;
     }
 
     return ($ok, $msg);
@@ -155,7 +154,14 @@ sub LoadAction  {
         @_
     );
 
-    $self->{_TicketObj} = $args{TicketObj};
+    # XXX: this whole block goes with TemplateObj method
+    unless ( @_ && exists $args{'TemplateObj'} ) {
+        local $self->{_TicketObj} = $args{TicketObj};
+        $args{'TemplateObj'} = $self->TemplateObj;
+    }
+    else {
+        $self->{'TemplateObj'} = $args{'TemplateObj'};
+    }
 
     $self->ExecModule =~ /^(\w+)$/;
     my $module = $1;
@@ -164,13 +170,10 @@ sub LoadAction  {
     eval "require $type" || die "Require of $type failed.\n$@\n";
 
     return $self->{'Action'} = $type->new(
-        Argument => $self->Argument,
-        CurrentUser => $self->CurrentUser,
+        %args,
+        Argument       => $self->Argument,
+        CurrentUser    => $self->CurrentUser,
         ScripActionObj => $self,
-        ScripObj => $args{'ScripObj'},
-        TemplateObj => $self->TemplateObj,
-        TicketObj => $args{'TicketObj'},
-        TransactionObj => $args{'TransactionObj'},
     );
 }
 
@@ -183,6 +186,8 @@ Return this action's template object
 
 sub TemplateObj {
     my $self = shift;
+    Carp::carp(__PACKAGE__."::TemplateObj is deprecated");
+
     return undef unless $self->{Template};
     if ( !$self->{'TemplateObj'} ) {
         $self->{'TemplateObj'} = RT::Template->new( $self->CurrentUser );

commit e70605073384873fb60449c90e18d6eb546ad2db
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Sep 19 01:29:04 2012 +0400

    check template harder in RT::Scrip->Create

diff --git a/lib/RT/Scrip.pm b/lib/RT/Scrip.pm
index df21cac..06ebe4c 100644
--- a/lib/RT/Scrip.pm
+++ b/lib/RT/Scrip.pm
@@ -158,9 +158,22 @@ sub Create {
     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'};
+    }
 
     return ( 0, $self->loc("Condition is mandatory argument") )
         unless $args{'ScripCondition'};
diff --git a/t/api/scrip.t b/t/api/scrip.t
index 7c9bf4a..4f94452 100644
--- a/t/api/scrip.t
+++ b/t/api/scrip.t
@@ -1,7 +1,7 @@
 
 use strict;
 use warnings;
-use RT::Test tests => 70;
+use RT::Test tests => 76;
 
 my $queue = RT::Test->load_or_create_queue( Name => 'General' );
 ok $queue && $queue->id, 'loaded or created queue';
@@ -113,22 +113,67 @@ note 'modify properties of a scrip';
 my $queue_B = RT::Test->load_or_create_queue( Name => 'B' );
 ok $queue_B && $queue_B->id, 'loaded or created queue';
 
-note 'check applications vs. templates';
+note 'check creation errors vs. templates';
 {
+    my $scrip = RT::Scrip->new(RT->SystemUser);
+    my ($status, $msg) = $scrip->Create(
+        Queue          => $queue->id,
+        ScripAction    => 'User Defined',
+        ScripCondition => 'User Defined',
+        Template       => 'not exist',
+    );
+    ok(!$status, "couldn't create scrip, not existing template");
+
+    ($status, $msg) = $scrip->Create(
+        ScripAction    => 'User Defined',
+        ScripCondition => 'User Defined',
+        Template       => 'not exist',
+    );
+    ok(!$status, "couldn't create scrip, not existing template");
+
+    ($status, $msg) = $scrip->Create(
+        Queue          => $queue->id,
+        ScripAction    => 'User Defined',
+        ScripCondition => 'User Defined',
+        Template       => 54321,
+    );
+    ok(!$status, "couldn't create scrip, not existing template");
+
+    ($status, $msg) = $scrip->Create(
+        ScripAction    => 'User Defined',
+        ScripCondition => 'User Defined',
+        Template       => 54321,
+    );
+    ok(!$status, "couldn't create scrip, not existing template");
+
     my $template = RT::Template->new( RT->SystemUser );
-    my ($status, $msg) = $template->Create( Queue => $queue->id, Name => 'foo' );
+    ($status, $msg) = $template->Create( Queue => $queue->id, Name => 'bar' );
     ok $status, 'created a template';
 
-    my $scrip = RT::Scrip->new(RT->SystemUser);
     ($status, $msg) = $scrip->Create(
-        Queue          => $queue->Id,
         ScripAction    => 'User Defined',
         ScripCondition => 'User Defined',
-        Template       => 'bar',
+        Template       => $template->id,
     );
-    ok(!$status, "couldn't create scrip, incorrect template");
+    ok(!$status, "couldn't create scrip, wrong template");
 
     ($status, $msg) = $scrip->Create(
+        Queue          => $queue_B->id,
+        ScripAction    => 'User Defined',
+        ScripCondition => 'User Defined',
+        Template       => $template->id,
+    );
+    ok(!$status, "couldn't create scrip, wrong template");
+}
+
+note 'check applications vs. templates';
+{
+    my $template = RT::Template->new( RT->SystemUser );
+    my ($status, $msg) = $template->Create( Queue => $queue->id, Name => 'foo' );
+    ok $status, 'created a template';
+
+    my $scrip = RT::Scrip->new(RT->SystemUser);
+    ($status, $msg) = $scrip->Create(
         Queue          => $queue->Id,
         ScripAction    => 'User Defined',
         ScripCondition => 'User Defined',

commit 7ea55a83a285aa86e8d1ecc946a82c648d083393
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Sep 19 17:57:00 2012 +0400

    test Templates in scrips' admin UI

diff --git a/t/web/scrips.t b/t/web/scrips.t
index 7b386c5..0bea8a0 100644
--- a/t/web/scrips.t
+++ b/t/web/scrips.t
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use RT::Test tests => 54;
+use RT::Test tests => 70;
 
 RT->Config->Set( UseTransactionBatch => 1 );
 
@@ -13,6 +13,12 @@ RT->Config->Set( UseTransactionBatch => 1 );
 # Test templates?
 # Test cleanup scripts.
 
+my $queue_g = RT::Test->load_or_create_queue( Name => 'General' );
+ok $queue_g && $queue_g->id, 'loaded or created queue';
+
+my $queue_r = RT::Test->load_or_create_queue( Name => 'Regression' );
+ok $queue_r && $queue_r->id, 'loaded or created queue';
+
 my ($baseurl, $m) = RT::Test->started_ok;
 ok $m->login, "logged in";
 
@@ -61,6 +67,7 @@ sub prepare_code_with_value {
             'CustomPrepareCode' => $prepare_code,
         );
         $m->click('Create');
+        $m->content_like(qr{Scrip Created});
     }
 
     my $ticket_obj = RT::Test->create_ticket(
@@ -153,11 +160,67 @@ note "check basics in scrip's admin interface";
     $m->content_contains("The new value has been set.");
 }
 
-note "apply scrip in different stage to different queues";
+note "check templates in scrip's admin interface";
 {
-    my $queue = RT::Test->load_or_create_queue( Name => 'Regression' );
-    ok $queue && $queue->id, 'loaded or created queue';
+    my $template = RT::Template->new( RT->SystemUser );
+    my ($status, $msg) = $template->Create( Queue => $queue_g->id, Name => 'foo' );
+    ok $status, 'created a template';
+
+    my @default = (
+          '',
+          'Admin Comment',
+          'Admin Correspondence',
+          'Autoreply',
+          'Blank',
+          'Correspondence',
+          'Email Digest',
+          'Error to RT owner: public key',
+          'Error: bad GnuPG data',
+          'Error: Missing dashboard',
+          'Error: no private key',
+          'Error: public key',
+          'Forward',
+          'Forward Ticket',
+          'PasswordChange',
+          'Resolved',
+          'Status Change',
+          'Transaction'
+    );
+
+    $m->follow_link_ok( { id => 'tools-config-global-scrips-create' } );
+    ok $m->form_name('CreateScrip');
+    my @templates = ($m->find_all_inputs( type => 'option', name => 'Template' ))[0]
+        ->possible_values;
+    is_deeply(\@templates, \@default);
+
+    $m->follow_link_ok( { id => 'tools-config-queues' } );
+    $m->follow_link_ok( { text => 'General' } );
+    $m->follow_link_ok( { id => 'page-scrips-create' } );
+
+    ok $m->form_name('CreateScrip');
+    my @templates = ($m->find_all_inputs( type => 'option', name => 'Template' ))[0]
+        ->possible_values;
+    is_deeply([sort @templates], [sort @default, 'foo']);
 
+note "make sure we can not apply scrip to queue without required template";
+    $m->field('Description' => 'test template');
+    $m->select('ScripCondition' => 'On Close');
+    $m->select('ScripAction' => 'Notify Ccs');
+    $m->select('Template' => 'foo');
+    $m->click('Create');
+    $m->content_contains("Scrip Created");
+
+    $m->follow_link_ok( { id => 'page-applies-to' } );
+    my ($id) = ($m->content =~ /Modify associated objects for scrip #(\d+)/);
+    $m->form_name('AddRemoveScrip');
+    $m->tick('AddScrip-'.$id, $queue_r->id);
+    $m->click('Update');
+
+    $m->content_like(qr{No template foo in queue Regression or global});
+}
+
+note "apply scrip in different stage to different queues";
+{
     $m->follow_link_ok( { id => 'tools-config-queues' } );
     $m->follow_link_ok( { text => 'General' } );
     $m->follow_link_ok( { id => 'page-scrips-create'});
@@ -176,7 +239,7 @@ note "apply scrip in different stage to different queues";
     $m->follow_link_ok({ text => 'Applies to' });
     ok $m->form_name('AddRemoveScrip');
     $m->select('Stage' => 'Batch');
-    $m->tick( "AddScrip-$sid" => $queue->id );
+    $m->tick( "AddScrip-$sid" => $queue_r->id );
     $m->click('Update');
     $m->content_contains("Object created");
 

commit 6e126efee0a02c63b436bb66645b7863985b041b
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Thu Sep 20 18:17:06 2012 +0400

    improve picking template for a scrip
    
    If Scrip is not applied then user can pick any template, so
    he can apply it to particular queue after that.
    
    Present Template picker on /Admin/Scrips/Objects.html page,
    so it's possible to pick new template when scrip is applied
    to a queue.

diff --git a/share/html/Admin/Scrips/Elements/SelectTemplate b/share/html/Admin/Scrips/Elements/SelectTemplate
index f61ce2a..88b3031 100755
--- a/share/html/Admin/Scrips/Elements/SelectTemplate
+++ b/share/html/Admin/Scrips/Elements/SelectTemplate
@@ -53,7 +53,6 @@
 ><% loc($name) %></option>
 % }
 </select>
-
 <%ARGS>
 $Name => 'Template'
 $Queue => undef
@@ -65,32 +64,42 @@ $Default => undef
 my $current;
 $current = $Scrip->Template if $Scrip;
 
-my $global = RT::Templates->new($session{'CurrentUser'});
-$global->LimitToGlobal;
+my @list;
+if ( $Scrip && $Scrip->id && !$Scrip->IsAddedToAny ) {
+    my $templates = RT::Templates->new($session{'CurrentUser'});
+    $templates->UnLimit;
+    @list = $templates->DistinctFieldValues('Name');
+} else {
+    my $global = RT::Templates->new($session{'CurrentUser'});
+    $global->LimitToGlobal;
 
-my %global;
-$global{ lc $_ } = $_ foreach map $_->Name, @{ $global->ItemsArrayRef };
+    my %global;
+    $global{ lc $_ } = $_ foreach map $_->Name, @{ $global->ItemsArrayRef };
 
-my @queues;
-push @queues, @{ $Scrip->AddedTo->ItemsArrayRef } if $Scrip && $Scrip->id;
-push @queues, $Queue if $Queue && $Queue->id;
+    my @queues;
+    push @queues, @{ $Scrip->AddedTo->ItemsArrayRef } if $Scrip && $Scrip->id;
+    push @queues, $Queue if $Queue && $Queue->id;
 
-my (%names, %counters);
-foreach my $queue ( @queues ) {
-    my $templates = RT::Templates->new($session{'CurrentUser'});
-    $templates->LimitToQueue( $queue->id );
-    foreach my $name ( map $_->Name, @{ $templates->ItemsArrayRef } ) {
-        next if $global{ lc $name };
-        $counters{ lc $name }++;
-        $names{lc $name} = $name;
+    my (%names, %counters);
+    foreach my $queue ( @queues ) {
+        my $templates = RT::Templates->new($session{'CurrentUser'});
+        $templates->LimitToQueue( $queue->id );
+        foreach my $name ( map $_->Name, @{ $templates->ItemsArrayRef } ) {
+            next if $global{ lc $name };
+            $counters{ lc $name }++;
+            $names{lc $name} = $name;
+        }
     }
+    delete $counters{ $_ }
+        foreach grep $counters{$_} != @queues,
+        keys %counters;
+
+    @list =
+        map $global{$_} || $names{$_},
+        keys %global, keys %counters;
 }
-delete $counters{ $_ }
-    foreach grep $counters{$_} != @queues,
-    keys %counters;
 
-my @list =
-    sort { lc loc($a) cmp lc loc($b) }
-    map $global{$_} || $names{$_},
-    keys %global, keys %counters;
+ at list = sort { lc loc($a) cmp lc loc($b) } @list
+    if @list;
+
 </%INIT>
diff --git a/share/html/Admin/Scrips/Objects.html b/share/html/Admin/Scrips/Objects.html
index 12e6cc4..09b59fc 100644
--- a/share/html/Admin/Scrips/Objects.html
+++ b/share/html/Admin/Scrips/Objects.html
@@ -57,9 +57,24 @@
 <input type="checkbox" name="RemoveScrip-<% $id %>" value="0" />
 <&|/l&>check this box to remove this scrip from all objects and be able to choose specific objects.</&>
 % } else {
-<h2><% loc('Stage') %></h2>
-<& /Admin/Elements/SelectStage, Default => $Stage &>
+<h2><% loc('Basics') %></h2>
+<table>
 
+<tr>
+    <td class="label"><&|/l&>Stage</&>:</td>
+    <td class="value"><& /Admin/Elements/SelectStage, Default => $Stage &></td>
+</tr>
+<tr>
+    <td class="label"> </td>
+    <td class="comment"><% loc("Set stage for new applications") %></td>
+</tr>
+
+<tr>
+    <td class="label"><&|/l&>Template</&>:</td>
+    <td class="value"><& Elements/SelectTemplate, Scrip => $scrip, Default => $Template &></td>
+</tr>
+
+</table>
 <h2><&|/l&>Apply globally</&></h2>
 
 <input type="checkbox" name="AddScrip-<% $id %>" value="0" />
@@ -106,6 +121,7 @@
 <%ARGS>
 $id => undef
 $Stage => undef
+$Template => ''
 $Update => 0
 </%ARGS>
 <%INIT>
@@ -115,6 +131,10 @@ $id = $scrip->id;
 
 if ( $Update ) {
     my (@results);
+    if ( $Template ) {
+        my ($status, $msg) = $scrip->SetTemplate( $Template );
+        push @results, loc('Template: [_1]', $msg);
+    }
     if ( defined (my $del = $ARGS{"RemoveScrip-$id"}) ) {
         foreach my $id ( ref $del? (@$del) : ($del) ) {
             my ($status, $msg) = $scrip->RemoveFromObject( $id );
diff --git a/t/web/scrips.t b/t/web/scrips.t
index 0bea8a0..c437bcd 100644
--- a/t/web/scrips.t
+++ b/t/web/scrips.t
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use RT::Test tests => 70;
+use RT::Test tests => 77;
 
 RT->Config->Set( UseTransactionBatch => 1 );
 
@@ -215,8 +215,37 @@ note "make sure we can not apply scrip to queue without required template";
     $m->form_name('AddRemoveScrip');
     $m->tick('AddScrip-'.$id, $queue_r->id);
     $m->click('Update');
-
     $m->content_like(qr{No template foo in queue Regression or global});
+
+note "unapply the scrip from any queue";
+    $m->form_name('AddRemoveScrip');
+    $m->tick('RemoveScrip-'.$id, $queue_g->id);
+    $m->click('Update');
+    $m->content_like(qr{Object deleted});
+
+note "you can pick any template";
+    $m->follow_link_ok( { id => 'page-basics' } );
+    ok $m->form_name('ModifyScrip');
+    my @templates = ($m->find_all_inputs( type => 'option', name => 'Template' ))[0]
+        ->possible_values;
+    is_deeply(
+        [sort @templates],
+        [sort do {
+            my $t = RT::Templates->new( RT->SystemUser );
+            $t->UnLimit;
+            ('', $t->DistinctFieldValues('Name'))
+        }],
+    );
+
+note "go to apply page and apply with template change";
+    $m->follow_link_ok( { id => 'page-applies-to' } );
+    $m->form_name('AddRemoveScrip');
+    $m->field('Template' => 'blank');
+    $m->tick('AddScrip-'.$id, $queue_g->id);
+    $m->tick('AddScrip-'.$id, $queue_r->id);
+    $m->click('Update');
+    $m->content_contains("The new value has been set.");
+    $m->content_contains("Object created");
 }
 
 note "apply scrip in different stage to different queues";

commit 0b4b5437d2298c73f1b905c78cda3d40f78e325f
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Thu Sep 27 20:53:33 2012 +0400

    make sure you can not delete template in use

diff --git a/lib/RT/Template.pm b/lib/RT/Template.pm
index e18e6d7..a87ba90 100644
--- a/lib/RT/Template.pm
+++ b/lib/RT/Template.pm
@@ -287,6 +287,10 @@ sub Delete {
         return ( 0, $self->loc('Permission Denied') );
     }
 
+    if ( $self->UsedBy->Count ) {
+        return ( 0, $self->loc('Template is in use') );
+    }
+
     return ( $self->SUPER::Delete(@_) );
 }
 
diff --git a/t/api/template.t b/t/api/template.t
index ec86b57..89a4fd7 100644
--- a/t/api/template.t
+++ b/t/api/template.t
@@ -2,7 +2,7 @@
 use strict;
 use warnings;
 
-use RT::Test tests => 8;
+use RT::Test tests => 25;
 
 use_ok('RT::Template');
 
@@ -100,6 +100,27 @@ note "changing queue of template is not implemented";
     ok(!$val,$msg);
 }
 
+note "make sure template can not be deleted if it has scrips";
+{
+    clean_templates( Queue => $queue->id );
+    my $template = RT::Template->new( RT->SystemUser );
+    my ($val,$msg) = $template->Create( Queue => $queue->id, Name => 'Test' );
+    ok($val,$msg);
+
+    my $scrip = RT::Scrip->new( RT->SystemUser );
+    ($val,$msg) = $scrip->Create(
+        Queue => $queue->id,
+        ScripCondition => "On Create",
+        ScripAction => 'Autoreply To Requestors',
+        Template => $template->Name,
+    );
+    ok($val, $msg);
+
+    ($val, $msg) = $template->Delete;
+    ok(!$val,$msg);
+}
+
+
 {
     my $t = RT::Template->new(RT->SystemUser);
     $t->Create(Name => "Foo", Queue => 1);

-----------------------------------------------------------------------


More information about the Rt-commit mailing list