doc
[freeside.git] / FS / bin / freeside-setup
1 #!/usr/bin/perl -Tw
2
3 #to delay loading dbdef until we're ready
4 BEGIN { $FS::Record::setup_hack = 1; }
5
6 use strict;
7 use vars qw($opt_s);
8 use Getopt::Std;
9 use DBI;
10 use DBIx::DBSchema 0.20;
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 use FS::raddb;
19 use FS::part_bill_event;
20
21 die "Not running uid freeside!" unless checkeuid();
22
23 my %attrib2db =
24   map { lc($FS::raddb::attrib{$_}) => $_ } keys %FS::raddb::attrib;
25
26 getopts("s");
27 my $user = shift or die &usage;
28 getsecrets($user);
29
30 #needs to match FS::Record
31 my($dbdef_file) = "/usr/local/etc/freeside/dbdef.". datasrc;
32
33 ###
34
35 #print "\nEnter the maximum username length: ";
36 #my($username_len)=&getvalue;
37 my $username_len = 32; #usernamemax config file
38
39 #print "\n\n", <<END, ":";
40 #Freeside tracks the RADIUS User-Name, check attribute Password and
41 #reply attribute Framed-IP-Address for each user.  You can specify additional
42 #check and reply attributes (or you can add them later with the
43 #fs-radius-add-check and fs-radius-add-reply programs).
44 #
45 #First enter any additional RADIUS check attributes you need to track for each 
46 #user, separated by whitespace.
47 #END
48 #my @check_attributes = map { $attrib2db{lc($_)} or die "unknown attribute $_"; }
49 #                         split(" ",&getvalue);
50 #
51 #print "\n\n", <<END, ":";
52 #Now enter any additional reply attributes you need to track for each user,
53 #separated by whitespace.
54 #END
55 #my @attributes = map { $attrib2db{lc($_)} or die "unknown attribute $_"; }
56 #                   split(" ",&getvalue);
57 #
58 #print "\n\n", <<END, ":";
59 #Do you wish to enable the tracking of a second, separate shipping/service
60 #address?
61 #END
62 #my $ship = &_yesno;
63 #
64 #sub getvalue {
65 #  my($x)=scalar(<STDIN>);
66 #  chop $x;
67 #  $x;
68 #}
69 #
70 #sub _yesno {
71 #  print " [y/N]:";
72 #  my $x = scalar(<STDIN>);
73 #  $x =~ /^y/i;
74 #}
75
76 my @check_attributes = (); #add later
77 my @attributes = (); #add later
78 my $ship = $opt_s;
79
80 ###
81
82 my($char_d) = 80; #default maxlength for text fields
83
84 #my(@date_type)  = ( 'timestamp', '', ''     );
85 my(@date_type)  = ( 'int', 'NULL', ''     );
86 my(@perl_type) = ( 'text', 'NULL', ''  ); 
87 my @money_type = ( 'decimal',   '', '10,2' );
88
89 ###
90 # create a dbdef object from the old data structure
91 ###
92
93 my(%tables)=&tables_hash_hack;
94
95 #turn it into objects
96 my($dbdef) = new DBIx::DBSchema ( map {  
97   my(@columns);
98   while (@{$tables{$_}{'columns'}}) {
99     my($name,$type,$null,$length)=splice @{$tables{$_}{'columns'}}, 0, 4;
100     push @columns, new DBIx::DBSchema::Column ( $name,$type,$null,$length );
101   }
102   DBIx::DBSchema::Table->new(
103     $_,
104     $tables{$_}{'primary_key'},
105     DBIx::DBSchema::ColGroup::Unique->new($tables{$_}{'unique'}),
106     DBIx::DBSchema::ColGroup::Index->new($tables{$_}{'index'}),
107     @columns,
108   );
109 } (keys %tables) );
110
111 my $cust_main = $dbdef->table('cust_main');
112 unless ($ship) { #remove ship_ from cust_main
113   $cust_main->delcolumn($_) foreach ( grep /^ship_/, $cust_main->columns );
114 } else { #add indices on ship_last and ship_company
115   push @{$cust_main->index->lol_ref}, ( ['ship_last'], ['ship_company'] ) 
116 }
117
118 #add radius attributes to svc_acct
119
120 my($svc_acct)=$dbdef->table('svc_acct');
121
122 my($attribute);
123 foreach $attribute (@attributes) {
124   $svc_acct->addcolumn ( new DBIx::DBSchema::Column (
125     'radius_'. $attribute,
126     'varchar',
127     'NULL',
128     $char_d,
129   ));
130 }
131
132 foreach $attribute (@check_attributes) {
133   $svc_acct->addcolumn( new DBIx::DBSchema::Column (
134     'rc_'. $attribute,
135     'varchar',
136     'NULL',
137     $char_d,
138   ));
139 }
140
141 ##make part_svc table (but now as object)
142 #
143 #my($part_svc)=$dbdef->table('part_svc');
144 #
145 ##because of svc_acct_pop
146 ##foreach (grep /^svc_/, $dbdef->tables) { 
147 ##foreach (qw(svc_acct svc_acct_sm svc_charge svc_domain svc_wo)) {
148 #foreach (qw(svc_acct svc_domain svc_forward svc_www)) {
149 #  my($table)=$dbdef->table($_);
150 #  my($col);
151 #  foreach $col ( $table->columns ) {
152 #    next if $col =~ /^svcnum$/;
153 #    $part_svc->addcolumn( new DBIx::DBSchema::Column (
154 #      $table->name. '__' . $table->column($col)->name,
155 #      'varchar', #$table->column($col)->type, 
156 #      'NULL',
157 #      $char_d, #$table->column($col)->length,
158 #    ));
159 #    $part_svc->addcolumn ( new DBIx::DBSchema::Column (
160 #      $table->name. '__'. $table->column($col)->name . "_flag",
161 #      'char',
162 #      'NULL',
163 #      1,
164 #    ));
165 #  }
166 #}
167
168 #create history tables (false laziness w/create-history-tables)
169 foreach my $table ( grep { ! /^h_/ } $dbdef->tables ) {
170   my $tableobj = $dbdef->table($table)
171     or die "unknown table $table";
172
173   die "unique->lol_ref undefined for $table"
174     unless defined $tableobj->unique->lol_ref;
175   die "index->lol_ref undefined for $table"
176     unless defined $tableobj->index->lol_ref;
177
178   my $h_tableobj = DBIx::DBSchema::Table->new( {
179     name        => "h_$table",
180     primary_key => 'historynum',
181     unique      => DBIx::DBSchema::ColGroup::Unique->new( [] ),
182     'index'     => DBIx::DBSchema::ColGroup::Index->new( [
183                      @{$tableobj->unique->lol_ref},
184                      @{$tableobj->index->lol_ref}
185                    ] ),
186     columns     => [
187                      DBIx::DBSchema::Column->new( {
188                        'name'    => 'historynum',
189                        'type'    => 'serial',
190                        'null'    => 'NOT NULL',
191                        'length'  => '',
192                        'default' => '',
193                        'local'   => '',
194                      } ),
195                      DBIx::DBSchema::Column->new( {
196                        'name'    => 'history_date',
197                        'type'    => 'int',
198                        'null'    => 'NULL',
199                        'length'  => '',
200                        'default' => '',
201                        'local'   => '',
202                      } ),
203                      DBIx::DBSchema::Column->new( {
204                        'name'    => 'history_user',
205                        'type'    => 'varchar',
206                        'null'    => 'NOT NULL',
207                        'length'  => '80',
208                        'default' => '',
209                        'local'   => '',
210                      } ),
211                      DBIx::DBSchema::Column->new( {
212                        'name'    => 'history_action',
213                        'type'    => 'varchar',
214                        'null'    => 'NOT NULL',
215                        'length'  => '80',
216                        'default' => '',
217                        'local'   => '',
218                      } ),
219                      map { $tableobj->column($_) } $tableobj->columns
220                    ],
221   } );
222   $dbdef->addtable($h_tableobj);
223 }
224
225 #important
226 $dbdef->save($dbdef_file);
227 &FS::Record::reload_dbdef($dbdef_file);
228
229 ###
230 # create 'em
231 ###
232
233 my($dbh)=adminsuidsetup $user;
234
235 #create tables
236 $|=1;
237
238 foreach my $statement ( $dbdef->sql($dbh) ) {
239   $dbh->do( $statement )
240     or die "CREATE error: ". $dbh->errstr. "\ndoing statement: $statement";
241 }
242
243 #not really sample data (and shouldn't default to US)
244
245 #cust_main_county
246
247 #USPS state codes
248 foreach ( qw(
249 AL AK AS AZ AR CA CO CT DC DE FM FL GA GU HI ID IL IN IA KS KY LA
250 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 
251 SC SD TN TX UT VT VI VA WA WV WI WY AE AA AP
252 ) ) {
253   my($cust_main_county)=new FS::cust_main_county({
254     'state' => $_,
255     'tax'   => 0,
256     'country' => 'US',
257   });  
258   my($error);
259   $error=$cust_main_county->insert;
260   die $error if $error;
261 }
262
263 #AU "offical" state codes ala mark.williamson@ebbs.com.au (Mark Williamson)
264 foreach ( qw(
265 VIC NSW NT QLD TAS ACT WA SA
266 ) ) {
267   my($cust_main_county)=new FS::cust_main_county({
268     'state' => $_,
269     'tax'   => 0,
270     'country' => 'AU',
271   });  
272   my($error);
273   $error=$cust_main_county->insert;
274   die $error if $error;
275 }
276
277 #ISO 2-letter country codes (same as country TLDs) except US and AU
278 foreach ( qw(
279 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
280 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
281 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
282 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
283 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
284 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
285 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
286 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
287 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
288 YE YU ZR ZM ZW
289 ) ) {
290   my($cust_main_county)=new FS::cust_main_county({
291     'tax'   => 0,
292     'country' => $_,
293   });  
294   my($error);
295   $error=$cust_main_county->insert;
296   die $error if $error;
297 }
298
299 #billing events
300 foreach my $aref ( 
301   [ 'COMP', 'Comp invoice', '$cust_bill->comp();', 30, 'comp' ],
302   [ 'CARD', 'Batch card', '$cust_bill->batch_card();', 40, 'batch-card' ],
303   [ 'BILL', 'Send invoice', '$cust_bill->send();', 50, 'send' ],
304 ) {
305
306   my $part_bill_event = new FS::part_bill_event({
307     'payby' => $aref->[0],
308     'event' => $aref->[1],
309     'eventcode' => $aref->[2],
310     'seconds' => 0,
311     'weight' => $aref->[3],
312     'plan' => $aref->[4],
313   });
314   my($error);
315   $error=$part_bill_event->insert;
316   die $error if $error;
317
318 }
319
320 $dbh->commit or die $dbh->errstr;
321 $dbh->disconnect or die $dbh->errstr;
322
323 #print "Freeside database initialized sucessfully\n";
324
325 sub usage {
326   die "Usage:\n  freeside-setup [ -s ] user\n"; 
327 }
328
329 ###
330 # Now it becomes an object.  much better.
331 ###
332 sub tables_hash_hack {
333
334   #note that s/(date|change)/_$1/; to avoid keyword conflict.
335   #put a kludge in FS::Record to catch this or? (pry need some date-handling
336   #stuff anyway also)
337
338   my(%tables)=( #yech.}
339
340     'agent' => {
341       'columns' => [
342         'agentnum', 'int',            '',     '',
343         'agent',    'varchar',           '',     $char_d,
344         'typenum',  'int',            '',     '',
345         'freq',     'int',       'NULL', '',
346         'prog',     @perl_type,
347       ],
348       'primary_key' => 'agentnum',
349       'unique' => [],
350       'index' => [ ['typenum'] ],
351     },
352
353     'agent_type' => {
354       'columns' => [
355         'typenum',   'int',  '', '',
356         'atype',     'varchar', '', $char_d,
357       ],
358       'primary_key' => 'typenum',
359       'unique' => [],
360       'index' => [],
361     },
362
363     'type_pkgs' => {
364       'columns' => [
365         'typenum',   'int',  '', '',
366         'pkgpart',   'int',  '', '',
367       ],
368       'primary_key' => '',
369       'unique' => [ ['typenum', 'pkgpart'] ],
370       'index' => [ ['typenum'] ],
371     },
372
373     'cust_bill' => {
374       'columns' => [
375         'invnum',    'int',  '', '',
376         'custnum',   'int',  '', '',
377         '_date',     @date_type,
378         'charged',   @money_type,
379         'printed',   'int',  '', '',
380         'closed',    'char', 'NULL', 1,
381       ],
382       'primary_key' => 'invnum',
383       'unique' => [],
384       'index' => [ ['custnum'] ],
385     },
386
387     'cust_bill_event' => {
388       'columns' => [
389         'eventnum',    'int',  '', '',
390         'invnum',   'int',  '', '',
391         'eventpart',   'int',  '', '',
392         '_date',     @date_type,
393         'status', 'varchar', '', $char_d,
394         'statustext', 'text', 'NULL', '',
395       ],
396       'primary_key' => 'eventnum',
397       #no... there are retries now #'unique' => [ [ 'eventpart', 'invnum' ] ],
398       'unique' => [],
399       'index' => [ ['invnum'], ['status'] ],
400     },
401
402     'part_bill_event' => {
403       'columns' => [
404         'eventpart',    'int',  '', '',
405         'payby',       'char',  '', 4,
406         'event',       'varchar',           '',     $char_d,
407         'eventcode',    @perl_type,
408         'seconds',     'int', 'NULL', '',
409         'weight',      'int', '', '',
410         'plan',       'varchar', 'NULL', $char_d,
411         'plandata',   'text', 'NULL', '',
412         'disabled',     'char', 'NULL', 1,
413       ],
414       'primary_key' => 'eventpart',
415       'unique' => [],
416       'index' => [ ['payby'] ],
417     },
418
419     'cust_bill_pkg' => {
420       'columns' => [
421         'pkgnum',  'int', '', '',
422         'invnum',  'int', '', '',
423         'setup',   @money_type,
424         'recur',   @money_type,
425         'sdate',   @date_type,
426         'edate',   @date_type,
427       ],
428       'primary_key' => '',
429       'unique' => [ ['pkgnum', 'invnum'] ],
430       'index' => [ ['invnum'] ],
431     },
432
433     'cust_credit' => {
434       'columns' => [
435         'crednum',  'int', '', '',
436         'custnum',  'int', '', '',
437         '_date',    @date_type,
438         'amount',   @money_type,
439         'otaker',   'varchar', '', 8,
440         'reason',   'text', 'NULL', '',
441         'closed',    'char', 'NULL', 1,
442       ],
443       'primary_key' => 'crednum',
444       'unique' => [],
445       'index' => [ ['custnum'] ],
446     },
447
448     'cust_credit_bill' => {
449       'columns' => [
450         'creditbillnum', 'int', '', '',
451         'crednum',  'int', '', '',
452         'invnum',  'int', '', '',
453         '_date',    @date_type,
454         'amount',   @money_type,
455       ],
456       'primary_key' => 'creditbillnum',
457       'unique' => [],
458       'index' => [ ['crednum'], ['invnum'] ],
459     },
460
461     'cust_main' => {
462       'columns' => [
463         'custnum',  'int',  '',     '',
464         'agentnum', 'int',  '',     '',
465 #        'titlenum', 'int',  'NULL',   '',
466         'last',     'varchar', '',     $char_d,
467 #        'middle',   'varchar', 'NULL', $char_d,
468         'first',    'varchar', '',     $char_d,
469         'ss',       'char', 'NULL', 11,
470         'company',  'varchar', 'NULL', $char_d,
471         'address1', 'varchar', '',     $char_d,
472         'address2', 'varchar', 'NULL', $char_d,
473         'city',     'varchar', '',     $char_d,
474         'county',   'varchar', 'NULL', $char_d,
475         'state',    'varchar', 'NULL', $char_d,
476         'zip',      'varchar', '',     10,
477         'country',  'char', '',     2,
478         'daytime',  'varchar', 'NULL', 20,
479         'night',    'varchar', 'NULL', 20,
480         'fax',      'varchar', 'NULL', 12,
481         'ship_last',     'varchar', 'NULL', $char_d,
482 #        'ship_middle',   'varchar', 'NULL', $char_d,
483         'ship_first',    'varchar', 'NULL', $char_d,
484         'ship_company',  'varchar', 'NULL', $char_d,
485         'ship_address1', 'varchar', 'NULL', $char_d,
486         'ship_address2', 'varchar', 'NULL', $char_d,
487         'ship_city',     'varchar', 'NULL', $char_d,
488         'ship_county',   'varchar', 'NULL', $char_d,
489         'ship_state',    'varchar', 'NULL', $char_d,
490         'ship_zip',      'varchar', 'NULL', 10,
491         'ship_country',  'char', 'NULL', 2,
492         'ship_daytime',  'varchar', 'NULL', 20,
493         'ship_night',    'varchar', 'NULL', 20,
494         'ship_fax',      'varchar', 'NULL', 12,
495         'payby',    'char', '',     4,
496         'payinfo',  'varchar', 'NULL', $char_d,
497         #'paydate',  @date_type,
498         'paydate',  'varchar', 'NULL', 10,
499         'payname',  'varchar', 'NULL', $char_d,
500         'tax',      'char', 'NULL', 1,
501         'otaker',   'varchar', '',     8,
502         'refnum',   'int',  '',     '',
503         'referral_custnum', 'int',  'NULL', '',
504         'comments', 'text', 'NULL', '',
505       ],
506       'primary_key' => 'custnum',
507       'unique' => [],
508       #'index' => [ ['last'], ['company'] ],
509       'index' => [ ['last'], [ 'company' ], [ 'referral_custnum' ] ],
510     },
511
512     'cust_main_invoice' => {
513       'columns' => [
514         'destnum',  'int',  '',     '',
515         'custnum',  'int',  '',     '',
516         'dest',     'varchar', '',  $char_d,
517       ],
518       'primary_key' => 'destnum',
519       'unique' => [],
520       'index' => [ ['custnum'], ],
521     },
522
523     'cust_main_county' => { #county+state+country are checked off the
524                             #cust_main_county for validation and to provide
525                             # a tax rate.
526       'columns' => [
527         'taxnum',   'int',   '',    '',
528         'state',    'varchar',  'NULL',    $char_d,
529         'county',   'varchar',  'NULL',    $char_d,
530         'country',  'char',  '', 2, 
531         'taxclass',   'varchar', 'NULL', $char_d,
532         'exempt_amount', @money_type,
533         'tax',      'real',  '',    '', #tax %
534       ],
535       'primary_key' => 'taxnum',
536       'unique' => [],
537   #    'unique' => [ ['taxnum'], ['state', 'county'] ],
538       'index' => [],
539     },
540
541     'cust_pay' => {
542       'columns' => [
543         'paynum',   'int',    '',   '',
544         #now cust_bill_pay #'invnum',   'int',    '',   '',
545         'custnum',  'int',    '',   '',
546         'paid',     @money_type,
547         '_date',    @date_type,
548         'payby',    'char',   '',     4, # CARD/BILL/COMP, should be index into
549                                          # payment type table.
550         'payinfo',  'varchar',   'NULL', 16,  #see cust_main above
551         'paybatch', 'varchar',   'NULL', $char_d, #for auditing purposes.
552         'closed',    'char', 'NULL', 1,
553       ],
554       'primary_key' => 'paynum',
555       'unique' => [],
556       'index' => [ [ 'custnum' ], [ 'paybatch' ] ],
557     },
558
559     'cust_bill_pay' => {
560       'columns' => [
561         'billpaynum', 'int',     '',   '',
562         'invnum',  'int',     '',   '',
563         'paynum',  'int',     '',   '',
564         'amount',  @money_type,
565         '_date',   @date_type
566       ],
567       'primary_key' => 'billpaynum',
568       'unique' => [],
569       'index' => [ [ 'paynum' ], [ 'invnum' ] ],
570     },
571
572     'cust_pay_batch' => { #what's this used for again?  list of customers
573                           #in current CARD batch? (necessarily CARD?)
574       'columns' => [
575         'paybatchnum',   'int',    '',   '',
576         'invnum',   'int',    '',   '',
577         'custnum',   'int',    '',   '',
578         'last',     'varchar', '',     $char_d,
579         'first',    'varchar', '',     $char_d,
580         'address1', 'varchar', '',     $char_d,
581         'address2', 'varchar', 'NULL', $char_d,
582         'city',     'varchar', '',     $char_d,
583         'state',    'varchar', 'NULL', $char_d,
584         'zip',      'varchar', '',     10,
585         'country',  'char', '',     2,
586 #        'trancode', 'int', '', '',
587         'cardnum',  'varchar', '',     16,
588         #'exp',      @date_type,
589         'exp',      'varchar', '',     11,
590         'payname',  'varchar', 'NULL', $char_d,
591         'amount',   @money_type,
592       ],
593       'primary_key' => 'paybatchnum',
594       'unique' => [],
595       'index' => [ ['invnum'], ['custnum'] ],
596     },
597
598     'cust_pkg' => {
599       'columns' => [
600         'pkgnum',    'int',    '',   '',
601         'custnum',   'int',    '',   '',
602         'pkgpart',   'int',    '',   '',
603         'otaker',    'varchar', '', 8,
604         'setup',     @date_type,
605         'bill',      @date_type,
606         'susp',      @date_type,
607         'cancel',    @date_type,
608         'expire',    @date_type,
609         'manual_flag', 'char', 'NULL', 1,
610       ],
611       'primary_key' => 'pkgnum',
612       'unique' => [],
613       'index' => [ ['custnum'] ],
614     },
615
616     'cust_refund' => {
617       'columns' => [
618         'refundnum',    'int',    '',   '',
619         #now cust_credit_refund #'crednum',      'int',    '',   '',
620         'custnum',  'int',    '',   '',
621         '_date',        @date_type,
622         'refund',       @money_type,
623         'otaker',       'varchar',   '',   8,
624         'reason',       'varchar',   '',   $char_d,
625         'payby',        'char',   '',     4, # CARD/BILL/COMP, should be index
626                                              # into payment type table.
627         'payinfo',      'varchar',   'NULL', 16,  #see cust_main above
628         'paybatch',     'varchar',   'NULL', $char_d,
629         'closed',    'char', 'NULL', 1,
630       ],
631       'primary_key' => 'refundnum',
632       'unique' => [],
633       'index' => [],
634     },
635
636     'cust_credit_refund' => {
637       'columns' => [
638         'creditrefundnum', 'int',     '',   '',
639         'crednum',  'int',     '',   '',
640         'refundnum',  'int',     '',   '',
641         'amount',  @money_type,
642         '_date',   @date_type
643       ],
644       'primary_key' => 'creditrefundnum',
645       'unique' => [],
646       'index' => [ [ 'crednum', 'refundnum' ] ],
647     },
648
649
650     'cust_svc' => {
651       'columns' => [
652         'svcnum',    'int',    '',   '',
653         'pkgnum',    'int',    'NULL',   '',
654         'svcpart',   'int',    '',   '',
655       ],
656       'primary_key' => 'svcnum',
657       'unique' => [],
658       'index' => [ ['svcnum'], ['pkgnum'], ['svcpart'] ],
659     },
660
661     'part_pkg' => {
662       'columns' => [
663         'pkgpart',    'int',    '',   '',
664         'pkg',        'varchar',   '',   $char_d,
665         'comment',    'varchar',   '',   $char_d,
666         'setup',      @perl_type,
667         'freq',       'int', '', '',  #billing frequency (months)
668         'recur',      @perl_type,
669         'setuptax',  'char', 'NULL', 1,
670         'recurtax',  'char', 'NULL', 1,
671         'plan',       'varchar', 'NULL', $char_d,
672         'plandata',   'text', 'NULL', '',
673         'disabled',   'char', 'NULL', 1,
674         'taxclass',   'varchar', 'NULL', $char_d,
675       ],
676       'primary_key' => 'pkgpart',
677       'unique' => [],
678       'index' => [],
679     },
680
681 #    'part_title' => {
682 #      'columns' => [
683 #        'titlenum',   'int',    '',   '',
684 #        'title',      'varchar',   '',   $char_d,
685 #      ],
686 #      'primary_key' => 'titlenum',
687 #      'unique' => [ [] ],
688 #      'index' => [ [] ],
689 #    },
690
691     'pkg_svc' => {
692       'columns' => [
693         'pkgpart',    'int',    '',   '',
694         'svcpart',    'int',    '',   '',
695         'quantity',   'int',    '',   '',
696       ],
697       'primary_key' => '',
698       'unique' => [ ['pkgpart', 'svcpart'] ],
699       'index' => [ ['pkgpart'] ],
700     },
701
702     'part_referral' => {
703       'columns' => [
704         'refnum',   'int',    '',   '',
705         'referral', 'varchar',   '',   $char_d,
706       ],
707       'primary_key' => 'refnum',
708       'unique' => [],
709       'index' => [],
710     },
711
712     'part_svc' => {
713       'columns' => [
714         'svcpart',    'int',    '',   '',
715         'svc',        'varchar',   '',   $char_d,
716         'svcdb',      'varchar',   '',   $char_d,
717         'disabled',   'char',  'NULL',   1,
718       ],
719       'primary_key' => 'svcpart',
720       'unique' => [],
721       'index' => [],
722     },
723
724     'part_svc_column' => {
725       'columns' => [
726         'columnnum',   'int',         '', '',
727         'svcpart',     'int',         '', '',
728         'columnname',  'varchar',     '', 64,
729         'columnvalue', 'varchar', 'NULL', $char_d,
730         'columnflag',  'char',    'NULL', 1, 
731       ],
732       'primary_key' => 'columnnum',
733       'unique' => [ [ 'svcpart', 'columnname' ] ],
734       'index' => [ [ 'svcpart' ] ],
735     },
736
737     #(this should be renamed to part_pop)
738     'svc_acct_pop' => {
739       'columns' => [
740         'popnum',    'int',    '',   '',
741         'city',      'varchar',   '',   $char_d,
742         'state',     'varchar',   '',   $char_d,
743         'ac',        'char',   '',   3,
744         'exch',      'char',   '',   3,
745         'loc',       'char',   'NULL',   4, #NULL for legacy purposes
746       ],
747       'primary_key' => 'popnum',
748       'unique' => [],
749       'index' => [ [ 'state' ] ],
750     },
751
752     'part_pop_local' => {
753       'columns' => [
754         'localnum',  'int',     '',     '',
755         'popnum',    'int',     '',     '',
756         'city',      'varchar', 'NULL', $char_d,
757         'state',     'char',    'NULL', 2,
758         'npa',       'char',    '',     3,
759         'nxx',       'char',    '',     3,
760       ],
761       'primary_key' => 'localnum',
762       'unique' => [],
763       'index' => [ [ 'npa', 'nxx' ], [ 'popnum' ] ],
764     },
765
766     'svc_acct' => {
767       'columns' => [
768         'svcnum',    'int',    '',   '',
769         'username',  'varchar',   '',   $username_len, #unique (& remove dup code)
770         '_password', 'varchar',   '',   50, #13 for encryped pw's plus ' *SUSPENDED* (mp5 passwords can be 34)
771         'sec_phrase', 'varchar',  'NULL',   $char_d,
772         'popnum',    'int',    'NULL',   '',
773         'uid',       'int', 'NULL',   '',
774         'gid',       'int', 'NULL',   '',
775         'finger',    'varchar',   'NULL',   $char_d,
776         'dir',       'varchar',   'NULL',   $char_d,
777         'shell',     'varchar',   'NULL',   $char_d,
778         'quota',     'varchar',   'NULL',   $char_d,
779         'slipip',    'varchar',   'NULL',   15, #four TINYINTs, bah.
780         'seconds',   'int', 'NULL',   '', #uhhhh
781         'domsvc',    'int', '',   '',
782       ],
783       'primary_key' => 'svcnum',
784       #'unique' => [ [ 'username', 'domsvc' ] ],
785       'unique' => [],
786       'index' => [ ['username'], ['domsvc'] ],
787     },
788
789 #    'svc_acct_sm' => {
790 #      'columns' => [
791 #        'svcnum',    'int',    '',   '',
792 #        'domsvc',    'int',    '',   '',
793 #        'domuid',    'int', '',   '',
794 #        'domuser',   'varchar',   '',   $char_d,
795 #      ],
796 #      'primary_key' => 'svcnum',
797 #      'unique' => [ [] ],
798 #      'index' => [ ['domsvc'], ['domuid'] ], 
799 #    },
800
801     #'svc_charge' => {
802     #  'columns' => [
803     #    'svcnum',    'int',    '',   '',
804     #    'amount',    @money_type,
805     #  ],
806     #  'primary_key' => 'svcnum',
807     #  'unique' => [ [] ],
808     #  'index' => [ [] ],
809     #},
810
811     'svc_domain' => {
812       'columns' => [
813         'svcnum',    'int',    '',   '',
814         'domain',    'varchar',    '',   $char_d,
815         'catchall',  'int', 'NULL',    '',
816       ],
817       'primary_key' => 'svcnum',
818       'unique' => [ ['domain'] ],
819       'index' => [],
820     },
821
822     'domain_record' => {
823       'columns' => [
824         'recnum',    'int',     '',  '',
825         'svcnum',    'int',     '',  '',
826         'reczone',   'varchar', '',  $char_d,
827         'recaf',     'char',    '',  2,
828         'rectype',   'char',    '',  5,
829         'recdata',   'varchar', '',  $char_d,
830       ],
831       'primary_key' => 'recnum',
832       'unique'      => [],
833       'index'       => [ ['svcnum'] ],
834     },
835
836     'svc_forward' => {
837       'columns' => [
838         'svcnum',   'int',    '',  '',
839         'srcsvc',   'int',    '',  '',
840         'dstsvc',   'int',    '',  '',
841         'dst',      'varchar',    'NULL',  $char_d,
842       ],
843       'primary_key' => 'svcnum',
844       'unique'      => [],
845       'index'       => [ ['srcsvc'], ['dstsvc'] ],
846     },
847
848     'svc_www' => {
849       'columns' => [
850         'svcnum',   'int',    '',  '',
851         'recnum',   'int',    '',  '',
852         'usersvc',  'int',    '',  '',
853       ],
854       'primary_key' => 'svcnum',
855       'unique'      => [],
856       'index'       => [],
857     },
858
859     #'svc_wo' => {
860     #  'columns' => [
861     #    'svcnum',    'int',    '',   '',
862     #    'svcnum',    'int',    '',   '',
863     #    'svcnum',    'int',    '',   '',
864     #    'worker',    'varchar',   '',   $char_d,
865     #    '_date',     @date_type,
866     #  ],
867     #  'primary_key' => 'svcnum',
868     #  'unique' => [ [] ],
869     #  'index' => [ [] ],
870     #},
871
872     'prepay_credit' => {
873       'columns' => [
874         'prepaynum',   'int',     '',   '',
875         'identifier',  'varchar', '', $char_d,
876         'amount',      @money_type,
877         'seconds',     'int',     'NULL', '',
878       ],
879       'primary_key' => 'prepaynum',
880       'unique'      => [ ['identifier'] ],
881       'index'       => [],
882     },
883
884     'port' => {
885       'columns' => [
886         'portnum',  'int',     '',   '',
887         'ip',       'varchar', 'NULL', 15,
888         'nasport',  'int',     'NULL', '',
889         'nasnum',   'int',     '',   '',
890       ],
891       'primary_key' => 'portnum',
892       'unique'      => [],
893       'index'       => [],
894     },
895
896     'nas' => {
897       'columns' => [
898         'nasnum',   'int',     '',    '',
899         'nas',      'varchar', '',    $char_d,
900         'nasip',    'varchar', '',    15,
901         'nasfqdn',  'varchar', '',    $char_d,
902         'last',     'int',     '',    '',
903       ],
904       'primary_key' => 'nasnum',
905       'unique'      => [ [ 'nas' ], [ 'nasip' ] ],
906       'index'       => [ [ 'last' ] ],
907     },
908
909     'session' => {
910       'columns' => [
911         'sessionnum', 'int',       '',   '',
912         'portnum',    'int',       '',   '',
913         'svcnum',     'int',       '',   '',
914         'login',      @date_type,
915         'logout',     @date_type,
916       ],
917       'primary_key' => 'sessionnum',
918       'unique'      => [],
919       'index'       => [ [ 'portnum' ] ],
920     },
921
922     'queue' => {
923       'columns' => [
924         'jobnum', 'int', '', '',
925         'job', 'text', '', '',
926         '_date', 'int', '', '',
927         'status', 'varchar', '', $char_d,
928         'statustext', 'text', 'NULL', '',
929         'svcnum', 'int', 'NULL', '',
930       ],
931       'primary_key' => 'jobnum',
932       'unique'      => [],
933       'index'       => [ [ 'svcnum' ], [ 'status' ] ],
934     },
935
936     'queue_arg' => {
937       'columns' => [
938         'argnum', 'int', '', '',
939         'jobnum', 'int', '', '',
940         'arg', 'text', 'NULL', '',
941       ],
942       'primary_key' => 'argnum',
943       'unique'      => [],
944       'index'       => [ [ 'jobnum' ] ],
945     },
946
947     'queue_depend' => {
948       'columns' => [
949         'dependnum', 'int', '', '',
950         'jobnum', 'int', '', '',
951         'depend_jobnum', 'int', '', '',
952       ],
953       'primary_key' => 'dependnum',
954       'unique'      => [],
955       'index'       => [ [ 'jobnum' ], [ 'depend_jobnum' ] ],
956     },
957
958     'export_svc' => {
959       'columns' => [
960         'exportsvcnum' => 'int', '', '',
961         'exportnum'    => 'int', '', '',
962         'svcpart'      => 'int', '', '',
963       ],
964       'primary_key' => 'exportsvcnum',
965       'unique'      => [ [ 'exportnum', 'svcpart' ] ],
966       'index'       => [ [ 'exportnum' ], [ 'svcpart' ] ],
967     },
968
969     'part_export' => {
970       'columns' => [
971         'exportnum', 'int', '', '',
972         #'svcpart',   'int', '', '',
973         'machine', 'varchar', '', $char_d,
974         'exporttype', 'varchar', '', $char_d,
975         'nodomain',     'char', 'NULL', 1,
976       ],
977       'primary_key' => 'exportnum',
978       'unique'      => [],
979       'index'       => [ [ 'machine' ], [ 'exporttype' ] ],
980     },
981
982     'part_export_option' => {
983       'columns' => [
984         'optionnum', 'int', '', '',
985         'exportnum', 'int', '', '',
986         'optionname', 'varchar', '', $char_d,
987         'optionvalue', 'text', 'NULL', '',
988       ],
989       'primary_key' => 'optionnum',
990       'unique'      => [],
991       'index'       => [ [ 'exportnum' ], [ 'optionname' ] ],
992     },
993
994     'radius_usergroup' => {
995       'columns' => [
996         'usergroupnum', 'int', '', '',
997         'svcnum',       'int', '', '',
998         'groupname',    'varchar', '', $char_d,
999       ],
1000       'primary_key' => 'usergroupnum',
1001       'unique'      => [],
1002       'index'       => [ [ 'svcnum' ], [ 'groupname' ] ],
1003     },
1004
1005     'msgcat' => {
1006       'columns' => [
1007         'msgnum', 'int', '', '',
1008         'msgcode', 'varchar', '', $char_d,
1009         'locale', 'varchar', '', 16,
1010         'msg', 'text', '', '',
1011       ],
1012       'primary_key' => 'msgnum',
1013       'unique'      => [ [ 'msgcode', 'locale' ] ],
1014       'index'       => [],
1015     },
1016
1017     'cust_tax_exempt' => {
1018       'columns' => [
1019         'exemptnum', 'int', '', '',
1020         'custnum',   'int', '', '',
1021         'taxnum',    'int', '', '',
1022         'year',      'int', '', '',
1023         'month',     'int', '', '',
1024         'amount',   @money_type,
1025       ],
1026       'primary_key' => 'exemptnum',
1027       'unique'      => [ [ 'custnum', 'taxnum', 'year', 'month' ] ],
1028       'index'       => [],
1029     },
1030
1031
1032
1033   );
1034
1035   %tables;
1036
1037 }
1038