[freeside-commits] freeside/bin fs-migrate-cust_tax_exempt, NONE, 1.1

Ivan,,, ivan at wavetail.420.am
Mon Apr 2 18:39:09 PDT 2007


Update of /home/cvs/cvsroot/freeside/bin
In directory wavetail:/tmp/cvs-serv18660

Added Files:
	fs-migrate-cust_tax_exempt 
Log Message:


--- NEW FILE: fs-migrate-cust_tax_exempt ---
#!/usr/bin/perl -w

use strict;
use Time::Local;
use Date::Format;
use Time::Duration;
use FS::UID qw(adminsuidsetup);
use FS::Record qw( qsearch dbh );
use FS::cust_tax_exempt;
#use FS::cust_bill;
use FS::h_cust_bill;
use FS::h_cust_tax_exempt;
use FS::cust_bill_pkg;
use FS::cust_tax_exempt_pkg;
#use Data::Dumper;

my $start = time;

adminsuidsetup shift;

my $fuz = 7; #seconds

 #site-specific rewrites
my %rewrite = (
  #cust_tax_exempt.exemptnum => { 'field' => 'newvalue', ... },
    '23' => { month=>10, year=>2005, invnum=>1640 },

    #etc.
);

my @cust_tax_exempt = qsearch('cust_tax_exempt', {} );
my $num_cust_tax_exempt = scalar(@cust_tax_exempt);
my $num_cust_tax_exempt_migrated = 0;
my $total_cust_tax_exempt_migrated = 0;
my $num_cust_tax_exempt_pkg_migrated = 0;
my $total_cust_tax_exempt_pkg_migrated = 0;

$FS::UID::AutoCommit = 0;

foreach my $cust_tax_exempt ( @cust_tax_exempt ) {

  if ( exists $rewrite{ $cust_tax_exempt->exemptnum } ) {
    my $hashref = $rewrite{ $cust_tax_exempt->exemptnum };
    $cust_tax_exempt->setfield($_, $hashref->{$_})
      foreach keys %$hashref;
  }

  if ( $cust_tax_exempt->year < 1990 ) {
    warn "exemption year is ". $cust_tax_exempt->year.
         "; not migrating exemption ". $cust_tax_exempt->exemptnum. 
         ' for custnum '. $cust_tax_exempt->custnum. "\n\n";
    next;
  }

  # also make sure cust_bill_pkg record dates contain the month/year
#  my $mon  = $cust_tax_exempt->month;
#  my $year = $cust_tax_exempt->year;
#  $mon--;
#  my $edate_after = timelocal(0,0,0,1,$mon,$year);
#  $mon++;
#  if ( $mon >= 12 ) { $mon-=12; $year++ };
#  my $sdate_before = timelocal(0,0,0,1,$mon,$year);

  my $mon  = $cust_tax_exempt->month;
  my $year = $cust_tax_exempt->year;
  if ( $mon >= 12 ) { $mon-=12; $year++ };
  my $sdate_before = timelocal(0,0,0,1,$mon,$year);
  #$mon++;
  #if ( $mon >= 12 ) { $mon-=12; $year++ };
  my $edate_after = timelocal(0,0,0,1,$mon,$year);

  # !! start a transaction?  (yes, its started)

  my @h_cust_tax_exempt = qsearch({
    'table'     => 'h_cust_tax_exempt',
    'hashref'   => { 'exemptnum' => $cust_tax_exempt->exemptnum },
    'extra_sql' => " AND (    history_action = 'insert'
                           OR history_action = 'replace_new' )
                     ORDER BY history_date ASC
                   ",
  });

  my $amount_so_far = 0;
  my $num_cust_tax_exempt_pkg = 0;
  my $total_cust_tax_exempt_pkg = 0;
  H_CUST_TAX_EXEMPT: foreach my $h_cust_tax_exempt ( @h_cust_tax_exempt ) {

    my $amount = sprintf('%.2f', $h_cust_tax_exempt->amount - $amount_so_far );
    $amount_so_far += $amount;

#    print Dumper($h_cust_tax_exempt), "\n";

    #find a matching cust_bill record
    # (print time differences and choose a meaningful threshold, should work)

    my @h_cust_bill = ();
    if ( $cust_tax_exempt->invnum ) {
      #warn "following invnum ". $cust_tax_exempt->invnum.
      #     " kludge for cust_tax_exempt ". $cust_tax_exempt->exemptnum. "\n";

      @h_cust_bill = qsearch({
        #'table'     => 'cust_bill',
        'table'     => 'h_cust_bill',
        'hashref'   => { 'custnum'        => $h_cust_tax_exempt->custnum,
                         'invnum'         => $cust_tax_exempt->invnum,
                         'history_action' => 'insert',
                       },
        #'extra_sql' =>
        #  ' AND history_date <= '. ( $h_cust_tax_exempt->history_date + $fuz ).
        #  ' AND history_date >  '. ( $h_cust_tax_exempt->history_date - $fuz ),
      });

    } else {

      @h_cust_bill = qsearch({
        #'table'     => 'cust_bill',
        'table'     => 'h_cust_bill',
        'hashref'   => { 'custnum'        => $h_cust_tax_exempt->custnum,
                         'history_action' => 'insert',
                       },
        'extra_sql' =>
          ' AND history_date <= '. ( $h_cust_tax_exempt->history_date + $fuz ).
          ' AND history_date >  '. ( $h_cust_tax_exempt->history_date - $fuz ),
      });

    }

    if ( scalar(@h_cust_bill) != 1 ) {
      warn '  '. scalar(@h_cust_bill). ' h_cust_bill records matching '.
           'h_cust_tax_exempt.historynum '. $h_cust_tax_exempt->historynum.
           "; not migrating (adjust fuz factor?)\n";
      next;
    }

    my $h_cust_bill = $h_cust_bill[0];

#    print Dumper(@cust_bill), "\n\n";

    # then find a matching cust_bill_pkg record with part_pkg.taxclass record
    # that matches the one pointed to by cust_tax_exempt.taxnum
    # (hopefully just one, see how many we can match automatically)

    my $cust_main_county = $cust_tax_exempt->cust_main_county;
    my $taxclass = $cust_main_county->taxclass;

    my $hashref = { 
                    'custnum' => $cust_tax_exempt->custnum,
                    'invnum'  => $h_cust_bill->invnum,
                    'pkgnum'  => { op=>'>', value=>0, },
                  };
    unless ( $cust_tax_exempt->invnum ) {
      # also make sure cust_bill_pkg record dates contain the month/year

      #$hashref->{'sdate'} = { op=>'<', value=>$sdate_before };
      $hashref->{'sdate'} = { op=>'<=', value=>$sdate_before };

      #$hashref->{'edate'} = { op=>'>', value=>$edate_after };
      $hashref->{'edate'} = { op=>'>=', value=>$edate_after };
    }

    if ( $cust_tax_exempt->billpkgnum ) {
      $hashref->{'billpkgnum'} = $cust_tax_exempt->billpkgnum;
    }

    my $extra_sql = 'ORDER BY billpkgnum';

    $extra_sql = "AND taxclass = '$taxclass' $extra_sql"
      unless $cust_tax_exempt->ignore_current_taxclass;

    my @cust_bill_pkg = qsearch({
      'select'    => 'cust_bill_pkg.*, part_pkg.freq',
      'table'     => 'cust_bill_pkg',
      'addl_from' => 'LEFT JOIN cust_pkg using ( pkgnum  ) '.
                     'LEFT JOIN part_pkg using ( pkgpart ) ',
      'hashref'   => $hashref,
      'extra_sql' => $extra_sql,
    });

    foreach my $cust_bill_pkg ( @cust_bill_pkg ) {
      $cust_bill_pkg->exemptable_per_month(
        sprintf('%.2f',
          ( $cust_bill_pkg->setup + $cust_bill_pkg->recur )
          /
          ( $cust_bill_pkg[0]->freq || 1 )
        )
      );
    }

    my(@cust_tax_exempt_pkg) = ();
    if ( scalar(@cust_bill_pkg) == 1
         && $cust_bill_pkg[0]->exemptable_per_month >= $amount
       )
    {

      my $cust_bill_pkg = $cust_bill_pkg[0];

      # finally, create an appropriate cust_tax_exempt_pkg record

      push @cust_tax_exempt_pkg, new FS::cust_tax_exempt_pkg {
        'billpkgnum' => $cust_bill_pkg->billpkgnum,
        'taxnum'     => $cust_tax_exempt->taxnum,
        'year'       => $cust_tax_exempt->year,
        'month'      => $cust_tax_exempt->month,
        'amount'     => $amount,
      };

    } else {

#      warn '  '. scalar(@cust_bill_pkg). ' cust_bill_pkg records for invoice '.
#           $h_cust_bill->invnum.
#           "; not migrating h_cust_tax_exempt historynum ".
#           $h_cust_tax_exempt->historynum. " for \$$amount\n";
#      warn "    *** DIFFERENT DATES ***\n"
#        if grep {    $_->sdate != $cust_bill_pkg[0]->sdate
#                  || $_->edate != $cust_bill_pkg[0]->edate
#                } @cust_bill_pkg;
#      foreach ( @cust_bill_pkg ) {
#        warn '    '. $_->billpkgnum. ': '. $_->setup. 's/'. $_->recur.'r'.
#             '  '. time2str('%D', $_->sdate). '-'. time2str('%D', $_->edate).
#             "\n";
#      }
#      
#      next;

      my $remaining = $amount;
      foreach my $cust_bill_pkg ( @cust_bill_pkg ) {
        last unless $remaining;
        my $this_amount =sprintf('%.2f',
          $remaining <= $cust_bill_pkg->exemptable_per_month
            ? $remaining
            : $cust_bill_pkg->exemptable_per_month
        );;

        push @cust_tax_exempt_pkg, new FS::cust_tax_exempt_pkg {
          'billpkgnum' => $cust_bill_pkg->billpkgnum,
          'taxnum'     => $cust_tax_exempt->taxnum,
          'year'       => $cust_tax_exempt->year,
          'month'      => $cust_tax_exempt->month,
          'amount'     => $this_amount,
        };

        $remaining -= $this_amount;

      }

    }

    foreach my $cust_tax_exempt_pkg ( @cust_tax_exempt_pkg ) {
      my $error = $cust_tax_exempt_pkg->insert;
      #my $error = $cust_tax_exempt_pkg->check;
      if ( $error ) {
        warn "*** error inserting cust_tax_exempt_pkg record: $error\n";
        next; #not necessary.. H_CUST_TAX_EXEMPT;

        #not necessary, incorrect $total_cust_tax_exempt_pkg will error it out
        # roll back at least the entire cust_tax_exempt transaction
        # next CUST_TAX_EXEMPT;
      }

      $num_cust_tax_exempt_pkg++;
    
      $total_cust_tax_exempt_pkg += $cust_tax_exempt_pkg->amount;

    }

  }

  $total_cust_tax_exempt_pkg = sprintf('%.2f', $total_cust_tax_exempt_pkg );

  unless ( $total_cust_tax_exempt_pkg == $cust_tax_exempt->amount ) {
    warn "total h_ amount $total_cust_tax_exempt_pkg != cust_tax_exempt.amount ".
         $cust_tax_exempt->amount.
         ";\n not migrating exemption ". $cust_tax_exempt->exemptnum. " for ".
         $cust_tax_exempt->month. '/'. $cust_tax_exempt->year.
         ' (custnum '. $cust_tax_exempt->custnum. ") ".
         #"\n  (sdate < ". time2str('%D', $sdate_before ).
         "\n  (sdate <= ". time2str('%D', $sdate_before ). " [$sdate_before]".
           #' / edate > '. time2str('%D', $edate_after  ). ')'.
           ' / edate >= '. time2str('%D', $edate_after  ). " [$edate_after])".
         "\n\n";

    # roll back at least the entire cust_tax_exempt transaction
    dbh->rollback;

    # next CUST_TAX_EXEMPT;
    next;
  }

  # remove the cust_tax_exempt record
  my $error = $cust_tax_exempt->delete;
  if ( $error ) {
    #roll back at least the entire cust_tax_exempt transaction
    dbh->rollback;

    #next CUST_TAX_EXEMPT;
    next;
  }

  $num_cust_tax_exempt_migrated++;
  $total_cust_tax_exempt_migrated += $cust_tax_exempt->amount;

  $num_cust_tax_exempt_pkg_migrated += $num_cust_tax_exempt_pkg;
  $total_cust_tax_exempt_pkg_migrated += $total_cust_tax_exempt_pkg;

  # commit the transaction
  dbh->commit;

}

$total_cust_tax_exempt_migrated = 
  sprintf('%.2f', $total_cust_tax_exempt_migrated );
$total_cust_tax_exempt_pkg_migrated = 
  sprintf('%.2f', $total_cust_tax_exempt_pkg_migrated );

warn
  "$num_cust_tax_exempt_migrated / $num_cust_tax_exempt (".
  sprintf('%.2f', 100 * $num_cust_tax_exempt_migrated / $num_cust_tax_exempt).
  '%) cust_tax_exempt records migrated ($'. $total_cust_tax_exempt_migrated.
  ")\n to $num_cust_tax_exempt_pkg_migrated cust_tax_exempt_pkg records".
  ' ($'. $total_cust_tax_exempt_pkg_migrated. ')'.
  "\n in ". duration(time-$start). "\n"
;




More information about the freeside-commits mailing list