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 % $header .= '_old' if $partname eq 'fbd' && $date < 1569826800; #9/30/2019
71 % # ( halfway between the two filing "as of" dates when it changed
73 % my $data = $this_part->{data};
74 % my $error = $this_part->{error};
79 % foreach my $row (@$data) {
80 % my %eh; # error hash
81 % if ( $error->[$rownum] ) {
82 % %eh = %{ $error->[$rownum] };
84 <tr<% keys(%eh) ? ' class="error"' : ''%>>
86 % foreach my $item (@$row) {
88 % if ($first and $part_link{$partname}) {
89 <a href="<% $part_link{$partname} . "477rownum=$rownum" %>"><% $item || '(empty)' %></a>
98 <td class="error"><ul>
99 % foreach my $key (sort keys %eh) {
100 <li><% $eh{$key} %></li>
103 % } # if there are errors
108 % } # foreach $partname
109 <& /elements/footer.html &>
112 unless $FS::CurrentUser::CurrentUser->access_right('List packages');
116 # load from cache if possible
118 if ( $cgi->param('session') =~ /^(\d+)$/ ) {
120 %parts = %{ $m->cache->get($session) };
122 $session = sprintf('%010d%06d', time, int(rand(1000000)));
123 $cgi->param('session', $session);
127 if ($cgi->param('agentnum') =~ /^(\d+)$/ ) {
130 my $date = parse_datetime($cgi->param('date')) || time;
131 my @partnames = grep /^\w+$/, $cgi->param('parts');
132 my $ignore_quantity = ($cgi->param('ignore_quantity') ? 1 : 0);
134 foreach my $partname (@partnames) {
135 $parts{$partname} ||= FS::Report::FCC_477->report( $partname,
137 agentnum => $agentnum,
138 ignore_quantity => $ignore_quantity,
139 ); # includes error, detail, and data parts
140 my $detail_table = FS::Report::FCC_477->part_table($partname);
141 if ($detail_table eq 'cust_pkg') {
142 my $link = popurl(1).'477_cust_pkg.html?477part='.$partname.";date=$date;";
144 $link .= "agentnum=$agentnum;";
146 $part_link{$partname} = $link;
147 } # don't include detail links to deploy_blocks, that's pointless
149 $m->cache->set($session, \%parts, '1h');
151 my $title = 'FCC Form 477 Data - ' . time2str('%b %o, %Y', $date);
153 if ( $cgi->param('type') eq 'csv' ) {
154 my $partname = $partnames[0]; # ignore any beyond the first
155 my $data = $parts{$partname}->{data};
156 my $csv = Text::CSV_XS->new({ eol => "\r\n" }); # i think
158 my $filename = time2str('%Y-%m-%d', $date) . '-'. $partname . '.csv';
159 http_header('Content-Type' => 'text/csv');
160 http_header('Content-Disposition' => qq(attachment;filename="$filename"));
164 foreach my $row (@$data) {
165 $csv->combine(@$row);
166 $m->print($csv->string);
171 my $part_titles = FS::Report::FCC_477->parts;
174 <%def .header_fbd_old>
176 <TD ROWSPAN=2>Census Block</TD>
177 <TD ROWSPAN=2>DBA Name</TD>
178 <TD ROWSPAN=2>Technology</TD>
179 <TD ROWSPAN=2>Consumer?</TD>
180 <TD COLSPAN=2>Advertised Speed (Mbps)</TD>
181 <TD ROWSPAN=2>Business?</TD>
182 <TD COLSPAN=2>Contractual Speed (Mbps)</TD>
193 <TD ROWSPAN=2>Census Block</TD>
194 <TD ROWSPAN=2>DBA Name</TD>
195 <TD ROWSPAN=2>Technology</TD>
196 <TD ROWSPAN=2>Consumer?</TD>
197 <TD COLSPAN=2>Advertised Speed (Mbps)</TD>
198 <TD ROWSPAN=2>Business?</TD>
207 <TD ROWSPAN=2>Census Tract</TD>
208 <TD ROWSPAN=2>Technology</TD>
209 <TD COLSPAN=2>Speed (Mbps)</TD>
210 <TD COLSPAN=2>Subscriptions</TD>
221 <TD ROWSPAN=2>Census Tract</TD>
222 <TD ROWSPAN=2>VoIP?</TD>
223 <TD COLSPAN=2>Lines/Subscriptions</TD>
232 <TD ROWSPAN=3>State</TD>
233 <TD COLSPAN=2>Wholesale</TD>
234 <TD COLSPAN=12>End User Lines</TD>
237 <TD ROWSPAN=2>VGEs</TD>
238 <TD ROWSPAN=2>UNE-Ls</TD>
240 <TD ROWSPAN=2>Total</TD>
241 <TD ROWSPAN=2>With Broadband</TD>
242 <TD COLSPAN=2>Consumer</TD>
243 <TD COLSPAN=2>Business</TD>
245 <TD COLSPAN=3>Local Loop</TD>
247 <TD COLSPAN=3>Special Media</TD>
267 <TD ROWSPAN=3>State</TD>
268 <TD COLSPAN=2>VoIP OTT</TD>
269 <TD COLSPAN=8>VoIP Non-OTT</TD>
272 <TD ROWSPAN=2>Total</TD>
273 <TD ROWSPAN=2>Consumer</TD>
275 <TD ROWSPAN=2>Total</TD>
276 <TD ROWSPAN=2>Consumer</TD>
277 <TD ROWSPAN=2>Bundled</TD>
278 <TD COLSPAN=5>Media Type</TD>
291 <TD ROWSPAN=2>State</TD>
292 <TD COLSPAN=2>Speed (Mbps)</TD>
293 <TD COLSPAN=2>Subscriptions</TD>
305 <TD ROWSPAN=2>State</TD>
306 <TD COLSPAN=2>Subscriptions</TD>