fix perf edge case with multiple large packages not just one, RT#26097
[freeside.git] / FS / FS / cust_main / Packages.pm
index 4b44fdd..3c96fc7 100644 (file)
@@ -57,7 +57,7 @@ action completes (such as running the customer's credit card successfully).
 
 Optional subject for a ticket created and attached to this customer
 
-=item ticket_subject
+=item ticket_queue
 
 Optional queue name for ticket additions
 
@@ -333,8 +333,8 @@ sub sort_packages {
     return 0  if !$a_num_cust_svc && !$b_num_cust_svc;
     return -1 if  $a_num_cust_svc && !$b_num_cust_svc;
     return 1  if !$a_num_cust_svc &&  $b_num_cust_svc;
-    my @a_cust_svc = $a->cust_svc;
-    my @b_cust_svc = $b->cust_svc;
+    my @a_cust_svc = $a->cust_svc_unsorted;
+    my @b_cust_svc = $b->cust_svc_unsorted;
     return 0  if !scalar(@a_cust_svc) && !scalar(@b_cust_svc);
     return -1 if  scalar(@a_cust_svc) && !scalar(@b_cust_svc);
     return 1  if !scalar(@a_cust_svc) &&  scalar(@b_cust_svc);
@@ -351,6 +351,7 @@ Returns all suspended packages (see L<FS::cust_pkg>) for this customer.
 
 sub suspended_pkgs {
   my $self = shift;
+  return $self->num_suspended_pkgs unless wantarray;
   grep { $_->susp } $self->ncancelled_pkgs;
 }
 
@@ -377,6 +378,7 @@ this customer.
 
 sub unsuspended_pkgs {
   my $self = shift;
+  return $self->num_unsuspended_pkgs unless wantarray;
   grep { ! $_->susp } $self->ncancelled_pkgs;
 }
 
@@ -395,16 +397,36 @@ sub active_pkgs {
        $self->unsuspended_pkgs;
 }
 
+=item billing_pkgs
+
+Returns active packages, and also any suspended packages which are set to
+continue billing while suspended.
+
+=cut
+
+sub billing_pkgs {
+  my $self = shift;
+  grep { my $part_pkg = $_->part_pkg;
+         $part_pkg->freq ne '' && $part_pkg->freq ne '0'
+           && ( ! $_->susp || $_->option('suspend_bill',1)
+                           || ( $part_pkg->option('suspend_bill', 1)
+                                  && ! $_->option('no_suspend_bill',1)
+                              )
+              );
+       }
+       $self->ncancelled_pkgs;
+}
+
 =item next_bill_date
 
 Returns the next date this customer will be billed, as a UNIX timestamp, or
-undef if no active package has a next bill date.
+undef if no billing package has a next bill date.
 
 =cut
 
 sub next_bill_date {
   my $self = shift;
-  min( map $_->get('bill'), grep $_->get('bill'), $self->active_pkgs );
+  min( map $_->get('bill'), grep $_->get('bill'), $self->billing_pkgs );
 }
 
 =item num_cancelled_pkgs
@@ -422,6 +444,16 @@ sub num_ncancelled_pkgs {
   shift->num_pkgs("( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )");
 }
 
+sub num_suspended_pkgs {
+  shift->num_pkgs("     ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
+                    AND cust_pkg.susp IS NOT NULL AND cust_pkg.susp != 0   ");
+}
+
+sub num_unsuspended_pkgs {
+  shift->num_pkgs("     ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
+                    AND ( cust_pkg.susp   IS NULL OR cust_pkg.susp   = 0 ) ");
+}
+
 sub num_pkgs {
   my( $self ) = shift;
   my $sql = scalar(@_) ? shift : '';