sub batch_invoice {
my ($self, $opt) = @_;
- my $batch = FS::bill_batch->get_open_batch;
+ my $bill_batch = $self->get_open_bill_batch;
my $cust_bill_batch = FS::cust_bill_batch->new({
- batchnum => $batch->batchnum,
+ batchnum => $bill_batch->batchnum,
invnum => $self->invnum,
});
return $cust_bill_batch->insert($opt);
}
+=item get_open_batch
+
+Returns the currently open batch as an FS::bill_batch object, creating a new
+one if necessary. (A per-agent batch if invoice_print_pdf-spoolagent is
+enabled)
+
+=cut
+
+sub get_open_bill_batch {
+ my $self = shift;
+ my $hashref = { status => 'O' };
+ $hashref->{'agentnum'} = $conf->exists('invoice_print_pdf-spoolagent')
+ ? $self->cust_main->agentnum
+ : '';
+ my $batch = qsearchs('bill_batch', $hashref);
+ return $batch if $batch;
+ $batch = FS::bill_batch->new($hashref);
+ my $error = $batch->insert;
+ die $error if $error;
+ return $batch;
+}
+
=item ftp_invoice [ TEMPLATENAME ]
Sends this invoice data via FTP.
$params{'time'} = $today if $today;
$params{'template'} = $template if $template;
$params{$_} = $opt{$_}
- foreach grep $opt{$_}, qw( unsquealch_cdr notice_name );
+ foreach grep $opt{$_}, qw( unsquelch_cdr notice_name );
$self->print_generic( %params );
}
$params{'time'} = $today if $today;
$params{'template'} = $template if $template;
$params{$_} = $opt{$_}
- foreach grep $opt{$_}, qw( unsquealch_cdr notice_name );
+ foreach grep $opt{$_}, qw( unsquelch_cdr notice_name );
$template ||= $self->_agent_template;
# (alignment in text invoice?) problems to change them all to '%.2f' ?
# yes: fixed width (dot matrix) text printing will be borked
sub print_generic {
-
my( $self, %params ) = @_;
my $today = $params{today} ? $params{today} : time;
warn "$me print_generic called on $self with suffix $params{template}\n"
push @detail_items,
{ 'description' => $didsummary_desc,
'ext_description' => [ $didsummary, $minutes ],
- }
- if !$multisection;
+ };
}
foreach my $section (@sections, @$late_sections) {
my %classnums = ();
my %lines = ();
+ my $maxlength = $conf->config('cust_bill-latex_lineitem_maxlength') || 50;
+
my %usage_class = map { $_->classnum => $_ } qsearch( 'usage_class', {} );
foreach my $cust_bill_pkg ( $self->cust_bill_pkg ) {
next unless $cust_bill_pkg->pkgnum > 0;
my $desc = $detail->regionname;
my $description = $desc;
- $description = substr($desc, 0, 50). '...'
- if $format eq 'latex' && length($desc) > 50;
+ $description = substr($desc, 0, $maxlength). '...'
+ if $format eq 'latex' && length($desc) > $maxlength;
$lines{$section}{$desc} ||= {
description => &{$escape}($description),
my $inserted = $h_cust_svc->date_inserted;
my $deleted = $h_cust_svc->date_deleted;
- my $phone_inserted = $h_cust_svc->h_svc_x($inserted);
+ my $phone_inserted = $h_cust_svc->h_svc_x($inserted+5);
my $phone_deleted;
$phone_deleted = $h_cust_svc->h_svc_x($deleted) if $deleted;
}
# increment usage minutes
- my @cdrs = $phone_inserted->get_cdrs('begin'=>$start,'end'=>$end);
- foreach my $cdr ( @cdrs ) {
- $minutes += $cdr->billsec/60;
- }
+ if ( $phone_inserted ) {
+ my @cdrs = $phone_inserted->get_cdrs('begin'=>$start,'end'=>$end,'billsec_sum'=>1);
+ $minutes = $cdrs[0]->billsec_sum if scalar(@cdrs) == 1;
+ }
+ else {
+ warn "WARNING: no matching h_svc_phone insert record for insert time $inserted, svcnum " . $h_cust_svc->svcnum;
+ }
# don't look at this service again
push @seen, $h_cust_svc->svcnum;
quantity => '',
product_code => 'N/A',
section => $section,
- ext_description => [],
+ ext_description => [ $section->{'header'} ],
+ detail_temp => [],
};
$section->{'amount'} += $amount;
$accountcodes{$accountcode}{'amount'} += $amount;
$accountcodes{$accountcode}{calls}++;
$accountcodes{$accountcode}{duration} += $detail->duration;
- push @{$accountcodes{$accountcode}{ext_description}},
- $detail->formatted('format' => $format);
+ push @{$accountcodes{$accountcode}{detail_temp}}, $detail;
}
}
foreach my $l ( values %accountcodes ) {
$l->{amount} = sprintf( "%.2f", $l->{amount} );
- unshift @{$l->{ext_description}}, $section->{'header'};
+ my @sorted_detail = sort { $a->startdate <=> $b->startdate } @{$l->{detail_temp}};
+ foreach my $sorted_detail ( @sorted_detail ) {
+ push @{$l->{ext_description}}, $sorted_detail->formatted('format'=>$format);
+ }
+ delete $l->{detail_temp};
push @lines, $l;
}
my %classnums = ();
my %lines = ();
+ my $maxlength = $conf->config('cust_bill-latex_lineitem_maxlength') || 50;
+
my %usage_class = map { $_->classnum => $_ } qsearch( 'usage_class', {} );
$usage_class{''} ||= new FS::usage_class { 'classname' => '', 'weight' => 0 };
my $desc = $detail->regionname;
my $description = $desc;
- $description = substr($desc, 0, 50). '...'
- if $format eq 'latex' && length($desc) > 50;
+ $description = substr($desc, 0, $maxlength). '...'
+ if $format eq 'latex' && length($desc) > $maxlength;
$lines{$phonenum}{$desc} ||= {
description => &{$escape}($description),
my $multisection = $opt{multisection} || '';
my $discount_show_always = 0;
+ my $maxlength = $conf->config('cust_bill-latex_lineitem_maxlength') || 50;
+
my @b = ();
my ($s, $r, $u) = ( undef, undef, undef );
foreach my $cust_bill_pkg ( @$cust_bill_pkgs )
{
- warn "$me _items_cust_bill_pkg considering cust_bill_pkg $cust_bill_pkg\n"
- if $DEBUG > 1;
-
- $discount_show_always = ($cust_bill_pkg->cust_bill_pkg_discount
- && $conf->exists('discount-show-always'));
-
foreach ( $s, $r, ($opt{skip_usage} ? () : $u ) ) {
if ( $_ && !$cust_bill_pkg->hidden ) {
$_->{amount} = sprintf( "%.2f", $_->{amount} ),
$_->{amount} =~ s/^\-0\.00$/0.00/;
$_->{unit_amount} = sprintf( "%.2f", $_->{unit_amount} ),
push @b, { %$_ }
- unless ( $_->{amount} == 0 && !$discount_show_always );
+ if $_->{amount} != 0
+ || $discount_show_always
+ || ( ! $_->{_is_setup} && $_->{recur_show_zero} )
+ || ( $_->{_is_setup} && $_->{setup_show_zero} )
+ ;
$_ = undef;
}
}
+ warn "$me _items_cust_bill_pkg considering cust_bill_pkg ".
+ $cust_bill_pkg->billpkgnum. ", pkgnum ". $cust_bill_pkg->pkgnum. "\n"
+ if $DEBUG > 1;
+
foreach my $display ( grep { defined($section)
? $_->section eq $section
: 1
)
{
- warn "$me _items_cust_bill_pkg considering display item $display\n"
+ warn "$me _items_cust_bill_pkg considering cust_bill_pkg_display ".
+ $display->billpkgdisplaynum. "\n"
if $DEBUG > 1;
my $type = $display->type;
my $desc = $cust_bill_pkg->desc;
- $desc = substr($desc, 0, 50). '...'
- if $format eq 'latex' && length($desc) > 50;
+ $desc = substr($desc, 0, $maxlength). '...'
+ if $format eq 'latex' && length($desc) > $maxlength;
my %details_opt = ( 'format' => $format,
'escape_function' => $escape_function,
my $cust_pkg = $cust_bill_pkg->cust_pkg;
- if ( $cust_bill_pkg->setup != 0 && (!$type || $type eq 'S') ) {
+ if ( (!$type || $type eq 'S')
+ && ( $cust_bill_pkg->setup != 0
+ || $cust_bill_pkg->setup_show_zero
+ )
+ )
+ {
warn "$me _items_cust_bill_pkg adding setup\n"
if $DEBUG > 1;
my $description = $desc;
- $description .= ' Setup' if $cust_bill_pkg->recur != 0;
+ $description .= ' Setup'
+ if $cust_bill_pkg->recur != 0
+ || $discount_show_always
+ || $cust_bill_pkg->recur_show_zero;
my @d = ();
unless ( $cust_pkg->part_pkg->hide_svc_detail
if ( $multilocation ) {
my $loc = $cust_pkg->location_label;
- $loc = substr($loc, 0, 50). '...'
- if $format eq 'latex' && length($loc) > 50;
+ $loc = substr($loc, 0, $maxlength). '...'
+ if $format eq 'latex' && length($loc) > $maxlength;
push @d, &{$escape_function}($loc);
}
push @{ $s->{ext_description} }, @d;
} else {
$s = {
+ _is_setup => 1,
description => $description,
#pkgpart => $part_pkg->pkgpart,
pkgnum => $cust_bill_pkg->pkgnum,
amount => $cust_bill_pkg->setup,
+ setup_show_zero => $cust_bill_pkg->setup_show_zero,
unit_amount => $cust_bill_pkg->unitsetup,
quantity => $cust_bill_pkg->quantity,
ext_description => \@d,
}
- if ( ( $cust_bill_pkg->recur != 0 || $cust_bill_pkg->setup == 0 ||
- ($discount_show_always && $cust_bill_pkg->recur == 0) ) &&
- ( !$type || $type eq 'R' || $type eq 'U' )
+ if ( ( !$type || $type eq 'R' || $type eq 'U' )
+ && (
+ $cust_bill_pkg->recur != 0
+ || $cust_bill_pkg->setup == 0
+ || $discount_show_always
+ || $cust_bill_pkg->recur_show_zero
+ )
)
{
$description .= " (" . time2str($date_format, $cust_bill_pkg->sdate).
" - ". time2str($date_format, $cust_bill_pkg->edate).
")"
- unless $conf->exists('disable_line_item_date_ranges');
+ unless $conf->exists('disable_line_item_date_ranges')
+ || $cust_pkg->part_pkg->option('disable_line_item_date_ranges',1);
my @d = ();
if ( $multilocation ) {
my $loc = $cust_pkg->location_label;
- $loc = substr($loc, 0, 50). '...'
- if $format eq 'latex' && length($loc) > 50;
+ $loc = substr($loc, 0, $maxlength). '...'
+ if $format eq 'latex' && length($loc) > $maxlength;
push @d, &{$escape_function}($loc);
}
#pkgpart => $part_pkg->pkgpart,
pkgnum => $cust_bill_pkg->pkgnum,
amount => $amount,
+ recur_show_zero => $cust_bill_pkg->recur_show_zero,
unit_amount => $cust_bill_pkg->unitrecur,
quantity => $cust_bill_pkg->quantity,
ext_description => \@d,
#pkgpart => $part_pkg->pkgpart,
pkgnum => $cust_bill_pkg->pkgnum,
amount => $amount,
+ recur_show_zero => $cust_bill_pkg->recur_show_zero,
unit_amount => $cust_bill_pkg->unitrecur,
quantity => $cust_bill_pkg->quantity,
ext_description => \@d,
}
- }
+ $discount_show_always = ($cust_bill_pkg->cust_bill_pkg_discount
+ && $conf->exists('discount-show-always'));
- warn "$me _items_cust_bill_pkg done considering cust_bill_pkgs\n"
- if $DEBUG > 1;
+ }
foreach ( $s, $r, ($opt{skip_usage} ? () : $u ) ) {
if ( $_ ) {
$_->{amount} =~ s/^\-0\.00$/0.00/;
$_->{unit_amount} = sprintf( "%.2f", $_->{unit_amount} ),
push @b, { %$_ }
- unless ( $_->{amount} == 0 && !$discount_show_always );
+ if $_->{amount} != 0
+ || $discount_show_always
+ || ( ! $_->{_is_setup} && $_->{recur_show_zero} )
+ || ( $_->{_is_setup} && $_->{setup_show_zero} )
}
}
+ warn "$me _items_cust_bill_pkg done considering cust_bill_pkgs\n"
+ if $DEBUG > 1;
+
@b;
}
push @search, "cust_main.agentnum = $1";
}
+ #agentnum
+ if ( $param->{'custnum'} =~ /^(\d+)$/ ) {
+ push @search, "cust_bill.custnum = $1";
+ }
+
#_date
if ( $param->{_date} ) {
my($beginning, $ending) = @{$param->{_date}};