#create the new invoice
my $cust_bill = new FS::cust_bill ( {
'custnum' => $self->custnum,
- '_date' => ( $invoice_time ),
+ '_date' => $invoice_time,
'charged' => $charged,
'billing_balance' => $balance,
'previous_balance' => $previous_balance,
#discard bundled packages of 0 value
sub _omit_zero_value_bundles {
+ my @in = @_;
my @cust_bill_pkg = ();
my @cust_bill_pkg_bundle = ();
my $sum = 0;
+ my $discount_show_always = 0;
+
+ foreach my $cust_bill_pkg ( @in ) {
+
+ $discount_show_always = ($cust_bill_pkg->get('discounts')
+ && scalar(@{$cust_bill_pkg->get('discounts')})
+ && $conf->exists('discount-show-always'));
+
+ warn " pkgnum ". $cust_bill_pkg->pkgnum.
+ " sum $sum, recur_show_zero ". $cust_bill_pkg->recur_show_zero. "\n"
+ if $DEBUG > 0;
- foreach my $cust_bill_pkg ( @_ ) {
if (scalar(@cust_bill_pkg_bundle) && !$cust_bill_pkg->pkgpart_override) {
- push @cust_bill_pkg, @cust_bill_pkg_bundle if $sum > 0;
+ push @cust_bill_pkg, @cust_bill_pkg_bundle
+ if $sum > 0
+ || ($sum == 0 && ( $discount_show_always
+ || grep $_->recur_show_zero, @cust_bill_pkg_bundle )
+ );
@cust_bill_pkg_bundle = ();
$sum = 0;
}
+
$sum += $cust_bill_pkg->setup + $cust_bill_pkg->recur;
push @cust_bill_pkg_bundle, $cust_bill_pkg;
+
}
- push @cust_bill_pkg, @cust_bill_pkg_bundle if $sum > 0;
+
+ push @cust_bill_pkg, @cust_bill_pkg_bundle
+ if $sum > 0
+ || ($sum == 0 && ( $discount_show_always
+ || grep $_->recur_show_zero, @cust_bill_pkg_bundle )
+ );
+
+ warn " _omit_zero_value_bundles: ". scalar(@in).
+ '->'. scalar(@cust_bill_pkg). "\n" #. Dumper(@cust_bill_pkg). "\n"
+ if $DEBUG > 2;
(@cust_bill_pkg);
foreach my $tax ( keys %$taxlisthash ) {
foreach ( @{ $taxlisthash->{$tax} }[1 ... scalar(@{ $taxlisthash->{$tax} })] ) {
next unless ref($_) eq 'FS::cust_bill_pkg';
- push @{ $packagemap{$_->pkgnum}->_cust_tax_exempt_pkg },
- splice( @{ $_->_cust_tax_exempt_pkg } );
+
+ my @cust_tax_exempt_pkg = splice( @{ $_->_cust_tax_exempt_pkg } );
+
+ next unless @cust_tax_exempt_pkg; #just avoiding the prob when irrelevant?
+ die "can't distribute tax exemptions: no line item for ". Dumper($_).
+ " in packagemap ". join(',', sort {$a<=>$b} keys %packagemap). "\n"
+ unless $packagemap{$_->pkgnum};
+
+ push @{ $packagemap{$_->pkgnum}->_cust_tax_exempt_pkg },
+ @cust_tax_exempt_pkg;
}
}
my $setup = 0;
my $unitsetup = 0;
- if ( $options{'resetup'}
- || ( ! $cust_pkg->setup
- && ( ! $cust_pkg->start_date
- || $cust_pkg->start_date <= $time
- )
- && ( ! $conf->exists('disable_setup_suspended_pkgs')
- || ( $conf->exists('disable_setup_suspended_pkgs') &&
- ! $cust_pkg->getfield('susp')
- )
- )
- )
- and !$options{recurring_only}
- )
+ my %setup_param = ();
+ if ( ! $options{recurring_only}
+ and ! $options{cancel}
+ and ( $options{'resetup'}
+ || ( ! $cust_pkg->setup
+ && ( ! $cust_pkg->start_date
+ || $cust_pkg->start_date <= $time
+ )
+ && ( ! $conf->exists('disable_setup_suspended_pkgs')
+ || ( $conf->exists('disable_setup_suspended_pkgs') &&
+ ! $cust_pkg->getfield('susp')
+ )
+ )
+ )
+ )
+ )
{
warn " bill setup\n" if $DEBUG > 1;
- $lineitems++;
- $setup = eval { $cust_pkg->calc_setup( $time, \@details ) };
- return "$@ running calc_setup for $cust_pkg\n"
- if $@;
+ unless ( $cust_pkg->waive_setup ) {
+ $lineitems++;
+
+ $setup = eval { $cust_pkg->calc_setup( $time, \@details, \%setup_param ) };
+ return "$@ running calc_setup for $cust_pkg\n"
+ if $@;
- $unitsetup = $cust_pkg->part_pkg->unit_setup || $setup; #XXX uuh
+ $unitsetup = $cust_pkg->part_pkg->unit_setup || $setup; #XXX uuh
+ }
$cust_pkg->setfield('setup', $time)
unless $cust_pkg->setup;
my $unitrecur = 0;
my $sdate;
if ( ! $cust_pkg->start_date
- and ( ! $cust_pkg->susp || $part_pkg->option('suspend_bill') )
+ and ( ! $cust_pkg->susp || $part_pkg->option('suspend_bill', 1) )
and
( $part_pkg->freq ne '0' && ( $cust_pkg->bill || 0 ) <= $time )
|| ( $part_pkg->plan eq 'voip_cdr'
'discounts' => \@discounts,
'real_pkgpart' => $real_pkgpart,
'freq_override' => $options{freq_override} || '',
+ %setup_param,
);
my $method = $options{cancel} ? 'calc_cancel' : 'calc_recur';
}
+ if ( defined $param{'discount_left_setup'} ) {
+ foreach my $discount_setup ( values %{$param{'discount_left_setup'}} ) {
+ $setup -= $discount_setup;
+ }
+ }
+
}
warn "\$setup is undefined" unless defined($setup);
if $DEBUG >1;
my $error = $cust_pkg->replace( $old_cust_pkg,
+ 'depend_jobnum'=>$options{depend_jobnum},
'options' => { $cust_pkg->options },
)
unless $options{no_commit};
return "negative recur $recur for pkgnum ". $cust_pkg->pkgnum;
}
- if ( $setup != 0 ||
- $recur != 0 ||
- !$part_pkg->hidden && $options{has_hidden} ) #include some $0 lines
+ my $discount_show_always = ($recur == 0 && scalar(@discounts)
+ && $conf->exists('discount-show-always'));
+
+ if ( $setup != 0
+ || $recur != 0
+ || (!$part_pkg->hidden && $options{has_hidden}) #include some $0 lines
+ || $discount_show_always
+ || ($recur == 0 && $part_pkg->recur_show_zero)
+ )
{
warn " charges (setup=$setup, recur=$recur); adding line items\n"
# handle taxes
###
+ unless ( $discount_show_always ) {
my $error =
$self->_handle_taxes($part_pkg, $taxlisthash, $cust_bill_pkg, $cust_pkg, $options{invoice_time}, $real_pkgpart, \%options);
return $error if $error;
+ }
push @$cust_bill_pkgs, $cust_bill_pkg;
my $amount = min( $payment->unapplied, $owed );
- my $cust_bill_pay = new FS::cust_bill_pay ( {
+ my $cbp = {
'paynum' => $payment->paynum,
'invnum' => $cust_bill->invnum,
'amount' => $amount,
- } );
+ };
+ $cbp->{_date} = $payment->_date
+ if $options{'manual'} && $options{'backdate_application'};
+ my $cust_bill_pay = new FS::cust_bill_pay($cbp);
$cust_bill_pay->pkgnum( $payment->pkgnum )
if $conf->exists('pkg-balances') && $payment->pkgnum;
my $error = $cust_bill_pay->insert(%options);