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