stray closing /TABLE in the no-ticket case
[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; # o2m
64 foreach ( qsearch('fcc477map', {}) ) {
65   push @{ $num_to_formkey{$_->formvalue} ||= [] }, $_->formkey;
66 }
67
68 sub report_option_to_fcc_option {
69   my $report_option_num = shift;
70   my $formkeys = $num_to_formkey{$report_option_num}
71     or return;
72   my @return;
73   foreach my $formkey (@$formkeys) {
74     if      ($formkey =~ /^part1_column_option_(\d+)/) {
75       #download speed
76       push @return, (broadband_downstream => $min_download_speed[$1]);
77     } elsif ($formkey =~ /^part1_row_option_(\d+)/) {
78       #upload speed
79       push @return, (broadband_upstream   => $min_upload_speed[$1]);
80     } elsif ($formkey =~ /^part1_technology_option_(\d+)/) {
81       #broadband tech
82       push @return, 
83              (is_broadband  => 1,
84               media         => $media_type[$1],
85               technology    => $technology[$1]);
86     } elsif ($formkey =~ /^part2a_row_option_(\d+)/) {
87       #local phone options
88       push @return,
89              (media => 'Copper', # sensible default
90               split(':', $phone_option[$1])
91              );
92     } elsif ($formkey =~ /^part2b_row_option_(\d+)/) {
93       #VoIP options (are all media types)
94       push @return, (split(':', $voip_option[$1]));
95     } elsif ($formkey =~ /^part5_report_option/) {
96       # ignore this
97     } else {
98       warn "can't parse option with formkey '$formkey'\n";
99     }
100   }
101   @return;
102 }
103
104 for my $part_pkg (qsearch('part_pkg', { freq => {op => '!=', value => '0'}})) {
105   my $pkgpart = $part_pkg->pkgpart;
106   #print "#$pkgpart\n";
107   my %report_opts = $part_pkg->options;
108   my @fcc_opts;
109   foreach my $optionname (keys(%report_opts)) {
110     $optionname =~ /^report_option_(\d+)$/ or next;
111     my $num = $1;
112     push @fcc_opts, report_option_to_fcc_option($num);
113   }
114   # other special stuff:
115   # FCC voice class (VoIP OTT, VoIP + broadband, Wholesale VoIP, Local
116   # Exchange) and DS0 equivalent lines
117   my $sessions = $part_pkg->fcc_ds0s;
118
119   if ( $sessions ) { # then this is a voice package of some kind
120     if ($part_pkg->fcc_voip_class == 1) {
121       # VoIP OTT (connection not included)
122       push @fcc_opts, 'is_voip' => 1, 'voip_ott' => 1,
123                       'voip_sessions' => $sessions;
124     } elsif ( $part_pkg->fcc_voip_class == 2) {
125       # VoIP non-OTT; do not set is_broadband since the connection is not 
126       # necessarily general Internet access
127       push @fcc_opts, 'is_voip' => 1,
128                       'voip_sessions' => $sessions;
129     } elsif ( $part_pkg->fcc_voip_class == 3 ) {
130       # wholesale VoIP; apparently no longer reportable?
131     } else {
132       # local exchange telephone
133       push @fcc_opts, 'is_phone' => 1,
134                       'phone_lines' => $sessions;
135     }
136   }
137
138   my %fcc_opts = @fcc_opts;
139   #print map {"\t$_\t".$fcc_opts{$_}."\n"} keys %fcc_opts;
140   my $error = $part_pkg->set_fcc_options(\%fcc_opts);
141   if ( $error ) {
142     die "$error\n";
143   }
144   #print "\n";
145 }
146
147 print "Finished.\n";
148