X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=site_perl%2Fcust_bill.pm;h=0e87755ac37a96e78f6be074df2ffc08d465d4f2;hb=8f4617e35f89b741b8ab5ba9136667b4c877d992;hp=455fc2d4fd939ae5854da190e3c928e5fa201070;hpb=0bf5ad9ff0a65195db88ed0bac3aa11c33ec1ad3;p=freeside.git diff --git a/site_perl/cust_bill.pm b/site_perl/cust_bill.pm index 455fc2d4f..0e87755ac 100644 --- a/site_perl/cust_bill.pm +++ b/site_perl/cust_bill.pm @@ -1,17 +1,21 @@ package FS::cust_bill; use strict; -use vars qw(@ISA $conf $add1 $add2 $add3 $add4); -use Exporter; +use vars qw( @ISA $conf $add1 $add2 $add3 $add4 ); use Date::Format; -use FS::Record qw(fields qsearch qsearchs); +use FS::Record qw( qsearch qsearchs ); +use FS::cust_main; +use FS::cust_bill_pkg; +use FS::cust_credit; +use FS::cust_pay; +use FS::cust_pkg; -@ISA = qw(FS::Record Exporter); +@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; - ( $add1, $add2, $add3, $add4 ) = $conf->config('address'); + ( $add1, $add2, $add3, $add4 ) = ( $conf->config('address'), '', '', '', '' ); }; =head1 NAME @@ -22,8 +26,8 @@ FS::cust_bill - Object methods for cust_bill records use FS::cust_bill; - $record = create FS::cust_bill \%hash; - $record = create FS::cust_bill { 'column' => 'value' }; + $record = new FS::cust_bill \%hash; + $record = new FS::cust_bill { 'column' => 'value' }; $error = $record->insert; @@ -72,7 +76,7 @@ all payments (see L). =over 4 -=item create HASHREF +=item new HASHREF Creates a new invoice. To add the invoice to the database, see L<"insert">. Invoices are normally created by calling the bill method of a customer object @@ -80,17 +84,7 @@ Invoices are normally created by calling the bill method of a customer object =cut -sub create { - my($proto,$hashref)=@_; - - #now in FS::Record::new - #my($field); - #foreach $field (fields('cust_bill')) { - # $hashref->{$field}='' unless defined $hashref->{$field}; - #} - - $proto->new('cust_bill',$hashref); -} +sub table { 'cust_bill'; } =item insert @@ -103,14 +97,13 @@ automatically set to charged). =cut sub insert { - my($self)=@_; + my $self = shift; - $self->setfield('owed',$self->charged) if $self->owed eq ''; + $self->owed( $self->charged ) if $self->owed eq ''; return "owed != charged!" unless $self->owed == $self->charged; - $self->check or - $self->add; + $self->SUPER::insert; } =item delete @@ -122,8 +115,6 @@ no record you ever posted this invoice (which is bad, no?) sub delete { return "Can't remove invoice!" - #my($self)=@_; - #$self->del; } =item replace OLD_RECORD @@ -138,21 +129,14 @@ calling the collect method of a customer object (see L). =cut sub replace { - my($new,$old)=@_; - return "(Old) Not a cust_bill record!" unless $old->table eq "cust_bill"; - return "Can't change invnum!" - unless $old->getfield('invnum') eq $new->getfield('invnum'); - return "Can't change custnum!" - unless $old->getfield('custnum') eq $new->getfield('custnum'); - return "Can't change _date!" - unless $old->getfield('_date') eq $new->getfield('_date'); - return "Can't change charged!" - unless $old->getfield('charged') eq $new->getfield('charged'); - return "(New) owed can't be > (new) charged!" - if $new->getfield('owed') > $new->getfield('charged'); - - $new->check or - $new->rep($old); + my( $new, $old ) = ( shift, shift ); + return "Can't change custnum!" unless $old->custnum == $new->custnum; + #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); } =item check @@ -164,30 +148,24 @@ methods. =cut sub check { - my($self)=@_; - return "Not a cust_bill record!" unless $self->table eq "cust_bill"; - my($recref) = $self->hashref; - - $recref->{invnum} =~ /^(\d*)$/ or return "Illegal invnum"; - $recref->{invnum} = $1; + my $self = shift; + + my $error = + $self->ut_numbern('invnum') + || $self->ut_number('custnum') + || $self->ut_numbern('_date') + || $self->ut_money('charged') + || $self->ut_money('owed') + || $self->ut_numbern('printed') + ; + return $error if $error; - $recref->{custnum} =~ /^(\d+)$/ or return "Illegal custnum"; - $recref->{custnum} = $1; return "Unknown customer" - unless qsearchs('cust_main',{'custnum'=>$recref->{custnum}}); - - $recref->{_date} =~ /^(\d*)$/ or return "Illegal date"; - $recref->{_date} = $recref->{_date} ? $1 : time; + unless qsearchs( 'cust_main', { 'custnum' => $self->custnum } ); - #$recref->{charged} =~ /^(\d+(\.\d\d)?)$/ or return "Illegal charged"; - $recref->{charged} =~ /^(\-?\d+(\.\d\d)?)$/ or return "Illegal charged"; - $recref->{charged} = $1; + $self->_date(time) unless $self->_date; - $recref->{owed} =~ /^(\-?\d+(\.\d\d)?)$/ or return "Illegal owed"; - $recref->{owed} = $1; - - $recref->{printed} =~ /^(\d*)$/ or return "Illegal printed"; - $recref->{printed} = $1 || '0'; + $self->printed(0) if $self->printed eq ''; ''; #no error } @@ -200,13 +178,13 @@ followed by the previous outstanding invoices (as FS::cust_bill objects also). =cut sub previous { - my($self)=@_; - my($total)=0; - my(@cust_bill) = sort { $a->_date <=> $b->_date } + my $self = shift; + my $total = 0; + my @cust_bill = sort { $a->_date <=> $b->_date } grep { $_->owed != 0 && $_->_date < $self->_date } - qsearch('cust_bill',{ 'custnum' => $self->custnum } ) + qsearch( 'cust_bill', { 'custnum' => $self->custnum } ) ; - foreach (@cust_bill) { $total += $_->owed; } + foreach ( @cust_bill ) { $total += $_->owed; } $total, @cust_bill; } @@ -217,7 +195,7 @@ Returns the line items (see L) for this invoice. =cut sub cust_bill_pkg { - my($self)=@_; + my $self = shift; qsearch( 'cust_bill_pkg', { 'invnum' => $self->invnum } ); } @@ -230,9 +208,9 @@ credits (FS::cust_credit objects). =cut sub cust_credit { - my($self)=@_; - my($total)=0; - my(@cust_credit) = sort { $a->_date <=> $b->date } + 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 } ) ; @@ -247,7 +225,7 @@ Returns all payments (see L) for this invoice. =cut sub cust_pay { - my($self)=@_; + my $self = shift; sort { $a->_date <=> $b->date } qsearch( 'cust_pay', { 'invnum' => $self->invnum } ) ; @@ -266,216 +244,201 @@ L and L for conversion functions. sub print_text { - my($self,$today)=@_; + my( $self, $today ) = ( shift, shift ); $today ||= time; - my($invnum)=$self->invnum; - my($cust_main) = qsearchs('cust_main', - { 'custnum', $self->custnum } ); - $cust_main->setfield('payname', - $cust_main->first. ' '. $cust_main->getfield('last') - ) unless $cust_main->payname; + my $invnum = $self->invnum; + my $cust_main = qsearchs('cust_main', { 'custnum', $self->custnum } ); + $cust_main->payname( $cust_main->first. ' '. $cust_main->getfield('last') ) + 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( $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; #overdue? - my($overdue) = ( + my $overdue = ( $balance_due > 0 && $today > $self->_date && $self->printed > 1 ); - #printing bits here - - local($SIG{CHLD}) = sub { wait() }; - $|=1; - my($pid)=open(CHILD,"-|"); - die "Can't fork: $!" unless defined($pid); - - if ($pid) { #parent - my(@collect)=; - close CHILD; - return @collect; - } else { #child - - my($description,$amount); - my(@buf); - - #define format stuff - $%=0; - $= = 35; - local($^L) = <payname. + ( ( $cust_main->payby eq 'BILL' ) && $cust_main->payinfo + ? " (P.O. #". $cust_main->payinfo. ")" + : '' + ) + ; + $address[$l++]=$cust_main->company if $cust_main->company; + $address[$l++]=$cust_main->address1; + $address[$l++]=$cust_main->address2 if $cust_main->address2; + $address[$l++]=$cust_main->city. ", ". $cust_main->state. " ". + $cust_main->zip; + $address[$l++]=$cust_main->country unless $cust_main->country eq 'US'; + + #previous balance + foreach ( @pr_cust_bill ) { + push @buf, ( + "Previous Balance, Invoice #". $_->invnum. + " (". time2str("%x",$_->_date). ")", + '$'. sprintf("%10.2f",$_->owed) + ); + } + if (@pr_cust_bill) { + push @buf,('','-----------'); + push @buf,('Total Previous Balance','$' . sprintf("%10.2f",$pr_total ) ); + push @buf,('',''); + } - #format address - my($l,@address)=(0,'','','','',''); - $address[$l++]=$cust_main->company if $cust_main->company; - $address[$l++]=$cust_main->address1; - $address[$l++]=$cust_main->address2 if $cust_main->address2; - $address[$l++]=$cust_main->city. ", ". $cust_main->state. " ". - $cust_main->zip; - $address[$l++]=$cust_main->country unless $cust_main->country eq 'US'; - - #previous balance - foreach ( @pr_cust_bill ) { - push @buf, ( - "Previous Balance, Invoice #". $_->invnum. - " (". time2str("%x",$_->_date). ")", - '$'. sprintf("%10.2f",$_->owed) - ); - } - if (@pr_cust_bill) { - push @buf,('','-----------'); - push @buf,('Total Previous Balance','$' . sprintf("%10.2f",$pr_total ) ); - push @buf,('',''); - } + #new charges + foreach ( $self->cust_bill_pkg ) { - #new charges - foreach ( $self->cust_bill_pkg ) { + if ( $_->pkgnum ) { - if ( $_->pkgnum ) { + my($cust_pkg)=qsearchs('cust_pkg', { 'pkgnum', $_->pkgnum } ); + my($part_pkg)=qsearchs('part_pkg',{'pkgpart'=>$cust_pkg->pkgpart}); + my($pkg)=$part_pkg->pkg; - my($cust_pkg)=qsearchs('cust_pkg', { 'pkgnum', $_->pkgnum } ); - my($part_pkg)=qsearchs('part_pkg',{'pkgpart'=>$cust_pkg->pkgpart}); - my($pkg)=$part_pkg->pkg; + if ( $_->setup != 0 ) { + push @buf, ( "$pkg Setup",'$' . sprintf("%10.2f",$_->setup) ); + push @buf, map { " ". $_->[0]. ": ". $_->[1], '' } $cust_pkg->labels; + } - push @buf, ( "$pkg Setup",'$' . sprintf("%10.2f",$_->setup) ) - if $_->setup != 0; + if ( $_->recur != 0 ) { push @buf, ( "$pkg (" . time2str("%x",$_->sdate) . " - " . time2str("%x",$_->edate) . ")", '$' . sprintf("%10.2f",$_->recur) - ) if $_->recur != 0; - - } else { #pkgnum Tax - push @buf,("Tax",'$' . sprintf("%10.2f",$_->setup) ) - if $_->setup != 0; + ); + push @buf, map { " ". $_->[0]. ": ". $_->[1], '' } $cust_pkg->labels; } - } - - push @buf,('','-----------'); - push @buf,('Total New Charges', - '$' . sprintf("%10.2f",$self->charged) ); - push @buf,('',''); - - push @buf,('','-----------'); - push @buf,('Total Charges', - '$' . sprintf("%10.2f",$self->charged + $pr_total) ); - push @buf,('',''); - #credits - foreach ( @cr_cust_credit ) { - push @buf,( - "Credit #". $_->crednum. " (" . time2str("%x",$_->_date) .")", - '$' . sprintf("%10.2f",$_->credited) - ); + } else { #pkgnum Tax + push @buf,("Tax",'$' . sprintf("%10.2f",$_->setup) ) + if $_->setup != 0; } - - #get & print payments - foreach ( $self->cust_pay ) { - push @buf,( - "Payment received ". time2str("%x",$_->_date ), - '$' . sprintf("%10.2f",$_->paid ) - ); - } - - #balance due - push @buf,('','-----------'); - push @buf,('Balance Due','$' . - sprintf("%10.2f",$self->owed + $pr_total - $cr_total ) ); - - #now print - - my($tot_pages)=int(scalar(@buf)/30); #15 lines, 2 values per line - $tot_pages++ if scalar(@buf) % 30; - - while (@buf) { + } + + push @buf,('','-----------'); + push @buf,('Total New Charges', + '$' . sprintf("%10.2f",$self->charged) ); + push @buf,('',''); + + push @buf,('','-----------'); + push @buf,('Total Charges', + '$' . sprintf("%10.2f",$self->charged + $pr_total) ); + push @buf,('',''); + + #credits + foreach ( @cr_cust_credit ) { + push @buf,( + "Credit #". $_->crednum. " (" . time2str("%x",$_->_date) .")", + '$' . sprintf("%10.2f",$_->credited) + ); + } + + #get & print payments + foreach ( $self->cust_pay ) { + push @buf,( + "Payment received ". time2str("%x",$_->_date ), + '$' . sprintf("%10.2f",$_->paid ) + ); + } + + #balance due + push @buf,('','-----------'); + push @buf,('Balance Due','$' . + sprintf("%10.2f",$self->owed + $pr_total - $cr_total ) ); + + #now print + + my $tot_lines = 50; #should be configurable + #header is 17 lines + my $tot_pages = int( scalar(@buf) / ( 2 * ( $tot_lines - 17 ) ) ); + $tot_pages++ if scalar(@buf) % ( 2 * ( $tot_lines - 17 ) ); + + my $page = 1; + my $lines; + while (@buf) { + $lines = $tot_lines; + my @header = &header( + $page, $tot_pages, $self->_date, $self->invnum, @address + ); + push @collect, @header; + $lines -= scalar(@header); + + while ( $lines-- && @buf ) { $description=shift(@buf); $amount=shift(@buf); - write; + push @collect, myswrite($description, $amount); } - ($description,$amount)=('',''); - write while ( $- ); - print $^L; - - exit; #kid - - format STDOUT_TOP = - - @||||||||||||||||||| - "Invoice" - @||||||||||||||||||| @<<<<<<< @<<<<<<<<<<< -{ - ( $tot_pages != 1 ) ? "Page $% of $tot_pages" : '', - time2str("%x",( $self->_date )), "FS-$invnum" -} - - -@>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -$add1 -@>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -$add2 -@>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -$add3 -@>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -$add4 - - @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< -{ $cust_main->payname, - ( ( $cust_main->payby eq 'BILL' ) && $cust_main->payinfo ) - ? "P.O. #". $cust_main->payinfo : '' -} - @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< -$address[0],'' - @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< -$address[1],$overdue ? "* This invoice is now PAST DUE! *" : '' - @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< -$address[2],$overdue ? " Please forward payment promptly " : '' - @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< -$address[3],$overdue ? "to avoid interruption of service." : '' - @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< -$address[4],'' - - - -. - - format STDOUT = + $page++; + } + while ( $lines-- ) { + push @collect, myswrite('', ''); + } + + return @collect; + + sub header { #17 lines + my ( $page, $tot_pages, $date, $invnum, @address ) = @_ ; + push @address, '', '', '', ''; + + my @return = (); + my $i = ' 'x32; + push @return, + '', + $i. 'Invoice', + $i. substr("Page $page of $tot_pages".' 'x10, 0, 20). + time2str("%x", $date ). " FS-". $invnum, + '', + '', + $add1, + $add2, + $add3, + $add4, + '', + splice @address, 0, 7; + ; + return map $_. "\n", @return; + } + + sub myswrite { + my $format = <, L, L, L, @@ -492,7 +455,20 @@ charges can be negative ivan@sisd.com 98-jul-13 pod, ingegrate with FS::Invoice ivan@sisd.com 98-sep-20 $Log: cust_bill.pm,v $ -Revision 1.3 1998-11-13 09:56:53 ivan +Revision 1.7 1999-02-09 09:55:05 ivan +invoices show line items for each service in a package (see the label method +of FS::cust_svc) + +Revision 1.6 1999/01/25 12:26:07 ivan +yet more mod_perl stuff + +Revision 1.5 1999/01/18 21:58:03 ivan +esthetic: eq and ne were used in a few places instead of == and != + +Revision 1.4 1998/12/29 11:59:36 ivan +mostly properly OO, some work still to be done with svc_ stuff + +Revision 1.3 1998/11/13 09:56:53 ivan change configuration file layout to support multiple distinct databases (with own set of config files, export, etc.)