merging vpopmail support branch
[freeside.git] / bin / fs-setup
1 #!/usr/bin/perl -Tw
2 #
3 # $Id: fs-setup,v 1.41 2001-08-12 19:41:25 jeff Exp $
4 #
5 # ivan@sisd.com 97-nov-8,9
6 #
7 # agent_type and type_pkgs added.
8 # (index need to be declared, & primary keys shoudln't have mysql syntax)
9 # ivan@sisd.com 97-nov-13
10 #
11 # pulled modified version back out of register.cgi ivan@sisd.com 98-feb-21
12 #
13 # removed extraneous sample data ivan@sisd.com 98-mar-23
14 #
15 # gained the big hash from dbdef.pm, dbdef.pm usage rewrite ivan@sisd.com
16 # 98-apr-19 - 98-may-11 plus
17 #
18 # finished up ivan@sisd.com 98-jun-1
19 #
20 # part_svc fields are all forced NULL, not the opposite
21 # hmm: also are forced varchar($char_d) as fixed '0' for things like
22 # uid is Not Good.  will this break anything else?
23 # ivan@sisd.com 98-jun-29
24 #
25 # ss is 11 chars ivan@sisd.com 98-jul-20
26 #
27 # setup of arbitrary radius fields ivan@sisd.com 98-aug-9
28 #
29 # ouch, removed index on company name that wasn't supposed to be there
30 # ivan@sisd.com 98-sep-4
31 #
32 # fix radius attributes ivan@sisd.com 98-sep-27
33 #
34 # $Log: fs-setup,v $
35 # Revision 1.41  2001-08-12 19:41:25  jeff
36 # merging vpopmail support branch
37 #
38 # Revision 1.40  2001/08/11 05:53:42  ivan
39 # add comments field
40 #
41 # Revision 1.39  2001/07/30 07:42:39  ivan
42 # need an DBIx::DBSchema with delcolumn
43 #
44 # Revision 1.38  2001/07/30 07:36:04  ivan
45 # templates!!!
46 #
47 # Revision 1.37  2001/06/03 14:16:11  ivan
48 # allow empty refund reasons
49 #
50 # Revision 1.36  2001/04/15 12:56:31  ivan
51 # s/dbdef/DBIx::DBSchema/
52 #
53 # Revision 1.35  2001/04/15 09:36:43  ivan
54 # http://www.sisd.com/freeside/list-archive/msg01450.html
55 #
56 # Revision 1.34  2001/04/09 23:05:16  ivan
57 # Transactions Part I!!!
58 #
59 # Revision 1.33  2001/02/03 14:03:50  ivan
60 # time-based prepaid cards, session monitor.  woop!
61 #
62 # Revision 1.32  2000/12/04 00:13:02  ivan
63 # fix nas.last type
64 #
65 # Revision 1.31  2000/12/01 18:34:53  ivan
66 # another tyop
67 #
68 # Revision 1.30  2000/12/01 18:33:32  ivan
69 # tyop
70 #
71 # Revision 1.29  2000/11/07 15:00:37  ivan
72 # session monitor
73 #
74 # Revision 1.28  2000/10/30 10:47:26  ivan
75 # nas.last can't be defined NULL if indexed
76 #
77 # Revision 1.26  2000/07/06 08:57:27  ivan
78 # support for radius check attributes (except importing).  poorly documented.
79 #
80 # Revision 1.25  2000/06/29 12:00:49  ivan
81 # support for pre-encrypted md5 passwords.
82 #
83 # Revision 1.24  2000/03/02 07:44:07  ivan
84 # typo forgot closing '
85 #
86 # Revision 1.23  2000/02/03 05:16:52  ivan
87 # beginning of DNS and Apache support
88 #
89 # Revision 1.22  2000/01/31 05:22:23  ivan
90 # prepaid "internet cards"
91 #
92 # Revision 1.21  2000/01/30 06:03:26  ivan
93 # postgres 6.5 finally supports decimal(10,2)
94 #
95 # Revision 1.20  2000/01/28 22:53:33  ivan
96 # track full phone number
97 #
98 # Revision 1.19  1999/07/29 08:50:35  ivan
99 # wrong type for cust_pay_batch.exp
100 #
101 # Revision 1.18  1999/04/15 22:46:30  ivan
102 # TT isn't a state!
103 #
104 # Revision 1.17  1999/04/14 07:58:39  ivan
105 # export getsecrets from FS::UID instead of calling it explicitly
106 #
107 # Revision 1.16  1999/02/28 19:44:16  ivan
108 # constructors s/create/new/ pointed out by "Bao C. Ha" <bao@hacom.net>
109 #
110 # Revision 1.15  1999/02/27 21:06:21  ivan
111 # cust_main.paydate should be varchar(10), not @date_type ; problem reported
112 # by Ben Leibig <leibig@colorado.edu>
113 #
114 # Revision 1.14  1999/02/07 09:59:14  ivan
115 # more mod_perl fixes, and bugfixes Peter Wemm sent via email
116 #
117 # Revision 1.13  1999/02/04 06:09:23  ivan
118 # add AU provences
119 #
120 # Revision 1.12  1999/02/03 10:42:27  ivan
121 # *** empty log message ***
122 #
123 # Revision 1.11  1999/01/17 03:11:52  ivan
124 # remove preliminary completehost changes
125 #
126 # Revision 1.10  1998/12/16 06:05:38  ivan
127 # add table cust_main_invoice
128 #
129 # Revision 1.9  1998/12/15 04:36:29  ivan
130 # s/croak/die/; #oops
131 #
132 # Revision 1.8  1998/12/15 04:33:27  ivan
133 # dies if it isn't running as the freeside user
134 #
135 # Revision 1.7  1998/11/18 09:01:31  ivan
136 # i18n! i18n!
137 #
138 # Revision 1.6  1998/11/15 13:18:02  ivan
139 # remove debugging
140 #
141 # Revision 1.5  1998/11/15 09:43:03  ivan
142 # update for new config file syntax, new adminsuidsetup
143 #
144 # Revision 1.4  1998/10/22 15:51:23  ivan
145 # also varchar with no length specified - postgresql fix broke mysql.
146 #
147 # Revision 1.3  1998/10/22 15:46:28  ivan
148 # now smallint is illegal, so remove that too.
149 #
150
151 #to delay loading dbdef until we're ready
152 BEGIN { $FS::Record::setup_hack = 1; }
153
154 use strict;
155 use DBI;
156 use DBIx::DBSchema 0.18;
157 use DBIx::DBSchema::Table;
158 use DBIx::DBSchema::Column;
159 use DBIx::DBSchema::ColGroup::Unique;
160 use DBIx::DBSchema::ColGroup::Index;
161 use FS::UID qw(adminsuidsetup datasrc checkeuid getsecrets);
162 use FS::Record;
163 use FS::cust_main_county;
164
165 die "Not running uid freeside!" unless checkeuid();
166
167 my $user = shift or die &usage;
168 getsecrets($user);
169
170 #needs to match FS::Record
171 my($dbdef_file) = "/usr/local/etc/freeside/dbdef.". datasrc;
172
173 ###
174
175 print "\nEnter the maximum username length: ";
176 my($username_len)=&getvalue;
177
178 print "\n\n", <<END, ":";
179 Freeside tracks the RADIUS attributes User-Name, check attribute Password and
180 reply attribute Framed-IP-Address for each user.  You can specify additional
181 check and reply attributes.  First enter any additional RADIUS check attributes
182 you need to track for each user, separated by whitespace.
183 END
184 my @check_attributes = map { s/\-/_/g; $_; } split(" ",&getvalue);
185
186 print "\n\n", <<END, ":";
187 Now enter any additional reply attributes you need to track for each user,
188 separated by whitespace.
189 END
190 my @attributes = map { s/\-/_/g; $_; } split(" ",&getvalue);
191
192 print "\n\n", <<END, ":";
193 Do you wish to enable the tracking of a second, separate shipping/service
194 address?
195 END
196 my $ship = &_yesno;
197
198 sub getvalue {
199   my($x)=scalar(<STDIN>);
200   chop $x;
201   $x;
202 }
203
204 sub _yesno {
205   print " [y/N]:";
206   my $x = scalar(<STDIN>);
207   $x =~ /^y/i;
208 }
209
210 ###
211
212 my($char_d) = 80; #default maxlength for text fields
213
214 #my(@date_type)  = ( 'timestamp', '', ''     );
215 my(@date_type)  = ( 'int', 'NULL', ''     );
216 my(@perl_type) = ( 'varchar', 'NULL', 255  ); 
217 my @money_type = ( 'decimal',   '', '10,2' );
218
219 ###
220 # create a dbdef object from the old data structure
221 ###
222
223 my(%tables)=&tables_hash_hack;
224
225 #turn it into objects
226 my($dbdef) = new DBIx::DBSchema ( map {  
227   my(@columns);
228   while (@{$tables{$_}{'columns'}}) {
229     my($name,$type,$null,$length)=splice @{$tables{$_}{'columns'}}, 0, 4;
230     push @columns, new DBIx::DBSchema::Column ( $name,$type,$null,$length );
231   }
232   DBIx::DBSchema::Table->new(
233     $_,
234     $tables{$_}{'primary_key'},
235     DBIx::DBSchema::ColGroup::Unique->new($tables{$_}{'unique'}),
236     DBIx::DBSchema::ColGroup::Index->new($tables{$_}{'index'}),
237     @columns,
238   );
239 } (keys %tables) );
240
241 #remove ship_ from cust_main
242 unless ($ship) {
243   my $cust_main = $dbdef->table('cust_main');
244   $cust_main->delcolumn($_) foreach ( grep /^ship_/, $cust_main->columns );
245 }
246
247 #add radius attributes to svc_acct
248
249 my($svc_acct)=$dbdef->table('svc_acct');
250
251 my($attribute);
252 foreach $attribute (@attributes) {
253   $svc_acct->addcolumn ( new DBIx::DBSchema::Column (
254     'radius_'. $attribute,
255     'varchar',
256     'NULL',
257     $char_d,
258   ));
259 }
260
261 foreach $attribute (@check_attributes) {
262   $svc_acct->addcolumn( new DBIx::DBSchema::Column (
263     'rc_'. $attribute,
264     'varchar',
265     'NULL',
266     $char_d,
267   ));
268 }
269
270 #make part_svc table (but now as object)
271
272 my($part_svc)=$dbdef->table('part_svc');
273
274 #because of svc_acct_pop
275 #foreach (grep /^svc_/, $dbdef->tables) { 
276 #foreach (qw(svc_acct svc_acct_sm svc_charge svc_domain svc_wo)) {
277 foreach (qw(svc_acct svc_acct_sm svc_domain svc_forward svc_www)) {
278   my($table)=$dbdef->table($_);
279   my($col);
280   foreach $col ( $table->columns ) {
281     next if $col =~ /^svcnum$/;
282     $part_svc->addcolumn( new DBIx::DBSchema::Column (
283       $table->name. '__' . $table->column($col)->name,
284       'varchar', #$table->column($col)->type, 
285       'NULL',
286       $char_d, #$table->column($col)->length,
287     ));
288     $part_svc->addcolumn ( new DBIx::DBSchema::Column (
289       $table->name. '__'. $table->column($col)->name . "_flag",
290       'char',
291       'NULL',
292       1,
293     ));
294   }
295 }
296
297 #important
298 $dbdef->save($dbdef_file);
299 &FS::Record::reload_dbdef($dbdef_file);
300
301 ###
302 # create 'em
303 ###
304
305 my($dbh)=adminsuidsetup $user;
306
307 #create tables
308 $|=1;
309
310 my @sql = $dbdef->sql($dbh);
311 foreach my $statement ( $dbdef->sql($dbh) ) {
312   $dbh->do( $statement )
313     or die "CREATE error: ",$dbh->errstr, "\ndoing statement: $statement";
314 }
315
316 #not really sample data (and shouldn't default to US)
317
318 #cust_main_county
319
320 #USPS state codes
321 foreach ( qw(
322 AL AK AS AZ AR CA CO CT DC DE FM FL GA GU HI ID IL IN IA KS KY LA
323 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 
324 SC SD TN TX UT VT VI VA WA WV WI WY AE AA AP
325 ) ) {
326   my($cust_main_county)=new FS::cust_main_county({
327     'state' => $_,
328     'tax'   => 0,
329     'country' => 'US',
330   });  
331   my($error);
332   $error=$cust_main_county->insert;
333   die $error if $error;
334 }
335
336 #AU "offical" state codes ala mark.williamson@ebbs.com.au (Mark Williamson)
337 foreach ( qw(
338 VIC NSW NT QLD TAS ACT WA SA
339 ) ) {
340   my($cust_main_county)=new FS::cust_main_county({
341     'state' => $_,
342     'tax'   => 0,
343     'country' => 'AU',
344   });  
345   my($error);
346   $error=$cust_main_county->insert;
347   die $error if $error;
348 }
349
350 #ISO 2-letter country codes (same as country TLDs) except US and AU
351 foreach ( qw(
352 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
353 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
354 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
355 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
356 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
357 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
358 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
359 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
360 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
361 YE YU ZR ZM ZW
362 ) ) {
363   my($cust_main_county)=new FS::cust_main_county({
364     'tax'   => 0,
365     'country' => $_,
366   });  
367   my($error);
368   $error=$cust_main_county->insert;
369   die $error if $error;
370 }
371
372 $dbh->disconnect or die $dbh->errstr;
373
374 print "Freeside database initialized sucessfully\n";
375
376 sub usage {
377   die "Usage:\n  fs-setup user\n"; 
378 }
379
380 ###
381 # Now it becomes an object.  much better.
382 ###
383 sub tables_hash_hack {
384
385   #note that s/(date|change)/_$1/; to avoid keyword conflict.
386   #put a kludge in FS::Record to catch this or? (pry need some date-handling
387   #stuff anyway also)
388
389   my(%tables)=( #yech.}
390
391     'agent' => {
392       'columns' => [
393         'agentnum', 'int',            '',     '',
394         'agent',    'varchar',           '',     $char_d,
395         'typenum',  'int',            '',     '',
396         'freq',     'int',       'NULL', '',
397         'prog',     @perl_type,
398       ],
399       'primary_key' => 'agentnum',
400       'unique' => [ [] ],
401       'index' => [ ['typenum'] ],
402     },
403
404     'agent_type' => {
405       'columns' => [
406         'typenum',   'int',  '', '',
407         'atype',     'varchar', '', $char_d,
408       ],
409       'primary_key' => 'typenum',
410       'unique' => [ [] ],
411       'index' => [ [] ],
412     },
413
414     'type_pkgs' => {
415       'columns' => [
416         'typenum',   'int',  '', '',
417         'pkgpart',   'int',  '', '',
418       ],
419       'primary_key' => '',
420       'unique' => [ ['typenum', 'pkgpart'] ],
421       'index' => [ ['typenum'] ],
422     },
423
424     'cust_bill' => {
425       'columns' => [
426         'invnum',    'int',  '', '',
427         'custnum',   'int',  '', '',
428         '_date',     @date_type,
429         'charged',   @money_type,
430         'printed',   'int',  '', '',
431       ],
432       'primary_key' => 'invnum',
433       'unique' => [ [] ],
434       'index' => [ ['custnum'] ],
435     },
436
437     'cust_bill_pkg' => {
438       'columns' => [
439         'pkgnum',  'int', '', '',
440         'invnum',  'int', '', '',
441         'setup',   @money_type,
442         'recur',   @money_type,
443         'sdate',   @date_type,
444         'edate',   @date_type,
445       ],
446       'primary_key' => '',
447       'unique' => [ ['pkgnum', 'invnum'] ],
448       'index' => [ ['invnum'] ],
449     },
450
451     'cust_credit' => {
452       'columns' => [
453         'crednum',  'int', '', '',
454         'custnum',  'int', '', '',
455         '_date',    @date_type,
456         'amount',   @money_type,
457         'otaker',   'varchar', '', 8,
458         'reason',   'varchar', 'NULL', 255,
459       ],
460       'primary_key' => 'crednum',
461       'unique' => [ [] ],
462       'index' => [ ['custnum'] ],
463     },
464
465     'cust_main' => {
466       'columns' => [
467         'custnum',  'int',  '',     '',
468         'agentnum', 'int',  '',     '',
469 #        'titlenum', 'int',  'NULL',   '',
470         'last',     'varchar', '',     $char_d,
471 #        'middle',   'varchar', 'NULL', $char_d,
472         'first',    'varchar', '',     $char_d,
473         'ss',       'char', 'NULL', 11,
474         'company',  'varchar', 'NULL', $char_d,
475         'address1', 'varchar', '',     $char_d,
476         'address2', 'varchar', 'NULL', $char_d,
477         'city',     'varchar', '',     $char_d,
478         'county',   'varchar', 'NULL', $char_d,
479         'state',    'varchar', 'NULL', $char_d,
480         'zip',      'varchar', '',     10,
481         'country',  'char', '',     2,
482         'daytime',  'varchar', 'NULL', 20,
483         'night',    'varchar', 'NULL', 20,
484         'fax',      'varchar', 'NULL', 12,
485         'ship_last',     'varchar', 'NULL', $char_d,
486 #        'ship_middle',   'varchar', 'NULL', $char_d,
487         'ship_first',    'varchar', 'NULL', $char_d,
488         'ship_company',  'varchar', 'NULL', $char_d,
489         'ship_address1', 'varchar', 'NULL', $char_d,
490         'ship_address2', 'varchar', 'NULL', $char_d,
491         'ship_city',     'varchar', 'NULL', $char_d,
492         'ship_county',   'varchar', 'NULL', $char_d,
493         'ship_state',    'varchar', 'NULL', $char_d,
494         'ship_zip',      'varchar', 'NULL', 10,
495         'ship_country',  'char', 'NULL', 2,
496         'ship_daytime',  'varchar', 'NULL', 20,
497         'ship_night',    'varchar', 'NULL', 20,
498         'ship_fax',      'varchar', 'NULL', 12,
499         'payby',    'char', '',     4,
500         'payinfo',  'varchar', 'NULL', 16,
501         #'paydate',  @date_type,
502         'paydate',  'varchar', 'NULL', 10,
503         'payname',  'varchar', 'NULL', $char_d,
504         'tax',      'char', 'NULL', 1,
505         'otaker',   'varchar', '',     8,
506         'refnum',   'int',  '',     '',
507         'comments', 'varchar', 'NULL', '',
508       ],
509       'primary_key' => 'custnum',
510       'unique' => [ [] ],
511       #'index' => [ ['last'], ['company'] ],
512       'index' => [ ['last'], ],
513     },
514
515     'cust_main_invoice' => {
516       'columns' => [
517         'destnum',  'int',  '',     '',
518         'custnum',  'int',  '',     '',
519         'dest',     'varchar', '',  $char_d,
520       ],
521       'primary_key' => 'destnum',
522       'unique' => [ [] ],
523       'index' => [ ['custnum'], ],
524     },
525
526     'cust_main_county' => { #county+state+country are checked off the
527                             #cust_main_county for validation and to provide
528                             # a tax rate.
529       'columns' => [
530         'taxnum',   'int',   '',    '',
531         'state',    'varchar',  'NULL',    $char_d,
532         'county',   'varchar',  'NULL',    $char_d,
533         'country',  'char',  '', 2, 
534         'tax',      'real',  '',    '', #tax %
535       ],
536       'primary_key' => 'taxnum',
537       'unique' => [ [] ],
538   #    'unique' => [ ['taxnum'], ['state', 'county'] ],
539       'index' => [ [] ],
540     },
541
542     'cust_pay' => {
543       'columns' => [
544         'paynum',   'int',    '',   '',
545         'invnum',   'int',    '',   '',
546         'paid',     @money_type,
547         '_date',    @date_type,
548         'payby',    'char',   '',     4, # CARD/BILL/COMP, should be index into
549                                          # payment type table.
550         'payinfo',  'varchar',   'NULL', 16,  #see cust_main above
551         'paybatch', 'varchar',   'NULL', $char_d, #for auditing purposes.
552       ],
553       'primary_key' => 'paynum',
554       'unique' => [ [] ],
555       'index' => [ ['invnum'] ],
556     },
557
558     'cust_pay_batch' => { #what's this used for again?  list of customers
559                           #in current CARD batch? (necessarily CARD?)
560       'columns' => [
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' => '',
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       ],
595       'primary_key' => 'pkgnum',
596       'unique' => [ [] ],
597       'index' => [ ['custnum'] ],
598     },
599
600     'cust_refund' => {
601       'columns' => [
602         'refundnum',    'int',    '',   '',
603         'crednum',      'int',    '',   '',
604         '_date',        @date_type,
605         'refund',       @money_type,
606         'otaker',       'varchar',   '',   8,
607         'reason',       'varchar',   '',   $char_d,
608         'payby',        'char',   '',     4, # CARD/BILL/COMP, should be index
609                                              # into payment type table.
610         'payinfo',      'varchar',   'NULL', 16,  #see cust_main above
611       ],
612       'primary_key' => 'refundnum',
613       'unique' => [ [] ],
614       'index' => [ ['crednum'] ],
615     },
616
617     'cust_svc' => {
618       'columns' => [
619         'svcnum',    'int',    '',   '',
620         'pkgnum',    'int',    'NULL',   '',
621         'svcpart',   'int',    '',   '',
622       ],
623       'primary_key' => 'svcnum',
624       'unique' => [ [] ],
625       'index' => [ ['svcnum'], ['pkgnum'], ['svcpart'] ],
626     },
627
628     'part_pkg' => {
629       'columns' => [
630         'pkgpart',    'int',    '',   '',
631         'pkg',        'varchar',   '',   $char_d,
632         'comment',    'varchar',   '',   $char_d,
633         'setup',      @perl_type,
634         'freq',       'int', '', '',  #billing frequency (months)
635         'recur',      @perl_type,
636       ],
637       'primary_key' => 'pkgpart',
638       'unique' => [ [] ],
639       'index' => [ [] ],
640     },
641
642 #    'part_title' => {
643 #      'columns' => [
644 #        'titlenum',   'int',    '',   '',
645 #        'title',      'varchar',   '',   $char_d,
646 #      ],
647 #      'primary_key' => 'titlenum',
648 #      'unique' => [ [] ],
649 #      'index' => [ [] ],
650 #    },
651
652     'pkg_svc' => {
653       'columns' => [
654         'pkgpart',    'int',    '',   '',
655         'svcpart',    'int',    '',   '',
656         'quantity',   'int',    '',   '',
657       ],
658       'primary_key' => '',
659       'unique' => [ ['pkgpart', 'svcpart'] ],
660       'index' => [ ['pkgpart'] ],
661     },
662
663     'part_referral' => {
664       'columns' => [
665         'refnum',   'int',    '',   '',
666         'referral', 'varchar',   '',   $char_d,
667       ],
668       'primary_key' => 'refnum',
669       'unique' => [ [] ],
670       'index' => [ [] ],
671     },
672
673     'part_svc' => {
674       'columns' => [
675         'svcpart',    'int',    '',   '',
676         'svc',        'varchar',   '',   $char_d,
677         'svcdb',      'varchar',   '',   $char_d,
678       ],
679       'primary_key' => 'svcpart',
680       'unique' => [ [] ],
681       'index' => [ [] ],
682     },
683
684     #(this should be renamed to part_pop)
685     'svc_acct_pop' => {
686       'columns' => [
687         'popnum',    'int',    '',   '',
688         'city',      'varchar',   '',   $char_d,
689         'state',     'varchar',   '',   $char_d,
690         'ac',        'char',   '',   3,
691         'exch',      'char',   '',   3,
692         'loc',       'char',   'NULL',   4, #NULL for legacy purposes
693       ],
694       'primary_key' => 'popnum',
695       'unique' => [ [] ],
696       'index' => [ [] ],
697     },
698
699     'svc_acct' => {
700       'columns' => [
701         'svcnum',    'int',    '',   '',
702         'username',  'varchar',   '',   $username_len, #unique (& remove dup code)
703         '_password', 'varchar',   '',   50, #13 for encryped pw's plus ' *SUSPENDED* (mp5 passwords can be 34)
704         'popnum',    'int',    'NULL',   '',
705         'uid',       'int', 'NULL',   '',
706         'gid',       'int', 'NULL',   '',
707         'finger',    'varchar',   'NULL',   $char_d,
708         'dir',       'varchar',   'NULL',   $char_d,
709         'shell',     'varchar',   'NULL',   $char_d,
710         'quota',     'varchar',   'NULL',   $char_d,
711         'slipip',    'varchar',   'NULL',   15, #four TINYINTs, bah.
712         'seconds',   'int', 'NULL',   '', #uhhhh
713         'domsvc',    'int', '',   '',
714       ],
715       'primary_key' => 'svcnum',
716       'unique' => [ [] ],
717       'index' => [ ['username'], ['domsvc'] ],
718     },
719
720     'svc_acct_sm' => {
721       'columns' => [
722         'svcnum',    'int',    '',   '',
723         'domsvc',    'int',    '',   '',
724         'domuid',    'int', '',   '',
725         'domuser',   'varchar',   '',   $char_d,
726       ],
727       'primary_key' => 'svcnum',
728       'unique' => [ [] ],
729       'index' => [ ['domsvc'], ['domuid'] ], 
730     },
731
732     #'svc_charge' => {
733     #  'columns' => [
734     #    'svcnum',    'int',    '',   '',
735     #    'amount',    @money_type,
736     #  ],
737     #  'primary_key' => 'svcnum',
738     #  'unique' => [ [] ],
739     #  'index' => [ [] ],
740     #},
741
742     'svc_domain' => {
743       'columns' => [
744         'svcnum',    'int',    '',   '',
745         'domain',    'varchar',    '',   $char_d,
746         'catchall',  'int',    '',    '',
747       ],
748       'primary_key' => 'svcnum',
749       'unique' => [ ['domain'] ],
750       'index' => [ [] ],
751     },
752
753     'domain_record' => {
754       'columns' => [
755         'recnum',    'int',     '',  '',
756         'svcnum',    'int',     '',  '',
757         'reczone',   'varchar', '',  $char_d,
758         'recaf',     'char',    '',  2,
759         'rectype',   'char',    '',  5,
760         'recdata',   'varchar', '',  $char_d,
761       ],
762       'primary_key' => 'recnum',
763       'unique'      => [ [] ],
764       'index'       => [ ['svcnum'] ],
765     },
766
767     'svc_forward' => {
768       'columns' => [
769         'svcnum',   'int',    '',  '',
770         'srcsvc',   'int',    '',  '',
771         'dstsvc',   'int',    '',  '',
772         'dst',      'varchar',    'NULL',  $char_d,
773       ],
774       'primary_key' => 'svcnum',
775       'unique'      => [ [] ],
776       'index'       => [ ['srcsvc'], ['dstsvc'] ],
777     },
778
779     'svc_www' => {
780       'columns' => [
781         'svcnum',   'int',    '',  '',
782         'recnum',   'int',    '',  '',
783         'usersvc',  'int',    '',  '',
784       ],
785       'primary_key' => 'svcnum',
786       'unique'      => [ [] ],
787       'index'       => [ [] ],
788     },
789
790     #'svc_wo' => {
791     #  'columns' => [
792     #    'svcnum',    'int',    '',   '',
793     #    'svcnum',    'int',    '',   '',
794     #    'svcnum',    'int',    '',   '',
795     #    'worker',    'varchar',   '',   $char_d,
796     #    '_date',     @date_type,
797     #  ],
798     #  'primary_key' => 'svcnum',
799     #  'unique' => [ [] ],
800     #  'index' => [ [] ],
801     #},
802
803     'prepay_credit' => {
804       'columns' => [
805         'prepaynum',   'int',     '',   '',
806         'identifier',  'varchar', '', $char_d,
807         'amount',      @money_type,
808         'seconds',     'int',     'NULL', '',
809       ],
810       'primary_key' => 'prepaynum',
811       'unique'      => [ ['identifier'] ],
812       'index'       => [ [] ],
813     },
814
815     'port' => {
816       'columns' => [
817         'portnum',  'int',     '',   '',
818         'ip',       'varchar', 'NULL', 15,
819         'nasport',  'int',     'NULL', '',
820         'nasnum',   'int',     '',   '',
821       ],
822       'primary_key' => 'portnum',
823       'unique'      => [],
824       'index'       => [],
825     },
826
827     'nas' => {
828       'columns' => [
829         'nasnum',   'int',     '',    '',
830         'nas',      'varchar', '',    $char_d,
831         'nasip',    'varchar', '',    15,
832         'nasfqdn',  'varchar', '',    $char_d,
833         'last',     'int',     '',    '',
834       ],
835       'primary_key' => 'nasnum',
836       'unique'      => [ [ 'nas' ], [ 'nasip' ] ],
837       'index'       => [ [ 'last' ] ],
838     },
839
840     'session' => {
841       'columns' => [
842         'sessionnum', 'int',       '',   '',
843         'portnum',    'int',       '',   '',
844         'svcnum',     'int',       '',   '',
845         'login',      @date_type,
846         'logout',     @date_type,
847       ],
848       'primary_key' => 'sessionnum',
849       'unique'      => [],
850       'index'       => [ [ 'portnum' ] ],
851     },
852
853   );
854
855   %tables;
856
857 }
858