477 report rewrite, #28020
[freeside.git] / bin / convert-477-options
1 #!/usr/bin/perl
2
3 my $user = shift;
4 use FS::UID 'adminsuidsetup';
5 use FS::Record qw(qsearch qsearchs dbh);
6 use FS::part_pkg_report_option;
7 use Text::CSV;
8
9 if (!$user) {
10   print "
11 Usage: bin/convert-477-options <username>
12
13 This script will convert your per-package FCC 477 report options
14 from the classic style (part IA, IB, IIA...) to the 2014 style.
15 This is an approximate conversion, and you should review the 
16 resulting package settings for accuracy.  In particular:
17   - Broadband speeds will be set to the lowest speed in their 
18     tier.
19   - Broadband technologies for ADSL and cable modem will be set
20     to 'other ADSL' and 'other cable modem'.  You should set 
21     them to the specific ADSL or cable encapsulation in use.
22   - All packages will be set to 'business grade'.  The 'consumer grade'
23     category did not exist in previous versions of the report.
24 ";
25   exit(1);
26 }
27
28 adminsuidsetup($user) or die "invalid user '$user'";
29 $FS::UID::AutoCommit = 1;
30 $FS::Record::nowarn_classload = 1;
31
32 print "Configuring packages...\n";
33
34 my @min_download_speed = ( 0.2, 0.768, 1.5, 3, 6, 10, 25, 100 );
35 my @min_upload_speed = ( 0.1, @min_download_speed );
36 my @media_type = ( 'Copper', 'Copper', 'Copper', 'Cable Modem',
37                    'Fiber', 'Satellite', 'Fixed Wireless', 'Mobile Wireless',
38                    'Other', 'Other' );
39 my @technology = ( 10, 20, 30, 40,
40                    50, 60, 70, 80,
41                    90, 0 );
42
43 my @phone_option = (
44   'phone_longdistance:1',   # LD carrier
45   'phone_localloop:owned',  # owned loops
46   'phone_localloop:leased', # unswitched UNE loops
47   'phone_localloop:resale', # UNE-P (is pretty much extinct...)
48   'phone_localloop:resale', # UNE-P replacement
49   'media:Fiber',
50   'media:Cable Modem',
51   'media:Fixed Wireless',
52 );
53
54 my @voip_option = (
55   '', #nomadic; no longer reported
56   'media:Copper',
57   'media:Fiber',
58   'media:Cable Modem',
59   'media:Fixed Wireless',
60   'media:Other'
61 );
62
63 my %num_to_formkey = map { $_->formvalue => $_->formkey }
64                       qsearch('fcc477map', {});
65
66 sub report_option_to_fcc_option {
67   my $report_option_num = shift;
68   my $formkey = $num_to_formkey{$report_option_num}
69     or return;
70   if      ($formkey =~ /^part1_column_option_(\d+)/) {
71     #download speed
72     return (broadband_downstream => $min_download_speed[$1]);
73   } elsif ($formkey =~ /^part1_row_option_(\d+)/) {
74     #upload speed
75     return (broadband_upstream   => $min_upload_speed[$1]);
76   } elsif ($formkey =~ /^part1_technology_option_(\d+)/) {
77     #broadband tech
78     return (is_broadband  => 1,
79             media         => $media_type[$1],
80             technology    => $technology[$1]);
81   } elsif ($formkey =~ /^part2a_row_option_(\d+)/) {
82     #local phone options
83     return (media => 'Copper', # sensible default
84             split(':', $phone_option[$1])
85            );
86   } elsif ($formkey =~ /^part2b_row_option_(\d+)/) {
87     #VoIP options (are all media types)
88     return (split(':', $voip_option[$1]));
89   } else {
90     warn "can't parse option with formkey '$formkey'\n";
91     return;
92   }
93 }
94
95 for my $part_pkg (qsearch('part_pkg', { freq => {op => '!=', value => '0'}})) {
96   my $pkgpart = $part_pkg->pkgpart;
97   #print "#$pkgpart\n";
98   my %report_opts = $part_pkg->options;
99   my @fcc_opts;
100   foreach my $optionname (keys(%report_opts)) {
101     $optionname =~ /^report_option_(\d+)$/ or next;
102     my $num = $1;
103     push @fcc_opts, report_option_to_fcc_option($num);
104   }
105   # other special stuff:
106   # FCC voice class (VoIP OTT, VoIP + broadband)
107   if ($part_pkg->fcc_voip_class == 1) {
108     push @fcc_opts, 'is_voip' => 1;
109   } elsif ( $part_pkg->fcc_voip_class == 2) {
110     push @fcc_opts, 'is_voip' => 1, 'is_broadband' => 1;
111   }
112   # DS0 equivalent lines
113   if ( $part_pkg->fcc_ds0s ) {
114     if ($part_pkg->fcc_voip_class) {
115       # there's no such thing as a VoIP DS0 equivalent, but this is
116       # what we used the field for
117       push @fcc_opts, 'voip_lines' => $part_pkg->fcc_ds0s;
118     } else {
119       push @fcc_opts, 'phone_lines' => $part_pkg->fcc_ds0s, 'is_phone' => 1;
120     }
121   }
122
123   my %fcc_opts = @fcc_opts;
124   #print map {"\t$_\t".$fcc_opts{$_}."\n"} keys %fcc_opts;
125   my $error = $part_pkg->process_fcc_options(\%fcc_opts);
126   if ( $error ) {
127     die "$error\n";
128   }
129   #print "\n";
130 }
131
132 print "Finished.\n";
133