[freeside-commits] branch master updated. cd1a490338a5da42ab94b62b24231aa14dd5d048

Jonathan Prykop jonathan at 420.am
Thu Mar 12 17:31:22 PDT 2015


The branch, master has been updated
       via  cd1a490338a5da42ab94b62b24231aa14dd5d048 (commit)
      from  771e64b732c69902be5552d53d4a7a1199d5fca3 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit cd1a490338a5da42ab94b62b24231aa14dd5d048
Author: Jonathan Prykop <jonathan at freeside.biz>
Date:   Thu Mar 12 19:30:08 2015 -0500

    RT#33582: RBC return batch processing failure [handling for non-chronological file]

diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index d5e8960..a37e5a6 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -3960,7 +3960,7 @@ and customer address. Include units.',
   {
     'key'         => 'batchconfig-RBC',
     'section'     => 'billing',
-    'description' => 'Configuration for Royal Bank of Canada PDS batching, four lines: 1. Client number, 2. Short name, 3. Long name, 4. Transaction code.',
+    'description' => 'Configuration for Royal Bank of Canada PDS batching, five lines: 1. Client number, 2. Short name, 3. Long name, 4. Transaction code 5. (optional) set to TEST to turn on test mode.',
     'type'        => 'textarea',
   },
 
diff --git a/FS/FS/cust_pay_batch.pm b/FS/FS/cust_pay_batch.pm
index da003d8..13b2eef 100644
--- a/FS/FS/cust_pay_batch.pm
+++ b/FS/FS/cust_pay_batch.pm
@@ -344,14 +344,8 @@ sub decline {
       }
       $cust_pay->void($reason);
     }
-    elsif ( lc($old->status) eq 'declined' ) {
-      # batch files from RBC can have multiple lines for one decline
-      # if this causes problems elsewhere, try hacking pay_batch/RBC.pm instead
-      return '';
-    }
     else {
       # normal case: refuse to do anything
-      # should never happen...only statuses are approved or declined
       return "cannot decline paybatchnum $paybatchnum, already resolved ('".$old->status."')";
     }
   } # !$old->status
diff --git a/FS/FS/pay_batch.pm b/FS/FS/pay_batch.pm
index f41b3e3..449ea22 100644
--- a/FS/FS/pay_batch.pm
+++ b/FS/FS/pay_batch.pm
@@ -222,17 +222,17 @@ takes precedence over I<format>.
 
 Supported format keys (defined in the specified FS::pay_batch module) are:
 
-I<filetype> - CSV, fixed, variable, XML
+I<filetype> - required, can be CSV, fixed, variable, XML
 
-I<fields> - list of field names for each row/line
+I<fields> - required list of field names for each row/line
 
 I<formatre> - regular expression for fixed filetype
 
-I<parse> - for variable filetype
+I<parse> - required for variable filetype
 
-I<xmlkeys> - for XML filetype
+I<xmlkeys> - required for XML filetype
 
-I<xmlrow> - for XML filetype
+I<xmlrow> - required for XML filetype
 
 I<begin_condition> - sub, ignore all lines before this returns true
 
@@ -242,11 +242,11 @@ I<end_hook> - sub, runs immediately after end_condition returns true
 
 I<skip_condition> - sub, skip lines when this returns true
 
-I<hook> - sub, runs before approved/declined conditions are checked
+I<hook> - required, sub, runs before approved/declined conditions are checked
 
-I<approved> - sub, returns true when approved
+I<approved> - required, sub, returns true when approved
 
-I<declined> - sub, returns true when declined
+I<declined> - required, sub, returns true when declined
 
 I<close_condition> - sub, decide whether or not to close the batch
 
diff --git a/FS/FS/pay_batch/RBC.pm b/FS/FS/pay_batch/RBC.pm
index a99d057..45e888d 100644
--- a/FS/FS/pay_batch/RBC.pm
+++ b/FS/FS/pay_batch/RBC.pm
@@ -6,7 +6,7 @@ use Date::Format 'time2str';
 use FS::Conf;
 
 my $conf;
-my ($client_num, $shortname, $longname, $trans_code, $i);
+my ($client_num, $shortname, $longname, $trans_code, $testmode, $i, $declined, $totaloffset);
 
 $name = 'RBC';
 # Royal Bank of Canada ACH Direct Payments Service
@@ -24,11 +24,12 @@ $name = 'RBC';
 # 4 - Foreign Currency Information Records
 # We skip all subtypes except 0
 #
-# additional info available at https://www.rbcroyalbank.com/ach/file-451806.pdf
+# additional info available at https://www.rbcroyalbank.com/ach/cid-213166.html
 %import_info = (
   'filetype'    => 'fixed',
+  #this only really applies to Debit Detail, but we otherwise only need first char
   'formatre'    => 
-  '^([0134]).{18}(.{4}).{3}(.).{11}(.{19}).{6}(.{30}).{17}(.{9})(.{18}).{6}(.{14}).{23}(.).{9}\r?$',
+  '^(.).{18}(.{4}).{3}(.).{11}(.{19}).{6}(.{30}).{17}(.{9})(.{18}).{6}(.{14}).{23}(.).{9}\r?$',
   'fields' => [ qw(
     recordtype
     batchnum
@@ -53,30 +54,67 @@ $name = 'RBC';
   },
   'declined'    => sub {
       my $hash = shift;
-      grep { $hash->{'status'} eq $_ } ('E', 'R', 'U', 'T');
+      my $status = $hash->{'status'};
+      my $message = '';
+      if ($status eq 'E') {
+        $message = 'Reversed payment';
+      } elsif ($status eq 'R') {
+        $message = 'Rejected payment';
+      } elsif ($status eq 'U') {
+        $message = 'Returned payment';
+      } elsif ($status eq 'T') {
+        $message = 'Error';
+      } else {
+        return 0;
+      }
+      $hash->{'error_message'} = $message;
+      $declined->{$hash->{'paybatchnum'}} = 1;
+      return 1;
   },
   'begin_condition' => sub {
       my $hash = shift;
-      $hash->{recordtype} eq '1'; # Detail Record
+      # Debit Detail Record
+      if ($hash->{recordtype} eq '1') {
+        $declined = {};
+        $totaloffset = 0;
+        return 1;
+      # Credit Detail Record, will immediately trigger end condition & error
+      } elsif ($hash->{recordtype} eq '2') { 
+        return 1;
+      } else {
+        return 0;
+      }
   },
   'end_hook'    => sub {
       my( $hash, $total, $line ) = @_;
+      return "Can't process Credit Detail Record, aborting import"
+        if ($hash->{'recordtype'} eq '2');
+      $totaloffset = sprintf("%.2f", $totaloffset / 100 );
+      $total += $totaloffset;
       $total = sprintf("%.2f", $total);
-      # We assume here that this is an 'All Records' or 'Input Records'
-      # report.
+      # We assume here that this is an 'All Records' or 'Input Records' report.
       my $batch_total = sprintf("%.2f", substr($line, 59, 18) / 100);
       return "Our total $total does not match bank total $batch_total!"
         if $total != $batch_total;
-      '';
+      return '';
   },
   'end_condition' => sub {
       my $hash = shift;
-      $hash->{recordtype} eq '4'; # Client Trailer Record
+      return ($hash->{recordtype} eq '4')  # Client Trailer Record
+          || ($hash->{recordtype} eq '2'); # Credit Detail Record, will throw error in end_hook
   },
   'skip_condition' => sub {
       my $hash = shift;
-      $hash->{'recordtype'} eq '3' ||
-        $hash->{'subtype'} ne '0';
+      #we already declined it this run, no takebacks
+      if ($declined->{$hash->{'paybatchnum'}}) {
+        #file counts this as part of total, but we skip
+        $totaloffset += $hash->{'paid'}
+          if $hash->{'status'} eq ' '; #false laziness with 'approved' above
+        return 1;
+      }
+      return 
+        ($hash->{'recordtype'} eq '3') || #Account Trailer Record, concludes returned items
+        ($hash->{'subtype'} ne '0'); #error messages, etc, too late to apply to previous entry
   },
 );
 
@@ -87,18 +125,22 @@ $name = 'RBC';
      $shortname,
      $longname,
      $trans_code, 
+     $testmode
      ) = $conf->config("batchconfig-RBC");
+    $testmode = '' unless $testmode eq 'TEST';
     $i = 1;
   },
   header => sub { 
     my $pay_batch = shift;
-    '$$AAPASTD0152[PROD[NL$$'."\n".
+    my $mode = $testmode ? 'TEST' : 'PROD';
+    my $filenum = $testmode ? 'TEST' : sprintf("%04u", $pay_batch->batchnum);
+    '$$AAPASTD0152['.$mode.'[NL$$'."\n".
     '000001'.
     'A'.
     'HDR'.
     sprintf("%10s", $client_num).
     sprintf("%-30s", $longname).
-    sprintf("%04u", $pay_batch->batchnum).
+    $filenum.
     time2str("%Y%j", $pay_batch->download).
     'CAD'.
     '1'.

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/Conf.pm           |    2 +-
 FS/FS/cust_pay_batch.pm |    6 -----
 FS/FS/pay_batch.pm      |   16 +++++------
 FS/FS/pay_batch/RBC.pm  |   68 ++++++++++++++++++++++++++++++++++++++---------
 4 files changed, 64 insertions(+), 28 deletions(-)




More information about the freeside-commits mailing list