X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_bill.pm;h=9b7c4add7907e8acd991e5f5f44bcbda210973f8;hb=dc3217c61d6a62a8e599d8804e05ba45b3224c7e;hp=ee95be83a31c089703e5e291e46515210bea8a27;hpb=5e05724a635a22776f1b973f5d7e77989da4e048;p=freeside.git diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index ee95be83a..9b7c4add7 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -1347,7 +1347,7 @@ sub print_csv { if ( $cust_bill_pkg->pkgnum ) { ($pkg, $setup, $recur, $sdate, $edate) = ( - $cust_bill_pkg->cust_pkg->part_pkg->pkg, + $cust_bill_pkg->part_pkg->pkg, ( $cust_bill_pkg->setup != 0 ? sprintf("%.2f", $cust_bill_pkg->setup ) : '' ), @@ -1468,7 +1468,7 @@ sub realtime_bop { $cust_main->agentnum. ")"; my $agent = $agent_obj->agent; my $pkgs = join(', ', - map { $_->cust_pkg->part_pkg->pkg } + map { $_->part_pkg->pkg } grep { $_->pkgnum } $self->cust_bill_pkg ); $description = eval qq("$dtempl"); @@ -1635,7 +1635,7 @@ sub print_generic { $templatefile .= "_$template" if length($template); my @invoice_template = map "$_\n", $conf->config($templatefile) - or die "cannot load config file $templatefile"; + or die "cannot load config data $templatefile"; my $old_latex = ''; if ( $format eq 'latex' && grep { /^%%Detail/ } @invoice_template ) { @@ -1653,7 +1653,7 @@ sub print_generic { ); $text_template->compile() - or die 'While compiling ' . $templatefile . ': ' . $Text::Template::ERROR; + or die "Can't compile $templatefile: $Text::Template::ERROR\n"; # additional substitution could possibly cause breakage in existing templates @@ -1674,8 +1674,10 @@ sub print_generic { s/\\item /
  • /g; s/\\end\{enumerate\}/<\/ol>/g; s/\\textbf\{(.*)\}/$1<\/b>/g; - s/\\\\\*/ /; + s/\\\\\*/
    /g; s/\\dollar ?/\$/g; + s/\\#/#/g; + s/~/ /g; $_; } @_ }, @@ -1738,7 +1740,7 @@ sub print_generic { ); my $escape_function = $escape_functions{$format}; - my %date_formats = ( 'latex' => '%b, %o, %Y', + my %date_formats = ( 'latex' => '%b %o, %Y', 'html' => '%b %o, %Y', 'template' => '%s', ); @@ -1783,13 +1785,17 @@ sub print_generic { ); } elsif ( grep /\S/, $conf->config('company_address') ) { - $returnaddress = join( "\n", $conf->config('company_address') ); - - $returnaddress = - join( '\\*'."\n", map s/( {2,})/'~' x length($1)/eg, - $conf->config('company_address') - ) - if $format eq 'latex'; + my $convert_map = $convert_maps{$format}{'returnaddress'}; + $returnaddress = join( "\n", &$convert_map( + map { s/( {2,})/'~' x length($1)/eg; + s/$/\\\\\*/; + $_ + } + ( $conf->config('company_name'), + $conf->config('company_address'), + ) + ) + ); } else { @@ -1861,33 +1867,38 @@ sub print_generic { #do variable substitution in notes, footer, smallfooter foreach my $include (qw( notes footer smallfooter )) { - my @inc_src = $conf->config_orbase("invoice_latex$include", $template ); - my $convert_map = $convert_maps{$format}{$include}; + my $inc_file = $conf->key_orbase("invoice_${format}$include", $template); + my @inc_src; + + if ( $conf->exists($inc_file) && length( $conf->config($inc_file) ) ) { + + @inc_src = $conf->config($inc_file); - if ( - defined( $conf->config_orbase("invoice_${format}$include", $template) ) - && length( $conf->config_orbase('invoice_${format}$include', $template) ) - ) { - @inc_src = $conf->config_orbase("invoice_${format}$include", $template ); } else { - @inc_src = - map { s/\[@--/$delimiters{$format}[0]/g; - s/--@]/$delimiters{$format}[1]/g; - $_; - } - &$convert_map( - $conf->config_orbase("invoice_latex$include", $template ) - ); + + $inc_file = $conf->key_orbase("invoice_latex$include", $template); + + my $convert_map = $convert_maps{$format}{$include}; + + @inc_src = map { s/\[\@--/$delimiters{$format}[0]/g; + s/--\@\]/$delimiters{$format}[1]/g; + $_; + } + &$convert_map( $conf->config($inc_file) ); + } my $inc_tt = new Text::Template ( TYPE => 'ARRAY', SOURCE => [ map "$_\n", @inc_src ], DELIMITERS => $delimiters{$format}, - ) or die "can't create new Text::Template object: $Text::Template::ERROR"; + ) or die "Can't create new Text::Template object: $Text::Template::ERROR"; - $inc_tt->compile() - or die "can't compile template: $Text::Template::ERROR"; + unless ( $inc_tt->compile() ) { + my $error = "Can't compile $inc_file template: $Text::Template::ERROR\n"; + warn $error. "Template:\n". join('', map "$_\n", @inc_src); + die $error; + } $invoice_data{$include} = $inc_tt->fill_in( HASH => \%invoice_data ); @@ -1939,7 +1950,11 @@ sub print_generic { push @sections, { 'description' => '', 'subtotal' => '' }; } - foreach my $line_item ( $self->_items_previous ) { + foreach my $line_item ( $conf->exists('disable_previous_balance') + ? () + : $self->_items_previous + ) + { my $detail = { ext_description => [], }; @@ -1964,7 +1979,7 @@ sub print_generic { ]; } - if (@pr_cust_bill) { + if ( @pr_cust_bill && !$conf->exists('disable_previous_balance') ) { push @buf, ['','-----------']; push @buf, [ 'Total Previous Balance', $money_char. sprintf("%10.2f", $pr_total) ]; @@ -1985,6 +2000,7 @@ sub print_generic { my %options = (); $options{'section'} = $section if $multisection; + $options{'format'} = $format; foreach my $line_item ( $self->_items_pkg(%options) ) { my $detail = { @@ -1995,9 +2011,7 @@ sub print_generic { $detail->{'section'} = $section; $detail->{'description'} = &$escape_function($line_item->{'description'}); if ( exists $line_item->{'ext_description'} ) { - @{$detail->{'ext_description'}} = map { - &$escape_function($_); - } @{$line_item->{'ext_description'}}; + @{$detail->{'ext_description'}} = @{$line_item->{'ext_description'}}; } { my $money = $old_latex ? '' : $money_char; @@ -2025,7 +2039,7 @@ sub print_generic { } - if ( $multisection ) { + if ( $multisection && !$conf->exists('disable_previous_balance') ) { unshift @sections, $previous_section; } @@ -2055,7 +2069,10 @@ sub print_generic { } push @buf,['','-----------']; - push @buf,['Total New Charges', + push @buf,[( $conf->exists('disable_previous_balance') + ? 'Total Charges' + : 'Total New Charges' + ), $money_char. sprintf("%10.2f",$self->charged) ]; push @buf,['','']; @@ -2063,66 +2080,79 @@ sub print_generic { my $total = {}; $total->{'total_item'} = &$embolden_function('Total'); $total->{'total_amount'} = - $total->{'total_amount'} = &$embolden_function( - $other_money_char. sprintf('%.2f', $self->charged + $pr_total ) + $other_money_char. + sprintf( '%.2f', + $self->charged + ( $conf->exists('disable_previous_balance') + ? 0 + : $pr_total + ) + ) ); push @total_items, $total; push @buf,['','-----------']; push @buf,['Total Charges', - $money_char. sprintf("%10.2f",$self->charged + $pr_total) ]; + $money_char. + sprintf( '%10.2f', $self->charged + + ( $conf->exists('disable_previous_balance') + ? 0 + : $pr_total + ) + ) + ]; push @buf,['','']; } - - #foreach my $thing ( sort { $a->_date <=> $b->_date } $self->_items_credits, $self->_items_payments + unless ( $conf->exists('disable_previous_balance') ) { + #foreach my $thing ( sort { $a->_date <=> $b->_date } $self->_items_credits, $self->_items_payments - # credits - foreach my $credit ( $self->_items_credits ) { - my $total; - $total->{'total_item'} = &$escape_function($credit->{'description'}); - #$credittotal - $total->{'total_amount'} = '-'. $other_money_char. $credit->{'amount'}; - push @total_items, $total; - } + # credits + foreach my $credit ( $self->_items_credits ) { + my $total; + $total->{'total_item'} = &$escape_function($credit->{'description'}); + #$credittotal + $total->{'total_amount'} = '-'. $other_money_char. $credit->{'amount'}; + push @total_items, $total; + } - # credits (again) - 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",$_->cust_credit->_date) .")". $reason, - $money_char. sprintf("%10.2f",$_->amount) - ]; - } + # credits (again) + 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",$_->cust_credit->_date) .")". $reason, + $money_char. sprintf("%10.2f",$_->amount) + ]; + } - # payments - foreach my $payment ( $self->_items_payments ) { - my $total = {}; - $total->{'total_item'} = &$escape_function($payment->{'description'}); - #$paymenttotal - $total->{'total_amount'} = '-'. $other_money_char. $payment->{'amount'}; - push @total_items, $total; - push @buf, [ $payment->{'description'}, - $money_char. sprintf("%10.2f", $payment->{'amount'}), - ]; - } + # payments + foreach my $payment ( $self->_items_payments ) { + my $total = {}; + $total->{'total_item'} = &$escape_function($payment->{'description'}); + #$paymenttotal + $total->{'total_amount'} = '-'. $other_money_char. $payment->{'amount'}; + push @total_items, $total; + push @buf, [ $payment->{'description'}, + $money_char. sprintf("%10.2f", $payment->{'amount'}), + ]; + } - { - my $total; - $total->{'total_item'} = &$embolden_function($self->balance_due_msg); - $total->{'total_amount'} = - &$embolden_function( - $other_money_char. sprintf('%.2f', $self->owed + $pr_total ) - ); - push @total_items, $total; - push @buf,['','-----------']; - push @buf,[$self->balance_due_msg, $money_char. - sprintf("%10.2f", $balance_due ) ]; + { + my $total; + $total->{'total_item'} = &$embolden_function($self->balance_due_msg); + $total->{'total_amount'} = + &$embolden_function( + $other_money_char. sprintf('%.2f', $self->owed + $pr_total ) + ); + push @total_items, $total; + push @buf,['','-----------']; + push @buf,[$self->balance_due_msg, $money_char. + sprintf("%10.2f", $balance_due ) ]; + } } $invoice_data{'logo_file'} = $params{'logo_file'} @@ -2405,7 +2435,7 @@ sub _items_sections { if ( $cust_bill_pkg->pkgnum > 0 ) { - my $desc = $cust_bill_pkg->cust_pkg->part_pkg->classname; + my $desc = $cust_bill_pkg->part_pkg->classname; $s{$desc} += $cust_bill_pkg->setup if ( $cust_bill_pkg->setup != 0 ); @@ -2472,26 +2502,40 @@ sub _items_pkg { my @cust_bill_pkg = grep { $_->pkgnum && ( defined($section) - ? $_->cust_pkg->part_pkg->classname eq $section->{'description'} + ? $_->part_pkg->classname eq $section->{'description'} : 1 ) } $self->cust_bill_pkg; $self->_items_cust_bill_pkg(\@cust_bill_pkg, %options); } +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; +} + sub _items_tax { my $self = shift; - my @cust_bill_pkg = grep { ! $_->pkgnum } $self->cust_bill_pkg; + my @cust_bill_pkg = sort _taxsort grep { ! $_->pkgnum } $self->cust_bill_pkg; $self->_items_cust_bill_pkg(\@cust_bill_pkg, @_); } sub _items_cust_bill_pkg { my $self = shift; my $cust_bill_pkg = shift; + my %opt = @_; + my $format = $opt{format} || ''; + my $escape_function = $opt{escape_function} || sub { shift }; my @b = (); foreach my $cust_bill_pkg ( @$cust_bill_pkg ) { + my $cust_pkg = $cust_bill_pkg->cust_pkg; + my $desc = $cust_bill_pkg->desc; if ( $cust_bill_pkg->pkgnum > 0 ) { @@ -2499,8 +2543,11 @@ sub _items_cust_bill_pkg { if ( $cust_bill_pkg->setup != 0 ) { my $description = $desc; $description .= ' Setup' if $cust_bill_pkg->recur != 0; - my @d = $cust_bill_pkg->cust_pkg->h_labels_short($self->_date); - push @d, $cust_bill_pkg->details if $cust_bill_pkg->recur == 0; + my @d = $cust_pkg->h_labels_short($self->_date); + push @d, $cust_bill_pkg->details( 'format' => $format, + 'escape_function' => $escape_function, + ) + if $cust_bill_pkg->recur == 0; push @b, { description => $description, #pkgpart => $part_pkg->pkgpart, @@ -2522,9 +2569,13 @@ sub _items_cust_bill_pkg { pkgnum => $cust_bill_pkg->pkgnum, amount => sprintf("%.2f", $cust_bill_pkg->recur), ext_description => - [ $cust_bill_pkg->cust_pkg->h_labels_short( $cust_bill_pkg->edate, - $cust_bill_pkg->sdate), - $cust_bill_pkg->details, + #at least until cust_bill_pkg has "past" ranges in addition to + #the "future" sdate/edate ones... see #3032 + [ $cust_pkg->h_labels_short( $self->_date ), + #$cust_bill_pkg->edate, + #$cust_bill_pkg->sdate), + $cust_bill_pkg->details( 'format' => $format, + 'escape_function' => $escape_function), ], }; } @@ -2643,7 +2694,7 @@ use Data::Dumper; use MIME::Base64; sub process_re_X { my( $method, $job ) = ( shift, shift ); - warn "process_re_X $method for job $job\n" if $DEBUG; + warn "$me process_re_X $method for job $job\n" if $DEBUG; my $param = thaw(decode_base64(shift)); warn Dumper($param) if $DEBUG; @@ -2669,16 +2720,20 @@ sub re_X { my $extra_sql = ' WHERE '. FS::cust_bill->search_sql(\%param); - my $addl_from = 'left join cust_main using ( custnum )'; + my $addl_from = 'LEFT JOIN cust_main USING ( custnum )'; - my @cust_bill = qsearch( 'cust_bill', - {}, - #"$distinct cust_bill.*", - "cust_bill.*", - $extra_sql, - '', - $addl_from - ); + my @cust_bill = qsearch( { + #'select' => "cust_bill.*", + 'table' => 'cust_bill', + 'addl_from' => $addl_from, + 'hashref' => {}, + 'extra_sql' => $extra_sql, + 'order_by' => $orderby, + 'debug' => 1, + } ); + + warn " $me re_X $method: ". scalar(@cust_bill). " invoices found\n" + if $DEBUG; my( $num, $last, $min_sec ) = (0, time, 5); #progresbar foo foreach my $cust_bill ( @cust_bill ) { @@ -2788,6 +2843,11 @@ Note: validates all passed-in data; i.e. safe to use with unchecked CGI params. sub search_sql { my($class, $param) = @_; + if ( $DEBUG ) { + warn "$me search_sql called with params: \n". + join("\n", map { " $_: ". $param->{$_} } keys %$param ). "\n"; + } + my @search = (); if ( $param->{'begin'} =~ /^(\d+)$/ ) { @@ -2838,7 +2898,22 @@ sub search_sql { } - push @search, $FS::CurrentUser::CurrentUser->agentnums_sql; + my $curuser = $FS::CurrentUser::CurrentUser; + if ( $curuser->username eq 'fs_queue' + && $param->{'CurrentUser'} =~ /^(\w+)$/ ) { + my $username = $1; + my $newuser = qsearchs('access_user', { + 'username' => $username, + 'disabled' => '', + } ); + if ( $newuser ) { + $curuser = $newuser; + } else { + warn "$me WARNING: (fs_queue) can't find CurrentUser $username\n"; + } + } + + push @search, $curuser->agentnums_sql; join(' AND ', @search );