suspension and cancellation reasons
authorjeff <jeff>
Wed, 18 Oct 2006 23:07:08 +0000 (23:07 +0000)
committerjeff <jeff>
Wed, 18 Oct 2006 23:07:08 +0000 (23:07 +0000)
FS/FS/AccessRight.pm
FS/FS/Schema.pm
FS/FS/part_bill_event.pm
FS/MANIFEST
htetc/handler.pl
httemplate/browse/part_bill_event.cgi
httemplate/edit/elements/edit.html
httemplate/edit/part_bill_event.cgi
httemplate/edit/process/part_bill_event.cgi
httemplate/elements/menu.html
httemplate/view/cust_main/packages.html

index 6fdb0b0..64c4f6b 100644 (file)
@@ -107,6 +107,8 @@ assigned to users and/or groups.
   'Unsuspend customer package',
   'Cancel customer package immediately',
   'Cancel customer package later',
+  'Add on-the-fly cancel reason',
+  'Add on-the-fly suspend reason',
 
 ###
 # customer service rights
index 607b2d9..d6725fc 100644 (file)
@@ -319,6 +319,7 @@ sub tables_hashref {
         'weight',      'int', '', '', '', '', 
         'plan',       'varchar', 'NULL', $char_d, '', '', 
         'plandata',   'text', 'NULL', '', '', '', 
+        'reason',     'int', 'NULL', '', '', '', 
         'disabled',     'char', 'NULL', 1, '', '', 
       ],
       'primary_key' => 'eventpart',
@@ -650,6 +651,19 @@ sub tables_hashref {
       'index' => [ ['custnum'], ['pkgpart'] ],
     },
 
+    'cust_pkg_reason' => {
+      'columns' => [
+        'num',      'serial',    '',   '', '', '', 
+        'pkgnum',   'int',    '',   '', '', '', 
+        'reasonnum','int',    '',   '', '', '', 
+        'otaker',   'varchar', '', 32, '', '', 
+        'date',     @date_type, '', '', 
+      ],
+      'primary_key' => 'num',
+      'unique' => [],
+      'index' => [],
+    },
+
     'cust_refund' => {
       'columns' => [
         'refundnum',    'serial',    '',   '', '', '', 
@@ -1352,17 +1366,6 @@ sub tables_hashref {
       'index'       => [],
     },
 
-    'cancel_reason' => {
-      'columns' => [
-        'reasonnum', 'serial',  '',     '', '', '', 
-        'reason',    'varchar', '',     $char_d, '', '', 
-        'disabled',  'char',    'NULL', 1, '', '', 
-      ],
-      'primary_key' => 'reasonnum',
-      'unique' => [],
-      'index'  => [ [ 'disabled' ] ],
-    },
-
     'pkg_class' => {
       'columns' => [
         'classnum',   'serial',  '', '', '', '', 
@@ -1607,7 +1610,30 @@ sub tables_hashref {
       'index'  => [ [ 'countrycode', 'phonenum' ] ],
     },
 
-  };
+    'reason_type' => {
+      'columns' => [
+        'typenum',   'serial',  '', '', '', '', 
+        'class',     'char', '', 1, '', '', 
+        'type',     'varchar', '', $char_d, '', '', 
+      ],
+      'primary_key' => 'typenum',
+      'unique' => [],
+      'index' => [],
+    },
+
+    'reason' => {
+      'columns' => [
+        'reasonnum',     'serial',  '', '', '', '', 
+        'reason_type',   'int',  '', '', '', '', 
+        'reason',        'varchar', '', $char_d, '', '', 
+        'disabled',      'char',    'NULL', 1, '', '', 
+      ],
+      'primary_key' => 'reasonnum',
+      'unique' => [],
+      'index' => [],
+    },
+
+    # name type nullability length default local
 
     #'new_table' => {
     #  'columns' => [
@@ -1618,6 +1644,8 @@ sub tables_hashref {
     #  'index'  => [],
     #},
 
+  };
+
 }
 
 =back
index 473e0bd..3f49d29 100644 (file)
@@ -60,6 +60,8 @@ FS::Record.  The following fields are currently supported:
 
 =item plandata - additional plan data
 
+=item reason   - an associated reason for this event to fire
+
 =item disabled - Disabled flag, empty or `Y'
 
 =back
@@ -161,6 +163,7 @@ sub check {
     || $self->ut_number('weight')
     || $self->ut_textn('plan')
     || $self->ut_anything('plandata')
+    || $self->ut_numbern('reason')
   ;
     #|| $self->ut_snumber('seconds')
   return $error if $error;
@@ -184,6 +187,9 @@ sub check {
     }
   }
 
+  my $reasonr = qsearchs('reason', {'reasonnum' => $self->reason});
+  return "Unknown reason" unless $reasonr;
+
   $self->SUPER::check;
 }
 
@@ -304,6 +310,22 @@ sub do_event {
   '';
 }
 
+=item reasontext
+
+Returns the text of any reason associated with this event.
+
+=cut
+
+sub reasontext {
+  my $self = shift;
+  my $r = qsearchs('reason', { 'reasonnum' => $self->reason });
+  if ($r){
+    $r->reason;
+  }else{
+    '';
+  }
+}
+
 =back
 
 =head1 BUGS
index c67145b..c14be07 100644 (file)
@@ -311,8 +311,6 @@ FS/agent_payment_gateway.pm
 t/agent_payment_gateway.t
 FS/banned_pay.pm
 t/banned_pay.t
-FS/cancel_reason.pm
-t/cancel_reason.t
 bin/freeside-prepaidd
 FS/cdr.pm
 t/cdr.t
@@ -358,3 +356,9 @@ FS/cust_credit_bill_pkg.pm
 t/cust_credit_bill_pkg.t
 FS/cust_main_note.pm
 t/cust_main_note.t
+FS/cust_pkg_reason.pm
+t/cust_pkg_reason.t
+FS/reason.pm
+t/reason.t
+FS/reason_type.pm
+t/reason_type.t
index c03313e..89287d7 100644 (file)
@@ -142,6 +142,7 @@ sub handler
       use FS::cust_main_county;
       use FS::cust_pay;
       use FS::cust_pkg;
+      use FS::cust_pkg_reason;
       use FS::cust_refund;
       use FS::cust_svc;
       use FS::nas;
@@ -189,6 +190,8 @@ sub handler
       use FS::access_right;
       use FS::AccessRight;
       use FS::svc_phone;
+      use FS::reason_type;
+      use FS::reason;
       use FS::cust_main_note;
 
       if ( %%%RT_ENABLED%%% ) {
index 2486c66..f7c3e03 100755 (executable)
@@ -55,6 +55,7 @@
 %         my $delay = duration_exact($part_bill_event->seconds);
 %         ( my $plandata = $part_bill_event->plandata ) =~ s/\n/<BR>/go;
 %         my $freq = $part_bill_event->freq || '1d';
+%         my $reason = $part_bill_event->reasontext ;
 %    
 % if ( $oldfreq ne $freq ) { 
 
@@ -67,6 +68,7 @@
           <TH CLASS="grid" BGCOLOR="#cccccc" COLSPAN=<% $cgi->param('showdisabled') ? 2 : 3 %>>Event</TH>
           <TH CLASS="grid" BGCOLOR="#cccccc">After</TH>
           <TH CLASS="grid" BGCOLOR="#cccccc">Action</TH>
+          <TH CLASS="grid" BGCOLOR="#cccccc">Reason</TH>
           <TH CLASS="grid" BGCOLOR="#cccccc">Options</TH>
           <TH CLASS="grid" BGCOLOR="#cccccc">Code</TH>
         </TR>
         <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
           <% $part_bill_event->plan %></TD>
         <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+          <% $reason %></TD>
+        <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
           <% $plandata %></TD>
         <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><FONT SIZE="-1">
           <% $part_bill_event->eventcode %></FONT></TD>
index ac00fc5..750e62f 100644 (file)
 %    &{$opt{'error_callback'}}($cgi, $object)
 %      if $opt{'error_callback'};
 %
-%  } elsif ( $cgi->keywords ) { #editing
+%  } elsif ( $cgi->keywords || $cgi->param($pkey) ) { #editing
 %
 %    my( $query ) = $cgi->keywords;
+%    $query = $cgi->param($pkey) unless $query;
 %    $query =~ /^(\d+)$/;
 %    $object = qsearchs( $table, { $pkey => $1 } );
 %    warn "$table $pkey => $1"
 %
 %  my $title = "$action $opt{'name'}";
 %
+%  my $viewall_url = $p . ( $opt{'viewall_dir'} || 'search' ) . "/$table.html";
+%  $viewall_url = $opt{'viewall_url'} if $opt{'viewall_url'};  
+%
 %  my @menubar = ();
 %  if ( $opt{'menubar'} ) {
 %    @menubar = @{ $opt{'menubar'} };
 %    @menubar = (
 %      'Main menu' => $p, #eventually get rid of this when the ACL/UI update is done
 %      #eventually use Lingua::bs to pluralize
-%      "View all $opt{'name'}s" => $p. ( $opt{'viewall_dir'} || 'search' ).
-%                                  "/$table.html",
+%      "View all $opt{'name'}s" => $viewall_url,
 %    );
 %  }
 %
 
       <TD BGCOLOR="#dddddd"><% $f->{'value'} %></TD>
       <INPUT TYPE="hidden" NAME="<% $field %>" VALUE="<% $f->{'value'} %>">
+% } elsif ( $type eq 'fixedhidden' ) { 
+
+
+      <INPUT TYPE="hidden" NAME="<% $field %>" VALUE="<% $f->{'value'} %>">
 % } elsif ( $type eq 'checkbox' ) { 
 
 
       <TD>
         <INPUT TYPE="checkbox" NAME="<% $field %>" VALUE="<% $f->{'value'} %>" <% $object->$field() eq $f->{'value'} ? ' CHECKED' : '' %>>
       </TD>
+% } elsif ( $type eq 'select' ) { 
+      <TD>
+        <SELECT NAME="<% $field %>" 
+%     my $aref = $f->{'value'}{'values'};
+%     my $vkey = $f->{'value'}{'vcolumn'};
+%     my $ckey = $f->{'value'}{'ccolumn'};
+%     foreach my $v (@$aref) {
+         <OPTION <% ($object->$field() eq $v->$vkey) ? 'SELECTED' : '' %>
+           VALUE="<% $v->$vkey %>"><% $v->$ckey %></OPTION>
+%     }
+       </SELECT>
+      </TD>
 % } else { 
 
 
index da11fc7..dda0bef 100755 (executable)
@@ -7,9 +7,14 @@
 %  $cgi->param('eventpart', '');
 %}
 %
+%my ($creason, $newcreasonT, $newcreason);
+%my ($sreason, $newsreasonT, $newsreason);
+%
+%
 %my ($query) = $cgi->keywords;
 %my $action = '';
 %my $part_bill_event = '';
+%my $currentreasonclass = '';
 %if ( $cgi->param('error') ) {
 %  $part_bill_event = new FS::part_bill_event ( {
 %    map { $_, scalar($cgi->param($_)) } fields('part_bill_event')
@@ -40,7 +45,7 @@
 % } 
 
 
-<FORM ACTION="<% popurl(1) %>process/part_bill_event.cgi" METHOD=POST>
+<FORM ACTION="<% popurl(1) %>process/part_bill_event.cgi" NAME="editEvent" METHOD=POST>
 <INPUT TYPE="hidden" NAME="eventpart" VALUE="<% $part_bill_event->eventpart %>">
 Invoice Event #<% $hashref->{eventpart} ? $hashref->{eventpart} : "(NEW)" %>
 
@@ -159,29 +164,34 @@ Invoice Event #<% $hashref->{eventpart} ? $hashref->{eventpart} : "(NEW)" %>
 %    'name'   => 'Suspend',
 %    'code'   => '$cust_main->suspend();',
 %    'weight' => 10,
+%    'reason' => 'S',
 %  },
 %  'suspend-if-balance' => {
 %    'name'   => 'Suspend if balance (this invoice and previous) over',
 %    'code'   => '$cust_bill->cust_suspend_if_balance_over( %%%balanceover%%% );',
 %    'html'   => " $money_char ". '<INPUT TYPE="text" SIZE="7" NAME="balanceover" VALUE="%%%balanceover%%%">',
 %    'weight' => 10,
+%    'reason' => 'S',
 %  },
 %  'suspend-if-pkgpart' => {
 %    'name'   => 'Suspend packages',
 %    'code'   => '$cust_main->suspend_if_pkgpart(%%%if_pkgpart%%%);',
 %    'html'   => sub { &select_pkgpart('if_pkgpart', @_) },
 %    'weight' => 10,
+%    'reason' => 'S',
 %  },
 %  'suspend-unless-pkgpart' => {
 %    'name'   => 'Suspend packages except',
 %    'code'   => '$cust_main->suspend_unless_pkgpart(%%%unless_pkgpart%%%);',
 %    'html'   => sub { &select_pkgpart('unless_pkgpart', @_) },
 %    'weight' => 10,
+%    'reason' => 'S',
 %  },
 %  'cancel' => {
 %    'name'   => 'Cancel',
 %    'code'   => '$cust_main->cancel();',
 %    'weight' => 10,
+%    'reason' => 'C',
 %  },
 %
 %  'addpost' => {
@@ -397,6 +407,7 @@ Invoice Event #<% $hashref->{eventpart} ? $hashref->{eventpart} : "(NEW)" %>
 %
 %;
 %
+<SCRIPT TYPE="text/javascript">var myreasons = new Array();</SCRIPT>
 %foreach my $event ( keys %events ) {
 %  my %plandata = map { /^(\w+) (.*)$/; ($1, $2); }
 %                   split(/\n/, $part_bill_event->plandata);
@@ -409,9 +420,15 @@ Invoice Event #<% $hashref->{eventpart} ? $hashref->{eventpart} : "(NEW)" %>
 %    $html =~ s/%%%$field%%%/$plandata{$field}/;
 %  }
 %
+<SCRIPT TYPE="text/javascript">myreasons.push('<% $events{$event}{reason} %>');
+</SCRIPT>
+%  if ($event eq $part_bill_event->plan){
+%    $currentreasonclass=$events{$event}{reason};
+%  }
 %  print ntable( "#cccccc", 2).
 %        qq!<TR><TD><INPUT TYPE="radio" NAME="plan_weight_eventcode" !;
 %  print "CHECKED " if $event eq $part_bill_event->plan;
+%  print qq!onClick="showhide_table()" !;
 %  print qq!VALUE="!.  $event. ":". $events{$event}{weight}. ":".
 %        encode_entities($events{$event}{code}).
 %        qq!">$events{$event}{name}</TD>!;
@@ -420,12 +437,73 @@ Invoice Event #<% $hashref->{eventpart} ? $hashref->{eventpart} : "(NEW)" %>
 %  print '</TABLE>';
 %}
 %
-%#print '</TABLE>';
+%  if ($currentreasonclass eq 'C'){
+%    if ($cgi->param('creason') =~ /^(-?\d+)$/){
+%      $creason =  $1;
+%    }else{
+%      $creason = $part_bill_event->reason;
+%    }
+%    if ($cgi->param('newcreasonT') =~ /^(\d+)$/){
+%      $newcreasonT =  $1;
+%    }
+%    if ($cgi->param('newcreason') =~ /^([\w\s]+)$/){
+%      $newcreason =  $1;
+%    }
+%  }elsif ($currentreasonclass eq 'S'){
+%    if ($cgi->param('sreason') =~ /^(-?\d+)$/){
+%      $sreason =  $1;
+%    }else{
+%      $sreason = $part_bill_event->reason;
+%    }
+%    if ($cgi->param('newsreasonT') =~ /^(\d+)$/){
+%      $newsreasonT =  $1;
+%    }
+%    if ($cgi->param('newsreason') =~ /^([\w\s]+)$/){
+%      $newsreason =  $1;
+%    }
+%  }
 %
-%print <<END;
-%</TD></TR>
-%</TABLE>
-%END
+
+</TD></TR>
+</TABLE>
+
+<SCRIPT TYPE="text/javascript">
+  function showhide_table()
+  {
+    for(i=0;i<document.editEvent.plan_weight_eventcode.length;i++){
+      if (document.editEvent.plan_weight_eventcode[i].checked == true){
+        currentevent=i;
+      }
+    }
+    if(myreasons[currentevent] == 'C'){
+      document.getElementById('Ctable').style.display = 'inline';
+      document.getElementById('Stable').style.display = 'none';
+    }else if(myreasons[currentevent] == 'S'){
+      document.getElementById('Ctable').style.display = 'none';
+      document.getElementById('Stable').style.display = 'inline';
+    }else{
+      document.getElementById('Ctable').style.display = 'none';
+      document.getElementById('Stable').style.display = 'none';
+    }
+  }
+</SCRIPT>
+
+<TABLE BGCOLOR="#cccccc" BORDER=0 WIDTH="100%">
+<TR><TD>
+<TABLE BORDER=0 id="Ctable" style="display:<% $currentreasonclass eq 'C' ? 'inline' : 'none' %>">
+<% include('/elements/tr-select-reason.html', 'creason', 'C', $creason, $newcreasonT, $newcreason) %>
+</TABLE>
+</TR></TD>
+</TABLE>
+
+<TABLE BGCOLOR="#cccccc" BORDER=0 WIDTH="100%">
+<TR><TD>
+<TABLE BORDER=0 id="Stable" style="display:<% $currentreasonclass eq 'S' ? 'inline' : 'none' %>">
+<% include('/elements/tr-select-reason.html', 'sreason', 'S', $sreason, $newsreasonT, $newsreason) %>
+</TABLE>
+</TR></TD>
+</TABLE>
+    
 %
 %print qq!<INPUT TYPE="submit" VALUE="!,
 %      $hashref->{eventpart} ? "Apply changes" : "Add invoice event",
index 4811d9c..dd5cd0c 100755 (executable)
@@ -1,5 +1,4 @@
 %
-%
 %my $eventpart = $cgi->param('eventpart');
 %
 %my $old = qsearchs('part_bill_event',{'eventpart'=>$eventpart}) if $eventpart;
 %  $cgi->param('eventcode', $eventcode);
 %  $cgi->param('plandata', $plandata);
 %
-%  my $new = new FS::part_bill_event ( {
-%    map {
-%      $_, scalar($cgi->param($_));
-%    } fields('part_bill_event'),
-%  } );
-%
-%  if ( $eventpart ) {
-%    $error = $new->replace($old);
-%  } else {
-%    $error = $new->insert;
-%    $eventpart = $new->getfield('eventpart');
+%  my $rnum;
+%  my $rtype;
+%  my $reasonm;
+%  if ($eventcode =~ /cancel/) {
+%    $cgi->param('creason') =~ /^(-?\d+)$/ || die "Invalid creason";
+%    $rnum = $1;
+%    if ($rnum == -1) {
+%      $cgi->param('newcreasonT') =~ /^(\d+)$/ || die "Invalid newcreasonT";
+%      $rtype = $1;
+%      $cgi->param('newcreason') =~ /^([\s\w]+)$/ || die "Invalid newcreasonT";
+%      $reasonm = $1;
+%    }
+%  }
+%  if ($eventcode =~ /suspend/) {
+%    $cgi->param('sreason') =~ /^(-?\d+)$/ || die "Invalid sreason";
+%    $rnum = $1;
+%    if ($rnum == -1) {
+%      $cgi->param('newsreasonT') =~ /^(\d+)$/ || die "Invalid newsreasonT";
+%      $rtype = $1;
+%      $cgi->param('newsreason') =~ /^([\s\w]+)$/ || die "Invalid newsreasonT";
+%      $reasonm = $1;
+%    }
+%  }
+% 
+%  if ($rnum == -1 && !$error) {
+%    my $reason = new FS::reason ({ 'reason'      => $reasonm,
+%                                   'reason_type' => $rtype,
+%                                 });
+%    $error = $reason->insert or $rnum = $reason->reasonnum;
+%  }
+%
+%  unless($error){
+%    my $new = new FS::part_bill_event ( {
+%      map {
+%        $_, scalar($cgi->param($_));
+%      } fields('part_bill_event'),
+%    } );
+%    $new->setfield('reason', $rnum);
+%
+%    if ( $eventpart ) {
+%      $error = $new->replace($old);
+%    } else {
+%      $error = $new->insert;
+%      $eventpart = $new->getfield('eventpart');
+%    }
 %  }
 %} 
 %
index 14c471d..60f2ab3 100644 (file)
@@ -215,10 +215,14 @@ tie my %config_employees, 'Tie::IxHash',
 ;
 
 tie my %config_export_svc_pkg, 'Tie::IxHash',
-  'View/Edit exports'             => [ $fsurl.'browse/part_export.cgi', 'Provisioning services to external machines, databases and APIs' ],
-  'View/Edit service definitions' => [ $fsurl.'browse/part_svc.cgi', 'Services are items you offer to your customers' ],
-  'View/Edit package definitions' => [ $fsurl.'browse/part_pkg.cgi', 'One or more services are grouped together into a package and given pricing information. Customers purchase packages, not services' ],
-  'View/Edit package classes'     => [ $fsurl.'browse/pkg_class.html', 'Package classes define groups of packages, for reporting and convenience purposes.' ],
+  'View/Edit exports'              => [ $fsurl.'browse/part_export.cgi', 'Provisioning services to external machines, databases and APIs' ],
+  'View/Edit service definitions'  => [ $fsurl.'browse/part_svc.cgi', 'Services are items you offer to your customers' ],
+  'View/Edit package definitions'  => [ $fsurl.'browse/part_pkg.cgi', 'One or more services are grouped together into a package and given pricing information. Customers purchase packages, not services' ],
+  'View/Edit package classes'      => [ $fsurl.'browse/pkg_class.html', 'Package classes define groups of packages, for reporting and convenience purposes.' ],
+  'View/Edit cancel reason types'  => [ $fsurl.'browse/reason_type.html?class=C', 'Cancel reason types define groups of reasons, for reporting and convenience purposes.' ],
+  'View/Edit cancel reasons'       => [ $fsurl.'browse/reason.html?class=C', 'Cancel reasons explain why a service was cancelled.' ],
+  'View/Edit suspend reason types' => [ $fsurl.'browse/reason_type.html?class=S', 'Suspend reason types define groups of reasons, for reporting and convenience purposes.' ],
+  'View/Edit suspend reasons' => [ $fsurl.'browse/reason_type.html?class=S', 'Suspend reasons explain why a service was suspended.' ],
 ;
 
 tie my %config_agent, 'Tie::IxHash',
index 0278f22..1d65ea7 100755 (executable)
@@ -539,7 +539,7 @@ Current packages
 %
 %sub pkg_suspend_link {
 %  my $pkg = shift or return '';
-%  return qq!<a href="${p}misc/susp_pkg.cgi?$pkg->{pkgnum}">Suspend</a>!;
+%  qq!<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('${p}misc/cancel_pkg.html?method=suspend&pkgnum=$pkg->{pkgnum}', 392, 336, 'suspend_pkg_popup' ), CAPTION, 'Suspend package $pkg->{pkgnum}', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK ); return false;">Suspend</A>!;
 %}
 %
 %sub pkg_unsuspend_link {
@@ -549,14 +549,13 @@ Current packages
 %
 %sub pkg_cancel_link {
 %  my $pkg = shift or return '';
-%  qq!<A HREF="javascript:areyousure('${p}misc/cancel_pkg.cgi?$pkg->{pkgnum}', !.
-%  qq!'Permanently delete included services and cancel this package?')">!.
-%  qq!Cancel now</A>!;
+%
+%  qq!<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('${p}misc/cancel_pkg.html?method=cancel&pkgnum=$pkg->{pkgnum}', 392, 336, 'cancel_pkg_popup' ), CAPTION, 'Cancel package $pkg->{pkgnum}', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK ); return false;">Cancel now</A>!;
 %}
 %
 %sub pkg_expire_link {
 %  my $pkg = shift or return '';
-%  qq!<A HREF="${p}misc/expire_pkg.cgi?$pkg->{pkgnum}">Cancel later</A>!;
+%  qq!<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('${p}misc/cancel_pkg.html?method=expire&pkgnum=$pkg->{pkgnum}', 392, 336, 'expire_pkg_popup' ), CAPTION, 'Expire package $pkg->{pkgnum}', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK ); return false;">Cancel later</A>!;
 %}
 %
 %sub pkg_dates_link {