summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjeff <jeff>2008-09-26 03:54:25 +0000
committerjeff <jeff>2008-09-26 03:54:25 +0000
commitf411189684b0ca7cc1b4b3e9be1895607245b595 (patch)
tree8d219fe11c5554a304b8d6c56407a1922cb370ca
parente2d78a94d7806862da7fcea0025cd380d49d5a75 (diff)
push out event triggered suspensions
-rw-r--r--FS/FS/AccessRight.pm1
-rw-r--r--FS/FS/Schema.pm1
-rw-r--r--FS/FS/cust_main.pm16
-rw-r--r--FS/FS/part_bill_event.pm5
-rw-r--r--FS/FS/part_event/Condition/dundate.pm26
-rwxr-xr-xhttemplate/edit/part_bill_event.cgi27
-rwxr-xr-xhttemplate/misc/delay_susp_pkg.html73
-rwxr-xr-xhttemplate/misc/process/delay_susp_pkg.html41
-rwxr-xr-xhttemplate/view/cust_main/packages.html40
9 files changed, 215 insertions, 15 deletions
diff --git a/FS/FS/AccessRight.pm b/FS/FS/AccessRight.pm
index 9ef35249c..b016d1885 100644
--- a/FS/FS/AccessRight.pm
+++ b/FS/FS/AccessRight.pm
@@ -119,6 +119,7 @@ tie my %rights, 'Tie::IxHash',
'Unsuspend customer package',
'Cancel customer package immediately',
'Cancel customer package later',
+ 'Delay suspension events',
'Add on-the-fly cancel reason', #NEW
'Add on-the-fly suspend reason', #NEW
'Edit customer package invoice details', #NEW
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index b3cce9a93..5c9f6248c 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -605,6 +605,7 @@ sub tables_hashref {
'stateid_state', 'varchar', 'NULL', $char_d, '', '',
'birthdate' ,@date_type, '', '',
'signupdate',@date_type, '', '',
+ 'dundate', @date_type, '', '',
'company', 'varchar', 'NULL', $char_d, '', '',
'address1', 'varchar', '', $char_d, '', '',
'address2', 'varchar', 'NULL', $char_d, '', '',
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index ec2ac3c61..b348aaa7b 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -227,6 +227,8 @@ Card Verification Value, "CVV2" (also known as CVC2 or CID), the 3 or 4 digit nu
=item spool_cdr - Enable individual CDR spooling, empty or `Y'
+=item dundate - a suggestion to events (see L<FS::part_bill_event">) to delay until this unix timestamp
+
=item squelch_cdr - Discourage individual CDR printing, empty or `Y'
=back
@@ -2976,14 +2978,16 @@ sub due_cust_event {
# 3: insert
##
- foreach my $cust_event ( @cust_event ) {
+ unless( $opt{testonly} ) {
+ foreach my $cust_event ( @cust_event ) {
- my $error = $cust_event->insert();
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
+ my $error = $cust_event->insert();
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
}
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
diff --git a/FS/FS/part_bill_event.pm b/FS/FS/part_bill_event.pm
index 1d48af9fc..4e7aa52f2 100644
--- a/FS/FS/part_bill_event.pm
+++ b/FS/FS/part_bill_event.pm
@@ -5,6 +5,8 @@ use vars qw( @ISA $DEBUG @EXPORT_OK );
use Carp qw(cluck confess);
use FS::Record qw( dbh qsearch qsearchs );
use FS::Conf;
+use FS::cust_main;
+use FS::cust_bill;
@ISA = qw( FS::Record );
@EXPORT_OK = qw( due_events );
@@ -244,6 +246,9 @@ sub due_events {
sort { $a->seconds <=> $b->seconds
|| $a->weight <=> $b->weight
|| $a->eventpart <=> $b->eventpart }
+ grep { ref($record) ne 'FS::cust_bill' || $_->eventcode !~ /honor_dundate/
+ || $event_time > $record->cust_main->dundate
+ }
grep { $_->seconds <= ( $interval )
&& ! qsearch( 'cust_bill_event', {
'invnum' => $record->get($record->dbdef_table->primary_key),
diff --git a/FS/FS/part_event/Condition/dundate.pm b/FS/FS/part_event/Condition/dundate.pm
new file mode 100644
index 000000000..ee2a95f0b
--- /dev/null
+++ b/FS/FS/part_event/Condition/dundate.pm
@@ -0,0 +1,26 @@
+package FS::part_event::Condition::dundate;
+
+use strict;
+
+use base qw( FS::part_event::Condition );
+
+sub description {
+ "Skip until customer dun date is reached";
+}
+
+sub condition {
+ my($self, $object, %opt) = @_;
+
+ my $cust_main = $self->cust_main($object);
+
+ $cust_main->dundate <= $opt{time};
+
+}
+
+#sub condition_sql {
+# my( $self, $table ) = @_;
+#
+# 'true';
+#}
+
+1;
diff --git a/httemplate/edit/part_bill_event.cgi b/httemplate/edit/part_bill_event.cgi
index 8e7b6da87..3b5114122 100755
--- a/httemplate/edit/part_bill_event.cgi
+++ b/httemplate/edit/part_bill_event.cgi
@@ -96,6 +96,18 @@ Invoice Event #<% $hashref->{eventpart} ? $hashref->{eventpart} : "(NEW)" %>
% '</SELECT>';
%}
%
+%sub honor_dundate {
+% my $label = shift;
+% my $plandata = shift;
+% '<TABLE>'.
+% '<TR><TD ALIGN="right">Allow delay until dun date? </TD>'.
+% qq(<TD><INPUT TYPE="checkbox" NAME="$label" VALUE="$label => 1," ).
+% ( $plandata->{$label} eq "$label => 1," ? 'CHECKED' : '' ).
+% '>'.
+% '</TD></TR>'.
+% '</TABLE>'
+%}
+%
%my $conf = new FS::Conf;
%my $money_char = $conf->config('money_char') || '$';
%
@@ -137,28 +149,29 @@ Invoice Event #<% $hashref->{eventpart} ? $hashref->{eventpart} : "(NEW)" %>
% },
% 'suspend' => {
% 'name' => 'Suspend',
-% 'code' => '$cust_main->suspend(reason => %%%sreason%%%);',
+% 'code' => '$cust_main->suspend(reason => %%%sreason%%%, %%%honor_dundate%%% );',
+% 'html' => sub { &honor_dundate('honor_dundate', @_) },
% 'weight' => 10,
% 'reason' => 'S',
% },
% 'suspend-if-balance' => {
% 'name' => 'Suspend if balance (this invoice and previous) over',
-% 'code' => '$cust_bill->cust_suspend_if_balance_over( %%%balanceover%%%, reason => %%%sreason%%%, );',
-% 'html' => " $money_char ". '<INPUT TYPE="text" SIZE="7" NAME="balanceover" VALUE="%%%balanceover%%%">',
+% 'code' => '$cust_bill->cust_suspend_if_balance_over( %%%balanceover%%%, reason => %%%sreason%%%, %%%balance_honor_dundate%%% );',
+% 'html' => sub { " $money_char ". '<INPUT TYPE="text" SIZE="7" NAME="balanceover" VALUE="%%%balanceover%%%"> '. &honor_dundate('balance_honor_dundate', @_) },
% 'weight' => 10,
% 'reason' => 'S',
% },
% 'suspend-if-pkgpart' => {
% 'name' => 'Suspend packages',
-% 'code' => '$cust_main->suspend_if_pkgpart({pkgparts => [%%%if_pkgpart%%%,], reason => %%%sreason%%%,});',
-% 'html' => sub { &select_pkgpart('if_pkgpart', @_) },
+% 'code' => '$cust_main->suspend_if_pkgpart({pkgparts => [%%%if_pkgpart%%%,], reason => %%%sreason%%%, %%%if_pkgpart_honor_dundate%%% });',
+% 'html' => sub { &select_pkgpart('if_pkgpart', @_). &honor_dundate('if_pkgpart_honor_dundate', @_) },
% 'weight' => 10,
% 'reason' => 'S',
% },
% 'suspend-unless-pkgpart' => {
% 'name' => 'Suspend packages except',
-% 'code' => '$cust_main->suspend_unless_pkgpart({unless_pkgpart => [%%%unless_pkgpart%%%], reason => %%%sreason%%%,});',
-% 'html' => sub { &select_pkgpart('unless_pkgpart', @_) },
+% 'code' => '$cust_main->suspend_unless_pkgpart({unless_pkgpart => [%%%unless_pkgpart%%%], reason => %%%sreason%%%, %%%unless_pkgpart_honor_dundate%%% });',
+% 'html' => sub { &select_pkgpart('unless_pkgpart', @_). &honor_dundate('unless_pkgpart_honor_dundate' => @_) },
% 'weight' => 10,
% 'reason' => 'S',
% },
diff --git a/httemplate/misc/delay_susp_pkg.html b/httemplate/misc/delay_susp_pkg.html
new file mode 100755
index 000000000..0755309db
--- /dev/null
+++ b/httemplate/misc/delay_susp_pkg.html
@@ -0,0 +1,73 @@
+%# if ( $link eq 'popup' ) {
+ <% include('/elements/header-popup.html', $title ) %>
+%# } else {
+%# <% include("/elements/header.html", $title, '') %>
+%# }
+
+<LINK REL="stylesheet" TYPE="text/css" HREF="../elements/calendar-win2k-2.css" TITLE="win2k-2">
+<SCRIPT TYPE="text/javascript" SRC="../elements/calendar_stripped.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="../elements/calendar-en.js"></SCRIPT>
+<SCRIPT TYPE="text/javascript" SRC="../elements/calendar-setup.js"></SCRIPT>
+
+<% include('/elements/error.html') %>
+
+<FORM NAME="ds_popup" ACTION="<% popurl(1) %>process/delay_susp_pkg.html" METHOD=POST>
+<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>">
+
+<BR><BR>
+<% "Delay automatic suspension of $pkgnum: " .$part_pkg->pkg. ' - ' .$part_pkg->comment %>
+<% ntable("#cccccc", 2) %>
+
+<TR>
+ <TD>Delay until</TD>
+ <TD><INPUT TYPE="text" NAME="date" ID="dun_date" VALUE="<% $date |h %>">
+ <IMG SRC="<% $p %>images/calendar.png" ID="dun_button" STYLE="cursor:pointer" TITLE="Select date">
+ <BR><I>m/d/y</I>
+ </TD>
+</TR>
+<SCRIPT TYPE="text/javascript">
+ Calendar.setup({
+ inputField: "dun_date",
+ ifFormat: "%m/%d/%Y",
+ button: "dun_button",
+ align: "BR"
+ });
+</SCRIPT>
+
+</TABLE>
+
+<BR>
+<INPUT TYPE="submit" NAME="submit" VALUE="<% $submit %>">
+
+</FORM>
+</BODY>
+</HTML>
+
+<%init>
+
+my $date = time2str("%m/%d/%Y", time);
+
+my($pkgnum);
+if ( $cgi->param('error') ) {
+ $pkgnum = $cgi->param('pkgnum');
+ $date = $cgi->param('date');
+} elsif ( $cgi->param('pkgnum') =~ /^(\d+)$/ ) {
+ $pkgnum = $1;
+} else {
+ die "illegal query ". $cgi->keywords;
+}
+
+my $submit = 'Delay Suspension';
+my $right = 'Delay suspension events';
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+die "access denied" unless $curuser->access_right($right);
+
+my $title = 'Delay Suspension of Package';
+
+my $cust_pkg = qsearchs('cust_pkg', {'pkgnum' => $pkgnum})
+ or die "Unknown pkgnum: $pkgnum";
+
+my $part_pkg = $cust_pkg->part_pkg;
+
+</%init>
diff --git a/httemplate/misc/process/delay_susp_pkg.html b/httemplate/misc/process/delay_susp_pkg.html
new file mode 100755
index 000000000..c7cc7de7c
--- /dev/null
+++ b/httemplate/misc/process/delay_susp_pkg.html
@@ -0,0 +1,41 @@
+<% header("Package suspension delayed") %>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+ </BODY>
+</HTML>
+<%once>
+
+my $right = 'Delay suspension events';
+
+</%once>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right($right);
+
+my ($pkgnum, $date, $cust_pkg, $cust_main, $error);
+
+#untaint pkgnum
+$cgi->param('pkgnum') =~ /^(\d+)$/ or die "Illegal pkgnum";
+$pkgnum = $1;
+
+#untaint date
+str2time($cgi->param('date')) =~ /^(\d+)$/ or die "Illegal date";
+my $date = $1;
+
+$cust_pkg = qsearchs( 'cust_pkg', {'pkgnum'=>$pkgnum} );
+if ($cust_pkg) {
+ $cust_main = $cust_pkg->cust_main;
+ $cust_main->dundate( $date );
+ $error = $cust_main->replace;
+} else {
+ $error = "Invalid pkgnum";
+}
+
+if ($error) {
+ $cgi->param('error', $error);
+ print $cgi->redirect(popurl(2). "cancel_pkg.html?". $cgi->query_string );
+}
+
+</%init>
diff --git a/httemplate/view/cust_main/packages.html b/httemplate/view/cust_main/packages.html
index ad5595c1a..5f1db4ab6 100755
--- a/httemplate/view/cust_main/packages.html
+++ b/httemplate/view/cust_main/packages.html
@@ -456,10 +456,13 @@ Current packages
% }
%
% }
+% my $autosuspend = pkg_autosuspend_time( $cust_pkg );
+% $cust_pkg->set('autosuspend', $autosuspend) if $autosuspend;
<% pkg_status_row_changed( $cust_pkg, conf=>$conf ) %>
<% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', conf=>$conf, curuser=>$curuser ) %>
<% pkg_status_row_if( $cust_pkg, $next_bill_or_prepaid_until, 'bill', conf=>$conf, curuser=>$curuser ) %>
+ <% pkg_status_row_if($cust_pkg, 'Will automatically suspend by', 'autosuspend', conf=>$conf) %>
<% pkg_status_row_if( $cust_pkg, 'Will suspend on', 'adjourn', conf=>$conf, curuser=>$curuser ) %>
<% pkg_status_row_if( $cust_pkg, 'Expires', 'expire', conf=>$conf, curuser=>$curuser ) %>
@@ -474,6 +477,9 @@ Current packages
% if ( $curuser->access_right('Suspend customer package later') ) {
(&nbsp;<% pkg_adjourn_link($cust_pkg) %>&nbsp;)
% }
+% if ( $curuser->access_right('Delay suspension events') ) {
+ (&nbsp;<% pkg_delay_link($cust_pkg) %>&nbsp;)
+% }
% if ( $curuser->access_right('Cancel customer package immediately') ) {
(&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
% }
@@ -759,10 +765,19 @@ sub pkg_adjourn_link { include( '/elements/popup_link-cust_pkg.html',
)
}
+sub pkg_delay_link { include( '/elements/popup_link-cust_pkg.html',
+ { 'action' => $p. 'misc/delay_susp_pkg.html',
+ 'label' => 'Delay&nbsp;suspend',
+ 'actionlabel' => 'Delay suspend for',
+ 'cust_pkg' => shift,
+ }
+ )
+ }
+
sub pkg_unsuspend_link { pkg_link('misc/unsusp_pkg', 'Unsuspend', @_ ); }
sub pkg_dates_link { pkg_link('edit/REAL_cust_pkg', 'Edit&nbsp;dates', @_ ); }
-sub pkg_unadjourn_link { pkg_link('misc/unadjourn_pkg', 'Abort', @_ ); }
-sub pkg_unexpire_link { pkg_link('misc/unexpire_pkg', 'Abort', @_ ); }
+sub pkg_unadjourn_link { pkg_link('misc/unadjourn_pkg', 'Abort', @_ ); }
+sub pkg_unexpire_link { pkg_link('misc/unexpire_pkg', 'Abort', @_ ); }
sub pkg_cancel_link { include( '/elements/popup_link-cust_pkg.html',
{ 'action' => $p. 'misc/cancel_pkg.html?method=cancel',
@@ -827,4 +842,25 @@ sub pkg_customize_link {
qq!">Customize</A>!;
}
+sub pkg_autosuspend_time {
+ my $cust_pkg = shift or return '';
+ my $days = 7;
+ my $time = time;
+ my $pending_suspend = 0;
+ while ( $days > 0 &&
+ scalar(
+ grep { $_->part_event->action eq 'suspend' }
+ @{$cust_pkg->cust_main->due_cust_event( time => $time + 86400*$days,
+ testonly => 1,
+ ) }
+ )
+ )
+ {
+ $pending_suspend = 1;
+ $days--;
+ }
+
+ $pending_suspend ? time + ($days + 1) * 86400 : '';
+
+}
</%init>