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;
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;
@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
=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">).
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
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
#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);
}
|| $self->ut_number('custnum')
|| $self->ut_numbern('_date')
|| $self->ut_money('charged')
- || $self->ut_money('owed')
|| $self->ut_numbern('printed')
;
return $error if $error;
=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).
+Depreciated. See the cust_credited method.
+
+ #Returns a list consisting of the total previous credited (see
+ #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 }
- grep { $_->credited != 0 && $_->_date < $self->_date }
- qsearch('cust_credit', { 'custnum' => $self->custnum } )
- ;
- foreach (@cust_credit) { $total += $_->credited; }
- $total, @cust_credit;
+ use Carp;
+ croak "FS::cust_bill->cust_credit depreciated; see ".
+ "FS::cust_bill->cust_credit_bill";
+ #my $self = shift;
+ #my $total = 0;
+ #my @cust_credit = sort { $a->_date <=> $b->_date }
+ # grep { $_->credited != 0 && $_->_date < $self->_date }
+ # qsearch('cust_credit', { 'custnum' => $self->custnum } )
+ #;
+ #foreach (@cust_credit) { $total += $_->credited; }
+ #$total, @cust_credit;
}
=item cust_pay
-Returns all payments (see L<FS::cust_pay>) for this invoice.
+Depreciated. See the cust_bill_pay method.
+
+#Returns all payments (see L<FS::cust_pay>) for this invoice.
=cut
sub cust_pay {
+ use Carp;
+ croak "FS::cust_bill->cust_pay depreciated; see FS::cust_bill->cust_bill_pay";
+ #my $self = shift;
+ #sort { $a->_date <=> $b->_date }
+ # qsearch( 'cust_pay', { 'invnum' => $self->invnum } )
+ #;
+}
+
+=item cust_bill_pay
+
+Returns all payment applications (see L<FS::cust_bill_pay>) for this invoice.
+
+=cut
+
+sub cust_bill_pay {
my $self = shift;
- sort { $a->_date <=> $b->date }
- qsearch( 'cust_pay', { 'invnum' => $self->invnum } )
+ sort { $a->_date <=> $b->_date }
+ qsearch( 'cust_bill_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 payment applications (see L<FS::cust_bill_pay>) and credit
+applications (see L<FS::cust_credit_bill>).
+
+=cut
+
+sub owed {
+ my $self = shift;
+ my $balance = $self->charged;
+ $balance -= $_->amount foreach ( $self->cust_bill_pay );
+ $balance -= $_->amount foreach ( $self->cust_credited );
+ $balance = sprintf( "%.2f", $balance);
+ $balance =~ s/^\-0\.00$/0.00/; #yay ieee fp
+ $balance;
+}
+
=item print_text [TIME];
Returns an text invoice, as a list of lines.
unless $cust_main->payname;
my( $pr_total, @pr_cust_bill ) = $self->previous; #previous balance
- my( $cr_total, @cr_cust_credit ) = $self->cust_credit; #credits
- my $balance_due = $self->owed + $pr_total - $cr_total;
-
- #
+# my( $cr_total, @cr_cust_credit ) = $self->cust_credit; #credits
+ #my $balance_due = $self->owed + $pr_total - $cr_total;
+ my $balance_due = $self->owed + $pr_total;
#my @collect = ();
#my($description,$amount);
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,['',''];
}
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;
}
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 ( @cr_cust_credit ) {
+ foreach ( $self->cust_credited ) {
+
+ #something more elaborate if $_->amount ne $_->cust_credit->credited ?
+
+ my $reason = substr($_->cust_credit->reason,0,32);
+ $reason .= '...' if length($reason) < length($_->cust_credit->reason);
+ $reason = " ($reason) " if $reason;
push @buf,[
- "Credit #". $_->crednum. " (" . time2str("%x",$_->_date) .")",
- '$' . sprintf("%10.2f",$_->credited)
+ "Credit #". $_->crednum. " (". time2str("%x",$_->cust_credit->_date) .")".
+ $reason,
+ $money_char. sprintf("%10.2f",$_->amount)
];
}
+ #foreach ( @cr_cust_credit ) {
+ # push @buf,[
+ # "Credit #". $_->crednum. " (" . time2str("%x",$_->_date) .")",
+ # $money_char. sprintf("%10.2f",$_->credited)
+ # ];
+ #}
#get & print payments
- foreach ( $self->cust_pay ) {
+ foreach ( $self->cust_bill_pay ) {
+
+ #something more elaborate if $_->amount ne ->cust_pay->paid ?
+
push @buf,[
- "Payment received ". time2str("%x",$_->_date ),
- '$' . sprintf("%10.2f",$_->paid )
+ "Payment received ". time2str("%x",$_->cust_pay->_date ),
+ $money_char. sprintf("%10.2f",$_->amount )
];
}
#balance due
push @buf,['','-----------'];
- push @buf,['Balance Due','$' .
- sprintf("%10.2f",$self->owed + $pr_total - $cr_total ) ];
+ push @buf,['Balance Due', $money_char.
+ sprintf("%10.2f", $balance_due ) ];
#setup template variables
=head1 VERSION
-$Id: cust_bill.pm,v 1.3 2000-09-20 10:35:21 ivan Exp $
+$Id: cust_bill.pm,v 1.14 2001-12-21 21:40:24 ivan Exp $
=head1 BUGS
=head1 SEE ALSO
-L<FS::Record>, L<FS::cust_main>, L<FS::cust_pay>, L<FS::cust_bill_pkg>,
-L<FS::cust_credit>, schema.html from the base documentation.
+L<FS::Record>, L<FS::cust_main>, L<FS::cust_bill_pay>, L<FS:;cust_pay>,
+L<FS::cust_bill_pkg>, L<FS::cust_bill_credit>, schema.html from the base
+documentation.
=cut