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