summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorivan <ivan>2008-06-01 22:48:15 +0000
committerivan <ivan>2008-06-01 22:48:15 +0000
commit15a02054fe0f91eda70003b8d1cf29497d19aa91 (patch)
tree68cd3680377bacb8a54785cf4aea7afbe1c78a4d
parentd8cbc19ac6d9d4aa9df946e6c9912bbcac26ef82 (diff)
refactor payment history slightly, add refund receipts, have "unapplied" refunds show like other unapplied/open things, RT#3545
-rw-r--r--FS/FS/cust_pay.pm88
-rw-r--r--FS/FS/cust_refund.pm7
-rw-r--r--FS/FS/payinfo_Mixin.pm2
-rw-r--r--FS/FS/payinfo_transaction_Mixin.pm122
-rwxr-xr-xhttemplate/search/elements/cust_pay_or_refund.html7
-rw-r--r--httemplate/view/cust_main/payment_history.html454
-rw-r--r--httemplate/view/cust_main/payment_history/credit.html110
-rw-r--r--httemplate/view/cust_main/payment_history/invoice.html34
-rw-r--r--httemplate/view/cust_main/payment_history/payment.html180
-rw-r--r--httemplate/view/cust_main/payment_history/refund.html50
-rw-r--r--httemplate/view/cust_main/payment_history/voided_payment.html37
-rw-r--r--httemplate/view/cust_refund.html141
12 files changed, 737 insertions, 495 deletions
diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm
index 03e355f..1568870 100644
--- a/FS/FS/cust_pay.pm
+++ b/FS/FS/cust_pay.pm
@@ -12,14 +12,14 @@ use FS::Misc qw( send_email );
use FS::Record qw( dbh qsearch qsearchs );
use FS::payby;
use FS::cust_main_Mixin;
-use FS::payinfo_Mixin;
+use FS::payinfo_transaction_Mixin;
use FS::cust_bill;
use FS::cust_bill_pay;
use FS::cust_pay_refund;
use FS::cust_main;
use FS::cust_pay_void;
-@ISA = qw( FS::Record FS::cust_main_Mixin FS::payinfo_Mixin );
+@ISA = qw( FS::payinfo_transaction_Mixin FS::cust_main_Mixin FS::Record );
$DEBUG = 0;
@@ -550,90 +550,6 @@ sub unrefunded {
sprintf("%.2f", $amount );
}
-
-=item cust_main
-
-Returns the parent customer object (see L<FS::cust_main>).
-
-=cut
-
-sub cust_main {
- my $self = shift;
- qsearchs( 'cust_main', { 'custnum' => $self->custnum } );
-}
-
-=item payby_name
-
-Returns a name for the payby field.
-
-=cut
-
-sub payby_name {
- my $self = shift;
- if ( $self->payby eq 'BILL' ) { #kludge
- 'Check';
- } else {
- FS::payby->shortname( $self->payby );
- }
-}
-
-=item gatewaynum
-
-Returns a gatewaynum for the processing gateway.
-
-=item processor
-
-Returns a name for the processing gateway.
-
-=item authorization
-
-Returns a name for the processing gateway.
-
-=item order_number
-
-Returns a name for the processing gateway.
-
-=cut
-
-sub gatewaynum { shift->_parse_paybatch->{'gatewaynum'}; }
-sub processor { shift->_parse_paybatch->{'processor'}; }
-sub authorization { shift->_parse_paybatch->{'authorization'}; }
-sub order_number { shift->_parse_paybatch->{'order_number'}; }
-
-#sucks that this stuff is in paybatch like this in the first place,
-#but at least other code can start to use new field names
-#(code nicked from FS::cust_main::realtime_refund_bop)
-sub _parse_paybatch {
- my $self = shift;
-
- $self->paybatch =~ /^((\d+)\-)?(\w+):\s*([\w\-\/ ]*)(:([\w\-]+))?$/
- or return {};
- #"Can't parse paybatch for paynum $options{'paynum'}: ".
- # $cust_pay->paybatch;
-
- my( $gatewaynum, $processor, $auth, $order_number ) = ( $2, $3, $4, $6 );
-
- if ( $gatewaynum ) { #gateway for the payment to be refunded
-
- my $payment_gateway =
- qsearchs('payment_gateway', { 'gatewaynum' => $gatewaynum } );
-
- die "payment gateway $gatewaynum not found" #?
- unless $payment_gateway;
-
- $processor = $payment_gateway->gateway_module;
-
- }
-
- {
- 'gatewaynum' => $gatewaynum,
- 'processor' => $processor,
- 'authorization' => $auth,
- 'order_number' => $order_number,
- };
-
-}
-
=back
=head1 CLASS METHODS
diff --git a/FS/FS/cust_refund.pm b/FS/FS/cust_refund.pm
index e075e3e..abc131e 100644
--- a/FS/FS/cust_refund.pm
+++ b/FS/FS/cust_refund.pm
@@ -3,15 +3,16 @@ package FS::cust_refund;
use strict;
use vars qw( @ISA @encrypted_fields );
use Business::CreditCard;
-use FS::Record qw( qsearch qsearchs dbh );
use FS::UID qw(getotaker);
+use FS::Record qw( qsearch qsearchs dbh );
+use FS::cust_main_Mixin;
+use FS::payinfo_transaction_Mixin;
use FS::cust_credit;
use FS::cust_credit_refund;
use FS::cust_pay_refund;
use FS::cust_main;
-use FS::payinfo_Mixin;
-@ISA = qw( FS::payinfo_Mixin FS::cust_main_Mixin FS::Record );
+@ISA = qw( FS::payinfo_transaction_Mixin FS::cust_main_Mixin FS::Record );
@encrypted_fields = ('payinfo');
diff --git a/FS/FS/payinfo_Mixin.pm b/FS/FS/payinfo_Mixin.pm
index fb56371..99cca6a 100644
--- a/FS/FS/payinfo_Mixin.pm
+++ b/FS/FS/payinfo_Mixin.pm
@@ -271,6 +271,8 @@ sub payby_payinfo_pretty {
}
}
+=back
+
=head1 BUGS
Future items?
diff --git a/FS/FS/payinfo_transaction_Mixin.pm b/FS/FS/payinfo_transaction_Mixin.pm
new file mode 100644
index 0000000..a6a2c99
--- /dev/null
+++ b/FS/FS/payinfo_transaction_Mixin.pm
@@ -0,0 +1,122 @@
+package FS::payinfo_transaction_Mixin;
+
+use strict;
+use vars qw( @ISA );
+use FS::payby;
+use FS::payinfo_Mixin;
+
+@ISA = qw( FS::payinfo_Mixin );
+
+=head1 NAME
+
+FS::payinfo_transaction_Mixin - Mixin class for records in tables that represent transactions.
+
+=head1 SYNOPSIS
+
+package FS::some_table;
+use vars qw(@ISA);
+@ISA = qw( FS::payinfo_transaction_Mixin FS::Record );
+
+=head1 DESCRIPTION
+
+This is a mixin class for records that represent transactions: that contain
+payinfo and paybatch. Currently FS::cust_pay and FS::cust_refund
+
+=head1 METHODS
+
+=over 4
+
+
+=item cust_main
+
+Returns the parent customer object (see L<FS::cust_main>).
+
+=cut
+
+sub cust_main {
+ my $self = shift;
+ qsearchs( 'cust_main', { 'custnum' => $self->custnum } );
+}
+
+=item payby_name
+
+Returns a name for the payby field.
+
+=cut
+
+sub payby_name {
+ my $self = shift;
+ if ( $self->payby eq 'BILL' ) { #kludge
+ 'Check';
+ } else {
+ FS::payby->shortname( $self->payby );
+ }
+}
+
+=item gatewaynum
+
+Returns a gatewaynum for the processing gateway.
+
+=item processor
+
+Returns a name for the processing gateway.
+
+=item authorization
+
+Returns a name for the processing gateway.
+
+=item order_number
+
+Returns a name for the processing gateway.
+
+=cut
+
+sub gatewaynum { shift->_parse_paybatch->{'gatewaynum'}; }
+sub processor { shift->_parse_paybatch->{'processor'}; }
+sub authorization { shift->_parse_paybatch->{'authorization'}; }
+sub order_number { shift->_parse_paybatch->{'order_number'}; }
+
+#sucks that this stuff is in paybatch like this in the first place,
+#but at least other code can start to use new field names
+#(code nicked from FS::cust_main::realtime_refund_bop)
+sub _parse_paybatch {
+ my $self = shift;
+
+ $self->paybatch =~ /^((\d+)\-)?(\w+):\s*([\w\-\/ ]*)(:([\w\-]+))?$/
+ or return {};
+ #"Can't parse paybatch for paynum $options{'paynum'}: ".
+ # $cust_pay->paybatch;
+
+ my( $gatewaynum, $processor, $auth, $order_number ) = ( $2, $3, $4, $6 );
+
+ if ( $gatewaynum ) { #gateway for the payment to be refunded
+
+ my $payment_gateway =
+ qsearchs('payment_gateway', { 'gatewaynum' => $gatewaynum } );
+
+ die "payment gateway $gatewaynum not found" #?
+ unless $payment_gateway;
+
+ $processor = $payment_gateway->gateway_module;
+
+ }
+
+ {
+ 'gatewaynum' => $gatewaynum,
+ 'processor' => $processor,
+ 'authorization' => $auth,
+ 'order_number' => $order_number,
+ };
+
+}
+
+
+
+
+=back
+
+=head1 SEE ALSO
+
+L<FS::payinfo_Mixin>
+
+=back
diff --git a/httemplate/search/elements/cust_pay_or_refund.html b/httemplate/search/elements/cust_pay_or_refund.html
index cd1e19d..9457ae2 100755
--- a/httemplate/search/elements/cust_pay_or_refund.html
+++ b/httemplate/search/elements/cust_pay_or_refund.html
@@ -242,10 +242,9 @@ if ( $cgi->param('magic') ) {
}
my $link = '';
-if ( $thing eq 'pay' ) { #XXX no refund receipts yet
- $link = [ "${p}view/cust_pay.html?paynum=", 'paynum' ]
- if $FS::CurrentUser::CurrentUser->access_right('View invoices'); #XXX for now
- #later# if $FS::CurrentUser::CurrentUser->access_right('View customer payments');
+if ( $FS::CurrentUser::CurrentUser->access_right('View invoices') #XXX for now
+ || $FS::CurrentUser::CurrentUser->access_right('View customer payments') ){
+ $link = [ "${p}view/cust_$thing.html?${thing}num=", $thing.'num' ]
}
my $cust_link = sub {
diff --git a/httemplate/view/cust_main/payment_history.html b/httemplate/view/cust_main/payment_history.html
index 582fc8d..750e59d 100644
--- a/httemplate/view/cust_main/payment_history.html
+++ b/httemplate/view/cust_main/payment_history.html
@@ -84,408 +84,6 @@
<BR>
% }
-%#get payment history
-%my @history = ();
-%
-%#invoices
-%foreach my $cust_bill ($cust_main->cust_bill) {
-% my $pre = ( $cust_bill->owed > 0 )
-% ? '<B><FONT SIZE="+1" COLOR="#FF0000">Open '
-% : '';
-% my $post = ( $cust_bill->owed > 0 ) ? '</FONT></B>' : '';
-% my $invnum = $cust_bill->invnum;
-% my $link = $curuser->access_right('View invoices')
-% ? qq!<A HREF="${p}view/cust_bill.cgi?$invnum">!
-% : '';
-% my $events = '';
-% if ( $cust_bill->num_cust_event
-% && ( $curuser->access_right('Billing event reports')
-% || $curuser->access_right('View customer billing events')
-% )
-% ) {
-% $events =
-% qq!<BR><FONT SIZE="-1"><A HREF="${p}search/cust_event.html?invnum=!.
-% $cust_bill->invnum. '">(&nbsp;View invoice events&nbsp;)</A></FONT>';
-% }
-% push @history, {
-% 'date' => $cust_bill->_date,
-% 'desc' => $link. $pre.
-% "Invoice #$invnum (Balance \$". $cust_bill->owed. ')'.
-% $post. ( $link ? '</A>' : '' ). $events,
-% '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->paymask;
-% } elsif ( $payby eq 'CHEK' ) {
-% my( $account, $aba ) = split('@', $cust_pay->paymask );
-% $payinfo = "ABA $aba, Acct #$account";
-% } 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 = '<B><FONT COLOR="#FF0000">Unapplied ';
-% $post = '</FONT></B>';
-% if ( $curuser->access_right('Apply payment') ) {
-% $apply = ' ('. include( '/elements/popup_link.html',
-% 'label' => 'apply',
-% 'action' => "${p}edit/cust_bill_pay.cgi?".
-% $cust_pay->paynum,
-% 'actionlabel' => 'Apply payment',
-% 'width' => 392,
-% #default# 'height' => 336,
-% ).
-% ')';
-% }
-% } elsif ( scalar(@cust_bill_pay) == 1
-% && scalar(@cust_pay_refund) == 0
-% && $cust_pay->unapplied == 0 ) {
-% #applied to one invoice, the usual situation
-% $desc = ' '. $cust_bill_pay[0]->applied_to_invoice;
-% } 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 = '<BR>';
-% foreach my $app ( sort { $a->_date <=> $b->_date }
-% ( @cust_bill_pay, @cust_pay_refund ) ) {
-% if ( $app->isa('FS::cust_bill_pay') ) {
-% $desc .= '&nbsp;&nbsp;'.
-% '$'. $app->amount.
-% ' '. $app->applied_to_invoice.
-% '<BR>';
-% #' on '. time2str("%D", $cust_bill_pay->_date).
-% } elsif ( $app->isa('FS::cust_pay_refund') ) {
-% $desc .= '&nbsp;&nbsp;'.
-% '$'. $app->amount.
-% ' refunded on '. time2str("%D", $app->_date).
-% '<BR>';
-% } else {
-% die "$app is not a FS::cust_bill_pay or FS::cust_pay_refund";
-% }
-% }
-% if ( $cust_pay->unapplied > 0 ) {
-% $desc .= '&nbsp;&nbsp;'.
-% '<B><FONT COLOR="#FF0000">$'.
-% $cust_pay->unapplied. ' unapplied</FONT></B>';
-% if ( $curuser->access_right('Apply payment') ) {
-% $desc = ' ('. include( '/elements/popup_link.html',
-% 'label' => 'apply',
-% 'action' => "${p}edit/cust_bill_pay.cgi?".
-% $cust_pay->paynum,
-% 'actionlabel' => 'Apply payment',
-% 'width' => 392,
-% #default# 'height' => 336,
-% ).
-% ')';
-% }
-% $desc .= '<BR>';
-% }
-% }
-%
-% my $view =
-% ' ('. include('/elements/popup_link.html',
-% 'label' => 'view receipt',
-% 'action' => "${p}view/cust_pay.html?link=popup;paynum=".
-% $cust_pay->paynum,
-% 'actionlabel' => 'Payment Receipt',
-% ).
-% ')';
-%
-% 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
-% && $curuser->access_right('Refund payment')
-% ) {
-% $refund = qq! (<A HREF="${p}edit/cust_refund.cgi?payby=$1;!.
-% qq!paynum=!. $cust_pay->paynum. '"'.
-% qq! TITLE="Send a refund for this payment to the payment gateway"!.
-% qq!>refund</A>)!;
-% }
-%
-% my $void = '';
-% if ( $cust_pay->closed !~ /^Y/i
-% && ( ( $cust_pay->payby eq 'CARD'
-% && $curuser->access_right('Credit card void')
-% )
-% || ( $cust_pay->payby eq 'CHEK'
-% && $curuser->access_right('Echeck void')
-% )
-% || ( $cust_pay->payby !~ /^(CARD|CHEK)$/
-% && $curuser->access_right('Regular void')
-% )
-% )
-% )
-% {
-% $void = qq! (<A HREF="javascript:areyousure('!.
-% qq!${p}misc/void-cust_pay.cgi?!. $cust_pay->paynum.
-% qq!', 'Are you sure you want to void this payment?')"!.
-% qq! TITLE="Void this payment from the database!.
-% ( $cust_pay->payby =~ /^(CARD|CHEK)$/
-% ? ' (do not send anything to the payment gateway)'
-% : ''
-% ). '"'.
-% qq!>void</A>)!;
-% }
-%
-% my $delete = '';
-% if ( $cust_pay->closed !~ /^Y/i
-% && $conf->exists('deletepayments')
-% && $curuser->access_right('Delete payment')
-% )
-% {
-% $delete = qq! (<A HREF="javascript:areyousure('!.
-% qq!${p}misc/delete-cust_pay.cgi?!. $cust_pay->paynum.
-% qq!', 'Are you sure you want to delete this payment?')"!.
-% qq! TITLE="Delete this payment from the database completely - not recommended"!.
-% qq!>delete</A>)!;
-% }
-%
-% my $unapply = '';
-% if ( $cust_pay->closed !~ /^Y/i
-% && scalar(@cust_bill_pay)
-% && $curuser->access_right('Unapply payment')
-% )
-% {
-% $unapply = qq! (<A HREF="javascript:areyousure('!.
-% qq!${p}misc/unapply-cust_pay.cgi?!. $cust_pay->paynum.
-% qq!', 'Are you sure you want to unapply this payment?')"!.
-% qq! TITLE="Keep this payment, but dissociate it from the invoices it is currently applied against"!.
-% qq!>unapply</A>)!;
-% }
-%
-% my $otaker = $cust_pay->otaker;
-% $otaker = '<i>auto billing</i>' if $otaker eq 'fs_daily';
-% $otaker = '<i>customer self-service</i>' if $otaker eq 'fs_selfservice';
-%
-% push @history, {
-% 'date' => $cust_pay->_date,
-% 'desc' => $pre. "Payment$post by $otaker $info$desc".
-% "$view$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->paymask
-% : $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)" : '';
-%
-% my $unvoid = '';
-% if ( $cust_pay_void->closed !~ /^Y/i
-% && $curuser->access_right('Unvoid')
-% )
-% {
-% $unvoid = qq! (<A HREF="javascript:areyousure('!.
-% qq!${p}misc/unvoid-cust_pay_void.cgi?!. $cust_pay_void->paynum.
-% qq!', 'Are you sure you want to unvoid this payment?')"!.
-% qq! TITLE="Unvoid this payment from the database!.
-% ( $cust_pay_void->payby =~ /^(CARD|CHEK)$/
-% ? ' (do not send anything to the payment gateway)'
-% : ''
-% ). '"'.
-% qq!>unvoid</A>)!;
-% }
-%
-% push @history, {
-% 'date' => $cust_pay_void->_date,
-% 'desc' => "<DEL>Payment $info</DEL> <I>voided ".
-% time2str("%D", $cust_pay_void->void_date).
-% " by ". $cust_pay_void->otaker. '</i>'. $unvoid,
-% '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 = '<B><FONT COLOR="#FF0000">Unapplied ';
-% $post = '</FONT></B>';
-% if ( $curuser->access_right('Apply credit') ) {
-% $apply = ' ('. include( '/elements/popup_link.html',
-% 'label' => 'apply',
-% 'action' => "${p}edit/cust_credit_bill.cgi?".
-% $cust_credit->crednum,
-% 'actionlabel' => 'Apply credit',
-% 'width' => 392,
-% #default# 'height' => 336,
-% ).
-% ')';
-% }
-% } elsif ( scalar(@cust_credit_bill) == 1
-% && scalar(@cust_credit_refund) == 0
-% && $cust_credit->credited == 0 ) {
-% #applied to one invoice, the usual situation
-% $desc = ' '. $cust_credit_bill[0]->applied_to_invoice;
-% } 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 = '<BR>';
-% foreach my $app ( sort { $a->_date <=> $b->_date }
-% ( @cust_credit_bill, @cust_credit_refund ) ) {
-% if ( $app->isa('FS::cust_credit_bill') ) {
-% $desc .= '&nbsp;&nbsp;'.
-% '$'. $app->amount.
-% ' '. $app->applied_to_invoice.
-% '<BR>';
-% #' on '. time2str("%D", $app->_date).
-% } elsif ( $app->isa('FS::cust_credit_refund') ) {
-% $desc .= '&nbsp;&nbsp;'.
-% '$'. $app->amount.
-% ' refunded on '. time2str("%D", $app->_date).
-% '<BR>';
-% } else {
-% die "$app is not a FS::cust_credit_bill or a FS::cust_credit_refund";
-% }
-% }
-% if ( $cust_credit->credited > 0 ) {
-% $desc .= '&nbsp;&nbsp;<B><FONT COLOR="#FF0000">$'.
-% $cust_credit->credited. ' unapplied</FONT></B>';
-% if ( $curuser->access_right('Apply credit') ) {
-% $desc = ' ('. include( '/elements/popup_link.html',
-% 'label' => 'apply',
-% 'action' => "${p}edit/cust_credit_bill.cgi?".
-% $cust_credit->crednum,
-% 'actionlabel' => 'Apply credit',
-% 'width' => 392,
-% #default# 'height' => 336,
-% ).
-% ')';
-% }
-% $desc .= '<BR>';
-% }
-% }
-%#
-% my $delete = '';
-% if ( $cust_credit->closed !~ /^Y/i
-%
-% #s'pose deleting a credit isn't bad like deleting a payment
-% # and this needs to be generally available until we have credit voiding..
-% #&& $conf->exists('deletecredits')
-%
-% && $curuser->access_right('Delete credit')
-% )
-% {
-% $delete = qq! (<A HREF="javascript:areyousure('!.
-% qq!${p}misc/delete-cust_credit.cgi?!. $cust_credit->crednum.
-% qq!', 'Are you sure you want to delete this credit?')">!.
-% qq!delete</A>)!;
-% }
-%
-% my $unapply = '';
-% if ( $cust_credit->closed !~ /^Y/i
-% && scalar(@cust_credit_bill)
-% && $curuser->access_right('Unapply credit')
-% )
-% {
-% $unapply = qq! (<A HREF="javascript:areyousure('!.
-% qq!${p}misc/unapply-cust_credit.cgi?!. $cust_credit->crednum.
-% qq!', 'Are you sure you want to unapply this credit?')">!.
-% qq!unapply</A>)!;
-% }
-%
-% push @history, {
-% 'date' => $cust_credit->_date,
-% 'desc' => $pre. "Credit$post by ". $cust_credit->otaker.
-% ( $cust_credit->reason
-% ? ' ('. $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->paymask
-% : $cust_refund->payinfo;
-%
-% $payby =~ s/^BILL$/Check #/ if $payinfo;
-% $payby =~ s/^CHEK$/Electronic check /;
-% $payby =~ s/^(CARD|COMP)$/$1 /;
-%
-% my $delete = '';
-% if ( $cust_refund->closed !~ /^Y/i
-% && $conf->exists('deleterefunds')
-% && $curuser->access_right('Delete refund')
-% )
-% {
-% $delete = qq! (<A HREF="javascript:areyousure('!.
-% qq!${p}misc/delete-cust_refund.cgi?!. $cust_refund->refundnum.
-% qq!', 'Are you sure you want to delete this refund?')"!.
-% qq! TITLE="Delete this refund from the database completely - not recommended"!.
-% qq!>delete</A>)!;
-% }
-%
-% push @history, {
-% 'date' => $cust_refund->_date,
-% 'desc' => "Refund ($payby$payinfo) by ". $cust_refund->otaker. "<BR>".
-% $delete,
-% 'refund' => $cust_refund->refund,
-% };
-%
-%}
-%
-%
-
<% include("/elements/table-grid.html") %>
% my $bgcolor1 = '#eeeeee';
@@ -681,4 +279,56 @@ my %status = (
'All' => '',
);
+#get payment history
+my @history = ();
+
+#invoices
+foreach my $cust_bill ($cust_main->cust_bill) {
+ push @history, {
+ 'date' => $cust_bill->_date,
+ 'desc' => include('payment_history/invoice.html', $cust_bill),
+ 'charge' => $cust_bill->charged,
+ };
+}
+
+#payments (some false laziness w/credits)
+foreach my $cust_pay ($cust_main->cust_pay) {
+ push @history, {
+ 'date' => $cust_pay->_date,
+ 'desc' => include('payment_history/payment.html', $cust_pay),
+ 'payment' => $cust_pay->paid,
+ #'target' => $target, #XXX
+ };
+}
+
+#voided payments
+foreach my $cust_pay_void ($cust_main->cust_pay_void) {
+ push @history, {
+ 'date' => $cust_pay_void->_date,
+ 'desc' => include('payment_history/voided_payment.html', $cust_pay_void),
+ 'void_payment' => $cust_pay_void->paid,
+ };
+
+}
+
+#credits (some false laziness w/payments)
+foreach my $cust_credit ($cust_main->cust_credit) {
+ push @history, {
+ 'date' => $cust_credit->_date,
+ 'desc' => include('payment_history/credit.html', $cust_credit),
+ 'credit' => $cust_credit->amount,
+ };
+
+}
+
+#refunds
+foreach my $cust_refund ($cust_main->cust_refund) {
+ push @history, {
+ 'date' => $cust_refund->_date,
+ 'desc' => include('payment_history/refund.html', $cust_refund),
+ 'refund' => $cust_refund->refund,
+ };
+
+}
+
</%init>
diff --git a/httemplate/view/cust_main/payment_history/credit.html b/httemplate/view/cust_main/payment_history/credit.html
new file mode 100644
index 0000000..bf76945
--- /dev/null
+++ b/httemplate/view/cust_main/payment_history/credit.html
@@ -0,0 +1,110 @@
+<% $pre %>Credit<% $post %>
+by <% $cust_credit->otaker %><% "$reason$desc$apply$delete$unapply" %>
+<%init>
+
+my( $cust_credit, %opt ) = @_;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+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 = '<B><FONT COLOR="#FF0000">Unapplied ';
+ $post = '</FONT></B>';
+ if ( $curuser->access_right('Apply credit') ) {
+ $apply = ' ('. include( '/elements/popup_link.html',
+ 'label' => 'apply',
+ 'action' => "${p}edit/cust_credit_bill.cgi?".
+ $cust_credit->crednum,
+ 'actionlabel' => 'Apply credit',
+ 'width' => 392,
+ #default# 'height' => 336,
+ ).
+ ')';
+ }
+} elsif ( scalar(@cust_credit_bill) == 1
+ && scalar(@cust_credit_refund) == 0
+ && $cust_credit->credited == 0 ) {
+ #applied to one invoice, the usual situation
+ $desc = ' '. $cust_credit_bill[0]->applied_to_invoice;
+} 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 = '<BR>';
+ foreach my $app ( sort { $a->_date <=> $b->_date }
+ ( @cust_credit_bill, @cust_credit_refund ) ) {
+ if ( $app->isa('FS::cust_credit_bill') ) {
+ $desc .= '&nbsp;&nbsp;'.
+ '$'. $app->amount.
+ ' '. $app->applied_to_invoice.
+ '<BR>';
+ #' on '. time2str("%D", $app->_date).
+ } elsif ( $app->isa('FS::cust_credit_refund') ) {
+ $desc .= '&nbsp;&nbsp;'.
+ '$'. $app->amount.
+ ' refunded on '. time2str("%D", $app->_date).
+ '<BR>';
+ } else {
+ die "$app is not a FS::cust_credit_bill or a FS::cust_credit_refund";
+ }
+ }
+ if ( $cust_credit->credited > 0 ) {
+ $desc .= '&nbsp;&nbsp;<B><FONT COLOR="#FF0000">$'.
+ $cust_credit->credited. ' unapplied</FONT></B>';
+ if ( $curuser->access_right('Apply credit') ) {
+ $desc = ' ('. include( '/elements/popup_link.html',
+ 'label' => 'apply',
+ 'action' => "${p}edit/cust_credit_bill.cgi?".
+ $cust_credit->crednum,
+ 'actionlabel' => 'Apply credit',
+ 'width' => 392,
+ #default# 'height' => 336,
+ ).
+ ')';
+ }
+ $desc .= '<BR>';
+ }
+}
+#
+my $delete = '';
+if ( $cust_credit->closed !~ /^Y/i
+
+ #s'pose deleting a credit isn't bad like deleting a payment
+ # and this needs to be generally available until we have credit voiding..
+ #&& $conf->exists('deletecredits')
+
+ && $curuser->access_right('Delete credit')
+ )
+{
+ $delete = qq! (<A HREF="javascript:areyousure('!.
+ qq!${p}misc/delete-cust_credit.cgi?!. $cust_credit->crednum.
+ qq!', 'Are you sure you want to delete this credit?')">!.
+ qq!delete</A>)!;
+}
+
+my $unapply = '';
+if ( $cust_credit->closed !~ /^Y/i
+ && scalar(@cust_credit_bill)
+ && $curuser->access_right('Unapply credit')
+ )
+{
+ $unapply = qq! (<A HREF="javascript:areyousure('!.
+ qq!${p}misc/unapply-cust_credit.cgi?!. $cust_credit->crednum.
+ qq!', 'Are you sure you want to unapply this credit?')">!.
+ qq!unapply</A>)!;
+}
+
+my $reason = $cust_credit->reason
+ ? ' ('. $cust_credit->reason. ')'
+ : '';
+
+</%init>
+
diff --git a/httemplate/view/cust_main/payment_history/invoice.html b/httemplate/view/cust_main/payment_history/invoice.html
new file mode 100644
index 0000000..39c6739
--- /dev/null
+++ b/httemplate/view/cust_main/payment_history/invoice.html
@@ -0,0 +1,34 @@
+<% $link %><% $pre %>Invoice #<% $invnum %>
+(Balance $ <% $cust_bill->owed %>)<% $post %><% $link ? '</A>' : '' %><% $events %>
+<%init>
+
+my( $cust_bill, %opt ) = @_;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my($pre, $post) = ('', '');
+if ( $cust_bill->owed > 0 ) {
+ $pre = '<B><FONT SIZE="+1" COLOR="#FF0000">Open ';
+ $post = '</FONT></B>';
+}
+
+my $invnum = $cust_bill->invnum;
+
+my $link = $curuser->access_right('View invoices')
+ ? qq!<A HREF="${p}view/cust_bill.cgi?$invnum">!
+ : '';
+
+my $events = '';
+#1.9
+if ( $cust_bill->num_cust_event
+ && ( $curuser->access_right('Billing event reports')
+ || $curuser->access_right('View customer billing events')
+ )
+ ) {
+ $events =
+ qq!<BR><FONT SIZE="-1"><A HREF="${p}search/cust_event.html?invnum=!.
+ $cust_bill->invnum. '">(&nbsp;View invoice events&nbsp;)</A></FONT>';
+}
+#
+
+</%init>
diff --git a/httemplate/view/cust_main/payment_history/payment.html b/httemplate/view/cust_main/payment_history/payment.html
new file mode 100644
index 0000000..96fca7f
--- /dev/null
+++ b/httemplate/view/cust_main/payment_history/payment.html
@@ -0,0 +1,180 @@
+<% $pre %>Payment<% $post %> by <% $otaker %>
+<% "$info$desc$view$apply$refund$void$delete$unapply" %>
+<%init>
+
+my( $cust_pay, %opt ) = @_;
+
+my $conf = new FS::Conf;
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my $payby = $cust_pay->payby;
+
+my $payinfo;
+if ( $payby eq 'CARD' ) {
+ $payinfo = $cust_pay->paymask;
+} elsif ( $payby eq 'CHEK' ) {
+ my( $account, $aba ) = split('@', $cust_pay->paymask );
+ $payinfo = "ABA $aba, Acct #$account";
+} 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 = '<B><FONT COLOR="#FF0000">Unapplied ';
+ $post = '</FONT></B>';
+ if ( $curuser->access_right('Apply payment') ) {
+ $apply = ' ('. include( '/elements/popup_link.html',
+ 'label' => 'apply',
+ 'action' => "${p}edit/cust_bill_pay.cgi?".
+ $cust_pay->paynum,
+ 'actionlabel' => 'Apply payment',
+ 'width' => 392,
+ #default# 'height' => 336,
+ ).
+ ')';
+ }
+} elsif ( scalar(@cust_bill_pay) == 1
+ && scalar(@cust_pay_refund) == 0
+ && $cust_pay->unapplied == 0 ) {
+ #applied to one invoice, the usual situation
+ $desc = ' '. $cust_bill_pay[0]->applied_to_invoice;
+} 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 = '<BR>';
+ foreach my $app ( sort { $a->_date <=> $b->_date }
+ ( @cust_bill_pay, @cust_pay_refund ) ) {
+ if ( $app->isa('FS::cust_bill_pay') ) {
+ $desc .= '&nbsp;&nbsp;'.
+ '$'. $app->amount.
+ ' '. $app->applied_to_invoice.
+ '<BR>';
+ #' on '. time2str("%D", $cust_bill_pay->_date).
+ } elsif ( $app->isa('FS::cust_pay_refund') ) {
+ $desc .= '&nbsp;&nbsp;'.
+ '$'. $app->amount.
+ ' refunded on '. time2str("%D", $app->_date).
+ '<BR>';
+ } else {
+ die "$app is not a FS::cust_bill_pay or FS::cust_pay_refund";
+ }
+ }
+ if ( $cust_pay->unapplied > 0 ) {
+ $desc .= '&nbsp;&nbsp;'.
+ '<B><FONT COLOR="#FF0000">$'.
+ $cust_pay->unapplied. ' unapplied</FONT></B>';
+ if ( $curuser->access_right('Apply payment') ) {
+ $desc = ' ('. include( '/elements/popup_link.html',
+ 'label' => 'apply',
+ 'action' => "${p}edit/cust_bill_pay.cgi?".
+ $cust_pay->paynum,
+ 'actionlabel' => 'Apply payment',
+ 'width' => 392,
+ #default# 'height' => 336,
+ ).
+ ')';
+ }
+ $desc .= '<BR>';
+ }
+}
+
+my $view =
+ ' ('. include('/elements/popup_link.html',
+ 'label' => 'view receipt',
+ 'action' => "${p}view/cust_pay.html?link=popup;paynum=".
+ $cust_pay->paynum,
+ 'actionlabel' => 'Payment Receipt',
+ ).
+ ')';
+
+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
+ && $curuser->access_right('Refund payment')
+) {
+ $refund = qq! (<A HREF="${p}edit/cust_refund.cgi?payby=$1;!.
+ qq!paynum=!. $cust_pay->paynum. '"'.
+ qq! TITLE="Send a refund for this payment to the payment gateway"!.
+ qq!>refund</A>)!;
+}
+
+my $void = '';
+if ( $cust_pay->closed !~ /^Y/i
+ && ( ( $cust_pay->payby eq 'CARD'
+ && $curuser->access_right('Credit card void')
+ )
+ || ( $cust_pay->payby eq 'CHEK'
+ && $curuser->access_right('Echeck void')
+ )
+ || ( $cust_pay->payby !~ /^(CARD|CHEK)$/
+ && $curuser->access_right('Regular void')
+ )
+ )
+ )
+{
+ $void = qq! (<A HREF="javascript:areyousure('!.
+ qq!${p}misc/void-cust_pay.cgi?!. $cust_pay->paynum.
+ qq!', 'Are you sure you want to void this payment?')"!.
+ qq! TITLE="Void this payment from the database!.
+ ( $cust_pay->payby =~ /^(CARD|CHEK)$/
+ ? ' (do not send anything to the payment gateway)'
+ : ''
+ ). '"'.
+ qq!>void</A>)!;
+}
+
+my $delete = '';
+if ( $cust_pay->closed !~ /^Y/i
+ && $conf->exists('deletepayments')
+ && $curuser->access_right('Delete payment')
+ )
+{
+ $delete = qq! (<A HREF="javascript:areyousure('!.
+ qq!${p}misc/delete-cust_pay.cgi?!. $cust_pay->paynum.
+ qq!', 'Are you sure you want to delete this payment?')"!.
+ qq! TITLE="Delete this payment from the database completely - not recommended"!.
+ qq!>delete</A>)!;
+}
+
+my $unapply = '';
+if ( $cust_pay->closed !~ /^Y/i
+ && scalar(@cust_bill_pay)
+ && $curuser->access_right('Unapply payment')
+ )
+{
+ $unapply = qq! (<A HREF="javascript:areyousure('!.
+ qq!${p}misc/unapply-cust_pay.cgi?!. $cust_pay->paynum.
+ qq!', 'Are you sure you want to unapply this payment?')"!.
+ qq! TITLE="Keep this payment, but dissociate it from the invoices it is currently applied against"!.
+ qq!>unapply</A>)!;
+}
+
+my $otaker = $cust_pay->otaker;
+$otaker = '<i>auto billing</i>' if $otaker eq 'fs_daily';
+$otaker = '<i>customer self-service</i>' if $otaker eq 'fs_selfservice';
+
+</%init>
diff --git a/httemplate/view/cust_main/payment_history/refund.html b/httemplate/view/cust_main/payment_history/refund.html
new file mode 100644
index 0000000..5f9bca3
--- /dev/null
+++ b/httemplate/view/cust_main/payment_history/refund.html
@@ -0,0 +1,50 @@
+<% $pre %>Refund<% $post %>
+(<% $payby. $payinfo %>)
+by <% $cust_refund->otaker %><% $view %><% $delete %>
+<%init>
+
+my( $cust_refund, %opt ) = @_;
+
+my $conf = new FS::Conf;
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my $payby = $cust_refund->payby;
+my $payinfo = $payby eq 'CARD'
+ ? $cust_refund->paymask
+ : $cust_refund->payinfo;
+
+$payby =~ s/^BILL$/Check #/ if $payinfo;
+$payby =~ s/^CHEK$/Electronic check /;
+$payby =~ s/^(CARD|COMP)$/$1 /;
+
+my($pre, $post) = ('', '');
+if ( $cust_refund->unapplied > 0 ) {
+ $pre = '<B><FONT COLOR="#FF0000">Unapplied ';
+ $post = '</FONT></B>';
+}
+
+my $view =
+ ' ('. include('/elements/popup_link.html',
+ 'label' => 'view receipt',
+ 'action' => "${p}view/cust_refund.html?link=popup;".
+ 'refundnum='. $cust_refund->refundnum,
+ 'actionlabel' => 'Payment Receipt',
+ ).
+ ')';
+
+
+my $delete = '';
+if ( $cust_refund->closed !~ /^Y/i
+ && $conf->exists('deleterefunds')
+ && $curuser->access_right('Delete refund')
+ )
+{
+ $delete = qq! (<A HREF="javascript:areyousure('!.
+ qq!${p}misc/delete-cust_refund.cgi?!. $cust_refund->refundnum.
+ qq!', 'Are you sure you want to delete this refund?')"!.
+ qq! TITLE="Delete this refund from the database completely - not recommended"!.
+ qq!>delete</A>)!;
+}
+
+</%init>
+
diff --git a/httemplate/view/cust_main/payment_history/voided_payment.html b/httemplate/view/cust_main/payment_history/voided_payment.html
new file mode 100644
index 0000000..9cbc47b
--- /dev/null
+++ b/httemplate/view/cust_main/payment_history/voided_payment.html
@@ -0,0 +1,37 @@
+<DEL>Payment <% $info %></DEL>
+<I>voided <% time2str("%D", $cust_pay_void->void_date) %>
+by <% $cust_pay_void->otaker %></I><% $unvoid %>
+<%init>
+
+my( $cust_pay_void, %opt ) = @_;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my $payby = $cust_pay_void->payby;
+my $payinfo = $payby eq 'CARD'
+ ? $cust_pay_void->paymask
+ : $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)" : '';
+
+my $unvoid = '';
+if ( $cust_pay_void->closed !~ /^Y/i
+ && $curuser->access_right('Unvoid')
+ )
+{
+ $unvoid = qq! (<A HREF="javascript:areyousure('!.
+ qq!${p}misc/unvoid-cust_pay_void.cgi?!. $cust_pay_void->paynum.
+ qq!', 'Are you sure you want to unvoid this payment?')"!.
+ qq! TITLE="Unvoid this payment from the database!.
+ ( $cust_pay_void->payby =~ /^(CARD|CHEK)$/
+ ? ' (do not send anything to the payment gateway)'
+ : ''
+ ). '"'.
+ qq!>unvoid</A>)!;
+}
+
+</%init>
diff --git a/httemplate/view/cust_refund.html b/httemplate/view/cust_refund.html
new file mode 100644
index 0000000..40f6ab6
--- /dev/null
+++ b/httemplate/view/cust_refund.html
@@ -0,0 +1,141 @@
+% if ( $link eq 'popup' ) {
+
+ <% include('/elements/header-popup.html', "Refund Receipt" ) %>
+
+ <CENTER><A HREF="javascript:self.parent.location = '<% $pr_link %>'">Print</A></CENTER><BR>
+
+% } elsif ( $link eq 'print' ) {
+
+ <% include('/elements/header-popup.html', "Refund Receipt" ) %>
+
+% #it would be nice if the menubar could be hidden for print, but better to
+% # have it available than not, otherwise the user winds up at a dead end
+ <% menubar(
+ "View this customer (#$custnum)" => "${p}view/cust_main.cgi?$custnum",
+ )
+ %>
+ <BR><BR>
+
+% } else {
+
+ <% include('/elements/header.html', "Refund Receipt", menubar(
+ "View this customer (#$custnum)" => "${p}view/cust_main.cgi?$custnum",
+ 'Print receipt' => $pr_link,
+ ))
+ %>
+
+% }
+
+% unless ($link eq 'popup' ) {
+ <% include('/elements/small_custview.html',
+ $custnum,
+ scalar($conf->config('countrydefault')),
+ 1, #no balance
+ )
+ %>
+ <BR><BR>
+% }
+
+<% ntable("#cccccc", 2) %>
+
+<TR>
+ <TD ALIGN="right">Refund#</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_refund->refundnum %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Date</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% time2str"%a&nbsp;%b&nbsp;%o,&nbsp;%Y&nbsp;%r", $cust_refund->_date %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Amount</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $money_char. $cust_refund->refund %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Reason</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_refund->reason %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Refund method</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_refund->payby_name %> #<% $cust_refund->paymask %></B></TD>
+</TR>
+
+% if ( $cust_refund->payby =~ /^(CARD|CHEK|LECB)$/ && $cust_refund->paybatch ) {
+
+ <TR>
+ <TD ALIGN="right">Processor</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_refund->processor %></B></TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Authorization#</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_refund->authorization %></B></TD>
+ </TR>
+
+% if ( $cust_refund->order_number ) {
+ <TR>
+ <TD ALIGN="right">Order#</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_refund->order_number %></B></TD>
+ </TR>
+% }
+
+% }
+
+</TABLE>
+
+% if ( $link eq 'print' ) {
+
+ <SCRIPT TYPE="text/javascript">
+ window.print();
+ </SCRIPT>
+
+% }
+
+% if ( $link =~ /^(popup|print)$/ ) {
+ </BODY>
+ </HTML>
+% } else {
+ <% include('/elements/footer.html') %>
+% }
+
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('View invoices') #remove this in 1.9 EVENTUALLY
+ || $curuser->access_right('View customer payments');
+ #'View customer refunds' ???
+
+
+$cgi->param('refundnum') =~ /^(\d+)$/ or die "no refundnum";
+my $refundnum = $1;
+
+my $link = '';
+if ( $cgi->param('link') =~ /^(\w+)$/ ) {
+ $link = $1;
+}
+
+my $cust_refund = qsearchs({
+ 'select' => 'cust_refund.*',
+ 'table' => 'cust_refund',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'refundnum' => $refundnum },
+ 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+});
+die "Refund #$refundnum not found!" unless $cust_refund;
+
+my $pr_link = "${p}view/cust_refund.html?link=print;refundnum=$refundnum";
+
+my $custnum = $cust_refund->custnum;
+
+my $conf = new FS::Conf;
+
+my $money_char = $conf->config('money_char') || '$';
+
+tie my %payby, 'Tie::IxHash', FS::payby->payby2longname;
+
+</%init>