-% unless ( $type eq 'xml' ) {
-<% include( '/elements/header.html', 'FCC Form 477 Results') %>
-%}else{
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<Form_477_submission xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://specialreports.fcc.gov/wcb/Form477/XMLSchema-instance/form_477_upload_Schema.xsd" >
-%}
-% if ( $type eq 'html' || $type eq 'html-print' ) {
-<TABLE WIDTH="100%">
- <TR><TD></TD>
-%}elsif ( $type eq 'xml' ) {
-%}
-% unless ( $type eq 'html-print' || $type eq 'xml' ) {
+<& /elements/header.html, $title &>
+<STYLE TYPE="text/css">
+table.fcc477part {
+ border-collapse: collapse;
+ border: 1px #777 solid;
+ margin-bottom: 20px;
+}
+table.fcc477part td {
+ padding: 0px 4px;
+ border-left: 1px #777 solid;
+ border-right: 1px #777 solid;
+}
+table.fcc477part tbody td {
+ text-align: right;
+}
+table.fcc477part thead tr.head {
+ text-align: center;
+ vertical-align: top;
+ font-weight: bold;
+ border-top: 1px #777 solid;
+ border-bottom: 1px #777 solid;
+}
+table.fcc477part thead tr.subhead {
+ text-align: center;
+ font-weight: bold;
+ font-size: small;
+ border-top: 1px #777 solid;
+ border-bottom: 1px #777 solid;
+}
+.parttitle {
+ font-weight: bold;
+ font-size: large;
+ float: left;
+}
+a.download {
+ float: right;
+}
+</STYLE>
+% foreach my $partnum (@partnums) {
+% $cgi->param('parts', $partnum);
+% $cgi->param('type', 'csv');
+<table class="fcc477part">
+ <caption>
+ <span class="parttitle">Part <% $partnum %></span>
+ <a class="download" href="<% $cgi->self_url %>">Download</a>
+ </caption>
+% my $header = ".header$partnum";
+% my $data = $parts{$partnum};
+ <thead>
+ <& $header &>
+ </thead>
+% #XXX column headings
+% foreach my $row (@$data) {
+ <tr>
+% foreach my $item (@$row) {
+ <td><% $item %></td>
+% }
+ </tr>
+% }
+</table>
+% } # foreach $partnum
+<& /elements/footer.html &>
+<%init>
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List packages');
- <TD ALIGN="right">
+my %parts;
+# load from cache if possible
+my $session;
+if ( $cgi->param('session') =~ /^(\d+)$/ ) {
+ $session = $1;
+ %parts = %{ $m->cache->get($session) };
+} else {
+ $session = sprintf('%010d%06d', time, int(rand(1000000)));
+ $cgi->param('session', $session);
+}
- Download full results<BR>
-% $cgi->param('_type', 'xml');
- as <A HREF="<% $cgi->self_url %>">XML file</A><BR>
+my $agentnum;
+if ($cgi->param('agentnum') =~ /^(\d+)$/ ) {
+ $agentnum = $1;
+}
+my $date = parse_datetime($cgi->param('date')) || time;
+my @partnums = grep /^\d+$/, $cgi->param('parts');
+foreach my $partnum (@partnums) {
+ my $method = "part$partnum";
+ $parts{$partnum} ||= FS::Report::FCC_477->$method(
+ date => $date,
+ agentnum => $agentnum
+ );
+}
+$m->cache->set($session, \%parts, '1h');
-% $cgi->param('_type', 'html-print');
- as <A HREF="<% $cgi->self_url %>">printable copy</A>
+my $title = 'FCC Form 477 Data - ' . time2str('%b %o, %Y', $date);
- </TD>
-% $cgi->param('_type', $type );
-% }
-% if ( $type eq 'html' || $type eq 'html-print' ) {
- </TR>
-</TABLE>
-%}elsif ( $type eq 'xml' ) {
-%}
-% foreach my $part ( @parts ) {
-% if ( $part{$part} ) {
-%
-% if ( $part eq 'V' ) {
-% next unless ( $part{'IIA'} || $part{'IIB'} );
-% }
-%
-% if ( $part eq 'VI_census' ) {
-% next unless $part{'IA'};
-% }
-%
-% my @reports = ();
-% if ( $part eq 'IA' ) {
-% for ( my $tech = 0; $tech < scalar(@technology_option); $tech++ ) {
-% next unless $technology_option[$tech];
-% my $url = &{$url_mangler}($part);
-% if ( $type eq 'xml' ) {
-<<% 'Part_IA_'. chr(65 + $tech) %>>
-% }
-<% include( "477part${part}_summary.html", 'tech_code' => $tech, 'url' => $url ) %>
-<% include( "477part${part}_detail.html", 'tech_code' => $tech, 'url' => $url ) %>
-% if ( $type eq 'xml' ) {
-</<% 'Part_IA_'. chr(65 + $tech) %>>
-% }
-% }
-% } else {
-% if ( $type eq 'xml' ) {
-<<% 'Part_'. $part %>>
-% }
-% my $url = &{$url_mangler}($part);
-<% include( "477part${part}.html", 'url' => $url ) %>
-% if ( $type eq 'xml' ) {
-</<% 'Part_'. $part %>>
-% }
-% }
-% }
-% }
-%
-% if ( $type eq 'html' || $type eq 'html-print' ) {
-<% include( '/elements/footer.html') %>
-%}elsif ( $type eq 'xml' ) {
-</Form_477_submission>
-%}
-<%init>
+if ( $cgi->param('type') eq 'csv' ) {
+ my $partnum = $partnums[0]; # ignore any beyond the first
+ my $data = $parts{$partnum};
+ my $csv = Text::CSV_XS->new({ eol => "\r\n" }); # i think
-my $curuser = $FS::CurrentUser::CurrentUser;
+ my $filename = time2str('%Y-%m-%d', $date) . '-part' . $partnum . '.csv';
+ http_header('Content-Type' => 'text/csv');
+ http_header('Content-Disposition' => qq(attachment;filename="$filename"));
-die "access denied"
- unless $curuser->access_right('List packages');
+ $m->clear_buffer;
-my %part = map { $_ => 1 } grep { /^\w+$/ } $cgi->param('part');
-my $type = $cgi->param('_type') || 'html';
-my $xlsname = '477report';
-my @technology_option = &FS::Report::FCC_477::parse_technology_option($cgi);
-my $url_mangler = sub {
- my $part = shift;
- my $url = $cgi->url('-path_info' => 1, '-full' => 1);
- $url =~ s/477\./477part$part./;
- $url;
-};
-my @parts = qw( IA IIA IIB IV V VI_census );
+ foreach my $row (@$data) {
+ $csv->combine(@$row);
+ $m->print($csv->string);
+ }
+ $m->abort;
+}
</%init>
+<%def .header6>
+ <TR CLASS="head">
+ <TD ROWSPAN=2>Census Tract</TD>
+ <TD ROWSPAN=2>Technology</TD>
+ <TD COLSPAN=2>Speed (Mbps)</TD>
+ <TD COLSPAN=2>Subscriptions</TD>
+ </TR>
+ <TR CLASS="subhead">
+ <TD>Down</TD>
+ <TD>Up</TD>
+ <TD>Total</TD>
+ <TD>Consumer</TD>
+ </TR>
+</%def>
+<%def .header7>
+ <TR CLASS="head">
+ <TD ROWSPAN=2>State</TD>
+ <TD COLSPAN=2>Speed (Mbps)</TD>
+ <TD COLSPAN=2>Subscriptions</TD>
+ </TR>
+ <TR CLASS="subhead">
+ <TD>Down</TD>
+ <TD>Up</TD>
+ <TD>Total</TD>
+ <TD>Consumer</TD>
+ </TR>
+</%def>
+<%def .header8>
+ <TR CLASS="head">
+ <TD ROWSPAN=2>State</TD>
+ <TD COLSPAN=2>Subscriptions</TD>
+ </TR>
+ <TR CLASS="subhead">
+ <TD>Total</TD>
+ <TD>Direct</TD>
+ </TR>
+</%def>
+<%def .header9>
+ <TR CLASS="head">
+ <TD ROWSPAN=3>State</TD>
+ <TD COLSPAN=2>Wholesale</TD>
+ <TD COLSPAN=12>End User Lines</TD>
+ </TR>
+ <TR CLASS="subhead">
+ <TD ROWSPAN=2>VGEs</TD>
+ <TD ROWSPAN=2>UNE-Ls</TD>
+
+ <TD ROWSPAN=2>Total</TD>
+ <TD ROWSPAN=2>With Broadband</TD>
+ <TD COLSPAN=2>Consumer</TD>
+ <TD COLSPAN=2>Business</TD>
+
+ <TD COLSPAN=3>Local Loop</TD>
+
+ <TD COLSPAN=3>Special Media</TD>
+ </TR>
+
+ <TR CLASS="subhead">
+ <TD> </TD>
+ <TD>+LD</TD>
+ <TD> </TD>
+ <TD>+LD</TD>
+
+ <TD>Owned</TD>
+ <TD>UNE-L</TD>
+ <TD>Resale</TD>
+
+ <TD>Fiber</TD>
+ <TD>Coaxial</TD>
+ <TD>Wireless</TD>
+ </TR>
+</%def>
+<%def .header10>
+ <TR CLASS="head">
+ <TD ROWSPAN=2>State</TD>
+ <TD COLSPAN=2>VoIP OTT</TD>
+ <TD COLSPAN=8>VoIP Non-OTT</TD>
+ </TR>
+ <TR CLASS="subhead">
+ <TD ROWSPAN=2>Total</TD>
+ <TD ROWSPAN=2>Consumer</TD>
+
+ <TD ROWSPAN=2>Total</TD>
+ <TD ROWSPAN=2>Consumer</TD>
+ <TD ROWSPAN=2>Bundled</TD>
+ <TD COLSPAN=5>Media Type</TD>
+ </TR>
+ <TR CLASS="subhead">
+ <TD>Copper</TD>
+ <TD>Fiber</TD>
+ <TD>Coaxial</TD>
+ <TD>Wireless</TD>
+ <TD>Other</TD>
+ </TR>
+</%def>
+<%def .header11>
+ <TR CLASS="head">
+ <TD ROWSPAN=2>Census Tract</TD>
+ <TD ROWSPAN=2>VoIP?</TD>
+ <TD COLSPAN=2>Lines/Subscriptions</TD>
+ </TR>
+ <TR CLASS="subhead">
+ <TD>Total</TD>
+ <TD>Consumer</TD>
+ </TR>
+</%def>