fix bug that charged full amounts of all open invoices as soon as balance went positi...
[freeside.git] / FS / FS / cust_main.pm
index 0ab2aa5..41bfa58 100644 (file)
@@ -41,7 +41,7 @@ use FS::Msgcat qw(gettext);
 
 $realtime_bop_decline_quiet = 0;
 
-$Debug = 1;
+$Debug = 0;
 #$Debug = 1;
 
 $import = 0;
@@ -294,8 +294,8 @@ sub insert {
   }
 
   # packages
-  local $FS::svc_Common::noexport_hack = 1 if $options{'noexport'};
-  $error = $self->order_pkgs($cust_pkgs, \$seconds);
+  #local $FS::svc_Common::noexport_hack = 1 if $options{'noexport'};
+  $error = $self->order_pkgs($cust_pkgs, \$seconds, %options);
   if ( $error ) {
     $dbh->rollback if $oldAutoCommit;
     return $error;
@@ -329,9 +329,27 @@ sub insert {
 
 }
 
-=item order_pkgs
+=item order_pkgs HASHREF, [ , OPTION => VALUE ... ] ]
+
+Like the insert method on an existing record, this method orders a package
+and included services atomicaly.  Pass a Tie::RefHash data structure to this
+method containing FS::cust_pkg and FS::svc_I<tablename> objects.  There should
+be a better explanation of this, but until then, here's an example:
+
+  use Tie::RefHash;
+  tie %hash, 'Tie::RefHash'; #this part is important
+  %hash = (
+    $cust_pkg => [ $svc_acct ],
+    ...
+  );
+  $cust_main->order_pkgs( \%hash, 'noexport'=>1 );
+
+Currently available options are: I<noexport>
 
-document me.  like ->insert(%cust_pkg) on an existing record
+If I<noexport> is set true, no provisioning jobs (exports) are scheduled.
+(You can schedule them later with the B<reexport> method for each
+cust_pkg object.  Using the B<reexport> method on the cust_main object is not
+recommended, as existing services will also be reexported.)
 
 =cut
 
@@ -339,6 +357,7 @@ sub order_pkgs {
   my $self = shift;
   my $cust_pkgs = shift;
   my $seconds = shift;
+  my %options = @_;
 
   local $SIG{HUP} = 'IGNORE';
   local $SIG{INT} = 'IGNORE';
@@ -351,6 +370,8 @@ sub order_pkgs {
   local $FS::UID::AutoCommit = 0;
   my $dbh = dbh;
 
+  local $FS::svc_Common::noexport_hack = 1 if $options{'noexport'};
+
   foreach my $cust_pkg ( keys %$cust_pkgs ) {
     $cust_pkg->custnum( $self->custnum );
     my $error = $cust_pkg->insert;
@@ -379,9 +400,9 @@ sub order_pkgs {
 
 =item reexport
 
-document me.  Re-schedules all exports by calling the B<reexport> method
-of all associated packages (see L<FS::cust_pkg>).  If there is an error,
-returns the error; otherwise returns false.
+Re-schedules all exports by calling the B<reexport> method of all associated
+packages (see L<FS::cust_pkg>).  If there is an error, returns the error;
+otherwise returns false.
 
 =cut
 
@@ -872,7 +893,7 @@ sub check {
   $self->tax =~ /^(Y?)$/ or return "Illegal tax: ". $self->tax;
   $self->tax($1);
 
-  $self->otaker(getotaker);
+  $self->otaker(getotaker) unless $self->otaker;
 
   #warn "AFTER: \n". $self->_dump;
 
@@ -1460,24 +1481,15 @@ sub collect {
     }
   }
 
-  foreach my $cust_bill ( $self->cust_bill ) {
-
-    #this has to be before next's
-    my $amount = sprintf( "%.2f", $balance < $cust_bill->owed
-                                  ? $balance
-                                  : $cust_bill->owed
-    );
-    $balance = sprintf( "%.2f", $balance - $amount );
-
-    next unless $cust_bill->owed > 0;
+  foreach my $cust_bill ( $self->open_cust_bill ) {
 
     # don't try to charge for the same invoice if it's already in a batch
     #next if qsearchs( 'cust_pay_batch', { 'invnum' => $cust_bill->invnum } );
 
-    warn "invnum ". $cust_bill->invnum. " (owed ". $cust_bill->owed. ", amount $amount, balance $balance)" if $Debug;
-
-    next unless $amount > 0;
+    last if $self->balance <= 0;
 
+    warn "invnum ". $cust_bill->invnum. " (owed ". $cust_bill->owed. ")"
+      if $Debug;
 
     foreach my $part_bill_event (
       sort {    $a->seconds   <=> $b->seconds
@@ -1494,7 +1506,8 @@ sub collect {
                                        'disabled' => '',           } )
     ) {
 
-      last unless $cust_bill->owed > 0; #don't run subsequent events if owed=0
+      last if $cust_bill->owed <= 0  # don't run subsequent events if owed<=0
+           || $self->balance   <= 0; # or if balance<=0
 
       warn "calling invoice event (". $part_bill_event->eventcode. ")\n"
         if $Debug;
@@ -1791,6 +1804,7 @@ sub realtime_bop {
   # (though that probably violates cardholder agreements)
   if ( defined $self->dbdef_table->column('paycvv')
        && length($self->paycvv)
+       && ! grep { $_ eq cardtype($self->payinfo) } $conf->config('cvv-save')
   ) {
     my $new = new FS::cust_main { $self->hash };
     $new->paycvv('');