From: Jonathan Prykop Date: Mon, 11 Apr 2016 12:08:02 +0000 (-0500) Subject: RT#40641: unprovisioning preserved cancelled services X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=5b77b3d0c9aa2d0fa15ca5284d7e34ed68f4ee12 RT#40641: unprovisioning preserved cancelled services --- diff --git a/FS/FS/part_svc.pm b/FS/FS/part_svc.pm index aba3ead40..884e3ad80 100644 --- a/FS/FS/part_svc.pm +++ b/FS/FS/part_svc.pm @@ -586,6 +586,26 @@ sub num_cust_svc { $sth->fetchrow_arrayref->[0]; } +=item num_cust_svc_cancelled + +Returns the number of associated customer services that are +attached to cancelled packages. + +=cut + +sub num_cust_svc_cancelled { + my $self = shift; + my $sth = dbh->prepare( + "SELECT COUNT(*) FROM cust_svc + LEFT JOIN cust_pkg USING ( pkgnum ) + WHERE svcpart = ? + AND cust_pkg.cancel IS NOT NULL" + ) or die dbh->errstr; + $sth->execute($self->svcpart) + or die $sth->errstr; + $sth->fetchrow_arrayref->[0]; +} + =item svc_x Returns a list of associated FS::svc_* records. diff --git a/FS/FS/svc_Common.pm b/FS/FS/svc_Common.pm index dea31ea85..d11b58375 100644 --- a/FS/FS/svc_Common.pm +++ b/FS/FS/svc_Common.pm @@ -1394,11 +1394,17 @@ Parameters: =item order_by +=item cancelled - if true, only returns svcs attached to cancelled pkgs; +if defined and false, only returns svcs not attached to cancelled packages + =back =cut -# svc_broadband::search should eventually use this instead +### Don't call the 'cancelled' option 'Service Status' +### There is no such thing +### See cautionary note in httemplate/browse/part_svc.cgi + sub search { my ($class, $params) = @_; @@ -1502,6 +1508,14 @@ sub search { push @where, "exportnum = $1"; } + if ( defined($params->{'cancelled'}) ) { + if ($params->{'cancelled'}) { + push @where, "cust_pkg.cancel IS NOT NULL"; + } else { + push @where, "cust_pkg.cancel IS NULL"; + } + } + # # sector and tower # my @where_sector = $class->tower_sector_sql($params); # if ( @where_sector ) { diff --git a/httemplate/browse/part_svc.cgi b/httemplate/browse/part_svc.cgi index 88f8d8d19..dee439466 100755 --- a/httemplate/browse/part_svc.cgi +++ b/httemplate/browse/part_svc.cgi @@ -119,9 +119,13 @@ function part_export_areyousure(href) { <% $svcdb %> CLASS="grid" BGCOLOR="<% $bgcolor %>"> - <% $num_active_cust_svc{$part_svc->svcpart} %> <% $num_active_cust_svc{$part_svc->svcpart} ? svc_url( 'ahref' => 1, 'm' => $m, 'action' => 'search', 'part_svc' => $part_svc, 'query' => "svcpart=". $part_svc->svcpart ) : '' %>active - -% if ( $num_active_cust_svc{$part_svc->svcpart} ) { +% my $svcurl_active = svc_url( 'ahref' => 1, 'm' => $m, 'action' => 'search', 'part_svc' => $part_svc, 'query' => "svcpart=". $part_svc->svcpart . "&cancelled=0"); +% my $svcurl_cancel = svc_url( 'ahref' => 1, 'm' => $m, 'action' => 'search', 'part_svc' => $part_svc, 'query' => "svcpart=". $part_svc->svcpart . "&cancelled=1"); + <% $num_cust_svc_active{$part_svc->svcpart} %> <% $num_cust_svc_active{$part_svc->svcpart} ? $svcurl_active : '' %>active<% $num_cust_svc_active{$part_svc->svcpart} ? '' : '' %> +% if ( $num_cust_svc_cancelled{$part_svc->svcpart} ) { +
<% $num_cust_svc_cancelled{$part_svc->svcpart} %> <% $svcurl_cancel %>cancelled +% } +% if ( $num_cust_svc{$part_svc->svcpart} ) {
[ change ] % } @@ -245,11 +249,25 @@ my @part_svc = qsearch('part_svc', \%search ); my $total = scalar(@part_svc); -my %num_active_cust_svc = map { $_->svcpart => $_->num_cust_svc } @part_svc; +## The Active/Cancelled distinction is a bit awkward, +## active currently includes unattached and suspended services, +## but we've previously referred to EVERY existing cust_svc as "Active", +## and we don't really want to know numbers by individual package status, +## so for now the UI will distinguish these as "Active" and "Cancelled", +## but please let's not go so far as to introduce the idea of "Service Status" + +my %num_cust_svc_active; +my %num_cust_svc_cancelled; +my %num_cust_svc; +foreach my $part_svc (@part_svc) { + $num_cust_svc{$part_svc->svcpart} = $part_svc->num_cust_svc; + $num_cust_svc_cancelled{$part_svc->svcpart} = $part_svc->num_cust_svc_cancelled; + $num_cust_svc_active{$part_svc->svcpart} = $num_cust_svc{$part_svc->svcpart} - $num_cust_svc_cancelled{$part_svc->svcpart}; +} if ( $cgi->param('orderby') eq 'active' ) { - @part_svc = sort { $num_active_cust_svc{$b->svcpart} <=> - $num_active_cust_svc{$a->svcpart} } @part_svc; + @part_svc = sort { $num_cust_svc{$b->svcpart} <=> + $num_cust_svc{$a->svcpart} } @part_svc; } elsif ( $cgi->param('orderby') eq 'svc' ) { @part_svc = sort { lc($a->svc) cmp lc($b->svc) } @part_svc; } diff --git a/httemplate/elements/tr-cust_svc_cancel.html b/httemplate/elements/tr-cust_svc_cancel.html index 44276ec82..52dedd6c8 100644 --- a/httemplate/elements/tr-cust_svc_cancel.html +++ b/httemplate/elements/tr-cust_svc_cancel.html @@ -18,7 +18,14 @@ for use in view/cust_main. % } -%# no action links, the service is canceled +%# no action links except unprovision, the service is canceled +% if ( $curuser->access_right('Unprovision customer service') && ! $opt{no_links} ) { + + + ( <% $svc_unprovision_link %> ) + + +% } <%init> my %opt = @_; @@ -29,4 +36,9 @@ my $part_svc = $opt{'part_svc'} || $cust_svc->part_svc; my $cust_pkg = $opt{'cust_pkg'} || $cust_svc->cust_pkg; my $svc_x = $cust_svc->svc_x; +my $svc_unprovision_link = + qq!!.emt('Unprovision').''; + diff --git a/httemplate/search/cust_svc.html b/httemplate/search/cust_svc.html index 3b770432e..7000e3048 100644 --- a/httemplate/search/cust_svc.html +++ b/httemplate/search/cust_svc.html @@ -1,50 +1,63 @@ <& elements/search.html, 'title' => emt('Service search results'), - 'name' => emt('services'), - 'query' => $sql_query, - 'count_query' => $count_query, - 'redirect' => $link, - 'header' => [ emt('#'), - emt('Service'), - # package? - FS::UI::Web::cust_header(), - ], - 'fields' => [ 'svcnum', - sub { - #$_[0]->svc. ': '. $_[0]->label; - my($label, $value, $svcdb) = $_[0]->label; - my $id = $_[0]->agent_svcid - ? $_[0]->agent_svcid.': ' - : ''; - "$label: $id$value"; - }, - # package? - \&FS::UI::Web::cust_fields, - ], - 'links' => [ $link, - $link, - # package? - ( map { $_ ne 'Cust. Status' ? $link_cust : '' } - FS::UI::Web::cust_header() - ), - ], - 'align' => 'rl'. FS::UI::Web::cust_aligns(), - 'color' => [ - '', - '', - FS::UI::Web::cust_colors(), - ], - 'style' => [ - '', - '', - FS::UI::Web::cust_styles(), - ], + 'name' => emt('services'), + 'query' => $sql_query, + 'count_query' => $count_query, + 'redirect' => $link, + 'header' => [ emt('#'), + emt('Service'), + emt('Pkg. Status'), + # package? + FS::UI::Web::cust_header(), + ], + 'fields' => [ 'svcnum', + sub { + #$_[0]->svc. ': '. $_[0]->label; + my($label, $value, $svcdb) = $_[0]->label; + my $id = $_[0]->agent_svcid + ? $_[0]->agent_svcid.': ' + : ''; + "$label: $id$value"; + }, + sub { + $cust_pkg_cache{$_[0]->svcnum} ||= $_[0]->cust_pkg; + $cust_pkg_cache{$_[0]->svcnum}->ucfirst_status + }, + # package? + \&FS::UI::Web::cust_fields, + ], + 'links' => [ $link, + $link, + '', # pkg status + # package? + ( map { $_ ne 'Cust. Status' ? $link_cust : '' } + FS::UI::Web::cust_header() + ), + ], + 'align' => 'rlr'. FS::UI::Web::cust_aligns(), + 'color' => [ + '', + '', + sub { + my $c = FS::cust_pkg::statuscolors; + $c->{$cust_pkg_cache{$_[0]->svcnum}->status }; + }, # pkg status + FS::UI::Web::cust_colors(), + ], + 'style' => [ + '', + '', + 'b', # pkg status + FS::UI::Web::cust_styles(), + ], &> <%init> die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('List services'); +my %cust_pkg_cache; + my $sql_query; my $orderby = 'ORDER BY cust_svc.svcnum'; #has to be ordered by something @@ -83,6 +96,13 @@ if ( length( $cgi->param('search_svc') ) ) { } elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) { push @extra_sql, "svcpart = $1"; + if (defined($cgi->param('cancelled'))) { + if ($cgi->param('cancelled')) { + push @extra_sql, "cust_pkg.cancel IS NOT NULL"; + } else { + push @extra_sql, "cust_pkg.cancel IS NULL"; + } + } } else { errorpage("No search term specified"); diff --git a/httemplate/search/svc_acct.cgi b/httemplate/search/svc_acct.cgi index 58764f881..ef89f01c8 100755 --- a/httemplate/search/svc_acct.cgi +++ b/httemplate/search/svc_acct.cgi @@ -59,6 +59,8 @@ my $curuser = $FS::CurrentUser::CurrentUser; die "access denied" unless $curuser->access_right('List services'); +my %cust_pkg_cache; + my $link = [ "${p}view/svc_acct.cgi?", 'svcnum' ]; my $link_cust = sub { my $svc_acct = shift; @@ -130,6 +132,7 @@ for (qw( towernum sectornum )) { my $timepermonth = ''; my $orderby = 'ORDER BY svcnum'; +my $addl_from = ''; if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) { $search_hash{'unlinked'} = 1 @@ -281,6 +284,9 @@ if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) { } elsif ( $cgi->param('svcpart') ) { $orderby = "ORDER BY uid"; #$orderby = "ORDER BY svcnum"; + if ( defined($cgi->param('cancelled')) ) { + $search_hash{'cancelled'} = $cgi->param('cancelled') ? 1 : 0; + } } else { $orderby = "ORDER BY uid"; @@ -347,6 +353,19 @@ foreach my $pkg_field ( @pkg_fields ) { } +push @header, emt('Pkg. Status'); +push @fields, sub { + $cust_pkg_cache{$_[0]->svcnum} ||= $_[0]->cust_svc->cust_pkg; + $cust_pkg_cache{$_[0]->svcnum}->ucfirst_status; +}; +push @links, ''; +$align .= 'r'; +push @color, sub { + my $c = FS::cust_pkg::statuscolors; + $c->{$cust_pkg_cache{$_[0]->svcnum}->status }; +}; +push @style, 'b'; + push @header, FS::UI::Web::cust_header($cgi->param('cust_fields')); push @fields, \&FS::UI::Web::cust_fields, push @links, map { $_ ne 'Cust. Status' ? $link_cust : '' } @@ -357,6 +376,7 @@ push @style, FS::UI::Web::cust_styles(); $search_hash{'order_by'} = $orderby; $search_hash{'where'} = \@extra_sql; +$search_hash{'addl_from'} = $addl_from; my $sql_query = FS::svc_acct->search(\%search_hash); my $count_query = delete($sql_query->{'count_query'}); diff --git a/httemplate/search/svc_broadband.cgi b/httemplate/search/svc_broadband.cgi index 856197725..6b16ace78 100755 --- a/httemplate/search/svc_broadband.cgi +++ b/httemplate/search/svc_broadband.cgi @@ -10,6 +10,7 @@ 'Router', @tower_header, 'IP Address', + emt('Pkg. Status'), FS::UI::Web::cust_header($cgi->param('cust_fields')), ], 'fields' => [ 'svcnum', @@ -20,6 +21,10 @@ }, @tower_fields, 'ip_addr', + sub { + $cust_pkg_cache{$_[0]->svcnum} ||= $_[0]->cust_svc->cust_pkg; + $cust_pkg_cache{$_[0]->svcnum}->ucfirst_status + }, \&FS::UI::Web::cust_fields, ], 'links' => [ $link, @@ -27,11 +32,12 @@ '', #$link_router, (map '', @tower_fields), $link, + '', # pkg status ( map { $_ ne 'Cust. Status' ? $link_cust : '' } FS::UI::Web::cust_header($cgi->param('cust_fields')) ), ], - 'align' => 'rll'.('r' x @tower_fields).'r'. + 'align' => 'rll'.('r' x @tower_fields).'rr'. FS::UI::Web::cust_aligns(), 'color' => [ '', @@ -39,6 +45,10 @@ '', (map '', @tower_fields), '', + sub { + my $c = FS::cust_pkg::statuscolors; + $c->{$cust_pkg_cache{$_[0]->svcnum}->status }; + }, # pkg status FS::UI::Web::cust_colors(), ], 'style' => [ @@ -47,6 +57,7 @@ '', (map '', @tower_fields), '', + 'b', FS::UI::Web::cust_styles(), ], @@ -56,6 +67,8 @@ die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('List services'); +my %cust_pkg_cache; + my $conf = new FS::Conf; my %search_hash; @@ -68,6 +81,9 @@ if ( $cgi->param('magic') eq 'unlinked' ) { foreach (qw(pkgpart routernum towernum sectornum)) { $search_hash{$_} = [ $cgi->param($_) ] if $cgi->param($_); } + if ( defined($cgi->param('cancelled')) ) { + $search_hash{'cancelled'} = $cgi->param('cancelled') ? 1 : 0; + } } if ( $cgi->param('sortby') =~ /^(\w+)$/ ) { diff --git a/httemplate/search/svc_circuit.cgi b/httemplate/search/svc_circuit.cgi index 8f05e0488..2174734ea 100644 --- a/httemplate/search/svc_circuit.cgi +++ b/httemplate/search/svc_circuit.cgi @@ -10,6 +10,7 @@ 'Termination', 'Circuit ID', 'IP Address', + emt('Pkg. Status'), FS::UI::Web::cust_header($cgi->param('cust_fields')), ], 'fields' => [ 'svcnum', @@ -18,6 +19,10 @@ 'termination', 'circuit_id', 'ip_addr', + sub { + $cust_pkg_cache{$_[0]->svcnum} ||= $_[0]->cust_svc->cust_pkg; + $cust_pkg_cache{$_[0]->svcnum}->ucfirst_status + }, \&FS::UI::Web::cust_fields, ], 'links' => [ $link, @@ -26,15 +31,21 @@ '', $link, $link, + '', # pkg status FS::UI::Web::cust_links($cgi->param('cust_fields')), ], - 'align' => 'rlllll'. FS::UI::Web::cust_aligns(), + 'align' => 'rlllllr'. FS::UI::Web::cust_aligns(), 'color' => [ ('') x 6, + sub { + my $c = FS::cust_pkg::statuscolors; + $c->{$cust_pkg_cache{$_[0]->svcnum}->status }; + }, # pkg status FS::UI::Web::cust_colors(), ], 'style' => [ ('') x 6, + 'b', FS::UI::Web::cust_styles(), ], @@ -44,6 +55,8 @@ die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('List services'); +my %cust_pkg_cache; + my $conf = new FS::Conf; my %search_hash; @@ -56,6 +69,9 @@ if ( $cgi->param('magic') eq 'unlinked' ) { foreach (qw(pkgpart routernum towernum sectornum)) { $search_hash{$_} = [ $cgi->param($_) ] if $cgi->param($_); } + if ( defined($cgi->param('cancelled')) ) { + $search_hash{'cancelled'} = $cgi->param('cancelled') ? 1 : 0; + } } my $query = FS::svc_circuit->search(\%search_hash); diff --git a/httemplate/search/svc_dish.cgi b/httemplate/search/svc_dish.cgi index 1f8cbc395..1e7330804 100755 --- a/httemplate/search/svc_dish.cgi +++ b/httemplate/search/svc_dish.cgi @@ -7,31 +7,42 @@ 'header' => [ '#', 'Service', 'Account #', + emt('Pkg. Status'), FS::UI::Web::cust_header(), ], 'fields' => [ 'svcnum', 'svc', 'acctnum', + sub { + $cust_pkg_cache{$_[0]->svcnum} ||= $_[0]->cust_svc->cust_pkg; + $cust_pkg_cache{$_[0]->svcnum}->ucfirst_status + }, \&FS::UI::Web::cust_fields, ], 'links' => [ $link, $link, $link, + '', # pkg status ( map { $_ ne 'Cust. Status' ? $link_cust : '' } FS::UI::Web::cust_header() ), ], - 'align' => 'rll'. FS::UI::Web::cust_aligns(), + 'align' => 'rllr'. FS::UI::Web::cust_aligns(), 'color' => [ '', '', '', + sub { + my $c = FS::cust_pkg::statuscolors; + $c->{$cust_pkg_cache{$_[0]->svcnum}->status }; + }, # pkg status FS::UI::Web::cust_colors(), ], 'style' => [ '', '', '', + 'b', FS::UI::Web::cust_styles(), ], @@ -41,6 +52,8 @@ die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('List services'); +my %cust_pkg_cache; + #my $conf = new FS::Conf; my $orderby = 'ORDER BY svcnum'; @@ -56,6 +69,13 @@ if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) { } } elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) { push @extra_sql, "svcpart = $1"; + if (defined($cgi->param('cancelled'))) { + if ($cgi->param('cancelled')) { + push @extra_sql, "cust_pkg.cancel IS NOT NULL"; + } else { + push @extra_sql, "cust_pkg.cancel IS NULL"; + } + } } my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '. diff --git a/httemplate/search/svc_domain.cgi b/httemplate/search/svc_domain.cgi index 56cfa30c8..c8fca9fdc 100755 --- a/httemplate/search/svc_domain.cgi +++ b/httemplate/search/svc_domain.cgi @@ -7,31 +7,42 @@ 'header' => [ '#', 'Service', 'Domain', + emt('Pkg. Status'), FS::UI::Web::cust_header(), ], 'fields' => [ 'svcnum', 'svc', 'domain', + sub { + $cust_pkg_cache{$_[0]->svcnum} ||= $_[0]->cust_svc->cust_pkg; + $cust_pkg_cache{$_[0]->svcnum}->ucfirst_status + }, \&FS::UI::Web::cust_fields, ], 'links' => [ $link, $link, $link, + '', # pkg status ( map { $_ ne 'Cust. Status' ? $link_cust : '' } FS::UI::Web::cust_header() ), ], - 'align' => 'rll'. FS::UI::Web::cust_aligns(), + 'align' => 'rllr'. FS::UI::Web::cust_aligns(), 'color' => [ '', '', '', + sub { + my $c = FS::cust_pkg::statuscolors; + $c->{$cust_pkg_cache{$_[0]->svcnum}->status }; + }, # pkg status FS::UI::Web::cust_colors(), ], 'style' => [ '', '', '', + 'b', FS::UI::Web::cust_styles(), ], @@ -41,6 +52,8 @@ die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('List services'); +my %cust_pkg_cache; + my $conf = new FS::Conf; my $orderby = 'ORDER BY svcnum'; @@ -58,6 +71,13 @@ if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) { } elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) { push @extra_sql, "svcpart = $1"; + if (defined($cgi->param('cancelled'))) { + if ($cgi->param('cancelled')) { + push @extra_sql, "cust_pkg.cancel IS NOT NULL"; + } else { + push @extra_sql, "cust_pkg.cancel IS NULL"; + } + } } else { $cgi->param('domain') =~ /^([\w\-\.]+)$/; $svc_domain{'domain'} = $1; diff --git a/httemplate/search/svc_external.cgi b/httemplate/search/svc_external.cgi index b282939a7..5f9056165 100755 --- a/httemplate/search/svc_external.cgi +++ b/httemplate/search/svc_external.cgi @@ -8,29 +8,39 @@ 'Service', ( FS::Msgcat::_gettext('svc_external-id') || 'External ID' ), ( FS::Msgcat::_gettext('svc_external-title') || 'Title' ), + emt('Pkg. Status'), FS::UI::Web::cust_header(), ], 'fields' => [ 'svcnum', 'svc', 'id', 'title', + sub { + $cust_pkg_cache{$_[0]->svcnum} ||= $_[0]->cust_svc->cust_pkg; + $cust_pkg_cache{$_[0]->svcnum}->ucfirst_status + }, \&FS::UI::Web::cust_fields, ], 'links' => [ $link, $link, $link, $link, + '', # pkg status ( map { $_ ne 'Cust. Status' ? $link_cust : '' } FS::UI::Web::cust_header() ), ], - 'align' => 'rlrr'. + 'align' => 'rlrrr'. FS::UI::Web::cust_aligns(), 'color' => [ '', '', '', '', + sub { + my $c = FS::cust_pkg::statuscolors; + $c->{$cust_pkg_cache{$_[0]->svcnum}->status }; + }, # pkg status FS::UI::Web::cust_colors(), ], 'style' => [ @@ -38,6 +48,7 @@ '', '', '', + 'b', FS::UI::Web::cust_styles(), ], @@ -47,6 +58,8 @@ die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('List services'); +my %cust_pkg_cache; + my $conf = new FS::Conf; my %svc_external; @@ -69,6 +82,13 @@ if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) { } elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) { push @extra_sql, "svcpart = $1"; + if (defined($cgi->param('cancelled'))) { + if ($cgi->param('cancelled')) { + push @extra_sql, "cust_pkg.cancel IS NOT NULL"; + } else { + push @extra_sql, "cust_pkg.cancel IS NULL"; + } + } } elsif ( $cgi->param('title') =~ /^(.*)$/ ) { diff --git a/httemplate/search/svc_fiber.html b/httemplate/search/svc_fiber.html index 0cb735c96..3960a1635 100644 --- a/httemplate/search/svc_fiber.html +++ b/httemplate/search/svc_fiber.html @@ -10,6 +10,7 @@ 'ONT', 'Model', 'Serial', + emt('Pkg. Status'), FS::UI::Web::cust_header($cgi->param('cust_fields')), ], 'fields' => [ 'svcnum', @@ -20,6 +21,10 @@ 'ont_id', 'ont_description', 'ont_serial', + sub { + $cust_pkg_cache{$_[0]->svcnum} ||= $_[0]->cust_svc->cust_pkg; + $cust_pkg_cache{$_[0]->svcnum}->ucfirst_status + }, \&FS::UI::Web::cust_fields, ], 'links' => [ $link, @@ -28,15 +33,21 @@ $link, $link, $link, + '', # pkg status FS::UI::Web::cust_links($cgi->param('cust_fields')), ], - 'align' => 'rlllll'. FS::UI::Web::cust_aligns(), + 'align' => 'rlllllr'. FS::UI::Web::cust_aligns(), 'color' => [ ('') x 6, + sub { + my $c = FS::cust_pkg::statuscolors; + $c->{$cust_pkg_cache{$_[0]->svcnum}->status }; + }, # pkg status FS::UI::Web::cust_colors(), ], 'style' => [ ('') x 6, + 'b', FS::UI::Web::cust_styles(), ], @@ -48,6 +59,8 @@ die "access denied" unless 'List services' ]); +my %cust_pkg_cache; + my $conf = new FS::Conf; my %search_hash; @@ -58,6 +71,9 @@ if ( $cgi->param('magic') eq 'unlinked' ) { ont_typenum oltnum shelf olt_port card vlan )) { $search_hash{$_} = $cgi->param($_) if defined($cgi->param($_)); } + if ( defined($cgi->param('cancelled')) ) { + $search_hash{'cancelled'} = $cgi->param('cancelled') ? 1 : 0; + } } my $query = FS::svc_fiber->search(\%search_hash); diff --git a/httemplate/search/svc_forward.cgi b/httemplate/search/svc_forward.cgi index 6a23bb3bb..ca2c28808 100755 --- a/httemplate/search/svc_forward.cgi +++ b/httemplate/search/svc_forward.cgi @@ -8,28 +8,38 @@ 'Service', 'Mail to', 'Forwards to', + emt('Pkg. Status'), FS::UI::Web::cust_header(), ], 'fields' => [ 'svcnum', 'svc', $format_src, $format_dst, + sub { + $cust_pkg_cache{$_[0]->svcnum} ||= $_[0]->cust_svc->cust_pkg; + $cust_pkg_cache{$_[0]->svcnum}->ucfirst_status + }, \&FS::UI::Web::cust_fields, ], 'links' => [ $link, $link, $link_src, $link_dst, + '', # pkg status ( map { $_ ne 'Cust. Status' ? $link_cust : '' } FS::UI::Web::cust_header() ), ], - 'align' => 'rlll'. FS::UI::Web::cust_aligns(), + 'align' => 'rlllr'. FS::UI::Web::cust_aligns(), 'color' => [ '', '', '', '', + sub { + my $c = FS::cust_pkg::statuscolors; + $c->{$cust_pkg_cache{$_[0]->svcnum}->status }; + }, # pkg status FS::UI::Web::cust_colors(), ], 'style' => [ @@ -37,6 +47,7 @@ '', '', '', + 'b', FS::UI::Web::cust_styles(), ], @@ -46,6 +57,8 @@ die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('List services'); +my %cust_pkg_cache; + my $conf = new FS::Conf; my $orderby = 'ORDER BY svcnum'; @@ -62,6 +75,13 @@ if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) { } elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) { push @extra_sql, "svcpart = $1"; + if (defined($cgi->param('cancelled'))) { + if ($cgi->param('cancelled')) { + push @extra_sql, "cust_pkg.cancel IS NOT NULL"; + } else { + push @extra_sql, "cust_pkg.cancel IS NULL"; + } + } } my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '. diff --git a/httemplate/search/svc_hardware.cgi b/httemplate/search/svc_hardware.cgi index 93fc2c391..78f413e30 100644 --- a/httemplate/search/svc_hardware.cgi +++ b/httemplate/search/svc_hardware.cgi @@ -12,6 +12,7 @@ 'Hardware addr.', 'IP addr.', 'Smartcard', + emt('Pkg. Status'), FS::UI::Web::cust_header(), ], 'fields' => [ 'svcnum', @@ -22,24 +23,36 @@ 'display_hw_addr', 'ip_addr', 'smartcard', + sub { + $cust_pkg_cache{$_[0]->svcnum} ||= $_[0]->cust_svc->cust_pkg; + $cust_pkg_cache{$_[0]->svcnum}->ucfirst_status + }, \&FS::UI::Web::cust_fields, ], 'links' => [ ($link_svc) x 8, + '', # pkg status ( map { $_ ne 'Cust. Status' ? $link_cust : '' } FS::UI::Web::cust_header() ) ], - 'align' => 'rlllllll' . FS::UI::Web::cust_aligns(), + 'align' => 'rlllllllr' . FS::UI::Web::cust_aligns(), 'color' => [ ('') x 8, - FS::UI::Web::cust_colors() ], + sub { + my $c = FS::cust_pkg::statuscolors; + $c->{$cust_pkg_cache{$_[0]->svcnum}->status }; + }, # pkg status + FS::UI::Web::cust_colors() ], 'style' => [ $svc_cancel_style, ('') x 7, - FS::UI::Web::cust_styles() ], + 'b', + FS::UI::Web::cust_styles() ], &> <%init> die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('List services'); +my %cust_pkg_cache; + my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) LEFT JOIN part_svc USING ( svcpart ) @@ -93,6 +106,13 @@ if ( $cgi->param('typenum') =~ /^(\d+)$/ ) { if ( $cgi->param('svcpart') =~ /^(\d+)$/ ) { push @extra_sql, "cust_svc.svcpart = $1"; + if (defined($cgi->param('cancelled'))) { + if ($cgi->param('cancelled')) { + push @extra_sql, "cust_pkg.cancel IS NOT NULL"; + } else { + push @extra_sql, "cust_pkg.cancel IS NULL"; + } + } } my ($orderby) = $cgi->param('orderby') =~ /^(\w+( ASC| DESC)?)$/i; diff --git a/httemplate/search/svc_phone.cgi b/httemplate/search/svc_phone.cgi index f3a056475..29e745690 100644 --- a/httemplate/search/svc_phone.cgi +++ b/httemplate/search/svc_phone.cgi @@ -9,6 +9,7 @@ 'Country code', 'Phone number', @header, + emt('Pkg. Status'), FS::UI::Web::cust_header($cgi->param('cust_fields')), ], 'fields' => [ 'svcnum', @@ -16,6 +17,10 @@ 'countrycode', 'phonenum', @fields, + sub { + $cust_pkg_cache{$_[0]->svcnum} ||= $_[0]->cust_svc->cust_pkg; + $cust_pkg_cache{$_[0]->svcnum}->ucfirst_status + }, \&FS::UI::Web::cust_fields, ], 'links' => [ $link, @@ -23,12 +28,14 @@ $link, $link, ( map '', @header ), + '', # pkg status ( map { $_ ne 'Cust. Status' ? $link_cust : '' } FS::UI::Web::cust_header($cgi->param('cust_fields')) ), ], 'align' => 'rlrr'. join('', map 'r', @header). + 'r'. FS::UI::Web::cust_aligns(), 'color' => [ '', @@ -36,6 +43,10 @@ '', '', ( map '', @header ), + sub { + my $c = FS::cust_pkg::statuscolors; + $c->{$cust_pkg_cache{$_[0]->svcnum}->status }; + }, # pkg status FS::UI::Web::cust_colors(), ], 'style' => [ @@ -44,6 +55,7 @@ '', '', ( map '', @header ), + 'b', FS::UI::Web::cust_styles(), ], @@ -53,6 +65,8 @@ die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('List services'); +my %cust_pkg_cache; + my $conf = new FS::Conf; my @select = (); @@ -132,6 +146,9 @@ if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) { } elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) { $search_hash{'svcpart'} = [ $1 ]; + if ( defined($cgi->param('cancelled')) ) { + $search_hash{'cancelled'} = $cgi->param('cancelled') ? 1 : 0; + } } else { $cgi->param('phonenum') =~ /^([\d\- ]+)$/; my $phonenum = $1; diff --git a/httemplate/search/svc_www.cgi b/httemplate/search/svc_www.cgi index 7410262e8..4f6611f17 100755 --- a/httemplate/search/svc_www.cgi +++ b/httemplate/search/svc_www.cgi @@ -8,6 +8,7 @@ 'Service', 'Zone', 'User', + emt('Pkg. Status'), FS::UI::Web::cust_header(), ], 'fields' => [ 'svcnum', @@ -20,22 +21,31 @@ ? $svc_acct->email : ''; }, + sub { + $cust_pkg_cache{$_[0]->svcnum} ||= $_[0]->cust_svc->cust_pkg; + $cust_pkg_cache{$_[0]->svcnum}->ucfirst_status + }, \&FS::UI::Web::cust_fields, ], 'links' => [ $link, $link, '', $ulink, + '', # pkg status ( map { $_ ne 'Cust. Status' ? $link_cust : '' } FS::UI::Web::cust_header() ), ], - 'align' => 'rlll'. FS::UI::Web::cust_aligns(), + 'align' => 'rlllr'. FS::UI::Web::cust_aligns(), 'color' => [ '', '', '', '', + sub { + my $c = FS::cust_pkg::statuscolors; + $c->{$cust_pkg_cache{$_[0]->svcnum}->status }; + }, # pkg status FS::UI::Web::cust_colors(), ], 'style' => [ @@ -43,6 +53,7 @@ '', '', '', + 'b', FS::UI::Web::cust_styles(), ], @@ -52,6 +63,8 @@ die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('List services'); +my %cust_pkg_cache; + #my $conf = new FS::Conf; my $orderby = 'ORDER BY svcnum'; @@ -68,6 +81,13 @@ if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) { } elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) { push @extra_sql, "svcpart = $1"; + if (defined($cgi->param('cancelled'))) { + if ($cgi->param('cancelled')) { + push @extra_sql, "cust_pkg.cancel IS NOT NULL"; + } else { + push @extra_sql, "cust_pkg.cancel IS NULL"; + } + } } my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '. diff --git a/httemplate/view/elements/svc_edit_link.html b/httemplate/view/elements/svc_edit_link.html index 3ff2f58b6..2de5ecf9c 100644 --- a/httemplate/view/elements/svc_edit_link.html +++ b/httemplate/view/elements/svc_edit_link.html @@ -1,18 +1,18 @@ -% if ( $cancel_date ) { -<% mt("Canceled [_1]", time2str('%b %o %Y', $cancel_date) ) |h %> -% } else { +% if ( $cancel_date ) { +| <% mt("Canceled [_1]", time2str('%b %o %Y', $cancel_date) ) |h %> +% } else { % if ( $curuser->access_right('Provision customer service') ) { | <% mt("Edit this [_1]", $label) |h %> % } -% if ( $curuser->access_right('Unprovision customer service') ) { +% } +% if ( $curuser->access_right('Unprovision customer service') ) { | <% mt('Unprovision this Service') |h %> -% } % } <& /elements/manage_device_link.html, 'svc' => $svc_x,