1 package FS::Cron::bill;
4 use vars qw( @ISA @EXPORT_OK );
8 use FS::Record qw(qsearchs);
11 @ISA = qw( Exporter );
12 @EXPORT_OK = qw ( bill );
19 $debug = 1 if $opt{'v'};
20 $debug = $opt{'l'} if $opt{'l'};
22 $FS::cust_main::DEBUG = $debug;
23 #$FS::cust_event::DEBUG = $opt{'l'} if $opt{'l'};
27 push @search, "( cust_main.archived != 'Y' OR archived IS NULL )"; #disable?
29 push @search, "cust_main.payby = '". $opt{'p'}. "'"
31 push @search, "cust_main.agentnum = ". $opt{'a'}
36 join(' OR ', map "cust_main.custnum = $_", @ARGV ).
41 # generate where_pkg / where_bill_event search clause (1.7-style)
44 #we're at now now (and later).
45 my($time)= $opt{'d'} ? str2time($opt{'d'}) : $^T;
46 $time += $opt{'y'} * 86400 if $opt{'y'};
48 my $invoice_time = $opt{'n'} ? $^T : $time;
50 # select * from cust_main where
51 my $where_pkg = <<"END";
52 0 < ( select count(*) from cust_pkg
53 where cust_main.custnum = cust_pkg.custnum
54 and ( cancel is null or cancel = 0 )
55 and ( setup is null or setup = 0
56 or bill is null or bill <= $time
57 or ( expire is not null and expire <= $^T )
58 or ( adjourn is not null and adjourn <= $^T )
64 my $where_bill_event = <<"END";
65 0 < ( select count(*) from cust_bill
66 where cust_main.custnum = cust_bill.custnum
69 ( select sum(amount) from cust_bill_pay
70 where cust_bill.invnum = cust_bill_pay.invnum )
74 ( select sum(amount) from cust_credit_bill
75 where cust_bill.invnum = cust_credit_bill.invnum )
78 and 0 < ( select count(*) from part_bill_event
79 where payby = cust_main.payby
80 and ( disabled is null or disabled = '' )
81 and seconds <= $time - cust_bill._date
82 and 0 = ( select count(*) from cust_bill_event
83 where cust_bill.invnum = cust_bill_event.invnum
84 and part_bill_event.eventpart = cust_bill_event.eventpart
92 push @search, "( $where_pkg OR $where_bill_event )";
95 # get a list of custnums
98 warn "searching for customers:\n". join("\n", @search). "\n"
99 if $opt{'v'} || $opt{'l'};
101 my $sth = dbh->prepare(
102 "SELECT custnum FROM cust_main".
103 " WHERE ". join(' AND ', @search)
104 ) or die dbh->errstr;
106 $sth->execute or die $sth->errstr;
108 my @custnums = map { $_->[0] } @{ $sth->fetchall_arrayref };
111 # for each custnum, queue or make one customer object and bill
112 # (one at a time, to reduce memory footprint with large #s of customers)
115 foreach my $custnum ( @custnums ) {
119 'invoice_time' => $invoice_time,
120 'actual_time' => $^T, #when freeside-bill was started
121 #(not, when using -m, freeside-queued)
122 'resetup' => ( $opt{'s'} ? $opt{'s'} : 0 ),
127 #add job to queue that calls bill_and_collect with options
128 my $queue = new FS::queue {
129 'job' => 'FS::cust_main::queued_bill',
130 'priority' => 99, #don't get in the way of provisioning jobs
132 my $error = $queue->insert( 'custnum'=>$custnum, %args );
136 my $cust_main = qsearchs( 'cust_main', { 'custnum' => $custnum } );
137 $cust_main->bill_and_collect( %args, 'debug' => $debug );