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