From 6821ffc8988f64ddeefe1219b32d00cc57c4ccde Mon Sep 17 00:00:00 2001 From: Jonathan Prykop Date: Wed, 29 Jul 2015 20:54:53 -0500 Subject: [PATCH] RT#35100: how to void a payment in the cust_pay_batch before file has been uploaded to the bank --- FS/FS/cust_pay_batch.pm | 69 +++++++++++++++++++++++ httemplate/misc/process/delete-cust_pay_batch.cgi | 37 ++++++++++++ httemplate/search/cust_pay_batch.cgi | 34 ++++++++++- 3 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 httemplate/misc/process/delete-cust_pay_batch.cgi diff --git a/FS/FS/cust_pay_batch.pm b/FS/FS/cust_pay_batch.pm index 8f31e4dda..a5fa89b19 100644 --- a/FS/FS/cust_pay_batch.pm +++ b/FS/FS/cust_pay_batch.pm @@ -433,6 +433,75 @@ sub request_item { ); } +=item process_unbatch_and_delete + +L run as a queued job, accepts I<$job> and I<$param>. + +=cut + +sub process_unbatch_and_delete { + my ($job, $param) = @_; + my $self = qsearchs('cust_pay_batch',{ 'paybatchnum' => scalar($param->{'paybatchnum'}) }) + or die 'Could not find paybatchnum ' . $param->{'paybatchnum'}; + my $error = $self->unbatch_and_delete; + die $error if $error; + return ''; +} + +=item unbatch_and_delete + +May only be called on a record with an empty status and an associated +L with a status of 'O' (not yet in transit.) Deletes all associated +records from L and then deletes this record. +If there is an error, returns the error, otherwise returns false. + +=cut + +sub unbatch_and_delete { + my $self = shift; + + return 'Cannot unbatch a cust_pay_batch with status ' . $self->status + if $self->status; + + my $pay_batch = qsearchs('pay_batch',{ 'batchnum' => $self->batchnum }) + or return 'Cannot find associated pay_batch record'; + + return 'Cannot unbatch from a pay_batch with status ' . $pay_batch->status + if $pay_batch->status ne 'O'; + + local $SIG{HUP} = 'IGNORE'; + local $SIG{INT} = 'IGNORE'; + local $SIG{QUIT} = 'IGNORE'; + local $SIG{TERM} = 'IGNORE'; + local $SIG{TSTP} = 'IGNORE'; + local $SIG{PIPE} = 'IGNORE'; + + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; + + # have not generated actual payments yet, so should be safe to delete + foreach my $cust_bill_pay_batch ( + qsearch('cust_bill_pay_batch',{ 'paybatchnum' => $self->paybatchnum }) + ) { + my $error = $cust_bill_pay_batch->delete; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } + + my $error = $self->delete; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + ''; + +} + =back =head1 BUGS diff --git a/httemplate/misc/process/delete-cust_pay_batch.cgi b/httemplate/misc/process/delete-cust_pay_batch.cgi new file mode 100644 index 000000000..4937b58e2 --- /dev/null +++ b/httemplate/misc/process/delete-cust_pay_batch.cgi @@ -0,0 +1,37 @@ +<% $server->process %> +<%init> + +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access denied" + unless $curuser->access_right('Process batches') + || $curuser->access_right('Process global batches'); + +# look up paybatch using agentnums_sql & status constraints +# to validate access for this particular cust_pay_batch, +# similar to how it's done in cust_pay_batch.cgi + +my %arg = $cgi->param('arg'); +my $paybatchnum = $arg{'paybatchnum'}; +$paybatchnum =~ /^\d+$/ or die "Illegal paybatchnum"; +my @search = (); +push @search, 'cust_pay_batch.paybatchnum = ' . $paybatchnum; +push @search, '(cust_pay_batch.status = \'\' OR cust_pay_batch.status IS NULL)'; +push @search, 'pay_batch.status = \'O\''; +push @search, $curuser->agentnums_sql({ table => 'cust_main' }); +push @search, $curuser->agentnums_sql({ table => 'pay_batch', + null_right => 'Process global batches', + }); +my $search = ' WHERE ' . join(' AND ', @search); +die "permission denied" unless qsearchs({ + 'table' => 'cust_pay_batch', + '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 +}); + +my $server = new FS::UI::Web::JSRPC 'FS::cust_pay_batch::process_unbatch_and_delete', $cgi; + + diff --git a/httemplate/search/cust_pay_batch.cgi b/httemplate/search/cust_pay_batch.cgi index c0f84ec87..cc958b96d 100755 --- a/httemplate/search/cust_pay_batch.cgi +++ b/httemplate/search/cust_pay_batch.cgi @@ -14,6 +14,7 @@ 'Exp', 'Amount', 'Status', + '', # delete link '', # error_message ], 'fields' => [ 'paybatchnum', @@ -31,9 +32,10 @@ sprintf('%.02f', $_[0]->amount) }, sub { $_[0]->display_status }, + $sub_unbatch, 'error_message', ], - 'align' => 'rrrlllcrlll', + 'align' => 'rrrlllcrllll', 'links' => [ '', ["${p}view/cust_bill.cgi?", 'invnum'], (["${p}view/cust_main.cgi?", 'custnum']) x 2, @@ -129,6 +131,36 @@ my $sub_receipt = sub { ); }; +my $sub_unbatch = ''; +if ( ($pay_batch && ($pay_batch->status eq 'O')) + && ( $curuser->access_right('Process batches') + || $curuser->access_right('Process global batches') ) +) { + $sub_unbatch = sub { + my $self = shift; + return '' if $self->status; # sanity check, shouldn't happen + my $batchnum = $self->batchnum; + my $paybatchnum = $self->paybatchnum; + my $out = < + + +EOF + $out .= include('/elements/progress-init.html', + "delete_cust_pay_batch_$paybatchnum", + [ 'paybatchnum' ], + $p.'misc/process/delete-cust_pay_batch.cgi', + $p.'search/cust_pay_batch.cgi?' . $cgi->query_string, + "paybatchnum$paybatchnum", + ); + my $onclick = 'if ( confirm(\''; + $onclick .= emt('Are you sure you want to delete batch payment ') . $self->paybatchnum; + $onclick .= emt(' from payment batch ') . $self->batchnum; + $onclick .= '\') ) { paybatchnum' . $paybatchnum . 'process() }'; + return $out . 'delete'; + }; +} + my $html_init = ''; if ( $pay_batch ) { $html_init = include('elements/cust_pay_batch_top.html', -- 2.11.0