From: ivan Date: Mon, 24 Aug 1998 02:01:19 +0000 (+0000) Subject: Initial revision X-Git-Tag: freeside_1_2_0~270 X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=cc60ec75f2f7ddbe0dca9292126adfc53e7b4e37 Initial revision --- diff --git a/bin/bill b/bin/bill new file mode 100755 index 000000000..5c5be703d --- /dev/null +++ b/bin/bill @@ -0,0 +1,188 @@ +#!/usr/local/bin/perl -Tw +# +# bill: Bill customer(s) +# +# Usage: bill [ -c [ i ] ] [ -d 'date' ] [ -b ] +# +# Bills all customers. +# +# Adds record to /dbin/cust_bill and /dbin/cust_pay (if payment made - +# CARD & COMP), prints invoice / charges card etc. +# +# -c: Turn on collecting (you probably want this). +# +# -i: real-time billing (as opposed to batch billing). only relevant +# for credit cards. +# +# -d: Pretent it's 'date'. Date is in any format Date::Parse is happy with, +# but be careful. +# +# ## n/a ## -b: send batch when done billing +# +# ivan@voicenet.com sep/oct 96 +# +# separated billing and collections, cleaned up code. +# ivan@voicenet.com 96-nov-11 +# +# added -d option +# ivan@voicenet.com 96-nov-13 +# +# added -v option and started to implement it, added 'd:' to getopts call +# (oops!) +# ivan@voicenet.com 97-jan-2 +# +# added more debug messages, moved some searches to fssearch.pl library (for +# speed) +# rewrote "all customer" finder to know about bill dates, for speed. +# ivan@voicenet.com 97-jan-8 +# +# thought about it a while, and removed passing of the -d option to collect...? +# ivan@voicenet.com 97-jan-14 +# +# make all -v stuff STDERR +# ivan@voicenet.com 97-feb-4 +# +# added pkgnum as argument to program from /db/part_pkg, with kludge for the +# "/bin/echo XX" 's already there. +# ivan@voicenet.com 97-feb-23 +# +# - general cleanup +# - customers who are suspended can still be billed for the setup fee +# - cust_pkg record is re-read after the package setup fee program is run. +# this way, +# that program can modify the record (for example, to start accounts off +# suspended) +# (best to think four or five times before modifying anything else!) +# ivan@voicenet.com 97-feb-26 +# +# don't bill recurring fee if its not time! (was removed) +# ivan@voicenet.com 97-mar-6 +# +# added -b option, send batch when done billing. +# ivan@voicenet.com 97-apr-4 +# +#insecure dependency on line 179ish below needs to be fixed before bill is +#used setuid +# ivan@voicenet.com 97-jun-2 +# +# removed running of setup program (depriciated) +# ivan@voicenet.com 97-jul-21 +# +# rewrote for new API, removed option to specify custnums (use FS::Bill +# instead), removed -v option (?) +# ivan@voicenet.com 97-jul-22 - 23 - 25 -28 +# (need to add back in email stuff, look in /home/ivan/old/dbin/collect) +# +# s/suidsetup/adminsuidsetup/, s/FS::Search/FS::Record/, added some batch +# exporting stuff (which still needs to be generalized) and removed &idiot +# ivan@sisd.com 98-may-27 + +# setup + +use strict; +use Fcntl qw(:flock); +use Date::Parse; +use Getopt::Std; +use FS::UID qw(adminsuidsetup swapuid); +use FS::Record qw(qsearch qsearchs); +use FS::Bill; + +my($batchfile)="/var/spool/freeside/batch"; +my($batchlock)="/var/spool/freeside/batch.lock"; + +adminsuidsetup; + +&untaint_argv; #what it sounds like (eww) +use vars qw($opt_b $opt_c $opt_i $opt_d); +getopts("bcid:"); #switches + +#we're at now now (and later). +my($time)= $main::opt_d ? str2time($main::opt_d) : $^T; + +# find packages w/ bill < time && cancel != '', and create corresponding +# customer objects + +my($cust_main,%saw); +foreach $cust_main ( + map { + if ( ( $_->getfield('bill') || 0 ) <= $time && + !$saw{ $_->getfield('custnum') }++ ) { + qsearchs('cust_main',{'custnum'=> $_->getfield('custnum') } ); + } else { + (); + } + } qsearch('cust_pkg',{'cancel'=>''}) +) { + + # and bill them + + print "Billing customer #" . $cust_main->getfield('custnum') . "\n"; + + bless($cust_main,"FS::Bill"); + + my($error); + + $error=$cust_main->bill('time'=>$time); + warn "Error billing, customer #" . $cust_main->getfield('custnum') . + ":" . $error if $error; + + if ($main::opt_c) { + $error=$cust_main->collect('invoice_time'=>$time, + 'batch_card' => $main::opt_i ? 'no' : 'yes', + ); + warn "Error collecting customer #" . $cust_main->getfield('custnum') . + ":" . $error if $error; + + #sleep 1; + + } + +} + +#if ($main::opt_b) { +# +# die "Batch still waiting for reply? ($batchlock exists)\n" if -e $batchlock; +# open(BATCHLOCK,"+>>$batchlock") or die "Can't open $batchlock: $!"; +# select(BATCHLOCK); $|=1; select(STDOUT); +# unless ( flock(BATCHLOCK,,LOCK_EX|LOCK_NB) ) { +# seek(BATCHLOCK,0,0); +# my($pid)=; +# chop($pid); +# die "Is a batch running? (pid $pid)\n"; +# } +# seek(BATCHLOCK,0,0); +# print BATCHLOCK $$,"\n"; +# +# ( open(BATCH,">$batchfile") +# and flock(BATCH,LOCK_EX|LOCK_NB) +# ) or die "Can't open $batchfile: $!"; +# +# my($cust_pay_batch); +# foreach $cust_pay_batch (qsearch('cust_pay_batch',{})) { +# print BATCH join(':', +# $_->getfield('cardnum'), +# $_->getfield('exp'), +# $_->getfield('amount'), +# $_->getfield('payname') +# || $_->getfield('first'). ' '. $_->getfield('last'), +# "Description", +# $_->getfield('zip'), +# ),"\n"; +# } +# +# flock(BATCH,LOCK_UN); +# close BATCH; +# +# flock(BATCHLOCK,LOCK_UN); +# close BATCHLOCK; +#} + +# subroutines + +sub untaint_argv { + foreach $_ ( $[ .. $#ARGV ) { #untaint @ARGV + $ARGV[$_] =~ /^([\w\-\/]*)$/ || die "Illegal arguement \"$ARGV[$_]\""; + $ARGV[$_]=$1; + } +} +