From db81b071af31d803a7707376d06f6b1c6c674bd9 Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Wed, 30 Jan 2013 12:07:51 -0800 Subject: [PATCH] record and show batch payment status info, #21117 --- FS/FS/Schema.pm | 2 + FS/FS/cust_pay_batch.pm | 8 +- FS/FS/pay_batch.pm | 9 +- FS/FS/pay_batch/paymentech.pm | 24 +++-- httemplate/search/cust_pay_batch.cgi | 91 +++++++++---------- .../search/elements/cust_pay_or_refund.html | 21 ++++- 6 files changed, 93 insertions(+), 62 deletions(-) diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 491dd732c..9c22d9e77 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -1375,6 +1375,7 @@ sub tables_hashref { 'depositor', 'varchar', 'NULL', $char_d, '', '', 'account', 'varchar', 'NULL', 20, '', '', 'teller', 'varchar', 'NULL', 20, '', '', + 'batchnum', 'int', 'NULL', '', '', '', #pay_batch foreign key ], 'primary_key' => 'paynum', #i guess not now, with cust_pay_pending, if we actually make it here, we _do_ want to record it# 'unique' => [ [ 'payunique' ] ], @@ -1486,6 +1487,7 @@ sub tables_hashref { 'payname', 'varchar', 'NULL', $char_d, '', '', 'amount', @money_type, '', '', 'status', 'varchar', 'NULL', $char_d, '', '', + 'error_message', 'varchar', 'NULL', $char_d, '', '', ], 'primary_key' => 'paybatchnum', 'unique' => [], diff --git a/FS/FS/cust_pay_batch.pm b/FS/FS/cust_pay_batch.pm index f5e6a4bf1..9c5c2d811 100644 --- a/FS/FS/cust_pay_batch.pm +++ b/FS/FS/cust_pay_batch.pm @@ -9,7 +9,7 @@ use FS::payinfo_Mixin; use FS::cust_main; use FS::cust_bill; -@ISA = qw( FS::payinfo_Mixin FS::Record ); +@ISA = qw( FS::payinfo_Mixin FS::cust_main_Mixin FS::Record ); # 1 is mostly method/subroutine entry and options # 2 traces progress of some operations @@ -80,7 +80,9 @@ following fields are currently supported: =item country -=item status +=item status - 'Approved' or 'Declined' + +=item error_message - the error returned by the gateway if any =back @@ -291,6 +293,7 @@ sub approve { 'paid' => $new->paid, '_date' => $new->_date, 'usernum' => $new->usernum, + 'batchnum' => $new->batchnum, } ); $error = $cust_pay->insert; if ( $error ) { @@ -343,6 +346,7 @@ sub decline { } } # !$old->status $new->status('Declined'); + $new->error_message($reason); my $error = $new->replace($old); if ( $error ) { return "error updating status of paybatchnum $paybatchnum: $error\n"; diff --git a/FS/FS/pay_batch.pm b/FS/FS/pay_batch.pm index bb92bdf2f..e0a1c4415 100644 --- a/FS/FS/pay_batch.pm +++ b/FS/FS/pay_batch.pm @@ -371,12 +371,12 @@ sub import_results { foreach ('paid', '_date', 'payinfo') { $new_cust_pay_batch->$_($hash{$_}) if $hash{$_}; } - $error = $new_cust_pay_batch->approve($hash{'paybatch'} || $self->batchnum); + $error = $new_cust_pay_batch->approve($hash{'paybatch'}); $total += $hash{'paid'}; } elsif ( &{$declined_condition}(\%hash) ) { - $error = $new_cust_pay_batch->decline; + $error = $new_cust_pay_batch->decline($hash{'error_message'});; } @@ -561,7 +561,6 @@ sub manual_approve { my $self = shift; my $date = time; my %opt = @_; - my $paybatch = $opt{'paybatch'} || $self->batchnum; my $usernum = $opt{'usernum'} || die "manual approval requires a usernum"; my $conf = FS::Conf->new; return 'manual batch approval disabled' @@ -591,7 +590,9 @@ sub manual_approve { '_date' => $date, 'usernum' => $usernum, }; - my $error = $new_cust_pay_batch->approve($paybatch); + my $error = $new_cust_pay_batch->approve(); + # there are no approval options here (authorization, order_number, etc.) + # because the transaction wasn't really approved if ( $error ) { $dbh->rollback; return 'paybatchnum '.$cust_pay_batch->paybatchnum.": $error"; diff --git a/FS/FS/pay_batch/paymentech.pm b/FS/FS/pay_batch/paymentech.pm index 7c13ebfe0..970550378 100644 --- a/FS/FS/pay_batch/paymentech.pm +++ b/FS/FS/pay_batch/paymentech.pm @@ -23,7 +23,10 @@ my $gateway; '_date', 'approvalStatus', 'order_number', - 'authorization', + 'auth', + 'procStatus', + 'procStatusMessage', + 'respCodeMessage', ], xmlkeys => [ 'orderID', @@ -31,6 +34,9 @@ my $gateway; 'approvalStatus', 'txRefNum', 'authorizationCode', + 'procStatus', + 'procStatusMessage', + 'respCodeMessage', ], 'hook' => sub { if ( !$gateway ) { @@ -38,7 +44,7 @@ my $gateway; # as the batch config, if there is one. If not, leave # gateway out entirely. my $merchant = (FS::Conf->new->config('batchconfig-paymentech'))[2]; - my $g = qsearchs({ + $gateway = qsearchs({ 'table' => 'payment_gateway', 'addl_from' => ' JOIN payment_gateway_option USING (gatewaynum) ', 'hashref' => { disabled => '', @@ -46,18 +52,24 @@ my $gateway; optionvalue => $merchant, }, }); - $gateway = ($g ? $g->gatewaynum . '-' : '') . 'PaymenTech'; } my ($hash, $oldhash) = @_; + $hash->{'gatewaynum'} = $gateway->gatewaynum if $gateway; + $hash->{'processor'} = 'PaymenTech'; my ($mon, $day, $year, $hour, $min, $sec) = $hash->{'_date'} =~ /^(..)(..)(....)(..)(..)(..)$/; $hash->{'_date'} = timelocal($sec, $min, $hour, $day, $mon-1, $year); $hash->{'paid'} = $oldhash->{'amount'}; - $hash->{'paybatch'} = join(':', - $gateway, - $hash->{'authorization'}, + $hash->{'paybatch'} = join(':', + $gateway->gatewaynum . '-PaymenTech', + $hash->{'auth'}, $hash->{'order_number'}, ); + if ( $hash->{'procStatus'} == 0 ) { + $hash->{'error_message'} = $hash->{'respCodeMessage'}; + } else { + $hash->{'error_message'} = $hash->{'procStatusMessage'}; + } }, 'approved' => sub { my $hash = shift; $hash->{'approvalStatus'} diff --git a/httemplate/search/cust_pay_batch.cgi b/httemplate/search/cust_pay_batch.cgi index f38264410..4d31a7582 100755 --- a/httemplate/search/cust_pay_batch.cgi +++ b/httemplate/search/cust_pay_batch.cgi @@ -7,53 +7,40 @@ 'disable_download' => 1, 'header' => [ '#', 'Inv #', - 'Customer', + 'Cust #', 'Customer', 'Card Name', 'Card', 'Exp', 'Amount', 'Status', + '', # error_message ], - 'fields' => [ sub { - shift->[0]; - }, - sub { - shift->[1]; - }, - sub { - shift->[2]; - }, - sub { - my $cpb = shift; - $cpb->[3] . ', ' . $cpb->[4]; - }, - sub { - shift->[5]; - }, - sub { - my $cardnum = shift->[6]; - 'x'x(length($cardnum)-4). substr($cardnum,(length($cardnum)-4)); - }, - sub { - shift->[7] =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/; - my( $mon, $year ) = ( $2, $1 ); - $mon = "0$mon" if length($mon) == 1; - "$mon/$year"; - }, - sub { - shift->[8]; - }, - sub { - shift->[9]; - }, - ], - 'align' => 'lllllllrl', - 'links' => [ ['', sub{'#';}], - ["${p}view/cust_bill.cgi?", sub{shift->[1];},], - ["${p}view/cust_main.cgi?", sub{shift->[2];},], - ["${p}view/cust_main.cgi?", sub{shift->[2];},], + 'fields' => [ 'paybatchnum', + 'invnum', + 'custnum', + sub { $_[0]->cust_main->name_short }, + 'payname', + 'mask_payinfo', + sub { + return('') if $_[0]->payby ne 'CARD'; + $_[0]->get('exp') =~ /^\d\d(\d\d)-(\d\d)/; + sprintf('%02d/%02d',$1,$2); + }, + sub { + sprintf('%.02f', $_[0]->amount) + }, + 'status', + 'error_message', + ], + 'align' => 'rrrlllcrll', + 'links' => [ '', + ["${p}view/cust_bill.cgi?", 'invnum'], + (["${p}view/cust_main.cgi?", 'custnum']) x 2, ], + 'link_onclicks' => [ ('') x 8, + $sub_receipt + ], ) %> <%init> @@ -120,13 +107,25 @@ $count_query = 'SELECT COUNT(*) FROM cust_pay_batch AS cpb ' . 'LEFT JOIN pay_batch USING ( batchnum )' . $search; -#grr -$sql_query = "SELECT paybatchnum,invnum,custnum,cpb.last,cpb.first," . - "cpb.payname,cpb.payinfo,cpb.exp,amount,cpb.status " . - "FROM cust_pay_batch AS cpb " . - 'LEFT JOIN cust_main USING ( custnum ) ' . - 'LEFT JOIN pay_batch USING ( batchnum ) ' . - "$search ORDER BY $orderby"; +$sql_query = { + 'table' => 'cust_pay_batch', + 'select' => 'cust_pay_batch.*, cust_main.*, cust_pay.paynum', + 'hashref' => {}, + 'addl_from' => 'LEFT JOIN pay_batch USING ( batchnum ) '. + 'LEFT JOIN cust_main USING ( custnum ) '. + + 'LEFT JOIN cust_pay USING ( batchnum, custnum ) ', + 'extra_sql' => $search, + 'order_by' => "ORDER BY $orderby", +}; + +my $sub_receipt = sub { + my $paynum = shift->paynum or return ''; + include('/elements/popup_link_onclick.html', + 'action' => $p.'view/cust_pay.html?link=popup;paynum='.$paynum, + 'actionlabel' => emt('Payment Receipt'), + ); +}; my $html_init = ''; if ( $pay_batch ) { diff --git a/httemplate/search/elements/cust_pay_or_refund.html b/httemplate/search/elements/cust_pay_or_refund.html index da887a3d5..a29b4eac5 100755 --- a/httemplate/search/elements/cust_pay_or_refund.html +++ b/httemplate/search/elements/cust_pay_or_refund.html @@ -51,6 +51,7 @@ Examples: 'sort_fields' => \@sort_fields, 'align' => $align, 'links' => \@links, + 'link_onclicks' => \@link_onclicks, 'color' => \@color, 'style' => \@style, &> @@ -134,11 +135,12 @@ if ( $cgi->param('tax_names') ) { } } -my @header = (); -my @fields = (); -my @sort_fields = (); +my @header; +my @fields; +my @sort_fields; my $align = ''; -my @links = (); +my @links; +my @link_onclicks; if ( $opt{'pre_header'} ) { push @header, @{ $opt{'pre_header'} }; $align .= 'c' x scalar(@{ $opt{'pre_header'} }); @@ -147,6 +149,16 @@ if ( $opt{'pre_header'} ) { push @sort_fields, @{ $opt{'pre_fields'} }; } +my $sub_receipt = sub { + my $obj = shift; + my $objnum = $obj->primary_key . '=' . $obj->get($obj->primary_key); + + include('/elements/popup_link_onclick.html', + 'action' => $p.'view/cust_pay.html?link=popup;'.$objnum, + 'actionlabel' => emt('Payment Receipt'), + ); +}; + push @header, "\u$name_singular", 'Amount', ; @@ -155,6 +167,7 @@ push @links, '', ''; push @fields, 'payby_payinfo_pretty', sub { sprintf('$%.2f', shift->$amount_field() ) }, ; +push @link_onclicks, $sub_receipt, '', push @sort_fields, '', $amount_field; if ( $unapplied ) { -- 2.20.1