Initial revision
authorivan <ivan>
Mon, 24 Aug 1998 02:01:19 +0000 (02:01 +0000)
committerivan <ivan>
Mon, 24 Aug 1998 02:01:19 +0000 (02:01 +0000)
bin/bill [new file with mode: 0755]

diff --git a/bin/bill b/bin/bill
new file mode 100755 (executable)
index 0000000..5c5be70
--- /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)=<BATCHLOCK>;
+#    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;
+  }
+}
+