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