From 2554b11e48a7ec4567bf89f9a48f7a83ec925eea Mon Sep 17 00:00:00 2001 From: Christopher Burger Date: Mon, 13 Nov 2017 12:45:15 -0500 Subject: [PATCH] RT# 77470 - added reason option to advanced package report with suspended status is selected. Also added links to suspend and unsuspend when status active or suspended is used. --- FS/FS/cust_pkg/Search.pm | 6 ++ httemplate/elements/tr-select-reason.html | 32 ++++++-- httemplate/elements/tr-td-label.html | 4 +- httemplate/misc/bulk_suspend_pkg.cgi | 94 ++++++++++++++++++++++ httemplate/misc/bulk_unsuspend_pkg.cgi | 66 +++++++++++++++ httemplate/misc/process/bulk_suspend_pkg.cgi | 106 +++++++++++++++++++++++++ httemplate/misc/process/bulk_unsuspend_pkg.cgi | 91 +++++++++++++++++++++ httemplate/search/cust_pkg.cgi | 18 ++++- httemplate/search/report_cust_pkg.html | 19 +++++ 9 files changed, 426 insertions(+), 10 deletions(-) create mode 100644 httemplate/misc/bulk_suspend_pkg.cgi create mode 100644 httemplate/misc/bulk_unsuspend_pkg.cgi create mode 100644 httemplate/misc/process/bulk_suspend_pkg.cgi create mode 100644 httemplate/misc/process/bulk_unsuspend_pkg.cgi diff --git a/FS/FS/cust_pkg/Search.pm b/FS/FS/cust_pkg/Search.pm index 311dbdbe1..3e1ca820e 100644 --- a/FS/FS/cust_pkg/Search.pm +++ b/FS/FS/cust_pkg/Search.pm @@ -627,6 +627,8 @@ sub search { push @where, $FS::CurrentUser::CurrentUser->agentnums_sql('table'=>'cust_main'); } + push @where, "cust_pkg_reason.reasonnum = '".$params->{reasonnum}."'" if $params->{reasonnum}; + my $extra_sql = scalar(@where) ? ' WHERE '. join(' AND ', @where) : ''; my $addl_from = 'LEFT JOIN part_pkg USING ( pkgpart ) '. @@ -634,6 +636,10 @@ sub search { 'LEFT JOIN cust_location USING ( locationnum ) '. FS::UI::Web::join_cust_main('cust_pkg', 'cust_pkg'); + if ($params->{reasonnum}) { + $addl_from .= 'LEFT JOIN cust_pkg_reason ON (cust_pkg_reason.pkgnum = cust_pkg.pkgnum) '; + } + my $select; my $count_query; if ( $params->{'select_zip5'} ) { diff --git a/httemplate/elements/tr-select-reason.html b/httemplate/elements/tr-select-reason.html index 9a430222c..6f126d327 100755 --- a/httemplate/elements/tr-select-reason.html +++ b/httemplate/elements/tr-select-reason.html @@ -5,16 +5,22 @@ Example: include( '/elements/tr-select-reason.html', #required - 'field' => 'reasonnum', - 'reason_class' => 'C', # one of those in %FS::reason_type::class_name + 'field' => 'reasonnum', # field name + 'reason_class' => 'C', # one of those in %FS::reason_type::class_name + 'label' => 'Your Label', # field display label #recommended 'cgi' => $cgi, #easiest way for things to be properly "sticky" on errors #optional - 'control_button' => 'element_name', #button to be enabled when a reason is - #selected + 'control_button' => 'element_name', #button to be enabled when a reason is + #selected 'id' => 'element_id', + 'hide_add' => '1', # setting this will hide the add new reason link, + # even if the user has access to add a new reason. + 'hide_onload' => '1', # setting this will hide reason select box on page load, + # allowing for it do be displayed later. + 'pre_options' => [ 0 => 'all'], # an array of pre options. Defaults to 0 => 'select reason...' #deprecated ways to keep things "sticky" on errors # (requires duplicate code in each using file to parse cgi params) @@ -67,8 +73,9 @@ Example: %# sadly can't just use add_inline here, as we have non-text fields + <& tr-select-table.html, - 'label' => 'Reason', + 'label' => $label, 'field' => $name, 'id' => $id, 'table' => 'reason', @@ -76,16 +83,17 @@ Example: 'label_callback' => sub { my $reason = shift; $reason->type . ' : ' . $reason->reason }, 'disable_empty' => 1, - 'pre_options' => [ 0 => 'Select reason...' ], + 'pre_options' => \@pre_options, 'post_options' => \@post_options, 'curr_value' => $init_reason, 'onchange' => $id.'_changed()', + 'hide_onload' => $opt{'hide_onload'}, &> % # "add new reason" fields % # should be a
, but that doesn't fit well into the table -% if ( $curuser->access_right($add_access_right) ) { +% if ( $curuser->access_right($add_access_right) && !$hide_addnew ) { @@ -184,6 +192,8 @@ my %opt = @_; my $name = $opt{'field'}; my $class = $opt{'reason_class'}; +my $label = $opt{'label'} ? $opt{'label'} : 'Reason'; +my $hide_addnew = $opt{'hide_addnew'} ? $opt{'hide_addnew'} : ''; my $init_reason; if ( $opt{'cgi'} ) { @@ -194,6 +204,8 @@ $init_reason ||= $opt{'curr_value'}; my $id = $opt{'id'} || $name; $id =~ s/\./_/g; # for edit/part_event +my $label_id = $opt{'label_id'} || ''; + my $add_access_right = $FS::reason_type::class_add_access_right{$class} or die "unknown class: $class"; @@ -206,8 +218,12 @@ my @reasons = qsearch({ 'order_by' => ' ORDER BY type, reason', }); + +my @pre_options = ( 0 => 'Select reason...' ); +@pre_options = @{ $opt{'pre_options'} if $opt{'pre_options'} }; + my @post_options; -if ( $curuser->access_right($add_access_right) ) { +if ( $curuser->access_right($add_access_right) && !$hide_addnew ) { @post_options = ( -1 => 'Add new reason' ); } diff --git a/httemplate/elements/tr-td-label.html b/httemplate/elements/tr-td-label.html index 1d96cf307..80dddaa47 100644 --- a/httemplate/elements/tr-td-label.html +++ b/httemplate/elements/tr-td-label.html @@ -6,7 +6,7 @@ Note that this puts the 'label' argument into the document verbatim, with no escaping or localization. - +>
* ' : ''; diff --git a/httemplate/misc/bulk_suspend_pkg.cgi b/httemplate/misc/bulk_suspend_pkg.cgi new file mode 100644 index 000000000..e41ea2b1a --- /dev/null +++ b/httemplate/misc/bulk_suspend_pkg.cgi @@ -0,0 +1,94 @@ +<% include('/elements/header-popup.html', "Suspend Packages") %> + +% if ( $cgi->param('error') ) { + Error: <% $cgi->param('error') %> +

+% } + +
+ +%# some false laziness w/search/cust_pkg.cgi + + +% for my $param ( +% qw( +% agentnum cust_status cust_main_salesnum salesnum custnum magic status +% custom pkgbatch zip reasonnum +% 477part 477rownum date +% report_option +% ), +% grep { /^location_\w+$/ || /^report_option_any/ } $cgi->param +% ) { + +% } +% +% for my $param (qw( censustract censustract2 ) ) { +% next unless grep { $_ eq $param } $cgi->param; + +% } +% +% for my $param (qw( pkgpart classnum refnum towernum )) { +% foreach my $value ($cgi->param($param)) { + +% } +% } +% +% foreach my $field (qw( setup last_bill bill adjourn susp expire contract_end change_date cancel active )) { +% + "> + "> + "> + "> + "> +% } + +<% ntable('#cccccc') %> + +% my $date_init = 0; + <& /elements/tr-input-date-field.html, { + 'name' => 'suspend_date', + 'value' => $date, + 'label' => mt("Suspend package on"), + 'format' => $date_format, + } &> +% $date_init = 1; + + <& /elements/tr-select-reason.html, + field => 'suspend_reasonnum', + reason_class => 'S', + &> + +% if ( $FS::CurrentUser::CurrentUser->access_right('Unsuspend customer package')) { + + <& /elements/tr-input-date-field.html, { + 'name' => 'suspend_resume_date', + 'value' => '', + 'label' => mt('Unsuspend on'), + 'format' => $date_format, + 'noinit' => $date_init, + } &> +% } + +
+ +
+ + + + + + +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Bulk change customer packages'); + +#use Date::Parse qw(str2time); +# + +my $conf = new FS::Conf; +my $date_format = $conf->config('date_format') || '%m/%d/%Y'; + +my $date = time; + + \ No newline at end of file diff --git a/httemplate/misc/bulk_unsuspend_pkg.cgi b/httemplate/misc/bulk_unsuspend_pkg.cgi new file mode 100644 index 000000000..8fbc41841 --- /dev/null +++ b/httemplate/misc/bulk_unsuspend_pkg.cgi @@ -0,0 +1,66 @@ +<% include('/elements/header-popup.html', "Unsuspend Packages") %> + +% if ( $cgi->param('error') ) { + Error: <% $cgi->param('error') %> +

+% } + + + +%# some false laziness w/search/cust_pkg.cgi + + +% for my $param ( +% qw( +% agentnum cust_status cust_main_salesnum salesnum custnum magic status +% custom pkgbatch zip reasonnum +% 477part 477rownum date +% report_option +% ), +% grep { /^location_\w+$/ || /^report_option_any/ } $cgi->param +% ) { + +% } +% +% for my $param (qw( censustract censustract2 ) ) { +% next unless grep { $_ eq $param } $cgi->param; + +% } +% +% for my $param (qw( pkgpart classnum refnum towernum )) { +% foreach my $value ($cgi->param($param)) { + +% } +% } +% +% foreach my $field (qw( setup last_bill bill adjourn susp expire contract_end change_date cancel active )) { +% + "> + "> + "> + "> + "> +% } + +<% ntable('#cccccc') %> + + + + + + +
Confirm Unsuspend Packages
+ +
+ + + + + + +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Bulk change customer packages'); + + diff --git a/httemplate/misc/process/bulk_suspend_pkg.cgi b/httemplate/misc/process/bulk_suspend_pkg.cgi new file mode 100644 index 000000000..2ac9c212f --- /dev/null +++ b/httemplate/misc/process/bulk_suspend_pkg.cgi @@ -0,0 +1,106 @@ +% if ($error) { +<% $cgi->redirect(popurl(2)."bulk_suspend_pkg.cgi?".$cgi->query_string ) %> +% } +<% include('/elements/popup-topreload.html', "Packages Suspended") %> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Bulk change customer packages'); + +my $error; + +if (!$error) { + + my %search_hash = (); + + $search_hash{'query'} = $cgi->param('query'); + + #scalars + for (qw( agentnum cust_status cust_main_salesnum salesnum custnum magic status + custom cust_fields pkgbatch zip reasonnum + 477part 477rownum date + )) + { + $search_hash{$_} = $cgi->param($_) if length($cgi->param($_)); + } + + #arrays + for my $param (qw( pkgpart classnum refnum towernum )) { + $search_hash{$param} = [ $cgi->param($param) ] + if grep { $_ eq $param } $cgi->param; + } + + #scalars that need to be passed if empty + for my $param (qw( censustract censustract2 )) { + $search_hash{$param} = $cgi->param($param) || '' + if grep { $_ eq $param } $cgi->param; + } + + #location flags (checkboxes) + my @loc = grep /^\w+$/, $cgi->param('loc'); + $search_hash{"location_$_"} = 1 foreach @loc; + + my $report_option = $cgi->param('report_option'); + $search_hash{report_option} = $report_option if $report_option; + + for my $param (grep /^report_option_any/, $cgi->param) { + $search_hash{$param} = $cgi->param($param); + } + + ### + # parse dates + ### + + #false laziness w/report_cust_pkg.html and bulk_pkg_increment_bill.cgi + my %disable = ( + 'all' => {}, + 'one-time charge' => { 'last_bill'=>1, 'bill'=>1, 'adjourn'=>1, 'susp'=>1, 'expire'=>1, 'cancel'=>1, }, + 'active' => { 'susp'=>1, 'cancel'=>1 }, + 'suspended' => { 'cancel' => 1 }, + 'cancelled' => {}, + '' => {}, + ); + + foreach my $field (qw( setup last_bill bill adjourn susp expire contract_end change_date cancel active )) { + + $search_hash{$field.'_null'} = scalar( $cgi->param($field.'_null') ); + + my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi, $field); + + next if $beginning == 0 && $ending == 4294967295 + or $disable{$cgi->param('status')}->{$field}; + + $search_hash{$field} = [ $beginning, $ending ]; + + } + + my $sql_query = FS::cust_pkg->search(\%search_hash); + $sql_query->{'select'} = 'cust_pkg.pkgnum'; + + ## set suspend info + $cgi->param('suspend_reasonnum') =~ /^(\d+)$/ or die "Illegal Reason"; + my $suspend_reasonnum = $1; + + my $suspend_date = time; + parse_datetime($cgi->param('suspend_date')) =~ /^(\d+)$/ or die "Illegal date"; + $suspend_date = $1; + + my $suspend_resume_date = ''; + (parse_datetime($cgi->param('suspend_resume_date')) =~ /^(\d+)$/ or die "Illegal resume date") if $cgi->param('suspend_resume_date'); + $suspend_resume_date = $1; + + foreach my $pkgnum (map { $_->pkgnum } qsearch($sql_query)) { + my $cust_pkg = qsearchs('cust_pkg',{'pkgnum'=>$pkgnum}); + + $error = $cust_pkg->suspend('reason' => $suspend_reasonnum, + 'date' => $suspend_date, + 'resume_date' => $suspend_resume_date, + ); + } + +} + +$cgi->param("error", substr($error, 0, 512)); # arbitrary length believed + # suited for all supported + # browsers + \ No newline at end of file diff --git a/httemplate/misc/process/bulk_unsuspend_pkg.cgi b/httemplate/misc/process/bulk_unsuspend_pkg.cgi new file mode 100644 index 000000000..13389f43a --- /dev/null +++ b/httemplate/misc/process/bulk_unsuspend_pkg.cgi @@ -0,0 +1,91 @@ +% if ($error) { +<% $cgi->redirect(popurl(2)."bulk_unsuspend_pkg.cgi?".$cgi->query_string ) %> +% } +<% include('/elements/popup-topreload.html', "Packages Unsuspended") %> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Bulk change customer packages'); + +my $error; +$error = 'Unsuspend packages not confirmed' if !$cgi->param('confirm'); + +if (!$error) { + + my %search_hash = (); + + $search_hash{'query'} = $cgi->param('query'); + + #scalars + for (qw( agentnum cust_status cust_main_salesnum salesnum custnum magic status + custom cust_fields pkgbatch zip reasonnum + 477part 477rownum date + )) + { + $search_hash{$_} = $cgi->param($_) if length($cgi->param($_)); + } + + #arrays + for my $param (qw( pkgpart classnum refnum towernum )) { + $search_hash{$param} = [ $cgi->param($param) ] + if grep { $_ eq $param } $cgi->param; + } + + #scalars that need to be passed if empty + for my $param (qw( censustract censustract2 )) { + $search_hash{$param} = $cgi->param($param) || '' + if grep { $_ eq $param } $cgi->param; + } + + #location flags (checkboxes) + my @loc = grep /^\w+$/, $cgi->param('loc'); + $search_hash{"location_$_"} = 1 foreach @loc; + + my $report_option = $cgi->param('report_option'); + $search_hash{report_option} = $report_option if $report_option; + + for my $param (grep /^report_option_any/, $cgi->param) { + $search_hash{$param} = $cgi->param($param); + } + + ### + # parse dates + ### + + #false laziness w/report_cust_pkg.html and bulk_pkg_increment_bill.cgi + my %disable = ( + 'all' => {}, + 'one-time charge' => { 'last_bill'=>1, 'bill'=>1, 'adjourn'=>1, 'susp'=>1, 'expire'=>1, 'cancel'=>1, }, + 'active' => { 'susp'=>1, 'cancel'=>1 }, + 'suspended' => { 'cancel' => 1 }, + 'cancelled' => {}, + '' => {}, + ); + + foreach my $field (qw( setup last_bill bill adjourn susp expire contract_end change_date cancel active )) { + + $search_hash{$field.'_null'} = scalar( $cgi->param($field.'_null') ); + + my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi, $field); + + next if $beginning == 0 && $ending == 4294967295 + or $disable{$cgi->param('status')}->{$field}; + + $search_hash{$field} = [ $beginning, $ending ]; + + } + + my $sql_query = FS::cust_pkg->search(\%search_hash); + $sql_query->{'select'} = 'cust_pkg.pkgnum'; + + foreach my $pkgnum (map { $_->pkgnum } qsearch($sql_query)) { + my $cust_pkg = qsearchs('cust_pkg',{'pkgnum'=>$pkgnum}); + $error = $cust_pkg->unsuspend; + } + +} + +$cgi->param("error", substr($error, 0, 512)); # arbitrary length believed + # suited for all supported + # browsers + \ No newline at end of file diff --git a/httemplate/search/cust_pkg.cgi b/httemplate/search/cust_pkg.cgi index 2459c44b2..3eb0332d2 100755 --- a/httemplate/search/cust_pkg.cgi +++ b/httemplate/search/cust_pkg.cgi @@ -159,7 +159,7 @@ $search_hash{'query'} = $cgi->keywords; #scalars for (qw( agentnum cust_status cust_main_salesnum salesnum custnum magic status - custom cust_fields pkgbatch zip + reasonnum custom cust_fields pkgbatch zip 477part 477rownum date )) { @@ -270,6 +270,22 @@ my $html_init = sub { 'height' => 210, ). '
'; + $text .= include( '/elements/popup_link.html', + 'label' => emt('Suspend these packages'), + 'action' => "${p}misc/bulk_suspend_pkg.cgi?$query", + 'actionlabel' => emt('Suspend Packages'), + 'width' => 569, + 'height' => 210, + ). '
' if $search_hash{status} eq 'active'; + + $text .= include( '/elements/popup_link.html', + 'label' => emt('Unsuspend these packages'), + 'action' => "${p}misc/bulk_unsuspend_pkg.cgi?$query", + 'actionlabel' => emt('Unsuspend Packages'), + 'width' => 569, + 'height' => 210, + ). '
' if $search_hash{status} eq 'suspended'; + if ( $curuser->access_right('Edit customer package dates') ) { $text .= include( '/elements/popup_link.html', 'label' => emt('Increment next bill date'), diff --git a/httemplate/search/report_cust_pkg.html b/httemplate/search/report_cust_pkg.html index 5e8c429ec..981c54607 100755 --- a/httemplate/search/report_cust_pkg.html +++ b/httemplate/search/report_cust_pkg.html @@ -65,10 +65,29 @@ 'onchange' => 'status_changed(this);', &> + <& /elements/tr-select-reason.html, + 'field' => 'reasonnum', + 'reason_class' => 'S', + 'label' => 'Suspended Reason', + 'label_id' => 'reasonnum_label', + 'hide_addnew' => '1', + 'hide_onload' => '1', + 'cgi' => $cgi, + 'control_button' => 'confirm_suspend_cust_button', + 'pre_options' => [ 0 => 'all' ], + &> +