X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_pkg.pm;h=56e4c90d78661e6f6a10e7a71aa0eda386ecdc03;hb=8c84e8692d48eff3b03822dcd18c1766fd0b9bca;hp=5e070e38d163b1b493ef55af5b75ab2cd680934c;hpb=908a4522939c0225ef4e7ba4236dab2eebe9daca;p=freeside.git diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index 5e070e38d..56e4c90d7 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -947,7 +947,7 @@ sub cancel { } else { $error = send_email( - 'from' => $conf->config('invoice_from', $self->cust_main->agentnum), + 'from' => $conf->invoice_from_full( $self->cust_main->agentnum ), 'to' => \@invoicing_list, 'subject' => ( $conf->config('cancelsubject') || 'Cancellation Notice' ), 'body' => [ map "$_\n", $conf->config('cancelmessage') ], @@ -1424,6 +1424,21 @@ are mandatory. =cut +# Implementation note: +# +# If you pkgpart-change a package that has been billed, and it's set to give +# credit on package change, then this method gets called and then the new +# package will have no last_bill date. Therefore the customer will be credited +# only once (per billing period) even if there are multiple package changes. +# +# If you location-change a package that has been billed, this method will NOT +# be called and the new package WILL have the last bill date of the old +# package. +# +# If the new package is then canceled within the same billing cycle, +# credit_remaining needs to run calc_remain on the OLD package to determine +# the amount of unused time to credit. + sub credit_remaining { # Add a credit for remaining service my ($self, $mode, $time) = @_; @@ -1441,10 +1456,29 @@ sub credit_remaining { and $next_bill >= $time # which is in the future ) { my @cust_credit_source_bill_pkg = (); - my $remaining_value = $self->calc_remain( + my $remaining_value = 0; + + my $remain_pkg = $self; + $remaining_value = $remain_pkg->calc_remain( 'time' => $time, 'cust_credit_source_bill_pkg' => \@cust_credit_source_bill_pkg, ); + + # we may have to walk back past some package changes to get to the + # one that actually has unused time + while ( $remaining_value == 0 ) { + if ( $remain_pkg->change_pkgnum ) { + $remain_pkg = FS::cust_pkg->by_key($remain_pkg->change_pkgnum); + } else { + # the package has really never been billed + return; + } + $remaining_value = $remain_pkg->calc_remain( + 'time' => $time, + 'cust_credit_source_bill_pkg' => \@cust_credit_source_bill_pkg, + ); + } + if ( $remaining_value > 0 ) { warn "Crediting for $remaining_value on package ".$self->pkgnum."\n" if $DEBUG; @@ -1583,19 +1617,41 @@ sub unsuspend { my $conf = new FS::Conf; #adjust the next bill date forward - $hash{'bill'} = ( $hash{'bill'} || $hash{'setup'} ) + $inactive - if $inactive > 0 + # increment next bill date if certain conditions are met: + # - it was due to be billed at some point + # - either the global or local config says to do this + my $adjust_bill = 0; + if ( + $inactive > 0 && ( $hash{'bill'} || $hash{'setup'} ) && ( $opt{'adjust_next_bill'} || $conf->exists('unsuspend-always_adjust_next_bill_date') || $self->part_pkg->option('unsuspend_adjust_bill', 1) ) - && ! $self->option('suspend_bill',1) - && ( ! $self->part_pkg->option('suspend_bill',1) - || $self->option('no_suspend_bill',1) - ) - && $hash{'order_date'} != $hash{'susp'} - ; + ) { + $adjust_bill = 1; + } + + # but not if: + # - the package billed during suspension + # - or it was ordered on hold + # - or the customer was credited for the unused time + + if ( $self->option('suspend_bill',1) + or ( $self->part_pkg->option('suspend_bill',1) + and ! $self->option('no_suspend_bill',1) + ) + or $hash{'order_date'} == $hash{'susp'} + or $self->part_pkg->option('unused_credit_suspend') + or ( ref($reason) and $reason->unused_credit ) + ) { + $adjust_bill = 0; + } + + # then add the length of time suspended to the bill date + if ( $adjust_bill ) { + $hash{'bill'} = ( $hash{'bill'} || $hash{'setup'} ) + $inactive + } $hash{'susp'} = ''; $hash{'adjourn'} = '' if $hash{'adjourn'} and $hash{'adjourn'} < time; @@ -2400,6 +2456,13 @@ sub modify_charge { } # else simply ignore them; the UI shouldn't allow editing the fields + + if ( exists($opt{'taxclass'}) + and $part_pkg->taxclass ne $opt{'taxclass'}) { + + $part_pkg->set('taxclass', $opt{'taxclass'}); + } + my $error; if ( $part_pkg->modified or $pkg_opt_modified ) { # can we safely modify the package def?