this is a quick hack to rebill customers when a cdr didn't happen
[freeside.git] / bin / rebill
diff --git a/bin/rebill b/bin/rebill
new file mode 100755 (executable)
index 0000000..4f05238
--- /dev/null
@@ -0,0 +1,132 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Getopt::Std;
+use Date::Parse;
+use FS::UID qw(adminsuidsetup);
+use FS::Record qw( qsearch );
+use cust_main_special;
+
+&untaint_argv; #what it sounds like  (eww)
+use vars qw(%opt);
+getopts("p:a:d:sy:n", \%opt);
+
+my $user = shift or die &usage;
+adminsuidsetup $user;
+
+my (@custnums) = @ARGV;
+
+my $time = $opt{d} ? str2time($opt{d}) : $^T;
+$time += $opt{y} * 86400 if $opt{y};
+my $invoice_time = $opt{n} ? $^T : $time;
+
+my %args = (
+  'time'         => $time,
+  'invoice_time' => $invoice_time,
+  'actual_time'  => $^T, #when freeside-bill was started
+                         #(not, when using -m, freeside-queued)
+  'resetup'      => ( $opt{'s'} ? $opt{'s'} : 0 ),
+  'backbill'     => $time,
+);
+
+my $extra_sql = ( $opt{a} || $opt{p} ) ? ' AND ' : ' WHERE ';
+$extra_sql .= "( ". join( ' OR ', map{ "custnum = $_" } @custnums ). " )";
+$extra_sql = '' unless scalar @custnums;
+
+my @cust = qsearch( { table   => 'cust_main',
+                      hashref => { $opt{a} ? ( 'agentnum' => $opt{a} ) : (),
+                                   $opt{p} ? ( 'payby'    => $opt{p} ) : (),
+                                 },
+                      extra_sql => $extra_sql,
+                    }
+                  );
+
+foreach my $cust ( @cust ) {
+  my $balance = $cust->balance;
+  cust_main_special::bill($cust, %args);
+  if ($balance != $cust->balance){
+    $cust->apply_payments_and_credits;
+    my $error = $cust->collect(%args);
+    warn "Error collecting, custnum ". $cust->custnum. ": $error" if $error;
+  }
+}
+
+
+###
+# subroutines
+###
+
+sub untaint_argv {
+  foreach $_ ( $[ .. $#ARGV ) { #untaint @ARGV
+    #$ARGV[$_] =~ /^([\w\-\/]*)$/ || die "Illegal arguement \"$ARGV[$_]\"";
+    # Date::Parse
+    $ARGV[$_] =~ /^(.*)$/ || die "Illegal arguement \"$ARGV[$_]\"";
+    $ARGV[$_]=$1;
+  }
+}
+
+sub usage {
+  die "Usage:\n\n  freeside-daily [ -d 'date' ] [ -y days ] [ -p 'payby' ] [ -a agentnum ] [ -s ] user [ custnum custnum ... ]\n";
+}
+
+###
+# documentation
+###
+
+=head1 NAME
+
+freeside-daily - Run daily billing and invoice collection events.
+
+=head1 SYNOPSIS
+
+  freeside-daily [ -d 'date' ] [ -y days ] [ -p 'payby' ] [ -a agentnum ] [ -s ] user [ custnum custnum ... ]
+
+=head1 DESCRIPTION
+
+Bills customers and runs invoice collection events.  Should be run from
+crontab daily.
+
+Bills customers.  Searches for customers who are due for billing and calls
+the bill and collect methods of a cust_main object.  See L<FS::cust_main>.
+
+  -d: Pretend it's 'date'.  Date is in any format Date::Parse is happy with,
+      but be careful.
+
+  -y: In addition to -d, which specifies an absolute date, the -y switch
+      specifies an offset, in days.  For example, "-y 15" would increment the
+      "pretend date" 15 days from whatever was specified by the -d switch
+      (or now, if no -d switch was given).
+
+  -n: When used with "-d" and/or "-y", specifies that invoices should be dated
+      with today's date, irregardless of the pretend date used to pre-generate
+      the invoices.
+
+  -p: Only process customers with the specified payby (I<CARD>, I<DCRD>, I<CHEK>, I<DCHK>, I<BILL>, I<COMP>, I<LECB>)
+
+  -a: Only process customers with the specified agentnum
+
+  -s: re-charge setup fees
+
+  -v: enable debugging
+
+  -l: debugging level
+
+  -m: Experimental multi-process mode uses the job queue for multi-process and/or multi-machine billing.
+
+  -r: Multi-process mode dry run option
+
+  -k: skip notify_flat_delay and vacuum
+
+user: From the mapsecrets file - see config.html from the base documentation
+
+custnum: if one or more customer numbers are specified, only bills those
+customers.  Otherwise, bills all customers.
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::cust_main>, config.html from the base documentation
+
+=cut
+