add svc_elec_features merged from reference code RT#7643
[freeside.git] / FS / FS / cust_bill.pm
index 8cc84e5..fcc2a65 100644 (file)
@@ -34,6 +34,10 @@ use FS::cust_bill_pay;
 use FS::cust_bill_pay_batch;
 use FS::part_bill_event;
 use FS::payby;
+use FS::bill_batch;
+use FS::cust_bill_batch;
+use FS::usage_elec qw(most_current_date);
+use FS::cust_bill_pkg_detail; #ugh
 
 @ISA = qw( FS::cust_main_Mixin FS::Record );
 
@@ -48,6 +52,13 @@ FS::UID->install_callback( sub {
   $rdate_format = $conf->config('date_format') || '%m/%d/%Y';  
 } );
 
+# i think this is cruft
+sub usage_elec{
+  warn "$me: usage_elec has been called\n";
+  my $self = shift;
+  qsearch('usage_elec',{ 'cust_nr' => $self->custnum});
+}
+
 =head1 NAME
 
 FS::cust_bill - Object methods for cust_bill records
@@ -1300,7 +1311,13 @@ sub print {
     'notice_name' => $notice_name,
   );
 
-  do_print $self->lpr_data(\%opt);
+  if($conf->exists('invoice_print_pdf')) {
+    # Add the invoice to the current batch.
+    $self->batch_invoice(\%opt);
+  }
+  else {
+    do_print $self->lpr_data(\%opt);
+  }
 }
 
 =item fax_invoice HASHREF | [ TEMPLATE ] 
@@ -1346,6 +1363,23 @@ sub fax_invoice {
 
 }
 
+=item batch_invoice [ HASHREF ]
+
+Place this invoice into the open batch (see C<FS::bill_batch>).  If there 
+isn't an open batch, one will be created.
+
+=cut
+
+sub batch_invoice {
+  my ($self, $opt) = @_;
+  my $batch = FS::bill_batch->get_open_batch;
+  my $cust_bill_batch = FS::cust_bill_batch->new({
+      batchnum => $batch->batchnum,
+      invnum   => $self->invnum,
+  });
+  return $cust_bill_batch->insert($opt);
+}
+
 =item ftp_invoice [ TEMPLATENAME ] 
 
 Sends this invoice data via FTP.
@@ -2026,7 +2060,7 @@ sub print_latex {
   $params{'time'} = $today if $today;
   $params{'template'} = $template if $template;
   $params{$_} = $opt{$_} 
-    foreach grep $opt{$_}, qw( unsquealch_cdr notice_name );
+    foreach grep $opt{$_}, qw(unsquealch_cdr notice_name base ignore_due_date);
 
   $template ||= $self->_agent_template;
 
@@ -2075,6 +2109,7 @@ Non optional options include
 
 Optional options include
 
+base - a value used for the name of the template. defaults to 'invoice'
 template - a value used as a suffix for a configuration template
 
 time - a value used to control the printing of overdue messages.  The
@@ -2104,6 +2139,15 @@ sub print_generic {
   die "Unknown format: $format"
     unless $format =~ /^(latex|html|template)$/;
 
+  # this weirdness switches to the most recent invoice under some circumstances
+  if ( $conf->exists('svc_elec_features') && ($params{base} =~ /^rec/i) ) {
+    $self = qsearchs({
+      'table' => 'cust_bill',
+      'hashref' => { 'custnum' => $self->custnum },
+      'order_by' => 'ORDER BY invnum DESC LIMIT 1',
+    });
+  }
+
   my $cust_main = $self->cust_main;
   $cust_main->payname( $cust_main->first. ' '. $cust_main->getfield('last') )
     unless $cust_main->payname
@@ -2116,7 +2160,8 @@ sub print_generic {
 
   #create the template
   my $template = $params{template} ? $params{template} : $self->_agent_template;
-  my $templatefile = "invoice_$format";
+  my $templatefile = $params{base} || 'invoice'; #base only used for 'rec'
+  $templatefile .= "_$format";
   $templatefile .= "_$template"
     if length($template);
   my @invoice_template = map "$_\n", $conf->config($templatefile)
@@ -2299,11 +2344,13 @@ sub print_generic {
 
   }
 
+  my $agentnum = $self->cust_main->agentnum;
+
   my %invoice_data = (
 
     #invoice from info
-    'company_name'    => scalar( $conf->config('company_name', $self->cust_main->agentnum) ),
-    'company_address' => join("\n", $conf->config('company_address', $self->cust_main->agentnum) ). "\n",
+    'company_name'    => scalar( $conf->config('company_name', $agentnum) ),
+    'company_address' => join("\n", $conf->config('company_address', $agentnum) ). "\n",
     'returnaddress'   => $returnaddress,
     'agent'           => &$escape_function($cust_main->agent->agent),
 
@@ -2316,9 +2363,12 @@ sub print_generic {
     'notice_name'     => ($params{'notice_name'} || 'Invoice'),#escape_function?
     'current_charges' => sprintf("%.2f", $self->charged),
     'duedate'         => $self->due_date2str($rdate_format), #date_format?
+    'due_date'        => $self->due_date2str($rdate_format), #date_format?
+    'ignore_due_date' => ($params{'ignore_due_date'} || ''),
 
     #customer info
     'custnum'         => $cust_main->display_custnum,
+    'phone'           => $cust_main->daytime,
     'agent_custid'    => &$escape_function($cust_main->agent_custid),
     ( map { $_ => &$escape_function($cust_main->$_()) } qw(
       payname company address1 address2 city state zip fax
@@ -2331,6 +2381,19 @@ sub print_generic {
     'smallerfooter'   => $conf->exists('invoice-smallerfooter'),
     'balance_due_below_line' => $conf->exists('balance_due_below_line'),
    
+    #layout info -- would be fancy to calc some of this and bury the template
+    #               here in the code
+    'topmargin'             => scalar($conf->config('invoice_latextopmargin', $agentnum)),
+    'headsep'               => scalar($conf->config('invoice_latexheadsep', $agentnum)),
+    'textheight'            => scalar($conf->config('invoice_latextextheight', $agentnum)),
+    'extracouponspace'      => scalar($conf->config('invoice_latexextracouponspace', $agentnum)),
+    'couponfootsep'         => scalar($conf->config('invoice_latexcouponfootsep', $agentnum)),
+    'verticalreturnaddress' => $conf->exists('invoice_latexverticalreturnaddress', $agentnum),
+    'addresssep'            => scalar($conf->config('invoice_latexaddresssep', $agentnum)),
+    'amountenclosedsep'     => scalar($conf->config('invoice_latexcouponamountenclosedsep', $agentnum)),
+    'coupontoaddresssep'    => scalar($conf->config('invoice_latexcoupontoaddresssep', $agentnum)),
+    'addcompanytoaddress'   => $conf->exists('invoice_latexcouponaddcompanytoaddress', $agentnum),
+
     # better hang on to conf_dir for a while (for old templates)
     'conf_dir'        => "$FS::UID::conf_dir/conf.$FS::UID::datasrc",
 
@@ -2340,6 +2403,121 @@ sub print_generic {
 
   );
 
+  my @last_cust_bill_pkg_details = ();
+  if ($conf->exists('svc_elec_features')) {
+
+    $invoice_data{date} = time2str('%D', $self->_date);  # date_format?
+
+    # get the detail records sorted by detailnum
+    # too inefficient? 
+    @last_cust_bill_pkg_details =
+      sort { $a->detailnum <=> $b->detailnum }
+      map { $_->cust_bill_pkg_detail }
+      $self->cust_bill_pkg;
+
+    # save a copy of  the last if there is one
+    my $last_cust_bill_pkg_detail;
+    if (scalar(@last_cust_bill_pkg_details)) {
+      $last_cust_bill_pkg_detail = pop @last_cust_bill_pkg_details;
+      push @last_cust_bill_pkg_details, $last_cust_bill_pkg_detail;
+    }
+
+    foreach my $method ( qw( last_pay setup_fee prev_read one_time_charge
+                             curr_read energy_charge energy_base tdsp gr_fee
+                             taxes esiid late_fee average_price 
+                             meter_multplier meter_number ) )
+    {
+      $invoice_data{$method} = $last_cust_bill_pkg_detail
+                               ? $last_cust_bill_pkg_detail->$method
+                               : '';
+    }
+
+    foreach my $method ( qw( prev_date curr_date last_pay_date ) )
+    {
+      $invoice_data{$method} =
+        $last_cust_bill_pkg_detail
+          ? time2str('%D', $last_cust_bill_pkg_detail->$method)
+          : '';
+    }
+
+    foreach my $method ( qw( one_time_description pkg_info note ) )
+    {
+      $invoice_data{$method} =
+        $last_cust_bill_pkg_detail
+          ? &$escape_function($last_cust_bill_pkg_detail->$method)
+          : '';
+    }
+
+    $invoice_data{$_} = ''
+      foreach qw( discount2_total discount2_description discount2_pkgnum
+                  bill_return_address usage numberOfDays balance rate
+                  previousbill_numberOfDays previousbill_totalUsage
+                  lastyear_numberOfDays lastyear_totalUsage
+                  billed_demand measured_demand );
+
+    if ($last_cust_bill_pkg_detail) {
+      $invoice_data{bill_return_address} =
+        $last_cust_bill_pkg_detail->bill_return_addr;
+      $invoice_data{usage} = $last_cust_bill_pkg_detail->energy_usage;
+      $invoice_data{numberOfDays} = $last_cust_bill_pkg_detail->number_of_days;
+      $invoice_data{balance} =
+        sprintf("%.2f", $last_cust_bill_pkg_detail->balance);
+      $invoice_data{actual_balance} = sprintf("%.2f", $cust_main->balance);
+      $invoice_data{rate} = sprintf("%.6f", $last_cust_bill_pkg_detail->rate);
+      $invoice_data{amount_due} =
+        sprintf("%.2f", $self->charged + $last_cust_bill_pkg_detail->balance);
+      $invoice_data{bill_charged} = $invoice_data{current_charges};
+      $invoice_data{billed_demand} = $last_cust_bill_pkg_detail->demanded_bill;
+      $invoice_data{measured_demand} =
+        $last_cust_bill_pkg_detail->measured_bill;
+      $invoice_data{total_discount1} =
+        sprintf('%.2f', $last_cust_bill_pkg_detail->discount1_total)
+        if  $last_cust_bill_pkg_detail->discount1_total
+    }
+
+    if (scalar(@last_cust_bill_pkg_details) > 1) {
+      $invoice_data{previousbill_numberOfDays} =
+        &$escape_function($last_cust_bill_pkg_details[1]->number_of_days);
+      $invoice_data{previousbill_totalUsage} =
+        &$escape_function($last_cust_bill_pkg_details[1]->energy_usage);
+    }
+
+    if (scalar(@last_cust_bill_pkg_details) > 11) {
+      $invoice_data{lastyear_numberOfDays} =
+        &$escape_function($last_cust_bill_pkg_details[11]->number_of_days);
+      $invoice_data{lastyear_totalUsage} =
+        &$escape_function($last_cust_bill_pkg_details[11]->energy_usage);
+    }
+
+    #-ctran 4/11/07 : Manipulatinng the Service address to be input
+    #into latex pdf invoice.  The database table cust_main call the
+    #service address as ship address.  Here I will combine the ship_address1,
+    #ship_address2, and ship_zip to form service address.
+    #-ctran 4/15/07 : If service address is empty, use address1 form cust_main,
+    #this is the mailing address.
+
+    my ($ship_addr1, $ship_addr2) = ($cust_main->ship_address1,
+                                     $cust_main->ship_address2);
+    $ship_addr1 .= ", $ship_addr2" if $ship_addr2;
+
+    # we have a total of 30 character for the service address location,
+    # so address will consist 19 chars, zip 9 chars, ', ' 2 chars = 30
+
+    my $service_addrs;
+    if ($ship_addr1) {
+      if ( (length($ship_addr1)) > 30 ) {
+        $service_addrs = substr($ship_addr1,0,28) . "...";
+      } else {
+        $service_addrs = $ship_addr1;
+      }
+      $service_addrs .= ", ".$cust_main->ship_zip if ($cust_main->ship_zip);
+    } else {
+      $service_addrs = substr($cust_main->address1,0,30);
+    }
+    $invoice_data{srvc_addr} = &$escape_function($service_addrs);
+
+  }
+
   $invoice_data{finance_section} = '';
   if ( $conf->config('finance_pkgclass') ) {
     my $pkg_class =
@@ -2399,8 +2577,6 @@ sub print_generic {
   $invoice_data{'previous_balance'} = sprintf("%.2f", $pr_total);
   $invoice_data{'balance'} = sprintf("%.2f", $balance_due);
 
-  my $agentnum = $self->cust_main->agentnum;
-
   my $summarypage = '';
   if ( $conf->exists('invoice_usesummary', $agentnum) ) {
     $summarypage = 1;
@@ -2468,6 +2644,8 @@ sub print_generic {
   my $other_money_char = $other_money_chars{$format};
   $invoice_data{'dollar'} = $other_money_char;
 
+  my $dash = $conf->exists('svc_elec_features') ? '*'x20 : '-----------';
+
   my @detail_items = ();
   my @total_items = ();
   my @buf = ();
@@ -2478,6 +2656,31 @@ sub print_generic {
   $invoice_data{'buf'} = \@buf;
   $invoice_data{'sections'} = \@sections;
 
+  # for some kind of statement
+  my @bills = qsearch({
+    'table' => 'cust_bill',
+    'hashref' => { 'custnum' => $self->custnum },
+    'order_by' => 'ORDER BY _date DESC LIMIT 19',
+  });
+  @bills = reverse(@bills);
+
+  #what about multiple details?  original code seems not to care
+  my @bill_details = ();
+  push @bill_details,
+    map { $_->cust_bill_pkg_detail }
+    map { $_->cust_bill_pkg }
+    @bills;
+
+  my @pays = reverse( qsearch({ 'table' => 'cust_pay',
+                                'hashref' => { 'custnum' => $self->custnum },
+                                'order_by' => 'ORDER BY _date DESC LIMIT 19',
+                              })
+                    );
+
+  $invoice_data{'total_bills'} = \@bills;
+  $invoice_data{'total_payments'} = \@pays;
+  $invoice_data{'total_details'} = \@bill_details;
+
   my $previous_section = { 'description' => 'Previous Charges',
                            'subtotal'    => $other_money_char.
                                             sprintf('%.2f', $pr_total),
@@ -2575,7 +2778,7 @@ sub print_generic {
   }
 
   if ( @pr_cust_bill && !$conf->exists('disable_previous_balance') ) {
-    push @buf, ['','-----------'];
+    push @buf, ['', $dash];
     push @buf, [ 'Total Previous Balance',
                  $money_char. sprintf("%10.2f", $pr_total) ];
     push @buf, ['',''];
@@ -2583,6 +2786,12 @@ sub print_generic {
 
   foreach my $section (@sections, @$late_sections) {
 
+    # begin some normalization
+    $section->{'subtotal'} = $section->{'amount'}
+      if $multisection
+         && !exists($section->{subtotal})
+         && exists($section->{amount});
+
     $invoice_data{finance_amount} = sprintf('%.2f', $section->{'subtotal'} )
       if ( $invoice_data{finance_section} &&
            $section->{'description'} eq $invoice_data{finance_section} );
@@ -2591,7 +2800,7 @@ sub print_generic {
                              sprintf('%.2f', $section->{'subtotal'})
       if $multisection;
 
-    # begin some normalization
+    # continue some normalization
     $section->{'amount'}   = $section->{'subtotal'}
       if $multisection;
 
@@ -2624,6 +2833,18 @@ sub print_generic {
       $detail->{'description'} = &$escape_function($line_item->{'description'});
       if ( exists $line_item->{'ext_description'} ) {
         @{$detail->{'ext_description'}} = @{$line_item->{'ext_description'}};
+
+        if ($conf->exists('svc_elec_features')) {
+          if ( grep { /DISCOUNT2/i } @{$line_item->{'ext_description'}} ) {
+            $invoice_data{'discount2_total'} = $line_item->{'amount'};
+            $invoice_data{'discount2_pkgnum'} = $detail->{'ref'};
+
+            #want the bare description
+            $invoice_data{'discount2_description'} = &$escape_function($_->desc)
+              foreach $self->cust_bill_pkg_pkgnum($detail->{'ref'});
+          }
+        }
+
       }
       $detail->{'amount'} = ( $old_latex ? '' : $money_char ).
                               $line_item->{'amount'};
@@ -2639,8 +2860,9 @@ sub print_generic {
                  );
     }
 
+
     if ( $section->{'description'} ) {
-      push @buf, ( ['','-----------'],
+      push @buf, ( ['', $dash],
                    [ $section->{'description'}. ' sub-total',
                       $money_char. sprintf("%10.2f", $section->{'subtotal'})
                    ],
@@ -2713,7 +2935,7 @@ sub print_generic {
   }
   $invoice_data{'taxtotal'} = sprintf('%.2f', $taxtotal);
 
-  push @buf,['','-----------'];
+  push @buf,['', $dash];
   push @buf,[( $conf->exists('disable_previous_balance') 
                ? 'Total Charges'
                : 'Total New Charges'
@@ -2747,7 +2969,7 @@ sub print_generic {
     }else{
       push @total_items, $total;
     }
-    push @buf,['','-----------'];
+    push @buf,['', $dash];
     push @buf,[$item,
                $money_char.
                sprintf( '%10.2f', $amount )
@@ -2842,7 +3064,7 @@ sub print_generic {
       }else{
         push @total_items, $total;
       }
-      push @buf,['','-----------'];
+      push @buf,['', $dash];
       push @buf,[$self->balance_due_msg, $money_char. 
         sprintf("%10.2f", $balance_due ) ];
     }
@@ -3353,7 +3575,9 @@ my %condensed_format = (
   'fields' => [
                 sub { shift->{description} },
                 sub { shift->{quantity} },
-                sub { shift->{amount} },
+                sub { my($href, %opt) = @_;
+                      ($opt{dollar} || ''). $href->{amount};
+                    },
               ],
   'align'  => [ qw( l r r ) ],
   'span'   => [ qw( 5 1 1 ) ],            # unitprices?
@@ -3427,6 +3651,7 @@ sub _condensed_description_generator {
   my ( $f, $prefix, $suffix, $separator, $column ) =
     _condensed_generator_defaults($format);
 
+  my $money_char = '$';
   if ($format eq 'latex') {
     $prefix = "\\hline\n\\multicolumn{1}{c}{\\rule{0pt}{2.5ex}~} &\n";
     $suffix = '\\\\';
@@ -3435,6 +3660,7 @@ sub _condensed_description_generator {
       sub { my ($d,$a,$s,$w) = @_;
             return "\\multicolumn{$s}{$a}{\\makebox[$w][$a]{\\textbf{$d}}}";
           };
+    $money_char = '\\dollar';
   }elsif ( $format eq 'html' ) {
     $prefix = '"><td align="center"></td>';
     $suffix = '';
@@ -3443,16 +3669,22 @@ sub _condensed_description_generator {
       sub { my ($d,$a,$s,$w) = @_;
             return qq!<td align="$html_align{$a}">$d</td>!;
       };
+    #$money_char = $conf->config('money_char') || '$';
+    $money_char = '';  # this is madness
   }
 
   sub {
-    my @args = @_;
+    #my @args = @_;
+    my $href = shift;
     my @result = ();
 
     foreach  (my $i = 0; $f->{label}->[$i]; $i++) {
-      push @result, &{$column}( &{$f->{fields}->[$i]}(@args),
-                                map { $f->{$_}->[$i] } qw(align span width)
-                              );
+      my $dollar = '';
+      $dollar = $money_char if $i == scalar(@{$f->{label}})-1;
+      push @result,
+        &{$column}( &{$f->{fields}->[$i]}($href, 'dollar' => $dollar),
+                    map { $f->{$_}->[$i] } qw(align span width)
+                  );
     }
 
     $prefix. join( $separator, @result ). $suffix;
@@ -3697,6 +3929,9 @@ sub _items_svc_phone_sections {
   foreach my $cust_bill_pkg ( $self->cust_bill_pkg ) {
     next unless $cust_bill_pkg->pkgnum > 0;
 
+    my @header = $cust_bill_pkg->details_header;
+    next unless scalar(@header);
+
     foreach my $detail ( $cust_bill_pkg->cust_bill_pkg_detail ) {
 
       my $phonenum = $detail->phonenum;
@@ -3745,6 +3980,7 @@ sub _items_svc_phone_sections {
           'duration' => 0,
           'sort_weight' => $usage_class{$detail->classnum}->weight,
           'phonenum' => $phonenum,
+          'header'  => [ @header ],
         };
       $sections{"$phonenum $line"}{amount} += $amount;  #subtotal
       $sections{"$phonenum $line"}{calls}++;
@@ -3775,11 +4011,17 @@ sub _items_svc_phone_sections {
 
   my %sectionmap = ();
   my $simple = new FS::usage_class { format => 'simple' }; #bleh
-  my $usage_simple = new FS::usage_class { format => 'usage_simple' }; #bleh
   foreach ( keys %sections ) {
+    my @header = @{ $sections{$_}{header} || [] };
+    my $usage_simple =
+      new FS::usage_class { format => 'usage_'. (scalar(@header) || 6). 'col' };
     my $summary = $sections{$_}{sort_weight} < 0 ? 1 : 0;
     my $usage_class = $summary ? $simple : $usage_simple;
     my $ending = $summary ? ' usage charges' : '';
+    my %gen_opt = ();
+    unless ($summary) {
+      $gen_opt{label} = [ map{ &{$escape}($_) } @header ];
+    }
     $sectionmap{$_} = { 'description' => &{$escape}($_. $ending),
                         'amount'    => $sections{$_}{amount},    #subtotal
                         'calls'       => $sections{$_}{calls},
@@ -3790,7 +4032,7 @@ sub _items_svc_phone_sections {
                         'sort_weight' => $sections{$_}{sort_weight},
                         'post_total'  => $summary, #inspire pagebreak
                         (
-                          ( map { $_ => $usage_class->$_($format) }
+                          ( map { $_ => $usage_class->$_($format, %gen_opt) }
                             qw( description_generator
                                 header_generator
                                 total_generator
@@ -3899,12 +4141,12 @@ sub _items_pkg {
 }
 
 sub _taxsort {
-  return 0 unless $a cmp $b;
-  return -1 if $b eq 'Tax';
-  return 1 if $a eq 'Tax';
-  return -1 if $b eq 'Other surcharges';
-  return 1 if $a eq 'Other surcharges';
-  $a cmp $b;
+  return 0 unless $a->itemdesc cmp $b->itemdesc;
+  return -1 if $b->itemdesc eq 'Tax';
+  return 1 if $a->itemdesc eq 'Tax';
+  return -1 if $b->itemdesc eq 'Other surcharges';
+  return 1 if $a->itemdesc eq 'Other surcharges';
+  $a->itemdesc cmp $b->itemdesc;
 }
 
 sub _items_tax {
@@ -4341,8 +4583,10 @@ Returns an SQL fragment to retreive the amount owed (charged minus credited and
 =cut
 
 sub owed_sql {
-  my $class = shift;
-  'charged - '. $class->paid_sql. ' - '. $class->credited_sql;
+  my ($class, $start, $end) = @_;
+  'charged - '. 
+    $class->paid_sql($start, $end). ' - '. 
+    $class->credited_sql($start, $end);
 }
 
 =item net_sql
@@ -4352,8 +4596,8 @@ Returns an SQL fragment to retreive the net amount (charged minus credited).
 =cut
 
 sub net_sql {
-  my $class = shift;
-  'charged - '. $class->credited_sql;
+  my ($class, $start, $end) = @_;
+  'charged - '. $class->credited_sql($start, $end);
 }
 
 =item paid_sql
@@ -4363,9 +4607,13 @@ Returns an SQL fragment to retreive the amount paid against this invoice.
 =cut
 
 sub paid_sql {
-  #my $class = shift;
+  my ($class, $start, $end) = @_;
+  $start &&= "AND cust_bill_pay._date <= $start";
+  $end   &&= "AND cust_bill_pay._date > $end";
+  $start = '' unless defined($start);
+  $end   = '' unless defined($end);
   "( SELECT COALESCE(SUM(amount),0) FROM cust_bill_pay
-       WHERE cust_bill.invnum = cust_bill_pay.invnum   )";
+       WHERE cust_bill.invnum = cust_bill_pay.invnum $start $end  )";
 }
 
 =item credited_sql
@@ -4375,9 +4623,13 @@ Returns an SQL fragment to retreive the amount credited against this invoice.
 =cut
 
 sub credited_sql {
-  #my $class = shift;
+  my ($class, $start, $end) = @_;
+  $start &&= "AND cust_credit_bill._date <= $start";
+  $end   &&= "AND cust_credit_bill._date >  $end";
+  $start = '' unless defined($start);
+  $end   = '' unless defined($end);
   "( SELECT COALESCE(SUM(amount),0) FROM cust_credit_bill
-       WHERE cust_bill.invnum = cust_credit_bill.invnum   )";
+       WHERE cust_bill.invnum = cust_credit_bill.invnum $start $end  )";
 }
 
 =item search_sql_where HASHREF