X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2FReport%2FFCC_477.pm;h=86fa0a6165a9ea4b3b787e724f87dea35fa357c9;hb=d7cf0d6bb3b81b1c91ef1bcc3252d56f96b65b0f;hp=79f00e371a5dceefc7ef195dcbcb92c548dd6ea3;hpb=8fdc0ea36474cfb3d1389f41691c14598559cbe7;p=freeside.git diff --git a/FS/FS/Report/FCC_477.pm b/FS/FS/Report/FCC_477.pm index 79f00e371..86fa0a616 100644 --- a/FS/FS/Report/FCC_477.pm +++ b/FS/FS/Report/FCC_477.pm @@ -8,6 +8,9 @@ use vars qw( @upload @download @technology @part2aoption @part2boption ); use FS::Record qw( dbh ); +use Tie::IxHash; +use Storable; + $DEBUG = 1; =head1 NAME @@ -165,8 +168,6 @@ sub save_fcc477map { local $FS::UID::AutoCommit = 0; my $dbh = dbh; - # lame (should be normal FS::Record access) - my $sql = "delete from fcc477map where formkey = ?"; my $sth = dbh->prepare($sql) or die dbh->errstr; $sth->execute($key) or do { @@ -204,6 +205,8 @@ sub statenum2state { my $num = shift; $states{$num}; } +### everything above this point is unmaintained ### + =head1 THE "NEW" REPORT (October 2014 and later) @@ -213,6 +216,8 @@ sub statenum2state { =cut +# functions for internal use + sub join_optionnames { join(' ', map { join_optionname($_) } @_); } @@ -259,26 +264,69 @@ sub is_fixed_broadband { ).")"; } -=item part6 OPTIONS +=item report SECTION, OPTIONS -Returns Part 6 of the 2014 FCC 477 data, as an arrayref of arrayrefs. -OPTIONS may contain: -- date: a timestamp value to count active packages as of that date -- agentnum: limit to customers of that agent - -Part 6 is the broadband subscription detail report. Columns of the -report are: -- census tract -- technology code -- downstream speed -- upstream speed -(the above columns form a key) -- number of subscriptions -- number of consumer-grade subscriptions +Returns the report section SECTION (see the C method for section +name strings) as an arrayref of arrayrefs. OPTIONS may contain "date" +(a timestamp value to run the report as of this date) and "agentnum" +(to limit to a single agent). =cut -sub part6 { +sub report { + my $class = shift; + my $section = shift; + my %opt = @_; + + my $method = $section.'_sql'; + die "Report section '$section' is not implemented\n" + unless $class->can($method); + my $statement = $class->$method(%opt); + + my $sth = dbh->prepare($statement); + $sth->execute or die $sth->errstr; + $sth->fetchall_arrayref; +} + +sub fbd_sql { + my $class = shift; + my %opt = shift; + my $date = $opt{date} || time; + warn $date; + my $agentnum = $opt{agentnum}; + + my @select = ( + 'censusblock', + 'COALESCE(dbaname, agent.agent)', + 'technology', + 'CASE WHEN is_consumer IS NOT NULL THEN 1 ELSE 0 END', + 'adv_speed_down', + 'adv_speed_up', + 'CASE WHEN is_business IS NOT NULL THEN 1 ELSE 0 END', + 'cir_speed_down', + 'cir_speed_up', + ); + my $from = + 'deploy_zone_block + JOIN deploy_zone USING (zonenum) + JOIN agent USING (agentnum)'; + my @where = ( + "zonetype = 'B'", + "active_date < $date", + "(expire_date > $date OR expire_date IS NULL)", + ); + push @where, "agentnum = $agentnum" if $agentnum; + + my $order_by = 'censusblock, dbaname, technology, is_consumer, is_business'; + + "SELECT ".join(', ', @select) . " + FROM $from + WHERE ".join(' AND ', @where)." + ORDER BY $order_by + "; +} + +sub fbs_sql { my $class = shift; my %opt = shift; my $date = $opt{date} || time; @@ -312,41 +360,58 @@ sub part6 { 'broadband_downstream, broadband_upstream '; my $order_by = $group_by; - my $statement = "SELECT ".join(', ', @select) . " + "SELECT ".join(', ', @select) . " FROM $from WHERE ".join(' AND ', @where)." GROUP BY $group_by ORDER BY $order_by "; - warn $statement if $DEBUG; - dbh->selectall_arrayref($statement); } -=item part9 OPTIONS - -Returns Part 9 of the 2014 FCC 477 data. Part 9 is the Local Exchange -Telephone Subscription report. Columns are: - -- state FIPS code (key) -- wholesale switched voice lines -- wholesale unswitched local loops -- end-user total lines -- end-user lines sold in a package with broadband -- consumer-grade lines where you are not the long-distance carrier -- consumer-grade lines where the carrier IS the long-distance carrier -- business-grade lines where you are not the long-distance carrier -- business-grade lines where the carrier IS the long-distance carrier -- end-user lines where you own the local loop facility -- end-user lines where you lease an unswitched local loop from a LEC -- end-user lines resold from another carrier -- end-user lines provided over fiber to the premises -- end-user lines provided over coaxial -- end-user lines provided over fixed wireless +sub fvs_sql { + my $class = shift; + my %opt = shift; + my $date = $opt{date} || time; + my $agentnum = $opt{agentnum}; -=cut + my @select = ( + 'cust_location.censustract', + # VoIP indicator (0 for non-VoIP, 1 for VoIP) + 'COALESCE(is_voip, 0)', + # number of lines/subscriptions + 'SUM(CASE WHEN is_voip = 1 THEN 1 ELSE phone_lines END)', + # consumer grade lines/subscriptions + 'SUM(CASE WHEN is_consumer = 1 THEN ( CASE WHEN is_voip = 1 THEN voip_sessions ELSE phone_lines END) ELSE 0 END)' + ); -sub part9 { + my $from = 'cust_pkg + JOIN cust_location ON (cust_pkg.locationnum = cust_location.locationnum) + JOIN cust_main ON (cust_pkg.custnum = cust_main.custnum) + JOIN part_pkg USING (pkgpart) '. + join_optionnames_int(qw( + is_phone is_voip is_consumer phone_lines voip_sessions + )) + ; + + my @where = ( + active_on($date), + "(is_voip = 1 OR is_phone = 1)", + ); + push @where, "cust_main.agentnum = $agentnum" if $agentnum; + my $group_by = 'cust_location.censustract, COALESCE(is_voip, 0)'; + my $order_by = $group_by; + + "SELECT ".join(', ', @select) . " + FROM $from + WHERE ".join(' AND ', @where)." + GROUP BY $group_by + ORDER BY $order_by + "; + +} + +sub lts_sql { my $class = shift; my %opt = shift; my $date = $opt{date} || time; @@ -358,10 +423,10 @@ sub part9 { "SUM(phone_circuits)", "SUM(phone_lines)", "SUM(CASE WHEN is_broadband = 1 THEN phone_lines ELSE 0 END)", - "SUM(CASE WHEN is_consumer = 1 AND is_longdistance IS NULL THEN phone_lines ELSE 0 END)", - "SUM(CASE WHEN is_consumer = 1 AND is_longdistance = 1 THEN phone_lines ELSE 0 END)", - "SUM(CASE WHEN is_consumer IS NULL AND is_longdistance IS NULL THEN phone_lines ELSE 0 END)", - "SUM(CASE WHEN is_consumer IS NULL AND is_longdistance = 1 THEN phone_lines ELSE 0 END)", + "SUM(CASE WHEN is_consumer = 1 AND phone_longdistance IS NULL THEN phone_lines ELSE 0 END)", + "SUM(CASE WHEN is_consumer = 1 AND phone_longdistance = 1 THEN phone_lines ELSE 0 END)", + "SUM(CASE WHEN is_consumer IS NULL AND phone_longdistance IS NULL THEN phone_lines ELSE 0 END)", + "SUM(CASE WHEN is_consumer IS NULL AND phone_longdistance = 1 THEN phone_lines ELSE 0 END)", "SUM(CASE WHEN phone_localloop = 'owned' THEN phone_lines ELSE 0 END)", "SUM(CASE WHEN phone_localloop = 'leased' THEN phone_lines ELSE 0 END)", "SUM(CASE WHEN phone_localloop = 'resale' THEN phone_lines ELSE 0 END)", @@ -378,7 +443,7 @@ sub part9 { join_optionnames_int(qw( is_phone is_broadband phone_vges phone_circuits phone_lines - is_consumer is_longdistance + is_consumer phone_longdistance )). join_optionnames('media', 'phone_localloop') ; @@ -390,18 +455,15 @@ sub part9 { my $group_by = 'state.fips'; my $order_by = $group_by; - my $statement = "SELECT ".join(', ', @select) . " + "SELECT ".join(', ', @select) . " FROM $from WHERE ".join(' AND ', @where)." GROUP BY $group_by ORDER BY $order_by "; - - warn $statement if $DEBUG; - dbh->selectall_arrayref($statement); } -sub part10 { +sub voip_sql { my $class = shift; my %opt = shift; my $date = $opt{date} || time; @@ -442,65 +504,37 @@ sub part10 { my $group_by = 'state.fips'; my $order_by = $group_by; - my $statement = "SELECT ".join(', ', @select) . " + "SELECT ".join(', ', @select) . " FROM $from WHERE ".join(' AND ', @where)." GROUP BY $group_by ORDER BY $order_by "; - warn $statement if $DEBUG; - dbh->selectall_arrayref($statement); } -=item part11 OPTIONS +=item parts -Returns part 11 (voice subscription detail), as above. +Returns a Tie::IxHash reference of the internal short names used for the +report sections ('fbd', 'mbs', etc.) to the full names. =cut -sub part11 { - my $class = shift; - my %opt = shift; - my $date = $opt{date} || time; - my $agentnum = $opt{agentnum}; - - my @select = ( - 'cust_location.censustract', - # VoIP indicator (0 for non-VoIP, 1 for VoIP) - 'COALESCE(is_voip, 0)', - # number of lines/subscriptions - 'SUM(CASE WHEN is_voip = 1 THEN 1 ELSE phone_lines END)', - # consumer grade lines/subscriptions - 'SUM(CASE WHEN is_consumer = 1 THEN ( CASE WHEN is_voip = 1 THEN 1 ELSE phone_lines END) ELSE 0 END)' - ); - - my $from = 'cust_pkg - JOIN cust_location ON (cust_pkg.locationnum = cust_location.locationnum) - JOIN cust_main ON (cust_pkg.custnum = cust_main.custnum) - JOIN part_pkg USING (pkgpart) '. - join_optionnames_int(qw( - is_phone is_voip is_consumer phone_lines - )) - ; - - my @where = ( - active_on($date), - "(is_voip = 1 OR is_phone = 1)", - ); - push @where, "cust_main.agentnum = $agentnum" if $agentnum; - my $group_by = 'cust_location.censustract, COALESCE(is_voip, 0)'; - my $order_by = $group_by; - - my $statement = "SELECT ".join(', ', @select) . " - FROM $from - WHERE ".join(' AND ', @where)." - GROUP BY $group_by - ORDER BY $order_by - "; +tie our %parts, 'Tie::IxHash', ( + fbd => 'Fixed Broadband Deployment', + fbs => 'Fixed Broadband Subscription', + fvs => 'Fixed Voice Subscription', + lts => 'Local Exchange Telephone Subscription', + voip => 'Interconnected VoIP Subscription', + mbd => 'Mobile Broadband Deployment', + mbsa => 'Mobile Broadband Service Availability', + mbs => 'Mobile Broadband Subscription', + mvd => 'Mobile Voice Deployment', + mvs => 'Mobile Voice Subscription', +); - warn $statement if $DEBUG; - dbh->selectall_arrayref($statement); +sub parts { + Storable::dclone(\%parts); } 1;