add prepaid support which sets RADIUS Expiration attribute, update customer view...
authorivan <ivan>
Wed, 21 Sep 2005 12:49:51 +0000 (12:49 +0000)
committerivan <ivan>
Wed, 21 Sep 2005 12:49:51 +0000 (12:49 +0000)
FS/FS/Conf.pm
FS/FS/Record.pm
FS/FS/svc_acct.pm
FS/MANIFEST
FS/bin/freeside-daily
FS/bin/freeside-prepaidd [new file with mode: 0644]
httemplate/edit/REAL_cust_pkg.cgi
httemplate/view/cust_main/packages.html
init.d/freeside-init

index 463d0b4..37d649b 100644 (file)
@@ -1562,6 +1562,13 @@ httemplate/docs/config.html
     ],
   },
 
+  {
+    'key'         => 'cust_pkg-display_times',
+    'section'     => 'UI',
+    'description' => 'Display full timestamps (not just dates) for customer packages.  Useful if you are doing real-time things like hourly prepaid.',
+    'type'        => 'checkbox',
+  },
+
 );
 
 1;
index 9cff579..d843658 100644 (file)
@@ -185,13 +185,36 @@ sub create {
   }
 }
 
-=item qsearch TABLE, HASHREF, SELECT, EXTRA_SQL, CACHE_OBJ, ADDL_FROM
+=item qsearch PARAMS_HASHREF | TABLE, HASHREF, SELECT, EXTRA_SQL, CACHE_OBJ, ADDL_FROM
 
 Searches the database for all records matching (at least) the key/value pairs
 in HASHREF.  Returns all the records found as `FS::TABLE' objects if that
 module is loaded (i.e. via `use FS::cust_main;'), otherwise returns FS::Record
 objects.
 
+The preferred usage is to pass a hash reference of named parameters:
+
+  my @records = qsearch( {
+                           'table'     => 'table_name',
+                           'hashref'   => { 'field' => 'value'
+                                            'field' => { 'op'    => '<',
+                                                         'value' => '420',
+                                                       },
+                                          },
+
+                           #these are optional...
+                           'select'    => '*',
+                           'extra_sql' => 'AND field ',
+                           #'cache_obj' => '', #optional
+                           'addl_from' => 'LEFT JOIN othtable USING ( field )',
+                         }
+                       );
+
+Much code still uses old-style positional parameters, this is also probably
+fine in the common case where there are only two parameters:
+
+  my @records = qsearch( 'table', { 'field' => 'value' } );
+
 ###oops, argh, FS::Record::new only lets us create database fields.
 #Normal behaviour if SELECT is not specified is `*', as in
 #C<SELECT * FROM table WHERE ...>.  However, there is an experimental new
@@ -204,12 +227,24 @@ objects.
 =cut
 
 sub qsearch {
-  my($stable, $record, $select, $extra_sql, $cache, $addl_from ) = @_;
+  my($stable, $record, $select, $extra_sql, $cache, $addl_from );
+  if ( ref($_[0]) ) { #hashref for now, eventually maybe accept a list too
+    my $opt = shift;
+    $stable    = $opt->{'table'}     or die "table name is required";
+    $record    = $opt->{'hashref'}   || {};
+    $select    = $opt->{'select'}    || '*';
+    $extra_sql = $opt->{'extra_sql'} || '';
+    $cache     = $opt->{'cache_obj'} || '';
+    $addl_from = $opt->{'addl_from'} || '';
+  } else {
+    ($stable, $record, $select, $extra_sql, $cache, $addl_from ) = @_;
+    $select ||= '*';
+  }
+
   #$stable =~ /^([\w\_]+)$/ or die "Illegal table: $table";
   #for jsearch
   $stable =~ /^([\w\s\(\)\.\,\=]+)$/ or die "Illegal table: $stable";
   $stable = $1;
-  $select ||= '*';
   my $dbh = dbh;
 
   my $table = $cache ? $cache->table : $stable;
@@ -471,7 +506,7 @@ sub jsearch {
   );
 }
 
-=item qsearchs TABLE, HASHREF, SELECT, EXTRA_SQL, CACHE_OBJ, ADDL_FROM
+=item qsearchs PARAMS_HASHREF | TABLE, HASHREF, SELECT, EXTRA_SQL, CACHE_OBJ, ADDL_FROM
 
 Same as qsearch, except that if more than one record matches, it B<carp>s but
 returns the first.  If this happens, you either made a logic error in asking
index 1ec5429..de89819 100644 (file)
@@ -15,6 +15,7 @@ use vars qw( @ISA $DEBUG $me $conf $skip_fuzzyfiles
              @saltset @pw_set );
 use Carp;
 use Fcntl qw(:flock);
+use Date::Format;
 use Crypt::PasswdMD5 1.2;
 use FS::UID qw( datasrc );
 use FS::Conf;
@@ -1011,6 +1012,7 @@ expected to change in the future.
 
 sub radius_reply { 
   my $self = shift;
+
   my %reply =
     map {
       /^(radius_(.*))$/;
@@ -1018,12 +1020,15 @@ sub radius_reply {
       #$attrib =~ s/_/\-/g;
       ( $FS::raddb::attrib{lc($attrib)}, $self->getfield($column) );
     } grep { /^radius_/ && $self->getfield($_) } fields( $self->table );
+
   if ( $self->slipip && $self->slipip ne '0e0' ) {
     $reply{$radius_ip} = $self->slipip;
   }
+
   if ( $self->seconds !~ /^$/ ) {
     $reply{'Session-Timeout'} = $self->seconds;
   }
+
   %reply;
 }
 
@@ -1040,16 +1045,25 @@ expected to change in the future.
 
 sub radius_check {
   my $self = shift;
-  my $password = $self->_password;
-  my $pw_attrib = length($password) <= 12 ? $radius_password : 'Crypt-Password';
-  ( $pw_attrib => $password,
+
+  my %check = 
     map {
       /^(rc_(.*))$/;
       my($column, $attrib) = ($1, $2);
       #$attrib =~ s/_/\-/g;
       ( $FS::raddb::attrib{lc($attrib)}, $self->getfield($column) );
-    } grep { /^rc_/ && $self->getfield($_) } fields( $self->table )
-  );
+    } grep { /^rc_/ && $self->getfield($_) } fields( $self->table );
+
+  my $password = $self->_password;
+  my $pw_attrib = length($password) <= 12 ? $radius_password : 'Crypt-Password';  $check{$pw_attrib} = $password;
+
+  my $cust_pkg = $self->cust_svc->cust_pkg;
+  if ( $cust_pkg && $cust_pkg->part_pkg->is_prepaid ) {
+    $check{'Expiration'} = time2str('%B %e %Y %T', $cust_pkg->bill ); #http://lists.cistron.nl/pipermail/freeradius-users/2005-January/040184.html
+  }
+
+  %check;
+
 }
 
 =item domain
@@ -1086,10 +1100,7 @@ Returns the FS::cust_svc record for this account (see L<FS::cust_svc>).
 
 =cut
 
-sub cust_svc {
-  my $self = shift;
-  qsearchs( 'cust_svc', { 'svcnum' => $self->svcnum } );
-}
+#inherited from svc_Common
 
 =item email
 
index f756b5c..e7d9dea 100644 (file)
@@ -291,3 +291,4 @@ FS/banned_pay.pm
 t/banned_pay.t
 FS/cancel_reason.pm
 t/cancel_reason.t
+bin/freeside-prepaidd
index 589af89..603da12 100755 (executable)
@@ -89,6 +89,19 @@ foreach $cust_main ( @cust_main ) {
          $cust_main->custnum. ": $error"
       if $error;
   }
+  # $^T not $time because -d is for pre-printing invoices
+  foreach my $cust_pkg (
+    grep { $_->part_pkg->is_prepaid
+           && $_->bill && $_->bill < $^T && ! $_->susp
+         }
+         $cust_main->ncancelled_pkgs
+  ) {
+    my $error = $cust_pkg->suspend;
+    warn "Error suspending package ". $cust_pkg->pkgnum.
+         " for custnum ". $cust_main->custnum.
+         ": $error"
+      if $error;
+  }
 
   my $error = $cust_main->bill( 'time'    => $time,
                                 'resetup' => $opt_s, );
diff --git a/FS/bin/freeside-prepaidd b/FS/bin/freeside-prepaidd
new file mode 100644 (file)
index 0000000..e51a563
--- /dev/null
@@ -0,0 +1,75 @@
+#!/usr/bin/perl -w
+
+use strict;
+use FS::Daemon qw(daemonize1 drop_root logfile daemonize2 sigint sigterm);
+use FS::UID qw(adminsuidsetup);
+use FS::Record qw(qsearch); # qsearchs);
+use FS::cust_pkg;
+
+my $user = shift or die &usage;
+
+#daemonize1('freeside-sprepaidd', $user); #keep unique pid files w/multi installs
+daemonize1('freeside-prepaidd');
+
+drop_root();
+
+adminsuidsetup($user);
+
+logfile( "/usr/local/etc/freeside/prepaidd-log.". $FS::UID::datasrc );
+
+daemonize2();
+
+#--
+
+while (1) {
+
+  foreach my $cust_pkg ( 
+    qsearch( {
+      'select'    => 'cust_pkg.*, part_pkg.plan',
+      'table'     => 'cust_pkg',
+      'addl_from' => 'LEFT JOIN part_pkg USING ( pkgpart )',
+      #'hashref'   => { 'plan' => 'prepaid' },#should check part_pkg::is_prepaid
+      #'extra_sql' => "AND bill < ". time.
+      'hashref'   => {},
+      'extra_sql' => "WHERE plan = 'prepaid' AND bill < ". time.
+                     " AND bill IS NOT NULL".
+                     " AND ( susp   IS NULL OR susp   = 0)".
+                     " AND ( cancel IS NULL OR cancel = 0)"
+    } )
+  ) {
+    my $error = $cust_pkg->suspend;
+    warn "Error suspended package ". $cust_pkg->pkgnum.
+         " for custnum ". $cust_pkg->custnum.
+         ": $error\n"
+      if $error;
+  }
+
+  die "exiting" if sigterm() || sigint();
+  sleep 5;
+
+}
+
+#--
+
+sub usage { 
+  die "Usage:\n\n  freeside-prepaidd user\n";
+}
+
+=head1 NAME
+
+freeside-prepaidd - Real-time daemon for prepaid packages
+
+=head1 SYNOPSIS
+
+  freeside-prepaidd
+
+=head1 DESCRIPTION
+
+Runs continuously and suspendes any prepaid customer packages which have
+passed their renewal date (next bill date).
+
+=head1 SEE ALSO
+
+=cut
+
+1;
index 2f6be7c..78dd0fa 100755 (executable)
@@ -1,6 +1,4 @@
-<!-- mason kludge -->
 <%
-# <!-- $Id: REAL_cust_pkg.cgi,v 1.9 2005-02-27 11:05:35 ivan Exp $ -->
 
 my $error ='';
 my $pkgnum = '';
@@ -33,17 +31,20 @@ if ( $error ) {
 }
 
 #my $custnum = $cust_pkg->getfield('custnum');
-print header('Package Edit'); #, menubar(
+%>
+
+<%= header('Customer package - Edit dates') %>
+<%
+#, menubar(
 #  "View this customer (#$custnum)" => popurl(2). "view/cust_main.cgi?$custnum",
 #  'Main Menu' => popurl(2)
 #));
-
 %>
 
-    <LINK REL="stylesheet" TYPE="text/css" HREF="../elements/calendar-win2k-2.css" TITLE="win2k-2">
-    <SCRIPT TYPE="text/javascript" SRC="../elements/calendar_stripped.js"></SCRIPT>
-    <SCRIPT TYPE="text/javascript" SRC="../elements/calendar-en.js"></SCRIPT>
-    <SCRIPT TYPE="text/javascript" SRC="../elements/calendar-setup.js"></SCRIPT>
+<LINK REL="stylesheet" TYPE="text/css" HREF="../elements/calendar-win2k-2.css" TITLE="win2k-2">
+<SCRIPT TYPE="text/javascript" SRC="../elements/calendar_stripped.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="../elements/calendar-en.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="../elements/calendar-setup.js"></SCRIPT>
 
 <%
 
@@ -57,67 +58,106 @@ my($pkg,$comment)=($part_pkg->getfield('pkg'),$part_pkg->getfield('comment'));
 my($setup,$bill)=($cust_pkg->getfield('setup'),$cust_pkg->getfield('bill'));
 my $otaker = $cust_pkg->getfield('otaker');
 
-print '<FORM NAME="formname" ACTION="process/REAL_cust_pkg.cgi" METHOD="POST">',      qq!<INPUT TYPE="hidden" NAME="pkgnum" VALUE="$pkgnum">!;
+%>
+
+<FORM NAME="formname" ACTION="process/REAL_cust_pkg.cgi" METHOD="POST">
+<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<%= $pkgnum %>">
+
+<% if ( $error ) { %>
+  <FONT SIZE="+1" COLOR="#ff0000">Error: <%= $error %></FONT>
+<% } %>
 
-print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: $error</FONT>!
-  if $error;
+<%
 
 #my $format = "%c %z (%Z)";
 my $format = "%m/%d/%Y %T %z (%Z)";
 
-print ntable("#cccccc",2),
-      '<TR><TD ALIGN="right">Package number</TD><TD BGCOLOR="#ffffff">',
-      $pkgnum, '</TD></TR>',
-      '<TR><TD ALIGN="right">Package</TD><TD BGCOLOR="#ffffff">',
-      $pkg,  '</TD></TR>',
-      '<TR><TD ALIGN="right">Comment</TD><TD BGCOLOR="#ffffff">',
-      $comment,  '</TD></TR>',
-      '<TR><TD ALIGN="right">Order taker</TD><TD BGCOLOR="#ffffff">',
-      $otaker,  '</TD></TR>',
-      '<TR><TD ALIGN="right">Setup date</TD><TD>'.
-      '<INPUT TYPE="text" NAME="setup" SIZE=32 ID="setup_text" VALUE="',
-      ( $setup ? time2str($format, $setup) : "" ), '">'.
-      ' <IMG SRC="../images/calendar.png" ID="setup_button" STYLE="cursor: pointer" TITLE="Select date">'.
-      '</TD></TR>';
-
-print '<TR><TD ALIGN="right">Last bill date</TD><TD>',
-      '<INPUT TYPE="text" NAME="last_bill" SIZE=32 ID="last_bill_text" VALUE="',
-      ( $cust_pkg->last_bill
-        ? time2str($format, $cust_pkg->last_bill)
-        : ""                                          ),
-      '">'.
-      ' <IMG SRC="../images/calendar.png" ID="last_bill_button" STYLE="cursor: pointer" TITLE="Select date">'.
-      '</TD></TR>'
-  if $cust_pkg->dbdef_table->column('last_bill');
-
-print '<TR><TD ALIGN="right">Next bill date</TD><TD>',
-      '<INPUT TYPE="text" NAME="bill" SIZE=32 ID="bill_text" VALUE="',
-      ( $bill ? time2str($format, $bill) : "" ), '">'.
-      ' <IMG SRC="../images/calendar.png" ID="bill_button" STYLE="cursor: pointer" TITLE="Select date">'.
-      '</TD></TR>';
-
-print '<TR><TD ALIGN="right">Suspension date</TD><TD BGCOLOR="#ffffff">',
-       time2str($format, $susp), '</TD></TR>'
-  if $susp;
-
-#print '<TR><TD ALIGN="right">Expiration date</TD><TD BGCOLOR="#ffffff">',
-#       time2str("%D",$expire), '</TD></TR>'
-#  if $expire;
-print '<TR><TD ALIGN="right">Expiration date'.
-      '</TD><TD>',
-      '<INPUT TYPE="text" NAME="expire" SIZE=32 ID="expire_text" VALUE="',
-      ( $expire ? time2str($format, $expire) : "" ), '">'.
-      ' <IMG SRC="../images/calendar.png" ID="expire_button" STYLE="cursor: pointer" TITLE="Select date">'.
-      '<BR><FONT SIZE=-1>(will <b>cancel</b> this package'.
-      ' when the date is reached)</FONT>'.
-      '</TD></TR>';
-
-print '<TR><TD ALIGN="right">Cancellation date</TD><TD BGCOLOR="#ffffff">',
-       time2str($format, $cancel), '</TD></TR>'
-  if $cancel;
+#false laziness w/view/cust_main/packages.html
+#my( $billed_or_prepaid,
+my( $last_bill_or_renewed, $next_bill_or_prepaid_until );
+unless ( $part_pkg->is_prepaid ) {
+  #$billed_or_prepaid = 'billed';
+  $last_bill_or_renewed = 'Last bill';
+  $next_bill_or_prepaid_until = 'Next bill';
+} else {
+  #$billed_or_prepaid = 'prepaid';
+  $last_bill_or_renewed = 'Renewed';
+  $next_bill_or_prepaid_until = 'Prepaid until';
+}
 
 %>
+
+<%= ntable("#cccccc",2) %>
+
+  <TR>
+    <TD ALIGN="right">Package number</TD>
+    <TD BGCOLOR="#ffffff"><%= $pkgnum %></TD>
+  </TR>
+
+  <TR>
+    <TD ALIGN="right">Package</TD>
+    <TD BGCOLOR="#ffffff"><%= $pkg %></TD>
+  </TR>
+
+  <TR>
+    <TD ALIGN="right">Comment</TD>
+    <TD BGCOLOR="#ffffff"><%= $comment %></TD>
+  </TR>
+
+  <TR>
+    <TD ALIGN="right">Order taker</TD>
+    <TD BGCOLOR="#ffffff"><%= $otaker %></TD>
+  </TR>
+
+  <TR>
+    <TD ALIGN="right">Setup date</TD>
+    <TD>
+      <INPUT TYPE="text" NAME="setup" SIZE=32 ID="setup_text" VALUE="<%= ( $setup ? time2str($format, $setup) : "" ) %>">
+      <IMG SRC="../images/calendar.png" ID="setup_button" STYLE="cursor: pointer" TITLE="Select date">
+    </TD>
+  </TR>
+
+  <TR>
+    <TD ALIGN="right"><%= $last_bill_or_renewed %> date</TD>
+    <TD>
+      <INPUT TYPE="text" NAME="last_bill" SIZE=32 ID="last_bill_text" VALUE="<%= ( $cust_pkg->last_bill ? time2str($format, $cust_pkg->last_bill) : "" ) %>">
+      <IMG SRC="../images/calendar.png" ID="last_bill_button" STYLE="cursor: pointer" TITLE="Select date">
+    </TD>
+  </TR>
+
+  <TR>
+    <TD ALIGN="right"><%= $next_bill_or_prepaid_until %> date</TD>
+    <TD>
+      <INPUT TYPE="text" NAME="bill" SIZE=32 ID="bill_text" VALUE="<%= ( $bill ? time2str($format, $bill) : "" ) %>">
+      <IMG SRC="../images/calendar.png" ID="bill_button" STYLE="cursor: pointer" TITLE="Select date">
+    </TD>
+  </TR>
+
+  <% if ( $susp ) { %>
+    <TR>
+      <TD ALIGN="right">Suspension date</TD>
+      <TD BGCOLOR="#ffffff"><%= time2str($format, $susp) %></TD>
+    </TR>
+  <% } %>
+
+  <TR>
+    <TD ALIGN="right">Expiration date</TD>
+    <TD>
+      <INPUT TYPE="text" NAME="expire" SIZE=32 ID="expire_text" VALUE="<%= ( $expire ? time2str($format, $expire) : "" ) %>">
+      <IMG SRC="../images/calendar.png" ID="expire_button" STYLE="cursor: pointer" TITLE="Select date">
+      <BR><FONT SIZE=-1>(will <b>cancel</b> this package when the date is reached)</FONT>
+    </TD>
+  </TR>
+
+  <% if ( $cancel ) { %>
+    <TR>
+      <TD ALIGN="right">Cancellation date</TD>
+      <TD BGCOLOR="#ffffff"><%= time2str($format, $cancel) %></TD>
+    </TR>
+  <% } %>
+
 </TABLE>
+
 <SCRIPT TYPE="text/javascript">
 <%
   my @cal = qw( setup bill expire );
index 068a827..ece1b62 100755 (executable)
@@ -5,6 +5,10 @@
   my $packages = get_packages($cust_main, $conf);
 %>
 
+<STYLE TYPE="text/css">
+.package .provision { font-weight: bold }
+</STYLE>
+
 <A NAME="cust_pkg"><FONT SIZE="+2">Packages</FONT></A>
 
 <%= include('order_pkg.html', $cust_main ) %>
@@ -71,12 +75,10 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) {
     (&nbsp;<%=pkg_dates_link($pkg)%>&nbsp;|&nbsp;<%=pkg_customize_link($pkg,$cust_main->custnum)%>&nbsp;)
 <% } %>
   </TD>
-<%
-  #foreach (qw(setup last_bill next_bill susp expire cancel)) {
-  #  print qq!  <TD ROWSPAN=$rowspan>! . pkg_datestr($pkg,$_,$conf) . qq!</TD>\n!;
-  #}
-  print "<TD ROWSPAN=$rowspan>". &itable('');
+  <TD ROWSPAN=<%=$rowspan%>>
+    <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%">
 
+<%
   sub myfreq {
     my $part_pkg = shift;
     my $freq = $part_pkg->freq_pretty;
@@ -84,92 +86,190 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) {
     $freq;
   }
 
-  if ( $pkg->{cancel} ) { #status: cancelled
-
-    print '<TR><TD><FONT COLOR="#ff0000"><B>Cancelled&nbsp;</B></FONT></TD>'.
-          '<TD>'. pkg_datestr($pkg,'cancel',$conf). '</TD></TR>';
-    unless ( $pkg->{setup} ) {
-      print '<TR><TD COLSPAN=2>Never billed</TD></TR>';
-    } else {
-      print "<TR><TD>Setup&nbsp;</TD><TD>".
-            pkg_datestr($pkg, 'setup',$conf). '</TD></TR>';
-      print "<TR><TD>Last&nbsp;bill&nbsp;</TD><TD>".
-            pkg_datestr($pkg, 'last_bill',$conf). '</TD></TR>'
-        if $pkg->{'last_bill'};
-      print "<TR><TD>Suspended&nbsp;</TD><TD>".
-            pkg_datestr($pkg, 'susp',$conf). '</TD></TR>'
-        if $pkg->{'susp'};
-    }
+  #this should use cust_pkg->status and cust_pkg->statuscolor eventually
+
+  my $colspan = $conf->exists('cust_pkg-display_times') ? 8 : 4;
+  my $width = $conf->exists('cust_pkg-display_times') ? '38%' : '56%';
 
+  #false laziness w/edit/REAL_cust_pkg.cgi
+  my( $billed_or_prepaid, $last_bill_or_renewed, $next_bill_or_prepaid_until );
+  unless ( $pkg->{'part_pkg'}->is_prepaid ) {
+    $billed_or_prepaid = 'billed';
+    $last_bill_or_renewed = 'Last&nbsp;bill';
+    $next_bill_or_prepaid_until = 'Next&nbsp;bill';
   } else {
+    $billed_or_prepaid = 'prepaid';
+    $last_bill_or_renewed = 'Renewed';
+    $next_bill_or_prepaid_until = 'Prepaid&nbsp;until';
+  }
 
-    if ( $pkg->{susp} ) { #status: suspended
-      print '<TR><TD><FONT COLOR="#FF9900"><B>Suspended</B>&nbsp;</FONT></TD>'.
-            '<TD>'. pkg_datestr($pkg,'susp',$conf). '</TD></TR>';
-      unless ( $pkg->{setup} ) {
-        print '<TR><TD COLSPAN=2>Never billed</TD></TR>';
-      } else {
-        print "<TR><TD>Setup&nbsp;</TD><TD>". 
-              pkg_datestr($pkg, 'setup',$conf). '</TD></TR>';
-      }
-      print "<TR><TD>Last&nbsp;bill&nbsp;</TD><TD>".
-            pkg_datestr($pkg, 'last_bill',$conf). '</TD></TR>'
-        if $pkg->{'last_bill'};
-      # next bill ??
-      print "<TR><TD>Expires&nbsp;</TD><TD>".
-            pkg_datestr($pkg, 'expire',$conf). '</TD></TR>'
-        if $pkg->{'expire'};
-      print '<TR><TD COLSPAN=2>(&nbsp;'. pkg_unsuspend_link($pkg).
-            '&nbsp;|&nbsp;'. pkg_cancel_link($pkg). '&nbsp;)</TD></TR>';
-
-    } else { #status: active
-
-      unless ( $pkg->{setup} ) { #not setup
-
-        print '<TR><TD COLSPAN=2>Not&nbsp;yet&nbsp;billed&nbsp;(';
-        unless ( $pkg->{freq} ) {
-          print 'one-time&nbsp;charge)</TD></TR>';
-          print '<TR><TD COLSPAN=2>(&nbsp;'. pkg_cancel_link($pkg).
-                '&nbsp;)</TD</TR>';
-        } else {
-          print 'billed&nbsp;'. myfreq($pkg->{part_pkg}). ')</TD></TR>';
-        }
-
-      } else { #setup
-
-        unless ( $pkg->{freq} ) {
-          print "<TR><TD COLSPAN=2>One-time&nbsp;charge</TD></TR>".
-                '<TR><TD>Billed&nbsp;</TD><TD>'.
-                pkg_datestr($pkg,'setup',$conf). '</TD></TR>';
-        } else {
-          print '<TR><TD COLSPAN=2><FONT COLOR="#00CC00"><B>Active</B></FONT>'.
-                ',&nbsp;billed&nbsp;'. myfreq($pkg->{part_pkg}). '</TD></TR>'.
-                '<TR><TD>Setup&nbsp;</TD><TD>'.
-                pkg_datestr($pkg, 'setup',$conf). '</TD></TR>';
-        }
-
-      }
-
-      print "<TR><TD>Last&nbsp;bill&nbsp;</TD><TD>".
-            pkg_datestr($pkg, 'last_bill',$conf). '</TD></TR>'
-        if $pkg->{'last_bill'};
-      print "<TR><TD>Next&nbsp;bill&nbsp;</TD><TD>".
-            pkg_datestr($pkg, 'next_bill',$conf). '</TD></TR>'
-        if $pkg->{'next_bill'};
-      print "<TR><TD>Expires&nbsp;</TD><TD>".
-            pkg_datestr($pkg, 'expire',$conf). '</TD></TR>'
-        if $pkg->{'expire'};
-      if ( $pkg->{freq} ) {
-        print '<TR><TD COLSPAN=2>(&nbsp;'. pkg_suspend_link($pkg).
-              '&nbsp;|&nbsp;'. pkg_cancel_link($pkg). '&nbsp;)</TD></TR>';
-      }
+%>
 
-    }
+<% if ( $pkg->{cancel} ) { %> <!-- #status: cancelled -->
 
-  }
+  <TR>
+    <TD WIDTH="<%=$width%>" ALIGN="right"><FONT COLOR="#ff0000"><B>Cancelled&nbsp;</B></FONT></TD>
+    <%= pkg_datestr($pkg,'cancel',$conf) %>
+  </TR>
+
+  <% unless ( $pkg->{setup} ) { %>
+
+    <TR>
+      <TD COLSPAN=<%=$colspan%>>Never billed</TD>
+    </TR>
+
+  <% } else { %>
+
+    <TR>
+      <TD WIDTH="<%=$width%>" ALIGN="right">Setup&nbsp;</TD>
+      <%= pkg_datestr($pkg, 'setup',$conf) %>
+    </TR>
+
+    <% if ( $pkg->{'last_bill'} ) { %>
+      <TR>
+        <TD WIDTH="<%=$width%>" ALIGN="right"><%= $last_bill_or_renewed %>&nbsp;</TD>
+        <%= pkg_datestr($pkg, 'last_bill',$conf) %>
+      </TR>
+    <% } %>
+
+    <% if ( $pkg->{'susp'} ) { %>
+      <TR>
+        <TD WIDTH="<%=$width%>" ALIGN="right">Suspended&nbsp;</TD>
+        <%= pkg_datestr($pkg, 'susp',$conf) %>
+      </TR>
+    <% } %>
+
+  <% } %>
+
+<% } else { %>
+
+  <% if ( $pkg->{susp} ) { %> <!-- #status: suspended -->
+
+    <TR>
+      <TD WIDTH="<%=$width%>" ALIGN="right"><FONT COLOR="#FF9900"><B>Suspended</B>&nbsp;</FONT></TD>
+      <%= pkg_datestr($pkg,'susp',$conf) %>
+    </TR>
+
+    <% unless ( $pkg->{setup} ) { %>
+
+      <TR>
+        <TD COLSPAN=<%=$colspan%>>Never billed</TD>
+      </TR>
+
+    <% } else { %>
+
+      <TR>
+        <TD WIDTH="<%=$width%>" ALIGN="right">Setup&nbsp;</TD>
+        <%= pkg_datestr($pkg, 'setup',$conf) %>
+      </TR>
+      
+    <% } %>
+
+    <% if ( $pkg->{'last_bill'} ) { %>
+      <TR>
+        <TD WIDTH="<%=$width%>" ALIGN="right"><%= $last_bill_or_renewed %>&nbsp;</TD>
+        <%= pkg_datestr($pkg, 'last_bill',$conf) %>
+      </TR>
+    <% } %>
+
+    <!-- # next bill ?? -->
+
+    <% if ( $pkg->{'expire'} ) { %>
+      <TR>
+        <TD WIDTH="<%=$width%>" ALIGN="right">Expires&nbsp;</TD>
+        <%= pkg_datestr($pkg, 'expire',$conf) %>
+      </TR>
+    <% } %>
 
-  print "</TABLE></TD>\n";
+    <TR>
+      <TD COLSPAN=<%=$colspan%>>(&nbsp;<%= pkg_unsuspend_link($pkg) %>&nbsp;|&nbsp;<%= pkg_cancel_link($pkg) %>&nbsp;)</TD>
+    </TR>
 
+  <% } else { %> <!-- #status: active -->
+
+    <% unless ( $pkg->{setup} ) { %> <!-- #not setup -->
+
+      <% unless ( $pkg->{'freq'} ) { %>
+
+        <TR>
+          <TD COLSPAN=<%=$colspan%>>Not&nbsp;yet&nbsp;billed&nbsp;(one-time&nbsp;charge)</TD>
+        </TR>
+
+        <TR>
+          <TD COLSPAN=<%=$colspan%>>(&nbsp;<%= pkg_cancel_link($pkg) %>&nbsp;)</TD>
+        </TR>
+
+      <% } else { %>
+
+        <TR>
+          <TD COLSPAN=<%=$colspan%>>Not&nbsp;yet&nbsp;billed&nbsp;(<%= $billed_or_prepaid %>&nbsp;<%= myfreq($pkg->{part_pkg}) %>)</TD>
+        </TR>
+
+      <% } %>
+
+    <% } else { %> <!-- #setup -->
+
+      <% unless ( $pkg->{freq} ) { %>
+
+        <TR>
+          <TD COLSPAN=<%=$colspan%>>One-time&nbsp;charge</TD>
+        </TR>
+
+        <TR>
+          <TD WIDTH="<%=$width%>" ALIGN="right">Billed&nbsp;</TD>
+          <%= pkg_datestr($pkg,'setup',$conf) %>
+        </TR>
+
+      <% } else { %>
+
+        <TR>
+          <TD COLSPAN=<%=$colspan%>><FONT COLOR="#00CC00"><B>Active</B></FONT>,&nbsp;<%= $billed_or_prepaid %>&nbsp;<%= myfreq($pkg->{part_pkg}) %></TD>
+        </TR>
+
+        <TR>
+          <TD WIDTH="<%=$width%>" ALIGN="right">Setup&nbsp;</TD>
+          <%= pkg_datestr($pkg, 'setup',$conf) %>
+        </TR>
+
+      <% } %>
+
+    <% } %>
+
+    <% if ( $pkg->{'last_bill'} ) { %>
+      <TR>
+        <TD WIDTH="<%=$width%>" ALIGN="right"><%= $last_bill_or_renewed %>&nbsp;</TD>
+        <%= pkg_datestr($pkg, 'last_bill',$conf) %>
+      </TR>
+    <% } %>
+
+    <% if ( $pkg->{'next_bill'} ) { %>
+      <TR>
+        <TD WIDTH="<%=$width%>" ALIGN="right"><%= $next_bill_or_prepaid_until %>&nbsp;</TD>
+        <%= pkg_datestr($pkg, 'next_bill',$conf) %>
+      </TR>
+    <% } %>
+
+    <% if ( $pkg->{'expire'} ) { %>
+      <TR>
+        <TD WIDTH="<%=$width%>" ALIGN="right">Expires&nbsp;</TD>
+        <%= pkg_datestr($pkg, 'expire',$conf) %>
+      </TR>
+    <% } %>
+
+    <% if ( $pkg->{freq} ) { %>
+      <TR>
+        <TD COLSPAN=<%=$colspan%>>(&nbsp;<%= pkg_suspend_link($pkg) %>&nbsp;|&nbsp;<%= pkg_cancel_link($pkg) %>&nbsp;)</TD>
+      </TR>
+    <% } %>
+
+  <% } %>
+
+<% } %>
+
+</TABLE>
+</TD>
+
+<%
   if ($rowspan == 0) { print qq!</TR>\n!; next; }
 
   my $cnt = 0;
@@ -342,9 +442,15 @@ sub pkgsort_pkgnum_cancel {
 sub pkg_datestr {
   my($pkg, $field, $conf) = @_ or return '';
   return '&nbsp;' unless $pkg->{$field};
-  my $format = $conf->exists('pkg_showtimes')
-               ? '<B>%D</B>&nbsp;<FONT SIZE=-3>%l:%M:%S%P&nbsp;%z</FONT>'
-               : '<B>%b&nbsp;%o,&nbsp;%Y</B>';
+  my $format = '<TD align="left"><B>%b</B></TD>'.
+               '<TD align="right"><B>&nbsp;%o,</B></TD>'.
+               '<TD align="right"><B>&nbsp;%Y</B></TD>';
+  #$format .= '&nbsp;<FONT SIZE=-3>%l:%M:%S%P&nbsp;%z</FONT>'
+  $format .= '<TD ALIGN="right"><B>&nbsp;%l</TD>'.
+             '<TD ALIGN="center"><B>:</B></TD>'.
+             '<TD ALIGN="left"><B>%M</B></TD>'.
+             '<TD ALIGN="left"><B>&nbsp;%P</B></TD>'
+    if $conf->exists('cust_pkg-display_times');
   ( my $strip = time2str($format, $pkg->{$field}) ) =~ s/ (\d)/$1/g;
   $strip;
 }
index 95598e9..ea396a2 100644 (file)
@@ -21,8 +21,12 @@ case "$1" in
         freeside-queued $QUEUED_USER
         echo "done."
 
-        echo -n "Starting freeside-sqlradius-radacctd: "
-        freeside-sqlradius-radacctd $QUEUED_USER
+        #echo -n "Starting freeside-sqlradius-radacctd: "
+        #freeside-sqlradius-radacctd $QUEUED_USER
+        #echo "done."
+
+        echo -n "Starting freeside-prepaidd: "
+        freeside-prepaidd $QUEUED_USER
         echo "done."
 
         for MACHINE in $SELFSERVICE_MACHINES; do
@@ -42,6 +46,10 @@ case "$1" in
         kill `cat /var/run/freeside-sqlradius-radacctd.pid`
         echo "done."
 
+        echo -n "Stopping freeside-prepaidd: "
+        kill `cat /var/run/freeside-prepaidd.pid`
+        echo "done."
+
         if [ -e /var/run/freeside-selfservice-server.$SELFSERVICE_USER.pid ]
         then
           echo -n "Stopping (old) freeside-selfservice-server: "