X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=FS%2FFS%2Fcust_main%2FBilling.pm;h=08b10c1ffe2601c1a8803120de59acd98b86769e;hp=4821ce5555533760e41a16ac29e803a910b9044c;hb=2cdb0b3f9e3b778fd914d847fc7851948a9930e4;hpb=a2ecb1cf6a6c084c521710f1256da082f70ba9e5 diff --git a/FS/FS/cust_main/Billing.pm b/FS/FS/cust_main/Billing.pm index 4821ce555..08b10c1ff 100644 --- a/FS/FS/cust_main/Billing.pm +++ b/FS/FS/cust_main/Billing.pm @@ -57,7 +57,7 @@ Cancels and suspends any packages due, generates bills, applies payments and credits, and applies collection events to run cards, send bills and notices, etc. -By default, warns on errors and continues with the next operation (but see the +Any errors prevent subsequent operations from continuing and die (but see the "fatal" flag below). Options are passed as name-value pairs. Currently available options are: @@ -131,8 +131,7 @@ sub bill_and_collect { if ( $error ) { $error = "Error expiring custnum ". $self->custnum. ": $error"; if ( $options{fatal} && $options{fatal} eq 'return' ) { return $error; } - elsif ( $options{fatal} ) { die $error; } - else { warn $error; } + else { die $error; } } $log->debug('suspending adjourned packages', %logopt); @@ -140,8 +139,7 @@ sub bill_and_collect { if ( $error ) { $error = "Error adjourning custnum ". $self->custnum. ": $error"; if ( $options{fatal} && $options{fatal} eq 'return' ) { return $error; } - elsif ( $options{fatal} ) { die $error; } - else { warn $error; } + else { die $error; } } $log->debug('unsuspending resumed packages', %logopt); @@ -149,8 +147,7 @@ sub bill_and_collect { if ( $error ) { $error = "Error resuming custnum ".$self->custnum. ": $error"; if ( $options{fatal} && $options{fatal} eq 'return' ) { return $error; } - elsif ( $options{fatal} ) { die $error; } - else { warn $error; } + else { die $error; } } $job->update_statustext('20,billing packages') if $job; @@ -159,8 +156,7 @@ sub bill_and_collect { if ( $error ) { $error = "Error billing custnum ". $self->custnum. ": $error"; if ( $options{fatal} && $options{fatal} eq 'return' ) { return $error; } - elsif ( $options{fatal} ) { die $error; } - else { warn $error; } + else { die $error; } } $job->update_statustext('50,applying payments and credits') if $job; @@ -169,8 +165,7 @@ sub bill_and_collect { if ( $error ) { $error = "Error applying custnum ". $self->custnum. ": $error"; if ( $options{fatal} && $options{fatal} eq 'return' ) { return $error; } - elsif ( $options{fatal} ) { die $error; } - else { warn $error; } + else { die $error; } } # In a batch tax environment, do not run collection if any pending @@ -195,8 +190,7 @@ sub bill_and_collect { if ( $error ) { $error = "Error collecting custnum ". $self->custnum. ": $error"; if ($options{fatal} && $options{fatal} eq 'return') { return $error; } - elsif ($options{fatal} ) { die $error; } - else { warn $error; } + else { die $error; } } } @@ -216,12 +210,11 @@ sub cancel_expired_pkgs { my @errors = (); - my @really_cancel_pkgs; - my @cancel_reasons; + my @really_cancel_pkgs = (); + my @cancel_reasons = (); CUST_PKG: foreach my $cust_pkg ( @cancel_pkgs ) { my $cpr = $cust_pkg->last_cust_pkg_reason('expire'); - my $error; if ( $cust_pkg->change_to_pkgnum ) { @@ -231,9 +224,10 @@ sub cancel_expired_pkgs { $cust_pkg->change_to_pkgnum.'; not expiring'; next CUST_PKG; } - $error = $cust_pkg->change( 'cust_pkg' => $new_pkg, - 'unprotect_svcs' => 1 ); - $error = '' if ref $error eq 'FS::cust_pkg'; + my $error = $cust_pkg->change( 'cust_pkg' => $new_pkg, + 'unprotect_svcs' => 1, + ); + push @errors, $error if $error && ref($error) ne 'FS::cust_pkg'; } else { # just cancel it @@ -544,14 +538,19 @@ sub bill { foreach my $part_pkg ( @part_pkg ) { - $cust_pkg->set($_, $hash{$_}) foreach qw ( setup last_bill bill ); + my $this_cust_pkg = $cust_pkg; + # for add-on packages, copy the object to avoid leaking changes back to + # the caller if pkg_list is in use; see RT#73607 + if ( $part_pkg->get('pkgpart') != $real_pkgpart ) { + $this_cust_pkg = FS::cust_pkg->new({ %hash }); + } my $pass = ''; - if ( $cust_pkg->separate_bill ) { + if ( $this_cust_pkg->separate_bill ) { # if no_auto is also set, that's fine. we just need to not have # invoices that are both auto and no_auto, and since the package # gets an invoice all to itself, it will only be one or the other. - $pass = $cust_pkg->pkgnum; + $pass = $this_cust_pkg->pkgnum; if (!exists $cust_bill_pkg{$pass}) { # it may not exist yet push @passes, $pass; $total_setup{$pass} = do { my $z = 0; \$z }; @@ -565,17 +564,17 @@ sub bill { ); $cust_bill_pkg{$pass} = []; } - } elsif ( ($cust_pkg->no_auto || $part_pkg->no_auto) ) { + } elsif ( ($this_cust_pkg->no_auto || $part_pkg->no_auto) ) { $pass = 'no_auto'; } - my $next_bill = $cust_pkg->getfield('bill') || 0; + my $next_bill = $this_cust_pkg->getfield('bill') || 0; my $error; # let this run once if this is the last bill upon cancellation while ( $next_bill <= $cmp_time or $options{cancel} ) { $error = $self->_make_lines( 'part_pkg' => $part_pkg, - 'cust_pkg' => $cust_pkg, + 'cust_pkg' => $this_cust_pkg, 'precommit_hooks' => \@precommit_hooks, 'line_items' => $cust_bill_pkg{$pass}, 'setup' => $total_setup{$pass}, @@ -590,12 +589,12 @@ sub bill { last if $error; # or if we're not incrementing the bill date. - last if ($cust_pkg->getfield('bill') || 0) == $next_bill; + last if ($this_cust_pkg->getfield('bill') || 0) == $next_bill; # or if we're letting it run only once last if $options{cancel}; - $next_bill = $cust_pkg->getfield('bill') || 0; + $next_bill = $this_cust_pkg->getfield('bill') || 0; #stop if -o was passed to freeside-daily last if $options{'one_recur'};