add package invoice details & comments, RT#3810
authorivan <ivan>
Mon, 8 Sep 2008 02:47:20 +0000 (02:47 +0000)
committerivan <ivan>
Mon, 8 Sep 2008 02:47:20 +0000 (02:47 +0000)
13 files changed:
FS/FS.pm
FS/FS/AccessRight.pm
FS/FS/Schema.pm
FS/FS/cust_main.pm
FS/FS/cust_pkg.pm
FS/FS/cust_pkg_detail.pm [new file with mode: 0644]
FS/MANIFEST
FS/t/cust_pkg_detail.t [new file with mode: 0644]
httemplate/edit/cust_pkg_detail.html [new file with mode: 0644]
httemplate/edit/process/cust_pkg_detail.html [new file with mode: 0644]
httemplate/pref/pref-process.html
httemplate/pref/pref.html
httemplate/view/cust_main/packages.html

index 8480a22..e4c87a9 100644 (file)
--- a/FS/FS.pm
+++ b/FS/FS.pm
@@ -198,6 +198,8 @@ L<FS::cust_pkg> - Customer package class
 
 L<FS::cust_pkg_option> - Customer package option class
 
+L<FS::cust_pkg_detail> - Customer package details class
+
 L<FS::reason_type> - Reason type class
 
 L<FS::reason> - Reason class
index 81b6534..27486da 100644 (file)
@@ -114,6 +114,8 @@ assigned to users and/or groups.
   'Cancel customer package later',
   'Add on-the-fly cancel reason', #NEW
   'Add on-the-fly suspend reason', #NEW
+  'Edit customer package invoice details', #NEW
+  'Edit customer package comments', #NEW
 
 ###
 # customer service rights
index 1d6bd7c..e71ded3 100644 (file)
@@ -791,6 +791,19 @@ sub tables_hashref {
       'index'       => [ [ 'pkgnum' ], [ 'optionname' ] ],
     },
 
+    'cust_pkg_detail' => {
+      'columns' => [
+        'pkgdetailnum', 'serial', '',      '', '', '',
+        'pkgnum',          'int', '',      '', '', '',
+        'detail',      'varchar', '', $char_d, '', '', 
+        'detailtype',     'char', '',       1, '', '', # "I"nvoice or "C"omment
+        'weight',          'int', '',      '', '', '',
+      ],
+      'primary_key' => 'pkgdetailnum',
+      'unique' => [],
+      'index'  => [ [ 'pkgnum', 'detailtype' ] ],
+    },
+
     'cust_pkg_reason' => {
       'columns' => [
         'num',      'serial',    '',   '', '', '', 
index 7da4399..939888e 100644 (file)
@@ -2089,6 +2089,9 @@ sub bill {
 
         warn "    charges (setup=$setup, recur=$recur); adding line items\n"
           if $DEBUG > 1;
+
+        push @details, map { $_->detail } $cust_pkg->cust_pkg_detail('I');
+
         my $cust_bill_pkg = new FS::cust_bill_pkg ({
           'invnum'    => $invnum,
           'pkgnum'    => $cust_pkg->pkgnum,
index c8d1cfe..cbec585 100644 (file)
@@ -14,6 +14,7 @@ use FS::cust_main;
 use FS::type_pkgs;
 use FS::pkg_svc;
 use FS::cust_bill_pkg;
+use FS::cust_pkg_detail;
 use FS::h_cust_svc;
 use FS::reg_code;
 use FS::part_svc;
@@ -999,6 +1000,77 @@ sub cust_bill_pkg {
   qsearch( 'cust_bill_pkg', { 'pkgnum' => $self->pkgnum } );
 }
 
+=item cust_pkg_detail [ DETAILTYPE ]
+
+Returns any customer package details for this package (see
+L<FS::cust_pkg_detail>).
+
+DETAILTYPE can be set to "I" for invoice details or "C" for comments.
+
+=cut
+
+sub cust_pkg_detail {
+  my $self = shift;
+  my %hash = ( 'pkgnum' => $self->pkgnum );
+  $hash{detailtype} = shift if @_;
+  qsearch({
+    'table'    => 'cust_pkg_detail',
+    'hashref'  => \%hash,
+    'order_by' => 'ORDER BY weight, pkgdetailnum',
+  });
+}
+
+=item set_cust_pkg_detail DETAILTYPE [ DETAIL, DETAIL, ... ]
+
+Sets customer package details for this package (see L<FS::cust_pkg_detail>).
+
+DETAILTYPE can be set to "I" for invoice details or "C" for comments.
+
+If there is an error, returns the error, otherwise returns false.
+
+=cut
+
+sub set_cust_pkg_detail {
+  my( $self, $detailtype, @details ) = @_;
+
+  local $SIG{HUP} = 'IGNORE';
+  local $SIG{INT} = 'IGNORE';
+  local $SIG{QUIT} = 'IGNORE';
+  local $SIG{TERM} = 'IGNORE';
+  local $SIG{TSTP} = 'IGNORE';
+  local $SIG{PIPE} = 'IGNORE';
+
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+  my $dbh = dbh;
+
+  foreach my $current ( $self->cust_pkg_detail($detailtype) ) {
+    my $error = $current->delete;
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return "error removing old detail: $error";
+    }
+  }
+
+  foreach my $detail ( @details ) {
+    my $cust_pkg_detail = new FS::cust_pkg_detail {
+      'pkgnum'     => $self->pkgnum,
+      'detailtype' => $detailtype,
+      'detail'     => $detail,
+    };
+    my $error = $cust_pkg_detail->insert;
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return "error adding new detail: $error";
+    }
+
+  }
+
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+  '';
+
+}
+
 =item cust_svc [ SVCPART ]
 
 Returns the services for this package, as FS::cust_svc objects (see
diff --git a/FS/FS/cust_pkg_detail.pm b/FS/FS/cust_pkg_detail.pm
new file mode 100644 (file)
index 0000000..b8c692c
--- /dev/null
@@ -0,0 +1,140 @@
+package FS::cust_pkg_detail;
+
+use strict;
+use vars qw( @ISA );
+use FS::Record qw( qsearch qsearchs );
+
+@ISA = qw(FS::Record);
+
+=head1 NAME
+
+FS::cust_pkg_detail - Object methods for cust_pkg_detail records
+
+=head1 SYNOPSIS
+
+  use FS::cust_pkg_detail;
+
+  $record = new FS::cust_pkg_detail \%hash;
+  $record = new FS::cust_pkg_detail { 'column' => 'value' };
+
+  $error = $record->insert;
+
+  $error = $new_record->replace($old_record);
+
+  $error = $record->delete;
+
+  $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::cust_pkg_detail object represents an example.  FS::cust_pkg_detail inherits from
+FS::Record.  The following fields are currently supported:
+
+=over 4
+
+=item pkgdetailnum
+
+primary key
+
+=item pkgnum
+
+pkgnum
+
+=item detail
+
+detail
+
+=item detailtype
+
+detailtype
+
+=item weight
+
+weight
+
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new example.  To add the example to the database, see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to.  You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+# the new method can be inherited from FS::Record, if a table method is defined
+
+sub table { 'cust_pkg_detail'; }
+
+=item insert
+
+Adds this record to the database.  If there is an error, returns the error,
+otherwise returns false.
+
+=cut
+
+# the insert method can be inherited from FS::Record
+
+=item delete
+
+Delete this record from the database.
+
+=cut
+
+# the delete method can be inherited from FS::Record
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database.  If there is an error,
+returns the error, otherwise returns false.
+
+=cut
+
+# the replace method can be inherited from FS::Record
+
+=item check
+
+Checks all fields to make sure this is a valid example.  If there is
+an error, returns the error, otherwise returns false.  Called by the insert
+and replace methods.
+
+=cut
+
+# the check method should currently be supplied - FS::Record contains some
+# data checking routines
+
+sub check {
+  my $self = shift;
+
+  my $error = 
+    $self->ut_numbern('pkgdetailnum')
+    || $self->ut_number('pkgnum')
+    || $self->ut_text('detail')
+    || $self->ut_('detailtype')
+    || $self->ut_number('weight')
+  ;
+  return $error if $error;
+
+  $self->SUPER::check;
+}
+
+=back
+
+=head1 BUGS
+
+The author forgot to customize this manpage.
+
+=head1 SEE ALSO
+
+L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
index d864d2e..8293b01 100644 (file)
@@ -378,3 +378,5 @@ t/cust_pay_pending.t
 FS/part_pkg_taxclass.pm
 t/part_pkg_taxclass.t
 FS/Yori.pm
+FS/cust_pkg_detail.pm
+t/cust_pkg_detail.t
diff --git a/FS/t/cust_pkg_detail.t b/FS/t/cust_pkg_detail.t
new file mode 100644 (file)
index 0000000..15dec00
--- /dev/null
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::cust_pkg_detail;
+$loaded=1;
+print "ok 1\n";
diff --git a/httemplate/edit/cust_pkg_detail.html b/httemplate/edit/cust_pkg_detail.html
new file mode 100644 (file)
index 0000000..1e4c802
--- /dev/null
@@ -0,0 +1,146 @@
+<% include("/elements/header-popup.html", $title, '',
+            ( $cgi->param('error') ? '' : 'onload="addRow()"' ),
+          )
+%>
+
+%# <% include('/elements/error.html') %>
+
+<FORM ACTION="process/cust_pkg_detail.html" NAME="DetailForm" ID="DetailForm" METHOD="POST">
+
+<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
+<INPUT TYPE="hidden" NAME="detailtype" VALUE="<% $detailtype %>">
+
+<TABLE ID="DetailTable" BGCOLOR="#cccccc" BORDER=0 CELLSPACING=1 STYLE="background-color: #cccccc">
+
+% if ( $curuser->option('show_pkgnum') ) {
+
+    <TR>
+      <TD ALIGN="right">Package #</TD>
+      <TD BGCOLOR="#ffffff"><% $pkgnum %></TD>
+    </TR>
+
+% }
+
+  <TR>
+    <TD ALIGN="right">Package</TD>
+    <TD BGCOLOR="#ffffff"><% $part_pkg->pkg %></TD>
+  </TR>
+
+  <TR>
+    <TD ALIGN="right">Comment</TD>
+    <TD BGCOLOR="#ffffff"><% $part_pkg->comment %></TD>
+  </TR>
+
+  <TR>
+    <TD ALIGN="right">Status</TD>
+    <TD BGCOLOR="#ffffff"><FONT COLOR="#<% $cust_pkg->statuscolor %>"><B><% ucfirst($cust_pkg->status) %></B></FONT></TD>
+  </TR>
+
+  <TR>
+    <TD COLSPAN=2><% ucfirst($name{$detailtype}) %>: </TD>
+  </TR>
+
+% my $row = 0;
+% if ( $cgi->param('error') || $cgi->param('magic') ) {
+%   my $param = $cgi->Vars;
+%
+%   for ( $row = 0; exists($param->{"detail$row"}); $row++ ) { 
+
+      <TR>
+        <TD></TD>
+        <TD>
+          <INPUT TYPE="text" NAME="detail<% $row %>" SIZE="60" MAXLENGTH="65" VALUE="<% $param->{"detail$row"} |h %>" rownum="<% $row %>" onkeyup = "possiblyAddRow;" >
+        </TD>
+      </TR>
+%   } 
+%
+% } 
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" ID="submit" NAME="submit" VALUE="<% $title %>">
+
+</FORM>
+
+<SCRIPT TYPE="text/javascript">
+
+  var rownum = <% $row %>;
+
+  function possiblyAddRow() {
+    if ( ( rownum - this.getAttribute('rownum') ) == 1 ) {
+      addRow();
+    }
+  }
+
+  function addRow() {
+
+    var table = document.getElementById('DetailTable');
+    var tablebody = table.getElementsByTagName('tbody').item(0);
+
+    var row = document.createElement('TR');
+
+    var empty_cell = document.createElement('TD');
+    row.appendChild(empty_cell);
+
+    var detail_cell = document.createElement('TD');
+
+      var detail_input = document.createElement('INPUT');
+      detail_input.setAttribute('name', 'detail'+rownum);
+      detail_input.setAttribute('id',   'detail'+rownum);
+      detail_input.setAttribute('size', 60);
+      detail_input.setAttribute('maxLength', 65);
+      detail_input.setAttribute('rownum',   rownum);
+      detail_input.onkeyup = possiblyAddRow;
+      detail_cell.appendChild(detail_input);
+
+    row.appendChild(detail_cell);
+
+    tablebody.appendChild(row);
+
+    rownum++;
+
+  }
+
+</SCRIPT>
+
+</BODY>
+</HTML>
+<%init>
+
+my %access_right = (
+  'I' => 'Edit customer package invoice details', 
+  'C' => 'Edit customer package comments',
+);
+
+my %name = (
+  'I' => 'invoice details',
+  'C' => 'package comments',
+);
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+$cgi->param('detailtype') =~ /^(\w)$/ or die 'illegal detailtype';
+my $detailtype = $1;
+
+my $right = $access_right{$detailtype};
+die "access denied"
+  unless $curuser->access_right($right);
+
+$cgi->param('pkgnum') =~ /^(\d+)$/ or die 'illegal pkgnum';
+my $pkgnum = $1;
+
+my $cust_pkg = qsearchs({
+  'table'     => 'cust_pkg',
+  'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+  'hashref'   => { 'pkgnum' => $pkgnum },
+  'extra_sql' => ' AND '. $curuser->agentnums_sql,
+});
+
+my $part_pkg = $cust_pkg->part_pkg;
+
+my @details = $cust_pkg->cust_pkg_detail($detailtype);
+
+my $title = ( scalar(@details) ? 'Edit ' : 'Add ' ). $name{$detailtype};
+
+</%init>
diff --git a/httemplate/edit/process/cust_pkg_detail.html b/httemplate/edit/process/cust_pkg_detail.html
new file mode 100644 (file)
index 0000000..132ff63
--- /dev/null
@@ -0,0 +1,59 @@
+% if ( $error ) {
+<% header('Error') %>
+<FONT COLOR="#ff0000"><B><% $error |h %></B></FONT><BR><BR>
+<CENTER><INPUT TYPE="BUTTON" VALUE="OK" onClick="parent.cClick()"></CENTER>
+</BODY></HTML>
+% } else {
+<% header($action) %>
+  <SCRIPT TYPE="text/javascript">
+    window.top.location.reload();
+  </SCRIPT>
+  </BODY></HTML>
+% }
+<%init>
+
+my %access_right = (
+  'I' => 'Edit customer package invoice details', 
+  'C' => 'Edit customer package comments',
+);
+
+my %name = (
+  'I' => 'invoice details',
+  'C' => 'package comments',
+);
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+$cgi->param('detailtype') =~ /^(\w)$/ or die 'illegal detailtype';
+my $detailtype = $1;
+
+my $right = $access_right{$detailtype};
+die "access denied"
+  unless $curuser->access_right($right);
+
+$cgi->param('pkgnum') =~ /^(\d+)$/ or die 'illegal pkgnum';
+my $pkgnum = $1;
+
+my $cust_pkg = qsearchs({
+  'table'     => 'cust_pkg',
+  'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+  'hashref'   => { 'pkgnum' => $pkgnum },
+  'extra_sql' => ' AND '. $curuser->agentnums_sql,
+});
+
+
+my @orig_details = $cust_pkg->cust_pkg_detail($detailtype);
+
+my $action = ucfirst($name{$detailtype}).
+             ( scalar(@orig_details) ? ' changed ' : ' added ' );
+
+my $param = $cgi->Vars;
+my @details = ();
+for ( my $row = 0; exists($param->{"detail$row"}); $row++ ) {
+  push @details, $param->{"detail$row"}
+    if $param->{"detail$row"} =~ /\S/;
+}
+
+my $error = $cust_pkg->set_cust_pkg_detail($detailtype, @details);
+
+</%init>
index 7042865..93d73e0 100644 (file)
@@ -28,7 +28,8 @@
 % }
 %
 % #XXX autogen
-% my @paramlist = qw( menu_position email_address
+% my @paramlist = qw( menu_position show_pkgnum
+%                     email_address
 %                     height width availHeight availWidth colorDepth
 %                   );
 %
index ec8aefd..77f8cec 100644 (file)
@@ -53,8 +53,20 @@ Email Address
  
  </TABLE>
  <BR>
+
+
+Development
+<% ntable("#cccccc",2) %>
+
+  <TR>
+    <TH>Show internal package numbers: </TH>
+    <TD><INPUT TYPE="checkbox" NAME="show_pkgnum" VALUE="1" <% $curuser->option('show_pkgnum') ? 'CHECKED' : '' %>></TD>
+  </TR>
+
+</TABLE>
+<BR>
+
+
 % foreach my $prop (qw( height width availHeight availWidth colorDepth )) {
   <INPUT TYPE="hidden" NAME="<% $prop %>" VALUE="">
   <SCRIPT TYPE="text/javascript">
@@ -67,11 +79,13 @@ Email Address
 <% include('/elements/footer.html') %>
 <%init>
 
+my $curuser = $FS::CurrentUser::CurrentUser;
+
 # XSS via your own preferences?  seems unlikely, but nice try anyway...
-( $FS::CurrentUser::CurrentUser->option('menu_position') || 'left' )
+( $curuser->option('menu_position') || 'left' )
   =~ /^(\w+)$/ or die "illegal menu_position";
 my $menu_position = $1;
-( $FS::CurrentUser::CurrentUser->option('email_address') )
+( $curuser->option('email_address') )
   =~ /^([,\w\@.]*)$/ or die "illegal email_address";  #too late
 my $email_address = $1;
 
index 77ca1cd..5c086f2 100755 (executable)
@@ -13,7 +13,7 @@
        'action'      => $p. 'edit/quick-charge.html?custnum='. $cust_main->custnum,
        'label'       => 'One-time charge',
        'actionlabel' => 'One-time charge',
-       'width'       => 545,
+       'width'       => 763,
      })
   %>
   <BR>
@@ -76,16 +76,33 @@ Current packages
 
 <!--pkgnum: <% $cust_pkg->pkgnum %>-->
 <TR>
-  <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
-    <A NAME="cust_pkg<% $cust_pkg->pkgnum %>"><% $cust_pkg->pkgnum %></A>:
-    <% $part_pkg->pkg %> - <% $part_pkg->comment %>
-    <BR>
+
+  <TD CLASS="inv" BGCOLOR="<% $bgcolor %>">
+    <TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%">
+      <TR>
+        <TD COLSPAN=2>
+          <A NAME="cust_pkg<% $cust_pkg->pkgnum %>"
+             ID  ="cust_pkg<% $cust_pkg->pkgnum %>"
+          ><% $curuser->option('show_pkgnum') ? $cust_pkg->pkgnum.': ' : '' %><% $part_pkg->pkg %></A>
+          - 
+          <% $part_pkg->comment %>
+        </TD>
+      </TR>
 
 %   if ( $cust_pkg->quantity > 1 ) {
-        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quantity: <B><% $cust_pkg->quantity %></B><BR>
+      <TR>
+        <TD COLSPAN=2>
+          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quantity: 
+          <B><% $cust_pkg->quantity %></B>
+        </TD>
+      </TR>
 %   }
 
-    <FONT SIZE=-1>
+      <TR>
+        <TD COLSPAN=2>
+
+          <FONT SIZE=-1>
+
 % unless ( $cust_pkg->get('cancel') ) { 
 % if ( $curuser->access_right('Change customer package') ) { 
 
@@ -101,8 +118,117 @@ Current packages
 % } 
 % } 
 
-    </FONT>
+          </FONT>
+
+        </TD>
+      </TR>
+
+%   my $editi = $curuser->access_right('Edit customer package invoice details');
+%   my $editc = $curuser->access_right('Edit customer package comments');
+%
+%   if ( $cust_pkg->cust_pkg_detail('I') || $cust_pkg->cust_pkg_detail('C')
+%        || $editi || $editc                                                ) {
+%
+%     my $editlink = $p. 'edit/cust_pkg_detail?pkgnum='. $cust_pkg->pkgnum.
+%                    ';detailtype=';
+
+      <TR>
+
+%       if ( $cust_pkg->cust_pkg_detail('I') ) { 
+          <TD VALIGN="top">
+            <% include('/elements/table-grid.html') %>
+              <TR>
+                <TH BGCOLOR="#dddddd" STYLE="border-bottom: dashed 1px black; padding-bottom: 1px">
+                  <FONT SIZE="-1">
+                    Invoice details
+%                   if ( $editi && ! $cust_pkg->get('cancel') ) {
+                      (<% include('/elements/popup_link.html', { 
+                                    'action'      => $editlink. 'I',
+                                    'label'       => 'edit',
+                                    'actionlabel' => 'Edit invoice details',
+                                    'color'       => '#333399',
+                                    'width'       => 763,
+                                 })
+                       %>)
+%                   }
+                  </FONT>
+                </TH>
+              </TR>
+%             foreach my $cust_pkg_detail ( $cust_pkg->cust_pkg_detail('I') ) {
+                <TR>
+                  <TD><FONT SIZE="-1">&nbsp;-&nbsp;<% $cust_pkg_detail->detail |h %></FONT></TD>
+                </TR>
+%             }
+            </TABLE>
+          </TD>
+%       } else {
+          <TD>
+%           if ( $editi && ! $cust_pkg->get('cancel') ) {
+              <FONT SIZE="-1">
+                (&nbsp;<% include('/elements/popup_link.html', { 
+                               'action'      => $editlink. 'I',
+                               'label'       => 'Add&nbsp;invoice&nbsp;details',
+                               'actionlabel' => 'Add invoice details',
+                               'color'       => '#333399',
+                               'width'       => 763,
+                            })
+                  %>&nbsp;)
+              </FONT>
+%           }
+          </TD>
+%       }
+
+%       if ( $cust_pkg->cust_pkg_detail('C') ) { 
+          <TD VALIGN="top">
+            <% include('/elements/table-grid.html') %>
+              <TR>
+                <TH BGCOLOR="#dddddd" STYLE="border-bottom: dashed 1px black; padding-bottom: 1px">
+                  <FONT SIZE="-1">
+                    Comments
+%                   if ( $editc ) {
+                      (<% include('/elements/popup_link.html', { 
+                                    'action'      => $editlink. 'C',
+                                    'label'       => 'edit',
+                                    'actionlabel' => 'Edit comments',
+                                    'color'       => '#333399',
+                                    'width'       => 763,
+                                 })
+                       %>)
+%                   }
+                  </FONT>
+                </TH>
+              </TR>
+%             foreach my $cust_pkg_detail ( $cust_pkg->cust_pkg_detail('C') ) {
+                <TR>
+                  <TD><FONT SIZE="-1">&nbsp;-&nbsp;<% $cust_pkg_detail->detail |h %></FONT></TD>
+                </TR>
+%             }
+            </TABLE>
+          </TD>
+%       } else {
+          <TD>
+%           if ( $editc ) {
+              <FONT SIZE="-1">
+                (&nbsp;<% include('/elements/popup_link.html', { 
+                               'action'      => $editlink. 'C',
+                               'label'       => 'Add&nbsp;comments',
+                               'actionlabel' => 'Add comments',
+                               'color'       => '#333399',
+                               'width'       => 763,
+                            })
+                  %>&nbsp;)
+              </FONT>
+%           }
+          </TD>
+%       }
+
+      </TR>
+%   }
+
+    </TABLE>
+
   </TD>
+
   <TD CLASS="inv" BGCOLOR="<% $bgcolor %>">
     <TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%">
 %