additional due_cust_event debugging
[freeside.git] / FS / FS / Cron / bill.pm
1 package FS::Cron::bill;
2
3 use strict;
4 use vars qw( @ISA @EXPORT_OK );
5 use Exporter;
6 use Date::Parse;
7 use FS::Record qw(qsearch qsearchs);
8 use FS::cust_main;
9 use FS::part_event;
10 use FS::part_event_condition;
11
12 @ISA = qw( Exporter );
13 @EXPORT_OK = qw ( bill );
14
15 sub bill {
16
17   my %opt = @_;
18
19   my $check_freq = $opt{'check_freq'} || '1d';
20
21   my $debug = 0;
22   $debug = 1 if $opt{'v'};
23   $debug = $opt{'l'} if $opt{'l'};
24  
25   $FS::cust_main::DEBUG = $debug;
26   #$FS::cust_event::DEBUG = $opt{'l'} if $opt{'l'};
27
28   my %search = ();
29   $search{'payby'}    = $opt{'p'} if $opt{'p'};
30   $search{'agentnum'} = $opt{'a'} if $opt{'a'};
31   
32   #we're at now now (and later).
33   my($time)= $opt{'d'} ? str2time($opt{'d'}) : $^T;
34   $time += $opt{'y'} * 86400 if $opt{'y'};
35
36   my $invoice_time = $opt{'n'} ? $^T : $time;
37
38   # select * from cust_main where
39   my $where_pkg = <<"END";
40     0 < ( select count(*) from cust_pkg
41             where cust_main.custnum = cust_pkg.custnum
42               and ( cancel is null or cancel = 0 )
43               and (    setup is null or setup =  0
44                     or bill  is null or bill  <= $time 
45                     or ( expire is not null and expire <= $^T )
46                     or ( adjourn is not null and adjourn <= $^T )
47                   )
48         )
49 END
50
51   my $where_event = join(' OR ', map {
52     my $eventtable = $_;
53
54     my $join  = FS::part_event_condition->join_conditions_sql(  $eventtable );
55     my $where = FS::part_event_condition->where_conditions_sql( $eventtable,
56                                                                 'time'=>$time,
57                                                               );
58
59     my $are_part_event = 
60       "0 < ( SELECT COUNT(*) FROM part_event $join
61                WHERE check_freq = '$check_freq'
62                  AND eventtable = '$eventtable'
63                  AND ( disabled = '' OR disabled IS NULL )
64                  AND $where
65            )
66       ";
67
68     if ( $eventtable eq 'cust_main' ) { 
69       $are_part_event;
70     } else {
71       "0 < ( SELECT COUNT(*) FROM $eventtable
72                WHERE cust_main.custnum = $eventtable.custnum
73                  AND $are_part_event
74            )
75       ";
76     }
77
78   } FS::part_event->eventtables);
79
80   my $extra_sql = ( scalar(%search) ? ' AND ' : ' WHERE ' ).
81                   "( $where_pkg OR $where_event )";
82
83   my @cust_main;
84   if ( @ARGV ) {
85     @cust_main = map { qsearchs('cust_main', { custnum => $_, %search } ) } @ARGV
86   } else {
87
88     warn "searching for customers:\n".
89          join("\n", map "  $_ => ".$search{$_}, keys %search). "\n".
90          "  $extra_sql\n"
91       if $opt{'v'} || $opt{'l'};
92
93     @cust_main = qsearch({
94       'table'     => 'cust_main',
95       'hashref'   => \%search,
96       'extra_sql' => $extra_sql,
97     });
98
99   }
100   
101   foreach my $cust_main ( @cust_main ) {
102
103     if ( $opt{'m'} ) {
104
105       #add job to queue that calls bill_and_collect with options
106         my $queue = new FS::queue {
107           'job'    => 'FS::cust_main::queued_bill',
108           'secure' => 'Y',
109         };
110         my $error = $queue->insert(
111         'custnum'      => $cust_main->custnum,
112         'time'         => $time,
113         'invoice_time' => $invoice_time,
114         'check_freq'   => $check_freq,
115         'resetup'      => $opt{'s'} ? $opt{'s'} : 0,
116       );
117
118     } else {
119
120       $cust_main->bill_and_collect(
121         'time'         => $time,
122         'invoice_time' => $invoice_time,
123         'check_freq'   => $check_freq,
124         'resetup'      => $opt{'s'},
125         'debug'        => $debug,
126       );
127
128     }
129
130   }
131
132 }