remove invoice deletion (and ancient & unused config settings), RT#37157
[freeside.git] / FS / FS / cust_bill.pm
index a65154e..b694924 100644 (file)
@@ -143,6 +143,16 @@ Invoices are normally created by calling the bill method of a customer object
 =cut
 
 sub table { 'cust_bill'; }
+sub template_conf { 'invoice_'; }
+
+sub has_sections {
+  my $self = shift;
+  my $agentnum = $self->cust_main->agentnum;
+  my $tc = $self->template_conf;
+
+  $self->conf->exists($tc.'sections', $agentnum) ||
+  $self->conf->exists($tc.'sections_by_location', $agentnum);
+}
 
 # should be the ONLY occurrence of "Invoice" in invoice rendering code.
 # (except email_subject and invnum_date_pretty)
@@ -257,14 +267,13 @@ sub void {
 
 =item delete
 
-This method now works but you probably shouldn't use it.  Instead, apply a
-credit against the invoice, or use the new void method.
+DO NOT USE THIS METHOD.  Instead, apply a credit against the invoice, or use
+the B<void> method.
 
-Using this method to delete invoices outright is really, really bad.  There
-would be no record you ever posted this invoice, and there are no check to
-make sure charged = 0 or that there are no associated cust_bill_pkg records.
+This is only for internal use by V<void>, which is what you should be using.
 
-Really, don't use it.
+DO NOT USE THIS METHOD.  Whatever reason you think you have is almost certainly
+wrong.  Use B<void>, that's what it is for.  Really.  This means you.
 
 =cut
 
@@ -284,7 +293,6 @@ sub delete {
   my $dbh = dbh;
 
   foreach my $table (qw(
-    cust_event
     cust_credit_bill
     cust_bill_pay
     cust_pay_batch
@@ -292,6 +300,7 @@ sub delete {
     cust_bill_batch
     cust_bill_pkg
   )) {
+    #cust_event # problematic
 
     foreach my $linked ( $self->$table() ) {
       my $error = $linked->delete;
@@ -447,16 +456,20 @@ followed by the previous outstanding invoices (as FS::cust_bill objects also).
 
 sub previous {
   my $self = shift;
-  my $total = 0;
-  my @cust_bill = sort { $a->_date <=> $b->_date }
-    grep { $_->owed != 0 }
-      qsearch( 'cust_bill', { 'custnum' => $self->custnum,
-                              #'_date'   => { op=>'<', value=>$self->_date },
-                              'invnum'   => { op=>'<', value=>$self->invnum },
-                            } ) 
-  ;
-  foreach ( @cust_bill ) { $total += $_->owed; }
-  $total, @cust_bill;
+  # simple memoize; we use this a lot
+  if (!$self->get('previous')) {
+    my $total = 0;
+    my @cust_bill = sort { $a->_date <=> $b->_date }
+      grep { $_->owed != 0 }
+        qsearch( 'cust_bill', { 'custnum' => $self->custnum,
+                                #'_date'   => { op=>'<', value=>$self->_date },
+                                'invnum'   => { op=>'<', value=>$self->invnum },
+                              } ) 
+    ;
+    foreach ( @cust_bill ) { $total += $_->owed; }
+    $self->set('previous', [$total, @cust_bill]);
+  }
+  return @{ $self->get('previous') };
 }
 
 =item enable_previous
@@ -874,6 +887,7 @@ sub hide {
 =item apply_payments_and_credits [ OPTION => VALUE ... ]
 
 Applies unapplied payments and credits to this invoice.
+Payments with the no_auto_apply flag set will not be applied.
 
 A hash of optional arguments may be passed.  Currently "manual" is supported.
 If true, a payment receipt is sent instead of a statement when
@@ -900,7 +914,9 @@ sub apply_payments_and_credits {
 
   $self->select_for_update; #mutex
 
-  my @payments = grep { $_->unapplied > 0 } $self->cust_main->cust_pay;
+  my @payments = grep { $_->unapplied > 0 } 
+                   grep { !$_->no_auto_apply }
+                     $self->cust_main->cust_pay;
   my @credits  = grep { $_->credited > 0 } $self->cust_main->cust_credit;
 
   if ( $conf->exists('pkg-balances') ) {
@@ -2165,7 +2181,7 @@ sub _items_extra_usage_sections {
   my %classnums = ();
   my %lines = ();
 
-  my $maxlength = $conf->config('cust_bill-latex_lineitem_maxlength') || 50;
+  my $maxlength = $conf->config('cust_bill-latex_lineitem_maxlength') || 40;
 
   my %usage_class =  map { $_->classnum => $_ } qsearch( 'usage_class', {} );
   foreach my $cust_bill_pkg ( $self->cust_bill_pkg ) {
@@ -2406,7 +2422,7 @@ sub _items_svc_phone_sections {
   my %classnums = ();
   my %lines = ();
 
-  my $maxlength = $conf->config('cust_bill-latex_lineitem_maxlength') || 50;
+  my $maxlength = $conf->config('cust_bill-latex_lineitem_maxlength') || 40;
 
   my %usage_class =  map { $_->classnum => $_ } qsearch( 'usage_class', {} );
   $usage_class{''} ||= new FS::usage_class { 'classname' => '', 'weight' => 0 };
@@ -2705,7 +2721,7 @@ sub _items_previous {
 
 sub _items_credits {
   my( $self, %opt ) = @_;
-  my $trim_len = $opt{'trim_len'} || 60;
+  my $trim_len = $opt{'trim_len'} || 40;
 
   my @b;
   #credits
@@ -2802,6 +2818,66 @@ sub _items_payments {
 
 }
 
+sub _items_total {
+  my $self = shift;
+  my $conf = $self->conf;
+
+  my @items;
+  my ($pr_total) = $self->previous;
+  my ($previous_charges_desc, $new_charges_desc, $new_charges_amount);
+
+  if ( $conf->exists('previous_balance-exclude_from_total') ) {
+    # can we do some caching on this stuff? it's going to change infrequently
+    # in production
+    $previous_charges_desc = $self->mt(
+      $conf->config('previous_balance-text') || 'Previous Balance'
+    );
+
+    # then return separate lines for previous balance and total new charges
+    if ( $pr_total ) {
+      push @items,
+        { total_item    => $previous_charges_desc,
+          total_amount  => sprintf('%.2f',$pr_total)
+        };
+    }
+    $new_charges_desc = $self->mt(
+      $conf->config('previous_balance-text-total_new_charges')
+       || 'Total New Charges'
+    );
+
+    $new_charges_amount = $self->charged;
+
+  } else {
+
+    $new_charges_desc = $self->mt('Total Charges');
+    $new_charges_amount = sprintf('%.2f',$self->charged + $pr_total);
+
+  }
+
+  if ( $conf->exists('invoice_show_prior_due_date') ) {
+    # then the due date should be shown with Total New Charges,
+    # and should NOT be shown with the Balance Due message.
+    if ( $self->due_date ) {
+      # localize the "Please pay by" message and the date itself
+      # (grammar issues with this, yeah)
+      $new_charges_desc .= ' - ' . $self->mt('Please pay by') . ' ' .
+                           $self->due_date2str('short');
+    } elsif ( $self->terms ) {
+      # phrases like "due on receipt" should be localized
+      $new_charges_desc .= ' - ' . $self->mt($self->terms);
+    }
+  }
+
+  push @items,
+    { total_item    => $new_charges_desc,
+      total_amount  => $new_charges_amount,
+    };
+
+  @items;
+}
+
+
+
 =item call_details [ OPTION => VALUE ... ]
 
 Returns an array of CSV strings representing the call details for this invoice
@@ -2897,6 +2973,9 @@ sub process_re_X {
 
 }
 
+# this is called from search/cust_bill.html and given all its search 
+# parameters, so it needs to perform the same search.
+
 sub re_X {
   # spool_invoice ftp_invoice fax_invoice print_invoice
   my($method, $job, %param ) = @_;
@@ -2906,22 +2985,15 @@ sub re_X {
   }
 
   #some false laziness w/search/cust_bill.html
-  my $distinct = '';
-  my $orderby = 'ORDER BY cust_bill._date';
-
-  my $extra_sql = ' WHERE '. FS::cust_bill->search_sql_where(\%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,
-  } );
+  $param{'order_by'} = 'cust_bill._date';
+
+  my $query = FS::cust_bill->search(\%param);
+  delete $query->{'count_query'};
+  delete $query->{'count_addl'};
+
+  $query->{debug} = 1; # was in here before, is obviously useful  
+
+  my @cust_bill = qsearch( $query );
 
   $method .= '_invoice' unless $method eq 'email' || $method eq 'print';