optimize invoice rendering with lots of CDRs, RT#15155
[freeside.git] / FS / FS / cust_bill_pkg.pm
index c9b0a4d..9cc6e7c 100644 (file)
@@ -146,18 +146,29 @@ sub insert {
 
   if ( $self->get('details') ) {
     foreach my $detail ( @{$self->get('details')} ) {
-      my $cust_bill_pkg_detail = new FS::cust_bill_pkg_detail {
-        'billpkgnum' => $self->billpkgnum,
-        'format'     => (ref($detail) ? $detail->[0] : '' ),
-        'detail'     => (ref($detail) ? $detail->[1] : $detail ),
-        'amount'     => (ref($detail) ? $detail->[2] : '' ),
-        'classnum'   => (ref($detail) ? $detail->[3] : '' ),
-        'phonenum'   => (ref($detail) ? $detail->[4] : '' ),
-        'accountcode' => (ref($detail) ? $detail->[5] : '' ),
-        'startdate'  => (ref($detail) ? $detail->[6] : '' ),
-        'duration'   => (ref($detail) ? $detail->[7] : '' ),
-        'regionname' => (ref($detail) ? $detail->[8] : '' ),
-      };
+      my %hash = ();
+      if ( ref($detail) ) {
+        if ( ref($detail) eq 'ARRAY' ) {
+          #carp "this way sucks, use a hash"; #but more useful/friendly
+          $hash{'format'}      = $detail->[0];
+          $hash{'detail'}      = $detail->[1];
+          $hash{'amount'}      = $detail->[2];
+          $hash{'classnum'}    = $detail->[3];
+          $hash{'phonenum'}    = $detail->[4];
+          $hash{'accountcode'} = $detail->[5];
+          $hash{'startdate'}   = $detail->[6];
+          $hash{'duration'}    = $detail->[7];
+          $hash{'regionname'}  = $detail->[8];
+        } elsif ( ref($detail) eq 'HASH' ) {
+          %hash = %$detail;
+        } else {
+          die "unknow detail type ". ref($detail);
+        }
+      } else {
+        $hash{'detail'} = $detail;
+      }
+      $hash{'billpkgnum'} = $self->billpkgnum;
+      my $cust_bill_pkg_detail = new FS::cust_bill_pkg_detail \%hash;
       $error = $cust_bill_pkg_detail->insert;
       if ( $error ) {
         $dbh->rollback if $oldAutoCommit;
@@ -815,27 +826,42 @@ usage.
 sub usage {
   my( $self, $classnum ) = @_;
   my $sum = 0;
-  my @values = ();
 
   if ( $self->get('details') ) {
 
-    @values = 
-      map { $_->[2] }
-      grep { ref($_) && ( defined($classnum) ? $_->[3] eq $classnum : 1 ) }
-      @{ $self->get('details') };
+    foreach my $value (
+      map { ref($_) eq 'HASH'
+              ? $_->{'amount'}
+              : $_->[2] 
+          }
+      grep { ref($_) && ( defined($classnum)
+                            ? $classnum eq ( ref($_) eq 'HASH'
+                                               ? $_->{'classnum'}
+                                               : $_->[3]
+                                           )
+                            : 1
+                        )
+           }
+      @{ $self->get('details') }
+    ) {
+      $sum += $value if $value;
+    }
 
-  }else{
+    return $sum;
 
-    my $hashref = { 'billpkgnum' => $self->billpkgnum };
-    $hashref->{ 'classnum' } = $classnum if defined($classnum);
-    @values = map { $_->amount } qsearch('cust_bill_pkg_detail', $hashref);
+  } else {
 
-  }
+    my $sql = 'SELECT SUM(COALESCE(amount,0)) FROM cust_bill_pkg_detail '.
+              ' WHERE billpkgnum = '. $self->billpkgnum;
+    $sql .= " AND classnum = $classnum" if defined($classnum);
+
+    my $sth = dbh->prepare($sql) or die dbh->errstr;
+    $sth->execute or die $sth->errstr;
+
+    return $sth->fetchrow_arrayref->[0];
 
-  foreach ( @values ) {
-    $sum += $_ if $_;
   }
-  $sum;
+
 }
 
 =item usage_classes
@@ -852,11 +878,14 @@ sub usage_classes {
 
     my %seen = ();
     foreach my $detail ( grep { ref($_) } @{$self->get('details')} ) {
-      $seen{ $detail->[3] } = 1;
+      $seen{ ref($detail) eq 'HASH'
+               ? $detail->{'classnum'}
+               : $detail->[3]
+           } = 1;
     }
     keys %seen;
 
-  }else{
+  } else {
 
     map { $_->classnum }
         qsearch({ table   => 'cust_bill_pkg_detail',