RT# 81961 Repair broken links in POD documentation
[freeside.git] / FS / FS / cust_pay_batch.pm
index cfba664..3cc8a7c 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 );
 
@@ -130,6 +133,8 @@ and replace methods.
 sub check {
   my $self = shift;
 
+  my $conf = new FS::Conf;
+
   my $error = 
       $self->ut_numbern('paybatchnum')
     || $self->ut_numbern('trancode') #deprecated
@@ -138,7 +143,9 @@ sub check {
     || $self->ut_number('custnum')
     || $self->ut_text('address1')
     || $self->ut_textn('address2')
-    || $self->ut_text('city')
+    || ($conf->exists('cust_main-no_city_in_address') 
+        ? $self->ut_textn('city') 
+        : $self->ut_text('city'))
     || $self->ut_textn('state')
   ;
 
@@ -229,7 +236,7 @@ sub expmmyy {
 
 =item pay_batch
 
-Returns the payment batch this payment belongs to (L<FS::pay_batch).
+Returns the payment batch this payment belongs to (L<FS::pay_batch>).
 
 =cut
 
@@ -311,20 +318,21 @@ sub approve {
   my %opt = @_;
   my $paybatchnum = $new->paybatchnum;
   my $old = qsearchs('cust_pay_batch', { paybatchnum => $paybatchnum })
-    or return "paybatchnum $paybatchnum not found";
+    or return "cannot approve, paybatchnum $paybatchnum not found";
   # leave these restrictions in place until TD EFT is converted over
   # to B::BP
-  return "paybatchnum $paybatchnum already resolved ('".$old->status."')" 
+  return "cannot approve paybatchnum $paybatchnum, already resolved ('".$old->status."')" 
     if $old->status;
   $new->status('Approved');
   my $error = $new->replace($old);
   if ( $error ) {
-    return "error updating status of paybatchnum $paybatchnum: $error\n";
+    return "error approving paybatchnum $paybatchnum: $error\n";
   }
   my $cust_pay = new FS::cust_pay ( {
       'custnum'   => $new->custnum,
       'payby'     => $new->payby,
       'payinfo'   => $new->payinfo || $old->payinfo,
+      'paymask'   => $new->mask_payinfo,
       'paid'      => $new->paid,
       '_date'     => $new->_date,
       'usernum'   => $new->usernum,
@@ -361,7 +369,7 @@ sub decline {
 
   my $paybatchnum = $new->paybatchnum;
   my $old = qsearchs('cust_pay_batch', { paybatchnum => $paybatchnum })
-    or return "paybatchnum $paybatchnum not found";
+    or return "cannot decline, paybatchnum $paybatchnum not found";
   if ( $old->status ) {
     # Handle the case where payments are rejected after the batch has been 
     # approved.  FS::pay_batch::import_results won't allow results to be 
@@ -388,14 +396,14 @@ sub decline {
     }
     else {
       # normal case: refuse to do anything
-      return "paybatchnum $paybatchnum already resolved ('".$old->status."')";
+      return "cannot decline paybatchnum $paybatchnum, already resolved ('".$old->status."')";
     }
   } # !$old->status
   $new->status('Declined');
   $new->error_message($reason);
   my $error = $new->replace($old);
   if ( $error ) {
-    return "error updating status of paybatchnum $paybatchnum: $error\n";
+    return "error declining paybatchnum $paybatchnum: $error\n";
   }
   my $due_cust_event = $new->cust_main->due_cust_event(
     'eventtable'  => 'cust_pay_batch',
@@ -451,6 +459,17 @@ sub request_item {
     die "unsupported BatchPayment method: ".$pay_batch->payby;
   }
 
+  my $recurring;
+  if ( $cust_main->status =~ /^active|suspended|ordered$/ ) {
+    if ( $self->payinfo_used ) {
+      $recurring = 'S'; # subsequent
+    } else {
+      $recurring = 'F'; # first use
+    }
+  } else {
+    $recurring = 'N'; # non-recurring
+  }
+
   Business::BatchPayment->create(Item =>
     # required
     action      => 'payment',
@@ -466,10 +485,81 @@ sub request_item {
     ( map { $_ => $location->$_ } qw(address2 city state country zip) ),
     
     invoice_number  => $self->invnum,
+    recurring_billing => $recurring,
     %payment,
   );
 }
 
+=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<FS::pay_batch> with a status of 'O' (not yet in transit.)  Deletes all associated
+records from L<FS::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