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