fix foreign keys to voided payments in advance of 4.x upgrade, #13971
authorMark Wells <mark@freeside.biz>
Wed, 23 Apr 2014 18:16:55 +0000 (11:16 -0700)
committerMark Wells <mark@freeside.biz>
Wed, 23 Apr 2014 18:16:55 +0000 (11:16 -0700)
FS/FS/Schema.pm
FS/FS/cust_pay.pm
FS/FS/cust_pay_pending.pm
FS/FS/cust_pay_void.pm

index f225658..f97495d 100644 (file)
@@ -1645,6 +1645,7 @@ sub tables_hashref {
         'gatewaynum',   'int',     'NULL',  '', '', '',
         #'cust_balance', @money_type,            '', '',
         'paynum',       'int',     'NULL',  '', '', '',
+        'void_paynum',  'int',     'NULL',  '', '', '',
         'jobnum',    'bigint',     'NULL',  '', '', '', 
         'invnum',       'int',     'NULL',  '', '', '',
         'manual',       'char',    'NULL',   1, '', '',
index d36bae6..3cdbdb3 100644 (file)
@@ -416,12 +416,17 @@ sub void {
   } );
   $cust_pay_void->reason(shift) if scalar(@_);
   my $error = $cust_pay_void->insert;
-  if ( $error ) {
-    $dbh->rollback if $oldAutoCommit;
-    return $error;
+
+  my $cust_pay_pending =
+    qsearchs('cust_pay_pending', { paynum => $self->paynum });
+  if ( $cust_pay_pending ) {
+    $cust_pay_pending->set('void_paynum', $self->paynum);
+    $cust_pay_pending->set('paynum', '');
+    $error ||= $cust_pay_pending->replace;
   }
 
-  $error = $self->delete;
+  $error ||= $self->delete;
+
   if ( $error ) {
     $dbh->rollback if $oldAutoCommit;
     return $error;
index 22c9293..b61635d 100644 (file)
@@ -133,6 +133,10 @@ L<FS::payment_gateway> id.
 
 Payment number (L<FS::cust_pay>) of the completed payment.
 
+=item void_paynum
+
+Payment number of the payment if it's been voided.
+
 =item invnum
 
 Invoice number (L<FS::cust_bill>) to try to apply this payment to.
@@ -221,6 +225,7 @@ sub check {
     || $self->ut_foreign_keyn('paynum', 'cust_pay', 'paynum' )
     || $self->ut_foreign_keyn('pkgnum', 'cust_pkg', 'pkgnum')
     || $self->ut_foreign_keyn('invnum', 'cust_bill', 'invnum')
+    || $self->ut_foreign_keyn('void_paynum', 'cust_pay_void', 'paynum' )
     || $self->ut_flag('manual')
     || $self->ut_numbern('discount_term')
     || $self->payinfo_check() #payby/payinfo/paymask/paydate
@@ -459,6 +464,20 @@ sub _upgrade_data {  #class method
   my $sth = dbh->prepare($sql) or die dbh->errstr;
   $sth->execute or die $sth->errstr;
 
+  # For cust_pay_pending records linked to voided payments, move the paynum
+  # to void_paynum.
+  $sql =
+    "UPDATE cust_pay_pending SET void_paynum = paynum, paynum = NULL 
+    WHERE paynum IS NOT NULL AND void_paynum IS NULL AND EXISTS(
+      SELECT 1 FROM cust_pay_void
+      WHERE cust_pay_void.paynum = cust_pay_pending.paynum
+    ) AND NOT EXISTS(
+      SELECT 1 FROM cust_pay
+      WHERE cust_pay.paynum = cust_pay_pending.paynum
+    )";
+  $sth = dbh->prepare($sql) or die dbh->errstr;
+  $sth->execute or die $sth->errstr;
+
 }
 
 =back
index e6e2159..fdb7c7f 100644 (file)
@@ -135,12 +135,16 @@ sub unvoid {
     map { $_ => $self->get($_) } fields('cust_pay')
   } );
   my $error = $cust_pay->insert;
-  if ( $error ) {
-    $dbh->rollback if $oldAutoCommit;
-    return $error;
+
+  my $cust_pay_pending =
+    qsearchs('cust_pay_pending', { void_paynum => $self->paynum });
+  if ( $cust_pay_pending ) {
+    $cust_pay_pending->set('paynum', $cust_pay->paynum);
+    $cust_pay_pending->set('void_paynum', '');
+    $error ||= $cust_pay_pending->replace;
   }
 
-  $error = $self->delete;
+  $error ||= $self->delete;
   if ( $error ) {
     $dbh->rollback if $oldAutoCommit;
     return $error;