summaryrefslogtreecommitdiff
path: root/httemplate
diff options
context:
space:
mode:
authorivan <ivan>2009-02-16 23:56:39 +0000
committerivan <ivan>2009-02-16 23:56:39 +0000
commit7621140d9f8945c54523c05bcac8e79693a16a52 (patch)
tree0131f25dae2e82f082fbf12ece05abfd85a324f4 /httemplate
parent46b9f652743ec853019a44772bba24cd5dbd681a (diff)
add reporting on (and resolution of) stuck pending transactions, RT#4837 (RT#3572)
Diffstat (limited to 'httemplate')
-rw-r--r--httemplate/edit/cust_pay_pending.html154
-rw-r--r--httemplate/edit/process/cust_pay_pending.html68
-rw-r--r--httemplate/elements/menu.html2
-rwxr-xr-xhttemplate/search/cust_pay_pending.html47
-rwxr-xr-xhttemplate/search/elements/cust_pay_or_refund.html78
-rw-r--r--httemplate/view/cust_main/payment_history.html16
6 files changed, 345 insertions, 20 deletions
diff --git a/httemplate/edit/cust_pay_pending.html b/httemplate/edit/cust_pay_pending.html
new file mode 100644
index 000000000..0916a1c0c
--- /dev/null
+++ b/httemplate/edit/cust_pay_pending.html
@@ -0,0 +1,154 @@
+<% include('/elements/header-popup.html', $title ) %>
+
+% if ( $action eq 'delete' ) {
+
+ <CENTER><FONT SIZE="+1"><B>Are you sure you want to delete this pending payment?</B></FONT></CENTER>
+
+% } elsif ( $action eq 'complete' ) {
+
+ <CENTER><FONT SIZE="+1"><B>No response was received from <% $cust_pay_pending->processor || 'the payment gateway' %> for this transaction. Check <% $cust_pay_pending->processor || 'the payment gateway' %>'s reporting and determine if this transaction completed successfully.</B></FONT></CENTER>
+
+% }
+
+<BR>
+
+%#false laziness w/view/cust_pay.html
+<% include('/elements/small_custview.html',
+ $cust_pay_pending->custnum,
+ scalar($conf->config('countrydefault')),
+ 1, #no balance
+ )
+%>
+<BR>
+
+<% ntable("#cccccc", 2) %>
+
+<TR>
+ <TD ALIGN="right">Pending payment#</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_pay_pending->paypendingnum %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Date</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% time2str"%a&nbsp;%b&nbsp;%o,&nbsp;%Y&nbsp;%r", $cust_pay_pending->_date %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Amount</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $money_char. $cust_pay_pending->paid %></B></TD>
+</TR>
+
+<TR>
+ <TD ALIGN="right">Payment method</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_pay_pending->payby_name %> #<% $cust_pay_pending->paymask %></B></TD>
+</TR>
+
+% #if ( $cust_pay_pending->payby =~ /^(CARD|CHEK|LECB)$/ && $cust_pay_pending->paybatch ) {
+
+ <TR>
+ <TD ALIGN="right">Processor</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_pay_pending->processor %></B></TD>
+ </TR>
+
+ <TR>
+ <TD ALIGN="right">Authorization#</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_pay_pending->authorization %></B></TD>
+ </TR>
+
+% if ( $cust_pay_pending->order_number ) {
+ <TR>
+ <TD ALIGN="right">Order#</TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $cust_pay_pending->order_number %></B></TD>
+ </TR>
+% }
+
+% #}
+
+</TABLE>
+
+<BR>
+
+<FORM NAME = "pendingform"
+ METHOD = "POST"
+ ACTION = "process/cust_pay_pending.html"
+>
+
+<INPUT TYPE="hidden" NAME="paypendingnum" VALUE="<% $paypendingnum %>">
+
+<% itable() %>
+
+% if ( $action eq 'delete' ) {
+
+ <INPUT TYPE="hidden" NAME="action" VALUE="<% $action %>">
+
+ <TR>
+ <TD ALIGN="center">
+ <BUTTON TYPE="button" onClick="document.pendingform.submit();"><!--IMG SRC="<%$p%>images/tick.png" ALT=""-->Yes, delete payment</BUTTON>
+ </TD>
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+ <TD ALIGN="center">
+ <BUTTON TYPE="button" onClick="parent.cClick();"><!--IMG SRC="<%$p%>images/cross.png" ALT=""-->No, cancel deletion</BUTTON>
+ </TD>
+ </TR>
+
+% } elsif ( $action eq 'complete' ) {
+
+ <INPUT TYPE="hidden" NAME="action" VALUE="">
+
+ <TR>
+ <TD ALIGN="center">
+ <BUTTON TYPE="button" onClick="document.pendingform.action.value = 'insert_cust_pay'; document.pendingform.submit();"><!--IMG SRC="<%$p%>images/tick.png" ALT=""-->Yes, transaction completed sucessfully.</BUTTON>
+ </TD>
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+ <TD ALIGN="center">
+ <BUTTON TYPE="button" onClick="document.pendingform.action.value = 'decline'; document.pendingform.submit();"><!--IMG SRC="<%$p%>images/cross.png" ALT=""-->No, transaction was declined</BUTTON>
+ </TD>
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+ <TD ALIGN="center">
+ <BUTTON TYPE="button" onClick="document.pendingform.action.value = 'delete'; document.pendingform.submit();"><!--IMG SRC="<%$p%>images/cross.png" ALT=""-->No, transaction was not received</BUTTON>
+ </TD>
+ </TR>
+
+ <TR><TD COLSPAN=5></TD></TR>
+
+ <TR>
+ <TD COLSPAN=5 ALIGN="center">
+ <BUTTON TYPE="button" onClick="parent.cClick();"><!--IMG SRC="<%$p%>images/cross.png" ALT=""-->Cancel payment completion; transaction status not yet known</BUTTON>
+ </TD>
+ </TR>
+
+% }
+
+</TABLE>
+
+</FORM>
+</BODY>
+</HTML>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Edit customer pending payments');
+
+$cgi->param('action') =~ /^(\w+)$/ or die 'illegal action';
+my $action = $1;
+my $title = ucfirst($action). ' pending payment';
+
+$cgi->param('paypendingnum') =~ /^(\d+)$/ or die 'illegal paypendingnum';
+my $paypendingnum = $1;
+my $cust_pay_pending =
+ qsearchs({
+ 'select' => 'cust_pay_pending.*',
+ 'table' => 'cust_pay_pending',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'paypendingnum' => $paypendingnum },
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql,
+ })
+ or die 'unknown paypendingnum';
+
+my $conf = new FS::Conf;
+
+my $money_char = $conf->config('money_char') || '$';
+
+</%init>
diff --git a/httemplate/edit/process/cust_pay_pending.html b/httemplate/edit/process/cust_pay_pending.html
new file mode 100644
index 000000000..1bad6cffe
--- /dev/null
+++ b/httemplate/edit/process/cust_pay_pending.html
@@ -0,0 +1,68 @@
+<% include('/elements/header-popup.html', $title ) %>
+% if ( $error ) {
+ <FONT SIZE="+1" COLOR="#ff0000">Error: <% $error |h %></FONT>
+% } else {
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+% }
+</BODY>
+</HTML>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Edit customer pending payments');
+
+$cgi->param('action') =~ /^(\w+)$/ or die 'illegal action';
+my $action = $1;
+
+$cgi->param('paypendingnum') =~ /^(\d+)$/ or die 'illegal paypendingnum';
+my $paypendingnum = $1;
+my $cust_pay_pending =
+ qsearchs({
+ 'select' => 'cust_pay_pending.*',
+ 'table' => 'cust_pay_pending',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'paypendingnum' => $paypendingnum },
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql,
+ })
+ or die 'unknown paypendingnum';
+
+my $error;
+my $title;
+if ( $action eq 'delete' ) {
+
+ $error = $cust_pay_pending->delete;
+ if ( $error ) {
+ $title = 'Error deleting pending payment';
+ } else {
+ $title = 'Pending payment deletion sucessful';
+ }
+
+} elsif ( $action eq 'insert_cust_pay' ) {
+
+ $error = $cust_pay_pending->insert_cust_pay;
+ if ( $error ) {
+ $title = 'Error completing pending payment';
+ } else {
+ $title = 'Pending payment completed';
+ }
+
+} elsif ( $action eq 'decline' ) {
+
+ $error = $cust_pay_pending->decline;
+ if ( $error ) {
+ $title = 'Error declining pending payment';
+ } else {
+ $title = 'Pending payment completed (decline)';
+ }
+
+} else {
+
+ die "unknown action $action";
+
+}
+
+</%init>
diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html
index ae5ff5880..627f9c857 100644
--- a/httemplate/elements/menu.html
+++ b/httemplate/elements/menu.html
@@ -191,6 +191,8 @@ tie my %report_financial, 'Tie::IxHash',
'Credit Report' => [ $fsurl.'search/report_cust_credit.html', 'Credit report (by employee and/or date range)' ],
'Payment Report' => [ $fsurl.'search/report_cust_pay.html', 'Payment report (by type and/or date range)' ],
;
+$report_financial{'Pending Payment Report'} = [ $fsurl.'search/cust_pay_pending.html?magic=_date;statusNOT=done', 'Pending real-time payments' ]
+ if $curuser->access_right('View customer pending payments');
$report_financial{'Payment Batch Report'} = [ $fsurl.'search/pay_batch.html', 'Payment batches (by status and/or date range)' ]
if $conf->exists('batch-enable') || $conf->config('batch-enable_payby');
$report_financial{'A/R Aging'} = [ $fsurl.'search/report_receivables.html', 'Accounts Receivable Aging report' ];
diff --git a/httemplate/search/cust_pay_pending.html b/httemplate/search/cust_pay_pending.html
new file mode 100755
index 000000000..f0a3a0150
--- /dev/null
+++ b/httemplate/search/cust_pay_pending.html
@@ -0,0 +1,47 @@
+<% include( 'elements/cust_pay_or_refund.html',
+ 'thing' => 'pay_pending',
+ 'amount_field' => 'paid',
+ 'name_singular' => 'pending payment',
+ 'name_verb' => 'pending',
+ 'disable_link' => 1,
+ 'disable_by' => 1, #add otaker to cust_pay_pending?
+ 'html_init' => include('/elements/init_overlib.html'),
+ 'addl_header' => [ 'Time', 'Payment Status', ],
+ 'addl_fields' => [ sub { time2str('%r', shift->_date ) },
+ $status_sub,
+ ],
+ )
+%>
+<%init>
+
+my %statusaction = (
+ 'new' => 'delete',
+ 'pending' => 'complete',
+ #'authorized' => '',
+ #'captured' => '',
+ #'declined' => '',
+ #wouldn't need to take action on a done state#'done'
+);
+
+my $edit_pending =
+ $FS::CurrentUser::CurrentUser->access_right('Edit customer pending payments');
+
+my $status_sub = sub {
+ my $pending = shift;
+ my $return = $pending->status;
+ my $action = $statusaction{$pending->status};
+ return $return unless $action && $edit_pending;
+ my $link = include('/elements/popup_link.html',
+ 'action' => $p. 'edit/cust_pay_pending.html'.
+ '?paypendingnum='. $pending->paypendingnum.
+ ";action=$action",
+ 'label' => $action,
+ 'color' => '#ff0000',
+ 'width' => 655,
+ 'height' => ( $action eq 'delete' ? 480 : 575 ),
+ 'actionlabel' => ucfirst($action). ' pending payment',
+ );
+ $return. qq! <FONT SIZE="-1">($link)</FONT>!;
+};
+
+</%init>
diff --git a/httemplate/search/elements/cust_pay_or_refund.html b/httemplate/search/elements/cust_pay_or_refund.html
index 9457ae2eb..9e2eceb3a 100755
--- a/httemplate/search/elements/cust_pay_or_refund.html
+++ b/httemplate/search/elements/cust_pay_or_refund.html
@@ -16,6 +16,18 @@ Examples:
'name_verb' => 'refunded',
)
+ include( 'elements/cust_pay_or_refund.html',
+ 'thing' => 'pay_pending',
+ 'amount_field' => 'paid',
+ 'name_singular' => 'pending payment',
+ 'name_verb' => 'pending',
+ 'disable_link' => 1,
+ 'disable_by' => 1,
+ 'html_init' => '',
+ 'addl_header' => [],
+ 'addl_fields' => [],
+ )
+
</%doc>
<% include( 'search.html',
'title' => $title,
@@ -26,27 +38,25 @@ Examples:
'header' => [ "\u$name_singular",
'Amount',
'Date',
- 'By',
+ @header,
FS::UI::Web::cust_header(),
],
'fields' => [
'payby_payinfo_pretty',
sub { sprintf('$%.2f', shift->$amount_field() ) },
sub { time2str('%b %d %Y', shift->_date ) },
- sub { my $o = shift->otaker;
- $o = 'auto billing' if $o eq 'fs_daily';
- $o = 'customer self-service' if $o eq 'fs_selfservice';
- $o;
- },
+ @fields,
\&FS::UI::Web::cust_fields,
],
#'align' => 'lrrrll',
- 'align' => 'rrrc'.FS::UI::Web::cust_aligns(),
+ 'align' => 'rrr'.
+ join('', map 'c', @fields ).
+ FS::UI::Web::cust_aligns(),
'links' => [
$link,
$link,
$link,
- '',
+ ( map '', @fields ),
( map { $_ ne 'Cust. Status' ? $cust_link : '' }
FS::UI::Web::cust_header()
),
@@ -55,14 +65,14 @@ Examples:
'',
'',
'',
- '',
+ ( map '', @fields ),
FS::UI::Web::cust_colors(),
],
'style' => [
'',
'',
'',
- '',
+ ( map '', @fields ),
FS::UI::Web::cust_styles(),
],
)
@@ -71,14 +81,35 @@ Examples:
my %opt = @_;
+my $curuser = $FS::CurrentUser::CurrentUser;
+
die "access denied"
- unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+ unless $curuser->access_right('Financial reports');
my $thing = $opt{'thing'};
my $amount_field = $opt{'amount_field'};
my $name_singular = $opt{'name_singular'};
my $title = "\u$name_singular Search Results";
+
+my @header = ();
+my @fields = ();
+unless ( $opt{'disable_by'} ) {
+ push @header, 'By';
+ push @fields, sub {
+ sub { my $o = shift->otaker;
+ $o = 'auto billing' if $o eq 'fs_daily';
+ $o = 'customer self-service' if $o eq 'fs_selfservice';
+ $o;
+ },
+ };
+}
+
+push @header, @{ $opt{'addl_header'} }
+ if $opt{'addl_header'};
+push @fields, @{ $opt{'addl_fields'} }
+ if $opt{'addl_fields'};
+
my( $count_query, $sql_query );
if ( $cgi->param('magic') ) {
@@ -93,7 +124,11 @@ if ( $cgi->param('magic') ) {
die "unknown agentnum $1" unless $agent;
$title = $agent->agent. " $title";
}
-
+
+ if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
+ push @search, "custnum = $1";
+ }
+
if ( $cgi->param('payby') ) {
$cgi->param('payby') =~
/^(CARD|CHEK|BILL|PREP|CASH|WEST|MCRD)(-(VisaMC|Amex|Discover|Maestro))?$/
@@ -175,6 +210,11 @@ if ( $cgi->param('magic') ) {
push @search, "cust_$thing.payinfo = '$1'";
}
+ #for cust_pay_pending... statusNOT=done
+ if ( $cgi->param('statusNOT') =~ /^(\w+)$/ ) {
+ push @search, "status != '$1'";
+ }
+
my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
push @search, "_date >= $beginning ",
"_date <= $ending";
@@ -197,7 +237,7 @@ if ( $cgi->param('magic') ) {
}
#here is the agent virtualization
- push @search, $FS::CurrentUser::CurrentUser->agentnums_sql;
+ push @search, $curuser->agentnums_sql;
my $search = ' WHERE '. join(' AND ', @search);
@@ -229,21 +269,25 @@ if ( $cgi->param('magic') ) {
$count_query = "SELECT COUNT(*), SUM($amount_field) FROM cust_$thing".
" WHERE payinfo = '$payinfo' AND payby = '$payby'".
- " AND ". $FS::CurrentUser::CurrentUser->agentnums_sql;
+ " AND ". $curuser->agentnums_sql;
$sql_query = {
'table' => "cust_$thing",
'hashref' => { 'payinfo' => $payinfo,
'payby' => $payby },
- 'extra_sql' => $FS::CurrentUser::CurrentUser->agentnums_sql.
+ 'extra_sql' => $curuser->agentnums_sql.
" ORDER BY _date",
};
}
my $link = '';
-if ( $FS::CurrentUser::CurrentUser->access_right('View invoices') #XXX for now
- || $FS::CurrentUser::CurrentUser->access_right('View customer payments') ){
+if ( ( $curuser->access_right('View invoices') #XXX for now
+ || $curuser->access_right('View customer payments')
+ )
+ && ! $opt{'disable_link'}
+ )
+{
$link = [ "${p}view/cust_$thing.html?${thing}num=", $thing.'num' ]
}
diff --git a/httemplate/view/cust_main/payment_history.html b/httemplate/view/cust_main/payment_history.html
index 2ab5339db..335ce2485 100644
--- a/httemplate/view/cust_main/payment_history.html
+++ b/httemplate/view/cust_main/payment_history.html
@@ -138,15 +138,25 @@
% if ( ( $conf->exists('batch-enable') || $conf->config('batch-enable_payby') )
% && $curuser->access_right('View customer batched payments')
-% ) {
- View batched payments:
+% )
+% {
+ View batched payments:
% foreach my $status (qw( Queued In-transit Complete All )) {
<A HREF="<% $p %>search/cust_pay_batch.cgi?status=<% $status{$status} %>;custnum=<% $custnum %>"><% $status %></A>
<% $status ne 'All' ? '|' : '' %>
% }
- <BR>
+ <BR>
% }
+%# pending payment links
+
+% if ( $curuser->access_right('View customer pending payments')
+% && scalar($cust_main->cust_pay_pending)
+% )
+% {
+ <A HREF="<% $p %>search/cust_pay_pending.html?magic=_date;statusNOT=done;custnum=<% $custnum %>">View pending payments</A><BR>
+% }
+
%# and now the table
<% include("/elements/table-grid.html") %>