1 <& /elements/header.html, $title &>
2 <STYLE TYPE="text/css">
4 border-collapse: collapse;
5 border: 1px #777 solid;
10 border-left: 1px #777 solid;
11 border-right: 1px #777 solid;
13 table.fcc477part tbody td {
16 table.fcc477part thead tr.head {
20 border-top: 1px #777 solid;
21 border-bottom: 1px #777 solid;
23 table.fcc477part thead tr.subhead {
27 border-top: 1px #777 solid;
28 border-bottom: 1px #777 solid;
40 background-color: #ffdddd;
48 list-style-image: url("<% $fsurl %>images/cross.png");
54 % foreach my $partname (@partnames) {
55 % my $this_part = $parts{$partname};
56 % $cgi->param('parts', $partname);
57 % $cgi->param('type', 'csv');
58 <table class="fcc477part">
60 <span class="parttitle"><% $part_titles->{$partname} %></span>
61 % if ( $this_part->{num_errors} > 0 ) {
62 % # show error heading while it contains errors
63 <span class="errortitle">
64 <% emt('This section contains [quant,_1,error].', $this_part->{num_errors}) %>
67 <a class="download" href="<% $cgi->self_url %>">Download</a>
69 % my $header = ".header_$partname";
70 % my $data = $this_part->{data};
71 % my $error = $this_part->{error};
76 % foreach my $row (@$data) {
77 % my %eh; # error hash
78 % if ( $error->[$rownum] ) {
79 % %eh = %{ $error->[$rownum] };
81 <tr<% keys(%eh) ? ' class="error"' : ''%>>
83 % foreach my $item (@$row) {
85 % if ($first and $part_link{$partname}) {
86 <a href="<% $part_link{$partname} . "477rownum=$rownum" %>"><% $item || '(empty)' %></a>
95 <td class="error"><ul>
96 % foreach my $key (sort keys %eh) {
97 <li><% $eh{$key} %></li>
100 % } # if there are errors
105 % } # foreach $partname
106 <& /elements/footer.html &>
109 unless $FS::CurrentUser::CurrentUser->access_right('List packages');
113 # load from cache if possible
115 if ( $cgi->param('session') =~ /^(\d+)$/ ) {
117 %parts = %{ $m->cache->get($session) };
119 $session = sprintf('%010d%06d', time, int(rand(1000000)));
120 $cgi->param('session', $session);
124 if ($cgi->param('agentnum') =~ /^(\d+)$/ ) {
127 my $date = parse_datetime($cgi->param('date')) || time;
128 my @partnames = grep /^\w+$/, $cgi->param('parts');
129 my $ignore_quantity = ($cgi->param('ignore_quantity') ? 1 : 0);
131 foreach my $partname (@partnames) {
132 $parts{$partname} ||= FS::Report::FCC_477->report( $partname,
134 agentnum => $agentnum,
135 ignore_quantity => $ignore_quantity,
136 ); # includes error, detail, and data parts
137 my $detail_table = FS::Report::FCC_477->part_table($partname);
138 if ($detail_table eq 'cust_pkg') {
139 my $link = popurl(1).'477_cust_pkg.html?477part='.$partname.";date=$date;";
141 $link .= "agentnum=$agentnum;";
143 $part_link{$partname} = $link;
144 } # don't include detail links to deploy_blocks, that's pointless
146 $m->cache->set($session, \%parts, '1h');
148 my $title = 'FCC Form 477 Data - ' . time2str('%b %o, %Y', $date);
150 if ( $cgi->param('type') eq 'csv' ) {
151 my $partname = $partnames[0]; # ignore any beyond the first
152 my $data = $parts{$partname}->{data};
153 my $csv = Text::CSV_XS->new({ eol => "\r\n" }); # i think
155 my $filename = time2str('%Y-%m-%d', $date) . '-'. $partname . '.csv';
156 http_header('Content-Type' => 'text/csv');
157 http_header('Content-Disposition' => qq(attachment;filename="$filename"));
161 foreach my $row (@$data) {
162 $csv->combine(@$row);
163 $m->print($csv->string);
168 my $part_titles = FS::Report::FCC_477->parts;
173 <TD ROWSPAN=2>Census Block</TD>
174 <TD ROWSPAN=2>DBA Name</TD>
175 <TD ROWSPAN=2>Technology</TD>
176 <TD ROWSPAN=2>Consumer?</TD>
177 <TD COLSPAN=2>Advertised Speed (Mbps)</TD>
178 <TD ROWSPAN=2>Business?</TD>
179 <TD COLSPAN=2>Contractual Speed (Mbps)</TD>
190 <TD ROWSPAN=2>Census Tract</TD>
191 <TD ROWSPAN=2>Technology</TD>
192 <TD COLSPAN=2>Speed (Mbps)</TD>
193 <TD COLSPAN=2>Subscriptions</TD>
204 <TD ROWSPAN=2>Census Tract</TD>
205 <TD ROWSPAN=2>VoIP?</TD>
206 <TD COLSPAN=2>Lines/Subscriptions</TD>
215 <TD ROWSPAN=3>State</TD>
216 <TD COLSPAN=2>Wholesale</TD>
217 <TD COLSPAN=12>End User Lines</TD>
220 <TD ROWSPAN=2>VGEs</TD>
221 <TD ROWSPAN=2>UNE-Ls</TD>
223 <TD ROWSPAN=2>Total</TD>
224 <TD ROWSPAN=2>With Broadband</TD>
225 <TD COLSPAN=2>Consumer</TD>
226 <TD COLSPAN=2>Business</TD>
228 <TD COLSPAN=3>Local Loop</TD>
230 <TD COLSPAN=3>Special Media</TD>
250 <TD ROWSPAN=3>State</TD>
251 <TD COLSPAN=2>VoIP OTT</TD>
252 <TD COLSPAN=8>VoIP Non-OTT</TD>
255 <TD ROWSPAN=2>Total</TD>
256 <TD ROWSPAN=2>Consumer</TD>
258 <TD ROWSPAN=2>Total</TD>
259 <TD ROWSPAN=2>Consumer</TD>
260 <TD ROWSPAN=2>Bundled</TD>
261 <TD COLSPAN=5>Media Type</TD>
274 <TD ROWSPAN=2>State</TD>
275 <TD COLSPAN=2>Speed (Mbps)</TD>
276 <TD COLSPAN=2>Subscriptions</TD>
288 <TD ROWSPAN=2>State</TD>
289 <TD COLSPAN=2>Subscriptions</TD>