summaryrefslogtreecommitdiff
path: root/FS
diff options
context:
space:
mode:
authormark <mark>2012-01-28 23:20:33 +0000
committermark <mark>2012-01-28 23:20:33 +0000
commit396e18e8b0b43fd6b7bf4c2f1e0465d16371441f (patch)
treef506bb3f7fa2e8246f1e5bdbe020916a85f5c23f /FS
parentf22d7f0c3b27d10450961090f755be8b2b22eb22 (diff)
future package unsuspend date, #14144
Diffstat (limited to 'FS')
-rw-r--r--FS/FS/Cron/bill.pm3
-rw-r--r--FS/FS/Schema.pm1
-rw-r--r--FS/FS/cust_main/Billing.pm31
-rw-r--r--FS/FS/cust_pkg.pm70
4 files changed, 93 insertions, 12 deletions
diff --git a/FS/FS/Cron/bill.pm b/FS/FS/Cron/bill.pm
index 1569ef6a2..cb617a05e 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>)
@@ -202,6 +202,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 be46f24e3..7975a302a 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 850ffaa3a..4c77721db 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 ) {
@@ -184,7 +192,7 @@ sub cancel_expired_pkgs {
push @errors, 'pkgnum '.$cust_pkg->pkgnum.": $error" if $error;
}
- scalar(@errors) ? join(' / ', @errors) : '';
+ join(' / ', @errors);
}
@@ -226,7 +234,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);
}
@@ -2158,6 +2184,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 349f20e1e..88ce3a0e1 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') ) {
@@ -940,9 +944,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
@@ -978,16 +994,16 @@ sub suspend {
return ""; # no error # complain on adjourn?
}
+ 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;
return "Package $pkgnum expires before it would be suspended.";
}
- my $suspend_time = $options{'time'} || time;
-
if ( $options{'reason'} ) {
$error = $self->insert_reason( 'reason' => $options{'reason'},
'action' => $date ? 'adjourn' : 'suspend',
@@ -1006,6 +1022,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 ) {
@@ -1083,6 +1105,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
@@ -1117,15 +1144,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 } )
) {
@@ -1166,7 +1216,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 ) {
@@ -1224,6 +1275,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 ) {
@@ -1335,7 +1387,7 @@ sub change {
my $unused_credit = 0;
if ( $opt->{'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);
}
}