import torrus 1.0.9
[freeside.git] / FS / FS / Cron / breakage.pm
1 package FS::Cron::breakage;
2
3 use strict;
4 use base 'Exporter';
5 use vars qw( @EXPORT_OK );
6 use FS::Conf;
7 use FS::Record qw(qsearch);
8 use FS::agent;
9 use FS::cust_main;
10
11 @EXPORT_OK = qw ( reconcile_breakage );
12
13 #freeside-daily %opt
14 # -v: enable debugging
15 # -l: debugging level
16
17 sub reconcile_breakage {
18   my %opt = @_;
19
20   my $conf = new FS::Conf;
21
22   foreach my $agent (qsearch('agent', {})) {
23
24     my $days = $conf->config('breakage-days', $agent->agentnum)
25       or next;
26
27     my $since = int( $^T - ($days * 86400) );
28
29     warn 'searching '. $agent->agent.  " for customers with unapplied payments more than $days days old\n"
30       if $opt{'v'};
31
32     #find customers w/negative balance older than $days (and no activity since)
33     # and no activity (invoices/payments/credits/refunds) newer than $since
34     #  (XXX except antother breakage invoice???)
35
36     my $extra_sql =
37       ' AND 0 > '. FS::cust_main->balance_sql.
38       ' AND '. join(' AND ', map {
39         " NOT EXISTS (
40             SELECT 1 FROM $_
41               WHERE $_.custnum = cust_main.custnum
42                 AND _date >= $since
43           ) "
44         } qw( cust_bill cust_pay cust_credit cust_refund )
45       );
46
47     my @customers = qsearch({
48       'table'     => 'cust_main',
49       'hashref'   => { 'agentnum' => $agent->agentnum,
50                        'payby'    => { op=>'!=', value=>'COMP', },
51                      },
52       'extra_sql' => $extra_sql,
53     });
54
55     #and then create a "breakage" charge & invoice for them
56
57     foreach my $cust_main ( @customers ) {
58
59       warn 'reconciling breakage for customer '. $cust_main->custnum.
60            ': '. $cust_main->name. "\n"
61         if $opt{'v'};
62
63       my $error =
64         $cust_main->charge({
65           'amount'   => sprintf('%.2f', 0 - $cust_main->balance ),
66           'pkg'      => 'Breakage',
67           'comment'  => 'breakage reconciliation',
68           'classnum' => scalar($conf->config('breakage-pkg_class')),
69           'setuptax' => 'Y',
70           'bill_now' => 1,
71         })
72         || $cust_main->apply_payments_and_credits;
73
74       if ( $error ) {
75         warn "error charging for breakage reconciliation: $error\n";
76       }
77
78     }
79
80   }
81
82 }
83
84 1;