don't show services on invoices that are newer than the invoice, closes: #3032
[freeside.git] / FS / FS / cust_bill.pm
index bd1dbe0..f0863c4 100644 (file)
@@ -2176,7 +2176,7 @@ sub print_html {
       && length(  $conf->config_orbase('invoice_htmlreturnaddress', $template) )
   ) {
     $invoice_data{'returnaddress'} =
-      join("\n", $conf->config('invoice_htmlreturnaddress', $template) );
+      join("\n", $conf->config_orbase('invoice_htmlreturnaddress', $template) );
   } else {
     $invoice_data{'returnaddress'} =
       join("\n", map { 
@@ -2214,8 +2214,10 @@ sub print_html {
                        s/\\item /  <li>/g;
                        s/\\end\{enumerate\}/<\/ol>/g;
                        s/\\textbf\{(.*)\}/<b>$1<\/b>/g;
-                       s/\\\\\*/ /;
+                       s/\\\\\*/<br>/g;
                        s/\\dollar ?/\$/g;
+                       s/\\#/#/g;
+                       s/~/&nbsp;/g;
                        $_;
                      } 
                      $conf->config_orbase('invoice_latexnotes', $template)
@@ -2417,6 +2419,8 @@ sub _items_cust_bill_pkg {
   my @b = ();
   foreach my $cust_bill_pkg ( @$cust_bill_pkg ) {
 
+    my $cust_pkg = $cust_bill_pkg->cust_pkg;
+
     my $desc = $cust_bill_pkg->desc;
 
     if ( $cust_bill_pkg->pkgnum > 0 ) {
@@ -2424,7 +2428,7 @@ sub _items_cust_bill_pkg {
       if ( $cust_bill_pkg->setup != 0 ) {
         my $description = $desc;
         $description .= ' Setup' if $cust_bill_pkg->recur != 0;
-        my @d = $cust_bill_pkg->cust_pkg->h_labels_short($self->_date);
+        my @d = $cust_pkg->h_labels_short($self->_date);
         push @d, $cust_bill_pkg->details if $cust_bill_pkg->recur == 0;
         push @b, {
           description     => $description,
@@ -2447,8 +2451,11 @@ sub _items_cust_bill_pkg {
           pkgnum          => $cust_bill_pkg->pkgnum,
           amount          => sprintf("%.2f", $cust_bill_pkg->recur),
           ext_description =>
-            [ $cust_bill_pkg->cust_pkg->h_labels_short( $cust_bill_pkg->edate,
-                                                        $cust_bill_pkg->sdate),
+            #at least until cust_bill_pkg has "past" ranges in addition to
+            #the "future" sdate/edate ones... see #3032
+            [ $cust_pkg->h_labels_short( $self->_date ),
+                                         #$cust_bill_pkg->edate,
+                                         #$cust_bill_pkg->sdate),
               $cust_bill_pkg->details,
             ],
         };
@@ -2568,7 +2575,7 @@ use Data::Dumper;
 use MIME::Base64;
 sub process_re_X {
   my( $method, $job ) = ( shift, shift );
-  warn "process_re_X $method for job $job\n" if $DEBUG;
+  warn "$me process_re_X $method for job $job\n" if $DEBUG;
 
   my $param = thaw(decode_base64(shift));
   warn Dumper($param) if $DEBUG;
@@ -2583,7 +2590,6 @@ sub process_re_X {
 
 sub re_X {
   my($method, $job, %param ) = @_;
-#              [ 'begin', 'end', 'agentnum', 'open', 'days', 'newest_percust' ],
   if ( $DEBUG ) {
     warn "re_X $method for job $job with param:\n".
          join( '', map { "  $_ => ". $param{$_}. "\n" } keys %param );
@@ -2593,48 +2599,179 @@ sub re_X {
   my $distinct = '';
   my $orderby = 'ORDER BY cust_bill._date';
 
-  my @where;
+  my $extra_sql = ' WHERE '. FS::cust_bill->search_sql(\%param);
+
+  my $addl_from = 'LEFT JOIN cust_main USING ( custnum )';
+     
+  my @cust_bill = qsearch( {
+    #'select'    => "cust_bill.*",
+    'table'     => 'cust_bill',
+    'addl_from' => $addl_from,
+    'hashref'   => {},
+    'extra_sql' => $extra_sql,
+    'order_by'  => $orderby,
+    'debug' => 1,
+  } );
+
+  warn " $me re_X $method: ". scalar(@cust_bill). " invoices found\n"
+    if $DEBUG;
+
+  my( $num, $last, $min_sec ) = (0, time, 5); #progresbar foo
+  foreach my $cust_bill ( @cust_bill ) {
+    $cust_bill->$method();
+
+    if ( $job ) { #progressbar foo
+      $num++;
+      if ( time - $min_sec > $last ) {
+        my $error = $job->update_statustext(
+          int( 100 * $num / scalar(@cust_bill) )
+        );
+        die $error if $error;
+        $last = time;
+      }
+    }
+
+  }
+
+}
+
+=back
+
+=head1 CLASS METHODS
+
+=over 4
+
+=item owed_sql
+
+Returns an SQL fragment to retreive the amount owed (charged minus credited and paid).
+
+=cut
+
+sub owed_sql {
+  my $class = shift;
+  'charged - '. $class->paid_sql. ' - '. $class->credited_sql;
+}
+
+=item net_sql
+
+Returns an SQL fragment to retreive the net amount (charged minus credited).
+
+=cut
+
+sub net_sql {
+  my $class = shift;
+  'charged - '. $class->credited_sql;
+}
+
+=item paid_sql
+
+Returns an SQL fragment to retreive the amount paid against this invoice.
+
+=cut
+
+sub paid_sql {
+  #my $class = shift;
+  "( SELECT COALESCE(SUM(amount),0) FROM cust_bill_pay
+       WHERE cust_bill.invnum = cust_bill_pay.invnum   )";
+}
+
+=item credited_sql
+
+Returns an SQL fragment to retreive the amount credited against this invoice.
 
-  if ( $param{'begin'} =~ /^(\d+)$/ ) {
-    push @where, "cust_bill._date >= $1";
+=cut
+
+sub credited_sql {
+  #my $class = shift;
+  "( SELECT COALESCE(SUM(amount),0) FROM cust_credit_bill
+       WHERE cust_bill.invnum = cust_credit_bill.invnum   )";
+}
+
+=item search_sql HASHREF
+
+Class method which returns an SQL WHERE fragment to search for parameters
+specified in HASHREF.  Valid parameters are
+
+=over 4
+
+=item begin
+
+Epoch date (UNIX timestamp) setting a lower bound for _date values
+
+=item end
+
+Epoch date (UNIX timestamp) setting an upper bound for _date values
+
+=item invnum_min
+
+=item invnum_max
+
+=item agentnum
+
+=item owed
+
+=item net
+
+=item days
+
+=item newest_percust
+
+=back
+
+Note: validates all passed-in data; i.e. safe to use with unchecked CGI params.
+
+=cut
+
+sub search_sql {
+  my($class, $param) = @_;
+  if ( $DEBUG ) {
+    warn "$me search_sql called with params: \n".
+         join("\n", map { "  $_: ". $param->{$_} } keys %$param ). "\n";
   }
-  if ( $param{'end'} =~ /^(\d+)$/ ) {
-    push @where, "cust_bill._date < $1";
+
+  my @search = ();
+
+  if ( $param->{'begin'} =~ /^(\d+)$/ ) {
+    push @search, "cust_bill._date >= $1";
   }
-  if ( $param{'invnum_min'} =~ /^(\d+)$/ ) {
-    push @where, "cust_bill.invnum >= $1";
+  if ( $param->{'end'} =~ /^(\d+)$/ ) {
+    push @search, "cust_bill._date < $1";
   }
-  if ( $param{'invnum_max'} =~ /^(\d+)$/ ) {
-    push @where, "cust_bill.invnum <= $1";
+  if ( $param->{'invnum_min'} =~ /^(\d+)$/ ) {
+    push @search, "cust_bill.invnum >= $1";
   }
-  if ( $param{'agentnum'} =~ /^(\d+)$/ ) {
-    push @where, "cust_main.agentnum = $1";
+  if ( $param->{'invnum_max'} =~ /^(\d+)$/ ) {
+    push @search, "cust_bill.invnum <= $1";
+  }
+  if ( $param->{'agentnum'} =~ /^(\d+)$/ ) {
+    push @search, "cust_main.agentnum = $1";
   }
 
-  my $owed =
-    "charged - ( SELECT COALESCE(SUM(amount),0) FROM cust_bill_pay
-                 WHERE cust_bill_pay.invnum = cust_bill.invnum )
-             - ( SELECT COALESCE(SUM(amount),0) FROM cust_credit_bill
-                 WHERE cust_credit_bill.invnum = cust_bill.invnum )";
+  push @search, '0 != '. FS::cust_bill->owed_sql
+    if $param->{'open'};
 
-  push @where, "0 != $owed"
-    if $param{'open'};
+  push @search, '0 != '. FS::cust_bill->net_sql
+    if $param->{'net'};
 
-  push @where, "cust_bill._date < ". (time-86400*$param{'days'})
-    if $param{'days'};
+  push @search, "cust_bill._date < ". (time-86400*$param->{'days'})
+    if $param->{'days'};
 
-  if ( $param{'newest_percust'} ) {
+  if ( $param->{'newest_percust'} ) {
 
     #$distinct = 'DISTINCT ON ( cust_bill.custnum )';
     #$orderby = 'ORDER BY cust_bill.custnum ASC, cust_bill._date DESC';
 
-    my @newest_where = map { s/\bcust_bill\./newest_cust_bill./g; }
-                           grep ! /^cust_main./, @where;
+    my @newest_where = map { my $x = $_;
+                             $x =~ s/\bcust_bill\./newest_cust_bill./g;
+                             $x;
+                           }
+                           grep ! /^cust_main./, @search;
     my $newest_where = scalar(@newest_where)
                          ? ' AND '. join(' AND ', @newest_where)
                         : '';
 
-    push @where, "cust_bill._date = (
+
+    push @search, "cust_bill._date = (
       SELECT(MAX(newest_cust_bill._date)) FROM cust_bill AS newest_cust_bill
         WHERE newest_cust_bill.custnum = cust_bill.custnum
           $newest_where
@@ -2642,36 +2779,25 @@ sub re_X {
 
   }
 
-  my $extra_sql = scalar(@where) ? 'WHERE '. join(' AND ', @where) : '';
-
-  my $addl_from = 'left join cust_main using ( custnum )';
-     
-  my @cust_bill = qsearch( 'cust_bill',
-                           {},
-                           #"$distinct cust_bill.*",
-                           "cust_bill.*",
-                           $extra_sql,
-                           '',
-                           $addl_from
-                         );
-
-  my( $num, $last, $min_sec ) = (0, time, 5); #progresbar foo
-  foreach my $cust_bill ( @cust_bill ) {
-    $cust_bill->$method();
-
-    if ( $job ) { #progressbar foo
-      $num++;
-      if ( time - $min_sec > $last ) {
-        my $error = $job->update_statustext(
-          int( 100 * $num / scalar(@cust_bill) )
-        );
-        die $error if $error;
-        $last = time;
-      }
+  my $curuser = $FS::CurrentUser::CurrentUser;
+  if ( $curuser->username eq 'fs_queue'
+       && $param->{'CurrentUser'} =~ /^(\w+)$/ ) {
+    my $username = $1;
+    my $newuser = qsearchs('access_user', {
+      'username' => $username,
+      'disabled' => '',
+    } );
+    if ( $newuser ) {
+      $curuser = $newuser;
+    } else {
+      warn "$me WARNING: (fs_queue) can't find CurrentUser $username\n";
     }
-
   }
 
+  push @search, $curuser->agentnums_sql;
+
+  join(' AND ', @search );
+
 }
 
 =back
@@ -2680,9 +2806,6 @@ sub re_X {
 
 The delete method.
 
-print_text formatting (and some logic :/) is in source, but needs to be
-slurped in from a file.  Also number of lines ($=).
-
 =head1 SEE ALSO
 
 L<FS::Record>, L<FS::cust_main>, L<FS::cust_bill_pay>, L<FS::cust_pay>,