self-service improvements, RT10883
[freeside.git] / FS / FS / pay_batch.pm
index 9a0b235..d142411 100644 (file)
@@ -7,6 +7,8 @@ use Text::CSV_XS;
 use FS::Record qw( dbh qsearch qsearchs );
 use FS::cust_pay;
 use FS::Conf;
+use Date::Parse qw(str2time);
+use Business::CreditCard qw(cardtype);
 
 @ISA = qw(FS::Record);
 
@@ -198,9 +200,12 @@ sub import_results {
   my $job = $param->{'job'};
   $job->update_statustext(0) if $job;
 
-  my $filetype            = $info->{'filetype'};      # CSV or fixed
+  my $conf = new FS::Conf;
+
+  my $filetype            = $info->{'filetype'};      # CSV, fixed, variable
   my @fields              = @{ $info->{'fields'}};
   my $formatre            = $info->{'formatre'};      # for fixed
+  my $parse               = $info->{'parse'};         # for variable
   my @all_values;
   my $begin_condition     = $info->{'begin_condition'};
   my $end_condition       = $info->{'end_condition'};
@@ -209,6 +214,7 @@ sub import_results {
   my $hook                = $info->{'hook'};
   my $approved_condition  = $info->{'approved'};
   my $declined_condition  = $info->{'declined'};
+  my $close_condition     = $info->{'close_condition'};
 
   my $csv = new Text::CSV_XS;
 
@@ -282,7 +288,17 @@ sub import_results {
         };
         push @values, $line;
         push @all_values, \@values;
-      }else{
+      }
+      elsif ($filetype eq 'variable') {
+        my @values = ( eval { $parse->($self, $line) } );
+        if( $@ ) {
+          $dbh->rollback if $oldAutoCommit;
+          return $@;
+        };
+        push @values, $line;
+        push @all_values, \@values;
+      }
+      else {
         $dbh->rollback if $oldAutoCommit;
         return "Unknown file type $filetype";
       }
@@ -357,15 +373,20 @@ sub import_results {
     }
 
     # purge CVV when the batch is processed
-    $new_cust_pay_batch->cust_main->remove_cvv
-      if ( $payby eq 'CARD' or $payby eq 'DCRD' );
+    if ( $payby =~ /^(CARD|DCRD)$/ ) {
+      my $payinfo = $hash{'payinfo'} || $cust_pay_batch->payinfo;
+      if ( ! grep { $_ eq cardtype($payinfo) }
+          $conf->config('cvv-save') ) {
+        $new_cust_pay_batch->cust_main->remove_cvv;
+      }
+    }
 
     if ( $new_cust_pay_batch->status =~ /Approved/i ) {
 
       my $cust_pay = new FS::cust_pay ( {
         'custnum'  => $custnum,
        'payby'    => $payby,
-        'paybatch' => $self->batchnum,
+        'paybatch' => $hash{'paybatch'} || $self->batchnum,
         'payinfo'  => ( $hash{'payinfo'} || $cust_pay_batch->payinfo ),
         map { $_ => $hash{$_} } (qw( paid _date )),
       } );
@@ -406,12 +427,25 @@ sub import_results {
           return $error;
        }
 
-      } # foreach $cust_event
+      }
+
+    }
 
-    } # if(status eq 'Approved')
+  }
+
+  if ( defined($close_condition) ) {
+    # Allow the module to decide whether to close the batch.
+    # This is used for TD EFT, which requires two imports before 
+    # closing.
+    # $close_condition can also die() to abort the whole import.
+    my $close = eval { $close_condition->($self) };
+    if ( $@ ) {
+      $dbh->rollback;
+      die $@;
+    }
+    $self->set_status('I') if !$close;
+  }
 
-  } # foreach(@all_values)
-  
   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
   '';
 
@@ -473,7 +507,20 @@ sub export_batch {
 
   my @cust_pay_batch = sort { $a->paybatchnum <=> $b->paybatchnum }
                       qsearch('cust_pay_batch', { batchnum => $self->batchnum } );
-
+  
+  # handle batch-increment_expiration option
+  if ( $self->payby eq 'CARD' ) {
+    my ($cmon, $cyear) = (localtime(time))[4,5];
+    foreach (@cust_pay_batch) {
+      my $etime = str2time($_->exp) or next;
+      my ($day, $mon, $year) = (localtime($etime))[3,4,5];
+      if( $conf->exists('batch-increment_expiration') ) {
+        $year++ while( $year < $cyear or ($year == $cyear and $mon <= $cmon) );
+        $_->exp( sprintf('%4u-%02u-%02u', $year + 1900, $mon+1, $day) );
+      }
+      $_->setfield('expmmyy', sprintf('%02u%02u', $mon+1, $year % 100));
+    }
+  }
   my $h = $info->{'header'};
   if(ref($h) eq 'CODE') {
     $batch .= &$h($self, \@cust_pay_batch) . "\n";