1 package FS::Report::FCC_477;
2 use base qw( FS::Report );
5 use vars qw( @upload @download @technology @part2aoption @part2boption
9 use FS::Record qw( dbh );
15 FS::Report::FCC_477 - Routines for FCC Form 477 reports
57 'Terrestrial Fixed Wireless',
58 'Terrestrial Mobile Wireless',
59 'Electric Power Line',
66 'unswitched UNE loops',
83 #from the select at http://www.ffiec.gov/census/default.aspx
85 '01' => 'ALABAMA (AL)',
86 '02' => 'ALASKA (AK)',
87 '04' => 'ARIZONA (AZ)',
88 '05' => 'ARKANSAS (AR)',
89 '06' => 'CALIFORNIA (CA)',
90 '08' => 'COLORADO (CO)',
92 '09' => 'CONNECTICUT (CT)',
93 '10' => 'DELAWARE (DE)',
94 '11' => 'DISTRICT OF COLUMBIA (DC)',
95 '12' => 'FLORIDA (FL)',
96 '13' => 'GEORGIA (GA)',
97 '15' => 'HAWAII (HI)',
100 '17' => 'ILLINOIS (IL)',
101 '18' => 'INDIANA (IN)',
103 '20' => 'KANSAS (KS)',
104 '21' => 'KENTUCKY (KY)',
106 '22' => 'LOUISIANA (LA)',
107 '23' => 'MAINE (ME)',
108 '24' => 'MARYLAND (MD)',
109 '25' => 'MASSACHUSETTS (MA)',
110 '26' => 'MICHIGAN (MI)',
111 '27' => 'MINNESOTA (MN)',
113 '28' => 'MISSISSIPPI (MS)',
114 '29' => 'MISSOURI (MO)',
115 '30' => 'MONTANA (MT)',
116 '31' => 'NEBRASKA (NE)',
117 '32' => 'NEVADA (NV)',
118 '33' => 'NEW HAMPSHIRE (NH)',
120 '34' => 'NEW JERSEY (NJ)',
121 '35' => 'NEW MEXICO (NM)',
122 '36' => 'NEW YORK (NY)',
123 '37' => 'NORTH CAROLINA (NC)',
124 '38' => 'NORTH DAKOTA (ND)',
127 '40' => 'OKLAHOMA (OK)',
128 '41' => 'OREGON (OR)',
129 '42' => 'PENNSYLVANIA (PA)',
130 '44' => 'RHODE ISLAND (RI)',
131 '45' => 'SOUTH CAROLINA (SC)',
132 '46' => 'SOUTH DAKOTA (SD)',
134 '47' => 'TENNESSEE (TN)',
135 '48' => 'TEXAS (TX)',
137 '50' => 'VERMONT (VT)',
138 '51' => 'VIRGINIA (VA)',
139 '53' => 'WASHINGTON (WA)',
141 '54' => 'WEST VIRGINIA (WV)',
142 '55' => 'WISCONSIN (WI)',
143 '56' => 'WYOMING (WY)',
144 '72' => 'PUERTO RICO (PR)',
147 sub restore_fcc477map {
149 FS::Record::scalar_sql('',"select formvalue from fcc477map where formkey = ?",$key);
156 local $SIG{HUP} = 'IGNORE';
157 local $SIG{INT} = 'IGNORE';
158 local $SIG{QUIT} = 'IGNORE';
159 local $SIG{TERM} = 'IGNORE';
160 local $SIG{TSTP} = 'IGNORE';
161 local $SIG{PIPE} = 'IGNORE';
163 my $oldAutoCommit = $FS::UID::AutoCommit;
164 local $FS::UID::AutoCommit = 0;
167 # lame (should be normal FS::Record access)
169 my $sql = "delete from fcc477map where formkey = ?";
170 my $sth = dbh->prepare($sql) or die dbh->errstr;
171 $sth->execute($key) or do {
172 warn "WARNING: Error removing FCC 477 form defaults: " . $sth->errstr;
173 $dbh->rollback if $oldAutoCommit;
176 $sql = "insert into fcc477map (formkey,formvalue) values (?,?)";
177 $sth = dbh->prepare($sql) or die dbh->errstr;
178 $sth->execute($key,$value) or do {
179 warn "WARNING: Error setting FCC 477 form defaults: " . $sth->errstr;
180 $dbh->rollback if $oldAutoCommit;
183 $dbh->commit or die $dbh->errstr if $oldAutoCommit;
188 sub parse_technology_option {
193 for (my $i = 0; $i < scalar(@technology); $i++) {
194 my $value = $cgi->param("part1_technology_option_$i"); #lame
195 save_fcc477map("part1_technology_option_$i",$value)
196 if $save && $value =~ /^\d+$/;
197 push @result, $value =~ /^\d+$/ ? $value : 0;
207 sub join_optionnames {
208 join(' ', map { join_optionname($_) } @_);
211 sub join_optionname {
212 # Returns a FROM phrase to join a specific option into the query (via
213 # part_pkg). The option value will appear as a field with the same name
216 "LEFT JOIN (SELECT pkgpart, optionvalue AS $name FROM part_pkg_fcc_option".
217 " WHERE fccoptionname = '$name') AS t_$name".
218 " ON (part_pkg.pkgpart = t_$name.pkgpart)";
222 # Returns a condition to limit packages to those that were setup before a
223 # certain date, and not canceled before that date.
225 # (Strictly speaking this should also exclude suspended packages but
226 # "suspended as of some past date" is a complicated query.)
228 "cust_pkg.setup <= $date AND ".
229 "(cust_pkg.cancel IS NULL OR cust_pkg.cancel > $date)";
232 sub is_fixed_broadband {
233 "is_broadband = '1' AND technology::integer IN(".join(',',
234 10, 11, 12, 20, 30, 40, 41, 42, 50, 60, 70, 90, 0
240 Returns Part 6 of the 2014 FCC 477 data, as an arrayref of arrayrefs.
241 OPTIONS may contain "date" => a timestamp to run the report as of that
249 my $date = $opt{date} || time;
252 'cust_location.censustract',
254 'broadband_downstream',
255 'broadband_upstream',
257 'COUNT(is_consumer)',
261 JOIN cust_location USING (locationnum)
262 JOIN part_pkg USING (pkgpart) '.
264 is_broadband technology
265 broadband_downstream broadband_upstream
273 my $group_by = 'cust_location.censustract, technology, '.
274 'broadband_downstream, broadband_upstream ';
275 my $order_by = $group_by;
277 my $statement = "SELECT ".join(', ', @select) . "
279 WHERE ".join(' AND ', @where)."
284 warn $statement if $DEBUG;
285 dbh->selectall_arrayref($statement);
290 Returns Part 9 of the 2014 FCC 477 data, as above.
297 my $date = $opt{date} || time;
300 "cust_location.state",
301 "SUM(COALESCE(phone_vges::int,0))",
302 "SUM(COALESCE(phone_circuits::int,0))",
303 "SUM(COALESCE(phone_lines::int,0))",
304 "SUM(CASE WHEN is_broadband = '1' THEN phone_lines::int ELSE 0 END)",
305 "SUM(CASE WHEN is_consumer = '1' AND is_longdistance IS NULL THEN phone_lines::int ELSE 0 END)",
306 "SUM(CASE WHEN is_consumer = '1' AND is_longdistance = '1' THEN phone_lines::int ELSE 0 END)",
307 "SUM(CASE WHEN is_consumer IS NULL AND is_longdistance IS NULL THEN phone_lines::int ELSE 0 END)",
308 "SUM(CASE WHEN is_consumer IS NULL AND is_longdistance = '1' THEN phone_lines::int ELSE 0 END)",
309 "SUM(CASE WHEN phone_localloop = 'owned' THEN phone_lines::int ELSE 0 END)",
310 "SUM(CASE WHEN phone_localloop = 'leased' THEN phone_lines::int ELSE 0 END)",
311 "SUM(CASE WHEN phone_localloop = 'resale' THEN phone_lines::int ELSE 0 END)",
312 "SUM(CASE WHEN media = 'Fiber' THEN phone_lines::int ELSE 0 END)",
313 "SUM(CASE WHEN media = 'Cable Modem' THEN phone_lines::int ELSE 0 END)",
314 "SUM(CASE WHEN media = 'Fixed Wireless' THEN phone_lines::int ELSE 0 END)",
318 JOIN cust_location USING (locationnum)
319 JOIN part_pkg USING (pkgpart) '.
321 is_phone is_broadband media
322 phone_vges phone_circuits phone_lines
323 is_consumer is_longdistance phone_localloop
330 my $group_by = 'cust_location.state';
331 my $order_by = $group_by;
333 my $statement = "SELECT ".join(', ', @select) . "
335 WHERE ".join(' AND ', @where)."
340 warn $statement if $DEBUG;
341 dbh->selectall_arrayref($statement);