From 0eedfd553057f9fd8d69197675f33dbc893e6c51 Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Fri, 5 Dec 2014 18:21:48 -0800 Subject: 477 report: detect errors and fix them more easily, #32499, from #24047 --- httemplate/edit/cust_location-censustract.html | 66 ++++++ httemplate/edit/process/bulk-477_cust_pkg.html | 20 ++ .../edit/process/cust_location-censustract.html | 34 +++ httemplate/search/477.html | 46 ++++- httemplate/search/477_cust_pkg.html | 228 +++++++++++++++++++++ 5 files changed, 389 insertions(+), 5 deletions(-) create mode 100644 httemplate/edit/cust_location-censustract.html create mode 100644 httemplate/edit/process/bulk-477_cust_pkg.html create mode 100644 httemplate/edit/process/cust_location-censustract.html create mode 100644 httemplate/search/477_cust_pkg.html (limited to 'httemplate') diff --git a/httemplate/edit/cust_location-censustract.html b/httemplate/edit/cust_location-censustract.html new file mode 100644 index 000000000..bdb9823fa --- /dev/null +++ b/httemplate/edit/cust_location-censustract.html @@ -0,0 +1,66 @@ +<% include('/elements/header-popup.html', "Edit Census Tract") %> + +<% include('/elements/error.html') %> + +
+ + +<% ntable('#cccccc') %> +<& /elements/location.html, + 'object' => $cust_location, + 'no_asterisks' => 1, + 'enable_censustract' => 1, + 'disabled' => 'DISABLED', +&> +<& /elements/standardize_locations.html, + 'form' => 'EditLocationForm', + 'callback' => 'document.EditLocationForm.submit();', + 'with_census' => 1, + 'with_census_functions' => 1, +&> + + +
+ + +
+ + + +<%init> + +my $conf = new FS::Conf; + +my $curuser = $FS::CurrentUser::CurrentUser; + +# it's the same access right you'd need to do this by editing packages +die "access denied" + unless $curuser->access_right('Change customer package'); + +my $locationnum = scalar($cgi->param('locationnum')); +my $cust_location = qsearchs({ + 'select' => 'cust_location.*', + 'table' => 'cust_location', + 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )', + 'hashref' => { 'locationnum' => $locationnum }, + 'extra_sql' => ' AND '. $curuser->agentnums_sql, + }) or die "unknown locationnum $locationnum"; + +# unlike the regular one, this allows editing disabled locations + +my $cust_main = qsearchs('cust_main', { 'custnum' => $cust_location->custnum }) + or die "can't get cust_main record for custnum ". $cust_location->custnum; + + diff --git a/httemplate/edit/process/bulk-477_cust_pkg.html b/httemplate/edit/process/bulk-477_cust_pkg.html new file mode 100644 index 000000000..064f73b60 --- /dev/null +++ b/httemplate/edit/process/bulk-477_cust_pkg.html @@ -0,0 +1,20 @@ +<% $cgi->redirect($fsurl.'search/477_cust_pkg.html?redirect='.$session) %> +<%init> +my $curuser = $FS::CurrentUser::CurrentUser; +my $edit_acl = $curuser->access_right('Edit FCC report configuration'); +my $global_edit_acl = $curuser->access_right('Edit FCC report configuration for all agents'); +die "access denied" unless $edit_acl or $global_edit_acl; + +my %error; +foreach my $param ($cgi->param) { + $param =~ /^pkgnum(\d+)pkgpart(\d+)$/ or next; + my $pkgpart = $2; + my $part_pkg = FS::part_pkg->by_key($pkgpart); + my $hashref = decode_json( $cgi->param($param) ); + my $error = $part_pkg->set_fcc_options($hashref); + $error{$pkgpart} = $error if $error; # XXX report this somehow +} + +my $session = $cgi->param('redirect'); + + diff --git a/httemplate/edit/process/cust_location-censustract.html b/httemplate/edit/process/cust_location-censustract.html new file mode 100644 index 000000000..bc9cd4f31 --- /dev/null +++ b/httemplate/edit/process/cust_location-censustract.html @@ -0,0 +1,34 @@ +% if ($error) { +% $cgi->param('error', $error); +% $cgi->redirect(popurl(3). 'edit/cust_location-censustract.html?'. $cgi->query_string ); +% } else { + + <% header("Census tract changed") %> + + + + +% } +<%init> + +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access denied" + unless $curuser->access_right('Change customer package'); + +my $locationnum = $cgi->param('locationnum'); +my $cust_location = qsearchs({ + 'select' => 'cust_location.*', + 'table' => 'cust_location', + 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )', + 'hashref' => { 'locationnum' => $locationnum }, + 'extra_sql' => ' AND '. $curuser->agentnums_sql, +}); +die "unknown locationnum $locationnum" unless $cust_location; + +$cust_location->set('censustract', $cgi->param('censustract')); +my $error = $cust_location->replace; + + diff --git a/httemplate/search/477.html b/httemplate/search/477.html index ff2ac8638..2e9f9428e 100644 --- a/httemplate/search/477.html +++ b/httemplate/search/477.html @@ -32,26 +32,54 @@ table.fcc477part thead tr.subhead { font-size: large; float: left; } +.errortitle { + font-weight: bold; + color: #ff0000; +} +tr.error td { + background-color: #ffdddd; +} +tr.error td.error { + text-align: left; + border: none; +} +tr.error ul { + margin: 0px; + list-style-image: url("<% $fsurl %>images/cross.png"); +} a.download { float: right; } % foreach my $partname (@partnames) { +% my $this_part = $parts{$partname}; % $cgi->param('parts', $partname); % $cgi->param('type', 'csv'); % my $header = ".header_$partname"; -% my $data = $parts{$partname}; +% my $data = $this_part->{data}; +% my $error = $this_part->{error}; <& $header &> % my $rownum = 0; % foreach my $row (@$data) { - +% my %eh; # error hash +% if ( $error->[$rownum] ) { +% %eh = %{ $error->[$rownum] }; +% } + > % my $first = 1; % foreach my $item (@$row) { % } #foreach $item +% # display errors +% if ( keys %eh ) { + +% } # if there are errors % $rownum++; % } #foreach $row @@ -98,10 +134,10 @@ foreach my $partname (@partnames) { date => $date, agentnum => $agentnum, ignore_quantity => $ignore_quantity, - ); + ); # includes error, detail, and data parts my $detail_table = FS::Report::FCC_477->part_table($partname); if ($detail_table eq 'cust_pkg') { - my $link = popurl(1).'cust_pkg.cgi?477part='.$partname.";date=$date;"; + my $link = popurl(1).'477_cust_pkg.html?477part='.$partname.";date=$date;"; if ($agentnum) { $link .= "agentnum=$agentnum;"; } @@ -114,7 +150,7 @@ my $title = 'FCC Form 477 Data - ' . time2str('%b %o, %Y', $date); if ( $cgi->param('type') eq 'csv' ) { my $partname = $partnames[0]; # ignore any beyond the first - my $data = $parts{$partname}; + my $data = $parts{$partname}->{data}; my $csv = Text::CSV_XS->new({ eol => "\r\n" }); # i think my $filename = time2str('%Y-%m-%d', $date) . '-'. $partname . '.csv'; diff --git a/httemplate/search/477_cust_pkg.html b/httemplate/search/477_cust_pkg.html new file mode 100644 index 000000000..b8df9fd0f --- /dev/null +++ b/httemplate/search/477_cust_pkg.html @@ -0,0 +1,228 @@ +<& elements/search.html, + 'html_init' => $html_init, + 'html_form' => $html_form, + 'html_foot' => '', + 'title' => emt('Package Search Results'), + 'name' => 'packages', + 'query' => $query, + 'count_query' => $count_query, + 'header' => [ emt('#'), + emt('Quan.'), + emt('Package'), + emt('Class'), + emt('Status'), + emt('Freq.'), + emt('Setup'), + emt('Next bill'), + emt('Susp.'), + emt('Changed'), + emt('Cancel'), + FS::UI::Web::cust_header(), + emt('Census tract'), + emt('Package options'), + ], + 'fields' => [ + 'pkgnum', + 'quantity', + sub { $_[0]->pkg; }, + 'classname', + sub { ucfirst(shift->status); }, + sub { FS::part_pkg::freq_pretty(shift); }, + + ( map { time_or_blank($_) } + qw( setup bill susp change_date cancel ) ), + + \&FS::UI::Web::cust_fields, + + sub { # census tract + my $cust_pkg = shift; + my $cust_location = $cust_pkg->cust_location; + ($cust_location->censustract || 'unknown'). + ' (edit)'; + }, + + # a hidden input in each row with the pkgnum, so that + # we can refresh back to this list of pkgnums + sub { + my $cust_pkg = shift; + my $part_pkg = $cust_pkg->part_pkg; + my %hash = $part_pkg->fcc_options; + '' . + include('/elements/input-fcc_options.html', + id => 'pkgnum'.$cust_pkg->pkgnum. + 'pkgpart'.$part_pkg->pkgpart, + curr_value => encode_json(\%hash), + html_only => 1 + ) + }, + ], + 'color' => [ + '', + '', + '', + '', + sub { shift->statuscolor; }, + '', '', '', '', '', '', + FS::UI::Web::cust_colors(), + '', + '', + ], + 'style' => [ '', '', '', '', 'b', + '', '', '', '', '', '', + FS::UI::Web::cust_styles() ], + 'size' => [ '', '', '', '', '-1' ], + 'align' => 'rrlcccrrrrr'. FS::UI::Web::cust_aligns(). 'cl', + 'links' => [ + $link, + $link, + $link, + '', '', '', '', '', '', '', '', + ( map { $_ ne 'Cust. Status' ? $clink : '' } + FS::UI::Web::cust_header() + ), + '', + '', + ], + 'link_onclicks' => [ + (('') x 11), + (map { '' } FS::UI::Web::cust_header()), + $pkg_edit_location_link, + '', + ], + +&> +<%init> + +my $curuser = $FS::CurrentUser::CurrentUser; +my $edit = 'Edit FCC report configuration'; +my $edit_global = 'Edit FCC report configuration for all agents'; +my $acl_edit = $curuser->access_right($edit); +my $acl_edit_global = $curuser->access_right($edit_global); + +die "access denied" + unless $acl_edit || $acl_edit_global; + +my $conf = new FS::Conf; + +my $session; + +my ($query, $count_query); + +if ( $cgi->param('redirect') ) { # then restore the pkgnum list + $session = $cgi->param('redirect'); + my $pref = $curuser->option("redirect$session"); # contains a list of pkgnums + die "unknown redirect session $session\n" unless length($pref); + my @pkgnums = grep /^\d+$/, split(',', $pref); + + $query = FS::cust_pkg->search({}); + $count_query = delete($query->{count_query}); + + my $where = "cust_pkg.pkgnum IN (".join(',', @pkgnums).")"; + if ( $count_query =~ /WHERE/i ) { + $where = " AND ($where) "; + } else { + $where = " WHERE ($where) "; + } + $query->{extra_sql} .= $where; + $count_query .= $where; +} else { + # build and run the query right now, and then cache the pkgnums it returned + my %search_hash = (); + + #scalars + for (qw( agentnum 477part 477rownum date )) { + $search_hash{$_} = $cgi->param($_) if length($cgi->param($_)); + } + + $query = FS::cust_pkg->search(\%search_hash); + $count_query = delete($query->{'count_query'}); + + my @cust_pkg = qsearch($query); + + my $pkgnums = join(',', map { $_->pkgnum } @cust_pkg); + $session = int(rand(4294967296)); #XXX + my $pref = new FS::access_user_pref({ + 'usernum' => $FS::CurrentUser::CurrentUser->usernum, + 'prefname' => "redirect$session", + 'prefvalue' => $pkgnums, + 'expiration' => time + 3600, #1h? 1m? + }); + my $pref_error = $pref->insert; + if ($pref_error) { + die "couldn't even set redirect cookie: $pref_error\n"; + } + + # and then bail out and reload using the redirect cookie + $cgi->delete_all(); + $cgi->param("redirect", $session); + $m->clear_buffer; + $m->print( $cgi->redirect($cgi->self_url) ); + $m->abort; +} + +my $show = $curuser->default_customer_view =~ /^(jumbo|packages)$/ + ? '' + : ';show=packages'; + +my $link = sub { + my $self = shift; + my $frag = 'cust_pkg'. $self->pkgnum; #hack for IE ignoring real #fragment + [ "${p}view/cust_main.cgi?custnum=".$self->custnum. + "$show;fragment=$frag#cust_pkg", + 'pkgnum' + ]; +}; + +my $html_init = + include('/elements/init_overlib.html') . + include('/elements/input-fcc_options.html', js_only => 1) . + include('.style') . + include('.script'); + +my $clink = sub { + my $cust_pkg = shift; + $cust_pkg->cust_main_custnum + ? [ "${p}view/cust_main.cgi?", 'custnum' ] + : ''; +}; + +my $html_form = qq! + + +!; + +my $pkg_edit_location_link = sub { + my $cust_pkg = shift; + my $locationnum = $cust_pkg->locationnum; + include('/elements/popup_link_onclick.html', + 'action' => $p. "edit/cust_location-censustract.html?locationnum=$locationnum", + 'actionlabel' => emt('Edit census tract'), + 'width' => 700, + 'height' => 355, + ); +}; + +sub time_or_blank { + my $column = shift; + return sub { + my $record = shift; + my $value = $record->get($column); #mmm closures + $value ? time2str('%b %d %Y', $value ) : ''; + }; +} + + +<%def .style> + + +<%def .script> + + -- cgit v1.2.1
<% $part_titles->{$partname} %> +% if ( $this_part->{num_errors} > 0 ) { +% # disable downloading while it contains errors + + <% emt('This section contains [quant,_1,error].', $this_part->{num_errors}) %> + +% } else { Download +% }
@@ -63,6 +91,14 @@ a.download { % }
    +% foreach my $key (sort keys %eh) { +
  • <% $eh{$key} %>
  • +% } +