add cust_credit_bill relating multiple invoices to credits
[freeside.git] / FS / FS / cust_bill.pm
index 2df92f7..4c1617f 100644 (file)
@@ -1,7 +1,7 @@
 package FS::cust_bill;
 
 use strict;
-use vars qw( @ISA $conf $invoice_template );
+use vars qw( @ISA $conf $invoice_template $money_char );
 use vars qw( $invoice_lines @buf ); #yuck
 use Date::Format;
 use Text::Template;
@@ -11,12 +11,17 @@ use FS::cust_bill_pkg;
 use FS::cust_credit;
 use FS::cust_pay;
 use FS::cust_pkg;
+use FS::cust_credit_bill;
 
 @ISA = qw( FS::Record );
 
 #ask FS::UID to run this stuff for us later
 $FS::UID::callback{'FS::cust_bill'} = sub { 
+
   $conf = new FS::Conf;
+
+  $money_char = $conf->config('money_char') || '$';  
+
   my @invoice_template = $conf->config('invoice_template')
     or die "cannot load config file invoice_template";
   $invoice_lines = 0;
@@ -60,13 +65,17 @@ FS::cust_bill - Object methods for cust_bill records
 
   @cust_pay_objects = $cust_bill->cust_pay;
 
+  $tax_amount = $record->tax;
+
   @lines = $cust_bill->print_text;
   @lines = $cust_bill->print_text $time;
 
 =head1 DESCRIPTION
 
-An FS::cust_bill object represents an invoice.  FS::cust_bill inherits from
-FS::Record.  The following fields are currently supported:
+An FS::cust_bill object represents an invoice; a declaration that a customer
+owes you money.  The specific charges are itemized as B<cust_bill_pkg> records
+(see L<FS::cust_bill_pkg>).  FS::cust_bill inherits from FS::Record.  The
+following fields are currently supported:
 
 =over 4
 
@@ -79,9 +88,6 @@ L<Time::Local> and L<Date::Parse> for conversion functions.
 
 =item charged - amount of this invoice
 
-=item owed - amount still outstanding on this invoice, which is charged minus
-all payments (see L<FS::cust_pay>).
-
 =item printed - how many times this invoice has been printed automatically
 (see L<FS::cust_main/"collect">).
 
@@ -106,21 +112,6 @@ sub table { 'cust_bill'; }
 Adds this invoice to the database ("Posts" the invoice).  If there is an error,
 returns the error, otherwise returns false.
 
-When adding new invoices, owed must be charged (or null, in which case it is
-automatically set to charged).
-
-=cut
-
-sub insert {
-  my $self = shift;
-
-  $self->owed( $self->charged ) if $self->owed eq '';
-  return "owed != charged!"
-    unless $self->owed == $self->charged;
-
-  $self->SUPER::insert;
-}
-
 =item delete
 
 Currently unimplemented.  I don't remove invoices because there would then be
@@ -137,9 +128,8 @@ sub delete {
 Replaces the OLD_RECORD with this one in the database.  If there is an error,
 returns the error, otherwise returns false.
 
-Only owed and printed may be changed.  Owed is normally updated by creating and
-inserting a payment (see L<FS::cust_pay>).  Printed is normally updated by
-calling the collect method of a customer object (see L<FS::cust_main>).
+Only printed may be changed.  printed is normally updated by calling the
+collect method of a customer object (see L<FS::cust_main>).
 
 =cut
 
@@ -149,7 +139,6 @@ sub replace {
   #return "Can't change _date!" unless $old->_date eq $new->_date;
   return "Can't change _date!" unless $old->_date == $new->_date;
   return "Can't change charged!" unless $old->charged == $new->charged;
-  return "(New) owed can't be > (new) charged!" if $new->owed > $new->charged;
 
   $new->SUPER::replace($old);
 }
@@ -170,7 +159,6 @@ sub check {
     || $self->ut_number('custnum')
     || $self->ut_numbern('_date')
     || $self->ut_money('charged')
-    || $self->ut_money('owed')
     || $self->ut_numbern('printed')
   ;
   return $error if $error;
@@ -217,15 +205,15 @@ sub cust_bill_pkg {
 =item cust_credit
 
 Returns a list consisting of the total previous credited (see
-L<FS::cust_credit>) for this customer, followed by the previous outstanding
-credits (FS::cust_credit objects).
+L<FS::cust_credit>) and unapplied for this customer, followed by the previous
+outstanding credits (FS::cust_credit objects).
 
 =cut
 
 sub cust_credit {
   my $self = shift;
   my $total = 0;
-  my @cust_credit = sort { $a->_date <=> $b->date }
+  my @cust_credit = sort { $a->_date <=> $b->_date }
     grep { $_->credited != 0 && $_->_date < $self->_date }
       qsearch('cust_credit', { 'custnum' => $self->custnum } )
   ;
@@ -241,11 +229,55 @@ Returns all payments (see L<FS::cust_pay>) for this invoice.
 
 sub cust_pay {
   my $self = shift;
-  sort { $a->_date <=> $b->date }
+  sort { $a->_date <=> $b->_date }
     qsearch( 'cust_pay', { 'invnum' => $self->invnum } )
   ;
 }
 
+=item cust_credited
+
+Returns all applied credits (see L<FS::cust_credit_bill>) for this invoice.
+
+=cut
+
+sub cust_credited {
+  my $self = shift;
+  sort { $a->_date <=> $b->_date }
+    qsearch( 'cust_credit_bill', { 'invnum' => $self->invnum } )
+  ;
+}
+
+=item tax
+
+Returns the tax amount (see L<FS::cust_bill_pkg>) for this invoice.
+
+=cut
+
+sub tax {
+  my $self = shift;
+  my $total = 0;
+  my @taxlines = qsearch( 'cust_bill_pkg', { 'invnum' => $self->invnum ,
+                                             'pkgnum' => 0 } );
+  foreach (@taxlines) { $total += $_->setup; }
+  $total;
+}
+
+=item owed
+
+Returns the amount owed (still outstanding) on this invoice, which is charged
+minus all payments (see L<FS::cust_pay>) and applied credits
+(see L<FS::cust_credit_bill>).
+
+=cut
+
+sub owed {
+  my $self = shift;
+  my $balance = $self->charged;
+  $balance -= $_->paid foreach ( $self->cust_pay );
+  $balance -= $_->amount foreach ( $self->cust_credited );
+  $balance = sprintf( "%.2f", $balance);
+}
+
 =item print_text [TIME];
 
 Returns an text invoice, as a list of lines.
@@ -281,12 +313,13 @@ sub print_text {
     push @buf, [
       "Previous Balance, Invoice #". $_->invnum. 
                  " (". time2str("%x",$_->_date). ")",
-      '$'. sprintf("%10.2f",$_->owed)
+      $money_char. sprintf("%10.2f",$_->owed)
     ];
   }
   if (@pr_cust_bill) {
     push @buf,['','-----------'];
-    push @buf,['Total Previous Balance','$' . sprintf("%10.2f",$pr_total ) ];
+    push @buf,[ 'Total Previous Balance',
+                $money_char. sprintf("%10.2f",$pr_total ) ];
     push @buf,['',''];
   }
 
@@ -300,7 +333,7 @@ sub print_text {
       my($pkg)=$part_pkg->pkg;
 
       if ( $_->setup != 0 ) {
-        push @buf, [ "$pkg Setup",'$' . sprintf("%10.2f",$_->setup) ];
+        push @buf, [ "$pkg Setup", $money_char. sprintf("%10.2f",$_->setup) ];
         push @buf,
           map { [ "  ". $_->[0]. ": ". $_->[1], '' ] } $cust_pkg->labels;
       }
@@ -309,33 +342,39 @@ sub print_text {
         push @buf, [
           "$pkg (" . time2str("%x",$_->sdate) . " - " .
                                 time2str("%x",$_->edate) . ")",
-          '$' . sprintf("%10.2f",$_->recur)
+          $money_char. sprintf("%10.2f",$_->recur)
         ];
         push @buf,
           map { [ "  ". $_->[0]. ": ". $_->[1], '' ] } $cust_pkg->labels;
       }
 
     } else { #pkgnum Tax
-      push @buf,["Tax",'$' . sprintf("%10.2f",$_->setup) ] 
+      push @buf,["Tax", $money_char. sprintf("%10.2f",$_->setup) ] 
         if $_->setup != 0;
     }
   }
 
   push @buf,['','-----------'];
   push @buf,['Total New Charges',
-             '$' . sprintf("%10.2f",$self->charged) ];
+             $money_char. sprintf("%10.2f",$self->charged) ];
   push @buf,['',''];
 
   push @buf,['','-----------'];
   push @buf,['Total Charges',
-             '$' . sprintf("%10.2f",$self->charged + $pr_total) ];
+             $money_char. sprintf("%10.2f",$self->charged + $pr_total) ];
   push @buf,['',''];
 
   #credits
+  foreach ( $self->cust_credited ) {
+    push @buf,[
+      "Credit #". $_->crednum. " (" . time2str("%x",$_->_date) .")",
+      $money_char. sprintf("%10.2f",$_->amount)
+    ];
+  }
   foreach ( @cr_cust_credit ) {
     push @buf,[
       "Credit #". $_->crednum. " (" . time2str("%x",$_->_date) .")",
-      '$' . sprintf("%10.2f",$_->credited)
+      $money_char. sprintf("%10.2f",$_->credited)
     ];
   }
 
@@ -343,13 +382,13 @@ sub print_text {
   foreach ( $self->cust_pay ) {
     push @buf,[
       "Payment received ". time2str("%x",$_->_date ),
-      '$' . sprintf("%10.2f",$_->paid )
+      $money_char. sprintf("%10.2f",$_->paid )
     ];
   }
 
   #balance due
   push @buf,['','-----------'];
-  push @buf,['Balance Due','$' 
+  push @buf,['Balance Due', $money_char
     sprintf("%10.2f",$self->owed + $pr_total - $cr_total ) ];
 
   #setup template variables
@@ -424,7 +463,7 @@ sub print_text {
 
 =head1 VERSION
 
-$Id: cust_bill.pm,v 1.3 2000-09-20 10:35:21 ivan Exp $
+$Id: cust_bill.pm,v 1.9 2001-09-01 21:52:19 jeff Exp $
 
 =head1 BUGS