RT#17599: display cancelled services from history [display unprovisionable services...
[freeside.git] / httemplate / view / cust_main / packages / status.html
index 2707803..97011c3 100644 (file)
-<TD CLASS="inv" BGCOLOR="<% $bgcolor %>">
+<TD CLASS="inv" BGCOLOR="<% $bgcolor %>" VALIGN="top">
   <TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%">
 
 %#this should use cust_pkg->status and cust_pkg->statuscolor eventually
 
-% if ( $cust_pkg->order_date ) {
-    <% pkg_status_row($cust_pkg, 'Ordered', 'order_date', %opt ) %>
+% if ( $supplemental ) {
+    <% pkg_status_row_colspan($cust_pkg, emt('Supplemental'), '', 'color' => '7777FF', %opt) %>
+% } elsif ( $cust_pkg->order_date ) {
+    <% pkg_status_row($cust_pkg, emt('Ordered'), 'order_date', %opt ) %>
 % }
 
 % if ( $cust_pkg->get('cancel') ) { #status: cancelled
 %   my $cpr = $cust_pkg->last_cust_pkg_reason('cancel');
 
-    <% pkg_status_row($cust_pkg, 'Cancelled', 'cancel', 'color'=>'FF0000', %opt ) %>
+    <% pkg_status_row($cust_pkg, emt('Cancelled'), 'cancel', 'color'=>'FF0000', %opt ) %>
 
-    <% pkg_status_row_colspan( $cust_pkg,
-         ( $cpr ? $cpr->reasontext. ' by '. $cpr->otaker : '' ), '',
-         'align'=>'right', 'color'=>'ff0000', 'size'=>'-2', 'colspan'=>$colspan,
-         %opt
-       )
-    %>
+    <% pkg_status_row_detached($cust_pkg, %opt) %>
+
+    <% pkg_reason_row($cust_pkg, $cpr, color => 'ff0000', %opt) %>
 
 %   unless ( $cust_pkg->get('setup') ) { 
 
-        <% pkg_status_row_colspan( $cust_pkg, 'Never billed', '', 'colspan'=>$colspan, %opt, ) %>
+        <% pkg_status_row_colspan( $cust_pkg, emt('Never billed'), '', %opt, ) %>
 
 %   } else { 
 
-       <% pkg_status_row( $cust_pkg, 'Setup', 'setup', %opt ) %>
-       <% pkg_status_row_changed( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+       <% pkg_status_row( $cust_pkg, emt('Setup'), 'setup', %opt ) %>
+       <% pkg_status_row_changed( $cust_pkg, %opt ) %>
        <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
-       <% pkg_status_row_if( $cust_pkg, 'Suspended', 'susp', %opt, curuser=>$curuser ) %>
+       <% pkg_status_row_if( $cust_pkg, emt('Suspended'), 'susp', %opt, curuser=>$curuser ) %>
 
 %   } 
 %
-% } else { 
+%   if ( $part_pkg->freq && !$supplemental && !$cust_pkg->change_custnum ) { #?
+
+      <TR>
+        <TD COLSPAN=<%$opt{colspan}%>>
+          <FONT SIZE=-1>
+%           if ( $curuser->access_right('Un-cancel customer package') && ! $opt{no_links} ) { 
+              (&nbsp;<% pkg_uncancel_link($cust_pkg) %>&nbsp;)
+%           } 
+          <FONT>
+        </TD>
+      </TR>
+%   }
+%
+% } else { # not canceled
 %
-%   if ( $cust_pkg->get('susp') ) { #status: suspended
-%     my $cpr = $cust_pkg->last_cust_pkg_reason('susp');
+%   if ( $cust_pkg->get('susp') ) { #suspended or on hold
+%
+%     #if ( $cust_pkg->order_date eq $cust_pkg->get('susp') ) # inconsistent with FS::cust_pkg::status
+%     if ( ! $cust_pkg->setup ) { #status: on hold
+
+        <% pkg_status_row( $cust_pkg, emt('On Hold'), '', 'color'=>'7E0079', %opt ) %>
+
+%     } else { #status: suspended
+%       my ($cpr,$susplabel);
+%       if ($cust_pkg->is_status_delay_cancel(%opt)) {
+%         $cpr = $cust_pkg->last_cust_pkg_reason('expire');
+%         $susplabel = 'Suspended (Cancelled)';
+%       } else {
+%         $cpr = $cust_pkg->last_cust_pkg_reason('susp');
+%         $susplabel = 'Suspended';
+%       }
+        <% pkg_status_row( $cust_pkg, emt($susplabel), 'susp', 'color'=>'FF9900', %opt ) %>
+        <% pkg_reason_row( $cust_pkg, $cpr, 'color' => 'FF9900', %opt ) %>
 
-    <% pkg_status_row( $cust_pkg, 'Suspended', 'susp', 'color'=>'FF9900', %opt ) %>
+%     }
 
-    <% pkg_status_row_colspan( $cust_pkg,
-         ( $cpr ? $cpr->reasontext. ' by '. $cpr->otaker : '' ), '',
-         'align'=>'right', 'color'=>'FF9900', 'size'=>'-2', 'colspan'=>$colspan,
-         %opt,
-       )
-    %>
+    <% pkg_status_row_noauto( $cust_pkg, %opt ) %>
 
-    <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+    <% pkg_status_row_separate_bill( $cust_pkg, %opt ) %>
 
-    <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+    <% pkg_status_row_discount( $cust_pkg, %opt ) %>
 
-%   unless ( $cust_pkg->get('setup') ) { 
-      <% pkg_status_row_colspan( $cust_pkg, 'Never billed', '', 'colspan'=>$colspan, %opt ) %>
-%   } else { 
-      <% pkg_status_row($cust_pkg, 'Setup', 'setup', %opt ) %>
-%   } 
+%   if ( $cust_pkg->order_date ne $cust_pkg->get('susp') ) { # not on hold
+%     if ( $cust_pkg->get('setup') ) {
+        <% pkg_status_row($cust_pkg, emt('Setup'), 'setup', %opt ) %>
+%     } else {
+        <% pkg_status_row_colspan( $cust_pkg, emt('Never billed'), '', %opt ) %>
+%     }
+%   }
+
+    <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
 
-    <% pkg_status_row_changed( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+    <% pkg_status_row_changed( $cust_pkg, %opt ) %>
     <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
-%   if ( $part_pkg->option('suspend_bill', 1) ) {
-      <% pkg_status_row_if( $cust_pkg, 'Next&nbsp;bill', 'bill', %opt, curuser=>$curuser ) %>
+%   if ( $cust_pkg->option('suspend_bill', 1)
+%        || ( $part_pkg->option('suspend_bill', 1)
+%               && ! $cust_pkg->option('no_suspend_bill',1)
+%           )
+%      )
+%   {
+      <% pkg_status_row_if( $cust_pkg, emt('Next bill'), 'bill', %opt, curuser=>$curuser ) %>
 %   }
-    <% pkg_status_row_if( $cust_pkg, 'Expires', 'expire', %opt, curuser=>$curuser ) %>
-    <% pkg_status_row_if( $cust_pkg, 'Contract ends', 'contract_end', %opt ) %>
-
-    <TR>
-      <TD COLSPAN=<%$colspan%>>
-        <FONT SIZE=-1>
-%         if ( $curuser->access_right('Unsuspend customer package') ) { 
-            (&nbsp;<% pkg_unsuspend_link($cust_pkg) %>&nbsp;)
-%         } 
-%         if ( $curuser->access_right('Cancel customer package immediately') ) {
-            (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
-%         } 
-        </FONT>
-      </TD>
-    </TR>
-
+    <% pkg_status_row_if( $cust_pkg, emt('Will resume'), 'resume', %opt, curuser=>$curuser ) %>
+    <% pkg_status_row_expire($cust_pkg, %opt, curuser=>$curuser) %>
+    <% pkg_status_row_if( $cust_pkg, emt('Contract ends'), 'contract_end', %opt ) %>
+
+%   # Status changes for suspended packages: can unsuspend, future-unsuspend,
+%   # or future-change. If this package is a future change or is supplemental
+%   # disable them all.
+%   if ( !$supplemental && ! $opt{no_links} && !$change_from ) {
+      <TR>
+        <TD COLSPAN=<%$opt{colspan}%>>
+          <FONT SIZE=-1>
+%           if ( $cust_pkg->change_to_pkgnum ) {
+%               # then you can modify the package change
+%               if ( $curuser->access_right('Change customer package') ) {
+                (&nbsp;<% pkg_change_now_link($cust_pkg) %>&nbsp;)
+                (&nbsp;<% pkg_change_later_link($cust_pkg) %>&nbsp;)
+                (&nbsp;<% pkg_unchange_link($cust_pkg) %>&nbsp;)
+                <BR>
+%               }
+%           }
+%           if ( $curuser->access_right('Unsuspend customer package') ) { 
+%             if ( $cust_pkg->order_date eq $cust_pkg->get('susp') ) { #on hold
+                (&nbsp;<% pkg_unhold_link($cust_pkg) %>&nbsp;)
+%             } else {
+                (&nbsp;<% pkg_unsuspend_link($cust_pkg) %>&nbsp;)
+                (&nbsp;<% pkg_resume_link($cust_pkg) %>&nbsp;)
+%             }
+%           }
+%           if ( !$cust_pkg->change_to_pkgnum and
+%                $curuser->access_right('Cancel customer package immediately')
+%           ) {
+              (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
+%           } 
+          </FONT>
+        </TD>
+      </TR>
+%     }
+%
 %   } else { #status: active
 %
-%     unless ( $cust_pkg->get('setup') ) { #not setup
+%     if ( $change_from ) { # future change
+%
+          <% pkg_status_row_colspan( $cust_pkg, emt('Waiting for package change'), '', %opt ) %>
+          <% pkg_status_row_if( $cust_pkg,
+                             emt('Will be activated on'),
+                             'start_date',
+                             %opt ) %>
+%
+%     } elsif ( ! $cust_pkg->get('setup') ) { # not setup
 %
-%       unless ( $part_pkg->freq ) {
+%       unless ( $part_pkg->freq ) { # one-time charge
 
-          <% pkg_status_row_colspan( $cust_pkg, 'Not&nbsp;yet&nbsp;billed&nbsp;(one-time&nbsp;charge)', '', 'colspan'=>$colspan, %opt ) %>
+          <% pkg_status_row_colspan( $cust_pkg, emt('Not yet billed (one-time charge)'), '', %opt ) %>
 
-          <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+          <% pkg_status_row_noauto( $cust_pkg, %opt ) %>
 
-          <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+          <% pkg_status_row_separate_bill( $cust_pkg, %opt ) %>
+
+          <% pkg_status_row_discount( $cust_pkg, %opt ) %>
 
           <% pkg_status_row_if(
                $cust_pkg,
-               ( $part_pkg->freq ? 'Start billing' : 'Bill on' ),
+               ( $part_pkg->freq ? emt('Start billing') : emt('Bill on') ),
                'start_date',
                %opt
              )
           %>
 
+          <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
+
+%         if ( !$supplemental && ! $opt{no_links} ) {
           <TR>
-            <TD COLSPAN=<%$colspan%>>
+            <TD COLSPAN=<%$opt{colspan}%>>
               <FONT SIZE=-1>
 %               if ( $curuser->access_right('Cancel customer package immediately') ) { 
                   (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
               </FONT>
             </TD>
           </TR>
+%         }
+
+%       } else { # recurring package, not yet billed
 
-%       } else { 
+          <% pkg_status_row_colspan($cust_pkg, emt("Not yet billed ($billed_or_prepaid [_1])", myfreq($part_pkg) ), '', %opt ) %>
 
-          <% pkg_status_row_colspan($cust_pkg, "Not&nbsp;yet&nbsp;billed&nbsp;($billed_or_prepaid&nbsp;". myfreq($part_pkg). ')', '', 'colspan'=>$colspan, %opt ) %>
+          <% pkg_status_row_noauto( $cust_pkg, %opt ) %>
 
-          <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+          <% pkg_status_row_separate_bill( $cust_pkg, %opt ) %>
 
-          <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+          <% pkg_status_row_discount( $cust_pkg, %opt ) %>
 
-          <% pkg_status_row_if($cust_pkg, 'Start billing', 'start_date', %opt) %>
+          <% pkg_status_row_if($cust_pkg, emt('Start billing'), 'start_date', %opt) %>
+          <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
 
+%         if ( !$opt{no_links}
+%               and !$change_from
+%               and !$supplemental # can be changed from its main package
+%               and $curuser->access_right('Change package start date') )
+%         {
+
+        <TR>
+          <TD COLSPAN=<%$opt{colspan}%>>
+            <FONT SIZE=-1>
+            (&nbsp;<% pkg_change_start_link($cust_pkg) %>&nbsp;)
+            </FONT>
+          </TD>
+        </TR>
+%         }
+          
 %       } 
 %
 %     } else { #setup
 %
 %       unless ( $part_pkg->freq ) { 
 
-          <% pkg_status_row_colspan($cust_pkg, 'One-time&nbsp;charge', '', 'colspan'=>$colspan, %opt ) %>
+          <% pkg_status_row_colspan($cust_pkg, emt('One-time charge'), '', %opt ) %>
 
-          <% pkg_status_row($cust_pkg, 'Billed', 'setup', %opt) %>
+          <% pkg_status_row($cust_pkg, emt('Billed'), 'setup', %opt) %>
 
-          <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+          <% pkg_status_row_noauto( $cust_pkg, %opt ) %>
 
-          <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+          <% pkg_status_row_separate_bill( $cust_pkg, %opt ) %>
 
-%       } else { 
+          <% pkg_status_row_discount( $cust_pkg, %opt ) %>
+
+          <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
+
+%       } else { # recurring package
+%
+%         my $num_cust_svc = $cust_pkg->num_cust_svc;
+%         my $summarize = $opt{'cust_pkg-large_pkg_size'} > 0
+%                           && $opt{'cust_pkg-large_pkg_size'} <= $num_cust_svc;
 %
-%         if (scalar($cust_pkg->overlimit)) {
+%         #overlimit process is expensive with many services, so skip w/summary
+%         if ( !$summarize && scalar($cust_pkg->overlimit) ) {
 
             <% pkg_status_row_colspan( $cust_pkg,
-                 'Overlimit',
+                 emt('Overlimit'),
                  $billed_or_prepaid. '&nbsp;'. myfreq($part_pkg),
-                 'color'=>'FFD000', 'colspan'=>$colspan,
+                 'color'=>'FFD000',
                  %opt
                )
             %>
 
 %         } else {
             <% pkg_status_row_colspan( $cust_pkg,
-                 'Active',
+                 emt('Active'),
                  $billed_or_prepaid. '&nbsp;'. myfreq($part_pkg),
-                 'color'=>'00CC00', 'colspan'=>$colspan,
+                 'color'=>'00CC00',
                  %opt
                )
             %>
 %         } 
 
-          <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+          <% pkg_status_row_noauto( $cust_pkg, %opt ) %>
 
-          <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+          <% pkg_status_row_separate_bill( $cust_pkg, %opt ) %>
 
-          <% pkg_status_row($cust_pkg, 'Setup', 'setup', %opt) %>
+          <% pkg_status_row_discount( $cust_pkg, %opt ) %>
+
+          <% pkg_status_row($cust_pkg, emt('Setup'), 'setup', %opt) %>
+
+          <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
 
 %       } 
 %
-%     } 
+%     }
 %
 %     if ( $opt{'cust_pkg-show_autosuspend'} ) {
 %       my $autosuspend = pkg_autosuspend_time( $cust_pkg );
 %       $cust_pkg->set('autosuspend', $autosuspend) if $autosuspend;
 %     }
 
-      <% pkg_status_row_changed( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+      <% pkg_status_row_changed( $cust_pkg, %opt ) %>
       <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
       <% pkg_status_row_if( $cust_pkg, $next_bill_or_prepaid_until, 'bill', %opt, curuser=>$curuser ) %>
-      <% pkg_status_row_if($cust_pkg, 'Will automatically suspend by', 'autosuspend', %opt) %>
-      <% pkg_status_row_if( $cust_pkg, 'Will suspend on', 'adjourn', %opt, curuser=>$curuser ) %>
-      <% pkg_status_row_if( $cust_pkg, 'Expires', 'expire', %opt, curuser=>$curuser ) %>
-      <% pkg_status_row_if( $cust_pkg, 'Contract ends', 'contract_end', %opt ) %>
-
-%     if ( $part_pkg->freq ) { 
+      <% pkg_status_row_if($cust_pkg, emt('Will automatically suspend by'), 'autosuspend', %opt) %>
+      <% pkg_status_row_if($cust_pkg, emt('Automatic suspension delayed until'), 'dundate', %opt) %>
+      <% pkg_status_row_if( $cust_pkg, emt('Will suspend on'), 'adjourn', %opt, curuser=>$curuser ) %>
+      <% pkg_status_row_if( $cust_pkg, emt('Will resume on'), 'resume', %opt, curuser=>$curuser ) %>
+      <% pkg_status_row_expire($cust_pkg, %opt, curuser=>$curuser) %>
+      <% pkg_status_row_if( $cust_pkg, emt('Contract ends'), 'contract_end', %opt ) %>
+
+%     # Status changes for active recurring packages. If it has a future
+%     # package change scheduled, let that be modified. If it's supplemental,
+%     # then that's the only allowed action. Otherwise allow suspend, future
+%     # suspend, do-not-suspend, and immediate and future cancel.
+%     if ( $part_pkg->freq and ! $opt{no_links} ) { 
 
         <TR>
-          <TD COLSPAN=<%$colspan%>>
+          <TD COLSPAN=<%$opt{colspan}%>>
             <FONT SIZE=-1>
-%             if ( $curuser->access_right('Suspend customer package') ) { 
+% # action links
+%           if ( $change_from ) {
+%               # nothing
+%           } elsif ( $cust_pkg->change_to_pkgnum ) {
+%               # then you can modify the package change
+%               if ( $curuser->access_right('Change customer package') ) {
+                (&nbsp;<% pkg_change_now_link($cust_pkg) %>&nbsp;)
+                (&nbsp;<% pkg_change_later_link($cust_pkg) %>&nbsp;)
+                (&nbsp;<% pkg_unchange_link($cust_pkg) %>&nbsp;)
+                <BR>
+%               }
+%           }
+
+%           if ( !$supplemental ) {
+%           # suspension actions--always available
+%             if ( $curuser->access_right('Suspend customer package') ) {
                 (&nbsp;<% pkg_suspend_link($cust_pkg) %>&nbsp;)
-%             } 
-%             if ( $curuser->access_right('Suspend customer package later') ) { 
+%             }
+%             if ( $curuser->access_right('Suspend customer package later') ) {
                 (&nbsp;<% pkg_adjourn_link($cust_pkg) %>&nbsp;)
-%             } 
+%             }
 %             if ( $curuser->access_right('Delay suspension events') ) { 
                 (&nbsp;<% pkg_delay_link($cust_pkg) %>&nbsp;)
-%             } 
-%             if ( $curuser->access_right('Cancel customer package immediately') ) { 
-                (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
-%             } 
-%             if ( $curuser->access_right('Cancel customer package later') ) { 
-                (&nbsp;<% pkg_expire_link($cust_pkg) %>&nbsp;)
-%             } 
+%             }
+%
+%             if ( $change_from or $cust_pkg->change_to_pkgnum ) {
+%                 # you can't cancel the package while in this state
+%             } else { # the normal case: links to cancel the package
+                <BR>
+%               if ( $curuser->access_right('Cancel customer package immediately') ) {
+                  (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
+%               }
+%               if ( $curuser->access_right('Cancel customer package later') ) {
+                  (&nbsp;<% pkg_expire_link($cust_pkg) %>&nbsp;)
+%               }
+%             }
+%           }
 
             <FONT>
           </TD>
@@ -215,8 +342,11 @@ my $bgcolor  = $opt{'bgcolor'};
 my $cust_pkg = $opt{'cust_pkg'};
 my $part_pkg = $opt{'part_pkg'};
 my $curuser  = $FS::CurrentUser::CurrentUser;
-my $colspan  = $opt{'cust_pkg-display_times'} ? 8 : 4;
 my $width    = $opt{'cust_pkg-display_times'} ? '38%' : '56%';
+my $supplemental = $opt{'supplemental'};
+my $change_from  = $opt{'change_from'};
+
+$opt{colspan}  = $opt{'cust_pkg-display_times'} ? 8 : 4;
 
 #false laziness w/edit/REAL_cust_pkg.cgi
 my( $billed_or_prepaid, $last_bill_or_renewed, $next_bill_or_prepaid_until );
@@ -235,7 +365,7 @@ unless ( $part_pkg->is_prepaid ) {
 sub myfreq {
   my $part_pkg = shift;
   my $freq = $part_pkg->freq_pretty;
-  $freq =~ s/ /&nbsp;/g;
+  #$freq =~ s/ /&nbsp;/g;
   $freq;
 }
 
@@ -249,9 +379,27 @@ sub pkg_link {
 sub pkg_status_row {
   my( $cust_pkg, $title, $field, %opt ) = @_;
 
+  if ( $field and $cust_pkg->main_pkgnum ) {
+    # for supplemental packages, we mostly only show these if they're 
+    # different from the main package
+    my $main_pkg = $cust_pkg-> main_pkg;
+    if (    $main_pkg->get($field) ne $cust_pkg->get($field)
+        # with some exceptions
+        or  $field eq 'bill'
+        or  $field eq 'last_bill'
+        or  $field eq 'setup'
+        or  $field eq 'susp'
+        or  $field eq 'cancel'
+      ) {
+      # handle it normally
+    } else {
+      return '';
+    }
+  }
+
   my $color = $opt{'color'};
 
-  my $html = qq(<TR><TD WIDTH="<%$width%>" ALIGN="right">);
+  my $html = qq(<TR><TD WIDTH="$width" ALIGN="right">);
   $html   .= qq(<FONT COLOR="#$color"><B>) if length($color);
   $html   .= qq($title&nbsp;);
   $html   .= qq(</B></FONT>) if length($color);
@@ -276,32 +424,97 @@ sub pkg_status_row_if {
          $opt{curuser}->access_right('Suspend customer package later')
        );
 
-  $title = '<FONT SIZE=-1>(&nbsp;'. pkg_unexpire_link($cust_pkg). '&nbsp;)&nbsp;</FONT>'. $title
-    if ( $field eq 'expire' &&
-         $opt{curuser}->access_right('Cancel customer package later')
-       );
-
   $cust_pkg->get($field) ? pkg_status_row($cust_pkg, $title, $field, %opt) : '';
 }
 
+sub pkg_status_row_expire {
+  my $cust_pkg = shift;
+  my %opt = @_;
+  return unless $cust_pkg->get('expire');
+
+  my $title;
+
+  if ( $cust_pkg->get('change_to_pkg') ) {
+    if ( $cust_pkg->change_to_pkg->pkgpart != $cust_pkg->pkgpart ) {
+      $title = mt('Will change to <b>[_1]</b> on',
+                 $cust_pkg->change_to_pkg->part_pkg->pkg);
+    } elsif ( $cust_pkg->change_to_pkg->locationnum != $cust_pkg->locationnum )
+    {
+      $title = mt('Will <b>change location</b> on');
+    } elsif (( $cust_pkg->change_to_pkg->quantity != $cust_pkg->quantity ) ||
+             ( $cust_pkg->change_to_pkg->contract_end != $cust_pkg->contract_end ))
+    {
+      $title = mt('Will change on');
+    } else {
+      # FS::cust_pkg->change_later should have prevented this, but 
+      # just so that we can display _something_
+      $title = '<font color="#ff0000">Unknown package change</font>';
+    }
+
+  } else {
+
+    $title = emt('Expires');
+    if ( $opt{curuser}->access_right('Cancel customer package later')) {
+      $title = '<FONT SIZE=-1>(&nbsp;'. pkg_unexpire_link($cust_pkg). '&nbsp;)&nbsp;</FONT>'. $title;
+    }
+
+  }
+
+  pkg_status_row( $cust_pkg, $title, 'expire', %opt );
+}
+
 sub pkg_status_row_changed {
   my( $cust_pkg, %opt ) = @_;
 
   return '' unless $cust_pkg->change_date;
 
   my $html =
-    pkg_status_row( $cust_pkg, 'Package&nbsp;changed', 'change_date', %opt );
+    pkg_status_row( $cust_pkg, emt('Package changed'), 'change_date', %opt );
 
   my $old = $cust_pkg->old_cust_pkg;
   if ( $old ) {
     my $part_pkg = $old->part_pkg;
-    my $label = 'Changed from '. $cust_pkg->change_pkgnum. ': '.
-                $part_pkg->pkg_comment(nopartpkg => 1);
-    $html .= pkg_status_row_colspan( $cust_pkg, $label, '',
+    $html .= pkg_status_row_colspan(
+      $cust_pkg, 
+#      emt("Changed from [_1]: [_2]",
+#             $cust_pkg->change_pkgnum,
+#             $part_pkg->pkg_comment(cust_pkg=>$old, nopartpkg=>1)
+#         ),
+      '',
+      '',
+      'size'    => '-1',
+      'align'   => 'right',
+    );
+  }
+
+  $html;
+}
+
+sub pkg_status_row_detached {
+  my( $cust_pkg, %opt ) = @_;
+
+  return '' unless $cust_pkg->change_custnum;
+
+  my $html = '';
+
+  my $cust_main = $cust_pkg->change_cust_main;
+  if ( $cust_main ) {
+
+    my $cust_link = '<A HREF="cust_main.cgi?'.  $cust_pkg->change_custnum. '">'.
+                      encode_entities( $cust_main->name ).
+                    '</A>';
+
+    my $what = $opt{'pkg_attached'} ? 'Attached' : 'Detached';
+
+    $html .= pkg_status_row_colspan( $cust_pkg, 
+                                     emt("$what to customer #[_1]: ",
+                                            $cust_pkg->change_custnum
+                                        ).
+                                       $cust_link,
+                                     '',
                                      'size'    => '-1',
                                      'align'   => 'right',
-                                     'colspan' => $opt{'colspan'},
-                                     #%opt,
+                                     'colspan' => 4,
                                    );
   }
 
@@ -310,19 +523,17 @@ sub pkg_status_row_changed {
 
 sub pkg_status_row_noauto {
   my( $cust_pkg, %opt ) = @_;
-  my $part_pkg = $opt{'part_pkg'};
-  return '' unless $cust_pkg->no_auto || $part_pkg->no_auto;
 
-  #inefficient, should be passed in
-  my $cust_main = $cust_pkg->cust_main;
+  return '' unless ( $cust_pkg->no_auto || $opt{'part_pkg'}->no_auto )
+                && $opt{'has_cust_payby_auto'};
 
-  return '' unless $cust_main->payby =~ /^(CARD|CHEK)$/;
-  my $what = lc(FS::payby->shortname($cust_main->payby));
+  pkg_status_row_colspan( $cust_pkg, emt("No automatic charge"), '');
+}
 
-  pkg_status_row_colspan( $cust_pkg, "No automatic $what charge", '',
-                          'colspan' => $opt{'colspan'},
-                          #%opt,
-                        );
+sub pkg_status_row_separate_bill {
+  my $cust_pkg = shift;
+  return '' unless $cust_pkg->separate_bill;
+  pkg_status_row_colspan( $cust_pkg, emt("Invoiced separately") );
 }
 
 sub pkg_status_row_discount {
@@ -330,32 +541,54 @@ sub pkg_status_row_discount {
 
   my $html;
 
-  foreach my $cust_pkg_discount ( $cust_pkg->cust_pkg_discount_active ) {
+  if ( $cust_pkg->waive_setup ) {
+    my $label = '<SPAN STYLE="font-size: small;font-weight: bold">' .
+                 emt('Setup fee waived') .
+                 '</SPAN>';
+    $html .= pkg_status_row_colspan( $cust_pkg, $label, '', %opt );
+  }
+
+  foreach my $cust_pkg_discount (@{ $cust_pkg->{_cust_pkg_discount_active} }) {
 
     my $discount = $cust_pkg_discount->discount;
 
-    my $label = '<B>Discount</B>: '. $discount->description;
-    if ( $discount->months ) {
+    my $label = '<SPAN STYLE="font-size: small"><B>';
+    if ( $cust_pkg_discount->setuprecur eq 'setup' ) {
+      $label .= emt('Setup Discount');
+    } else {
+      $label .= emt('Recurring Discount');
+    }
+    $label .= '</B>: '. $discount->description;
+    if ( $discount->months > 0 and $cust_pkg_discount->months_used > 0 ) {
       my $remaining = $discount->months - $cust_pkg_discount->months_used;
       $remaining = sprintf('%.2f', $remaining) if $remaining =~ /\./;
-      $label .= " ($remaining months remaining)"
+      $label .= <br> . emt(" ([quant,_1,month,months] remaining)",$remaining);
     }
+    $label .= '</SPAN>';
 
-    $label .= ' <FONT SIZE="-1">('.
-                '<A HREF="../misc/delete-cust_pkg_discount.html?'.
-                  $cust_pkg_discount->pkgdiscountnum.
-                '">remove&nbsp;discount</A>)</FONT>';
+    #$label .= ' <FONT SIZE="-1">('.
+    #            '<A HREF="../misc/delete-cust_pkg_discount.html?'.
+    #              $cust_pkg_discount->pkgdiscountnum.
+    #            '">'.emt('remove discount').'</A>)</FONT>';
 
-    $html .= pkg_status_row_colspan( $cust_pkg, $label, '',
-                                     'colspan' => $opt{'colspan'},
-                                     #%opt,
-                                   );
+    $html .= pkg_status_row_colspan( $cust_pkg, $label, '', %opt );
 
   }
 
   $html;
 }
 
+sub pkg_reason_row {
+  my ($cust_pkg, $cpr, %opt) = @_;
+  return '' if $cust_pkg->main_pkgnum;
+
+  my $reasontext = '';
+  $reasontext = $cpr->reasontext . ' by ' . $cpr->otaker if $cpr;
+  pkg_status_row_colspan( $cust_pkg, $reasontext, '',
+    'align'=>'right', 'size'=>'-2', %opt
+  );
+}
+
 sub pkg_status_row_colspan {
   my($cust_pkg, $title, $addl, %opt) = @_;
 
@@ -405,61 +638,127 @@ sub pkg_datestr {
 sub pkg_suspend_link {
   include( '/elements/popup_link-cust_pkg.html',
              'action'      => $p. 'misc/cancel_pkg.html?method=suspend',
-             'label'       => 'Suspend&nbsp;now',
-             'actionlabel' => 'Suspend',
+             'label'       => emt('Suspend now'),
+             'actionlabel' => emt('Suspend'),
              'color'       => '#FF9900',
              'cust_pkg'    => shift,
+             'height'      => 420,
          )
 }
 
 sub pkg_adjourn_link {
   include( '/elements/popup_link-cust_pkg.html',
              'action'      => $p. 'misc/cancel_pkg.html?method=adjourn',
-             'label'       => 'Suspend&nbsp;later',
-             'actionlabel' => 'Adjourn',
+             'label'       => emt('Suspend later'),
+             'actionlabel' => emt('Adjourn'),
              'color'       => '#CC6600',
              'cust_pkg'    => shift,
+             'height'      => 445,
          )
 }
 
 sub pkg_delay_link  {
+  my($cust_pkg) = shift;
   include( '/elements/popup_link-cust_pkg.html',
              'action'      => $p. 'misc/delay_susp_pkg.html',
-             'label'       => 'Delay&nbsp;suspend',
-             'actionlabel' => 'Delay suspend for',
+             'label'       => ( $cust_pkg->dundate
+                                  ? emt('Edit suspension delay')
+                                  : emt('Delay suspend')
+                              ),
+             'actionlabel' => emt('Delay suspend for'),
+             'cust_pkg'    => $cust_pkg,
+         )
+}
+
+sub pkg_resume_link {
+  include( '/elements/popup_link-cust_pkg.html',
+             'action'      => $p. 'misc/cancel_pkg.html?method=resume',
+             'label'       => emt('Unsuspend later'),
+             'actionlabel' => emt('Resume'),
+             'color'       => '#00CC00',
+             'cust_pkg'    => shift,
+         )
+}
+
+sub pkg_unhold_link {
+  include( '/elements/popup_link-cust_pkg.html',
+             'action'      => $p. 'misc/unhold_pkg.html',
+             'label'       => emt('Start billing'),
+             'actionlabel' => emt('Start billing'),
+             'color'       => '#00CC00',
+             'width'       => 510,
+             'height'      => 310,
              'cust_pkg'    => shift,
          )
 }
 
-sub pkg_unsuspend_link { pkg_link('misc/unsusp_pkg',    'Unsuspend', @_ ); }
-sub pkg_unadjourn_link { pkg_link('misc/unadjourn_pkg', 'Abort',     @_ ); }
-sub pkg_unexpire_link  { pkg_link('misc/unexpire_pkg',  'Abort',     @_ ); }
+sub pkg_unsuspend_link { pkg_link('misc/unsusp_pkg',    emt('Unsuspend now'), @_ ); }
+sub pkg_unadjourn_link { pkg_link('misc/unadjourn_pkg', emt('Abort'),     @_ ); }
+sub pkg_unexpire_link  { pkg_link('misc/unexpire_pkg',  emt('Abort'),     @_ ); }
+sub pkg_unchange_link  { pkg_link('misc/do_not_change_pkg',  emt('Abort change'),     @_ ); }
+sub pkg_change_now_link  { pkg_link('misc/change_pkg_now',  emt('Change now'),     @_ ); }
 
 sub pkg_cancel_link {
   include( '/elements/popup_link-cust_pkg.html',
              'action'      => $p. 'misc/cancel_pkg.html?method=cancel',
-             'label'       => 'Cancel&nbsp;now',
-             'actionlabel' => 'Cancel',
+             'label'       => emt('Cancel now'),
+             'actionlabel' => emt('Cancel'),
              'color'       => '#ff0000',
              'cust_pkg'    => shift,
          )
 }
 
+sub pkg_uncancel_link {
+  include( '/elements/popup_link-cust_pkg.html',
+             'action'      => $p. 'misc/cancel_pkg.html?method=uncancel',
+             'label'       => emt('Un-cancel'),
+             'actionlabel' => emt('Un-cancel'),
+             #'color'       =>  #?
+             'cust_pkg'    => shift,
+             'width'       => 960,
+             'height'      => 740,
+         )
+}
+
 sub pkg_expire_link {
   include( '/elements/popup_link-cust_pkg.html',
              'action'      => $p. 'misc/cancel_pkg.html?method=expire',
-             'label'       => 'Cancel&nbsp;later',
-             'actionlabel' => 'Expire', #"Cancel package $num later"
+             'label'       => emt('Cancel later'),
+             'actionlabel' => emt('Expire'),
              'color'       => '#CC0000',
              'cust_pkg'    => shift,
          )
 }
 
+sub pkg_change_later_link {
+  my $cust_pkg = shift;
+  include( '/elements/popup_link-cust_pkg.html',
+    'action'      => $p . 'misc/change_pkg.cgi',
+    'label'       => emt('Reschedule'),
+    'actionlabel' => emt('Edit scheduled change for'),
+    'cust_pkg'    => $cust_pkg,
+    'width'       => 960,
+    'height'      => 490,
+  )
+}
+
+sub pkg_change_start_link {
+  my $cust_pkg = shift;
+  include( '/elements/popup_link-cust_pkg.html',
+    'action'      => $p . 'misc/change_pkg_start.html',
+    'label'       => emt('Set start date'),
+    'actionlabel' => emt('Set start of billing for'),
+    'cust_pkg'    => $cust_pkg,
+    'width'       => 510,
+    'height'      => 310,
+  )
+}
+
 sub svc_recharge_link {
   include( '/elements/popup_link-cust_svc.html',
              'action'      => $p. 'misc/recharge_svc.html',
-             'label'       => 'Recharge',
-             'actionlabel' => 'Recharge',
+             'label'       => emt('Recharge'),
+             'actionlabel' => emt('Recharge'),
              'color'       => '#333399',
              'cust_svc'    => shift,
          )