bulk credit import, RT#26319
[freeside.git] / FS / FS / cust_credit.pm
index 4553aff..24f7134 100644 (file)
@@ -717,6 +717,7 @@ sub credit_lineitems {
   my %cust_credit_bill = ();
   my %cust_bill_pkg = ();
   my %cust_credit_bill_pkg = ();
+  my %unapplied_payments = (); #invoice numbers, and then billpaynums
   foreach my $billpkgnum ( @{$arg{billpkgnums}} ) {
     my $setuprecur = shift @{$arg{setuprecurs}};
     my $amount = shift @{$arg{amounts}};
@@ -744,7 +745,6 @@ sub credit_lineitems {
 
     push @{$cust_bill_pkg{$invnum}}, $cust_bill_pkg;
 
-    my %unapplied_payments; # billpaynum => amount
     #unapply any payments applied to this line item (other credits too?)
     foreach my $cust_bill_pay_pkg ( $cust_bill_pkg->cust_bill_pay_pkg($setuprecur) ) {
       $error = $cust_bill_pay_pkg->delete;
@@ -752,28 +752,9 @@ sub credit_lineitems {
         $dbh->rollback if $oldAutoCommit;
         return "Error unapplying payment: $error";
       }
-      $unapplied_payments{$cust_bill_pay_pkg->billpaynum}
+      $unapplied_payments{$invnum}{$cust_bill_pay_pkg->billpaynum}
         += $cust_bill_pay_pkg->amount;
     }
-    # also unapply that amount from the invoice so it doesn't screw up 
-    # application of the credit
-    foreach my $billpaynum (keys %unapplied_payments) {
-      my $cust_bill_pay = FS::cust_bill_pay->by_key($billpaynum)
-        or die "broken payment application $billpaynum";
-      $cust_bill_pay->set('amount',
-        sprintf('%.2f',
-          $cust_bill_pay->get('amount') - $unapplied_payments{$billpaynum})
-      );
-      if ( $cust_bill_pay->amount >= 0.005 ) {
-        $error = $cust_bill_pay->replace;
-      } else {
-        $error = $cust_bill_pay->delete;
-      }
-      if ( $error ) {
-        $dbh->rollback if $oldAutoCommit;
-        return "Error unapplying payment: $error";
-      }
-    }
 
     #$subtotal += $amount;
     $cust_credit_bill{$invnum} += $amount;
@@ -921,11 +902,57 @@ sub credit_lineitems {
             };
 
         } # if $amount > 0
+
+        #unapply any payments applied to the tax
+        foreach my $cust_bill_pay_pkg 
+          ( $tax_cust_bill_pkg->cust_bill_pay_pkg('setup') )
+        {
+          $error = $cust_bill_pay_pkg->delete;
+          if ( $error ) {
+            $dbh->rollback if $oldAutoCommit;
+            return "Error unapplying payment: $error";
+          }
+          $unapplied_payments{$invnum}{$cust_bill_pay_pkg->billpaynum}
+            += $cust_bill_pay_pkg->amount;
+        }
       } #foreach $taxline
 
     } # if @{ $cust_bill_pkg{$invnum} }
 
-    #insert cust_credit_bill
+    # if we unapplied any payments from line items, also unapply that
+    # amount from the invoice
+    foreach my $billpaynum (keys %{$unapplied_payments{$invnum}}) {
+      my $cust_bill_pay = FS::cust_bill_pay->by_key($billpaynum)
+        or die "broken payment application $billpaynum";
+      my @subapps = $cust_bill_pay->lineitem_applications;
+      $error = $cust_bill_pay->delete; # can't replace
+
+      my $new_cust_bill_pay = FS::cust_bill_pay->new({
+          $cust_bill_pay->hash,
+          billpaynum => '',
+          amount => sprintf('%.2f',
+              $cust_bill_pay->get('amount')
+              - $unapplied_payments{$invnum}{$billpaynum})
+      });
+
+      if ( $new_cust_bill_pay->amount > 0 ) {
+        $error ||= $new_cust_bill_pay->insert;
+        # Also reapply it to everything it was applied to before.
+        # Note that we've already deleted cust_bill_pay_pkg records for the
+        # items we're crediting, so they aren't on this list.
+        foreach my $cust_bill_pay_pkg (@subapps) {
+          $cust_bill_pay_pkg->billpaypkgnum('');
+          $cust_bill_pay_pkg->billpaynum($new_cust_bill_pay->billpaynum);
+          $error ||= $cust_bill_pay_pkg->insert;
+        }
+      }
+      if ( $error ) {
+        $dbh->rollback if $oldAutoCommit;
+        return "Error unapplying payment: $error";
+      }
+    }
+
+    #NOW insert cust_credit_bill
 
     my $cust_credit_bill = new FS::cust_credit_bill {
       'crednum' => $cust_credit->crednum,
@@ -958,6 +985,58 @@ sub credit_lineitems {
 
 =back
 
+=head1 SUBROUTINES
+
+=over 4
+
+=item process_batch_import
+
+=cut
+
+use List::Util qw( min );
+use FS::cust_bill;
+use FS::cust_credit_bill;
+sub process_batch_import {
+  my $job = shift;
+
+  my $opt = { 'table'   => 'cust_credit',
+              'params'  => [ 'credbatch' ],
+              'formats' => { 'simple' =>
+                               [ 'custnum', 'amount', 'reasonnum', 'invnum' ],
+                           },
+              'default_csv' => 1,
+              'postinsert_callback' => sub {
+                my $cust_credit = shift; #my ($cust_credit, $param ) = @_;
+
+                if ( $cust_credit->invnum ) {
+
+                  my $cust_bill = qsearchs('cust_bill', { invnum=>$cust_credit->invnum } );
+                  my $amount = min( $cust_credit->credited, $cust_bill->owed );
+    
+                  my $cust_credit_bill = new FS::cust_credit_bill ( {
+                    'crednum' => $cust_credit->crednum,
+                    'invnum'  => $cust_bill->invnum,
+                    'amount'  => $amount,
+                  } );
+                  my $error = $cust_credit_bill->insert;
+                  return '' unless $error;
+
+                }
+
+                #apply_payments_and_credits ?
+                $cust_credit->cust_main->apply_credits;
+
+                return '';
+
+              },
+            };
+
+  FS::Record::process_batch_import( $job, $opt, @_ );
+
+}
+
+=back
+
 =head1 BUGS
 
 The delete method.  The replace method.