summaryrefslogtreecommitdiff
path: root/FS/FS/Cron/breakage.pm
blob: 6dd904d6a4079cce4cc6453b02e5435ee9afde7a (plain)
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;