RT#35100 how to void a payment in the cust_pay_batch before file has been uploaded...
authorJonathan Prykop <jonathan@freeside.biz>
Thu, 30 Jul 2015 01:54:53 +0000 (20:54 -0500)
committerJonathan Prykop <jonathan@freeside.biz>
Sat, 1 Aug 2015 02:55:59 +0000 (21:55 -0500)
FS/FS/cust_pay_batch.pm
httemplate/misc/process/delete-cust_pay_batch.cgi [new file with mode: 0644]
httemplate/search/cust_pay_batch.cgi

index d28085c..774ea29 100644 (file)
@@ -8,6 +8,9 @@ use FS::Record qw(dbh qsearch qsearchs);
 use FS::payinfo_Mixin;
 use FS::cust_main;
 use FS::cust_bill;
+use Storable qw( thaw );
+use MIME::Base64 qw( decode_base64 );
+
 
 @ISA = qw( FS::payinfo_Mixin FS::cust_main_Mixin FS::Record );
 
@@ -474,6 +477,76 @@ sub request_item {
   );
 }
 
+=item process_unbatch_and_delete
+
+L</unbatch_and_delete> run as a queued job, accepts I<$job> and I<$param>.
+
+=cut
+
+sub process_unbatch_and_delete {
+  my ($job, $param) = @_;
+  $param = thaw(decode_base64($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<pay_batch> with a status of 'O' (not yet in transit.)  Deletes all associated
+records from L<cust_bill_pay_batch> 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 (file)
index 0000000..4937b58
--- /dev/null
@@ -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; 
+
+</%init>
index b47aaf3..9e02e1b 100755 (executable)
@@ -14,6 +14,7 @@
                                 'Exp',
                                 'Amount',
                                 'Status',
+                                 '', # delete link
                                  '', # error_message
                               ],
               'fields'      => [  'paybatchnum',
                                   sub {
                                     sprintf('%.02f', $_[0]->amount)
                                   },
-                                  'status',
+                                  sub { $_[0]->display_status },
+                                  $sub_unbatch,
                                   'error_message',
                                 ],
-             'align'       => 'rrrlllcrll',
+             'align'       => 'rrrlllcrlll',
              '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;
+<FORM name="delete_cust_pay_batch_$paybatchnum">
+<INPUT TYPE="hidden" name="paybatchnum" value="$paybatchnum">
+</FORM>
+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 . '<A HREF="javascript:void(0)" ONCLICK="' . $onclick . '">delete</A>';
+  };
+}
+
 my $html_init = '';
 if ( $pay_batch ) {
   $html_init = include('elements/cust_pay_batch_top.html',