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