use FS::cust_main_Mixin;
use FS::cust_main;
use FS::cust_bill_pkg;
+use FS::cust_bill_pkg_display;
use FS::cust_credit;
use FS::cust_pay;
use FS::cust_pkg;
}
+=item ftp_invoice [ TEMPLATENAME ]
+
+Sends this invoice data via FTP.
+
+TEMPLATENAME is unused?
+
+=cut
+
+sub ftp_invoice {
+ my $self = shift;
+ my $template = scalar(@_) ? shift : '';
+
+ $self->send_csv(
+ 'protocol' => 'ftp',
+ 'server' => $conf->config('cust_bill-ftpserver'),
+ 'username' => $conf->config('cust_bill-ftpusername'),
+ 'password' => $conf->config('cust_bill-ftppassword'),
+ 'dir' => $conf->config('cust_bill-ftpdir'),
+ 'format' => $conf->config('cust_bill-ftpformat'),
+ );
+}
+
+=item spool_invoice [ TEMPLATENAME ]
+
+Spools this invoice data (see L<FS::spool_csv>)
+
+TEMPLATENAME is unused?
+
+=cut
+
+sub spool_invoice {
+ my $self = shift;
+ my $template = scalar(@_) ? shift : '';
+
+ $self->spool_csv(
+ 'format' => $conf->config('cust_bill-spoolformat'),
+ 'agent_spools' => $conf->exists('cust_bill-spoolagent'),
+ );
+}
+
=item send_if_newest [ TEMPLATENAME [ , AGENTNUM [ , INVOICE_FROM ] ] ]
Like B<send>, but only sends the invoice if it is the newest open invoice for
my $cust_main = $self->cust_main;
$cust_main->payname( $cust_main->first. ' '. $cust_main->getfield('last') )
- unless $cust_main->payname && $cust_main->payby !~ /^(CHEK|DCHK)$/;
-
+ unless $cust_main->payname
+ && $cust_main->payby !~ /^(CARD|DCRD|CHEK|DCHK)$/;
my %delimiters = ( 'latex' => [ '[@--', '--@]' ],
'html' => [ '<%=', '%>' ],
my %invoice_data = (
'company_name' => scalar( $conf->config('company_name') ),
'company_address' => join("\n", $conf->config('company_address') ). "\n",
- 'custnum' => $self->custnum,
+ 'custnum' => $cust_main->display_custnum,
'invnum' => $self->invnum,
'date' => time2str($date_format, $self->_date),
'today' => time2str('%b %o, %Y', $today),
'city' => &$escape_function($cust_main->city),
'state' => &$escape_function($cust_main->state),
'zip' => &$escape_function($cust_main->zip),
+ 'fax' => &$escape_function($cust_main->fax),
'returnaddress' => $returnaddress,
#'quantity' => 1,
'terms' => $self->terms,
{
if ( $cust_bill_pkg->pkgnum > 0 ) {
+ my $usage = $cust_bill_pkg->usage;
+
+ foreach my $display ($cust_bill_pkg->cust_bill_pkg_display) {
+ my $desc = $display->section;
+ my $type = $display->type;
+
+ if ( $display->post_total ) {
+ if (! $type || $type eq 'S') {
+ $l{$desc} += $cust_bill_pkg->setup
+ if ( $cust_bill_pkg->setup != 0 );
+ }
+
+ if (! $type) {
+ $l{$desc} += $cust_bill_pkg->recur
+ if ( $cust_bill_pkg->recur != 0 );
+ }
+
+ if ($type && $type eq 'R') {
+ $l{$desc} += $cust_bill_pkg->recur - $usage
+ if ( $cust_bill_pkg->recur != 0 );
+ }
+
+ if ($type && $type eq 'U') {
+ $l{$desc} += $usage;
+ }
+
+ } else {
+ if (! $type || $type eq 'S') {
+ $s{$desc} += $cust_bill_pkg->setup
+ if ( $cust_bill_pkg->setup != 0 );
+ }
+
+ if (! $type) {
+ $s{$desc} += $cust_bill_pkg->recur
+ if ( $cust_bill_pkg->recur != 0 );
+ }
+
+ if ($type && $type eq 'R') {
+ $s{$desc} += $cust_bill_pkg->recur - $usage
+ if ( $cust_bill_pkg->recur != 0 );
+ }
+
+ if ($type && $type eq 'U') {
+ $s{$desc} += $usage;
+ }
- my $desc = $cust_bill_pkg->section;
- my $dup_desc = $cust_bill_pkg->duplicate_section;
-
- if ($cust_bill_pkg->duplicate) {
- $s{$dup_desc} += $cust_bill_pkg->setup
- if ( $cust_bill_pkg->setup != 0 );
-
- $s{$dup_desc} += $cust_bill_pkg->recur
- if ( $cust_bill_pkg->recur != 0 );
- }
-
- if ( $cust_bill_pkg->post_total ) {
- $l{$desc} += $cust_bill_pkg->setup
- if ( $cust_bill_pkg->setup != 0 );
-
- $l{$desc} += $cust_bill_pkg->recur
- if ( $cust_bill_pkg->recur != 0 );
-
- } else {
- $s{$desc} += $cust_bill_pkg->setup
- if ( $cust_bill_pkg->setup != 0 );
+ }
- $s{$desc} += $cust_bill_pkg->recur
- if ( $cust_bill_pkg->recur != 0 );
}
}
my %options = @_;
my $section = $options{'section'};
my $desc = $section->{'description'};
- my @cust_bill_pkg =
- grep { $_->pkgnum &&
- ( defined($section)
- ? ( $_->section eq $desc || $_->duplicate_section eq $desc )
- : 1
- )
- } $self->cust_bill_pkg;
+ my @cust_bill_pkg = grep { $_->pkgnum } $self->cust_bill_pkg;
$self->_items_cust_bill_pkg(\@cust_bill_pkg, %options);
}
my $escape_function = $opt{escape_function} || sub { shift };
my $format_function = $opt{format_function} || '';
my $unsquelched = $opt{unsquelched} || '';
+ my $section = $opt{section}->{description} if $opt{section};
my @b = ();
- my $last_pkgnum = '';
foreach my $cust_bill_pkg ( @$cust_bill_pkg )
{
+ foreach my $display ( grep { defined($section)
+ ? $_->section eq $section
+ : 1
+ }
+ $cust_bill_pkg->cust_bill_pkg_display
+ )
+ {
- my $cust_pkg = $cust_bill_pkg->cust_pkg;
-
- my $desc = $cust_bill_pkg->desc;
-
- my %details_opt = ( 'format' => $format,
- 'escape_function' => $escape_function,
- 'format_function' => $format_function,
- );
-
- if ( $cust_bill_pkg->pkgnum > 0 ) {
+ my $type = $display->type;
- if ( $cust_bill_pkg->setup != 0 ) {
+ my $cust_pkg = $cust_bill_pkg->cust_pkg;
- my $description = $desc;
- $description .= ' Setup' if $cust_bill_pkg->recur != 0;
+ my $desc = $cust_bill_pkg->desc;
- my @d = map &{$escape_function}($_),
- $cust_pkg->h_labels_short($self->_date);
- push @d, $cust_bill_pkg->details(%details_opt)
- if $cust_bill_pkg->recur == 0;
+ my %details_opt = ( 'format' => $format,
+ 'escape_function' => $escape_function,
+ 'format_function' => $format_function,
+ );
- push @b, {
- description => $description,
- #pkgpart => $part_pkg->pkgpart,
- pkgnum => $cust_bill_pkg->pkgnum,
- amount => sprintf("%.2f", $cust_bill_pkg->setup),
- unit_amount => sprintf("%.2f", $cust_bill_pkg->unitsetup),
- quantity => $cust_bill_pkg->quantity,
- ext_description => \@d,
- };
+ if ( $cust_bill_pkg->pkgnum > 0 ) {
- $last_pkgnum = '';
+ if ( $cust_bill_pkg->setup != 0 && (!$type || $type eq 'S') ) {
- }
+ my $description = $desc;
+ $description .= ' Setup' if $cust_bill_pkg->recur != 0;
- if ( $cust_bill_pkg->recur != 0 ) {
+ my @d = map &{$escape_function}($_),
+ $cust_pkg->h_labels_short($self->_date);
+ push @d, $cust_bill_pkg->details(%details_opt)
+ if $cust_bill_pkg->recur == 0;
- my $is_summary =
- ( $cust_bill_pkg->duplicate &&
- $opt{section}->{description} ne $cust_bill_pkg->section
- );
- my $description = $is_summary ? "Usage charges" : $desc;
+ push @b, {
+ description => $description,
+ #pkgpart => $part_pkg->pkgpart,
+ pkgnum => $cust_bill_pkg->pkgnum,
+ amount => sprintf("%.2f", $cust_bill_pkg->setup),
+ unit_amount => sprintf("%.2f", $cust_bill_pkg->unitsetup),
+ quantity => $cust_bill_pkg->quantity,
+ ext_description => \@d,
+ };
- unless ( $conf->exists('disable_line_item_date_ranges') ) {
- $description .= " (" . time2str("%x", $cust_bill_pkg->sdate).
- " - ". time2str("%x", $cust_bill_pkg->edate). ")";
}
- #at least until cust_bill_pkg has "past" ranges in addition to
- #the "future" sdate/edate ones... see #3032
- my @d = ();
- push @d, map &{$escape_function}($_),
- $cust_pkg->h_labels_short($self->_date)
- #$cust_bill_pkg->edate,
- #$cust_bill_pkg->sdate),
- unless ($cust_bill_pkg->pkgnum eq $last_pkgnum);
-
- @d = () if ($cust_bill_pkg->itemdesc || $is_summary);
- push @d, $cust_bill_pkg->details(%details_opt)
- unless $is_summary;
-
- if ($cust_bill_pkg->pkgnum eq $last_pkgnum) {
-
- $b[$#b]->{amount} =
- sprintf("%.2f", $b[$#b]->{amount} + $cust_bill_pkg->recur);
- push @{$b[$#b]->{ext_description}}, @d;
-
- }else{
-
+ if ( $cust_bill_pkg->recur != 0 &&
+ ( !$type || $type eq 'R' || $type eq 'U' )
+ )
+ {
+
+ my $is_summary = $display->summary;
+ my $description = $is_summary ? "Usage charges" : $desc;
+
+ unless ( $conf->exists('disable_line_item_date_ranges') ) {
+ $description .= " (" . time2str("%x", $cust_bill_pkg->sdate).
+ " - ". time2str("%x", $cust_bill_pkg->edate). ")";
+ }
+
+ #at least until cust_bill_pkg has "past" ranges in addition to
+ #the "future" sdate/edate ones... see #3032
+ my @d = ();
+ push @d, map &{$escape_function}($_),
+ $cust_pkg->h_labels_short($self->_date)
+ #$cust_bill_pkg->edate,
+ #$cust_bill_pkg->sdate),
+ ;
+
+ @d = () if ($cust_bill_pkg->itemdesc || $is_summary);
+ push @d, $cust_bill_pkg->details(%details_opt)
+ unless ($is_summary || $type && $type eq 'R');
+
+ my $amount = 0;
+ if (!$type) {
+ $amount = $cust_bill_pkg->recur;
+ }elsif($type eq 'R') {
+ $amount = $cust_bill_pkg->recur - $cust_bill_pkg->usage;
+ }elsif($type eq 'U') {
+ $amount = $cust_bill_pkg->usage;
+ }
+
push @b, {
description => $description,
#pkgpart => $part_pkg->pkgpart,
pkgnum => $cust_bill_pkg->pkgnum,
- amount => sprintf("%.2f", $cust_bill_pkg->recur),
+ amount => sprintf("%.2f", $amount),
unit_amount => sprintf("%.2f", $cust_bill_pkg->unitrecur),
quantity => $cust_bill_pkg->quantity,
ext_description => \@d,
- };
+ } unless ( $type eq 'U' && ! $amount );
}
- if ($conf->exists('separate_usage') && $cust_bill_pkg->type ne 'U') {
- $last_pkgnum = '';
- }else{
- $last_pkgnum = $cust_bill_pkg->pkgnum;
- }
- }
+ } else { #pkgnum tax or one-shot line item (??)
- } else { #pkgnum tax or one-shot line item (??)
+ if ( $cust_bill_pkg->setup != 0 ) {
+ push @b, {
+ 'description' => $desc,
+ 'amount' => sprintf("%.2f", $cust_bill_pkg->setup),
+ };
+ }
+ if ( $cust_bill_pkg->recur != 0 ) {
+ push @b, {
+ 'description' => "$desc (".
+ time2str("%x", $cust_bill_pkg->sdate). ' - '.
+ time2str("%x", $cust_bill_pkg->edate). ')',
+ 'amount' => sprintf("%.2f", $cust_bill_pkg->recur),
+ };
+ }
- if ( $cust_bill_pkg->setup != 0 ) {
- push @b, {
- 'description' => $desc,
- 'amount' => sprintf("%.2f", $cust_bill_pkg->setup),
- };
- }
- if ( $cust_bill_pkg->recur != 0 ) {
- push @b, {
- 'description' => "$desc (".
- time2str("%x", $cust_bill_pkg->sdate). ' - '.
- time2str("%x", $cust_bill_pkg->edate). ')',
- 'amount' => sprintf("%.2f", $cust_bill_pkg->recur),
- };
}
- $last_pkgnum = '';
-
}
}
=over 4
-=item reprint
+=item process_reprint
=cut
process_re_X('print', @_);
}
-=item reemail
+=item process_reemail
=cut
process_re_X('email', @_);
}
-=item refax
+=item process_refax
=cut
process_re_X('fax', @_);
}
+=item process_reftp
+
+=cut
+
+sub process_reftp {
+ process_re_X('ftp', @_);
+}
+
+=item respool
+
+=cut
+
+sub process_respool {
+ process_re_X('spool', @_);
+}
+
use Storable qw(thaw);
use Data::Dumper;
use MIME::Base64;
'debug' => 1,
} );
+ $method .= '_invoice' unless $method eq 'email' || $method eq 'print';
+
warn " $me re_X $method: ". scalar(@cust_bill). " invoices found\n"
if $DEBUG;