Merge branch 'master' of git.freeside.biz:/home/git/freeside
authorIvan Kohler <ivan@freeside.biz>
Fri, 28 Sep 2012 03:27:43 +0000 (20:27 -0700)
committerIvan Kohler <ivan@freeside.biz>
Fri, 28 Sep 2012 03:27:43 +0000 (20:27 -0700)
Conflicts:
FS/FS/cust_main/Billing.pm

61 files changed:
1  2 
FS/FS/Misc.pm
FS/FS/TicketSystem/RT_Internal.pm
FS/FS/cust_main/Billing.pm
FS/FS/cust_pkg_discount.pm
FS/FS/discount.pm
FS/FS/part_event/Action/pkg_agent_credit.pm
FS/FS/part_export/shellcommands.pm
FS/FS/rate.pm
FS/FS/svc_Tower_Mixin.pm
bin/231commit
bin/23diff
bin/cdr.import
bin/cust_main-bill_now
bin/pod2x
fs_selfservice/DEPLOY
fs_selfservice/FS-SelfService/cgi/agent.cgi
fs_selfservice/FS-SelfService/cgi/cust_bill-logo.cgi
fs_selfservice/FS-SelfService/cgi/xmlrpc.cgi
httemplate/browse/cust_note_class.html
httemplate/docs/license.html
httemplate/edit/discount.html
httemplate/edit/process/cust_pkg_discount.html
httemplate/edit/process/quick-cust_pkg.cgi
httemplate/edit/process/svc_broadband.cgi
httemplate/elements/tr-select-discount.html
httemplate/view/cust_main/custom_content/.birthdate.html.swp
httemplate/view/cust_main/custom_content/.small_custview.html.swp
httemplate/view/cust_main/custom_content/.spouse_birthdate.html.swp
httemplate/view/cust_main/custom_content/.svc_Common.html.swp
httemplate/view/cust_main/custom_content/.svc_acct.html.swp
httemplate/view/cust_main/custom_content/.svc_hardware.html.swp
httemplate/view/cust_main/custom_content/.svc_phone.html.swp
rt/sbin/rt-server.fcgi.in
rt/sbin/rt-server.in
rt/sbin/rt-test-dependencies.in
rt/share/html/Search/Results.xls
rt/t/api/config.t
rt/t/api/template-insert.t
rt/t/api/template-simple.t
rt/t/api/template.t
rt/t/articles/search-interface.t
rt/t/articles/uri-a.t
rt/t/data/configs/apache2.2+fastcgi.conf.in
rt/t/data/configs/apache2.2+mod_perl.conf.in
rt/t/mail/dashboard-chart-with-utf8.t
rt/t/mail/dashboards.t
rt/t/mail/gateway.t
rt/t/shredder/01ticket.t
rt/t/shredder/03plugin_tickets.t
rt/t/shredder/03plugin_users.t
rt/t/shredder/utils.pl
rt/t/ticket/search_by_watcher.t
rt/t/web/attachments.t
rt/t/web/command_line.t
rt/t/web/command_line_with_unknown_field.t
rt/t/web/crypt-gnupg.t
rt/t/web/googleish_search.t
rt/t/web/query_builder_queue_limits.t
rt/t/web/search_simple.t
rt/t/web/ticket_modify_all.t
rt/t/web/transaction_batch.t

diff --cc FS/FS/Misc.pm
@@@ -913,16 -913,16 +913,6 @@@ sub ocr_image 
    @lines;
  }
  
--=item spool_formats
--  
--Returns a list of the invoice spool formats.
--
--=cut
--
--sub spool_formats {
--  qw(default oneline billco bridgestone)
--}
--
  =back
  
  =head1 BUGS
@@@ -50,7 -50,7 +50,7 @@@ sub access_right 
  sub session {
    my( $self, $session ) = @_;
  
--  if ( $session && $session->{'Current_User'} ) { # does this even work?
++  if ( $session && $session->{'CurrentUser'} ) { # does this even work?
      warn "$me session: using existing session and CurrentUser: \n".
           Dumper($session->{'CurrentUser'})
        if $DEBUG;
Simple merge
@@@ -106,7 -106,7 +106,8 @@@ sub insert 
        'amount'   => $self->amount,
        'percent'  => $self->percent,
        'months'   => $self->months,
--      'setup'   => $self->setup,
++      'setup'    => $self->setup,
++      #'linked'   => $self->linked,
        'disabled' => 'Y',
      };
      my $error = $discount->insert;
@@@ -136,6 -136,6 +136,7 @@@ sub check 
      || $self->ut_floatn('months') #actually decimal, but this will do
      || $self->ut_enum('disabled', [ '', 'Y' ])
      || $self->ut_enum('setup', [ '', 'Y' ])
++    #|| $self->ut_enum('linked', [ '', 'Y' ])
    ;
    return $error if $error;
  
@@@ -18,7 -18,7 +18,7 @@@ sub do_action 
    my $agent_cust_main = $agent->agent_cust_main;
      #? or return "No customer record for agent ". $agent->agent;
  
--  my $amount    = $self->_calc_credit($cust_pkg);
++  my $amount = $self->_calc_credit($cust_pkg);
    return '' unless $amount > 0;
  
    my $reasonnum = $self->option('reasonnum');
@@@ -29,6 -29,6 +29,7 @@@
      'eventnum' => $cust_event->eventnum,
      'addlinfo' => 'for customer #'. $cust_main->display_custnum.
                                 ': '.$cust_main->name,
++    #'commission_agentnum' => $agent->agentnum,
    );
    die "Error crediting customer ". $agent_cust_main->custnum.
        " for agent commission: $error"
@@@ -490,7 -490,7 +490,7 @@@ sub ssh_cmd { #subroutine, not metho
    my ($output, $errput) = $ssh->capture2($ssh_opt, $opt->{'command'});
  
    return if $opt->{'ignore_all_errors'};
--  die "Error running SSH command: ". $ssh->error if $ssh->error;
++  #die "Error running SSH command: ". $ssh->error if $ssh->error;
  
    if ( ($output || $errput)
         && $opt->{'ignored_errors'} && length($opt->{'ignored_errors'})
      $errput =~ s/[\s\n]//g;
    }
  
--  die "$errput\n" if $errput;
++  die (($errput || $ssh->error). "\n") if $errput || $ssh->error; 
++  #die "$errput\n" if $errput;
++
    die "$output\n" if $output and $opt->{'fail_on_output'};
    '';
  }
diff --cc FS/FS/rate.pm
@@@ -387,7 -387,7 +387,7 @@@ sub rate_detail 
  
  =item process
  
--Experimental job-queue processor for web interface adds/edits
++Job-queue processor for web interface adds/edits
  
  =cut
  
@@@ -52,5 -52,5 +52,4 @@@ sub tower_sector_sql 
    @where;
  }
  
--
  1;
diff --cc bin/231commit
@@@ -20,8 -20,8 +20,8 @@@ die "no files!" unless @ARGV
  system join('',
    "( cd /home/$USER/freeside2.3/$prefix; git pull ) && ",
    "( cd /home/$USER/freeside2.1/$prefix; git pull ) && ",
--  "git diff -u @ARGV | ( cd /home/$USER/freeside2.3/$prefix; patch ) ",
--  " && git diff -u @ARGV | ( cd /home/$USER/freeside2.1/$prefix; patch ) ",
++  "git diff -u @ARGV | ( cd /home/$USER/freeside2.3/$prefix; patch -p1 ) ",
++  " && git diff -u @ARGV | ( cd /home/$USER/freeside2.1/$prefix; patch -p1 ) ",
    " && ( ( git commit  -m $desc @ARGV && git push); ",
    "( cd /home/$USER/freeside2.3/$prefix; git commit -m $desc @ARGV && git push); ",
    "( cd /home/$USER/freeside2.1/$prefix; git commit -m $desc @ARGV && git push) )"
diff --cc bin/23diff
@@@ -3,7 -3,7 +3,8 @@@
  my $file = shift;
  
  chomp(my $dir = `pwd`);
--$dir =~ s/freeside\//freeside2.3\//;
++$dir =~ s/freeside(\/?)/freeside2.3$1/;
++warn $dir;
  
  #$cmd = "diff -u $file $dir/$file";
  $cmd = "diff -u $dir/$file $file";
diff --cc bin/cdr.import
index 36266ef,36266ef..36266ef
mode 100644,100644..100755
index 17e48fb,17e48fb..f8a1580
mode 100644,100644..100755
@@@ -13,7 -13,7 +13,9 @@@ my $custnum = shift or die &usage
  my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
    or die "unknown custnum $custnum\n";
  
--$cust_main->bill_and_collect( debug=>2, check_freq=>'1d' );
++$FS::cust_main::DEBUG = 3;
++
++$cust_main->bill_and_collect( debug=>3, check_freq=>'1d' );
  
  sub usage {
    die "Usage:\n  cust_main-bill_now user custnum\n";
diff --cc bin/pod2x
+++ b/bin/pod2x
@@@ -7,12 -7,12 +7,15 @@@ chomp( my $mw_password = `cat .mw-passw
  
  my $site_perl = "./FS";
  #my $html = "Freeside:1.7:Documentation:Developer";
--my $html = "Freeside:1.9:Documentation:Developer";
++#my $html = "Freeside:1.9:Documentation:Developer";
++my $html = "Freeside:3:Documentation:Developer";
  
  foreach my $dir (
    $html,
--  map "$html/$_", qw( bin FS FS/UI FS/part_export FS/part_pkg
++  map "$html/$_", qw( bin FS
++                      FS/cdr FS/cust_main FS/cust_pkg FS/detail_format
                        FS/part_event FS/part_event/Condition FS/part_event/Action
++                      FS/part_export FS/part_pkg FS/pay_batch
                        FS/ClientAPI FS/Cron FS/Misc FS/Report FS/Report/Table
                        FS/TicketSystem FS/UI
                        FS/SelfService
@@@ -43,6 -43,6 +46,7 @@@ foreach my $file 
  use WWW::Mediawiki::Client;
  my $mvs = WWW::Mediawiki::Client->new(
              'host'           => 'www.freeside.biz',
++            'protocol'       => 'https',
              'wiki_path'      => 'mediawiki/index.php',
              'username'       => $mw_username,
              'password'       => $mw_password,
@@@ -11,7 -11,7 +11,7 @@@ perl Makefile.PL && make && make instal
  cd ..
  
  #( cd ..; make deploy; cd fs_selfservice )
--( cd ..; make clean; make install-perl-modules; /etc/init.d/freeside restart; cd fs_selfservice )
++( cd ..; make clean; make configure-rt; make install-perl-modules; /etc/init.d/freeside restart; cd fs_selfservice )
  
  #cp /home/ivan/freeside/fs_selfservice/FS-SelfService/cgi/* /var/www/MyAccount
  #chown freeside /var/www/MyAccount/*.cgi
@@@ -3,7 -3,7 +3,7 @@@
                   'html_init'   => $html_init,
                   'name'        => 'customer note classes',
                   'disableable' => 1,
--                 'disabled_statuspos' => 2,
++                 'disabled_statuspos' => 1,
                   'query'       => { 'table'     => 'cust_note_class',
                                      'hashref'   => {},
                                      'order_by' => 'ORDER BY classnum',
@@@ -6,7 -6,7 +6,7 @@@
  
  <P>
  
--Copyright &copy; 2005-2009 Freeside Internet Services, Inc.<BR>
++Copyright &copy; 2005-2012 Freeside Internet Services, Inc.<BR>
  Copyright &copy; 2000-2005 Ivan Kohler<BR>
  Copyright &copy; 1999 Silicon Interactive Software Design<BR>
  All rights reserved<BR>
@@@ -22,6 -22,6 +22,7 @@@
                                   postfix => '<BR><FONT SIZE="-1"><I>(blank for non-expiring discount)</I></FONT>',
                                 },
                                 { field => 'setup', type => 'checkbox', value=>'Y', },
++                               #{ field => 'linked', type => 'checkbox', value=>'Y', },
                               ],
                   'labels' => { 
                                 'discountnum' => 'Discount #',
@@@ -32,6 -32,6 +33,7 @@@
                                 'percent'     => 'Percentage&nbsp;',
                                 'months'      => 'Duration (months)',
                                 'setup'       => 'Apply to setup fees',
++                               #'linked'      => 'Apply to add-on packages',
                               },
                   'viewall_dir' => 'browse',
                   'new_callback' => $new_callback,
@@@ -114,6 -114,6 +116,10 @@@ my $javascript = <<END
          document.getElementById('percent_label').style.visibility = 'hidden';
          document.getElementById('percent_input0').style.display = 'none';
          document.getElementById('percent_input0').style.visibility = 'hidden';
++//        document.getElementById('linked_label').style.display = 'none';
++//        document.getElementById('linked_label').style.visibility = 'hidden';
++//        document.getElementById('linked').style.display = 'none';
++//        document.getElementById('linked').style.visibility = 'hidden';
        } else if ( _type == 'Amount' ) {
          document.getElementById('amount_label').style.display = '';
          document.getElementById('amount_label').style.visibility = '';
          document.getElementById('percent_label').style.visibility = 'hidden';
          document.getElementById('percent_input0').style.display = 'none';
          document.getElementById('percent_input0').style.visibility = 'hidden';
++//        document.getElementById('linked_label').style.display = 'none';
++//        document.getElementById('linked_label').style.visibility = 'hidden';
++//        document.getElementById('linked').style.display = 'none';
++//        document.getElementById('linked').style.visibility = 'hidden';
        } else if ( _type == 'Percentage' ) {
          document.getElementById('amount_label').style.display = 'none';
          document.getElementById('amount_label').style.visibility = 'hidden';
          document.getElementById('percent_label').style.visibility = '';
          document.getElementById('percent_input0').style.display = '';
          document.getElementById('percent_input0').style.visibility = '';
++//        document.getElementById('linked_label').style.display = '';
++//        document.getElementById('linked_label').style.visibility = '';
++//        document.getElementById('linked').style.display = '';
++//        document.getElementById('linked').style.visibility = '';
       }
  
      }
@@@ -39,7 -39,7 +39,8 @@@ my $cust_pkg_discount = new FS::cust_pk
    'amount'      => scalar($cgi->param('discountnum_amount')),
    'percent'     => scalar($cgi->param('discountnum_percent')),
    'months'      => scalar($cgi->param('discountnum_months')),
--  'setup'      => scalar($cgi->param('discountnum_setup')),
++  'setup'       => scalar($cgi->param('discountnum_setup')),
++  #'linked'       => scalar($cgi->param('discountnum_linked')),
    #'disabled'    => $self->discountnum_disabled,
  };
  my $error = $cust_pkg_discount->insert;
@@@ -2,19 -2,19 +2,24 @@@
  %  $cgi->param('error', $error);
  <% $cgi->redirect(popurl(3). 'misc/order_pkg.html?'. $cgi->query_string ) %>
  %} else {
--%  my $frag = "cust_pkg". $cust_pkg->pkgnum;
  %  my $show = $curuser->default_customer_view =~ /^(jumbo|packages)$/
  %               ? ''
  %               : ';show=packages';
--%  my $redir_url = popurl(3)
--%            ."view/cust_main.cgi?custnum=$custnum$show;fragment=$frag#$frag";
++%
++%  my $redir_url = popurl(3);
++%  if ( $svcpart ) { # for going straight to service provisining after ordering
++%    $redir_url .= 'edit/'.$part_svc->svcdb.'.cgi?'.
++%                    'pkgnum='.$cust_pkg->pkgnum. ";svcpart=$svcpart";
++%    $redir_url .= ";qualnum=$qualnum" if $qualnum;
++%  } elsif ( $quotationnum ) {
++%    $redir_url .= "view/quotation.html?quotationnum=$quotationnum";
++%  } else {
++%    my $custnum = $cust_main->custnum;
++%    my $frag = "cust_pkg". $cust_pkg->pkgnum;
++%    $redir_url .=
++%      "view/cust_main.cgi?custnum=$custnum$show;fragment=$frag#$frag";
++%  }
  % 
--% # for going right to a provision service after ordering a package
--% if ( $svcpart ) { 
--%   $redir_url = popurl(3)."edit/".$part_svc->svcdb.".cgi?".
--%                  "pkgnum=".$cust_pkg->pkgnum. ";svcpart=$svcpart";
--%   $redir_url .= ";qualnum=$qualnum" if $qualnum;
--% }
  <% header('Package ordered') %>
    <SCRIPT TYPE="text/javascript">
      // XXX fancy ajax rebuild table at some point, but a page reload will do for now
@@@ -33,16 -33,16 +38,27 @@@ my $curuser = $FS::CurrentUser::Current
  die "access denied"
    unless $curuser->access_right('Order customer package');
  
--#untaint custnum (probably not necessary, searching for it is escape enough)
--$cgi->param('custnum') =~ /^(\d+)$/
--  or die 'illegal custnum '. $cgi->param('custnum');
--my $custnum = $1;
--my $cust_main = qsearchs({
--  'table'     => 'cust_main',
--  'hashref'   => { 'custnum' => $custnum },
--  'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
--});
--die 'unknown custnum' unless $cust_main;
++my $cust_main;
++if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
++  my $custnum = $1;
++  $cust_main = qsearchs({
++    'table'     => 'cust_main',
++    'hashref'   => { 'custnum' => $custnum },
++    'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
++  });
++}
++
++my $prospect_main;
++if ( $cgi->param('prospectnum') =~ /^(\d+)$/ ) {
++  my $prospectnum = $1;
++  $prospect_main = qsearchs({
++    'table'     => 'prospect_main',
++    'hashref'   => { 'prospectnum' => $prospectnum },
++    'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
++  });
++}
++
++die 'no custnum or prospectnum' unless $cust_main || $prospect_main;
  
  #probably not necessary, taken care of by cust_pkg::check
  $cgi->param('pkgpart') =~ /^(\d+)$/
@@@ -72,47 -72,47 +88,70 @@@ if ( $cgi->param('svcpart') ) 
  }
  
  my $qualnum = '';
--if ( $cgi->param('qualnum') ) {
--  $cgi->param('qualnum') =~ /^(\d+)$/ or die 'illegal qualnum';
++if ( $cgi->param('qualnum') =~ /^(\d+)$/ ) {
    $qualnum = $1;
  }
++my $quotationnum = '';
++if ( $cgi->param('quotationnum') =~ /^(\d+)$/ ) {
++  $quotationnum = $1;
++}
++# verify this quotation is visible to this user
  
++my $cust_pkg = '';
++my $quotation_pkg = '';
++my $error = '';
  
--my $cust_pkg = new FS::cust_pkg {
--  'custnum'              => $custnum,
--  'pkgpart'              => $pkgpart,
--  'quantity'             => $quantity,
--  'start_date'           => ( scalar($cgi->param('start_date'))
--                                ? parse_datetime($cgi->param('start_date'))
--                                : ''
--                            ),
--  'no_auto'              => scalar($cgi->param('no_auto')),
--  'refnum'               => $refnum,
--  'locationnum'          => $locationnum,
--  'discountnum'          => $discountnum,
--  #for the create a new discount case
--  'discountnum__type'    => scalar($cgi->param('discountnum__type')),
--  'discountnum_amount'   => scalar($cgi->param('discountnum_amount')),
--  'discountnum_percent'  => scalar($cgi->param('discountnum_percent')),
--  'discountnum_months'   => scalar($cgi->param('discountnum_months')),
--  'discountnum_setup'    => scalar($cgi->param('discountnum_setup')),
--  'contract_end'         => ( scalar($cgi->param('contract_end'))
--                                ? parse_datetime($cgi->param('contract_end'))
--                                : ''
--                            ),
--   'waive_setup'         => ( $cgi->param('waive_setup') eq 'Y' ? 'Y' : '' ),
--};
--
--my %opt = ( 'cust_pkg' => $cust_pkg );
--
--if ( $locationnum == -1 ) {
--  my $cust_location = new FS::cust_location {
--    map { $_ => scalar($cgi->param($_)) }
--        qw( custnum address1 address2 city county state zip country geocode )
--  };
--  $opt{'cust_location'} = $cust_location;
--}
++my %hash = (
++    'pkgpart'              => $pkgpart,
++    'quantity'             => $quantity,
++    'start_date'           => ( scalar($cgi->param('start_date'))
++                                  ? parse_datetime($cgi->param('start_date'))
++                                  : ''
++                              ),
++    'refnum'               => $refnum,
++    'locationnum'          => $locationnum,
++    'discountnum'          => $discountnum,
++    #for the create a new discount case
++    'discountnum__type'    => scalar($cgi->param('discountnum__type')),
++    'discountnum_amount'   => scalar($cgi->param('discountnum_amount')),
++    'discountnum_percent'  => scalar($cgi->param('discountnum_percent')),
++    'discountnum_months'   => scalar($cgi->param('discountnum_months')),
++    'discountnum_setup'    => scalar($cgi->param('discountnum_setup')),
++    'contract_end'         => ( scalar($cgi->param('contract_end'))
++                                  ? parse_datetime($cgi->param('contract_end'))
++                                  : ''
++                              ),
++     'waive_setup'         => ( $cgi->param('waive_setup') eq 'Y' ? 'Y' : '' ),
++);
++$hash{'custnum'} = $cust_main->custnum if $cust_main;
++
++if ( $quotationnum ) {
++
++  $quotation_pkg = new FS::quotation_pkg \%hash;
++  $quotation_pkg->quotationnum($quotationnum);
++  $quotation_pkg->prospectnum($prospect_main->prospectnum) if $prospect_main;
  
--my $error = $cust_main->order_pkg( \%opt );
++  #XXX handle new location
++  $error = $quotation_pkg->insert;
++
++} else {
++
++  $cust_pkg = new FS::cust_pkg \%hash;
++
++  $cust_pkg->no_auto( scalar($cgi->param('no_auto')) );
++
++  my %opt = ( 'cust_pkg' => $cust_pkg );
++
++  if ( $locationnum == -1 ) {
++    my $cust_location = new FS::cust_location {
++      map { $_ => scalar($cgi->param($_)) }
++          qw( custnum address1 address2 city county state zip country geocode )
++    };
++    $opt{'cust_location'} = $cust_location;
++  }
++
++  $error = $cust_main->order_pkg( \%opt );
++
++}
  
  </%init>
@@@ -1,11 -1,11 +1,10 @@@
  <& elements/svc_Common.html,
--  table       => 'svc_broadband',
--  fields      => [ fields('svc_broadband'), fields('nas'), 'usergroup' ],
++  table             => 'svc_broadband',
++  fields            => [ fields('svc_broadband'), fields('nas'), 'usergroup' ],
    precheck_callback => \&precheck,
  &>
  <%init>
--# for historical reasons, process_m2m for usergroup tables is done 
--# in the svc_x::insert/replace/delete methods, not here
++
  my $curuser = $FS::CurrentUser::CurrentUser;
  
  die "access denied"
@@@ -6,7 -6,7 +6,7 @@@
  % } else { 
  
    <TR>
--    <TD ALIGN="right" WIDTH="176"><% $opt{'label'} || '<B>'.emt('Discount').'</B>' %></TD>
++    <TD ALIGN="right" WIDTH="275"><% $opt{'label'} || '<B>'.emt('Discount').'</B>' %></TD>
      <TD <% $colspan %>>
        <% include( '/elements/select-discount.html',
                      'curr_value' => $discountnum,
              )
    %>
  
++%#  <% include( '/elements/tr-checkbox.html',
++%#                'label'     => '<B>Apply discount to add-on packages</B>',
++%#                'field'     => $name.'_linked',
++%#                'id'        => $name.'_linked',
++%#                'curr_value' => scalar($cgi->param($name.'_linked')),
++%#                'value'     => 'Y',
++%#                'colspan'    => $opt{'colspan'},
++%#            )
++%#  %>
++
    <SCRIPT TYPE="text/javascript">
  
  %   my $ge = 'document.getElementById';
          <% $ge %>('<% $name %>_percent_label0').style.visibility = 'hidden';
          <% $ge %>('<% $name %>_percent_input0').style.display = 'none';
          <% $ge %>('<% $name %>_percent_input0').style.visibility = 'hidden';
++//        <% $ge %>('<% $name %>_linked_label0').style.display = 'none';
++//        <% $ge %>('<% $name %>_linked_label0').style.visibility = 'hidden';
++//        <% $ge %>('<% $name %>_linked').style.display = 'none';
++//        <% $ge %>('<% $name %>_linked').style.visibility = 'hidden';
        } else if ( <% $name %>__type == 'Amount' ) {
          <% $ge %>('<% $name %>_amount_label0').style.display = '';
          <% $ge %>('<% $name %>_amount_label0').style.visibility = '';
          <% $ge %>('<% $name %>_percent_label0').style.visibility = 'hidden';
          <% $ge %>('<% $name %>_percent_input0').style.display = 'none';
          <% $ge %>('<% $name %>_percent_input0').style.visibility = 'hidden';
++        <% $ge %>('<% $name %>_percent_input0').style.visibility = 'hidden';
++//        <% $ge %>('<% $name %>_linked_label0').style.display = 'none';
++//        <% $ge %>('<% $name %>_linked_label0').style.visibility = 'hidden';
++//        <% $ge %>('<% $name %>_linked').style.display = 'none';
++//        <% $ge %>('<% $name %>_linked').style.visibility = 'hidden';
        } else if ( <% $name %>__type == 'Percentage' ) {
          <% $ge %>('<% $name %>_amount_label0').style.display = 'none';
          <% $ge %>('<% $name %>_amount_label0').style.visibility = 'hidden';
          <% $ge %>('<% $name %>_percent_label0').style.visibility = '';
          <% $ge %>('<% $name %>_percent_input0').style.display = '';
          <% $ge %>('<% $name %>_percent_input0').style.visibility = '';
++        <% $ge %>('<% $name %>_percent_input0').style.visibility = '';
++//        <% $ge %>('<% $name %>_linked_label0').style.display = '';
++//        <% $ge %>('<% $name %>_linked_label0').style.visibility = '';
++//        <% $ge %>('<% $name %>_linked').style.display = '';
++//        <% $ge %>('<% $name %>_linked').style.visibility = '';
       }
  
      }
diff --cc httemplate/view/cust_main/custom_content/.birthdate.html.swp
index 9571d22,9571d22..0000000
deleted file mode 100644,100644
Binary files differ
diff --cc httemplate/view/cust_main/custom_content/.small_custview.html.swp
index a39f52d,a39f52d..0000000
deleted file mode 100644,100644
Binary files differ
diff --cc httemplate/view/cust_main/custom_content/.spouse_birthdate.html.swp
index 0042012,0042012..0000000
deleted file mode 100644,100644
Binary files differ
diff --cc httemplate/view/cust_main/custom_content/.svc_Common.html.swp
index 15591b9,15591b9..0000000
deleted file mode 100644,100644
Binary files differ
diff --cc httemplate/view/cust_main/custom_content/.svc_acct.html.swp
index e2db6d5,e2db6d5..0000000
deleted file mode 100644,100644
Binary files differ
diff --cc httemplate/view/cust_main/custom_content/.svc_hardware.html.swp
index 1106f9e,1106f9e..0000000
deleted file mode 100644,100644
Binary files differ
diff --cc httemplate/view/cust_main/custom_content/.svc_phone.html.swp
index 79b8185,79b8185..0000000
deleted file mode 100644,100644
Binary files differ
@@@ -172,7 -172,7 +172,7 @@@ if (caller) 
  require Plack::Runner;
  
  my $is_fastcgi = $0 =~ m/fcgi$/;
--my $r = Plack::Runner->new( $0 =~ 'standalone' ? ( server => 'Standalone' ) :
++my $r = Plack::Runner->new( $0 =~ /standalone/ ? ( server => 'Standalone' ) :
                              $is_fastcgi        ? ( server => 'FCGI' )
                                                 : (),
                              env => 'deployment' );
@@@ -172,7 -172,7 +172,7 @@@ if (caller) 
  require Plack::Runner;
  
  my $is_fastcgi = $0 =~ m/fcgi$/;
--my $r = Plack::Runner->new( $0 =~ 'standalone' ? ( server => 'Standalone' ) :
++my $r = Plack::Runner->new( $0 =~ /standalone/ ? ( server => 'Standalone' ) :
                              $is_fastcgi        ? ( server => 'FCGI' )
                                                 : (),
                              env => 'deployment' );
@@@ -56,9 -56,9 +56,10 @@@ no warnings qw(numeric redefine)
  use Getopt::Long;
  my %args;
  my %deps;
++my @orig_argv = @ARGV;
  GetOptions(
      \%args,                               'v|verbose',
--    'install',                            'with-MYSQL',
++    'install!',                           'with-MYSQL',
      'with-POSTGRESQL|with-pg|with-pgsql', 'with-SQLITE',
      'with-ORACLE',                        'with-FASTCGI',
      'with-MODPERL1',                      'with-MODPERL2',
@@@ -293,7 -293,7 +294,7 @@@ Test::LongStrin
  .
  
  $deps{'FASTCGI'} = [ text_to_hash( << '.') ];
--FCGI
++FCGI 0.74
  FCGI::ProcManager
  .
  
@@@ -344,7 -344,7 +345,7 @@@ URI 1.5
  
  $deps{'GRAPHVIZ'} = [ text_to_hash( << '.') ];
  GraphViz
--IPC::Run
++IPC::Run 0.90
  .
  
  $deps{'GD'} = [ text_to_hash( << '.') ];
@@@ -359,6 -359,6 +360,7 @@@ Convert::Colo
  
  my %AVOID = (
      'DBD::Oracle' => [qw(1.23)],
++    'Email::Address' => [qw(1.893 1.894)],
  );
  
  if ($args{'download'}) {
@@@ -403,7 -403,7 +405,12 @@@ foreach my $type (sort grep $args{$_}, 
      $Missing_By_Type{$type} = \%missing if keys %missing;
  }
  
--conclude(%Missing_By_Type);
++if ( $args{'install'} && keys %Missing_By_Type ) {
++    exec($0, @orig_argv, '--no-install');
++}
++else {
++    conclude(%Missing_By_Type);
++}
  
  sub test_deps {
      my @deps = @_;
@@@ -54,6 -54,6 +54,7 @@@ $Format => unde
  <%INIT>
  
  use Spreadsheet::WriteExcel;
++use OLE::Storage_Lite;
  use List::Util qw( max );
  use Date::Format qw( time2str );
  
@@@ -1,7 -1,7 +1,8 @@@
  use strict;
  use warnings;
  use RT;
--use RT::Test nodb => 1, tests => 9;
++use RT::Test nodb => 1, tests => 11;
++use Test::Warn;
  
  ok(
      RT::Config->AddOption(
@@@ -31,3 -31,3 +32,12 @@@ is( $meta->{Widget}, '/Widgets/Form/Boo
  ok( RT::Config->DeleteOption( Name => 'foo' ), 'removed option foo' );
  is( RT::Config->Meta('foo'), undef, 'foo is indeed deleted' );
  
++# Test EmailInputEncodings PostLoadCheck code
++RT::Config->Set('EmailInputEncodings', qw(utf-8 iso-8859-1 us-ascii foo));
++my @encodings = qw(utf-8-strict iso-8859-1 ascii);
++
++warning_is {RT::Config->PostLoadCheck} "Unknown encoding 'foo' in \@EmailInputEncodings option",
++  'Correct warning for encoding foo';
++
++my @canonical_encodings = RT::Config->Get('EmailInputEncodings');
++is_deeply(\@encodings, \@canonical_encodings, 'Got correct encoding list');
diff --cc rt/t/api/template-insert.t
index 1bf5fc3,1bf5fc3..0000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,26 -1,26 +1,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 --cc rt/t/api/template-simple.t
index bbdebb3,bbdebb3..0000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,275 -1,275 +1,0 @@@
--use strict;
--use warnings;
--use RT;
--use RT::Test tests => 231;
--use Test::Warn;
--
--my $queue = RT::Queue->new(RT->SystemUser);
--$queue->Load("General");
--
--my $ticket_cf = RT::CustomField->new(RT->SystemUser);
--$ticket_cf->Create(
--    Name        => 'Department',
--    Queue       => '0',
--    Type        => 'FreeformSingle',
--);
--
--my $txn_cf = RT::CustomField->new(RT->SystemUser);
--$txn_cf->Create(
--    Name        => 'Category',
--    LookupType  => RT::Transaction->CustomFieldLookupType,
--    Type        => 'FreeformSingle',
--);
--$txn_cf->AddToObject($queue);
--
--my $ticket = RT::Ticket->new(RT->SystemUser);
--my ($id, $msg) = $ticket->Create(
--    Subject   => "template testing",
--    Queue     => "General",
--    Owner     => 'root@localhost',
--    Requestor => ["dom\@example.com"],
--    "CustomField-" . $txn_cf->id => "Special",
--);
--ok($id, "Created ticket: $msg");
--my $txn = $ticket->Transactions->First;
--
--$ticket->AddCustomFieldValue(
--    Field => 'Department',
--    Value => 'Coolio',
--);
--
--TemplateTest(
--    Content      => "\ntest",
--    PerlOutput   => "test",
--    SimpleOutput => "test",
--);
--
--TemplateTest(
--    Content      => "\ntest { 5 * 5 }",
--    PerlOutput   => "test 25",
--    SimpleOutput => "test { 5 * 5 }",
--);
--
--TemplateTest(
--    Content      => "\ntest { \$Requestor }",
--    PerlOutput   => "test dom\@example.com",
--    SimpleOutput => "test dom\@example.com",
--);
--
--TemplateTest(
--    Content      => "\ntest { \$TicketSubject }",
--    PerlOutput   => "test ",
--    SimpleOutput => "test template testing",
--);
--
--SimpleTemplateTest(
--    Content => "\ntest { \$TicketQueueId }",
--    Output  => "test 1",
--);
--
--SimpleTemplateTest(
--    Content => "\ntest { \$TicketQueueName }",
--    Output  => "test General",
--);
--
--SimpleTemplateTest(
--    Content => "\ntest { \$TicketOwnerId }",
--    Output  => "test 12",
--);
--
--SimpleTemplateTest(
--    Content => "\ntest { \$TicketOwnerName }",
--    Output  => "test root",
--);
--
--SimpleTemplateTest(
--    Content => "\ntest { \$TicketOwnerEmailAddress }",
--    Output  => "test root\@localhost",
--);
--
--SimpleTemplateTest(
--    Content => "\ntest { \$TicketStatus }",
--    Output  => "test new",
--);
--
--SimpleTemplateTest(
--    Content => "\ntest #{ \$TicketId }",
--    Output  => "test #" . $ticket->id,
--);
--
--SimpleTemplateTest(
--    Content => "\ntest { \$TicketCFDepartment }",
--    Output  => "test Coolio",
--);
--
--SimpleTemplateTest(
--    Content => "\ntest #{ \$TransactionId }",
--    Output  => "test #" . $txn->id,
--);
--
--SimpleTemplateTest(
--    Content => "\ntest { \$TransactionType }",
--    Output  => "test Create",
--);
--
--SimpleTemplateTest(
--    Content => "\ntest { \$TransactionCFCategory }",
--    Output  => "test Special",
--);
--
--SimpleTemplateTest(
--    Content => "\ntest { \$TicketDelete }",
--    Output  => "test { \$TicketDelete }",
--);
--
--SimpleTemplateTest(
--    Content => "\ntest { \$Nonexistent }",
--    Output  => "test { \$Nonexistent }",
--);
--
--warning_like {
--    TemplateTest(
--        Content      => "\ntest { \$Ticket->Nonexistent }",
--        PerlOutput   => undef,
--        SimpleOutput => "test { \$Ticket->Nonexistent }",
--    );
--} qr/RT::Ticket::Nonexistent Unimplemented/;
--
--warning_like {
--    TemplateTest(
--        Content      => "\ntest { \$Nonexistent->Nonexistent }",
--        PerlOutput   => undef,
--        SimpleOutput => "test { \$Nonexistent->Nonexistent }",
--    );
--} qr/Can't call method "Nonexistent" on an undefined value/;
--
--TemplateTest(
--    Content      => "\ntest { \$Ticket->OwnerObj->Name }",
--    PerlOutput   => "test root",
--    SimpleOutput => "test { \$Ticket->OwnerObj->Name }",
--);
--
--warning_like {
--    TemplateTest(
--        Content      => "\ntest { *!( }",
--        SyntaxError  => 1,
--        PerlOutput   => undef,
--        SimpleOutput => "test { *!( }",
--    );
--} qr/Template parsing error: syntax error/;
--
--TemplateTest(
--    Content      => "\ntest { \$rtname ",
--    SyntaxError  => 1,
--    PerlOutput   => undef,
--    SimpleOutput => undef,
--);
--
--is($ticket->Status, 'new', "test setup");
--SimpleTemplateTest(
--    Content => "\ntest { \$Ticket->SetStatus('resolved') }",
--    Output  => "test { \$Ticket->SetStatus('resolved') }",
--);
--is($ticket->Status, 'new', "simple templates can't call ->SetStatus");
--
--# Make sure changing the template's type works
--my $template = RT::Template->new(RT->SystemUser);
--$template->Create(
--    Name    => "type chameleon",
--    Type    => "Perl",
--    Content => "\ntest { 10 * 7 }",
--);
--ok($id = $template->id, "Created template");
--$template->Parse;
--is($template->MIMEObj->stringify_body, "test 70", "Perl output");
--
--$template = RT::Template->new(RT->SystemUser);
--$template->Load($id);
--is($template->Name, "type chameleon");
--
--$template->SetType('Simple');
--$template->Parse;
--is($template->MIMEObj->stringify_body, "test { 10 * 7 }", "Simple output");
--
--$template = RT::Template->new(RT->SystemUser);
--$template->Load($id);
--is($template->Name, "type chameleon");
--
--$template->SetType('Perl');
--$template->Parse;
--is($template->MIMEObj->stringify_body, "test 70", "Perl output");
--
--undef $ticket;
--
--my $counter = 0;
--sub IndividualTemplateTest {
--    local $Test::Builder::Level = $Test::Builder::Level + 1;
--
--    my %args = (
--        Name => "Test-" . ++$counter,
--        Type => "Perl",
--        @_,
--    );
--
--    my $t = RT::Template->new(RT->SystemUser);
--    $t->Create(
--        Name    => $args{Name},
--        Type    => $args{Type},
--        Content => $args{Content},
--    );
--
--    ok($t->id, "Created $args{Type} template");
--    is($t->Name, $args{Name}, "$args{Type} template name");
--    is($t->Content, $args{Content}, "$args{Type} content");
--    is($t->Type, $args{Type}, "template type");
--
--    # this should never blow up!
--    my ($ok, $msg) = $t->CompileCheck;
--
--    # we don't need to syntax check simple templates since if you mess them up
--    # it's safe to just use the input directly as the template's output
--    if ($args{SyntaxError} && $args{Type} eq 'Perl') {
--        ok(!$ok, "got a syntax error");
--    }
--    else {
--        ok($ok, $msg);
--    }
--
--    ($ok, $msg) = $t->Parse(
--        TicketObj      => $ticket,
--        TransactionObj => $txn,
--    );
--    if (defined $args{Output}) {
--        ok($ok, $msg);
--        is($t->MIMEObj->stringify_body, $args{Output}, "$args{Type} template's output");
--    }
--    else {
--        ok(!$ok, "expected a failure");
--    }
--}
--
--sub TemplateTest {
--    local $Test::Builder::Level = $Test::Builder::Level + 1;
--    my %args = @_;
--
--    for my $type ('Perl', 'Simple') {
--        next if $args{"Skip$type"};
--
--        IndividualTemplateTest(
--            %args,
--            Type   => $type,
--            Output => $args{$type . 'Output'},
--        );
--    }
--}
--
--sub SimpleTemplateTest {
--    local $Test::Builder::Level = $Test::Builder::Level + 1;
--    my %args = @_;
--
--    IndividualTemplateTest(
--        %args,
--        Type => 'Simple',
--    );
--}
--
@@@ -1,25 -1,25 +1,34 @@@
  
--use strict;
  use warnings;
--use RT;
--use RT::Test tests => 2;
--
--
--{
--
--ok(require RT::Template);
++use strict;
  
++use RT;
++use RT::Test tests => 10;
  
--}
++my $queue = RT::Test->load_or_create_queue( Name => 'Templates' );
++ok $queue && $queue->id, "loaded or created a queue";
  
  {
--
--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 $template = RT::Template->new( RT->SystemUser );
++    isa_ok($template, 'RT::Template');
++    my ($val,$msg) = $template->Create(
++        Queue => $queue->id,
++        Name => 'InsertTest',
++        Content => 'This is template content'
++    );
++    ok $val, "created a template" or diag "error: $msg";
++    ok my $id = $template->id, "id is defined";
++    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, "changed content" or diag "error: $msg";
++
++    is $template->Content, 'This is new template content', "We managed to _Set_ the content";
++
++    ($val, $msg) = $template->Delete;
++    ok $val, "deleted template";
++
++    $template->Load($id);
++    ok !$template->id, "can not load template after deletion";
  }
--
@@@ -3,7 -3,7 +3,7 @@@
  use strict;
  use warnings;
  
--use RT::Test tests => 23;
++use RT::Test tests => 44;
  
  use RT::CustomField;
  use RT::Queue;
@@@ -67,7 -67,7 +67,12 @@@ my %cvals = ('article1q' => 'Some quest
                'article3q' => 'Why should I eat my supper?',
                'article3a' => 'There are starving children in Africa',
                'article4q' => 'What did Brian originally write?',
--              'article4a' => 'Romanes eunt domus');
++              'article4a' => 'This is an answer that is longer than 255 '
++           . 'characters so these tests will be sure to use the LargeContent '
++           . 'SQL as well as the normal SQL that would be generated if this '
++           . 'was an answer that was shorter than 255 characters. This second '
++           . 'sentence has a few extra characters to get this string to go '
++           . 'over the 255 character boundary. Lorem ipsum.');
  
  # Create an article or two with our custom field values.
  
@@@ -108,6 -108,6 +113,52 @@@ isa_ok($m, 'Test::WWW::Mechanize')
  ok($m->login, 'logged in');
  $m->follow_link_ok( { text => 'Articles', url_regex => qr!^/Articles/! },
      'UI -> Articles' );
--$m->follow_link_ok( {text => 'Search'}, 'Articles -> Search');
--$m->follow_link_ok( {text => 'in class '.$class->Name}, 'Articles in class '.$class->Name);
--$m->content_contains($article1->Name);
++
++# In all of the search results below, the results page should
++# have the summary text of the article it occurs in.
++
++# Case sensitive search on small field.
++DoArticleSearch($m, $class->Name, 'Africa');
++$m->text_contains('Search results'); # Did we do a search?
++$m->text_contains('blah blah 1');
++
++# Case insensitive search on small field.
++DoArticleSearch($m, $class->Name, 'africa');
++$m->text_contains('Search results'); # Did we do a search?
++$m->text_contains('blah blah 1');
++
++# Case sensitive search on large field.
++DoArticleSearch($m, $class->Name, 'ipsum');
++$m->text_contains('Search results'); # Did we do a search?
++$m->text_contains('hoi polloi 4');
++
++# Case insensitive search on large field.
++DoArticleSearch($m, $class->Name, 'lorem');
++$m->text_contains('Search results'); # Did we do a search?
++TODO:{
++    local $TODO = 'Case insensitive search on LONGBLOB not available in MySQL'
++      if RT->Config->Get('DatabaseType') eq 'mysql';
++    $m->text_contains('hoi polloi 4');
++}
++
++# When you send $m to this sub, it must be on a page with
++# a Search link.
++sub DoArticleSearch{
++  my $m = shift;
++  my $class_name = shift;
++  my $search_text = shift;
++
++  $m->follow_link_ok( {text => 'Search'}, 'Articles -> Search');
++  $m->follow_link_ok( {text => 'in class '. $class_name}, 'Articles in class '. $class_name);
++  $m->text_contains('First article');
++
++  $m->submit_form_ok( {
++            form_number => 3,
++            fields      => {
++                'Article~' => $search_text
++            },
++        }, "Search for $search_text"
++    );
++  return;
++}
++
@@@ -3,7 -3,7 +3,7 @@@
  use strict;
  use warnings;
  
--use RT::Test tests => 7;
++use RT::Test tests => 15;
  
  use_ok("RT::URI::a");
  my $uri = RT::URI::a->new($RT::SystemUser);
@@@ -26,3 -26,3 +26,39 @@@ is(ref($uri->Object), "RT::Article", "O
  is($uri->Object->Id, $article->Id, "Object loaded has correct ID");
  is($article->URI, 'fsck.com-article://example.com/article/'.$article->Id, 
     "URI object has correct URI string");
++
++{
++    my $aid = $article->id;
++    my $ticket = RT::Ticket->new( RT->SystemUser );
++    my ($id, $msg) = $ticket->Create(
++        Queue       => 1,
++        Subject     => 'test ticket',
++    );
++    ok $id, "Created a test ticket";
++
++    # Try searching
++    my $tickets = RT::Tickets->new( RT->SystemUser );
++    $tickets->FromSQL(" RefersTo = 'a:$aid' ");
++    is $tickets->Count, 0, "No results yet";
++
++    # try with the full uri
++    $tickets->FromSQL(" RefersTo = '@{[ $article->URI ]}' ");
++    is $tickets->Count, 0, "Still no results";
++
++    # add the link
++    $ticket->AddLink( Type => 'RefersTo', Target => "a:$aid" );
++
++    # verify the ticket has it
++    my @links = @{$ticket->RefersTo->ItemsArrayRef};
++    is scalar @links, 1, "Has one RefersTo link";
++    is ref $links[0]->TargetObj, "RT::Article", "Link points to an article";
++    is $links[0]->TargetObj->id, $aid, "Link points to the article we specified";
++
++    # search again
++    $tickets->FromSQL(" RefersTo = 'a:$aid' ");
++    is $tickets->Count, 1, "Found one ticket with short URI";
++
++    # search with the full uri
++    $tickets->FromSQL(" RefersTo = '@{[ $article->URI ]}' ");
++    is $tickets->Count, 1, "Found one ticket with full URI";
++}
@@@ -12,6 -12,6 +12,7 @@@ Group @WEB_GROUP
  </IfModule>
  </IfModule>
  
++ServerName localhost
  Listen %%LISTEN%%
  
  ErrorLog "%%LOG_FILE%%"
@@@ -30,6 -30,6 +30,7 @@@ Group @WEB_GROUP
  </IfModule>
  </IfModule>
  
++ServerName localhost
  Listen %%LISTEN%%
  
  ErrorLog "%%LOG_FILE%%"
@@@ -1,7 -1,7 +1,17 @@@
  use strict;
  use warnings;
  
--use RT::Test tests => 15;
++BEGIN {
++    require RT::Test;
++
++    if (eval { require GD }) {
++        RT::Test->import(tests => 15);
++    }
++    else {
++        RT::Test->import(skip_all => 'GD required.');
++    }
++}
++
  use utf8;
  
  my $root = RT::Test->load_or_create_user( Name => 'root' );
@@@ -2,7 -2,7 +2,7 @@@
  use strict;
  use warnings;
  
--use RT::Test tests => 187;
++use RT::Test tests => 181;
  use Test::Warn;
  use RT::Dashboard::Mailer;
  
@@@ -138,17 -138,17 +138,6 @@@ sub delete_dashboard { # {{
      ok($ok, $msg);
  } # }}}
  
--sub delete_subscriptions { # {{{
--    my $subscription_id = shift;
--    # delete the dashboard and make sure we get exactly one subscription failure
--    # notice
--    my $user = RT::User->new(RT->SystemUser);
--    $user->Load('root');
--    for my $subscription ($user->Attributes->Named('Subscription')) {
--        $subscription->Delete;
--    }
--} # }}}
--
  my $good_time = 1290423660; # 6:01 EST on a monday
  my $bad_time  = 1290427260; # 7:01 EST on a monday
  
@@@ -223,21 -223,21 +212,9 @@@ SKIP: 
  
  delete_dashboard($dashboard_id);
  
--warning_like {
--    RT::Dashboard::Mailer->MailDashboards(All => 1);
--} qr/Unable to load dashboard $dashboard_id of subscription $subscription_id for user root/;
--
--@mails = RT::Test->fetch_caught_mails;
--is(@mails, 1, "one mail for subscription failure");
--$mail = parse_mail($mails[0]);
--is($mail->head->get('Subject'), "[example.com] Missing dashboard!\n");
--is($mail->head->get('From'), "dashboard\@example.com\n");
--is($mail->head->get('X-RT-Dashboard-Id'), "$dashboard_id\n");
--is($mail->head->get('X-RT-Dashboard-Subscription-Id'), "$subscription_id\n");
--
  RT::Dashboard::Mailer->MailDashboards(All => 1);
  @mails = RT::Test->fetch_caught_mails;
--is(@mails, 0, "no mail because the subscription notice happens only once");
++is(@mails, 0, "no mail because the subscription is deleted");
  
  RT::Test->stop_server;
  RT::Test->clean_caught_mails;
@@@ -277,7 -277,7 +254,6 @@@ RT->Config->Set('EmailDashboardRemove' 
  ($baseurl, $m) = RT::Test->started_ok;
  
  delete_dashboard($dashboard_id);
--delete_subscriptions();
  
  RT::Test->clean_caught_mails;
  
@@@ -330,7 -330,7 +306,6 @@@ RT->Config->Set('EmailDashboardRemove' 
  ($baseurl, $m) = RT::Test->started_ok;
  
  delete_dashboard($dashboard_id);
--delete_subscriptions();
  
  RT::Test->clean_caught_mails;
  
@@@ -373,7 -373,7 +348,6 @@@ RT->Config->Set('EmailDashboardRemove' 
  ($baseurl, $m) = RT::Test->started_ok;
  
  delete_dashboard($dashboard_id);
--delete_subscriptions();
  
  RT::Test->clean_caught_mails;
  
@@@ -57,7 -57,7 +57,7 @@@ use strict
  use warnings;
  
  
--use RT::Test config => 'Set( $UnsafeEmailCommands, 1);', tests => 221, actual_server => 1;
++use RT::Test config => 'Set( $UnsafeEmailCommands, 1);', tests => 228, actual_server => 1;
  my ($baseurl, $m) = RT::Test->started_ok;
  
  use RT::Tickets;
@@@ -608,6 -608,6 +608,35 @@@ EO
      $m->no_warnings_ok;
  }
  
++diag "make sure we check that UTF-8 is really UTF-8";
++{
++    my $text = <<EOF;
++From: root\@localhost
++To: rtemail\@@{[RT->Config->Get('rtname')]}
++Subject: This is test wrong utf-8 chars
++Content-Type: text/plain; charset="utf-8"
++
++utf-8: informaci\303\263n confidencial
++latin1: informaci\363n confidencial
++
++bye
++EOF
++    my ($status, $id) = RT::Test->send_via_mailgate_and_http($text);
++    is ($status >> 8, 0, "The mail gateway exited normally");
++    ok ($id, "created ticket");
++
++    my $tick = RT::Test->last_ticket;
++    is ($tick->Id, $id, "correct ticket");
++
++    my $content = $tick->Transactions->First->Content;
++    Encode::_utf8_off($content);
++
++    like $content, qr{informaci\303\263n confidencial};
++    like $content, qr{informaci\357\277\275n confidencial};
++
++    $m->no_warnings_ok;
++}
++
  diag "check that mailgate doesn't suffer from empty Reply-To:";
  {
      my $text = <<EOF;
@@@ -78,7 -78,7 +78,11 @@@ cmp_deeply( dump_current_and_savepoint(
      my $shredder = shredder_new();
      $shredder->PutObjects( Objects => $child );
      $shredder->WipeoutAll;
--    cmp_deeply( dump_current_and_savepoint('parent_ticket'), "current DB equal to savepoint");
++
++  TODO: {
++        local $TODO = "Shredder doesn't delete all links and transactions";
++        cmp_deeply( dump_current_and_savepoint('parent_ticket'), "current DB equal to savepoint");
++    }
  
      $shredder->PutObjects( Objects => $parent );
      $shredder->WipeoutAll;
@@@ -34,6 -34,6 +34,7 @@@ use_ok('RT::Tickets')
      my $child = RT::Ticket->new( RT->SystemUser );
      my ($cid) = $child->Create( Subject => 'child', Queue => 1, MemberOf => $pid );
      ok( $cid, "created new ticket" );
++    $_->ApplyTransactionBatch for $parent, $child;
  
      my $plugin = RT::Shredder::Plugin::Tickets->new;
      isa_ok($plugin, 'RT::Shredder::Plugin::Tickets');
@@@ -77,6 -77,6 +78,8 @@@ cmp_deeply( dump_current_and_savepoint(
      my ($status, $msg) = $child->AddLink( Target => $pid, Type => 'DependsOn' );
      ok($status, "added reqursive link") or diag "error: $msg";
  
++    $_->ApplyTransactionBatch for $parent, $child;
++
      my $plugin = RT::Shredder::Plugin::Tickets->new;
      isa_ok($plugin, 'RT::Shredder::Plugin::Tickets');
  
@@@ -121,6 -121,6 +124,8 @@@ cmp_deeply( dump_current_and_savepoint(
      ok( $cid2, "created new ticket" );
      $child2->SetStatus('resolved');
  
++    $_->ApplyTransactionBatch for $parent, $child1, $child2;
++
      my $plugin = RT::Shredder::Plugin::Tickets->new;
      isa_ok($plugin, 'RT::Shredder::Plugin::Tickets');
  
@@@ -5,8 -5,8 +5,8 @@@ use warnings
  
  use Test::Deep;
  use File::Spec;
--use Test::More tests => 9;
--use RT::Test nodb => 1;
++use Test::More tests => 21;
++use RT::Test ();
  BEGIN {
      my $shredder_utils = RT::Test::get_relocatable_file('utils.pl',
          File::Spec->curdir());
@@@ -38,3 -38,3 +38,61 @@@ use_ok('RT::Shredder::Plugin::Users')
      ok(!$status, "bad 'status' arg value");
  }
  
++init_db();
++
++RT::Test->set_rights(
++    { Principal => 'Everyone', Right => [qw(CreateTicket)] },
++);
++
++create_savepoint('clean');
++
++{ # Create two users and a ticket. Shred second user and replace relations with first user
++    my ($uidA, $uidB, $msg);
++    my $userA = RT::User->new( RT->SystemUser );
++    ($uidA, $msg) = $userA->Create( Name => 'userA', Privileged => 1, Disabled => 0 );
++    ok( $uidA, "created user A" ) or diag "error: $msg";
++
++    my $userB = RT::User->new( RT->SystemUser );
++    ($uidB, $msg) = $userB->Create( Name => 'userB', Privileged => 1, Disabled => 0 );
++    ok( $uidB, "created user B" ) or diag "error: $msg";
++
++    my ($tid, $trid);
++    my $ticket = RT::Ticket->new( RT::CurrentUser->new($userB) );
++    ($tid, $trid, $msg) = $ticket->Create( Subject => 'UserB Ticket', Queue => 1 );
++    ok( $tid, "created new ticket") or diag "error: $msg";
++
++    my $transaction = RT::Transaction->new( RT->SystemUser );
++    $transaction->Load($trid);
++    is ( $transaction->Creator, $uidB, "ticket creator is user B" );
++
++    my $plugin = RT::Shredder::Plugin::Users->new;
++    isa_ok($plugin, 'RT::Shredder::Plugin::Users');
++
++    my $status;
++    ($status, $msg) = $plugin->TestArgs( status => 'any', name => 'userB', replace_relations => $uidA );
++    ok($status, "plugin arguments are ok") or diag "error: $msg";
++
++    my @objs;
++    ($status, @objs) = $plugin->Run;
++    ok($status, "executed plugin successfully") or diag "error: @objs";
++    @objs = RT::Shredder->CastObjectsToRecords( Objects => \@objs );
++    is(scalar @objs, 1, "one object in the result set");
++
++    my $shredder = shredder_new();
++
++    ($status, $msg) = $plugin->SetResolvers( Shredder => $shredder );
++    ok($status, "set conflicts resolver") or diag "error: $msg";
++
++    $shredder->PutObjects( Objects => \@objs );
++    $shredder->WipeoutAll;
++
++    $ticket->Load( $tid );
++    is($ticket->id, $tid, 'loaded ticket');
++
++    $transaction->Load($trid);
++    is ( $transaction->Creator, $uidA, "ticket creator is now user A" );
++
++    $shredder->Wipeout( Object => $ticket );
++    $shredder->Wipeout( Object => $userA );
++}
++cmp_deeply( dump_current_and_savepoint('clean'), "current DB equal to savepoint");
@@@ -283,7 -283,7 +283,7 @@@ sub dump_sqlit
      my $old_fhkn = $dbh->{'FetchHashKeyName'};
      $dbh->{'FetchHashKeyName'} = 'NAME_lc';
  
--    my $sth = $dbh->table_info( '', '', '%', 'TABLE' ) || die $DBI::err;
++    my $sth = $dbh->table_info( '', '%', '%', 'TABLE' ) || die $DBI::err;
      my @tables = keys %{$sth->fetchall_hashref( 'table_name' )};
  
      my $res = {};
@@@ -142,8 -142,8 +142,8 @@@ sub run_auto_tests 
  @conditions = (
      'Cc = "not@exist"'       => sub { 0 },
      'Cc != "not@exist"'      => sub { 1 },
--    'Cc IS NULL'             => sub { $_[0] =~ 'c:-;' },
--    'Cc IS NOT NULL'         => sub { $_[0] !~ 'c:-;' },
++    'Cc IS NULL'             => sub { $_[0] =~ /c:-;/ },
++    'Cc IS NOT NULL'         => sub { $_[0] !~ /c:-;/ },
      'Cc = "x@foo.com"'       => sub { $_[0] =~ /c:[^;]*x/ },
      'Cc != "x@foo.com"'      => sub { $_[0] !~ /c:[^;]*x/ },
      'Cc LIKE "@bar.com"'     => sub { $_[0] =~ /c:[^;]*(?:y|z)/ },
  
      'Requestor = "not@exist"'   => sub { 0 },
      'Requestor != "not@exist"'  => sub { 1 },
--    'Requestor IS NULL'         => sub { $_[0] =~ 'r:-;' },
--    'Requestor IS NOT NULL'     => sub { $_[0] !~ 'r:-;' },
++    'Requestor IS NULL'         => sub { $_[0] =~ /r:-;/ },
++    'Requestor IS NOT NULL'     => sub { $_[0] !~ /r:-;/ },
      'Requestor = "x@foo.com"'   => sub { $_[0] =~ /r:[^;]*x/ },
      'Requestor != "x@foo.com"'  => sub { $_[0] !~ /r:[^;]*x/ },
      'Requestor LIKE "@bar.com"' => sub { $_[0] =~ /r:[^;]*(?:y|z)/ },
      'Subject LIKE "ne"'      => sub { 0 },
      'Subject NOT LIKE "ne"'  => sub { 1 },
      'Subject = "r:x;c:y;"'   => sub { $_[0] eq 'r:x;c:y;' },
--    'Subject LIKE "x"'       => sub { $_[0] =~ 'x' },
++    'Subject LIKE "x"'       => sub { $_[0] =~ /x/ },
  );
  
  @tickets = generate_tix();
@@@ -1,10 -1,10 +1,11 @@@
  #!/usr/bin/perl -w
  use strict;
  
--use RT::Test tests => 25;
++use RT::Test tests => 33;
  
  use constant LogoFile => $RT::MasonComponentRoot .'/NoAuth/images/bpslogo.png';
  use constant FaviconFile => $RT::MasonComponentRoot .'/NoAuth/images/favicon.png';
++use constant TextFile => $RT::MasonComponentRoot .'/NoAuth/css/print.css';
  
  my ($baseurl, $m) = RT::Test->started_ok;
  ok $m->login, 'logged in';
@@@ -30,9 -30,9 +31,18 @@@ $m->content_contains('Attachments test'
  $m->content_contains('Some content', 'and content');
  $m->content_contains('Download bpslogo.png', 'page has file name');
  
++open LOGO, "<", LogoFile or die "Can't open logo file: $!";
++binmode LOGO;
++my $logo_contents = do {local $/; <LOGO>};
++close LOGO;
++$m->follow_link_ok({text => "Download bpslogo.png"});
++is($m->content_type, "image/png");
++is($m->content, $logo_contents, "Binary content matches");
++
++$m->back;
  $m->follow_link_ok({text => 'Reply'}, "reply to the ticket");
  $m->form_name('TicketUpdate');
--$m->field('Attach',  LogoFile);
++$m->field('Attach',  TextFile);
  $m->click('AddMoreAttach');
  is($m->status, 200, "request successful");
  
@@@ -44,7 -44,7 +54,16 @@@ is($m->status, 200, "request successful
  
  $m->content_contains('Download bpslogo.png', 'page has file name');
  $m->content_contains('Download favicon.png', 'page has file name');
++$m->content_contains('Download print.css', 'page has file name');
++
++$m->follow_link_ok( { text => 'Download bpslogo.png' } );
++is( $m->response->header('Content-Type'), 'image/png', 'Content-Type of png lacks charset' );
++
++$m->back;
  
++$m->follow_link_ok( { text => 'Download print.css' } );
++is( $m->response->header('Content-Type'),
++    'text/css;charset=UTF-8', 'Content-Type of text has charset' );
  
  diag "test mobile ui";
  $m->get_ok( $baseurl . '/m/ticket/create?Queue=' . $qid );
@@@ -3,7 -3,7 +3,7 @@@
  use strict;
  use File::Spec ();
  use Test::Expect;
--use RT::Test tests => 303, actual_server => 1;
++use RT::Test tests => 315, actual_server => 1;
  my ($baseurl, $m) = RT::Test->started_ok;
  
  use RT::User;
@@@ -480,6 -480,6 +480,8 @@@ expect_like(qr/Merged into ticket #$mer
          expect_like(qr/Created link $link1_id $reln $link2_id/, 'Linked');
          expect_send("show -s ticket/$link1_id/links", "Checking creation of $reln...");
          expect_like(qr/$display_relns{$reln}: [\w\d\.\-]+:\/\/[\w\d\.]+\/ticket\/$link2_id/, "Created link $reln");
++        expect_send("show ticket/$link1_id/links", "Checking show links without format");
++        expect_like(qr/$display_relns{$reln}: [\w\d\.\-]+:\/\/[\w\d\.]+\/ticket\/$link2_id/, "Found link $reln");
  
          # delete link
          expect_send("link -d $link1_id $reln $link2_id", "Delete $reln...");
@@@ -3,7 -3,7 +3,7 @@@
  use strict;
  use File::Spec ();
  use Test::Expect;
--use RT::Test tests => 14, actual_server => 1;
++use RT::Test tests => 17, actual_server => 1;
  my ($baseurl, $m) = RT::Test->started_ok;
  my $rt_tool_path = "$RT::BinPath/rt";
  
@@@ -19,6 -19,6 +19,11 @@@ expect_run
      prompt => 'rt> ',
      quit => 'quit',
  );
++
++expect_send( q{create -t ticket set foo=bar}, "create ticket with unknown field" );
++expect_like(qr/foo: Unknown field/, 'foo is unknown field');
++expect_like(qr/Could not create ticket/, 'ticket is not created');
++
  expect_send(q{create -t ticket set subject='new ticket' add cc=foo@example.com}, "Creating a ticket...");
  
  expect_like(qr/Ticket \d+ created/, "Created the ticket");
@@@ -53,6 -53,6 +53,7 @@@ RT::Test->clean_caught_mails
  
  $m->goto_create_ticket( $queue );
  $m->form_name('TicketCreate');
++$m->field('Requestors', 'recipient@example.com');
  $m->field('Subject', 'Encryption test');
  $m->field('Content', 'Some content');
  ok($m->value('Encrypt', 2), "encrypt tick box is checked");
@@@ -122,6 -122,6 +123,7 @@@ RT::Test->clean_caught_mails
  
  $m->goto_create_ticket( $queue );
  $m->form_name('TicketCreate');
++$m->field('Requestors', 'recipient@example.com');
  $m->field('Subject', 'Signing test');
  $m->field('Content', 'Some other content');
  ok(!$m->value('Encrypt', 2), "encrypt tick box is unchecked");
@@@ -195,6 -195,6 +197,7 @@@ RT::Test->clean_caught_mails
  
  $m->goto_create_ticket( $queue );
  $m->form_name('TicketCreate');
++$m->field('Requestors', 'recipient@example.com');
  $m->field('Subject', 'Crypt+Sign test');
  $m->field('Content', 'Some final? content');
  ok($m->value('Encrypt', 2), "encrypt tick box is checked");
@@@ -260,6 -260,6 +263,7 @@@ RT::Test->clean_caught_mails
  
  $m->goto_create_ticket( $queue );
  $m->form_name('TicketCreate');
++$m->field('Requestors', 'recipient@example.com');
  $m->field('Subject', 'Test crypt-off on encrypted queue');
  $m->field('Content', 'Thought you had me figured out didya');
  $m->field(Encrypt => undef, 2); # turn off encryption
@@@ -2,7 -2,7 +2,8 @@@
  use strict;
  use warnings;
  
--use RT::Test tests => 96, config => 'Set( %FullTextSearch, Enable => 1, Indexed => 0 );';
++use RT::Test tests => undef,
++    config => 'Set( %FullTextSearch, Enable => 1, Indexed => 0 );';
  my ($baseurl, $m) = RT::Test->started_ok;
  my $url = $m->rt_base_url;
  
@@@ -57,6 -57,6 +58,7 @@@ ok $two_words_queue && $two_words_queue
      is $parser->QueryToSQL("'me'"), "$active AND ( Subject LIKE 'me' )", "correct parsing";
      is $parser->QueryToSQL("owner:me"), "( Owner.id = '__CurrentUser__' ) AND $active", "correct parsing";
      is $parser->QueryToSQL("owner:'me'"), "( Owner = 'me' ) AND $active", "correct parsing";
++    is $parser->QueryToSQL('owner:root@localhost'), "( Owner.EmailAddress = 'root\@localhost' ) AND $active", "Email address as owner";
  
      is $parser->QueryToSQL("resolved me"), "( Owner.id = '__CurrentUser__' ) AND ( Status = 'resolved' )", "correct parsing";
      is $parser->QueryToSQL("resolved active me"), "( Owner.id = '__CurrentUser__' ) AND ( Status = 'resolved' OR Status = 'new' OR Status = 'open' OR Status = 'stalled' )", "correct parsing";
@@@ -217,3 -217,3 +219,5 @@@ for my $quote ( q{'}, q{"} ) 
      }
  }
  
++undef $m;
++done_testing;
@@@ -11,6 -11,6 +11,9 @@@ $lifecycles->{foo} = 
  
  };
  
++# explicitly Set so RT::Test can catch our change
++RT->Config->Set( Lifecycles => %$lifecycles );
++
  RT::Lifecycle->FillCache();
  
  my $general = RT::Test->load_or_create_queue( Name => 'General' );
@@@ -1,7 -1,7 +1,7 @@@
  use strict;
  use warnings;
  
--use RT::Test tests => 16;
++use RT::Test tests => 30;
  my ( $baseurl, $m ) = RT::Test->started_ok;
  
  RT::Test->create_tickets(
@@@ -19,4 -19,4 +19,58 @@@ $m->content_contains( 'Show Results'
  $m->title_is( 'Found 1 ticket', 'title' );
  $m->content_contains( 'ticket foo', 'has ticket foo' );
  
++# Test searches on custom fields
++my $cf1 = RT::Test->load_or_create_custom_field(
++                      Name  => 'Location',
++                      Queue => 'General',
++                      Type  => 'FreeformSingle', );
++isa_ok( $cf1, 'RT::CustomField' );
++
++my $cf2 = RT::Test->load_or_create_custom_field(
++                      Name  => 'Server-name',
++                      Queue => 'General',
++                      Type  => 'FreeformSingle', );
++isa_ok( $cf2, 'RT::CustomField' );
++
++my $t = RT::Ticket->new(RT->SystemUser);
++
++{
++  my ($id,undef,$msg) = $t->Create(
++            Queue => 'General',
++            Subject => 'Test searching CFs');
++  ok( $id, "Created ticket - $msg" );
++}
++
++{
++  my ($status, $msg) = $t->AddCustomFieldValue(
++                           Field => $cf1->id,
++                         Value => 'Downtown');
++  ok( $status, "Added CF value - $msg" );
++}
++
++{
++  my ($status, $msg) = $t->AddCustomFieldValue(
++                           Field => $cf2->id,
++                         Value => 'Proxy');
++  ok( $status, "Added CF value - $msg" );
++}
++
++# Regular search
++my $search = 'cf.Location:Downtown';
++$m->get_ok("/Search/Simple.html?q=$search");
++$m->title_is( 'Found 1 ticket', 'Found 1 ticket' );
++$m->text_contains( 'Test searching CFs', "Found test CF ticket with $search" );
++
++# Case insensitive
++$search = "cf.Location:downtown";
++$m->get_ok("/Search/Simple.html?q=$search");
++$m->title_is( 'Found 1 ticket', 'Found 1 ticket' );
++$m->text_contains( 'Test searching CFs', "Found test CF ticket with $search" );
++
++# With dash in CF name
++$search = "cf.Server-name:Proxy";
++$m->get_ok("/Search/Simple.html?q=$search");
++$m->title_is( 'Found 1 ticket', 'Found 1 ticket' );
++$m->text_contains( 'Test searching CFs', "Found test CF ticket with $search" );
++
  # TODO more simple search tests
@@@ -1,7 -1,7 +1,7 @@@
  use strict;
  use warnings;
  
--use RT::Test tests => 15;
++use RT::Test tests => 22;
  
  my $ticket = RT::Test->create_ticket(
      Subject => 'test bulk update',
@@@ -40,5 -40,5 +40,44 @@@ $m->click('SubmitTicket')
  $m->form_name('TicketModifyAll');
  is($m->value('Owner'), 'root', 'owner was successfully changed to root');
  
--# XXX TODO test other parts, i.e. basic, dates, people and links
++$m->get_ok($url . "/Ticket/ModifyAll.html?id=" . $ticket->id);
  
++$m->form_name('TicketModifyAll');
++$m->field('Starts_Date' => "2013-01-01 00:00:00");
++$m->click('SubmitTicket');
++$m->text_contains("Starts: (Tue Jan 01 00:00:00 2013)", 'start date successfully updated');
++
++$m->form_name('TicketModifyAll');
++$m->field('Started_Date' => "2014-01-01 00:00:00");
++$m->click('SubmitTicket');
++$m->text_contains("Started: (Wed Jan 01 00:00:00 2014)", 'started date successfully updated');
++
++$m->form_name('TicketModifyAll');
++$m->field('Told_Date' => "2015-01-01 00:00:00");
++$m->click('SubmitTicket');
++$m->text_contains("Last Contact:  (Thu Jan 01 00:00:00 2015)", 'told date successfully updated');
++
++$m->form_name('TicketModifyAll');
++$m->field('Due_Date' => "2016-01-01 00:00:00");
++$m->click('SubmitTicket');
++$m->text_contains("Due: (Fri Jan 01 00:00:00 2016)", 'due date successfully updated');
++
++$m->get( $url . '/Ticket/ModifyAll.html?id=' . $ticket->id );
++$m->form_name('TicketModifyAll');
++$m->field(WatcherTypeEmail => 'Requestor');
++$m->field(WatcherAddressEmail => 'root@localhost');
++$m->click('SubmitTicket');
++$m->text_contains(
++    "Added principal as a Requestor for this ticket",
++    'watcher is added',
++);
++$m->form_name('TicketModifyAll');
++$m->field(WatcherTypeEmail => 'Requestor');
++$m->field(WatcherAddressEmail => 'root@localhost');
++$m->click('SubmitTicket');
++$m->text_contains(
++    "That principal is already a Requestor for this ticket",
++    'no duplicate watchers',
++);
++
++# XXX TODO test other parts, i.e. links
@@@ -12,7 -12,7 +12,14 @@@ my ($val, $msg) =$s1->Create( Queue => 
               ScripAction       => 'User Defined',
               CustomIsApplicableCode => 'return ($self->TransactionObj->Field||"") eq "TimeEstimated"',
               CustomPrepareCode => 'return 1',
--             CustomCommitCode  => '$self->TicketObj->SetPriority($self->TicketObj->Priority + 2); return 1;',
++             CustomCommitCode  => '
++if ( $self->TicketObj->CurrentUser->Name ne "RT_System" ) { 
++    warn "Ticket obj has incorrect CurrentUser (should be RT_System) ".$self->TicketObj->CurrentUser->Name
++}
++if ( $self->TicketObj->QueueObj->CurrentUser->Name ne "RT_System" ) { 
++    warn "Queue obj has incorrect CurrentUser (should be RT_System) ".$self->TicketObj->QueueObj->CurrentUser->Name
++}
++$self->TicketObj->SetPriority($self->TicketObj->Priority + 2); return 1;',
               Template          => 'Blank',
               Stage             => 'TransactionBatch',
      );