fix upgrade issues with old voided tax records, #73360
[freeside.git] / FS / FS / cust_bill_pkg_void.pm
index 7855d58..604c615 100644 (file)
@@ -2,11 +2,17 @@ package FS::cust_bill_pkg_void;
 use base qw( FS::TemplateItem_Mixin FS::Record );
 
 use strict;
 use base qw( FS::TemplateItem_Mixin FS::Record );
 
 use strict;
-use FS::Record qw( qsearch qsearchs );
+use FS::Record qw( qsearch qsearchs dbh fields );
 use FS::cust_bill_void;
 use FS::cust_bill_void;
-use FS::cust_bill_pkg_detail_void;
-use FS::cust_bill_pkg_display_void;
-use FS::cust_bill_pkg_discount_void;
+use FS::cust_bill_pkg_detail;
+use FS::cust_bill_pkg_display;
+use FS::cust_bill_pkg_discount;
+use FS::cust_bill_pkg;
+use FS::cust_bill_pkg_fee;
+use FS::cust_bill_pkg_tax_location;
+use FS::cust_bill_pkg_tax_rate_location;
+use FS::cust_tax_exempt_pkg;
+use FS::Cursor;
 
 =head1 NAME
 
 
 =head1 NAME
 
@@ -129,21 +135,85 @@ sub discount_table          { 'cust_bill_pkg_discount_void'; }
 Adds this record to the database.  If there is an error, returns the error,
 otherwise returns false.
 
 Adds this record to the database.  If there is an error, returns the error,
 otherwise returns false.
 
+=item unvoid 
+
+"Un-void"s this line item: Deletes the voided line item from the database and
+adds back a normal line item (and related tables).
+
 =cut
 
 =cut
 
+sub unvoid {
+  my $self = shift;
+
+  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;
+
+  my $cust_bill_pkg = new FS::cust_bill_pkg ( {
+    map { $_ => $self->get($_) } fields('cust_bill_pkg')
+  } );
+  my $error = $cust_bill_pkg->insert;
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error;
+  }
+
+  foreach my $table (qw(
+    cust_bill_pkg_detail
+    cust_bill_pkg_display
+    cust_bill_pkg_discount
+    cust_bill_pkg_tax_location
+    cust_bill_pkg_tax_rate_location
+    cust_tax_exempt_pkg
+    cust_bill_pkg_fee
+  )) {
+
+    foreach my $voided (
+      qsearch($table.'_void', { billpkgnum=>$self->billpkgnum })
+    ) {
+
+      my $class = 'FS::'.$table;
+      my $unvoid = $class->new( {
+        map { $_ => $voided->get($_) } fields($table)
+      });
+      my $error = $unvoid->insert || $voided->delete;
+      if ( $error ) {
+        $dbh->rollback if $oldAutoCommit;
+        return $error;
+      }
+
+    }
+
+  }
+
+  $error = $self->delete;
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error;
+  }
+
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+  '';
+
+}
+
 =item delete
 
 Delete this record from the database.
 
 =item delete
 
 Delete this record from the database.
 
-=cut
-
 =item replace OLD_RECORD
 
 Replaces the OLD_RECORD with this one in the database.  If there is an error,
 returns the error, otherwise returns false.
 
 =item replace OLD_RECORD
 
 Replaces the OLD_RECORD with this one in the database.  If there is an error,
 returns the error, otherwise returns false.
 
-=cut
-
 =item check
 
 Checks all fields to make sure this is a valid record.  If there is
 =item check
 
 Checks all fields to make sure this is a valid record.  If there is
@@ -172,6 +242,7 @@ sub check {
     || $self->ut_moneyn('unitsetup')
     || $self->ut_moneyn('unitrecur')
     || $self->ut_enum('hidden', [ '', 'Y' ])
     || $self->ut_moneyn('unitsetup')
     || $self->ut_moneyn('unitrecur')
     || $self->ut_enum('hidden', [ '', 'Y' ])
+    || $self->ut_numbern('feepart')
   ;
   return $error if $error;
 
   ;
   return $error if $error;
 
@@ -191,6 +262,50 @@ sub cust_bill {
   qsearchs( 'cust_bill_void', { 'invnum' => $self->invnum } );
 }
 
   qsearchs( 'cust_bill_void', { 'invnum' => $self->invnum } );
 }
 
+sub cust_bill_pkg_fee {
+  my $self = shift;
+  qsearch( 'cust_bill_pkg_fee_void', { 'billpkgnum' => $self->billpkgnum } );
+}
+
+# _upgrade_data
+#
+# Used by FS::Upgrade to migrate to a new database.
+sub _upgrade_data {  # class method
+  my ($class, %opts) = @_;
+
+  my $error;
+  # fix voids with tax from before July 2013, when the taxable_billpkgnum
+  # field was added to the void table
+  local $FS::Record::nowarn_classload = 1;
+  my $search = FS::Cursor->new({
+    'table'   => 'cust_bill_pkg_tax_location_void',
+    'hashref' => { 'taxable_billpkgnum' => '' }
+  });
+  while (my $void = $search->fetch) {
+    # the history for the unvoided record should have the correct
+    # taxable_billpkgnum
+    my $num = $void->billpkgtaxlocationnum;
+    my $unvoid = qsearchs({
+      'table'   => 'h_cust_bill_pkg_tax_location',
+      'hashref' => { 'billpkgtaxlocationnum' => $num },
+      'extra_sql' => ' AND taxable_billpkgnum IS NOT NULL',
+      'order_by' => ' ORDER BY history_date DESC LIMIT 1'
+    });
+    if (!$unvoid) {
+      # should never happen
+      # but should this be fatal? or wait until someone actually tries to
+      # use the record?
+      warn "billpkgtaxlocationnum $num: could not find pre-void history record to restore taxable_billpkgnum.";
+    }
+    if ($unvoid) {
+      $void->set('taxable_billpkgnum', $unvoid->taxable_billpkgnum);
+      $error = $void->replace;
+      die "billpkgtaxlocationnum $num: $error\n" if $error;
+    }
+  }
+
+}
+
 =back
 
 =head1 BUGS
 =back
 
 =head1 BUGS