quiet warnings about CGI::param in list context
[freeside.git] / httemplate / search / 477.html
1 <& /elements/header.html, $title &>
2 <STYLE TYPE="text/css">
3 table.fcc477part {
4   border-collapse: collapse;
5   border: 1px #777 solid;
6   margin-bottom: 20px;
7 }
8 table.fcc477part td {
9   padding: 0px 4px;
10   border-left: 1px #777 solid;
11   border-right: 1px #777 solid;
12 }
13 table.fcc477part tbody td {
14   text-align: right;
15 }
16 table.fcc477part thead tr.head {
17   text-align: center;
18   vertical-align: top;
19   font-weight: bold;
20   border-top: 1px #777 solid;
21   border-bottom: 1px #777 solid;
22 }
23 table.fcc477part thead tr.subhead {
24   text-align: center;
25   font-weight: bold;
26   font-size: small;
27   border-top: 1px #777 solid;
28   border-bottom: 1px #777 solid;
29 }
30 .parttitle {
31   font-weight: bold;
32   font-size: large;
33   float: left;
34 }
35 .errortitle {
36   font-weight: bold;
37   color: #ff0000;
38 }
39 tr.error td {
40   background-color: #ffdddd;
41 }
42 tr.error td.error {
43   text-align: left;
44   border: none;
45 }
46 tr.error ul {
47   margin: 0px;
48   list-style-image: url("<% $fsurl %>images/cross.png");
49 }
50 a.download {
51   float: right;
52 }
53 </STYLE>
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">
59   <caption>
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}) %>
65       </span>
66 %   }
67     <a class="download" href="<% $cgi->self_url %>">Download</a>
68   </caption>
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
72
73 %   my $data = $this_part->{data};
74 %   my $error = $this_part->{error};
75   <thead>
76     <& $header &>
77   </thead>
78 %   my $rownum = 0;
79 %   foreach my $row (@$data) {
80 %     my %eh; # error hash
81 %     if ( $error->[$rownum] ) {
82 %       %eh = %{ $error->[$rownum] };
83 %     }
84   <tr<% keys(%eh) ? ' class="error"' : ''%>>
85 %     my $first = 1;
86 %     foreach my $item (@$row) {
87     <td>
88 %     if ($first and $part_link{$partname}) {
89       <a href="<% $part_link{$partname} . "477rownum=$rownum" %>"><% $item || '(empty)' %></a>
90 %       $first = 0;
91 %     } else {
92       <% $item %>
93 %     }
94     </td>
95 %   } #foreach $item
96 %   # display errors
97 %   if ( keys %eh ) {
98     <td class="error"><ul>
99 %     foreach my $key (sort keys %eh) {
100       <li><% $eh{$key} %></li>
101 %     }
102     </ul></td>
103 %   } # if there are errors
104   </tr>
105 %   $rownum++;
106 %   } #foreach $row
107 </table>
108 % } # foreach $partname
109 <& /elements/footer.html &>
110 <%init>
111 die "access denied"
112   unless $FS::CurrentUser::CurrentUser->access_right('List packages');
113
114 my %parts;
115 my %part_link;
116 # load from cache if possible
117 my $session;
118 if ( $cgi->param('session') =~ /^(\d+)$/ ) {
119   $session = $1;
120   %parts = %{ $m->cache->get($session) };
121 } else {
122   $session = sprintf('%010d%06d', time, int(rand(1000000)));
123   $cgi->param('session', $session);
124 }
125
126 my $agentnum;
127 if ($cgi->param('agentnum') =~ /^(\d+)$/ ) {
128   $agentnum = $1;
129 }
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);
133
134 foreach my $partname (@partnames) {
135   $parts{$partname} ||= FS::Report::FCC_477->report( $partname,
136     date            => $date,
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;";
143     if ($agentnum) {
144       $link .= "agentnum=$agentnum;";
145     }
146     $part_link{$partname} = $link;
147   } # don't include detail links to deploy_blocks, that's pointless
148 }
149 $m->cache->set($session, \%parts, '1h');
150
151 my $title = 'FCC Form 477 Data - ' . time2str('%b %o, %Y', $date);
152
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
157
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"));
161
162   $m->clear_buffer;
163
164   foreach my $row (@$data) {
165     $csv->combine(@$row);
166     $m->print($csv->string);
167   }
168   $m->abort;
169 }
170
171 my $part_titles = FS::Report::FCC_477->parts;
172
173 </%init>
174 <%def .header_fbd_old>
175   <TR CLASS="head">
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>
183   </TR>
184   <TR CLASS="subhead">
185     <TD>Down</TD>
186     <TD>Up</TD>
187     <TD>Down</TD>
188     <TD>Up</TD>
189   </TR>
190 </%def>
191 <%def .header_fbd>
192   <TR CLASS="head">
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>
199   </TR>
200   <TR CLASS="subhead">
201     <TD>Down</TD>
202     <TD>Up</TD>
203   </TR>
204 </%def>
205 <%def .header_fbs>
206   <TR CLASS="head">
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>
211   </TR>
212   <TR CLASS="subhead">
213     <TD>Down</TD>
214     <TD>Up</TD>
215     <TD>Total</TD>
216     <TD>Consumer</TD>
217   </TR>
218 </%def>
219 <%def .header_fvs>
220   <TR CLASS="head">
221     <TD ROWSPAN=2>Census Tract</TD>
222     <TD ROWSPAN=2>VoIP?</TD>
223     <TD COLSPAN=2>Lines/Subscriptions</TD>
224   </TR>
225   <TR CLASS="subhead">
226     <TD>Total</TD>
227     <TD>Consumer</TD>
228   </TR>
229 </%def>
230 <%def .header_lts>
231   <TR CLASS="head">
232     <TD ROWSPAN=3>State</TD>
233     <TD COLSPAN=2>Wholesale</TD>
234     <TD COLSPAN=12>End User Lines</TD>
235   </TR>
236   <TR CLASS="subhead">
237     <TD ROWSPAN=2>VGEs</TD>
238     <TD ROWSPAN=2>UNE-Ls</TD>
239
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>
244
245     <TD COLSPAN=3>Local Loop</TD>
246
247     <TD COLSPAN=3>Special Media</TD>
248   </TR>
249
250   <TR CLASS="subhead">
251     <TD> </TD>
252     <TD>+LD</TD>
253     <TD> </TD>
254     <TD>+LD</TD>
255
256     <TD>Owned</TD>
257     <TD>UNE-L</TD>
258     <TD>Resale</TD>
259
260     <TD>Fiber</TD>
261     <TD>Coaxial</TD>
262     <TD>Wireless</TD>
263   </TR>
264 </%def>
265 <%def .header_voip>
266   <TR CLASS="head">
267     <TD ROWSPAN=3>State</TD>
268     <TD COLSPAN=2>VoIP OTT</TD>
269     <TD COLSPAN=8>VoIP Non-OTT</TD>
270   </TR>
271   <TR CLASS="subhead">
272     <TD ROWSPAN=2>Total</TD>
273     <TD ROWSPAN=2>Consumer</TD>
274
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>
279   </TR>
280   <TR CLASS="subhead">
281     <TD>Copper</TD>
282     <TD>Fiber</TD>
283     <TD>Coaxial</TD>
284     <TD>Wireless</TD>
285     <TD>Other</TD>
286   </TR>
287 </%def>
288 <%def .header_mbs>
289 %# unimplemented
290   <TR CLASS="head">
291     <TD ROWSPAN=2>State</TD>
292     <TD COLSPAN=2>Speed (Mbps)</TD>
293     <TD COLSPAN=2>Subscriptions</TD>
294   </TR>
295   <TR CLASS="subhead">
296     <TD>Down</TD>
297     <TD>Up</TD>
298     <TD>Total</TD>
299     <TD>Consumer</TD>
300   </TR>
301 </%def>
302 <%def .header_mvs>
303 %# unimplemented
304   <TR CLASS="head">
305     <TD ROWSPAN=2>State</TD>
306     <TD COLSPAN=2>Subscriptions</TD>
307   </TR>
308   <TR CLASS="subhead">
309     <TD>Total</TD>
310     <TD>Direct</TD>
311   </TR>
312 </%def>
313