diff options
author | mark <mark> | 2012-01-28 23:20:11 +0000 |
---|---|---|
committer | mark <mark> | 2012-01-28 23:20:11 +0000 |
commit | 781f0ffcf560d3df0aec7ae349b57463d1c2518a (patch) | |
tree | 1c1c872d11d69b54370325786b2b2e72e2f009d8 /FS | |
parent | 45ecb21934e80c6f1dcc6e26284398995a04a8e6 (diff) |
future package unsuspend date, #14144
Diffstat (limited to 'FS')
-rw-r--r-- | FS/FS/Cron/bill.pm | 3 | ||||
-rw-r--r-- | FS/FS/Schema.pm | 1 | ||||
-rw-r--r-- | FS/FS/cust_main/Billing.pm | 31 | ||||
-rw-r--r-- | FS/FS/cust_pkg.pm | 68 |
4 files changed, 92 insertions, 11 deletions
diff --git a/FS/FS/Cron/bill.pm b/FS/FS/Cron/bill.pm index 64979baec..8d1223b80 100644 --- a/FS/FS/Cron/bill.pm +++ b/FS/FS/Cron/bill.pm @@ -146,7 +146,7 @@ sub bill { # (or now, if no -d switch was given). # # -n: When used with "-d" and/or "-y", specifies that invoices should be dated -# with today's date, irregardless of the pretend date used to pre-generate +# with today's date, regardless of the pretend date used to pre-generate # the invoices. # # -p: Only process customers with the specified payby (I<CARD>, I<DCRD>, I<CHEK>, I<DCHK>, I<BILL>, I<COMP>, I<LECB>) @@ -211,6 +211,7 @@ sub bill_where { OR bill IS NULL OR bill <= $billtime OR ( expire IS NOT NULL AND expire <= $^T ) OR ( adjourn IS NOT NULL AND adjourn <= $^T ) + OR ( resume IS NOT NULL AND resume <= $^T ) ) ) END diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 6727420ca..9de1b7f3f 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -1481,6 +1481,7 @@ sub tables_hashref { 'last_bill', @date_type, '', '', 'susp', @date_type, '', '', 'adjourn', @date_type, '', '', + 'resume', @date_type, '', '', 'cancel', @date_type, '', '', 'expire', @date_type, '', '', 'contract_end', @date_type, '', '', diff --git a/FS/FS/cust_main/Billing.pm b/FS/FS/cust_main/Billing.pm index 23d3b4933..ed7b0fa77 100644 --- a/FS/FS/cust_main/Billing.pm +++ b/FS/FS/cust_main/Billing.pm @@ -129,6 +129,14 @@ sub bill_and_collect { else { warn $error; } } + $error = $self->unsuspend_resumed_pkgs( day_end( $options{actual_time} ) ); + 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; } + } + $job->update_statustext('20,billing packages') if $job; $error = $self->bill( %options ); if ( $error ) { @@ -185,7 +193,7 @@ sub cancel_expired_pkgs { push @errors, 'pkgnum '.$cust_pkg->pkgnum.": $error" if $error; } - scalar(@errors) ? join(' / ', @errors) : ''; + join(' / ', @errors); } @@ -227,7 +235,25 @@ sub suspend_adjourned_pkgs { push @errors, 'pkgnum '.$cust_pkg->pkgnum.": $error" if $error; } - scalar(@errors) ? join(' / ', @errors) : ''; + join(' / ', @errors); + +} + +sub unsuspend_resumed_pkgs { + my ( $self, $time, %options ) = @_; + + my @unsusp_pkgs = $self->ncancelled_pkgs( { + 'extra_sql' => " AND resume IS NOT NULL AND resume > 0 AND resume <= $time " + } ); + + my @errors = (); + + foreach my $cust_pkg ( @unsusp_pkgs ) { + my $error = $cust_pkg->unsuspend( 'time' => $time ); + push @errors, 'pkgnum '.$cust_pkg->pkgnum.": $error" if $error; + } + + join(' / ', @errors); } @@ -2168,6 +2194,7 @@ sub apply_payments { cancel_expired_pkgs suspend_adjourned_pkgs + unsuspend_resumed_pkgs bill (do_cust_event pre-bill) diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index 469bd94ab..855accc0c 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -605,6 +605,7 @@ sub check { || $self->ut_numbern('susp') || $self->ut_numbern('cancel') || $self->ut_numbern('adjourn') + || $self->ut_numbern('resume') || $self->ut_numbern('expire') || $self->ut_numbern('dundate') || $self->ut_enum('no_auto', [ '', 'Y' ]) @@ -618,6 +619,9 @@ sub check { return "A package with both start date (future start) and setup date (already started) will never bill" if $self->start_date && $self->setup; + return "A future unsuspend date can only be set for a package with a suspend date" + if $self->resume and !$self->susp and !$self->adjourn; + $self->usernum($FS::CurrentUser::CurrentUser->usernum) unless $self->usernum; if ( $self->dbdef_table->column('manual_flag') ) { @@ -936,9 +940,21 @@ Available options are: =over 4 -=item reason - can be set to a cancellation reason (see L<FS:reason>), either a reasonnum of an existing reason, or passing a hashref will create a new reason. The hashref should have the following keys: typenum - Reason type (see L<FS::reason_type>, reason - Text of the new reason. +=item reason - can be set to a cancellation reason (see L<FS:reason>), +either a reasonnum of an existing reason, or passing a hashref will create +a new reason. The hashref should have the following keys: +- typenum - Reason type (see L<FS::reason_type> +- reason - Text of the new reason. + +=item date - can be set to a unix style timestamp to specify when to +suspend (adjourn) + +=item time - can be set to override the current time, for calculation +of final invoices or unused-time credits -=item date - can be set to a unix style timestamp to specify when to suspend (adjourn) +=item resume_date - can be set to a time when the package should be +unsuspended. This may be more convenient than calling C<unsuspend()> +separately. =back @@ -976,7 +992,7 @@ sub suspend { my $suspend_time = $options{'time'} || time; my $date = $options{date} if $options{date}; # adjourn/suspend later - $date = '' if ($date && $date <= time); # complain instead? + $date = '' if ($date && $date <= $suspend_time); # complain instead? if ( $date && $old->get('expire') && $old->get('expire') < $date ) { dbh->rollback if $oldAutoCommit; @@ -1019,6 +1035,12 @@ sub suspend { } else { $hash{'susp'} = $suspend_time; } + + my $resume_date = $options{'resume_date'} || 0; + if ( $resume_date > ($date || $suspend_time) ) { + $hash{'resume'} = $resume_date; + } + my $new = new FS::cust_pkg ( \%hash ); $error = $new->replace( $self, options => { $self->options } ); if ( $error ) { @@ -1098,7 +1120,7 @@ sub suspend { Generate a credit for this package for the time remaining in the current billing period. MODE is either "suspend" or "cancel" (determines the -credit type). TIME is the time of suspension/cancellation. Both options +credit type). TIME is the time of suspension/cancellation. Both arguments are mandatory. =cut @@ -1146,6 +1168,11 @@ Available options are: =over 4 +=item date + +Can be set to a date to unsuspend the package in the future (the 'resume' +field). + =item adjust_next_bill Can be set true to adjust the next bill date forward by @@ -1180,15 +1207,38 @@ sub unsuspend { my $pkgnum = $old->pkgnum; if ( $old->get('cancel') || $self->get('cancel') ) { - dbh->rollback if $oldAutoCommit; + $dbh->rollback if $oldAutoCommit; return "Can't unsuspend cancelled package $pkgnum"; } unless ( $old->get('susp') && $self->get('susp') ) { - dbh->rollback if $oldAutoCommit; + $dbh->rollback if $oldAutoCommit; return ""; # no error # complain instead? } + my $date = $opt{'date'}; + if ( $date and $date > time ) { # return an error if $date <= time? + + if ( $old->get('expire') && $old->get('expire') < $date ) { + $dbh->rollback if $oldAutoCommit; + return "Package $pkgnum expires before it would be unsuspended."; + } + + my $new = new FS::cust_pkg { $self->hash }; + $new->set('resume', $date); + $error = $new->replace($self, options => $self->options); + + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + else { + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + return ''; + } + + } #if $date + foreach my $cust_svc ( qsearch('cust_svc',{'pkgnum'=> $self->pkgnum } ) ) { @@ -1229,7 +1279,8 @@ sub unsuspend { } $hash{'susp'} = ''; - $hash{'adjourn'} = '' if $hash{'adjourn'} < time; + $hash{'adjourn'} = '' if $hash{'adjourn'} and $hash{'adjourn'} < time; + $hash{'resume'} = '' if !$hash{'adjourn'}; my $new = new FS::cust_pkg ( \%hash ); $error = $new->replace( $self, options => { $self->options } ); if ( $error ) { @@ -1287,6 +1338,7 @@ sub unadjourn { my %hash = $self->hash; $hash{'adjourn'} = ''; + $hash{'resume'} = ''; my $new = new FS::cust_pkg ( \%hash ); $error = $new->replace( $self, options => { $self->options } ); if ( $error ) { @@ -1409,7 +1461,7 @@ sub change { if ( $keep_dates ) { foreach my $date ( qw(setup bill last_bill susp adjourn cancel expire - start_date contract_end ) ) { + resume start_date contract_end ) ) { $hash{$date} = $self->getfield($date); } } |