%
my( $cust_main ) = @_;
my $custnum = $cust_main->custnum;
my $conf = new FS::Conf;
my @payby = grep /\w/, $conf->config('payby');
#@payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH WEST COMP ))
@payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH COMP ))
unless @payby;
my %payby = map { $_=>1 } @payby;
my $s = 0;
%>
Payment History
<% if ( $payby{'BILL'} ) { %>
<%= $s++ ? ' | ' : '' %>
Post check payment
<% } %>
<% if ( $payby{'CASH'} ) { %>
<%= $s++ ? ' | ' : '' %>
Post cash payment
<% } %>
<% if ( $payby{'WEST'} ) { %>
<%= $s++ ? ' | ' : '' %>
Post Western Union payment
<% } %>
<% if ( $payby{'CARD'} || $payby{'DCRD'} ) { %>
<%= $s++ ? ' | ' : '' %>
Process credit card payment
<% } %>
<% if ( $payby{'CHEK'} || $payby{'DCHK'} ) { %>
<%= $s++ ? ' | ' : '' %>
Process electronic check (ACH) payment
<% } %>
<% if ( $payby{'MCRD'} ) { %>
<%= $s++ ? ' | ' : '' %>
Post manual credit card payment
<% } %>
Post credit
<%
#get payment history
my @history = ();
#invoices
foreach my $cust_bill ($cust_main->cust_bill) {
my $pre = ( $cust_bill->owed > 0 )
? 'Open '
: '';
my $post = ( $cust_bill->owed > 0 ) ? '' : '';
my $invnum = $cust_bill->invnum;
push @history, {
'date' => $cust_bill->_date,
'desc' => qq!!. $pre.
"Invoice #$invnum (Balance \$". $cust_bill->owed. ')'.
$post. '',
'charge' => $cust_bill->charged,
};
}
#payments (some false laziness w/credits)
foreach my $cust_pay ($cust_main->cust_pay) {
my $payby = $cust_pay->payby;
my $payinfo;
if ( $payby eq 'CARD' ) {
$payinfo = $cust_pay->payinfo_masked;
} elsif ( $payby eq 'CHEK' && $cust_pay->payinfo =~ /^(\d+)\@(\d+)$/ ) {
$payinfo = "ABA $2, Acct# $1";
} else {
$payinfo = $cust_pay->payinfo;
}
my @cust_bill_pay = $cust_pay->cust_bill_pay;
my @cust_pay_refund = $cust_pay->cust_pay_refund;
my $target = "$payby$payinfo";
$payby =~ s/^BILL$/Check #/ if $payinfo;
$payby =~ s/^CHEK$/Electronic check /;
$payby =~ s/^PREP$/Prepaid card /;
$payby =~ s/^CARD$/Credit card #/;
$payby =~ s/^COMP$/Complimentary by /;
$payby =~ s/^CASH$/Cash/;
$payby =~ s/^WEST$/Western Union/;
$payby =~ s/^MCRD$/Manual credit card/;
$payby =~ s/^BILL$//;
my $info = $payby ? " ($payby$payinfo)" : '';
my( $pre, $post, $desc, $apply, $ext ) = ( '', '', '', '', '' );
if ( scalar(@cust_bill_pay) == 0
&& scalar(@cust_pay_refund) == 0 ) {
#completely unapplied
$pre = 'Unapplied ';
$post = '';
$apply = qq! (apply)';
} elsif ( scalar(@cust_bill_pay) == 1
&& scalar(@cust_pay_refund) == 0
&& $cust_pay->unapplied == 0 ) {
#applied to one invoice, the usual situation
$desc = ' applied to Invoice #'. $cust_bill_pay[0]->invnum;
} elsif ( scalar(@cust_bill_pay) == 0
&& scalar(@cust_pay_refund) == 1
&& $cust_pay->unapplied == 0 ) {
#applied to one refund
$desc = ' refunded on '. time2str("%D", $cust_pay_refund[0]->_date);
} else {
#complicated
$desc = '
';
foreach my $app ( sort { $a->_date <=> $b->_date }
( @cust_bill_pay, @cust_pay_refund ) ) {
if ( $app->isa('FS::cust_bill_pay') ) {
$desc .= ' '.
'$'. $app->amount.
' applied to Invoice #'. $app->invnum.
'
';
#' on '. time2str("%D", $cust_bill_pay->_date).
} elsif ( $app->isa('FS::cust_pay_refund') ) {
$desc .= ' '.
'$'. $app->amount.
' refunded on'. time2str("%D", $app->_date).
'
';
} else {
die "$app is not a FS::cust_bill_pay or FS::cust_pay_refund";
}
}
if ( $cust_pay->unapplied > 0 ) {
$desc .= ' '.
'$'.
$cust_pay->unapplied. ' unapplied'.
qq! (apply)'.
'
';
}
}
my $refund = '';
my $refund_days = $conf->config('card_refund-days') || 120;
if ( $cust_pay->closed !~ /^Y/i
&& $cust_pay->payby =~ /^(CARD|CHEK)$/
&& time-$cust_pay->_date < $refund_days*86400
&& $cust_pay->unrefunded > 0
) {
$refund = qq! (refund)!;
}
my $void = '';
if ( $cust_pay->closed !~ /^Y/i
&& ( $cust_pay->payby ne 'CARD' || $conf->exists('cc-void') )
&& ( $cust_pay->payby ne 'CHEK' || $conf->exists('echeck-void') )
) {
$void = qq! (void)!;
}
my $delete = '';
if ( $cust_pay->closed !~ /^Y/i && $conf->exists('deletepayments') ) {
$delete = qq! (delete)!;
}
my $unapply = '';
if ( $cust_pay->closed !~ /^Y/i
&& $conf->exists('unapplypayments')
&& scalar(@cust_bill_pay) ) {
$unapply = qq! (unapply)!;
}
push @history, {
'date' => $cust_pay->_date,
'desc' => $pre. "Payment$post$info$desc".
"$apply$refund$void$delete$unapply",
'payment' => $cust_pay->paid,
'target' => $target,
};
}
#voided payments
foreach my $cust_pay_void ($cust_main->cust_pay_void) {
my $payby = $cust_pay_void->payby;
my $payinfo = $payby eq 'CARD'
? $cust_pay_void->payinfo_masked
: $cust_pay_void->payinfo;
$payby =~ s/^BILL$/Check #/ if $payinfo;
$payby =~ s/^CHEK$/Electronic check /;
$payby =~ s/^BILL$//;
$payby =~ s/^(CARD|COMP)$/$1 /;
my $info = $payby ? " ($payby$payinfo)" : '';
push @history, {
'date' => $cust_pay_void->_date,
'desc' => "Payment $info voided ".
time2str("%D", $cust_pay_void->void_date).
" by ". $cust_pay_void->otaker. '',
'void_payment' => $cust_pay_void->paid,
};
}
#credits (some false laziness w/payments)
foreach my $cust_credit ($cust_main->cust_credit) {
my @cust_credit_bill = $cust_credit->cust_credit_bill;
my @cust_credit_refund = $cust_credit->cust_credit_refund;
my( $pre, $post, $desc, $apply, $ext ) = ( '', '', '', '', '' );
if ( scalar(@cust_credit_bill) == 0
&& scalar(@cust_credit_refund) == 0 ) {
#completely unapplied
$pre = 'Unapplied ';
$post = '';
$apply = qq! (apply)';
} elsif ( scalar(@cust_credit_bill) == 1
&& scalar(@cust_credit_refund) == 0
&& $cust_credit->credited == 0 ) {
#applied to one invoice, the usual situation
$desc = ' applied to Invoice #'. $cust_credit_bill[0]->invnum;
} elsif ( scalar(@cust_credit_bill) == 0
&& scalar(@cust_credit_refund) == 1
&& $cust_credit->credited == 0 ) {
#applied to one refund
$desc = ' refunded on '. time2str("%D", $cust_credit_refund[0]->_date);
} else {
#complicated
$desc = '
';
foreach my $app ( sort { $a->_date <=> $b->_date }
( @cust_credit_bill, @cust_credit_refund ) ) {
if ( $app->isa('FS::cust_credit_bill') ) {
$desc .= ' '.
'$'. $app->amount.
' applied to Invoice #'. $app->invnum.
'
';
#' on '. time2str("%D", $app->_date).
} elsif ( $app->isa('FS::cust_credit_refund') ) {
$desc .= ' '.
'$'. $app->amount.
' refunded on'. time2str("%D", $app->_date).
'
';
} else {
die "$app is not a FS::cust_credit_bill or a FS::cust_credit_refund";
}
}
if ( $cust_credit->credited > 0 ) {
$desc .= ' $'.
$cust_credit->credited. ' unapplied'.
qq! (apply)'.
'
';
}
}
#
my $delete = '';
if ( $cust_credit->closed !~ /^Y/i && $conf->exists('deletecredits') ) {
$delete = qq! (!.
qq!delete)!;
}
my $unapply = '';
if ( $cust_credit->closed !~ /^Y/i
&& $conf->exists('unapplycredits')
&& scalar(@cust_credit_bill) ) {
$unapply = qq! (!.
qq!unapply)!;
}
push @history, {
'date' => $cust_credit->_date,
'desc' => $pre. "Credit$post by ". $cust_credit->otaker.
' ('. $cust_credit->reason. ')'.
"$desc$apply$delete$unapply",
'credit' => $cust_credit->amount,
};
}
#refunds
foreach my $cust_refund ($cust_main->cust_refund) {
my $payby = $cust_refund->payby;
my $payinfo = $payby eq 'CARD'
? $cust_refund->payinfo_masked
: $cust_refund->payinfo;
$payby =~ s/^BILL$/Check #/ if $payinfo;
$payby =~ s/^CHEK$/Electronic check /;
$payby =~ s/^(CARD|COMP)$/$1 /;
push @history, {
'date' => $cust_refund->_date,
'desc' => "Refund ($payby$payinfo) by ". $cust_refund->otaker,
'refund' => $cust_refund->refund,
};
}
%>
<%= table() %>