reduce memory usage of voip_tiered, RT#14903
authorivan <ivan>
Fri, 18 Nov 2011 00:09:52 +0000 (00:09 +0000)
committerivan <ivan>
Fri, 18 Nov 2011 00:09:52 +0000 (00:09 +0000)
FS/FS/cdr.pm
FS/FS/cdr_termination.pm
FS/FS/part_pkg/voip_tiered.pm
FS/FS/svc_phone.pm

index 850f797..1507dde 100644 (file)
@@ -130,9 +130,9 @@ following fields are currently supported:
 
 =item svcnum - Link to customer service (see L<FS::cust_svc>)
 
-=item freesidestatus - NULL, done (or something)
+=item freesidestatus - NULL, processing-tiered, done
 
-=item freesiderewritestatus - NULL, done (or something)
+=item freesiderewritestatus - NULL, done, skipped
 
 =item cdrbatch
 
@@ -404,10 +404,7 @@ sub set_status_and_rated_price {
 
   if ($opt{'inbound'}) {
 
-    my $term = qsearchs('cdr_termination', {
-        acctid   => $self->acctid, 
-        termpart => 1 # inbound
-    });
+    my $term = $self->cdr_termination( 1 ); #1: inbound
     my $error;
     if ( $term ) {
       warn "replacing existing cdr status (".$self->acctid.")\n" if $term;
@@ -419,10 +416,10 @@ sub set_status_and_rated_price {
         termpart    => 1,
         rated_price => $rated_price,
         status      => $status,
-        svcnum      => $svcnum,
     });
     $term->rated_seconds($opt{rated_seconds}) if exists($opt{rated_seconds});
     $term->rated_minutes($opt{rated_minutes}) if exists($opt{rated_minutes});
+    $term->svcnum($svcnum) if $svcnum;
     return $term->insert;
 
   } else {
@@ -437,6 +434,29 @@ sub set_status_and_rated_price {
   }
 }
 
+=item cdr_termination [ TERMPART ]
+
+=cut
+
+sub cdr_termination {
+  my $self = shift;
+
+  if ( scalar(@_) && $_[0] ) {
+    my $termpart = shift;
+
+    qsearchs('cdr_termination', { acctid   => $self->acctid,
+                                  termpart => $termpart,
+                                }
+            );
+
+  } else {
+
+    qsearch('cdr_termination', { acctid => $self->acctid, } );
+
+  }
+
+}
+
 =item calldate_unix 
 
 Parses the calldate in SQL string format and returns a UNIX timestamp.
@@ -753,14 +773,13 @@ sub clear_status {
     return $error;
   } 
 
-  my @cdr_termination = qsearch('cdr_termination', 
-                               { 'acctid' => $self->acctid } );
-  foreach my $cdr_termination ( @cdr_termination ) {
-      $cdr_termination->status('');
-      $error = $cdr_termination->replace;
+  foreach my $cdr_termination ( $self->cdr_termination ) {
+      #$cdr_termination->status('');
+      #$error = $cdr_termination->replace;
+      $error = $cdr_termination->delete;
       if ( $error ) {
-       $dbh->rollback if $oldAutoCommit;
-       return $error;
+        $dbh->rollback if $oldAutoCommit;
+        return $error;
       } 
   }
   
index 5e30805..0209f0d 100644 (file)
@@ -119,8 +119,8 @@ sub check {
     || $self->ut_foreign_key('acctid', 'cdr', 'acctid')
     #|| $self->ut_foreign_key('termpart', 'part_termination', 'termpart')
     || $self->ut_number('termpart')
-    || $self->ut_float('rated_price')
-    || $self->ut_enum('status', [ '', 'done' ] ) # , 'skipped' ] )
+    || $self->ut_floatn('rated_price')
+    || $self->ut_enum('status', [ '', 'processing-tiered', 'done' ] ) # , 'skipped' ] )
   ;
   return $error if $error;
 
index 29e60d4..1ed2450 100644 (file)
@@ -107,7 +107,6 @@ sub calc_usage {
   # pass one: find the total minutes/calls and store the CDRs
   ###
   my $total = 0;
-  my @cdrs = ();
 
   my @cust_svc;
   if( $self->option('bill_inactive_svcs',1) ) {
@@ -161,11 +160,16 @@ sub calc_usage {
            $included_min = 0;
         }
 
-        $cdr->tmp_inout( $pass );
-        $cdr->tmp_rated_seconds( $seconds );
-        $cdr->tmp_rated_minutes( $charge_min );
-        $cdr->tmp_svcnum( $cust_svc->svcnum );
-        push @cdrs, $cdr;
+        my $error = $cdr->set_status_and_rated_price(
+          'processing-tiered',
+          '', #charge,
+          $cust_svc->svcnum,
+          'inbound'       => ($pass eq 'inbound'),
+          'rated_minutes' => $charge_min,
+          'rated_seconds' => $seconds,
+        );
+        die $error if $error;
+
         $total += $charge_min;
 
       } # $cdr
@@ -191,55 +195,79 @@ sub calc_usage {
   my $charges = 0;
   my @invoice_details_sort;
 
-  foreach my $cdr (@cdrs) {
-
-    my $charge_min = $cdr->tmp_rated_minutes;
-
-    my $charge = sprintf('%.4f', ( $min_charge * $charge_min )
-                                 + 0.0000000001 ); #so 1.00005 rounds to 1.0001
-
-
-    if ( $charge > 0 ) {
-      $charges += $charge;
-
-      my $detail = 
-        $cdr->downstream_csv( 'format'  => $output_format,
-                              'charge'  => $charge,
-                              'seconds' => ($use_duration ? 
-                                              $cdr->duration : 
-                                              $cdr->billsec),
-                              'granularity' => $granularity,
-                            );
-
-      my $call_details =
-        { format      => 'C',
-          detail      => $detail,
-          amount      => $charge,
-          #classnum    => $cdr->calltypenum, #classnum
-          #phonenum    => $phonenum, #XXX need this to sort on them
-          accountcode => $cdr->accountcode,
-          startdate   => $cdr->startdate,
-          duration    => $cdr->tmp_rated_seconds,
-        };
-
-       #warn "  adding details on charge to invoice: [ ".
-      #    join(', ', @{$call_details} ). " ]"
-      #  if ( $DEBUG && ref($call_details) );
-      push @invoice_details_sort, [ $call_details, $cdr->calldate_unix ];
+  $options{'status'} = 'processing-tiered';
+
+  foreach my $cust_svc (@cust_svc) {
+
+    my $svc_x;
+    if( $self->option('bill_inactive_svcs',1) ) {
+      $svc_x = $cust_svc->h_svc_x($$sdate, $last_bill);
+    }
+    else {
+      $svc_x = $cust_svc->svc_x;
     }
 
-    my $error = $cdr->set_status_and_rated_price(
-      'done',
-      $charge,
-      $cdr->tmp_svcnum,
-      'inbound'       => ($cdr->tmp_inout eq 'inbound'),
-      'rated_minutes' => $charge_min,
-      'rated_seconds' => $cdr->tmp_rated_seconds,
-    );
-    die $error if $error;
+    foreach my $pass (split('_', $cdr_inout)) {
 
+      $options{'inbound'} = ( $pass eq 'inbound' );
 
-  }
+      foreach my $cdr (
+        $svc_x->get_cdrs( %options )
+      ) {
+
+        my $object = $options{'inbound'}
+                       ? $cdr->cdr_termination( 1 ) #1: inbound
+                       : $cdr;
+
+        my $charge_min = $object->rated_minutes;
+
+        my $charge = sprintf('%.4f', ( $min_charge * $charge_min )
+                                     + 0.0000000001 ); #so 1.00005 rounds to 1.0001
+
+        if ( $charge > 0 ) {
+          $charges += $charge;
+
+          my $detail = 
+            $cdr->downstream_csv( 'format'  => $output_format,
+                                  'charge'  => $charge,
+                                  'seconds' => ($use_duration ? 
+                                                  $cdr->duration : 
+                                                  $cdr->billsec),
+                                  'granularity' => $granularity,
+                                );
+
+          my $call_details =
+            { format      => 'C',
+              detail      => $detail,
+              amount      => $charge,
+              #classnum    => $cdr->calltypenum, #classnum
+              #phonenum    => $phonenum, #XXX need this to sort on them
+              accountcode => $cdr->accountcode,
+              startdate   => $cdr->startdate,
+              duration    => $object->rated_seconds,
+            };
+
+           #warn "  adding details on charge to invoice: [ ".
+          #    join(', ', @{$call_details} ). " ]"
+          #  if ( $DEBUG && ref($call_details) );
+          push @invoice_details_sort, [ $call_details, $cdr->calldate_unix ];
+        }
+
+        my $error = $cdr->set_status_and_rated_price(
+          'done',
+          $charge,
+          $cust_svc->svcnum,
+          'inbound'       => $options{'inbound'},
+          'rated_minutes' => $charge_min,
+          'rated_seconds' => $object->rated_seconds,
+        );
+        die $error if $error;
+
+      } # $cdr
+
+    } # $pass
+
+  } # $cust_svc
 
   my @sorted_invoice_details = sort { ${$a}[1] <=> ${$b}[1] } @invoice_details_sort;
   foreach my $sorted_call_detail ( @sorted_invoice_details ) {
index 4945391..e3d18e0 100644 (file)
@@ -650,7 +650,7 @@ Accepts the following options:
 
 =item for_update => 1: SELECT the CDRs "FOR UPDATE".
 
-=item status => "" (or "done"): Return only CDRs with that processing status.
+=item status => "" (or "processing-tiered", "done"): Return only CDRs with that processing status.
 
 =item inbound => 1: Return CDRs for inbound calls.  With "status", will filter 
 on inbound processing status.
@@ -673,25 +673,24 @@ sub get_cdrs {
   my @where;
 
   if ( $options{'inbound'} ) {
+
     @fields = ( 'dst' );
     if ( exists($options{'status'}) ) {
-      # must be 'done' or ''
-      my $sq = 'EXISTS ( SELECT 1 FROM cdr_termination '.
-        'WHERE cdr.acctid = cdr_termination.acctid '.
-        'AND cdr_termination.status = \'done\' '.
-        'AND cdr_termination.termpart = 1 )';
-      if ( $options{'status'} eq 'done' ) {
-        push @where, $sq;
-      }
-      elsif ($options{'status'} eq '' ) {
-        push @where, "NOT $sq";
-      }
-      else {
-        warn "invalid status: $options{'status'} (ignored)\n";
+      my $status = $options{'status'};
+      if ( $status ) {
+        push @where, 'EXISTS ( SELECT 1 FROM cdr_termination '.
+          'WHERE cdr.acctid = cdr_termination.acctid '.
+          "AND cdr_termination.status = '$status' ". #quoting kludge
+          'AND cdr_termination.termpart = 1 )';
+      } else {
+        push @where, 'NOT EXISTS ( SELECT 1 FROM cdr_termination '.
+          'WHERE cdr.acctid = cdr_termination.acctid '.
+          'AND cdr_termination.termpart = 1 )';
       }
     }
-  }
-  else {
+
+  } else {
+
     @fields = ( 'charged_party' );
     push @fields, 'src' if !$options{'disable_src'};
     $hash{'freesidestatus'} = $options{'status'}