1 #!/usr/local/bin/perl -Tw
3 # bill: Bill customer(s)
5 # Usage: bill [ -c [ i ] ] [ -d 'date' ] [ -b ]
9 # Adds record to /dbin/cust_bill and /dbin/cust_pay (if payment made -
10 # CARD & COMP), prints invoice / charges card etc.
12 # -c: Turn on collecting (you probably want this).
14 # -i: real-time billing (as opposed to batch billing). only relevant
17 # -d: Pretent it's 'date'. Date is in any format Date::Parse is happy with,
20 # ## n/a ## -b: send batch when done billing
22 # ivan@voicenet.com sep/oct 96
24 # separated billing and collections, cleaned up code.
25 # ivan@voicenet.com 96-nov-11
28 # ivan@voicenet.com 96-nov-13
30 # added -v option and started to implement it, added 'd:' to getopts call
32 # ivan@voicenet.com 97-jan-2
34 # added more debug messages, moved some searches to fssearch.pl library (for
36 # rewrote "all customer" finder to know about bill dates, for speed.
37 # ivan@voicenet.com 97-jan-8
39 # thought about it a while, and removed passing of the -d option to collect...?
40 # ivan@voicenet.com 97-jan-14
42 # make all -v stuff STDERR
43 # ivan@voicenet.com 97-feb-4
45 # added pkgnum as argument to program from /db/part_pkg, with kludge for the
46 # "/bin/echo XX" 's already there.
47 # ivan@voicenet.com 97-feb-23
50 # - customers who are suspended can still be billed for the setup fee
51 # - cust_pkg record is re-read after the package setup fee program is run.
53 # that program can modify the record (for example, to start accounts off
55 # (best to think four or five times before modifying anything else!)
56 # ivan@voicenet.com 97-feb-26
58 # don't bill recurring fee if its not time! (was removed)
59 # ivan@voicenet.com 97-mar-6
61 # added -b option, send batch when done billing.
62 # ivan@voicenet.com 97-apr-4
64 #insecure dependency on line 179ish below needs to be fixed before bill is
66 # ivan@voicenet.com 97-jun-2
68 # removed running of setup program (depriciated)
69 # ivan@voicenet.com 97-jul-21
71 # rewrote for new API, removed option to specify custnums (use FS::Bill
72 # instead), removed -v option (?)
73 # ivan@voicenet.com 97-jul-22 - 23 - 25 -28
74 # (need to add back in email stuff, look in /home/ivan/old/dbin/collect)
76 # s/suidsetup/adminsuidsetup/, s/FS::Search/FS::Record/, added some batch
77 # exporting stuff (which still needs to be generalized) and removed &idiot
78 # ivan@sisd.com 98-may-27
86 use FS::UID qw(adminsuidsetup swapuid);
87 use FS::Record qw(qsearch qsearchs);
90 my($batchfile)="/var/spool/freeside/batch";
91 my($batchlock)="/var/spool/freeside/batch.lock";
95 &untaint_argv; #what it sounds like (eww)
96 use vars qw($opt_b $opt_c $opt_i $opt_d);
97 getopts("bcid:"); #switches
99 #we're at now now (and later).
100 my($time)= $main::opt_d ? str2time($main::opt_d) : $^T;
102 # find packages w/ bill < time && cancel != '', and create corresponding
108 if ( ( $_->getfield('bill') || 0 ) <= $time &&
109 !$saw{ $_->getfield('custnum') }++ ) {
110 qsearchs('cust_main',{'custnum'=> $_->getfield('custnum') } );
114 } qsearch('cust_pkg',{'cancel'=>''})
119 print "Billing customer #" . $cust_main->getfield('custnum') . "\n";
121 bless($cust_main,"FS::Bill");
125 $error=$cust_main->bill('time'=>$time);
126 warn "Error billing, customer #" . $cust_main->getfield('custnum') .
127 ":" . $error if $error;
130 $error=$cust_main->collect('invoice_time'=>$time,
131 'batch_card' => $main::opt_i ? 'no' : 'yes',
133 warn "Error collecting customer #" . $cust_main->getfield('custnum') .
134 ":" . $error if $error;
144 # die "Batch still waiting for reply? ($batchlock exists)\n" if -e $batchlock;
145 # open(BATCHLOCK,"+>>$batchlock") or die "Can't open $batchlock: $!";
146 # select(BATCHLOCK); $|=1; select(STDOUT);
147 # unless ( flock(BATCHLOCK,,LOCK_EX|LOCK_NB) ) {
148 # seek(BATCHLOCK,0,0);
149 # my($pid)=<BATCHLOCK>;
151 # die "Is a batch running? (pid $pid)\n";
153 # seek(BATCHLOCK,0,0);
154 # print BATCHLOCK $$,"\n";
156 # ( open(BATCH,">$batchfile")
157 # and flock(BATCH,LOCK_EX|LOCK_NB)
158 # ) or die "Can't open $batchfile: $!";
160 # my($cust_pay_batch);
161 # foreach $cust_pay_batch (qsearch('cust_pay_batch',{})) {
162 # print BATCH join(':',
163 # $_->getfield('cardnum'),
164 # $_->getfield('exp'),
165 # $_->getfield('amount'),
166 # $_->getfield('payname')
167 # || $_->getfield('first'). ' '. $_->getfield('last'),
169 # $_->getfield('zip'),
173 # flock(BATCH,LOCK_UN);
176 # flock(BATCHLOCK,LOCK_UN);
183 foreach $_ ( $[ .. $#ARGV ) { #untaint @ARGV
184 $ARGV[$_] =~ /^([\w\-\/]*)$/ || die "Illegal arguement \"$ARGV[$_]\"";