option to force one-time charges to be billed separately, #32866
[freeside.git] / httemplate / view / cust_main / packages / status.html
1 <TD CLASS="inv" BGCOLOR="<% $bgcolor %>" VALIGN="top">
2   <TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%">
3
4 %#this should use cust_pkg->status and cust_pkg->statuscolor eventually
5
6 % if ( $supplemental ) {
7     <% pkg_status_row_colspan($cust_pkg, emt('Supplemental'), '', 'color' => '7777FF', %opt) %>
8 % } elsif ( $cust_pkg->order_date ) {
9     <% pkg_status_row($cust_pkg, emt('Ordered'), 'order_date', %opt ) %>
10 % }
11
12 % if ( $cust_pkg->get('cancel') ) { #status: cancelled
13 %   my $cpr = $cust_pkg->last_cust_pkg_reason('cancel');
14
15     <% pkg_status_row($cust_pkg, emt('Cancelled'), 'cancel', 'color'=>'FF0000', %opt ) %>
16
17     <% pkg_status_row_detached($cust_pkg, %opt) %>
18
19     <% pkg_reason_row($cust_pkg, $cpr, color => 'ff0000', %opt) %>
20
21 %   unless ( $cust_pkg->get('setup') ) { 
22
23         <% pkg_status_row_colspan( $cust_pkg, emt('Never billed'), '', %opt, ) %>
24
25 %   } else { 
26
27        <% pkg_status_row( $cust_pkg, emt('Setup'), 'setup', %opt ) %>
28        <% pkg_status_row_changed( $cust_pkg, %opt ) %>
29        <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
30        <% pkg_status_row_if( $cust_pkg, emt('Suspended'), 'susp', %opt, curuser=>$curuser ) %>
31
32 %   } 
33 %
34 %   if ( $part_pkg->freq && !$supplemental && !$cust_pkg->change_custnum ) { #?
35
36       <TR>
37         <TD COLSPAN=<%$opt{colspan}%>>
38           <FONT SIZE=-1>
39 %           if ( $curuser->access_right('Un-cancel customer package') && ! $opt{no_links} ) { 
40               (&nbsp;<% pkg_uncancel_link($cust_pkg) %>&nbsp;)
41 %           } 
42           <FONT>
43         </TD>
44       </TR>
45 %   }
46 %
47 % } else {
48 %
49 %   if ( $cust_pkg->get('susp') ) { #suspended or on hold
50 %
51 %     #if ( $cust_pkg->order_date eq $cust_pkg->get('susp') ) { # inconsistent with FS::cust_pkg::status
52 %     if ( ! $cust_pkg->setup ) { #status: on hold
53
54         <% pkg_status_row( $cust_pkg, emt('On Hold'), '', 'color'=>'7E0079', %opt ) %>
55
56 %     } else { #status: suspended
57
58         <% pkg_status_row( $cust_pkg, emt('Suspended'), 'susp', 'color'=>'FF9900', %opt ) %>
59 %       my $cpr = $cust_pkg->last_cust_pkg_reason('susp');
60         <% pkg_reason_row( $cust_pkg, $cpr, 'color' => 'FF9900', %opt ) %>
61
62 %     }
63
64     <% pkg_status_row_noauto( $cust_pkg, %opt ) %>
65
66     <% pkg_status_row_separate_bill( $cust_pkg, %opt ) %>
67
68     <% pkg_status_row_discount( $cust_pkg, %opt ) %>
69
70 %   unless ( $cust_pkg->order_date eq $cust_pkg->get('susp') ) { #on hold
71 %     unless ( $cust_pkg->get('setup') ) { 
72         <% pkg_status_row_colspan( $cust_pkg, emt('Never billed'), '', %opt ) %>
73 %     } else { 
74         <% pkg_status_row($cust_pkg, emt('Setup'), 'setup', %opt ) %>
75 %     }
76 %   } 
77
78     <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
79
80     <% pkg_status_row_changed( $cust_pkg, %opt ) %>
81     <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
82 %   if ( $cust_pkg->option('suspend_bill', 1)
83 %        || ( $part_pkg->option('suspend_bill', 1)
84 %               && ! $cust_pkg->option('no_suspend_bill',1)
85 %           )
86 %      )
87 %   {
88       <% pkg_status_row_if( $cust_pkg, emt('Next bill'), 'bill', %opt, curuser=>$curuser ) %>
89 %   }
90     <% pkg_status_row_if( $cust_pkg, emt('Will resume'), 'resume', %opt, curuser=>$curuser ) %>
91     <% pkg_status_row_expire($cust_pkg, %opt, curuser=>$curuser) %>
92     <% pkg_status_row_if( $cust_pkg, emt('Contract ends'), 'contract_end', %opt ) %>
93
94 % if ( !$supplemental && ! $opt{no_links} && !$change_from ) {
95       <TR>
96         <TD COLSPAN=<%$opt{colspan}%>>
97           <FONT SIZE=-1>
98 %           if ( $cust_pkg->change_to_pkgnum ) {
99 %               # then you can modify the package change
100 %               if ( $curuser->access_right('Change customer package') ) {
101                 (&nbsp;<% pkg_change_now_link($cust_pkg) %>&nbsp;)
102                 (&nbsp;<% pkg_change_later_link($cust_pkg) %>&nbsp;)
103                 (&nbsp;<% pkg_unchange_link($cust_pkg) %>&nbsp;)
104                 <BR>
105 %               }
106 %           }
107 %           if ( $curuser->access_right('Unsuspend customer package') ) { 
108 %             if ( $cust_pkg->order_date eq $cust_pkg->get('susp') ) { #on hold
109                 (&nbsp;<% pkg_link('misc/unsusp_pkg', emt('Start bililng now'), $cust_pkg) %>&nbsp;)
110 %             } else {
111                 (&nbsp;<% pkg_unsuspend_link($cust_pkg) %>&nbsp;)
112                 (&nbsp;<% pkg_resume_link($cust_pkg) %>&nbsp;)
113 %             }
114 %           }
115 %           if ( !$cust_pkg->change_to_pkgnum and
116 %                $curuser->access_right('Cancel customer package immediately')
117 %           ) {
118               (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
119 %           } 
120           </FONT>
121         </TD>
122       </TR>
123 %     }
124 %
125 %   } else { #status: active
126 %
127 %     if ( $change_from ) { # future change
128 %
129           <% pkg_status_row_colspan( $cust_pkg, emt('Waiting for package change'), '', %opt ) %>
130           <% pkg_status_row( $cust_pkg,
131                              emt('Will be activated on'),
132                              'start_date',
133                              %opt ) %>
134 %
135 %     } elsif ( ! $cust_pkg->get('setup') ) { # not setup
136 %
137 %       unless ( $part_pkg->freq ) { # one-time charge
138
139           <% pkg_status_row_colspan( $cust_pkg, emt('Not yet billed (one-time charge)'), '', %opt ) %>
140
141           <% pkg_status_row_noauto( $cust_pkg, %opt ) %>
142
143           <% pkg_status_row_separate_bill( $cust_pkg, %opt ) %>
144
145           <% pkg_status_row_discount( $cust_pkg, %opt ) %>
146
147           <% pkg_status_row_if(
148                $cust_pkg,
149                ( $part_pkg->freq ? emt('Start billing') : emt('Bill on') ),
150                'start_date',
151                %opt
152              )
153           %>
154
155           <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
156
157 %         if ( !$supplemental && ! $opt{no_links} ) {
158           <TR>
159             <TD COLSPAN=<%$opt{colspan}%>>
160               <FONT SIZE=-1>
161 %               if ( $curuser->access_right('Cancel customer package immediately') ) { 
162                   (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
163 %               } 
164               </FONT>
165             </TD>
166           </TR>
167 %         }
168
169 %       } else { 
170
171           <% pkg_status_row_colspan($cust_pkg, emt("Not yet billed ($billed_or_prepaid [_1])", myfreq($part_pkg) ), '', %opt ) %>
172
173           <% pkg_status_row_noauto( $cust_pkg, %opt ) %>
174
175           <% pkg_status_row_separate_bill( $cust_pkg, %opt ) %>
176
177           <% pkg_status_row_discount( $cust_pkg, %opt ) %>
178
179           <% pkg_status_row_if($cust_pkg, emt('Start billing'), 'start_date', %opt) %>
180           <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
181
182 %       } 
183 %
184 %     } else { #setup
185 %
186 %       unless ( $part_pkg->freq ) { 
187
188           <% pkg_status_row_colspan($cust_pkg, emt('One-time charge'), '', %opt ) %>
189
190           <% pkg_status_row($cust_pkg, emt('Billed'), 'setup', %opt) %>
191
192           <% pkg_status_row_noauto( $cust_pkg, %opt ) %>
193
194           <% pkg_status_row_separate_bill( $cust_pkg, %opt ) %>
195
196           <% pkg_status_row_discount( $cust_pkg, %opt ) %>
197
198           <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
199
200 %       } else { 
201 %
202 %         my $num_cust_svc = $cust_pkg->num_cust_svc;
203 %         my $summarize = $opt{'cust_pkg-large_pkg_size'} > 0
204 %                           && $opt{'cust_pkg-large_pkg_size'} <= $num_cust_svc;
205 %
206 %         #overlimit process is expensive with many services, so skip w/summary
207 %         if ( !$summarize && scalar($cust_pkg->overlimit) ) {
208
209             <% pkg_status_row_colspan( $cust_pkg,
210                  emt('Overlimit'),
211                  $billed_or_prepaid. '&nbsp;'. myfreq($part_pkg),
212                  'color'=>'FFD000',
213                  %opt
214                )
215             %>
216
217 %         } else {
218             <% pkg_status_row_colspan( $cust_pkg,
219                  emt('Active'),
220                  $billed_or_prepaid. '&nbsp;'. myfreq($part_pkg),
221                  'color'=>'00CC00',
222                  %opt
223                )
224             %>
225 %         } 
226
227           <% pkg_status_row_noauto( $cust_pkg, %opt ) %>
228
229           <% pkg_status_row_separate_bill( $cust_pkg, %opt ) %>
230
231           <% pkg_status_row_discount( $cust_pkg, %opt ) %>
232
233           <% pkg_status_row($cust_pkg, emt('Setup'), 'setup', %opt) %>
234
235           <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
236
237 %       } 
238 %
239 %     }
240 %
241 %     if ( $opt{'cust_pkg-show_autosuspend'} ) {
242 %       my $autosuspend = pkg_autosuspend_time( $cust_pkg );
243 %       $cust_pkg->set('autosuspend', $autosuspend) if $autosuspend;
244 %     }
245
246       <% pkg_status_row_changed( $cust_pkg, %opt ) %>
247       <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
248       <% pkg_status_row_if( $cust_pkg, $next_bill_or_prepaid_until, 'bill', %opt, curuser=>$curuser ) %>
249       <% pkg_status_row_if($cust_pkg, emt('Will automatically suspend by'), 'autosuspend', %opt) %>
250       <% pkg_status_row_if($cust_pkg, emt('Automatic suspension delayed until'), 'dundate', %opt) %>
251       <% pkg_status_row_if( $cust_pkg, emt('Will suspend on'), 'adjourn', %opt, curuser=>$curuser ) %>
252       <% pkg_status_row_if( $cust_pkg, emt('Will resume on'), 'resume', %opt, curuser=>$curuser ) %>
253       <% pkg_status_row_expire($cust_pkg, %opt, curuser=>$curuser) %>
254       <% pkg_status_row_if( $cust_pkg, emt('Contract ends'), 'contract_end', %opt ) %>
255
256 %     if ( $part_pkg->freq and !$supplemental && ! $opt{no_links} ) { 
257
258         <TR>
259           <TD COLSPAN=<%$opt{colspan}%>>
260             <FONT SIZE=-1>
261 % # action links
262 %           if ( $change_from ) {
263 %               # nothing
264 %           } elsif ( $cust_pkg->change_to_pkgnum ) {
265 %               # then you can modify the package change
266 %               if ( $curuser->access_right('Change customer package') ) {
267                 (&nbsp;<% pkg_change_now_link($cust_pkg) %>&nbsp;)
268                 (&nbsp;<% pkg_change_later_link($cust_pkg) %>&nbsp;)
269                 (&nbsp;<% pkg_unchange_link($cust_pkg) %>&nbsp;)
270                 <BR>
271 %               }
272 %           }
273
274 %           # suspension actions--always available
275 %           if ( $curuser->access_right('Suspend customer package') ) { 
276               (&nbsp;<% pkg_suspend_link($cust_pkg) %>&nbsp;)
277 %           } 
278 %           if ( $curuser->access_right('Suspend customer package later') ) { 
279               (&nbsp;<% pkg_adjourn_link($cust_pkg) %>&nbsp;)
280 %           } 
281 %           if ( $curuser->access_right('Delay suspension events') ) { 
282               (&nbsp;<% pkg_delay_link($cust_pkg) %>&nbsp;)
283 %           }
284 %
285 %           if ( $change_from or $cust_pkg->change_to_pkgnum ) {
286 %               # you can't cancel the package while in this state
287 %           } else { # the normal case: links to cancel the package
288               <BR>
289 %             if ( $curuser->access_right('Cancel customer package immediately') ) { 
290                 (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
291 %             }
292 %             if ( $curuser->access_right('Cancel customer package later') ) { 
293                 (&nbsp;<% pkg_expire_link($cust_pkg) %>&nbsp;)
294 %             } 
295 %           }
296
297             <FONT>
298           </TD>
299         </TR>
300 %     }
301 %
302 %   } 
303 % } 
304
305   </TABLE>
306 </TD>
307 <%init>
308
309 my %opt = @_;
310
311 my $bgcolor  = $opt{'bgcolor'};
312 my $cust_pkg = $opt{'cust_pkg'};
313 my $part_pkg = $opt{'part_pkg'};
314 my $curuser  = $FS::CurrentUser::CurrentUser;
315 my $width    = $opt{'cust_pkg-display_times'} ? '38%' : '56%';
316 my $supplemental = $opt{'supplemental'};
317 my $change_from  = $opt{'change_from'};
318
319 $opt{colspan}  = $opt{'cust_pkg-display_times'} ? 8 : 4;
320
321 #false laziness w/edit/REAL_cust_pkg.cgi
322 my( $billed_or_prepaid, $last_bill_or_renewed, $next_bill_or_prepaid_until );
323 unless ( $part_pkg->is_prepaid ) {
324   $billed_or_prepaid = 'billed';
325   $last_bill_or_renewed = 'Last&nbsp;bill';
326   $next_bill_or_prepaid_until = 'Next&nbsp;bill';
327 } else {
328   $billed_or_prepaid = 'prepaid';
329   $last_bill_or_renewed = 'Renewed';
330   $next_bill_or_prepaid_until = 'Prepaid&nbsp;until';
331 }
332
333 #subroutines
334
335 sub myfreq {
336   my $part_pkg = shift;
337   my $freq = $part_pkg->freq_pretty;
338   #$freq =~ s/ /&nbsp;/g;
339   $freq;
340 }
341
342 #false laziness w/package.html
343 sub pkg_link {
344   my($action, $label, $cust_pkg) = @_;
345   return '' unless $cust_pkg;
346   qq!<a href="$p$action.cgi?!. $cust_pkg->pkgnum. qq!">$label</a>!;
347 }
348
349 sub pkg_status_row {
350   my( $cust_pkg, $title, $field, %opt ) = @_;
351
352   if ( $field and $cust_pkg->main_pkgnum ) {
353     # for supplemental packages, we mostly only show these if they're 
354     # different from the main package
355     my $main_pkg = $cust_pkg-> main_pkg;
356     if (    $main_pkg->get($field) ne $cust_pkg->get($field)
357         # with some exceptions
358         or  $field eq 'bill'
359         or  $field eq 'last_bill'
360         or  $field eq 'setup'
361         or  $field eq 'susp'
362         or  $field eq 'cancel'
363       ) {
364       # handle it normally
365     } else {
366       return '';
367     }
368   }
369
370   my $color = $opt{'color'};
371
372   my $html = qq(<TR><TD WIDTH="$width" ALIGN="right">);
373   $html   .= qq(<FONT COLOR="#$color"><B>) if length($color);
374   $html   .= qq($title&nbsp;);
375   $html   .= qq(</B></FONT>) if length($color);
376
377   if ( $opt{'pkg_balances'} && ! $cust_pkg->{_printed_balance}++ ) { #kludge
378     $html .= ' (Balance:&nbsp;<B>'. $opt{'money_char'}.
379              $cust_pkg->cust_main->balance_pkgnum($cust_pkg->pkgnum).
380              '</B>)';
381   }
382
383   $html   .= qq(</TD>);
384   $html   .= pkg_datestr($cust_pkg, $field, %opt). '</TR>';
385
386   $html;
387 }
388
389 sub pkg_status_row_if {
390   my( $cust_pkg, $title, $field, %opt ) = @_;
391   
392   $title = '<FONT SIZE=-1>(&nbsp;'. pkg_unadjourn_link($cust_pkg). '&nbsp;)&nbsp;</FONT>'. $title
393     if ( $field eq 'adjourn' &&
394          $opt{curuser}->access_right('Suspend customer package later')
395        );
396
397   $cust_pkg->get($field) ? pkg_status_row($cust_pkg, $title, $field, %opt) : '';
398 }
399
400 sub pkg_status_row_expire {
401   my $cust_pkg = shift;
402   my %opt = @_;
403   return unless $cust_pkg->get('expire');
404
405   my $title;
406
407   if ( $cust_pkg->get('change_to_pkg') ) {
408     if ( $cust_pkg->change_to_pkg->pkgpart != $cust_pkg->pkgpart ) {
409       $title = mt('Will change to <b>[_1]</b> on',
410                  $cust_pkg->change_to_pkg->part_pkg->pkg);
411     } elsif ( $cust_pkg->change_to_pkg->locationnum != $cust_pkg->locationnum )
412     {
413       $title = mt('Will <b>change location</b> on');
414     } else {
415       # FS::cust_pkg->change_later should have prevented this, but 
416       # just so that we can display _something_
417       $title = '<font color="#ff0000">Unknown package change</font>';
418     }
419
420   } else {
421
422     $title = emt('Expires');
423     if ( $opt{curuser}->access_right('Cancel customer package later')) {
424       $title = '<FONT SIZE=-1>(&nbsp;'. pkg_unexpire_link($cust_pkg). '&nbsp;)&nbsp;</FONT>'. $title;
425     }
426
427   }
428
429   pkg_status_row( $cust_pkg, $title, 'expire', %opt );
430 }
431
432 sub pkg_status_row_changed {
433   my( $cust_pkg, %opt ) = @_;
434
435   return '' unless $cust_pkg->change_date;
436
437   my $html =
438     pkg_status_row( $cust_pkg, emt('Package changed'), 'change_date', %opt );
439
440   my $old = $cust_pkg->old_cust_pkg;
441   if ( $old ) {
442     my $part_pkg = $old->part_pkg;
443     $html .= pkg_status_row_colspan( $cust_pkg, 
444                                      emt("Changed from [_1]: [_2]",
445                                             $cust_pkg->change_pkgnum,
446                                             $part_pkg->pkg_comment(nopartpkg => 1) ),
447                                      '',
448                                      'size'    => '-1',
449                                      'align'   => 'right',
450                                    );
451   }
452
453   $html;
454 }
455
456 sub pkg_status_row_detached {
457   my( $cust_pkg, %opt ) = @_;
458
459   return '' unless $cust_pkg->change_custnum;
460
461   my $html = '';
462
463   my $cust_main = $cust_pkg->change_cust_main;
464   if ( $cust_main ) {
465
466     my $cust_link = '<A HREF="cust_main.cgi?'.  $cust_pkg->change_custnum. '">'.
467                       encode_entities( $cust_main->name ).
468                     '</A>';
469
470     my $what = $opt{'pkg_attached'} ? 'Attached' : 'Detached';
471
472     $html .= pkg_status_row_colspan( $cust_pkg, 
473                                      emt("$what to customer #[_1]: ",
474                                             $cust_pkg->change_custnum
475                                         ).
476                                        $cust_link,
477                                      '',
478                                      'size'    => '-1',
479                                      'align'   => 'right',
480                                      'colspan' => 4,
481                                    );
482   }
483
484   $html;
485 }
486
487 sub pkg_status_row_noauto {
488   my( $cust_pkg, %opt ) = @_;
489   my $part_pkg = $opt{'part_pkg'};
490   return '' unless $cust_pkg->no_auto || $part_pkg->no_auto;
491
492   #inefficient, should be passed in
493   my $cust_main = $cust_pkg->cust_main;
494
495   return '' unless $cust_main->payby =~ /^(CARD|CHEK)$/;
496   my $what = lc(FS::payby->shortname($cust_main->payby));
497
498   pkg_status_row_colspan( $cust_pkg, emt("No automatic $what charge"), '');
499 }
500
501 sub pkg_status_row_separate_bill {
502   my $cust_pkg = shift;
503   return '' unless $cust_pkg->separate_bill;
504   pkg_status_row_colspan( $cust_pkg, emt("Invoiced separately") );
505 }
506
507 sub pkg_status_row_discount {
508   my( $cust_pkg, %opt ) = @_;
509
510   my $html;
511
512   foreach my $cust_pkg_discount (@{ $cust_pkg->{_cust_pkg_discount_active} }) {
513
514     my $discount = $cust_pkg_discount->discount;
515
516     my $label = '<B>'.emt('Discount').'</B>: '. $discount->description;
517     if ( $discount->months ) {
518       my $remaining = $discount->months - $cust_pkg_discount->months_used;
519       $remaining = sprintf('%.2f', $remaining) if $remaining =~ /\./;
520       $label .= emt("([_1] months remaining)",$remaining);
521     }
522
523     $label .= ' <FONT SIZE="-1">('.
524                 '<A HREF="../misc/delete-cust_pkg_discount.html?'.
525                   $cust_pkg_discount->pkgdiscountnum.
526                 '">'.emt('remove discount').'</A>)</FONT>';
527
528     $html .= pkg_status_row_colspan( $cust_pkg, $label, '', %opt );
529
530   }
531
532   $html;
533 }
534
535 sub pkg_reason_row {
536   my ($cust_pkg, $cpr, %opt) = @_;
537   return '' if $cust_pkg->main_pkgnum;
538
539   my $reasontext = '';
540   $reasontext = $cpr->reasontext . ' by ' . $cpr->otaker if $cpr;
541   pkg_status_row_colspan( $cust_pkg, $reasontext, '',
542     'align'=>'right', 'size'=>'-2', %opt
543   );
544 }
545
546 sub pkg_status_row_colspan {
547   my($cust_pkg, $title, $addl, %opt) = @_;
548
549   my $colspan  = $opt{'colspan'};
550
551   my $align = $opt{'align'} ? 'ALIGN="'. $opt{'align'}.'"' : '';
552   my $color = $opt{'color'} ? 'COLOR="#'.$opt{'color'}.'"' : '';
553   my $size  = $opt{'size'}  ? 'SIZE="'.  $opt{'size'}. '"' : '';
554
555   my $html = qq(<TR><TD COLSPAN=$colspan $align>);
556   $html   .= qq(<FONT $color $size>) if length($color) || $size;
557   $html   .= qq(<B>) if $color && !$size;
558   $html   .= $title;
559   $html   .= qq(</B>) if $color && !$size;
560   $html   .= qq(</FONT>) if length($color) || $size;
561   $html   .= ",&nbsp;$addl" if length($addl);
562
563   if ( $opt{'pkg-balances'} && ! $cust_pkg->{_printed_balance}++ ) { #kludge
564     $html .= ' (Balance:&nbsp;<B>'. $opt{'money_char'}.
565              $cust_pkg->cust_main->balance_pkgnum($cust_pkg->pkgnum).
566              '</B>)';
567   }
568
569   $html   .= qq(</TD></TR>);
570
571   $html;
572
573 }
574
575 sub pkg_datestr {
576   my($cust_pkg, $field, %opt) = @_ or return '';
577   return '&nbsp;' unless $cust_pkg->get($field);
578   my $format = '<TD align="left"><B>%b</B></TD>'.
579                '<TD align="right"><B>&nbsp;%o,</B></TD>'.
580                '<TD align="right"><B>&nbsp;%Y</B></TD>';
581   #$format .= '&nbsp;<FONT SIZE=-3>%l:%M:%S%P&nbsp;%z</FONT>'
582   $format .= '<TD ALIGN="right"><B>&nbsp;%l</TD>'.
583              '<TD ALIGN="center"><B>:</B></TD>'.
584              '<TD ALIGN="left"><B>%M</B></TD>'.
585              '<TD ALIGN="left"><B>&nbsp;%P</B></TD>'
586     if $opt{'cust_pkg-display_times'};
587   my $strip = time2str($format, $cust_pkg->get($field) );
588   $strip =~ s/ (\d)/$1/g;
589   $strip;
590 }
591
592 sub pkg_suspend_link {
593   include( '/elements/popup_link-cust_pkg.html',
594              'action'      => $p. 'misc/cancel_pkg.html?method=suspend',
595              'label'       => emt('Suspend now'),
596              'actionlabel' => emt('Suspend'),
597              'color'       => '#FF9900',
598              'cust_pkg'    => shift,
599              'height'      => 420,
600          )
601 }
602
603 sub pkg_adjourn_link {
604   include( '/elements/popup_link-cust_pkg.html',
605              'action'      => $p. 'misc/cancel_pkg.html?method=adjourn',
606              'label'       => emt('Suspend later'),
607              'actionlabel' => emt('Adjourn'),
608              'color'       => '#CC6600',
609              'cust_pkg'    => shift,
610              'height'      => 445,
611          )
612 }
613
614 sub pkg_delay_link  {
615   my($cust_pkg) = shift;
616   include( '/elements/popup_link-cust_pkg.html',
617              'action'      => $p. 'misc/delay_susp_pkg.html',
618              'label'       => ( $cust_pkg->dundate
619                                   ? emt('Edit suspension delay')
620                                   : emt('Delay suspend')
621                               ),
622              'actionlabel' => emt('Delay suspend for'),
623              'cust_pkg'    => $cust_pkg,
624          )
625 }
626
627 sub pkg_resume_link {
628   include( '/elements/popup_link-cust_pkg.html',
629              'action'      => $p. 'misc/cancel_pkg.html?method=resume',
630              'label'       => emt('Unsuspend later'),
631              'actionlabel' => emt('Resume'),
632              'color'       => '#00CC00',
633              'cust_pkg'    => shift,
634          )
635 }
636
637 sub pkg_unsuspend_link { pkg_link('misc/unsusp_pkg',    emt('Unsuspend now'), @_ ); }
638 sub pkg_unadjourn_link { pkg_link('misc/unadjourn_pkg', emt('Abort'),     @_ ); }
639 sub pkg_unexpire_link  { pkg_link('misc/unexpire_pkg',  emt('Abort'),     @_ ); }
640 sub pkg_unchange_link  { pkg_link('misc/do_not_change_pkg',  emt('Abort change'),     @_ ); }
641 sub pkg_change_now_link  { pkg_link('misc/change_pkg_now',  emt('Change now'),     @_ ); }
642
643 sub pkg_cancel_link {
644   include( '/elements/popup_link-cust_pkg.html',
645              'action'      => $p. 'misc/cancel_pkg.html?method=cancel',
646              'label'       => emt('Cancel now'),
647              'actionlabel' => emt('Cancel'),
648              'color'       => '#ff0000',
649              'cust_pkg'    => shift,
650          )
651 }
652
653 sub pkg_uncancel_link {
654   include( '/elements/popup_link-cust_pkg.html',
655              'action'      => $p. 'misc/cancel_pkg.html?method=uncancel',
656              'label'       => emt('Un-cancel'),
657              'actionlabel' => emt('Un-cancel'),
658              #'color'       =>  #?
659              'cust_pkg'    => shift,
660          )
661 }
662
663 sub pkg_expire_link {
664   include( '/elements/popup_link-cust_pkg.html',
665              'action'      => $p. 'misc/cancel_pkg.html?method=expire',
666              'label'       => emt('Cancel later'),
667              'actionlabel' => emt('Expire'),
668              'color'       => '#CC0000',
669              'cust_pkg'    => shift,
670          )
671 }
672
673 sub pkg_change_later_link {
674   my $cust_pkg = shift;
675   include( '/elements/popup_link-cust_pkg.html',
676     'action'      => $p . 'misc/change_pkg.cgi?',
677     'label'       => emt('Reschedule'),
678     'actionlabel' => emt('Edit scheduled change for'),
679     'cust_pkg'    => $cust_pkg,
680     'width'       => 960,
681     'height'      => 490,
682   )
683 }
684
685 sub svc_recharge_link {
686   include( '/elements/popup_link-cust_svc.html',
687              'action'      => $p. 'misc/recharge_svc.html',
688              'label'       => emt('Recharge'),
689              'actionlabel' => emt('Recharge'),
690              'color'       => '#333399',
691              'cust_svc'    => shift,
692          )
693 }
694
695 sub pkg_autosuspend_time {
696   my $cust_pkg = shift or return '';
697   my $days = 7;
698   my $time = time;
699   my $pending_suspend = 0;
700   #this seems to be extremely inefficient...  and is slowing down all customer
701   #views
702   while ( $days > 0 &&
703           scalar(
704             grep { $_->part_event->action eq 'suspend' }
705             @{$cust_pkg->cust_main->due_cust_event( time => $time + 86400*$days,
706                                                     testonly => 1,
707                                                   ) }
708           )
709         )
710   {
711     $pending_suspend = 1;
712     $days--;
713   }
714
715   $pending_suspend ? time + ($days + 1) * 86400 : '';
716
717 }
718
719 </%init>