From a7d8494c57376bfc493fbaa234b250cc86a79a94 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Sun, 27 Apr 2014 14:19:59 -0700 Subject: [PATCH] "on hold" package ordering and status, RT#28508 also even with flag set to do so, don't adjust bill dates forward on a package which is billing while suspended, RT#27882 --- FS/FS/cust_main/Billing.pm | 14 +++++--- FS/FS/cust_pkg.pm | 47 ++++++++++++++++++++------ FS/FS/cust_pkg/Search.pm | 10 ++++-- httemplate/browse/part_pkg.cgi | 15 ++++++-- httemplate/edit/process/quick-cust_pkg.cgi | 12 ++++--- httemplate/elements/order_pkg.js | 19 ++++++++++- httemplate/misc/change_pkg.cgi | 2 -- httemplate/misc/order_pkg.html | 18 +++++----- httemplate/search/report_cust_pkg.html | 3 +- httemplate/view/cust_main/packages/status.html | 33 ++++++++++++------ 10 files changed, 126 insertions(+), 47 deletions(-) diff --git a/FS/FS/cust_main/Billing.pm b/FS/FS/cust_main/Billing.pm index 63c7f2b58..2878276cc 100644 --- a/FS/FS/cust_main/Billing.pm +++ b/FS/FS/cust_main/Billing.pm @@ -1127,10 +1127,16 @@ sub _make_lines { my $recur_billed_amount = 0; my $sdate; if ( ! $cust_pkg->start_date - and ( ! $cust_pkg->susp || $cust_pkg->option('suspend_bill',1) - || ( $part_pkg->option('suspend_bill', 1) ) - && ! $cust_pkg->option('no_suspend_bill',1) - ) + and + ( ! $cust_pkg->susp + || ( $cust_pkg->susp != $cust_pkg->order_date + && ( $cust_pkg->option('suspend_bill',1) + || ( $part_pkg->option('suspend_bill', 1) + && ! $cust_pkg->option('no_suspend_bill',1) + ) + ) + ) + ) and ( $part_pkg->freq ne '0' && ( $cust_pkg->bill || 0 ) <= $cmp_time ) || ( $part_pkg->plan eq 'voip_cdr' diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index a893e5cbe..d546e555d 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -341,6 +341,8 @@ sub insert { $self->order_date(time) unless ($import && $self->order_date) or $self->change_pkgnum; + $self->susp( $self->order_date ) if $self->susp eq 'now'; + my $oldAutoCommit = $FS::UID::AutoCommit; local $FS::UID::AutoCommit = 0; my $dbh = dbh; @@ -1526,16 +1528,20 @@ sub unsuspend { my $conf = new FS::Conf; - 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) ) - ) { - - $hash{'bill'} = ( $hash{'bill'} || $hash{'setup'} ) + $inactive; - - } + #adjust the next bill date forward + $hash{'bill'} = ( $hash{'bill'} || $hash{'setup'} ) + $inactive + 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'} + ; $hash{'susp'} = ''; $hash{'adjourn'} = '' if $hash{'adjourn'} and $hash{'adjourn'} < time; @@ -3086,6 +3092,8 @@ Returns a short status string for this package, currently: =over 4 +=item on hold + =item not yet billed =item one-time charge @@ -3106,6 +3114,7 @@ sub status { my $freq = length($self->freq) ? $self->freq : $self->part_pkg->freq; return 'cancelled' if $self->get('cancel'); + return 'on hold' if $self->susp && ! $self->setup; return 'suspended' if $self->susp; return 'not yet billed' unless $self->setup; return 'one-time charge' if $freq =~ /^(0|$)/; @@ -3132,6 +3141,7 @@ Class method that returns the list of possible status strings for packages =cut tie my %statuscolor, 'Tie::IxHash', + 'on hold' => '7E0079', #purple! 'not yet billed' => '009999', #teal? cyan? 'one-time charge' => '000000', 'active' => '00CC00', @@ -4176,6 +4186,21 @@ sub inactive_sql { " AND ( cust_pkg.susp IS NULL OR cust_pkg.susp = 0 ) "; } +=item on_hold_sql + +Returns an SQL expression identifying on-hold packages. + +=cut + +sub on_hold_sql { + #$_[0]->recurring_sql(). ' AND '. + " + ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 ) + AND cust_pkg.susp IS NOT NULL AND cust_pkg.susp != 0 + AND ( cust_pkg.setup IS NULL OR cust_pkg.setup = 0 ) + "; +} + =item susp_sql =item suspended_sql @@ -4189,6 +4214,7 @@ sub susp_sql { " ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 ) AND cust_pkg.susp IS NOT NULL AND cust_pkg.susp != 0 + AND cust_pkg.setup IS NOT NULL AND cust_pkg.setup != 0 "; } @@ -4214,6 +4240,7 @@ Returns an SQL expression to give the package status as a string. sub status_sql { "CASE WHEN cust_pkg.cancel IS NOT NULL THEN 'cancelled' + WHEN ( cust_pkg.susp IS NOT NULL AND cust_pkg.setup IS NULL ) THEN 'on hold' WHEN cust_pkg.susp IS NOT NULL THEN 'suspended' WHEN cust_pkg.setup IS NULL THEN 'not yet billed' WHEN ".onetime_sql()." THEN 'one-time charge' diff --git a/FS/FS/cust_pkg/Search.pm b/FS/FS/cust_pkg/Search.pm index 47efd3140..543ef1a61 100644 --- a/FS/FS/cust_pkg/Search.pm +++ b/FS/FS/cust_pkg/Search.pm @@ -19,11 +19,11 @@ Valid parameters are =item magic -active, inactive, suspended, cancel (or cancelled) +on hold, active, inactive (or one-time charge), suspended, cancel (or cancelled) =item status -active, inactive, suspended, one-time charge, inactive, cancel (or cancelled) +on hold, active, inactive (or one-time charge), suspended, cancel (or cancelled) =item custom @@ -191,6 +191,12 @@ sub search { push @where, FS::cust_pkg->inactive_sql(); + } elsif ( $params->{'magic'} =~ /^on[ _]hold$/ + || $params->{'status'} =~ /^on[ _]hold$/ ) { + + push @where, FS::cust_pkg->on_hold_sql(); + + } elsif ( $params->{'magic'} eq 'suspended' || $params->{'status'} eq 'suspended' ) { diff --git a/httemplate/browse/part_pkg.cgi b/httemplate/browse/part_pkg.cgi index 574cf7af3..d0c14da4c 100755 --- a/httemplate/browse/part_pkg.cgi +++ b/httemplate/browse/part_pkg.cgi @@ -128,9 +128,16 @@ $select = " ( $count_cust_pkg AND ( cancel IS NULL OR cancel = 0 ) AND susp IS NOT NULL AND susp != 0 + AND setup IS NOT NULL AND setup != 0 ) AS num_suspended, ( $count_cust_pkg + AND ( cancel IS NULL OR cancel = 0 ) + AND susp IS NOT NULL AND susp != 0 + AND ( setup IS NULL OR setup = 0 ) + ) AS num_on_hold, + + ( $count_cust_pkg AND cancel IS NOT NULL AND cancel != 0 ) AS num_cancelled @@ -382,6 +389,7 @@ if ( $acl_edit_global ) { #if ( $cgi->param('active') ) { push @header, 'Customer
packages'; my %col = ( + 'on hold' => '7E0079', #purple! 'not yet billed' => '009999', #teal? cyan? 'active' => '00CC00', 'suspended' => 'FF9900', @@ -397,10 +405,11 @@ if ( $acl_edit_global ) { my $label = $_; if ( $magic eq 'active' && $part_pkg->freq == 0 ) { $magic = 'inactive'; - #$label = 'one-time charge', - $label = 'charge', + #$label = 'one-time charge'; + $label = 'charge'; } $label= 'not yet billed' if $magic eq 'not_yet_billed'; + $label= 'on hold' if $magic eq 'on_hold'; [ { @@ -425,7 +434,7 @@ if ( $acl_edit_global ) { ), }, ], - } (qw( not_yet_billed active suspended cancelled )) + } (qw( on_hold not_yet_billed active suspended cancelled )) ), ($acl_config ? [ {}, diff --git a/httemplate/edit/process/quick-cust_pkg.cgi b/httemplate/edit/process/quick-cust_pkg.cgi index c3ab6fec3..f1d8c2696 100644 --- a/httemplate/edit/process/quick-cust_pkg.cgi +++ b/httemplate/edit/process/quick-cust_pkg.cgi @@ -110,10 +110,6 @@ my $error = ''; my %hash = ( 'pkgpart' => $pkgpart, 'quantity' => $quantity, - 'start_date' => ( scalar($cgi->param('start_date')) - ? parse_datetime($cgi->param('start_date')) - : '' - ), 'salesnum' => $salesnum, 'refnum' => $refnum, 'contactnum' => $contactnum, @@ -133,6 +129,14 @@ my %hash = ( ); $hash{'custnum'} = $cust_main->custnum if $cust_main; +if ( $cgi->param('start') eq 'on_hold' ) { + $hash{'susp'} = 'now'; +} elsif ( $cgi->param('start') eq 'on_date' ) { + $hash{'start_date'} = scalar($cgi->param('start_date')) + ? parse_datetime($cgi->param('start_date')) + : ''; +} + my @cust_pkg_usageprice = (); foreach my $quantity_param ( grep { $cgi->param($_) && $cgi->param($_) > 0 } grep /^usagepricenum(\d+)_quantity$/, diff --git a/httemplate/elements/order_pkg.js b/httemplate/elements/order_pkg.js index 393b845c9..a145cbb03 100644 --- a/httemplate/elements/order_pkg.js +++ b/httemplate/elements/order_pkg.js @@ -6,9 +6,12 @@ function pkg_changed () { var opt = form.pkgpart.options[form.pkgpart.selectedIndex]; var date_button = document.getElementById('start_date_button'); - var date_button_disabled = document.getElementById('start_date_button_disabled'); + var date_button_disabled = document.getElementById('start_date_disabled'); var date_text = document.getElementById('start_date_text'); + var radio_now = document.getElementById('start_now'); + //var radio_on_hold = document.getElementById('start_on_hold'); + var radio_on_date = document.getElementById('start_on_date'); form.submitButton.disabled = false; if ( discountnum ) { @@ -32,11 +35,25 @@ function pkg_changed () { date_text.disabled = false; date_button.style.display = ''; date_button_disabled.style.display = 'none'; + if ( radio_on_date ) { + radio_on_date.disabled = false; + if ( form.start_date_text.value.length > 0 && radio_now.checked ) { + radio_now.checked = false; + radio_on_date.checked = true; + } + } } else { date_text.style.backgroundColor = '#dddddd'; date_text.disabled = true; date_button.style.display = 'none'; date_button_disabled.style.display = ''; + if ( radio_on_date ) { + if ( radio_on_date.checked ) { + radio_on_date.checked = false; + radio_now.checked = true; + } + radio_on_date.disabled = true; + } } get_part_pkg_usageprice( opt.value, update_part_pkg_usageprice ); diff --git a/httemplate/misc/change_pkg.cgi b/httemplate/misc/change_pkg.cgi index 5b4a3dea9..1b4a94e81 100755 --- a/httemplate/misc/change_pkg.cgi +++ b/httemplate/misc/change_pkg.cgi @@ -59,8 +59,6 @@ 'name' => 'start_date', 'value' => ($cgi->param('start_date') || $cust_main->next_bill_date), } &> - diff --git a/httemplate/misc/order_pkg.html b/httemplate/misc/order_pkg.html index 080ba41d9..672e142c7 100644 --- a/httemplate/misc/order_pkg.html +++ b/httemplate/misc/order_pkg.html @@ -10,11 +10,7 @@ 'subs' => [ 'get_part_pkg_usageprice' ], &> - - - - - +<& /elements/init_calendar.html &> @@ -90,18 +86,20 @@ % } - <% mt('Start date') |h %> + <% mt('Start') |h %> + param('start') eq '' ? 'CHECKED' : ''%>>Now +   + param('start') eq 'on_hold' ? 'CHECKED' : ''%>>On hold +   + param('start') eq 'date' ? 'CHECKED' : ''%>>On date + <& /elements/input-date-field.html,{ 'name' => 'start_date', 'format' => $date_format, 'value' => '', 'noinit' => 1, } &> - - (<% mt('leave blank to start immediately') |h %>) diff --git a/httemplate/search/report_cust_pkg.html b/httemplate/search/report_cust_pkg.html index e75a0985b..f124f0f87 100755 --- a/httemplate/search/report_cust_pkg.html +++ b/httemplate/search/report_cust_pkg.html @@ -260,7 +260,8 @@ my @date_fields = keys %label; #false laziness w/cust_pkg.cgi my %disable = ( 'all' => {}, - 'not yet billed' => { 'setup'=>1, 'last_bill'=>1, 'bill'=>1, 'adjourn'=>1, 'susp'=>1, 'expire'=>1, 'cancel'=>1, }, + 'on hold' => { 'setup'=>1, 'last_bill'=>1, 'bill'=>1, 'adjourn'=>1, 'expire'=>1, 'cancel'=>1, 'dundate'=> 1, }, + 'not yet billed' => { 'setup'=>1, 'last_bill'=>1, 'bill'=>1, 'adjourn'=>1, 'susp'=>1, 'expire'=>1, 'cancel'=>1, 'dundate'=>1, }, 'one-time charge' => { 'last_bill'=>1, 'bill'=>1, 'adjourn'=>1, 'susp'=>1, 'expire'=>1, 'cancel'=>1, 'contract_end'=>1, 'dundate'=>1, }, 'active' => { 'susp'=>1, 'cancel'=>1 }, 'suspended' => { 'cancel'=>1, 'dundate'=>1, }, diff --git a/httemplate/view/cust_main/packages/status.html b/httemplate/view/cust_main/packages/status.html index 3ebdf22dc..689ee45c0 100644 --- a/httemplate/view/cust_main/packages/status.html +++ b/httemplate/view/cust_main/packages/status.html @@ -46,21 +46,30 @@ % % } else { % -% if ( $cust_pkg->get('susp') ) { #status: suspended -% my $cpr = $cust_pkg->last_cust_pkg_reason('susp'); +% if ( $cust_pkg->get('susp') ) { #suspended or on hold +% +% if ( $cust_pkg->order_date eq $cust_pkg->get('susp') ) { #status: on hold + + <% pkg_status_row( $cust_pkg, emt('On Hold'), '', 'color'=>'7E0079', %opt ) %> - <% pkg_status_row( $cust_pkg, emt('Suspended'), 'susp', 'color'=>'FF9900', %opt ) %> +% } else { #status: suspended - <% pkg_reason_row( $cust_pkg, $cpr, 'color' => 'FF9900', %opt ) %> + <% pkg_status_row( $cust_pkg, emt('Suspended'), 'susp', 'color'=>'FF9900', %opt ) %> +% my $cpr = $cust_pkg->last_cust_pkg_reason('susp'); + <% pkg_reason_row( $cust_pkg, $cpr, 'color' => 'FF9900', %opt ) %> + +% } <% pkg_status_row_noauto( $cust_pkg, %opt ) %> <% pkg_status_row_discount( $cust_pkg, %opt ) %> -% unless ( $cust_pkg->get('setup') ) { - <% pkg_status_row_colspan( $cust_pkg, emt('Never billed'), '', %opt ) %> -% } else { - <% pkg_status_row($cust_pkg, emt('Setup'), 'setup', %opt ) %> +% unless ( $cust_pkg->order_date eq $cust_pkg->get('susp') ) { #on hold +% unless ( $cust_pkg->get('setup') ) { + <% pkg_status_row_colspan( $cust_pkg, emt('Never billed'), '', %opt ) %> +% } else { + <% pkg_status_row($cust_pkg, emt('Setup'), 'setup', %opt ) %> +% } % } <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %> @@ -93,8 +102,12 @@ % } % } % if ( $curuser->access_right('Unsuspend customer package') ) { - ( <% pkg_unsuspend_link($cust_pkg) %> ) - ( <% pkg_resume_link($cust_pkg) %> ) +% if ( $cust_pkg->order_date eq $cust_pkg->get('susp') ) { #on hold + ( <% pkg_link('misc/unsusp_pkg', emt('Start bililng now'), $cust_pkg) %> ) +% } else { + ( <% pkg_unsuspend_link($cust_pkg) %> ) + ( <% pkg_resume_link($cust_pkg) %> ) +% } % } % if ( !$cust_pkg->change_to_pkgnum and % $curuser->access_right('Cancel customer package immediately') -- 2.11.0