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