4 use vars qw( $days_to_pay $cust_main $cust_pkg
11 use FS::Record qw(qsearch qsearchs);
12 use FS::UID qw(adminsuidsetup);
16 getopts('ed:qpl:scbyoi', \%opt);
17 my $user = shift or die &usage;
21 my $now = time; #eventually take a time option like freeside-bill
22 my ($sec,$min,$hour,$mday,$mon,$year) =
23 (localtime($now) )[0,1,2,3,4,5];
27 foreach $cust_main ( qsearch('cust_main',{} ) ) {
29 my ( $eyear, $emon, $eday ) = ( 2037, 12, 31 );
30 if ( $cust_main->paydate =~ /^(\d{4})\-(\d{1,2})\-(\d{1,2})$/
31 && $cust_main->payby eq 'BILL') {
32 ( $eyear, $emon, $eday ) = ( $1, $2, $3 );
36 && $cust_main->balance_date(time - $opt{d} * 86400) > 0
37 && qsearchs( 'cust_pkg', { 'custnum' => $cust_main->custnum,
40 && $cust_main->payby eq 'BILL'
42 || ( $eyear == $year && $emon < $mon ) ) )
46 print $cust_main->custnum, "\t",
47 $cust_main->last, "\t", $cust_main->first, "\t",
48 $cust_main->balance_date(time-$opt{d} * 86400);
51 if ( $opt{p} && ! grep { $_ eq 'POST' } $cust_main->invoicing_list ) {
52 print "\n\tAdding postal invoicing" unless $opt{q};
53 my @invoicing_list = $cust_main->invoicing_list;
54 push @invoicing_list, 'POST';
55 $cust_main->invoicing_list(\@invoicing_list);
59 print "\n\tCharging late fee of \$$opt{l}" unless $opt{q};
60 my $error = $cust_main->charge($opt{l}, 'Late fee');
61 # comment or plandata with info so we don't redo the same late fee every
65 foreach $cust_pkg ( qsearch( 'cust_pkg',
66 { 'custnum' => $cust_main->custnum } ) ) {
69 print "\n\tSuspending pkgnum " . $cust_pkg->pkgnum unless $opt{q};
74 print "\n\tCancelling pkgnum " . $cust_pkg->pkgnum unless $opt{q};
81 print "\n\tBilling" unless $opt{q};
82 my $error = $cust_main->bill('time'=>$now);
83 warn "Error billing, customer #" . $cust_main->custnum .
84 ":" . $error if $error;
88 print "\n\tApplying outstanding payments and credits" unless $opt{q};
89 $cust_main->apply_payments;
90 $cust_main->apply_credits;
94 print "\n\tCollecting" unless $opt{q};
95 my $error = $cust_main->collect(
96 'invoice_time' => $now,
97 'batch_card' => $opt{i} ? 'no' : 'yes',
98 'force_print' => 'yes',
100 warn "Error collecting from customer #" . $cust_main->custnum. ":$error"
104 print "\n" unless $opt{q};
111 foreach $_ ( $[ .. $#ARGV ) {
112 $ARGV[$_] =~ /^([\w\-\/\.]*)$/ || die "Illegal arguement \"$ARGV[$_]\"";
118 die "Usage:\n\n freeside-overdue [ -e ] [ -d days ] [ -q ] [ -p ] [ -l amount ] [ -s ] [ -c ] [ -b ] [ -y ] [ -o [ -i ] ] user\n";
124 freeside-overdue - Perform actions on overdue and/or expired accounts.
128 freeside-overdue [ -e ] [ -d days ] [ -q ] [ -p ] [ -l amount ] [ -s ] [ -c ] [ -b ] [ -y ] [ -o [ -i ] ] user
132 This script is deprecated in 1.4.0. You should use freeside-daily and invoice
135 Performs actions on overdue and/or expired accounts.
137 Selection options (at least one selection option is required):
139 -d: Customers with a balance due on invoices older than the supplied number
140 of days. Requires an integer argument.
142 -e: Customers with a billing expiration date in the past.
146 -q: Be quiet (by default, selected accounts are printed).
148 -p: Add postal invoicing to the relevant customers.
150 -l: Add a charge of the given amount to the relevant customers.
152 -s: Suspend accounts.
156 -b: Bill customers (create invoices)
158 -y: Apply unapplied payments and credits
160 -o: Collect from customers (charge cards, print invoices)
162 -i: real-time billing (as opposed to batch billing). only relevant
165 user: From the mapsecrets file - see config.html from the base documentation
169 Example crontab entries:
171 # suspend expired accounts
172 20 4 * * * freeside-overdue -e -s user
174 # quietly add postal invoicing to customers over 30 days past due
175 20 4 * * * freeside-overdue -d 30 -p -q user
177 # suspend accounts and charge a $10.23 fee for customers over 60 days past due
178 20 4 * * * freeside-overdue -d 60 -s -l 10.23 user
180 # cancel accounts over 90 days past due
181 20 4 * * * freeside-overdue -d 90 -c user
183 =head1 ORIGINAL AUTHORS
185 Original disable-overdue version by mw/kwh: Mark W.? and Kristian Hoffmann ?
187 Ivan seems to be turning it into the "do-everything" CLI.
191 Hell now that this is the do-everything CLI it should have --longoptions