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