remove the unwise "counter" attribute; assorted format fixes
authorMark Wells <mark@freeside.biz>
Wed, 8 Aug 2012 01:38:02 +0000 (18:38 -0700)
committerMark Wells <mark@freeside.biz>
Wed, 8 Aug 2012 01:38:02 +0000 (18:38 -0700)
TD_EFT.pm

index ba9ee9f..c33ad93 100644 (file)
--- a/TD_EFT.pm
+++ b/TD_EFT.pm
@@ -31,7 +31,6 @@ my $processor = Business::BatchPayment->processor('TD_EFT',
   return_branch   => '10202',   # 0004 + 5-digit branch number
   return_account  => '00124598951', # 11 digits
   cpa_code        => '120',
-  counter         => 101,
 );
 
 my $result = $processor->submit(@items);
@@ -57,9 +56,6 @@ to use for returned payments.
 
 =item cpa_code - Your 3-digit CPA industry code.
 
-=item counter - Batch sequence number.  You MUST save this after submitting
-a batch, and pass the same value back in in the next session.
-
 =back
 
 =cut
@@ -85,19 +81,13 @@ has 'datacentre' => (
   required => 1,
 );
 
-has 'counter' => (
-  is => 'rw',
-  isa => 'Int',
-  default => 0,
-);
-
 sub BUILD {
   my $self = shift;
   # should be a parametric string type or something
   $self->originator(     sprintf('%-10.10s', $self->originator)     );
   $self->short_name(     sprintf('%-15.15s', $self->short_name)     );
   $self->long_name(      sprintf('%-30.30s', $self->long_name)      );
-  $self->return_account( sprintf('%-11.11s', $self->return_account) );
+  $self->return_account( sprintf('%-11.11s', $self->return_account) . ' ' );
   $self->return_branch ( '0004'.
     sprintf('%-5.5s', $self->return_branch) )
     unless length($self->return_branch) == 9;
@@ -109,21 +99,20 @@ before format_request => sub {
   Business::BatchPayment::TD_EFT::Batch->meta->apply($batch);
   
   my $dt = DateTime->now;
+  $dt->set_time_zone('local');
   $batch->create_date(sprintf('%03d%03d', $dt->year % 1000, $dt->day_of_year));
 
+  my $counter = $batch->batch_id;
+  $counter = 0 unless $counter =~ /^\d+$/;
   # a number from 1 to 9999
-  $batch->fcn(sprintf('%04u', ($self->counter % 9999) + 1));
-  # what should be a unique identifier
-  $batch->batch_id($batch->create_date . '-' . $batch->fcn);
-};
-
-after submit => sub {
-  my $self = shift;
-  $self->counter($self->counter + 1);
+  $batch->fcn(sprintf('%04u', ($counter % 9999) + 1));
+  # We can't return the FCN as the batch_id because it wraps around.
+  # The TIDs are still correct though.
 };
 
 sub format_header {
   my ($self, $batch) = @_;
+  $batch->row(1);
   my $header =
     'A' .          #record type
     '000000001' .  #row number
@@ -138,7 +127,10 @@ sub format_item {
   my ($self, $item, $batch) = @_;
 
   $batch->row($batch->row + 1);
-  my $cents = int($item->amount * 100);
+  # Avoid floating point error: if we're passed a non-exact number of
+  # cents (and we will be...), round to the nearest integer, and then
+  # sum integer numbers of cents to get the batch total.
+  my $cents = sprintf('%.0f',$item->amount * 100);
   if ( $item->action eq 'payment' ) {
     $batch->total_payment( $batch->total_payment + $cents );
     $batch->count_payment( $batch->count_payment + 1 );
@@ -151,7 +143,11 @@ sub format_item {
   # (should this use Time::Business?  Date::Holidays::CA?)
   # (should we just require the merchant to specify a process date?)
   my $process_date = $item->process_date;
-  $process_date ||= DateTime->today->add(days => 1);
+  if ( $process_date ) {
+    $process_date->set_time_zone('local');
+  } else {
+    $process_date = DateTime->today->set_time_zone('local')->add(days => 1);
+  }
 
   my $duedate = sprintf('%03d%03d', 
     $process_date->year % 1000,
@@ -256,13 +252,12 @@ sub parse_ack_264 {
         # Most of these fields aren't interesting to us.
         $batch->fcn($4);
         $batch->create_date($5);
-        $batch->batch_id($batch->create_date . '-' . $batch->fcn);
         my $date = $10;
         $date =~ /^(....)-(..)-(..)$/; # actual process date, YYYY-MM-DD
         $payment_date = DateTime->new(year => $1, month => $2, day => $3);
       } elsif ( $row =~ /^[CD]/ ) {
         # Rejected item detail.
-        my @f = ($row =~ /^(.{1})(.{9})(.{14})(.{3})(.{10})(.{6})(.{9})(.{12})(.{25})(.{15})(.{30})(.{30})(.{10})(.{19})(.{9})(.{12})(.{15})(.{22})(.{2})(.{11})$/)
+        my @f = ($row =~ /^(.{1})(.{9})(.{14})(.{3})(.{10})(.{6})(.{9})(.{12})(.{22})(.{3})(.{15})(.{30})(.{30})(.{10})(.{19})(.{9})(.{12})(.{15})(.{22})(.{2})(.{11})$/)
           or die "invalid detail row\n";
         foreach (@f) { s/^\s+//; s/\s+$//; }
         unshift @f,  ''; # make field numbers line up
@@ -281,8 +276,7 @@ sub parse_ack_264 {
           account_number  => $f[8],
           tid             => $f[15],
         );
-        my @error_fields = map { $field_order[$_] } ($f[21] =~ /../g);
-        # yuck
+        my @error_fields = map { $field_order[$_] } ($f[21] =~ /../g) if $f[21];
         $item->error_message('invalid fields: '.join(', ', @error_fields));
         $batch->push($item);
       } elsif ( $row =~ /^R/ ) {
@@ -335,12 +329,15 @@ sub parse_ret_80 {
     try {
       if ( $row =~ /^H/ ) {
         # Header.
-        $row =~ /^(.{1})(.{10})(.{1})( {3})(.{6})(.{30})(.{12})( {8})$/
+        $row =~ /^(.{1})(.{10})(.{1})( {3})(.{6})(.{30})(.{9})(.{12})( {8})$/
           or die "invalid header row\n";
         # the only field we care about is payment vs. credit
         # and even that only minimally
-        if ( $3 eq 'I' ) { $action = 'credit' }
-        elsif ( $3 eq 'J') { $action = 'payment' }
+        if ( $3 eq 'I' ) {
+          $action = 'credit'
+        } elsif ( $3 eq 'J') {
+          $action = 'payment'
+        }
       } elsif ( $row =~ /^D/ ) {
         # Detail.
         my @f = ( $row =~ /^(.{1})(.{20})(.{2})(.{1})(.{6})(.{19})(.{9})(.{12})(.{10})$/ )
@@ -364,9 +361,9 @@ sub parse_ret_80 {
       }
     } catch {
       $self->parse_error($row, $_);
-    }
+    };
     die "no valid header row found\n" unless $action;
-  }
+  } #foreach $row
   $batch;
 }