From fc0d0fe616e4bc5dc8137ad1af1cc7072d25f19f Mon Sep 17 00:00:00 2001 From: mark Date: Fri, 24 Dec 2010 09:56:38 +0000 Subject: [PATCH] option to credit unused time on package change, RT#10670 --- FS/FS/cust_pkg.pm | 84 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 26 deletions(-) diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index 5bb07d4ff..2ed25a06c 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -595,6 +595,12 @@ Available options are: =item nobill - can be set true to skip billing if it might otherwise be done. +=item unused_credit - can be set to 1 to credit the remaining time, or 0 to +not credit it. This must be set (by change()) when changing the package +to a different pkgpart or location, and probably shouldn't be in any other +case. If it's not set, the 'unused_credit_cancel' part_pkg option will +be used. + =back If there is an error, returns the error, otherwise returns false. @@ -645,7 +651,6 @@ sub cancel { if $error; } - my $cancel_time = $options{'time'} || time; if ( $options{'reason'} ) { @@ -662,24 +667,7 @@ sub cancel { my %svc; if ( $date ) { - # copied from below - foreach my $cust_svc ( - #schwartz - map { $_->[0] } - sort { $a->[1] <=> $b->[1] } - map { [ $_, $_->svc_x->table_info->{'cancel_weight'} ]; } - qsearch( 'cust_svc', { 'pkgnum' => $self->pkgnum } ) - ) { - - my $error = $cust_svc->cancel( ('date' => $date) ); - - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "Error expiring cust_svc: $error"; - } - } - - } else { +# copied from below foreach my $cust_svc ( #schwartz map { $_->[0] } @@ -687,7 +675,21 @@ sub cancel { map { [ $_, $_->svc_x->table_info->{'cancel_weight'} ]; } qsearch( 'cust_svc', { 'pkgnum' => $self->pkgnum } ) ) { + my $error = $cust_svc->cancel( ('date' => $date) ); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "Error expiring cust_svc: $error"; + } + } + } else { #!date + foreach my $cust_svc ( + #schwartz + map { $_->[0] } + sort { $a->[1] <=> $b->[1] } + map { [ $_, $_->svc_x->table_info->{'cancel_weight'} ]; } + qsearch( 'cust_svc', { 'pkgnum' => $self->pkgnum } ) + ) { my $error = $cust_svc->cancel; if ( $error ) { @@ -695,10 +697,28 @@ sub cancel { return "Error cancelling cust_svc: $error"; } } + } #if $date - # Add a credit for remaining service - my $remaining_value = $self->calc_remain(time=>$cancel_time); - if ( $remaining_value > 0 && !$options{'no_credit'} ) { + # Add a credit for remaining service + my $last_bill = $self->getfield('last_bill') || 0; + my $next_bill = $self->getfield('bill') || 0; + my $do_credit; + if ( exists($options{'unused_credit'}) ) { + $do_credit = $options{'unused_credit'}; + } + else { + $do_credit = $self->part_pkg->option('unused_credit_cancel', 1); + } + if ( $do_credit + and $last_bill > 0 # the package has been billed + and $next_bill > 0 # the package has a next bill date + and $next_bill >= $cancel_time # which is in the future + ) { + my $remaining_value = $self->calc_remain('time' => $cancel_time); + if ( $remaining_value > 0 ) { + # && !$options{'no_credit'} ) { + # Undocumented, unused option. + # part_pkg configuration should decide this anyway. my $error = $self->cust_main->credit( $remaining_value, 'Credit for unused time on '. $self->part_pkg->pkg, @@ -709,8 +729,8 @@ sub cancel { return "Error crediting customer \$$remaining_value for unused time on". $self->part_pkg->pkg. ": $error"; } - } - } + } #if $remaining_value + } #if $do_credit my %hash = $self->hash; $date ? ($hash{'expire'} = $date) : ($hash{'cancel'} = $cancel_time); @@ -1221,12 +1241,23 @@ sub change { $opt->{'locationnum'} = $opt->{'cust_location'}->locationnum; } + my $unused_credit = 0; if ( $opt->{'keep_dates'} ) { foreach my $date ( qw(setup bill last_bill susp adjourn cancel expire start_date contract_end ) ) { $hash{$date} = $self->getfield($date); } } + # Special case. If the pkgpart is changing, and the customer is + # going to be credited for remaining time, don't keep setup, bill, + # or last_bill dates, and DO pass the flag to cancel() to credit + # the customer. + if ( $opt->{'pkgpart'} + and $opt->{'pkgpart'} != $self->pkgpart + and $self->part_pkg->option('unused_credit_change', 1) ) { + $unused_credit = 1; + $hash{$_} = '' foreach qw(setup bill last_bill); + } # Create the new package. my $cust_pkg = new FS::cust_pkg { @@ -1285,8 +1316,9 @@ sub change { } } - #Good to go, cancel old package. - $error = $self->cancel( quiet=>1 ); + #Good to go, cancel old package. Notify 'cancel' of whether to credit + #remaining time. + $error = $self->cancel( quiet=>1, unused_credit => $unused_credit ); if ($error) { $dbh->rollback if $oldAutoCommit; return $error; -- 2.11.0