From 96528846ba030e43a45d0787140be865f7783698 Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Thu, 9 May 2013 15:07:39 -0700 Subject: [PATCH] billing events for reconciling inactive accounts, #19873 --- FS/FS/part_event/Action/fee.pm | 18 ++++++++++-- FS/FS/part_event/Condition/inactive_age.pm | 46 ++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 FS/FS/part_event/Condition/inactive_age.pm diff --git a/FS/FS/part_event/Action/fee.pm b/FS/FS/part_event/Action/fee.pm index 68288d090..cd9e200c8 100644 --- a/FS/FS/part_event/Action/fee.pm +++ b/FS/FS/part_event/Action/fee.pm @@ -17,14 +17,25 @@ sub option_fields { type=>'checkbox', value=>'Y' }, 'nextbill' => { label=>'Hold late fee until next invoice', type=>'checkbox', value=>'Y' }, + 'limit_to_credit'=> + { label=>"Charge no more than the customer's credit balance", + type=>'checkbox', value=>'Y' }, ); } sub default_weight { 10; } sub _calc_fee { - #my( $self, $cust_object ) = @_; - my $self = shift; + my( $self, $cust_object ) = @_; + if ( $self->option('limit_to_credit') ) { + my $balance = $cust_object->cust_main->balance; + if ( $balance >= 0 ) { + return 0; + } elsif ( (-1 * $balance) < $self->option('charge') ) { + return -1 * $balance; + } + } + $self->option('charge'); } @@ -44,6 +55,9 @@ sub do_action { 'setuptax' => $self->option('setuptax'), ); + # amazingly, FS::cust_main::charge will allow a charge of zero + return '' if $charge{'amount'} == 0; + #unless its more than N months away? $charge{'start_date'} = $cust_main->next_bill_date if $self->option('nextbill'); diff --git a/FS/FS/part_event/Condition/inactive_age.pm b/FS/FS/part_event/Condition/inactive_age.pm new file mode 100644 index 000000000..8918a1a3c --- /dev/null +++ b/FS/FS/part_event/Condition/inactive_age.pm @@ -0,0 +1,46 @@ +package FS::part_event::Condition::inactive_age; + +use strict; +use base qw( FS::part_event::Condition ); +use FS::Record qw( qsearch ); + +sub description { 'Days without billing activity' } + +sub option_fields { + ( + 'age' => { 'label' => 'No activity within', + 'type' => 'freq', + }, + # flags to select kinds of activity, + # like if you just want "no payments since"? + # not relevant yet + ); +} + +sub condition { + my( $self, $obj, %opt ) = @_; + my $custnum = $obj->custnum; + my $age = $self->option_age_from('age', $opt{'time'} ); + + foreach my $t (qw(cust_bill cust_pay cust_credit cust_refund)) { + my $class = "FS::$t"; + return 0 if $class->count("custnum = $custnum AND _date >= $age"); + } + 1; +} + +sub condition_sql { + my( $class, $table, %opt ) = @_; + my $age = $class->condition_sql_option_age_from('age', $opt{'time'}); + my @sql; + for my $t (qw(cust_bill cust_pay cust_credit cust_refund)) { + push @sql, + "NOT EXISTS( SELECT 1 FROM $t ". + "WHERE $t.custnum = cust_main.custnum AND $t._date >= $age". + ")"; + } + join(' AND ', @sql); +} + +1; + -- 2.11.0