optimizations for large package lists, RT#28526
[freeside.git] / httemplate / view / cust_main / packages.html
index 546dd89..500632d 100755 (executable)
@@ -3,7 +3,6 @@ td.package {
   vertical-align: top;
   border-width: 0;
   border-style: solid;
-  border-color: #bbbbff;
 }
 table.package {
   border: none;
@@ -24,7 +23,10 @@ table.usage {
 .row1 { background-color: #ffffff; }
 
 </STYLE>
-% my $s = 0;
+
+% unless ( $opt{no_links} ) {
+
+%   my $s = 0;
 
 % if ( $curuser->access_right('Qualify service') ) { 
   <% $s++ ? ' | ' : '' %>
@@ -43,21 +45,33 @@ table.usage {
   <& one_time_charge_link.html, $cust_main &>
 % } 
 
+% if ( $curuser->access_right('Bulk move customer services') ) { 
+  <% $s++ ? ' | ' : '' %>
+
+  <& /elements/popup_link-cust_main.html,
+               'label'       => emt('Move services between packages'),
+               'action'      => "${p}edit/bulk-cust_svc-pkgnum.html",
+               'cust_main'   => $cust_main,
+               'actionlabel' => emt('Move services'),
+               'width'       => 968, #763,
+               'height'      => 575,
+  &>
+
+% } 
+
 % if ( $curuser->access_right('Bulk change customer packages') ) { 
   <% $s++ ? ' | ' : '' %>
-  <A HREF="<% $p %>edit/cust_pkg.cgi?<% $cust_main->custnum %>"><% mt('Bulk order and cancel packages') |h %></A> (<% mt('preserves services') |h %>)
+  <A HREF="<% $p %>edit/cust_pkg.cgi?<% $cust_main->custnum %>"><% mt('Bulk order and cancel packages') |h %></A>
 % } 
 
 <BR><BR>
 
+% } # unless $opt{no_links}
+
 <TABLE>
   <TR>
     <TD ALIGN="left" VALIGN="top">
 
-% if ( @$packages ) {
-
-<% mt('Current packages') |h %> 
-% } 
 % if ( $cust_main->num_cancelled_pkgs ) {
 %     if ( $cgi->param('showcancelledpackages') eq '0' #see if it was set by me
 %          || ( $conf->exists('hidecancelledpackages')
@@ -86,6 +100,9 @@ table.usage {
 % }
 
     </TD>
+
+%   unless ( $opt{no_links} ) {
+
     <TD ALIGN="right">
       <A HREF="<%$p%>search/report_cust_pkg.html?custnum=<% $cust_main->custnum %>"><% mt('Package reports') |h %></A>
 % if ( $curuser->access_right('Qualify service') ) { 
@@ -97,25 +114,25 @@ table.usage {
       <% mt('Usage reports:') |h %> 
         <A HREF="<%$p%>search/report_cdr.html?custnum=<% $cust_main->custnum %>"><% mt('CDRs') |h %></A>
     </TD>
+
+%   } # unless $opt{no_links}
+
   </TR>
 
   <TR>
     <TD COLSPAN=2>
-% if ( $conf->exists('cust_pkg-group_by_location') ) {
-<& locations.html,
-    'cust_main'     => $cust_main,
-    'packages'      => $packages,
- &>
-% }
-% else {
-% # in this format, put all packages in one section
-<& /elements/table-grid.html &>
-<& packages/section.html,
-    'cust_main'     => $cust_main,
-    'packages'      => $packages,
- &>
-</TABLE>
-% }
+
+%     $opt{cust_main} = $cust_main;
+%     $opt{packages}  = $packages;
+%     $opt{cust_location_cache} = {};
+%     if ( $conf->exists('cust_pkg-group_by_location') ) {
+        <& locations.html, %opt &>
+%     } else { # in this format, put all packages in one section
+        <& /elements/table-grid.html &>
+        <& packages/section.html, %opt &>
+        </TABLE>
+%     }
+
     </TD>
   </TR>
 
@@ -161,7 +178,10 @@ sub get_packages {
     join(', ', map { "cust_pkg.$_ AS $_"          } fields('cust_pkg') );
 
   my $part_pkg_fields =
-    join(', ', map { "part_pkg.$_ AS part_pkg_$_" } fields('part_pkg') );
+  join(', ', ( map { "part_pkg.$_ AS part_pkg_$_" } fields('part_pkg') ),
+             'setup_option.optionvalue AS part_pkg__setup_fee',
+             'recur_option.optionvalue AS part_pkg__recur_fee',
+      );
 
   my $group_by =
     join(', ', map "cust_pkg.$_", fields('cust_pkg') ). ', '.
@@ -172,15 +192,42 @@ sub get_packages {
 
   my @packages = $cust_main->$method( {
     'select'    => "$cust_pkg_fields, $part_pkg_fields, $num_svcs",
-    'addl_from' => 'LEFT JOIN part_pkg USING ( pkgpart )',
+    'addl_from' => qq{
+      LEFT JOIN part_pkg USING ( pkgpart )
+      LEFT JOIN part_pkg_option AS setup_option
+        ON (     cust_pkg.pkgpart = setup_option.pkgpart
+             AND setup_option.optionname = 'setup_fee' )
+      LEFT JOIN part_pkg_option AS recur_option
+        ON (     cust_pkg.pkgpart = recur_option.pkgpart
+             AND recur_option.optionname = 'recur_fee' )
+    },
   } );
   my $num_old_packages = scalar(@packages);
 
+  my %change_to_from; # target pkgnum => current cust_pkg, for future changes
+
   foreach my $cust_pkg ( @packages ) {
     my %hash = $cust_pkg->hash;
     my %part_pkg = map  { /^part_pkg_(.+)$/ or die; ( $1 => $hash{$_} ); }
                    grep { /^part_pkg_/ } keys %hash;
     $cust_pkg->{'_pkgpart'} = new FS::part_pkg \%part_pkg;
+    if ( $cust_pkg->change_to_pkgnum ) {
+      $change_to_from{$cust_pkg->change_to_pkgnum} = $cust_pkg;
+    }
+  }
+
+  if ( keys %change_to_from ) {
+    my @not_future_packages;
+    foreach my $cust_pkg (@packages) {
+      if ( exists( $change_to_from{$cust_pkg->pkgnum} ) ) {
+        my $change_from = $change_to_from{ $cust_pkg->pkgnum };
+        $cust_pkg->set('change_from_pkg', $change_from);
+        $change_from->set('change_to_pkg', $cust_pkg);
+      } else {
+        push @not_future_packages, $cust_pkg;
+      }
+    }
+    @packages = @not_future_packages;
   }
 
   unless ( $cgi->param('showoldpackages') ) {
@@ -202,8 +249,14 @@ sub get_packages {
   
   # don't include supplemental packages in this list; they'll be found from
   # their main packages
+  # (as will change-target packages)
   @packages = grep !$_->main_pkgnum, @packages;
 
+  foreach my $cust_pkg ( @packages ) {
+    $cust_pkg->{'_cust_pkg_discount_active'} =
+     [ $cust_pkg->cust_pkg_discount_active ];
+  }
+
   ( \@packages, $num_old_packages );
 }