RADIUS groups on the way!
[freeside.git] / bin / fs-setup
1 #!/usr/bin/perl -Tw
2 #
3 # $Id: fs-setup,v 1.84 2002-03-22 18:56:32 ivan Exp $
4
5 #to delay loading dbdef until we're ready
6 BEGIN { $FS::Record::setup_hack = 1; }
7
8 use strict;
9 use DBI;
10 use DBIx::DBSchema 0.20;
11 use DBIx::DBSchema::Table;
12 use DBIx::DBSchema::Column;
13 use DBIx::DBSchema::ColGroup::Unique;
14 use DBIx::DBSchema::ColGroup::Index;
15 use FS::UID qw(adminsuidsetup datasrc checkeuid getsecrets);
16 use FS::Record;
17 use FS::cust_main_county;
18 use FS::raddb;
19 use FS::part_bill_event;
20
21 die "Not running uid freeside!" unless checkeuid();
22
23 my %attrib2db =
24   map { lc($FS::raddb::attrib{$_}) => $_ } keys %FS::raddb::attrib;
25
26 my $user = shift or die &usage;
27 getsecrets($user);
28
29 #needs to match FS::Record
30 my($dbdef_file) = "/usr/local/etc/freeside/dbdef.". datasrc;
31
32 ###
33
34 #print "\nEnter the maximum username length: ";
35 #my($username_len)=&getvalue;
36 my $username_len = 32; #usernamemax config file
37
38 print "\n\n", <<END, ":";
39 Freeside tracks the RADIUS User-Name, check attribute Password and
40 reply attribute Framed-IP-Address for each user.  You can specify additional
41 check and reply attributes (or you can add them later with the
42 fs-radius-add-check and fs-radius-add-reply programs).
43
44 First enter any additional RADIUS check attributes you need to track for each 
45 user, separated by whitespace.
46 END
47 my @check_attributes = map { $attrib2db{lc($_)} or die "unknown attribute $_"; }
48                          split(" ",&getvalue);
49
50 print "\n\n", <<END, ":";
51 Now enter any additional reply attributes you need to track for each user,
52 separated by whitespace.
53 END
54 my @attributes = map { $attrib2db{lc($_)} or die "unknown attribute $_"; }
55                    split(" ",&getvalue);
56
57 print "\n\n", <<END, ":";
58 Do you wish to enable the tracking of a second, separate shipping/service
59 address?
60 END
61 my $ship = &_yesno;
62
63 sub getvalue {
64   my($x)=scalar(<STDIN>);
65   chop $x;
66   $x;
67 }
68
69 sub _yesno {
70   print " [y/N]:";
71   my $x = scalar(<STDIN>);
72   $x =~ /^y/i;
73 }
74
75 ###
76
77 my($char_d) = 80; #default maxlength for text fields
78
79 #my(@date_type)  = ( 'timestamp', '', ''     );
80 my(@date_type)  = ( 'int', 'NULL', ''     );
81 my(@perl_type) = ( 'text', 'NULL', ''  ); 
82 my @money_type = ( 'decimal',   '', '10,2' );
83
84 ###
85 # create a dbdef object from the old data structure
86 ###
87
88 my(%tables)=&tables_hash_hack;
89
90 #turn it into objects
91 my($dbdef) = new DBIx::DBSchema ( map {  
92   my(@columns);
93   while (@{$tables{$_}{'columns'}}) {
94     my($name,$type,$null,$length)=splice @{$tables{$_}{'columns'}}, 0, 4;
95     push @columns, new DBIx::DBSchema::Column ( $name,$type,$null,$length );
96   }
97   DBIx::DBSchema::Table->new(
98     $_,
99     $tables{$_}{'primary_key'},
100     DBIx::DBSchema::ColGroup::Unique->new($tables{$_}{'unique'}),
101     DBIx::DBSchema::ColGroup::Index->new($tables{$_}{'index'}),
102     @columns,
103   );
104 } (keys %tables) );
105
106 my $cust_main = $dbdef->table('cust_main');
107 unless ($ship) { #remove ship_ from cust_main
108   $cust_main->delcolumn($_) foreach ( grep /^ship_/, $cust_main->columns );
109 } else { #add indices on ship_last and ship_company
110   push @{$cust_main->index->lol_ref}, ( ['ship_last'], ['ship_company'] ) 
111 }
112
113 #add radius attributes to svc_acct
114
115 my($svc_acct)=$dbdef->table('svc_acct');
116
117 my($attribute);
118 foreach $attribute (@attributes) {
119   $svc_acct->addcolumn ( new DBIx::DBSchema::Column (
120     'radius_'. $attribute,
121     'varchar',
122     'NULL',
123     $char_d,
124   ));
125 }
126
127 foreach $attribute (@check_attributes) {
128   $svc_acct->addcolumn( new DBIx::DBSchema::Column (
129     'rc_'. $attribute,
130     'varchar',
131     'NULL',
132     $char_d,
133   ));
134 }
135
136 ##make part_svc table (but now as object)
137 #
138 #my($part_svc)=$dbdef->table('part_svc');
139 #
140 ##because of svc_acct_pop
141 ##foreach (grep /^svc_/, $dbdef->tables) { 
142 ##foreach (qw(svc_acct svc_acct_sm svc_charge svc_domain svc_wo)) {
143 #foreach (qw(svc_acct svc_domain svc_forward svc_www)) {
144 #  my($table)=$dbdef->table($_);
145 #  my($col);
146 #  foreach $col ( $table->columns ) {
147 #    next if $col =~ /^svcnum$/;
148 #    $part_svc->addcolumn( new DBIx::DBSchema::Column (
149 #      $table->name. '__' . $table->column($col)->name,
150 #      'varchar', #$table->column($col)->type, 
151 #      'NULL',
152 #      $char_d, #$table->column($col)->length,
153 #    ));
154 #    $part_svc->addcolumn ( new DBIx::DBSchema::Column (
155 #      $table->name. '__'. $table->column($col)->name . "_flag",
156 #      'char',
157 #      'NULL',
158 #      1,
159 #    ));
160 #  }
161 #}
162
163 #create history tables (false laziness w/create-history-tables)
164 foreach my $table ( grep { ! /^h_/ } $dbdef->tables ) {
165   my $tableobj = $dbdef->table($table);
166   my $h_tableobj = DBIx::DBSchema::Table->new( {
167     name        => "h_$table",
168     primary_key => 'historynum',
169     unique      => DBIx::DBSchema::ColGroup::Unique->new( [] ),
170     'index'     => DBIx::DBSchema::ColGroup::Index->new( [
171                      @{$tableobj->unique->lol_ref},
172                      @{$tableobj->index->lol_ref}
173                    ] ),
174     columns     => [
175                      DBIx::DBSchema::Column->new( {
176                        'name'    => 'historynum',
177                        'type'    => 'serial',
178                        'null'    => 'NOT NULL',
179                        'length'  => '',
180                        'default' => '',
181                        'local'   => '',
182                      } ),
183                      DBIx::DBSchema::Column->new( {
184                        'name'    => 'history_date',
185                        'type'    => 'int',
186                        'null'    => 'NULL',
187                        'length'  => '',
188                        'default' => '',
189                        'local'   => '',
190                      } ),
191                      DBIx::DBSchema::Column->new( {
192                        'name'    => 'history_user',
193                        'type'    => 'varchar',
194                        'null'    => 'NOT NULL',
195                        'length'  => '80',
196                        'default' => '',
197                        'local'   => '',
198                      } ),
199                      DBIx::DBSchema::Column->new( {
200                        'name'    => 'history_action',
201                        'type'    => 'varchar',
202                        'null'    => 'NOT NULL',
203                        'length'  => '80',
204                        'default' => '',
205                        'local'   => '',
206                      } ),
207                      map { $tableobj->column($_) } $tableobj->columns
208                    ],
209   } );
210   $dbdef->addtable($h_tableobj);
211 }
212
213 #important
214 $dbdef->save($dbdef_file);
215 &FS::Record::reload_dbdef($dbdef_file);
216
217 ###
218 # create 'em
219 ###
220
221 my($dbh)=adminsuidsetup $user;
222
223 #create tables
224 $|=1;
225
226 foreach my $statement ( $dbdef->sql($dbh) ) {
227   $dbh->do( $statement )
228     or die "CREATE error: ". $dbh->errstr. "\ndoing statement: $statement";
229 }
230
231 #not really sample data (and shouldn't default to US)
232
233 #cust_main_county
234
235 #USPS state codes
236 foreach ( qw(
237 AL AK AS AZ AR CA CO CT DC DE FM FL GA GU HI ID IL IN IA KS KY LA
238 ME MH MD MA MI MN MS MO MT NC ND NE NH NJ NM NV NY MP OH OK OR PA PW PR RI 
239 SC SD TN TX UT VT VI VA WA WV WI WY AE AA AP
240 ) ) {
241   my($cust_main_county)=new FS::cust_main_county({
242     'state' => $_,
243     'tax'   => 0,
244     'country' => 'US',
245   });  
246   my($error);
247   $error=$cust_main_county->insert;
248   die $error if $error;
249 }
250
251 #AU "offical" state codes ala mark.williamson@ebbs.com.au (Mark Williamson)
252 foreach ( qw(
253 VIC NSW NT QLD TAS ACT WA SA
254 ) ) {
255   my($cust_main_county)=new FS::cust_main_county({
256     'state' => $_,
257     'tax'   => 0,
258     'country' => 'AU',
259   });  
260   my($error);
261   $error=$cust_main_county->insert;
262   die $error if $error;
263 }
264
265 #ISO 2-letter country codes (same as country TLDs) except US and AU
266 foreach ( qw(
267 AF AL DZ AS AD AO AI AQ AG AR AM AW AT AZ BS BH BD BB BY BE BZ BJ BM BT BO
268 BA BW BV BR IO BN BG BF BI KH CM CA CV KY CF TD CL CN CX CC CO KM CG CK CR CI
269 HR CU CY CZ DK DJ DM DO TP EC EG SV GQ ER EE ET FK FO FJ FI FR FX GF PF TF GA
270 GM GE DE GH GI GR GL GD GP GU GT GN GW GY HT HM HN HK HU IS IN ID IR IQ IE IL
271 IT JM JP JO KZ KE KI KP KR KW KG LA LV LB LS LR LY LI LT LU MO MK MG MW MY MV
272 ML MT MH MQ MR MU YT MX FM MD MC MN MS MA MZ MM NA NR NP NL AN NC NZ NI NE NG
273 NU NF MP NO OM PK PW PA PG PY PE PH PN PL PT PR QA RE RO RU RW KN LC VC WS SM
274 ST SA SN SC SL SG SK SI SB SO ZA GS ES LK SH PM SD SR SJ SZ SE CH SY TW TJ TZ
275 TH TG TK TO TT TN TR TM TC TV UG UA AE GB UM UY UZ VU VA VE VN VG VI WF EH
276 YE YU ZR ZM ZW
277 ) ) {
278   my($cust_main_county)=new FS::cust_main_county({
279     'tax'   => 0,
280     'country' => $_,
281   });  
282   my($error);
283   $error=$cust_main_county->insert;
284   die $error if $error;
285 }
286
287 #billing events
288 foreach my $aref ( 
289   [ 'COMP', 'Comp invoice', '$cust_bill->comp();', 30, 'comp' ],
290   [ 'CARD', 'Batch card', '$cust_bill->batch_card();', 40, 'batch-card' ],
291   [ 'BILL', 'Send invoice', '$cust_bill->send();', 50, 'send' ],
292 ) {
293
294   my $part_bill_event = new FS::part_bill_event({
295     'payby' => $aref->[0],
296     'event' => $aref->[1],
297     'eventcode' => $aref->[2],
298     'seconds' => 0,
299     'weight' => $aref->[3],
300     'plan' => $aref->[4],
301   });
302   my($error);
303   $error=$part_bill_event->insert;
304   die $error if $error;
305
306 }
307
308 $dbh->commit or die $dbh->errstr;
309 $dbh->disconnect or die $dbh->errstr;
310
311 print "Freeside database initialized sucessfully\n";
312
313 sub usage {
314   die "Usage:\n  fs-setup user\n"; 
315 }
316
317 ###
318 # Now it becomes an object.  much better.
319 ###
320 sub tables_hash_hack {
321
322   #note that s/(date|change)/_$1/; to avoid keyword conflict.
323   #put a kludge in FS::Record to catch this or? (pry need some date-handling
324   #stuff anyway also)
325
326   my(%tables)=( #yech.}
327
328     'agent' => {
329       'columns' => [
330         'agentnum', 'int',            '',     '',
331         'agent',    'varchar',           '',     $char_d,
332         'typenum',  'int',            '',     '',
333         'freq',     'int',       'NULL', '',
334         'prog',     @perl_type,
335       ],
336       'primary_key' => 'agentnum',
337       'unique' => [ [] ],
338       'index' => [ ['typenum'] ],
339     },
340
341     'agent_type' => {
342       'columns' => [
343         'typenum',   'int',  '', '',
344         'atype',     'varchar', '', $char_d,
345       ],
346       'primary_key' => 'typenum',
347       'unique' => [ [] ],
348       'index' => [ [] ],
349     },
350
351     'type_pkgs' => {
352       'columns' => [
353         'typenum',   'int',  '', '',
354         'pkgpart',   'int',  '', '',
355       ],
356       'primary_key' => '',
357       'unique' => [ ['typenum', 'pkgpart'] ],
358       'index' => [ ['typenum'] ],
359     },
360
361     'cust_bill' => {
362       'columns' => [
363         'invnum',    'int',  '', '',
364         'custnum',   'int',  '', '',
365         '_date',     @date_type,
366         'charged',   @money_type,
367         'printed',   'int',  '', '',
368         'closed',    'char', 'NULL', 1,
369       ],
370       'primary_key' => 'invnum',
371       'unique' => [ [] ],
372       'index' => [ ['custnum'] ],
373     },
374
375     'cust_bill_event' => {
376       'columns' => [
377         'eventnum',    'int',  '', '',
378         'invnum',   'int',  '', '',
379         'eventpart',   'int',  '', '',
380         '_date',     @date_type,
381         'status', 'varchar', '', $char_d,
382         'statustext', 'text', 'NULL', '',
383       ],
384       'primary_key' => 'eventnum',
385       'unique' => [ [ 'eventpart', 'invnum' ] ],
386       'index' => [ ['invnum'], ['status'] ],
387     },
388
389     'part_bill_event' => {
390       'columns' => [
391         'eventpart',    'int',  '', '',
392         'payby',       'char',  '', 4,
393         'event',       'varchar',           '',     $char_d,
394         'eventcode',    @perl_type,
395         'seconds',     'int', 'NULL', '',
396         'weight',      'int', '', '',
397         'plan',       'varchar', 'NULL', $char_d,
398         'plandata',   'text', 'NULL', '',
399         'disabled',     'char', 'NULL', 1,
400       ],
401       'primary_key' => 'eventpart',
402       'unique' => [ [] ],
403       'index' => [ ['payby'] ],
404     },
405
406     'cust_bill_pkg' => {
407       'columns' => [
408         'pkgnum',  'int', '', '',
409         'invnum',  'int', '', '',
410         'setup',   @money_type,
411         'recur',   @money_type,
412         'sdate',   @date_type,
413         'edate',   @date_type,
414       ],
415       'primary_key' => '',
416       'unique' => [ ['pkgnum', 'invnum'] ],
417       'index' => [ ['invnum'] ],
418     },
419
420     'cust_credit' => {
421       'columns' => [
422         'crednum',  'int', '', '',
423         'custnum',  'int', '', '',
424         '_date',    @date_type,
425         'amount',   @money_type,
426         'otaker',   'varchar', '', 8,
427         'reason',   'text', 'NULL', '',
428         'closed',    'char', 'NULL', 1,
429       ],
430       'primary_key' => 'crednum',
431       'unique' => [ [] ],
432       'index' => [ ['custnum'] ],
433     },
434
435     'cust_credit_bill' => {
436       'columns' => [
437         'creditbillnum', 'int', '', '',
438         'crednum',  'int', '', '',
439         'invnum',  'int', '', '',
440         '_date',    @date_type,
441         'amount',   @money_type,
442       ],
443       'primary_key' => 'creditbillnum',
444       'unique' => [ [] ],
445       'index' => [ ['crednum'], ['invnum'] ],
446     },
447
448     'cust_main' => {
449       'columns' => [
450         'custnum',  'int',  '',     '',
451         'agentnum', 'int',  '',     '',
452 #        'titlenum', 'int',  'NULL',   '',
453         'last',     'varchar', '',     $char_d,
454 #        'middle',   'varchar', 'NULL', $char_d,
455         'first',    'varchar', '',     $char_d,
456         'ss',       'char', 'NULL', 11,
457         'company',  'varchar', 'NULL', $char_d,
458         'address1', 'varchar', '',     $char_d,
459         'address2', 'varchar', 'NULL', $char_d,
460         'city',     'varchar', '',     $char_d,
461         'county',   'varchar', 'NULL', $char_d,
462         'state',    'varchar', 'NULL', $char_d,
463         'zip',      'varchar', '',     10,
464         'country',  'char', '',     2,
465         'daytime',  'varchar', 'NULL', 20,
466         'night',    'varchar', 'NULL', 20,
467         'fax',      'varchar', 'NULL', 12,
468         'ship_last',     'varchar', 'NULL', $char_d,
469 #        'ship_middle',   'varchar', 'NULL', $char_d,
470         'ship_first',    'varchar', 'NULL', $char_d,
471         'ship_company',  'varchar', 'NULL', $char_d,
472         'ship_address1', 'varchar', 'NULL', $char_d,
473         'ship_address2', 'varchar', 'NULL', $char_d,
474         'ship_city',     'varchar', 'NULL', $char_d,
475         'ship_county',   'varchar', 'NULL', $char_d,
476         'ship_state',    'varchar', 'NULL', $char_d,
477         'ship_zip',      'varchar', 'NULL', 10,
478         'ship_country',  'char', 'NULL', 2,
479         'ship_daytime',  'varchar', 'NULL', 20,
480         'ship_night',    'varchar', 'NULL', 20,
481         'ship_fax',      'varchar', 'NULL', 12,
482         'payby',    'char', '',     4,
483         'payinfo',  'varchar', 'NULL', $char_d,
484         #'paydate',  @date_type,
485         'paydate',  'varchar', 'NULL', 10,
486         'payname',  'varchar', 'NULL', $char_d,
487         'tax',      'char', 'NULL', 1,
488         'otaker',   'varchar', '',     8,
489         'refnum',   'int',  '',     '',
490         'referral_custnum', 'int',  'NULL', '',
491         'comments', 'text', 'NULL', '',
492       ],
493       'primary_key' => 'custnum',
494       'unique' => [ [] ],
495       #'index' => [ ['last'], ['company'] ],
496       'index' => [ ['last'], [ 'company' ], [ 'referral_custnum' ] ],
497     },
498
499     'cust_main_invoice' => {
500       'columns' => [
501         'destnum',  'int',  '',     '',
502         'custnum',  'int',  '',     '',
503         'dest',     'varchar', '',  $char_d,
504       ],
505       'primary_key' => 'destnum',
506       'unique' => [ [] ],
507       'index' => [ ['custnum'], ],
508     },
509
510     'cust_main_county' => { #county+state+country are checked off the
511                             #cust_main_county for validation and to provide
512                             # a tax rate.
513       'columns' => [
514         'taxnum',   'int',   '',    '',
515         'state',    'varchar',  'NULL',    $char_d,
516         'county',   'varchar',  'NULL',    $char_d,
517         'country',  'char',  '', 2, 
518         'tax',      'real',  '',    '', #tax %
519       ],
520       'primary_key' => 'taxnum',
521       'unique' => [ [] ],
522   #    'unique' => [ ['taxnum'], ['state', 'county'] ],
523       'index' => [ [] ],
524     },
525
526     'cust_pay' => {
527       'columns' => [
528         'paynum',   'int',    '',   '',
529         #now cust_bill_pay #'invnum',   'int',    '',   '',
530         'custnum',  'int',    '',   '',
531         'paid',     @money_type,
532         '_date',    @date_type,
533         'payby',    'char',   '',     4, # CARD/BILL/COMP, should be index into
534                                          # payment type table.
535         'payinfo',  'varchar',   'NULL', 16,  #see cust_main above
536         'paybatch', 'varchar',   'NULL', $char_d, #for auditing purposes.
537         'closed',    'char', 'NULL', 1,
538       ],
539       'primary_key' => 'paynum',
540       'unique' => [ [] ],
541       'index' => [ [ 'custnum' ], [ 'paybatch' ] ],
542     },
543
544     'cust_bill_pay' => {
545       'columns' => [
546         'billpaynum', 'int',     '',   '',
547         'invnum',  'int',     '',   '',
548         'paynum',  'int',     '',   '',
549         'amount',  @money_type,
550         '_date',   @date_type
551       ],
552       'primary_key' => 'billpaynum',
553       'unique' => [ [] ],
554       'index' => [ [ 'paynum' ], [ 'invnum' ] ],
555     },
556
557     'cust_pay_batch' => { #what's this used for again?  list of customers
558                           #in current CARD batch? (necessarily CARD?)
559       'columns' => [
560         'paybatchnum',   'int',    '',   '',
561         'invnum',   'int',    '',   '',
562         'custnum',   'int',    '',   '',
563         'last',     'varchar', '',     $char_d,
564         'first',    'varchar', '',     $char_d,
565         'address1', 'varchar', '',     $char_d,
566         'address2', 'varchar', 'NULL', $char_d,
567         'city',     'varchar', '',     $char_d,
568         'state',    'varchar', '',     $char_d,
569         'zip',      'varchar', '',     10,
570         'country',  'char', '',     2,
571 #        'trancode', 'int', '', '',
572         'cardnum',  'varchar', '',     16,
573         #'exp',      @date_type,
574         'exp',      'varchar', '',     11,
575         'payname',  'varchar', 'NULL', $char_d,
576         'amount',   @money_type,
577       ],
578       'primary_key' => 'paybatchnum',
579       'unique' => [ [] ],
580       'index' => [ ['invnum'], ['custnum'] ],
581     },
582
583     'cust_pkg' => {
584       'columns' => [
585         'pkgnum',    'int',    '',   '',
586         'custnum',   'int',    '',   '',
587         'pkgpart',   'int',    '',   '',
588         'otaker',    'varchar', '', 8,
589         'setup',     @date_type,
590         'bill',      @date_type,
591         'susp',      @date_type,
592         'cancel',    @date_type,
593         'expire',    @date_type,
594         'manual_flag', 'char', 'NULL', 1,
595       ],
596       'primary_key' => 'pkgnum',
597       'unique' => [ [] ],
598       'index' => [ ['custnum'] ],
599     },
600
601     'cust_refund' => {
602       'columns' => [
603         'refundnum',    'int',    '',   '',
604         #now cust_credit_refund #'crednum',      'int',    '',   '',
605         'custnum',  'int',    '',   '',
606         '_date',        @date_type,
607         'refund',       @money_type,
608         'otaker',       'varchar',   '',   8,
609         'reason',       'varchar',   '',   $char_d,
610         'payby',        'char',   '',     4, # CARD/BILL/COMP, should be index
611                                              # into payment type table.
612         'payinfo',      'varchar',   'NULL', 16,  #see cust_main above
613         'paybatch',     'varchar',   'NULL', $char_d,
614         'closed',    'char', 'NULL', 1,
615       ],
616       'primary_key' => 'refundnum',
617       'unique' => [ [] ],
618       'index' => [ [] ],
619     },
620
621     'cust_credit_refund' => {
622       'columns' => [
623         'creditrefundnum', 'int',     '',   '',
624         'crednum',  'int',     '',   '',
625         'refundnum',  'int',     '',   '',
626         'amount',  @money_type,
627         '_date',   @date_type
628       ],
629       'primary_key' => 'creditrefundnum',
630       'unique' => [ [] ],
631       'index' => [ [ 'crednum', 'refundnum' ] ],
632     },
633
634
635     'cust_svc' => {
636       'columns' => [
637         'svcnum',    'int',    '',   '',
638         'pkgnum',    'int',    'NULL',   '',
639         'svcpart',   'int',    '',   '',
640       ],
641       'primary_key' => 'svcnum',
642       'unique' => [ [] ],
643       'index' => [ ['svcnum'], ['pkgnum'], ['svcpart'] ],
644     },
645
646     'part_pkg' => {
647       'columns' => [
648         'pkgpart',    'int',    '',   '',
649         'pkg',        'varchar',   '',   $char_d,
650         'comment',    'varchar',   '',   $char_d,
651         'setup',      @perl_type,
652         'freq',       'int', '', '',  #billing frequency (months)
653         'recur',      @perl_type,
654         'setuptax',  'char', 'NULL', 1,
655         'recurtax',  'char', 'NULL', 1,
656         'plan',       'varchar', 'NULL', $char_d,
657         'plandata',   'text', 'NULL', '',
658         'disabled',   'char', 'NULL', 1,
659       ],
660       'primary_key' => 'pkgpart',
661       'unique' => [ [] ],
662       'index' => [ [] ],
663     },
664
665 #    'part_title' => {
666 #      'columns' => [
667 #        'titlenum',   'int',    '',   '',
668 #        'title',      'varchar',   '',   $char_d,
669 #      ],
670 #      'primary_key' => 'titlenum',
671 #      'unique' => [ [] ],
672 #      'index' => [ [] ],
673 #    },
674
675     'pkg_svc' => {
676       'columns' => [
677         'pkgpart',    'int',    '',   '',
678         'svcpart',    'int',    '',   '',
679         'quantity',   'int',    '',   '',
680       ],
681       'primary_key' => '',
682       'unique' => [ ['pkgpart', 'svcpart'] ],
683       'index' => [ ['pkgpart'] ],
684     },
685
686     'part_referral' => {
687       'columns' => [
688         'refnum',   'int',    '',   '',
689         'referral', 'varchar',   '',   $char_d,
690       ],
691       'primary_key' => 'refnum',
692       'unique' => [ [] ],
693       'index' => [ [] ],
694     },
695
696     'part_svc' => {
697       'columns' => [
698         'svcpart',    'int',    '',   '',
699         'svc',        'varchar',   '',   $char_d,
700         'svcdb',      'varchar',   '',   $char_d,
701         'disabled',   'char',  'NULL',   1,
702       ],
703       'primary_key' => 'svcpart',
704       'unique' => [ [] ],
705       'index' => [ [] ],
706     },
707
708     'part_svc_column' => {
709       'columns' => [
710         'columnnum',   'int',         '', '',
711         'svcpart',     'int',         '', '',
712         'columnname',  'varchar',     '', 64,
713         'columnvalue', 'varchar', 'NULL', $char_d,
714         'columnflag',  'char',    'NULL', 1, 
715       ],
716       'primary_key' => 'columnnum',
717       'unique' => [ [ 'svcpart', 'columnname' ] ],
718       'index' => [ [ 'svcpart' ] ],
719     },
720
721     #(this should be renamed to part_pop)
722     'svc_acct_pop' => {
723       'columns' => [
724         'popnum',    'int',    '',   '',
725         'city',      'varchar',   '',   $char_d,
726         'state',     'varchar',   '',   $char_d,
727         'ac',        'char',   '',   3,
728         'exch',      'char',   '',   3,
729         'loc',       'char',   'NULL',   4, #NULL for legacy purposes
730       ],
731       'primary_key' => 'popnum',
732       'unique' => [ [] ],
733       'index' => [ [ 'state' ] ],
734     },
735
736     'part_pop_local' => {
737       'columns' => [
738         'localnum',  'int',     '',     '',
739         'popnum',    'int',     '',     '',
740         'city',      'varchar', 'NULL', $char_d,
741         'state',     'char',    'NULL', 2,
742         'npa',       'char',    '',     3,
743         'nxx',       'char',    '',     3,
744       ],
745       'primary_key' => 'popnum',
746       'unique' => [ [] ],
747       'index' => [ [ 'npa', 'nxx' ] ],
748     },
749
750     'svc_acct' => {
751       'columns' => [
752         'svcnum',    'int',    '',   '',
753         'username',  'varchar',   '',   $username_len, #unique (& remove dup code)
754         '_password', 'varchar',   '',   50, #13 for encryped pw's plus ' *SUSPENDED* (mp5 passwords can be 34)
755         'popnum',    'int',    'NULL',   '',
756         'uid',       'int', 'NULL',   '',
757         'gid',       'int', 'NULL',   '',
758         'finger',    'varchar',   'NULL',   $char_d,
759         'dir',       'varchar',   'NULL',   $char_d,
760         'shell',     'varchar',   'NULL',   $char_d,
761         'quota',     'varchar',   'NULL',   $char_d,
762         'slipip',    'varchar',   'NULL',   15, #four TINYINTs, bah.
763         'seconds',   'int', 'NULL',   '', #uhhhh
764         'domsvc',    'int', '',   '',
765       ],
766       'primary_key' => 'svcnum',
767       'unique' => [ [ 'username', 'domsvc' ] ],
768       'index' => [ ['username'], ['domsvc'] ],
769     },
770
771 #    'svc_acct_sm' => {
772 #      'columns' => [
773 #        'svcnum',    'int',    '',   '',
774 #        'domsvc',    'int',    '',   '',
775 #        'domuid',    'int', '',   '',
776 #        'domuser',   'varchar',   '',   $char_d,
777 #      ],
778 #      'primary_key' => 'svcnum',
779 #      'unique' => [ [] ],
780 #      'index' => [ ['domsvc'], ['domuid'] ], 
781 #    },
782
783     #'svc_charge' => {
784     #  'columns' => [
785     #    'svcnum',    'int',    '',   '',
786     #    'amount',    @money_type,
787     #  ],
788     #  'primary_key' => 'svcnum',
789     #  'unique' => [ [] ],
790     #  'index' => [ [] ],
791     #},
792
793     'svc_domain' => {
794       'columns' => [
795         'svcnum',    'int',    '',   '',
796         'domain',    'varchar',    '',   $char_d,
797         'catchall',  'int', 'NULL',    '',
798       ],
799       'primary_key' => 'svcnum',
800       'unique' => [ ['domain'] ],
801       'index' => [ [] ],
802     },
803
804     'domain_record' => {
805       'columns' => [
806         'recnum',    'int',     '',  '',
807         'svcnum',    'int',     '',  '',
808         'reczone',   'varchar', '',  $char_d,
809         'recaf',     'char',    '',  2,
810         'rectype',   'char',    '',  5,
811         'recdata',   'varchar', '',  $char_d,
812       ],
813       'primary_key' => 'recnum',
814       'unique'      => [ [] ],
815       'index'       => [ ['svcnum'] ],
816     },
817
818     'svc_forward' => {
819       'columns' => [
820         'svcnum',   'int',    '',  '',
821         'srcsvc',   'int',    '',  '',
822         'dstsvc',   'int',    '',  '',
823         'dst',      'varchar',    'NULL',  $char_d,
824       ],
825       'primary_key' => 'svcnum',
826       'unique'      => [ [] ],
827       'index'       => [ ['srcsvc'], ['dstsvc'] ],
828     },
829
830     'svc_www' => {
831       'columns' => [
832         'svcnum',   'int',    '',  '',
833         'recnum',   'int',    '',  '',
834         'usersvc',  'int',    '',  '',
835       ],
836       'primary_key' => 'svcnum',
837       'unique'      => [ [] ],
838       'index'       => [ [] ],
839     },
840
841     #'svc_wo' => {
842     #  'columns' => [
843     #    'svcnum',    'int',    '',   '',
844     #    'svcnum',    'int',    '',   '',
845     #    'svcnum',    'int',    '',   '',
846     #    'worker',    'varchar',   '',   $char_d,
847     #    '_date',     @date_type,
848     #  ],
849     #  'primary_key' => 'svcnum',
850     #  'unique' => [ [] ],
851     #  'index' => [ [] ],
852     #},
853
854     'prepay_credit' => {
855       'columns' => [
856         'prepaynum',   'int',     '',   '',
857         'identifier',  'varchar', '', $char_d,
858         'amount',      @money_type,
859         'seconds',     'int',     'NULL', '',
860       ],
861       'primary_key' => 'prepaynum',
862       'unique'      => [ ['identifier'] ],
863       'index'       => [ [] ],
864     },
865
866     'port' => {
867       'columns' => [
868         'portnum',  'int',     '',   '',
869         'ip',       'varchar', 'NULL', 15,
870         'nasport',  'int',     'NULL', '',
871         'nasnum',   'int',     '',   '',
872       ],
873       'primary_key' => 'portnum',
874       'unique'      => [],
875       'index'       => [],
876     },
877
878     'nas' => {
879       'columns' => [
880         'nasnum',   'int',     '',    '',
881         'nas',      'varchar', '',    $char_d,
882         'nasip',    'varchar', '',    15,
883         'nasfqdn',  'varchar', '',    $char_d,
884         'last',     'int',     '',    '',
885       ],
886       'primary_key' => 'nasnum',
887       'unique'      => [ [ 'nas' ], [ 'nasip' ] ],
888       'index'       => [ [ 'last' ] ],
889     },
890
891     'session' => {
892       'columns' => [
893         'sessionnum', 'int',       '',   '',
894         'portnum',    'int',       '',   '',
895         'svcnum',     'int',       '',   '',
896         'login',      @date_type,
897         'logout',     @date_type,
898       ],
899       'primary_key' => 'sessionnum',
900       'unique'      => [],
901       'index'       => [ [ 'portnum' ] ],
902     },
903
904     'queue' => {
905       'columns' => [
906         'jobnum', 'int', '', '',
907         'job', 'text', '', '',
908         '_date', 'int', '', '',
909         'status', 'varchar', '', $char_d,
910         'statustext', 'text', 'NULL', '',
911         'svcnum', 'int', 'NULL', '',
912       ],
913       'primary_key' => 'jobnum',
914       'unique'      => [],
915       'index'       => [ [ 'svcnum' ], [ 'status' ] ],
916     },
917
918     'queue_arg' => {
919       'columns' => [
920         'argnum', 'int', '', '',
921         'jobnum', 'int', '', '',
922         'arg', 'text', 'NULL', '',
923       ],
924       'primary_key' => 'argnum',
925       'unique'      => [],
926       'index'       => [ [ 'jobnum' ] ],
927     },
928
929     'part_export' => {
930       'columns' => [
931         'exportnum', 'int', '', '',
932         'svcpart',   'int', '', '',
933         'machine', 'varchar', '', $char_d,
934         'exporttype', 'varchar', '', $char_d,
935         'nodomain',     'char', 'NULL', 1,
936       ],
937       'primary_key' => 'exportnum',
938       'unique'      => [],
939       'index'       => [ [ 'machine' ], [ 'exporttype' ] ],
940     },
941
942     'part_export_option' => {
943       'columns' => [
944         'optionnum', 'int', '', '',
945         'exportnum', 'int', '', '',
946         'optionname', 'varchar', '', $char_d,
947         'optionvalue', 'text', 'NULL', '',
948       ],
949       'primary_key' => 'optionnum',
950       'unique'      => [],
951       'index'       => [ [ 'exportnum' ], [ 'optionname' ] ],
952     },
953
954     'radius_usergroup' => {
955       'columns' => [
956         'usergroupnum', 'int', '', '',
957         'svcnum',       'int', '', '',
958         'groupname',    'varchar', '', $char_d,
959       ],
960       'primary_key' => 'usergroupnum',
961       'unique'      => [],
962       'index'       => [ [ 'svcnum' ], [ 'groupname' ] ],
963     },
964
965   );
966
967   %tables;
968
969 }
970