c867a721fb90ecffe83475cba147062c72607172
[freeside.git] / FS / bin / freeside-setup
1 #!/usr/bin/perl -Tw
2
3 #to delay loading dbdef until we're ready
4 BEGIN { $FS::Record::setup_hack = 1; }
5
6 use strict;
7 use vars qw($opt_s);
8 use Getopt::Std;
9 use Locale::Country;
10 use Locale::SubCountry;
11 use DBI;
12 use DBIx::DBSchema 0.21;
13 use DBIx::DBSchema::Table;
14 use DBIx::DBSchema::Column;
15 use DBIx::DBSchema::ColGroup::Unique;
16 use DBIx::DBSchema::ColGroup::Index;
17 use FS::UID qw(adminsuidsetup datasrc checkeuid getsecrets);
18 use FS::Record;
19 use FS::cust_main_county;
20 use FS::raddb;
21 use FS::part_bill_event;
22
23 die "Not running uid freeside!" unless checkeuid();
24
25 my %attrib2db =
26   map { lc($FS::raddb::attrib{$_}) => $_ } keys %FS::raddb::attrib;
27
28 getopts("s");
29 my $user = shift or die &usage;
30 getsecrets($user);
31
32 #needs to match FS::Record
33 my($dbdef_file) = "/usr/local/etc/freeside/dbdef.". datasrc;
34
35 ###
36
37 #print "\nEnter the maximum username length: ";
38 #my($username_len)=&getvalue;
39 my $username_len = 32; #usernamemax config file
40
41 #print "\n\n", <<END, ":";
42 #Freeside tracks the RADIUS User-Name, check attribute Password and
43 #reply attribute Framed-IP-Address for each user.  You can specify additional
44 #check and reply attributes (or you can add them later with the
45 #fs-radius-add-check and fs-radius-add-reply programs).
46 #
47 #First enter any additional RADIUS check attributes you need to track for each 
48 #user, separated by whitespace.
49 #END
50 #my @check_attributes = map { $attrib2db{lc($_)} or die "unknown attribute $_"; }
51 #                         split(" ",&getvalue);
52 #
53 #print "\n\n", <<END, ":";
54 #Now enter any additional reply attributes you need to track for each user,
55 #separated by whitespace.
56 #END
57 #my @attributes = map { $attrib2db{lc($_)} or die "unknown attribute $_"; }
58 #                   split(" ",&getvalue);
59 #
60 #print "\n\n", <<END, ":";
61 #Do you wish to enable the tracking of a second, separate shipping/service
62 #address?
63 #END
64 #my $ship = &_yesno;
65 #
66 #sub getvalue {
67 #  my($x)=scalar(<STDIN>);
68 #  chop $x;
69 #  $x;
70 #}
71 #
72 #sub _yesno {
73 #  print " [y/N]:";
74 #  my $x = scalar(<STDIN>);
75 #  $x =~ /^y/i;
76 #}
77
78 my @check_attributes = (); #add later
79 my @attributes = (); #add later
80 my $ship = $opt_s;
81
82 ###
83
84 my($char_d) = 80; #default maxlength for text fields
85
86 #my(@date_type)  = ( 'timestamp', '', ''     );
87 my(@date_type)  = ( 'int', 'NULL', ''     );
88 my(@perl_type) = ( 'text', 'NULL', ''  ); 
89 my @money_type = ( 'decimal',   '', '10,2' );
90
91 ###
92 # create a dbdef object from the old data structure
93 ###
94
95 my(%tables)=&tables_hash_hack;
96
97 #turn it into objects
98 my($dbdef) = new DBIx::DBSchema ( map {  
99   my(@columns);
100   while (@{$tables{$_}{'columns'}}) {
101     my($name,$type,$null,$length)=splice @{$tables{$_}{'columns'}}, 0, 4;
102     push @columns, new DBIx::DBSchema::Column ( $name,$type,$null,$length );
103   }
104   DBIx::DBSchema::Table->new(
105     $_,
106     $tables{$_}{'primary_key'},
107     DBIx::DBSchema::ColGroup::Unique->new($tables{$_}{'unique'}),
108     DBIx::DBSchema::ColGroup::Index->new($tables{$_}{'index'}),
109     @columns,
110   );
111 } (keys %tables) );
112
113 my $cust_main = $dbdef->table('cust_main');
114 unless ($ship) { #remove ship_ from cust_main
115   $cust_main->delcolumn($_) foreach ( grep /^ship_/, $cust_main->columns );
116 } else { #add indices
117   push @{$cust_main->index->lol_ref},
118     map { [ "ship_$_" ] } qw( last company daytime night fax );
119 }
120
121 #add radius attributes to svc_acct
122
123 my($svc_acct)=$dbdef->table('svc_acct');
124
125 my($attribute);
126 foreach $attribute (@attributes) {
127   $svc_acct->addcolumn ( new DBIx::DBSchema::Column (
128     'radius_'. $attribute,
129     'varchar',
130     'NULL',
131     $char_d,
132   ));
133 }
134
135 foreach $attribute (@check_attributes) {
136   $svc_acct->addcolumn( new DBIx::DBSchema::Column (
137     'rc_'. $attribute,
138     'varchar',
139     'NULL',
140     $char_d,
141   ));
142 }
143
144 #create history tables (false laziness w/create-history-tables)
145 foreach my $table ( grep { ! /^h_/ } $dbdef->tables ) {
146   my $tableobj = $dbdef->table($table)
147     or die "unknown table $table";
148
149   die "unique->lol_ref undefined for $table"
150     unless defined $tableobj->unique->lol_ref;
151   die "index->lol_ref undefined for $table"
152     unless defined $tableobj->index->lol_ref;
153
154   my $h_tableobj = DBIx::DBSchema::Table->new( {
155     name        => "h_$table",
156     primary_key => 'historynum',
157     unique      => DBIx::DBSchema::ColGroup::Unique->new( [] ),
158     'index'     => DBIx::DBSchema::ColGroup::Index->new( [
159                      @{$tableobj->unique->lol_ref},
160                      @{$tableobj->index->lol_ref}
161                    ] ),
162     columns     => [
163                      DBIx::DBSchema::Column->new( {
164                        'name'    => 'historynum',
165                        'type'    => 'serial',
166                        'null'    => 'NOT NULL',
167                        'length'  => '',
168                        'default' => '',
169                        'local'   => '',
170                      } ),
171                      DBIx::DBSchema::Column->new( {
172                        'name'    => 'history_date',
173                        'type'    => 'int',
174                        'null'    => 'NULL',
175                        'length'  => '',
176                        'default' => '',
177                        'local'   => '',
178                      } ),
179                      DBIx::DBSchema::Column->new( {
180                        'name'    => 'history_user',
181                        'type'    => 'varchar',
182                        'null'    => 'NOT NULL',
183                        'length'  => '80',
184                        'default' => '',
185                        'local'   => '',
186                      } ),
187                      DBIx::DBSchema::Column->new( {
188                        'name'    => 'history_action',
189                        'type'    => 'varchar',
190                        'null'    => 'NOT NULL',
191                        'length'  => '80',
192                        'default' => '',
193                        'local'   => '',
194                      } ),
195                      map {
196                        my $column = $tableobj->column($_);
197
198                        #clone so as to not disturb the original
199                        $column = DBIx::DBSchema::Column->new( {
200                          map { $_ => $column->$_() }
201                            qw( name type null length default local )
202                        } );
203
204                        $column->type('int')
205                          if $column->type eq 'serial';
206                        #$column->default('')
207                        #  if $column->default =~ /^nextval\(/i;
208                        #( my $local = $column->local ) =~ s/AUTO_INCREMENT//i;
209                        #$column->local($local);
210                        $column;
211                      } $tableobj->columns
212                    ],
213   } );
214   $dbdef->addtable($h_tableobj);
215 }
216
217 #important
218 $dbdef->save($dbdef_file);
219 &FS::Record::reload_dbdef($dbdef_file);
220
221 ###
222 # create 'em
223 ###
224
225 my($dbh)=adminsuidsetup $user;
226
227 #create tables
228 $|=1;
229
230 foreach my $statement ( $dbdef->sql($dbh) ) {
231   $dbh->do( $statement )
232     or die "CREATE error: ". $dbh->errstr. "\ndoing statement: $statement";
233 }
234
235 #cust_main_county
236 foreach my $country ( sort map uc($_), all_country_codes ) {
237
238   my $subcountry = eval { new Locale::SubCountry($country) };
239   my @states = $subcountry ? $subcountry->all_codes : undef;
240
241   if ( !scalar(@states) || ( scalar(@states) == 1 && !defined($states[0]) ) ) {
242
243     my $cust_main_county = new FS::cust_main_county({
244       'tax'   => 0,
245       'country' => $country,
246     });  
247     my $error = $cust_main_county->insert;
248     die $error if $error;
249
250   } else {
251
252     if ( $states[0] =~ /^(\d+|\w)$/ ) {
253       @states = map $subcountry->full_name($_), @states
254     }
255
256     foreach my $state ( @states ) {
257
258       my $cust_main_county = new FS::cust_main_county({
259         'state' => $state,
260         'tax'   => 0,
261         'country' => $country,
262       });  
263       my $error = $cust_main_county->insert;
264       die $error if $error;
265
266     }
267   
268   }
269 }
270
271 #billing events
272 foreach my $aref ( 
273   #[ 'COMP', 'Comp invoice', '$cust_bill->comp();', 30, 'comp' ],
274   [ 'CARD', 'Batch card', '$cust_bill->batch_card();', 40, 'batch-card' ],
275   [ 'BILL', 'Send invoice', '$cust_bill->send();', 50, 'send' ],
276   [ 'DCRD', 'Send invoice', '$cust_bill->send();', 50, 'send' ],
277   [ 'DCHK', 'Send invoice', '$cust_bill->send();', 50, 'send' ],
278 ) {
279
280   my $part_bill_event = new FS::part_bill_event({
281     'payby' => $aref->[0],
282     'event' => $aref->[1],
283     'eventcode' => $aref->[2],
284     'seconds' => 0,
285     'weight' => $aref->[3],
286     'plan' => $aref->[4],
287   });
288   my($error);
289   $error=$part_bill_event->insert;
290   die $error if $error;
291
292 }
293
294 $dbh->commit or die $dbh->errstr;
295 $dbh->disconnect or die $dbh->errstr;
296
297 #print "Freeside database initialized sucessfully\n";
298
299 sub usage {
300   die "Usage:\n  freeside-setup [ -s ] user\n"; 
301 }
302
303 ###
304 # Now it becomes an object.  much better.
305 ###
306 sub tables_hash_hack {
307
308   #note that s/(date|change)/_$1/; to avoid keyword conflict.
309   #put a kludge in FS::Record to catch this or? (pry need some date-handling
310   #stuff anyway also)
311
312   my(%tables)=( #yech.}
313
314     'agent' => {
315       'columns' => [
316         'agentnum', 'serial',            '',     '',
317         'agent',    'varchar',           '',     $char_d,
318         'typenum',  'int',            '',     '',
319         'freq',     'int',       'NULL', '',
320         'prog',     @perl_type,
321         'disabled',     'char', 'NULL', 1,
322         'username', 'varchar',       'NULL',     $char_d,
323         '_password','varchar',       'NULL',     $char_d,
324       ],
325       'primary_key' => 'agentnum',
326       'unique' => [],
327       'index' => [ ['typenum'], ['disabled'] ],
328     },
329
330     'agent_type' => {
331       'columns' => [
332         'typenum',   'serial',  '', '',
333         'atype',     'varchar', '', $char_d,
334       ],
335       'primary_key' => 'typenum',
336       'unique' => [],
337       'index' => [],
338     },
339
340     'type_pkgs' => {
341       'columns' => [
342         'typenum',   'int',  '', '',
343         'pkgpart',   'int',  '', '',
344       ],
345       'primary_key' => '',
346       'unique' => [ ['typenum', 'pkgpart'] ],
347       'index' => [ ['typenum'] ],
348     },
349
350     'cust_bill' => {
351       'columns' => [
352         'invnum',    'serial',  '', '',
353         'custnum',   'int',  '', '',
354         '_date',     @date_type,
355         'charged',   @money_type,
356         'printed',   'int',  '', '',
357         'closed',    'char', 'NULL', 1,
358       ],
359       'primary_key' => 'invnum',
360       'unique' => [],
361       'index' => [ ['custnum'], ['_date'] ],
362     },
363
364     'cust_bill_event' => {
365       'columns' => [
366         'eventnum',    'serial',  '', '',
367         'invnum',   'int',  '', '',
368         'eventpart',   'int',  '', '',
369         '_date',     @date_type,
370         'status', 'varchar', '', $char_d,
371         'statustext', 'text', 'NULL', '',
372       ],
373       'primary_key' => 'eventnum',
374       #no... there are retries now #'unique' => [ [ 'eventpart', 'invnum' ] ],
375       'unique' => [],
376       'index' => [ ['invnum'], ['status'] ],
377     },
378
379     'part_bill_event' => {
380       'columns' => [
381         'eventpart',    'serial',  '', '',
382         'payby',       'char',  '', 4,
383         'event',       'varchar',           '',     $char_d,
384         'eventcode',    @perl_type,
385         'seconds',     'int', 'NULL', '',
386         'weight',      'int', '', '',
387         'plan',       'varchar', 'NULL', $char_d,
388         'plandata',   'text', 'NULL', '',
389         'disabled',     'char', 'NULL', 1,
390       ],
391       'primary_key' => 'eventpart',
392       'unique' => [],
393       'index' => [ ['payby'], ['disabled'], ],
394     },
395
396     'cust_bill_pkg' => {
397       'columns' => [
398         'pkgnum',  'int', '', '',
399         'invnum',  'int', '', '',
400         'setup',   @money_type,
401         'recur',   @money_type,
402         'sdate',   @date_type,
403         'edate',   @date_type,
404         'itemdesc', 'varchar', 'NULL', $char_d,
405       ],
406       'primary_key' => '',
407       'unique' => [],
408       'index' => [ ['invnum'] ],
409     },
410
411     'cust_bill_pkg_detail' => {
412       'columns' => [
413         'detailnum', 'serial', '', '',
414         'pkgnum',  'int', '', '',
415         'invnum',  'int', '', '',
416         'detail',  'varchar', '', $char_d,
417       ],
418       'primary_key' => 'detailnum',
419       'unique' => [],
420       'index' => [ [ 'pkgnum', 'invnum' ] ],
421     },
422
423     'cust_credit' => {
424       'columns' => [
425         'crednum',  'serial', '', '',
426         'custnum',  'int', '', '',
427         '_date',    @date_type,
428         'amount',   @money_type,
429         'otaker',   'varchar', '', 32,
430         'reason',   'text', 'NULL', '',
431         'closed',    'char', 'NULL', 1,
432       ],
433       'primary_key' => 'crednum',
434       'unique' => [],
435       'index' => [ ['custnum'] ],
436     },
437
438     'cust_credit_bill' => {
439       'columns' => [
440         'creditbillnum', 'serial', '', '',
441         'crednum',  'int', '', '',
442         'invnum',  'int', '', '',
443         '_date',    @date_type,
444         'amount',   @money_type,
445       ],
446       'primary_key' => 'creditbillnum',
447       'unique' => [],
448       'index' => [ ['crednum'], ['invnum'] ],
449     },
450
451     'cust_main' => {
452       'columns' => [
453         'custnum',  'serial',  '',     '',
454         'agentnum', 'int',  '',     '',
455 #        'titlenum', 'int',  'NULL',   '',
456         'last',     'varchar', '',     $char_d,
457 #        'middle',   'varchar', 'NULL', $char_d,
458         'first',    'varchar', '',     $char_d,
459         'ss',       'varchar', 'NULL', 11,
460         'company',  'varchar', 'NULL', $char_d,
461         'address1', 'varchar', '',     $char_d,
462         'address2', 'varchar', 'NULL', $char_d,
463         'city',     'varchar', '',     $char_d,
464         'county',   'varchar', 'NULL', $char_d,
465         'state',    'varchar', 'NULL', $char_d,
466         'zip',      'varchar', 'NULL', 10,
467         'country',  'char', '',     2,
468         'daytime',  'varchar', 'NULL', 20,
469         'night',    'varchar', 'NULL', 20,
470         'fax',      'varchar', 'NULL', 12,
471         'ship_last',     'varchar', 'NULL', $char_d,
472 #        'ship_middle',   'varchar', 'NULL', $char_d,
473         'ship_first',    'varchar', 'NULL', $char_d,
474         'ship_company',  'varchar', 'NULL', $char_d,
475         'ship_address1', 'varchar', 'NULL', $char_d,
476         'ship_address2', 'varchar', 'NULL', $char_d,
477         'ship_city',     'varchar', 'NULL', $char_d,
478         'ship_county',   'varchar', 'NULL', $char_d,
479         'ship_state',    'varchar', 'NULL', $char_d,
480         'ship_zip',      'varchar', 'NULL', 10,
481         'ship_country',  'char', 'NULL', 2,
482         'ship_daytime',  'varchar', 'NULL', 20,
483         'ship_night',    'varchar', 'NULL', 20,
484         'ship_fax',      'varchar', 'NULL', 12,
485         'payby',    'char', '',     4,
486         'payinfo',  'varchar', 'NULL', $char_d,
487         'paycvv',   'varchar', 'NULL', 4,
488         #'paydate',  @date_type,
489         'paydate',  'varchar', 'NULL', 10,
490         'payname',  'varchar', 'NULL', $char_d,
491         'tax',      'char', 'NULL', 1,
492         'otaker',   'varchar', '',    32,
493         'refnum',   'int',  '',     '',
494         'referral_custnum', 'int',  'NULL', '',
495         'comments', 'text', 'NULL', '',
496       ],
497       'primary_key' => 'custnum',
498       'unique' => [],
499       #'index' => [ ['last'], ['company'] ],
500       'index' => [ ['last'], [ 'company' ], [ 'referral_custnum' ],
501                    [ 'daytime' ], [ 'night' ], [ 'fax' ], [ 'refnum' ],
502                  ],
503     },
504
505     'cust_main_invoice' => {
506       'columns' => [
507         'destnum',  'serial',  '',     '',
508         'custnum',  'int',  '',     '',
509         'dest',     'varchar', '',  $char_d,
510       ],
511       'primary_key' => 'destnum',
512       'unique' => [],
513       'index' => [ ['custnum'], ],
514     },
515
516     'cust_main_county' => { #county+state+country are checked off the
517                             #cust_main_county for validation and to provide
518                             # a tax rate.
519       'columns' => [
520         'taxnum',   'serial',   '',    '',
521         'state',    'varchar',  'NULL',    $char_d,
522         'county',   'varchar',  'NULL',    $char_d,
523         'country',  'char',  '', 2, 
524         'taxclass',   'varchar', 'NULL', $char_d,
525         'exempt_amount', @money_type,
526         'tax',      'real',  '',    '', #tax %
527         'taxname',  'varchar',  'NULL',    $char_d,
528         'setuptax',  'char', 'NULL', 1, # Y = setup tax exempt
529         'recurtax',  'char', 'NULL', 1, # Y = recur tax exempt
530       ],
531       'primary_key' => 'taxnum',
532       'unique' => [],
533   #    'unique' => [ ['taxnum'], ['state', 'county'] ],
534       'index' => [],
535     },
536
537     'cust_pay' => {
538       'columns' => [
539         'paynum',   'serial',    '',   '',
540         #now cust_bill_pay #'invnum',   'int',    '',   '',
541         'custnum',  'int',    '',   '',
542         'paid',     @money_type,
543         '_date',    @date_type,
544         'payby',    'char',   '',     4, # CARD/BILL/COMP, should be index into
545                                          # payment type table.
546         'payinfo',  'varchar',   'NULL', $char_d,  #see cust_main above
547         'paybatch', 'varchar',   'NULL', $char_d, #for auditing purposes.
548         'closed',    'char', 'NULL', 1,
549       ],
550       'primary_key' => 'paynum',
551       'unique' => [],
552       'index' => [ [ 'custnum' ], [ 'paybatch' ], [ 'payby' ], [ '_date' ] ],
553     },
554
555     'cust_pay_void' => {
556       'columns' => [
557         'paynum',    'int',    '',   '',
558         'custnum',   'int',    '',   '',
559         'paid',      @money_type,
560         '_date',     @date_type,
561         'payby',     'char',   '',     4, # CARD/BILL/COMP, should be index into
562                                           # payment type table.
563         'payinfo',   'varchar',   'NULL', $char_d,  #see cust_main above
564         'paybatch',  'varchar',   'NULL', $char_d, #for auditing purposes.
565         'closed',    'char', 'NULL', 1,
566         'void_date', @date_type,
567         'reason',    'varchar',   'NULL', $char_d,
568         'otaker',   'varchar', '', 32,
569       ],
570       'primary_key' => 'paynum',
571       'unique' => [],
572       'index' => [ [ 'custnum' ] ],
573     },
574
575     'cust_bill_pay' => {
576       'columns' => [
577         'billpaynum', 'serial',     '',   '',
578         'invnum',  'int',     '',   '',
579         'paynum',  'int',     '',   '',
580         'amount',  @money_type,
581         '_date',   @date_type
582       ],
583       'primary_key' => 'billpaynum',
584       'unique' => [],
585       'index' => [ [ 'paynum' ], [ 'invnum' ] ],
586     },
587
588     'cust_pay_batch' => { #what's this used for again?  list of customers
589                           #in current CARD batch? (necessarily CARD?)
590       'columns' => [
591         'paybatchnum',   'serial',    '',   '',
592         'invnum',   'int',    '',   '',
593         'custnum',   'int',    '',   '',
594         'last',     'varchar', '',     $char_d,
595         'first',    'varchar', '',     $char_d,
596         'address1', 'varchar', '',     $char_d,
597         'address2', 'varchar', 'NULL', $char_d,
598         'city',     'varchar', '',     $char_d,
599         'state',    'varchar', 'NULL', $char_d,
600         'zip',      'varchar', 'NULL', 10,
601         'country',  'char', '',     2,
602 #        'trancode', 'int', '', '',
603         'cardnum',  'varchar', '',     16,
604         #'exp',      @date_type,
605         'exp',      'varchar', '',     11,
606         'payname',  'varchar', 'NULL', $char_d,
607         'amount',   @money_type,
608       ],
609       'primary_key' => 'paybatchnum',
610       'unique' => [],
611       'index' => [ ['invnum'], ['custnum'] ],
612     },
613
614     'cust_pkg' => {
615       'columns' => [
616         'pkgnum',    'serial',    '',   '',
617         'custnum',   'int',    '',   '',
618         'pkgpart',   'int',    '',   '',
619         'otaker',    'varchar', '', 32,
620         'setup',     @date_type,
621         'bill',      @date_type,
622         'last_bill', @date_type,
623         'susp',      @date_type,
624         'cancel',    @date_type,
625         'expire',    @date_type,
626         'manual_flag', 'char', 'NULL', 1,
627       ],
628       'primary_key' => 'pkgnum',
629       'unique' => [],
630       'index' => [ ['custnum'] ],
631     },
632
633     'cust_refund' => {
634       'columns' => [
635         'refundnum',    'serial',    '',   '',
636         #now cust_credit_refund #'crednum',      'int',    '',   '',
637         'custnum',  'int',    '',   '',
638         '_date',        @date_type,
639         'refund',       @money_type,
640         'otaker',       'varchar',   '',   32,
641         'reason',       'varchar',   '',   $char_d,
642         'payby',        'char',   '',     4, # CARD/BILL/COMP, should be index
643                                              # into payment type table.
644         'payinfo',      'varchar',   'NULL', $char_d,  #see cust_main above
645         'paybatch',     'varchar',   'NULL', $char_d,
646         'closed',    'char', 'NULL', 1,
647       ],
648       'primary_key' => 'refundnum',
649       'unique' => [],
650       'index' => [],
651     },
652
653     'cust_credit_refund' => {
654       'columns' => [
655         'creditrefundnum', 'serial',     '',   '',
656         'crednum',  'int',     '',   '',
657         'refundnum',  'int',     '',   '',
658         'amount',  @money_type,
659         '_date',   @date_type
660       ],
661       'primary_key' => 'creditrefundnum',
662       'unique' => [],
663       'index' => [ [ 'crednum', 'refundnum' ] ],
664     },
665
666
667     'cust_svc' => {
668       'columns' => [
669         'svcnum',    'serial',    '',   '',
670         'pkgnum',    'int',    'NULL',   '',
671         'svcpart',   'int',    '',   '',
672       ],
673       'primary_key' => 'svcnum',
674       'unique' => [],
675       'index' => [ ['svcnum'], ['pkgnum'], ['svcpart'] ],
676     },
677
678     'part_pkg' => {
679       'columns' => [
680         'pkgpart',    'serial',    '',   '',
681         'pkg',        'varchar',   '',   $char_d,
682         'comment',    'varchar',   '',   $char_d,
683         'promo_code', 'varchar', 'NULL', $char_d,
684         'setup',      @perl_type,
685         'freq',       'varchar',   '',   $char_d,  #billing frequency
686         'recur',      @perl_type,
687         'setuptax',  'char', 'NULL', 1,
688         'recurtax',  'char', 'NULL', 1,
689         'plan',       'varchar', 'NULL', $char_d,
690         'plandata',   'text', 'NULL', '',
691         'disabled',   'char', 'NULL', 1,
692         'taxclass',   'varchar', 'NULL', $char_d,
693       ],
694       'primary_key' => 'pkgpart',
695       'unique' => [],
696       'index' => [ [ 'promo_code' ], [ 'disabled' ] ],
697     },
698
699 #    'part_title' => {
700 #      'columns' => [
701 #        'titlenum',   'int',    '',   '',
702 #        'title',      'varchar',   '',   $char_d,
703 #      ],
704 #      'primary_key' => 'titlenum',
705 #      'unique' => [ [] ],
706 #      'index' => [ [] ],
707 #    },
708
709     'pkg_svc' => {
710       'columns' => [
711         'pkgpart',    'int',    '',   '',
712         'svcpart',    'int',    '',   '',
713         'quantity',   'int',    '',   '',
714         'primary_svc','char', 'NULL',  1,
715       ],
716       'primary_key' => '',
717       'unique' => [ ['pkgpart', 'svcpart'] ],
718       'index' => [ ['pkgpart'] ],
719     },
720
721     'part_referral' => {
722       'columns' => [
723         'refnum',   'serial',    '',   '',
724         'referral', 'varchar',   '',   $char_d,
725         'disabled',     'char', 'NULL', 1,
726       ],
727       'primary_key' => 'refnum',
728       'unique' => [],
729       'index' => [ ['disabled'] ],
730     },
731
732     'part_svc' => {
733       'columns' => [
734         'svcpart',    'serial',    '',   '',
735         'svc',        'varchar',   '',   $char_d,
736         'svcdb',      'varchar',   '',   $char_d,
737         'disabled',   'char',  'NULL',   1,
738       ],
739       'primary_key' => 'svcpart',
740       'unique' => [],
741       'index' => [ [ 'disabled' ] ],
742     },
743
744     'part_svc_column' => {
745       'columns' => [
746         'columnnum',   'serial',         '', '',
747         'svcpart',     'int',         '', '',
748         'columnname',  'varchar',     '', 64,
749         'columnvalue', 'varchar', 'NULL', $char_d,
750         'columnflag',  'char',    'NULL', 1, 
751       ],
752       'primary_key' => 'columnnum',
753       'unique' => [ [ 'svcpart', 'columnname' ] ],
754       'index' => [ [ 'svcpart' ] ],
755     },
756
757     #(this should be renamed to part_pop)
758     'svc_acct_pop' => {
759       'columns' => [
760         'popnum',    'serial',    '',   '',
761         'city',      'varchar',   '',   $char_d,
762         'state',     'varchar',   '',   $char_d,
763         'ac',        'char',   '',   3,
764         'exch',      'char',   '',   3,
765         'loc',       'char',   'NULL',   4, #NULL for legacy purposes
766       ],
767       'primary_key' => 'popnum',
768       'unique' => [],
769       'index' => [ [ 'state' ] ],
770     },
771
772     'part_pop_local' => {
773       'columns' => [
774         'localnum',  'serial',     '',     '',
775         'popnum',    'int',     '',     '',
776         'city',      'varchar', 'NULL', $char_d,
777         'state',     'char',    'NULL', 2,
778         'npa',       'char',    '',     3,
779         'nxx',       'char',    '',     3,
780       ],
781       'primary_key' => 'localnum',
782       'unique' => [],
783       'index' => [ [ 'npa', 'nxx' ], [ 'popnum' ] ],
784     },
785
786     'svc_acct' => {
787       'columns' => [
788         'svcnum',    'int',    '',   '',
789         'username',  'varchar',   '',   $username_len, #unique (& remove dup code)
790         '_password', 'varchar',   '',   72, #13 for encryped pw's plus ' *SUSPENDED* (md5 passwords can be 34, blowfish 60)
791         'sec_phrase', 'varchar',  'NULL',   $char_d,
792         'popnum',    'int',    'NULL',   '',
793         'uid',       'int', 'NULL',   '',
794         'gid',       'int', 'NULL',   '',
795         'finger',    'varchar',   'NULL',   $char_d,
796         'dir',       'varchar',   'NULL',   $char_d,
797         'shell',     'varchar',   'NULL',   $char_d,
798         'quota',     'varchar',   'NULL',   $char_d,
799         'slipip',    'varchar',   'NULL',   15, #four TINYINTs, bah.
800         'seconds',   'int', 'NULL',   '', #uhhhh
801         'domsvc',    'int', '',   '',
802       ],
803       'primary_key' => 'svcnum',
804       #'unique' => [ [ 'username', 'domsvc' ] ],
805       'unique' => [],
806       'index' => [ ['username'], ['domsvc'] ],
807     },
808
809     #'svc_charge' => {
810     #  'columns' => [
811     #    'svcnum',    'int',    '',   '',
812     #    'amount',    @money_type,
813     #  ],
814     #  'primary_key' => 'svcnum',
815     #  'unique' => [ [] ],
816     #  'index' => [ [] ],
817     #},
818
819     'svc_domain' => {
820       'columns' => [
821         'svcnum',    'int',    '',   '',
822         'domain',    'varchar',    '',   $char_d,
823         'catchall',  'int', 'NULL',    '',
824       ],
825       'primary_key' => 'svcnum',
826       'unique' => [ ['domain'] ],
827       'index' => [],
828     },
829
830     'domain_record' => {
831       'columns' => [
832         'recnum',    'serial',     '',  '',
833         'svcnum',    'int',     '',  '',
834         #'reczone',   'varchar', '',  $char_d,
835         'reczone',   'varchar', '',  255,
836         'recaf',     'char',    '',  2,
837         'rectype',   'varchar',    '',  5,
838         #'recdata',   'varchar', '',  $char_d,
839         'recdata',   'varchar', '',  255,
840       ],
841       'primary_key' => 'recnum',
842       'unique'      => [],
843       'index'       => [ ['svcnum'] ],
844     },
845
846     'svc_forward' => {
847       'columns' => [
848         'svcnum',   'int',            '',   '',
849         'srcsvc',   'int',        'NULL',   '',
850         'src',      'varchar',    'NULL',  255,
851         'dstsvc',   'int',        'NULL',   '',
852         'dst',      'varchar',    'NULL',  255,
853       ],
854       'primary_key' => 'svcnum',
855       'unique'      => [],
856       'index'       => [ ['srcsvc'], ['dstsvc'] ],
857     },
858
859     'svc_www' => {
860       'columns' => [
861         'svcnum',   'int',    '',  '',
862         'recnum',   'int',    '',  '',
863         'usersvc',  'int',    '',  '',
864       ],
865       'primary_key' => 'svcnum',
866       'unique'      => [],
867       'index'       => [],
868     },
869
870     #'svc_wo' => {
871     #  'columns' => [
872     #    'svcnum',    'int',    '',   '',
873     #    'svcnum',    'int',    '',   '',
874     #    'svcnum',    'int',    '',   '',
875     #    'worker',    'varchar',   '',   $char_d,
876     #    '_date',     @date_type,
877     #  ],
878     #  'primary_key' => 'svcnum',
879     #  'unique' => [ [] ],
880     #  'index' => [ [] ],
881     #},
882
883     'prepay_credit' => {
884       'columns' => [
885         'prepaynum',   'serial',     '',   '',
886         'identifier',  'varchar', '', $char_d,
887         'amount',      @money_type,
888         'seconds',     'int',     'NULL', '',
889       ],
890       'primary_key' => 'prepaynum',
891       'unique'      => [ ['identifier'] ],
892       'index'       => [],
893     },
894
895     'port' => {
896       'columns' => [
897         'portnum',  'serial',     '',   '',
898         'ip',       'varchar', 'NULL', 15,
899         'nasport',  'int',     'NULL', '',
900         'nasnum',   'int',     '',   '',
901       ],
902       'primary_key' => 'portnum',
903       'unique'      => [],
904       'index'       => [],
905     },
906
907     'nas' => {
908       'columns' => [
909         'nasnum',   'serial',     '',    '',
910         'nas',      'varchar', '',    $char_d,
911         'nasip',    'varchar', '',    15,
912         'nasfqdn',  'varchar', '',    $char_d,
913         'last',     'int',     '',    '',
914       ],
915       'primary_key' => 'nasnum',
916       'unique'      => [ [ 'nas' ], [ 'nasip' ] ],
917       'index'       => [ [ 'last' ] ],
918     },
919
920     'session' => {
921       'columns' => [
922         'sessionnum', 'serial',       '',   '',
923         'portnum',    'int',       '',   '',
924         'svcnum',     'int',       '',   '',
925         'login',      @date_type,
926         'logout',     @date_type,
927       ],
928       'primary_key' => 'sessionnum',
929       'unique'      => [],
930       'index'       => [ [ 'portnum' ] ],
931     },
932
933     'queue' => {
934       'columns' => [
935         'jobnum', 'serial', '', '',
936         'job', 'text', '', '',
937         '_date', 'int', '', '',
938         'status', 'varchar', '', $char_d,
939         'statustext', 'text', 'NULL', '',
940         'svcnum', 'int', 'NULL', '',
941       ],
942       'primary_key' => 'jobnum',
943       'unique'      => [],
944       'index'       => [ [ 'svcnum' ], [ 'status' ] ],
945     },
946
947     'queue_arg' => {
948       'columns' => [
949         'argnum', 'serial', '', '',
950         'jobnum', 'int', '', '',
951         'arg', 'text', 'NULL', '',
952       ],
953       'primary_key' => 'argnum',
954       'unique'      => [],
955       'index'       => [ [ 'jobnum' ] ],
956     },
957
958     'queue_depend' => {
959       'columns' => [
960         'dependnum', 'serial', '', '',
961         'jobnum', 'int', '', '',
962         'depend_jobnum', 'int', '', '',
963       ],
964       'primary_key' => 'dependnum',
965       'unique'      => [],
966       'index'       => [ [ 'jobnum' ], [ 'depend_jobnum' ] ],
967     },
968
969     'export_svc' => {
970       'columns' => [
971         'exportsvcnum' => 'serial', '', '',
972         'exportnum'    => 'int', '', '',
973         'svcpart'      => 'int', '', '',
974       ],
975       'primary_key' => 'exportsvcnum',
976       'unique'      => [ [ 'exportnum', 'svcpart' ] ],
977       'index'       => [ [ 'exportnum' ], [ 'svcpart' ] ],
978     },
979
980     'part_export' => {
981       'columns' => [
982         'exportnum', 'serial', '', '',
983         #'svcpart',   'int', '', '',
984         'machine', 'varchar', '', $char_d,
985         'exporttype', 'varchar', '', $char_d,
986         'nodomain',     'char', 'NULL', 1,
987       ],
988       'primary_key' => 'exportnum',
989       'unique'      => [],
990       'index'       => [ [ 'machine' ], [ 'exporttype' ] ],
991     },
992
993     'part_export_option' => {
994       'columns' => [
995         'optionnum', 'serial', '', '',
996         'exportnum', 'int', '', '',
997         'optionname', 'varchar', '', $char_d,
998         'optionvalue', 'text', 'NULL', '',
999       ],
1000       'primary_key' => 'optionnum',
1001       'unique'      => [],
1002       'index'       => [ [ 'exportnum' ], [ 'optionname' ] ],
1003     },
1004
1005     'radius_usergroup' => {
1006       'columns' => [
1007         'usergroupnum', 'serial', '', '',
1008         'svcnum',       'int', '', '',
1009         'groupname',    'varchar', '', $char_d,
1010       ],
1011       'primary_key' => 'usergroupnum',
1012       'unique'      => [],
1013       'index'       => [ [ 'svcnum' ], [ 'groupname' ] ],
1014     },
1015
1016     'msgcat' => {
1017       'columns' => [
1018         'msgnum', 'serial', '', '',
1019         'msgcode', 'varchar', '', $char_d,
1020         'locale', 'varchar', '', 16,
1021         'msg', 'text', '', '',
1022       ],
1023       'primary_key' => 'msgnum',
1024       'unique'      => [ [ 'msgcode', 'locale' ] ],
1025       'index'       => [],
1026     },
1027
1028     'cust_tax_exempt' => {
1029       'columns' => [
1030         'exemptnum', 'serial', '', '',
1031         'custnum',   'int', '', '',
1032         'taxnum',    'int', '', '',
1033         'year',      'int', '', '',
1034         'month',     'int', '', '',
1035         'amount',   @money_type,
1036       ],
1037       'primary_key' => 'exemptnum',
1038       'unique'      => [ [ 'custnum', 'taxnum', 'year', 'month' ] ],
1039       'index'       => [],
1040     },
1041
1042     'router' => {
1043       'columns' => [
1044         'routernum', 'serial', '', '',
1045         'routername', 'varchar', '', $char_d,
1046         'svcnum', 'int', 'NULL', '',
1047       ],
1048       'primary_key' => 'routernum',
1049       'unique'      => [],
1050       'index'       => [],
1051     },
1052
1053     'part_svc_router' => {
1054       'columns' => [
1055         'svcpart', 'int', '', '',
1056         'routernum', 'int', '', '',
1057       ],
1058       'primary_key' => '',
1059       'unique'      => [],
1060       'index'       => [],
1061     },
1062
1063     'addr_block' => {
1064       'columns' => [
1065         'blocknum', 'serial', '', '',
1066         'routernum', 'int', '', '',
1067         'ip_gateway', 'varchar', '', 15,
1068         'ip_netmask', 'int', '', '',
1069       ],
1070       'primary_key' => 'blocknum',
1071       'unique'      => [ [ 'blocknum', 'routernum' ] ],
1072       'index'       => [],
1073     },
1074
1075     'svc_broadband' => {
1076       'columns' => [
1077         'svcnum', 'int', '', '',
1078         'blocknum', 'int', '', '',
1079         'speed_up', 'int', '', '',
1080         'speed_down', 'int', '', '',
1081         'ip_addr', 'varchar', '', 15,
1082       ],
1083       'primary_key' => 'svcnum',
1084       'unique'      => [],
1085       'index'       => [],
1086     },
1087
1088     'part_virtual_field' => {
1089       'columns' => [
1090         'vfieldpart', 'int', '', '',
1091         'dbtable', 'varchar', '', 32,
1092         'name', 'varchar', '', 32,
1093         'check_block', 'text', 'NULL', '',
1094         'length', 'int', 'NULL', '',
1095         'list_source', 'text', 'NULL', '',
1096         'label', 'varchar', 'NULL', 80,
1097       ],
1098       'primary_key' => 'vfieldpart',
1099       'unique' => [],
1100       'index' => [],
1101     },
1102
1103     'virtual_field' => {
1104       'columns' => [
1105         'recnum', 'int', '', '',
1106         'vfieldpart', 'int', '', '',
1107         'value', 'varchar', '', 128,
1108       ],
1109       'primary_key' => '',
1110       'unique' => [ [ 'vfieldpart', 'recnum' ] ],
1111       'index' => [],
1112     },
1113
1114     'acct_snarf' => {
1115       'columns' => [
1116         'snarfnum',  'int', '', '',
1117         'svcnum',    'int', '', '',
1118         'machine',   'varchar', '', 255,
1119         'protocol',  'varchar', '', $char_d,
1120         'username',  'varchar', '', $char_d,
1121         '_password', 'varchar', '', $char_d,
1122       ],
1123       'primary_key' => 'snarfnum',
1124       'unique' => [],
1125       'index'  => [ [ 'svcnum' ] ],
1126     },
1127
1128     'svc_external' => {
1129       'columns' => [
1130         'svcnum', 'int', '', '',
1131         'id',     'int', 'NULL', '',
1132         'title',  'varchar', 'NULL', $char_d,
1133       ],
1134       'primary_key' => 'svcnum',
1135       'unique'      => [],
1136       'index'       => [],
1137     },
1138
1139     'cust_pay_refund' => {
1140       'columns' => [
1141         'payrefundnum', 'serial', '', '',
1142         'paynum',  'int', '', '',
1143         'refundnum',  'int', '', '',
1144         '_date',    @date_type,
1145         'amount',   @money_type,
1146       ],
1147       'primary_key' => 'payrefundnum',
1148       'unique' => [],
1149       'index' => [ ['paynum'], ['refundnum'] ],
1150     },
1151
1152     'part_pkg_option' => {
1153       'columns' => [
1154         'optionnum', 'serial', '', '',
1155         'pkgpart', 'int', '', '',
1156         'optionname', 'varchar', '', $char_d,
1157         'optionvalue', 'text', 'NULL', '',
1158       ],
1159       'primary_key' => 'optionnum',
1160       'unique'      => [],
1161       'index'       => [ [ 'pkgpart' ], [ 'optionname' ] ],
1162     },
1163
1164     'rate' => {
1165       'columns' => [
1166         'ratenum',  'serial', '', '',
1167         'ratename', 'varchar', '', $char_d,
1168       ],
1169       'primary_key' => 'ratenum',
1170       'unique'      => [],
1171       'index'       => [],
1172     },
1173
1174     'rate_detail' => {
1175       'columns' => [
1176         'ratenum',         'int',     '', '',
1177         'orig_regionnum',  'int', 'NULL', '',
1178         'dest_regionnum',  'int',     '', '',
1179         'min_included',    'int',     '', '',
1180         'min_charge',      @money_type,
1181         'sec_granularity', 'int',     '', '',
1182         #time period (link to table of periods)?
1183       ],
1184       'primary_key' => '',
1185       'unique'      => [ [ 'ratenum', 'orig_regionnum', 'dest_regionnum' ] ],
1186       'index'       => [],
1187     },
1188
1189     'rate_region' => {
1190       'columns' => [
1191         'regionnum',   'serial',      '', '',
1192         'regionname',  'varchar',     '', $char_d,
1193       ],
1194       'primary_key' => 'regionnum',
1195       'unique'      => [],
1196       'index'       => [],
1197     },
1198
1199     'rate_prefix' => {
1200       'columns' => [
1201         'prefixnum',   'serial',    '', '',
1202         'regionnum',   'int',       '', '',,
1203         'countrycode', 'varchar',     '', 3,
1204         'npa',         'varchar', 'NULL', 6,
1205         'nxx',         'varchar', 'NULL', 3,
1206       ],
1207       'primary_key' => 'prefixnum',
1208       'unique'      => [],
1209       'index'       => [ [ 'countrycode' ], [ 'regionnum' ] ],
1210     },
1211
1212
1213   );
1214
1215   %tables;
1216
1217 }
1218