start of FCC 477 report rewrite, #24047 and #28020
[freeside.git] / bin / convert-477-options
diff --git a/bin/convert-477-options b/bin/convert-477-options
new file mode 100755 (executable)
index 0000000..a52c56c
--- /dev/null
@@ -0,0 +1,125 @@
+#!/usr/bin/perl
+
+my $user = shift;
+use FS::UID 'adminsuidsetup';
+use FS::Record qw(qsearch qsearchs dbh);
+use FS::part_pkg_report_option;
+use Text::CSV;
+
+adminsuidsetup($user) or die "invalid user '$user'";
+$FS::UID::AutoCommit = 1;
+$FS::Record::nowarn_classload = 1;
+
+print "This script will convert your per-package FCC 477 report options
+from the classic style (part IA, IB, IIA...) to the 2014 style.
+This is an approximate conversion, and you should review the 
+resulting package settings for accuracy.  In particular:
+  - Broadband speeds will be set to the lowest speed in their 
+    tier.
+  - Broadband technologies for ADSL and cable modem will be set
+    to 'other ADSL' and 'other cable modem'.  You should set 
+    them to the specific ADSL or cable encapsulation in use.
+  - The 'consumer grade' vs. 'business grade' classification 
+    was introduced in 2014 and will not be set.
+
+Configuring packages...
+";
+
+my @min_download_speed = ( 0.2, 0.768, 1.5, 3, 6, 10, 25, 100 );
+my @min_upload_speed = ( 0.1, @min_download_speed );
+my @media_type = ( 'Copper', 'Copper', 'Copper', 'Cable Modem',
+                   'Fiber', 'Satellite', 'Fixed Wireless', 'Mobile Wireless',
+                   'Other', 'Other' );
+my @technology = ( 10, 20, 30, 40,
+                   50, 60, 70, 80,
+                   90, 0 );
+
+my @phone_option = (
+  'phone_longdistance:1',   # LD carrier
+  'phone_localloop:owned',  # owned loops
+  'phone_localloop:leased', # unswitched UNE loops
+  'phone_localloop:resale', # UNE-P (is pretty much extinct...)
+  'phone_localloop:resale', # UNE-P replacement
+  'media:Fiber',
+  'media:Cable Modem',
+  'media:Fixed Wireless',
+);
+
+my @voip_option = (
+  '', #nomadic; no longer reported
+  'media:Copper',
+  'media:Fiber',
+  'media:Cable Modem',
+  'media:Fixed Wireless',
+  'media:Other'
+);
+
+my %num_to_formkey = map { $_->formvalue => $_->formkey }
+                      qsearch('fcc477map', {});
+
+sub report_option_to_fcc_option {
+  my $report_option_num = shift;
+  my $formkey = $num_to_formkey{$report_option_num}
+    or return;
+  if      ($formkey =~ /^part1_column_option_(\d+)/) {
+    #download speed
+    return (broadband_downstream => $min_download_speed[$1]);
+  } elsif ($formkey =~ /^part1_row_option_(\d+)/) {
+    #upload speed
+    return (broadband_upstream   => $min_upload_speed[$1]);
+  } elsif ($formkey =~ /^part1_technology_option_(\d+)/) {
+    #broadband tech
+    return (is_broadband  => 1,
+            media         => $media_type[$1],
+            technology    => $technology[$1]);
+  } elsif ($formkey =~ /^part2a_row_option_(\d+)/) {
+    #local phone options
+    return (split(':', $phone_option[$1]));
+  } elsif ($formkey =~ /^part2b_row_option_(\d+)/) {
+    #VoIP options (are all media types)
+    return (split(':', $voip_option[$1]));
+  } else {
+    warn "can't parse option with formkey '$formkey'\n";
+    return;
+  }
+}
+
+for my $part_pkg (qsearch('part_pkg', { freq => {op => '!=', value => '0'}})) {
+  my $pkgpart = $part_pkg->pkgpart;
+  print "#$pkgpart\n";
+  my %report_opts = $part_pkg->options;
+  my @fcc_opts;
+  foreach my $optionname (keys(%report_opts)) {
+    $optionname =~ /^report_option_(\d+)$/ or next;
+    my $num = $1;
+    push @fcc_opts, report_option_to_fcc_option($num);
+  }
+  # other special stuff:
+  # FCC voice class (VoIP OTT, VoIP + broadband)
+  if ($part_pkg->fcc_voip_class == 1) {
+    push @fcc_opts, 'is_voip' => 1;
+  } elsif ( $part_pkg->fcc_voip_class == 2) {
+    push @fcc_opts, 'is_voip' => 1, 'is_broadband' => 1;
+  }
+  # DS0 equivalent lines
+  if ( $part_pkg->fcc_ds0s ) {
+    if ($part_pkg->fcc_voip_class) {
+      # there's no such thing as a VoIP DS0 equivalent, but this is
+      # what we used the field for
+      push @fcc_opts, 'voip_lines' => $part_pkg->fcc_ds0s;
+    } else {
+      push @fcc_opts, 'phone_lines' => $part_pkg->fcc_ds0s, 'is_phone' => 1;
+    }
+  }
+
+  my %fcc_opts = @fcc_opts;
+  print map {"\t$_\t".$fcc_opts{$_}."\n"} keys %fcc_opts;
+  my $error = $part_pkg->process_fcc_options(\%fcc_opts);
+  if ( $error ) {
+    die "$error\n";
+  }
+  print "\n";
+}
+
+print "Finished.\n";
+