Merge branch 'master' of git.freeside.biz:/home/git/freeside
[freeside.git] / httemplate / view / cust_main / packages / status.html
1 <TD CLASS="inv" BGCOLOR="<% $bgcolor %>">
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 ( $cust_pkg->order_date ) {
7     <% pkg_status_row($cust_pkg, emt('Ordered'), 'order_date', %opt ) %>
8 % }
9
10 % if ( $cust_pkg->get('cancel') ) { #status: cancelled
11 %   my $cpr = $cust_pkg->last_cust_pkg_reason('cancel');
12
13     <% pkg_status_row($cust_pkg, emt('Cancelled'), 'cancel', 'color'=>'FF0000', %opt ) %>
14
15     <% pkg_status_row_colspan( $cust_pkg,
16          ( $cpr ? $cpr->reasontext. ' by '. $cpr->otaker : '' ), '',
17          'align'=>'right', 'color'=>'ff0000', 'size'=>'-2', 'colspan'=>$colspan,
18          %opt
19        )
20     %>
21
22 %   unless ( $cust_pkg->get('setup') ) { 
23
24         <% pkg_status_row_colspan( $cust_pkg, emt('Never billed'), '', 'colspan'=>$colspan, %opt, ) %>
25
26 %   } else { 
27
28        <% pkg_status_row( $cust_pkg, emt('Setup'), 'setup', %opt ) %>
29        <% pkg_status_row_changed( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
30        <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
31        <% pkg_status_row_if( $cust_pkg, emt('Suspended'), 'susp', %opt, curuser=>$curuser ) %>
32
33 %   } 
34 %
35 %   if ( $part_pkg->freq ) { #?
36
37       <TR>
38         <TD COLSPAN=<%$colspan%>>
39           <FONT SIZE=-1>
40 %           if ( $curuser->access_right('Un-cancel customer package') ) { 
41               (&nbsp;<% pkg_uncancel_link($cust_pkg) %>&nbsp;)
42 %           } 
43           <FONT>
44         </TD>
45       </TR>
46 %   }
47 %
48 % } else {
49 %
50 %   if ( $cust_pkg->get('susp') ) { #status: suspended
51 %     my $cpr = $cust_pkg->last_cust_pkg_reason('susp');
52
53     <% pkg_status_row( $cust_pkg, emt('Suspended'), 'susp', 'color'=>'FF9900', %opt ) %>
54
55     <% pkg_status_row_colspan( $cust_pkg,
56          ( $cpr ? $cpr->reasontext. ' by '. $cpr->otaker : '' ), '',
57          'align'=>'right', 'color'=>'FF9900', 'size'=>'-2', 'colspan'=>$colspan,
58          %opt,
59        )
60     %>
61
62     <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
63
64     <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
65
66 %   unless ( $cust_pkg->get('setup') ) { 
67       <% pkg_status_row_colspan( $cust_pkg, emt('Never billed'), '', 'colspan'=>$colspan, %opt ) %>
68 %   } else { 
69       <% pkg_status_row($cust_pkg, emt('Setup'), 'setup', %opt ) %>
70 %   } 
71
72     <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
73
74     <% pkg_status_row_changed( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
75     <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
76 %   if ( $cust_pkg->option('suspend_bill', 1)
77 %        || ( $part_pkg->option('suspend_bill', 1)
78 %               && ! $cust_pkg->option('no_suspend_bill',1)
79 %           )
80 %      )
81 %   {
82       <% pkg_status_row_if( $cust_pkg, emt('Next bill'), 'bill', %opt, curuser=>$curuser ) %>
83 %   }
84     <% pkg_status_row_if( $cust_pkg, emt('Will resume'), 'resume', %opt, curuser=>$curuser ) %>
85     <% pkg_status_row_if( $cust_pkg, emt('Expires'), 'expire', %opt, curuser=>$curuser ) %>
86     <% pkg_status_row_if( $cust_pkg, emt('Contract ends'), 'contract_end', %opt ) %>
87
88     <TR>
89       <TD COLSPAN=<%$colspan%>>
90         <FONT SIZE=-1>
91 %         if ( $curuser->access_right('Unsuspend customer package') ) { 
92             (&nbsp;<% pkg_unsuspend_link($cust_pkg) %>&nbsp;)
93             (&nbsp;<% pkg_resume_link($cust_pkg) %>&nbsp;)
94 %         }
95 %         if ( $curuser->access_right('Cancel customer package immediately') ) {
96             (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
97 %         } 
98         </FONT>
99       </TD>
100     </TR>
101
102 %   } else { #status: active
103 %
104 %     unless ( $cust_pkg->get('setup') ) { #not setup
105 %
106 %       unless ( $part_pkg->freq ) {
107
108           <% pkg_status_row_colspan( $cust_pkg, emt('Not yet billed (one-time charge)'), '', 'colspan'=>$colspan, %opt ) %>
109
110           <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
111
112           <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
113
114           <% pkg_status_row_if(
115                $cust_pkg,
116                ( $part_pkg->freq ? emt('Start billing') : emt('Bill on') ),
117                'start_date',
118                %opt
119              )
120           %>
121
122           <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
123
124           <TR>
125             <TD COLSPAN=<%$colspan%>>
126               <FONT SIZE=-1>
127 %               if ( $curuser->access_right('Cancel customer package immediately') ) { 
128                   (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
129 %               } 
130               </FONT>
131             </TD>
132           </TR>
133
134 %       } else { 
135
136           <% pkg_status_row_colspan($cust_pkg, emt("Not yet billed ($billed_or_prepaid [_1])", myfreq($part_pkg) ), '', 'colspan'=>$colspan, %opt ) %>
137
138           <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
139
140           <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
141
142           <% pkg_status_row_if($cust_pkg, emt('Start billing'), 'start_date', %opt) %>
143           <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
144
145 %       } 
146 %
147 %     } else { #setup
148 %
149 %       unless ( $part_pkg->freq ) { 
150
151           <% pkg_status_row_colspan($cust_pkg, emt('One-time charge'), '', 'colspan'=>$colspan, %opt ) %>
152
153           <% pkg_status_row($cust_pkg, emt('Billed'), 'setup', %opt) %>
154
155           <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
156
157           <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
158
159           <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
160
161 %       } else { 
162 %
163 %         my $num_cust_svc = $cust_pkg->num_cust_svc;
164 %         my $summarize = $opt{'cust_pkg-large_pkg_size'} > 0
165 %                           && $opt{'cust_pkg-large_pkg_size'} <= $num_cust_svc;
166 %
167 %         #overlimit process is expensive with many services, so skip w/summary
168 %         if ( !$summarize && scalar($cust_pkg->overlimit) ) {
169
170             <% pkg_status_row_colspan( $cust_pkg,
171                  emt('Overlimit'),
172                  $billed_or_prepaid. '&nbsp;'. myfreq($part_pkg),
173                  'color'=>'FFD000', 'colspan'=>$colspan,
174                  %opt
175                )
176             %>
177
178 %         } else {
179             <% pkg_status_row_colspan( $cust_pkg,
180                  emt('Active'),
181                  $billed_or_prepaid. '&nbsp;'. myfreq($part_pkg),
182                  'color'=>'00CC00', 'colspan'=>$colspan,
183                  %opt
184                )
185             %>
186 %         } 
187
188           <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
189
190           <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
191
192           <% pkg_status_row($cust_pkg, emt('Setup'), 'setup', %opt) %>
193
194           <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
195
196 %       } 
197 %
198 %     } 
199 %
200 %     if ( $opt{'cust_pkg-show_autosuspend'} ) {
201 %       my $autosuspend = pkg_autosuspend_time( $cust_pkg );
202 %       $cust_pkg->set('autosuspend', $autosuspend) if $autosuspend;
203 %     }
204
205       <% pkg_status_row_changed( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
206       <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
207       <% pkg_status_row_if( $cust_pkg, $next_bill_or_prepaid_until, 'bill', %opt, curuser=>$curuser ) %>
208       <% pkg_status_row_if($cust_pkg, emt('Will automatically suspend by'), 'autosuspend', %opt) %>
209       <% pkg_status_row_if($cust_pkg, emt('Automatic suspension delayed until'), 'dundate', %opt) %>
210       <% pkg_status_row_if( $cust_pkg, emt('Will suspend on'), 'adjourn', %opt, curuser=>$curuser ) %>
211       <% pkg_status_row_if( $cust_pkg, emt('Will resume on'), 'resume', %opt, curuser=>$curuser ) %>
212       <% pkg_status_row_if( $cust_pkg, emt('Expires'), 'expire', %opt, curuser=>$curuser ) %>
213       <% pkg_status_row_if( $cust_pkg, emt('Contract ends'), 'contract_end', %opt ) %>
214
215 %     if ( $part_pkg->freq ) { 
216
217         <TR>
218           <TD COLSPAN=<%$colspan%>>
219             <FONT SIZE=-1>
220 %             if ( $curuser->access_right('Suspend customer package') ) { 
221                 (&nbsp;<% pkg_suspend_link($cust_pkg) %>&nbsp;)
222 %             } 
223 %             if ( $curuser->access_right('Suspend customer package later') ) { 
224                 (&nbsp;<% pkg_adjourn_link($cust_pkg) %>&nbsp;)
225 %             } 
226 %             if ( $curuser->access_right('Delay suspension events') ) { 
227                 (&nbsp;<% pkg_delay_link($cust_pkg) %>&nbsp;)
228 %             } 
229 %             if ( $curuser->access_right('Cancel customer package immediately') ) { 
230                 (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
231 %             } 
232 %             if ( $curuser->access_right('Cancel customer package later') ) { 
233                 (&nbsp;<% pkg_expire_link($cust_pkg) %>&nbsp;)
234 %             } 
235
236             <FONT>
237           </TD>
238         </TR>
239 %     }
240 %
241 %   } 
242 % } 
243
244   </TABLE>
245 </TD>
246 <%init>
247
248 my %opt = @_;
249
250 my $bgcolor  = $opt{'bgcolor'};
251 my $cust_pkg = $opt{'cust_pkg'};
252 my $part_pkg = $opt{'part_pkg'};
253 my $curuser  = $FS::CurrentUser::CurrentUser;
254 my $colspan  = $opt{'cust_pkg-display_times'} ? 8 : 4;
255 my $width    = $opt{'cust_pkg-display_times'} ? '38%' : '56%';
256
257 #false laziness w/edit/REAL_cust_pkg.cgi
258 my( $billed_or_prepaid, $last_bill_or_renewed, $next_bill_or_prepaid_until );
259 unless ( $part_pkg->is_prepaid ) {
260   $billed_or_prepaid = 'billed';
261   $last_bill_or_renewed = 'Last&nbsp;bill';
262   $next_bill_or_prepaid_until = 'Next&nbsp;bill';
263 } else {
264   $billed_or_prepaid = 'prepaid';
265   $last_bill_or_renewed = 'Renewed';
266   $next_bill_or_prepaid_until = 'Prepaid&nbsp;until';
267 }
268
269 #subroutines
270
271 sub myfreq {
272   my $part_pkg = shift;
273   my $freq = $part_pkg->freq_pretty;
274   #$freq =~ s/ /&nbsp;/g;
275   $freq;
276 }
277
278 #false laziness w/package.html
279 sub pkg_link {
280   my($action, $label, $cust_pkg) = @_;
281   return '' unless $cust_pkg;
282   qq!<a href="$p$action.cgi?!. $cust_pkg->pkgnum. qq!">$label</a>!;
283 }
284
285 sub pkg_status_row {
286   my( $cust_pkg, $title, $field, %opt ) = @_;
287
288   my $color = $opt{'color'};
289
290   my $html = qq(<TR><TD WIDTH="<%$width%>" ALIGN="right">);
291   $html   .= qq(<FONT COLOR="#$color"><B>) if length($color);
292   $html   .= qq($title&nbsp;);
293   $html   .= qq(</B></FONT>) if length($color);
294
295   if ( $opt{'pkg_balances'} && ! $cust_pkg->{_printed_balance}++ ) { #kludge
296     $html .= ' (Balance:&nbsp;<B>'. $opt{'money_char'}.
297              $cust_pkg->cust_main->balance_pkgnum($cust_pkg->pkgnum).
298              '</B>)';
299   }
300
301   $html   .= qq(</TD>);
302   $html   .= pkg_datestr($cust_pkg, $field, %opt). '</TR>';
303
304   $html;
305 }
306
307 sub pkg_status_row_if {
308   my( $cust_pkg, $title, $field, %opt ) = @_;
309   
310   $title = '<FONT SIZE=-1>(&nbsp;'. pkg_unadjourn_link($cust_pkg). '&nbsp;)&nbsp;</FONT>'. $title
311     if ( $field eq 'adjourn' &&
312          $opt{curuser}->access_right('Suspend customer package later')
313        );
314
315   $title = '<FONT SIZE=-1>(&nbsp;'. pkg_unexpire_link($cust_pkg). '&nbsp;)&nbsp;</FONT>'. $title
316     if ( $field eq 'expire' &&
317          $opt{curuser}->access_right('Cancel customer package later')
318        );
319
320   $cust_pkg->get($field) ? pkg_status_row($cust_pkg, $title, $field, %opt) : '';
321 }
322
323 sub pkg_status_row_changed {
324   my( $cust_pkg, %opt ) = @_;
325
326   return '' unless $cust_pkg->change_date;
327
328   my $html =
329     pkg_status_row( $cust_pkg, emt('Package changed'), 'change_date', %opt );
330
331   my $old = $cust_pkg->old_cust_pkg;
332   if ( $old ) {
333     my $part_pkg = $old->part_pkg;
334     $html .= pkg_status_row_colspan( $cust_pkg, 
335                                      emt("Changed from [_1]: [_2]",
336                                             $cust_pkg->change_pkgnum,
337                                             $part_pkg->pkg_comment(nopartpkg => 1) ),
338                                      '',
339                                      'size'    => '-1',
340                                      'align'   => 'right',
341                                      'colspan' => $opt{'colspan'},
342                                    );
343   }
344
345   $html;
346 }
347
348 sub pkg_status_row_noauto {
349   my( $cust_pkg, %opt ) = @_;
350   my $part_pkg = $opt{'part_pkg'};
351   return '' unless $cust_pkg->no_auto || $part_pkg->no_auto;
352
353   #inefficient, should be passed in
354   my $cust_main = $cust_pkg->cust_main;
355
356   return '' unless $cust_main->payby =~ /^(CARD|CHEK)$/;
357   my $what = lc(FS::payby->shortname($cust_main->payby));
358
359   pkg_status_row_colspan( $cust_pkg, emt("No automatic $what charge"), '',
360                           'colspan' => $opt{'colspan'},
361                         );
362 }
363
364 sub pkg_status_row_discount {
365   my( $cust_pkg, %opt ) = @_;
366
367   my $html;
368
369   foreach my $cust_pkg_discount ( $cust_pkg->cust_pkg_discount_active ) {
370
371     my $discount = $cust_pkg_discount->discount;
372
373     my $label = '<B>'.emt('Discount').'</B>: '. $discount->description;
374     if ( $discount->months ) {
375       my $remaining = $discount->months - $cust_pkg_discount->months_used;
376       $remaining = sprintf('%.2f', $remaining) if $remaining =~ /\./;
377       $label .= emt("([_1] months remaining)",$remaining);
378     }
379
380     $label .= ' <FONT SIZE="-1">('.
381                 '<A HREF="../misc/delete-cust_pkg_discount.html?'.
382                   $cust_pkg_discount->pkgdiscountnum.
383                 '">'.emt('remove discount').'</A>)</FONT>';
384
385     $html .= pkg_status_row_colspan( $cust_pkg, $label, '',
386                                      'colspan' => $opt{'colspan'},
387                                    );
388
389   }
390
391   $html;
392 }
393
394 sub pkg_status_row_colspan {
395   my($cust_pkg, $title, $addl, %opt) = @_;
396
397   my $colspan  = $opt{'colspan'};
398
399   my $align = $opt{'align'} ? 'ALIGN="'. $opt{'align'}.'"' : '';
400   my $color = $opt{'color'} ? 'COLOR="#'.$opt{'color'}.'"' : '';
401   my $size  = $opt{'size'}  ? 'SIZE="'.  $opt{'size'}. '"' : '';
402
403   my $html = qq(<TR><TD COLSPAN=$colspan $align>);
404   $html   .= qq(<FONT $color $size>) if length($color) || $size;
405   $html   .= qq(<B>) if $color && !$size;
406   $html   .= $title;
407   $html   .= qq(</B>) if $color && !$size;
408   $html   .= qq(</FONT>) if length($color) || $size;
409   $html   .= ",&nbsp;$addl" if length($addl);
410
411   if ( $opt{'pkg-balances'} && ! $cust_pkg->{_printed_balance}++ ) { #kludge
412     $html .= ' (Balance:&nbsp;<B>'. $opt{'money_char'}.
413              $cust_pkg->cust_main->balance_pkgnum($cust_pkg->pkgnum).
414              '</B>)';
415   }
416
417   $html   .= qq(</TD></TR>);
418
419   $html;
420
421 }
422
423 sub pkg_datestr {
424   my($cust_pkg, $field, %opt) = @_ or return '';
425   return '&nbsp;' unless $cust_pkg->get($field);
426   my $format = '<TD align="left"><B>%b</B></TD>'.
427                '<TD align="right"><B>&nbsp;%o,</B></TD>'.
428                '<TD align="right"><B>&nbsp;%Y</B></TD>';
429   #$format .= '&nbsp;<FONT SIZE=-3>%l:%M:%S%P&nbsp;%z</FONT>'
430   $format .= '<TD ALIGN="right"><B>&nbsp;%l</TD>'.
431              '<TD ALIGN="center"><B>:</B></TD>'.
432              '<TD ALIGN="left"><B>%M</B></TD>'.
433              '<TD ALIGN="left"><B>&nbsp;%P</B></TD>'
434     if $opt{'cust_pkg-display_times'};
435   my $strip = time2str($format, $cust_pkg->get($field) );
436   $strip =~ s/ (\d)/$1/g;
437   $strip;
438 }
439
440 sub pkg_suspend_link {
441   include( '/elements/popup_link-cust_pkg.html',
442              'action'      => $p. 'misc/cancel_pkg.html?method=suspend',
443              'label'       => emt('Suspend now'),
444              'actionlabel' => emt('Suspend'),
445              'color'       => '#FF9900',
446              'cust_pkg'    => shift,
447          )
448 }
449
450 sub pkg_adjourn_link {
451   include( '/elements/popup_link-cust_pkg.html',
452              'action'      => $p. 'misc/cancel_pkg.html?method=adjourn',
453              'label'       => emt('Suspend later'),
454              'actionlabel' => emt('Adjourn'),
455              'color'       => '#CC6600',
456              'cust_pkg'    => shift,
457          )
458 }
459
460 sub pkg_delay_link  {
461   my($cust_pkg) = shift;
462   include( '/elements/popup_link-cust_pkg.html',
463              'action'      => $p. 'misc/delay_susp_pkg.html',
464              'label'       => ( $cust_pkg->dundate
465                                   ? emt('Edit suspension delay')
466                                   : emt('Delay suspend')
467                               ),
468              'actionlabel' => emt('Delay suspend for'),
469              'cust_pkg'    => $cust_pkg,
470          )
471 }
472
473 sub pkg_resume_link {
474   include( '/elements/popup_link-cust_pkg.html',
475              'action'      => $p. 'misc/cancel_pkg.html?method=resume',
476              'label'       => emt('Unsuspend later'),
477              'actionlabel' => emt('Resume'),
478              'color'       => '#00CC00',
479              'cust_pkg'    => shift,
480          )
481 }
482
483 sub pkg_unsuspend_link { pkg_link('misc/unsusp_pkg',    emt('Unsuspend now'), @_ ); }
484 sub pkg_unadjourn_link { pkg_link('misc/unadjourn_pkg', emt('Abort'),     @_ ); }
485 sub pkg_unexpire_link  { pkg_link('misc/unexpire_pkg',  emt('Abort'),     @_ ); }
486
487 sub pkg_cancel_link {
488   include( '/elements/popup_link-cust_pkg.html',
489              'action'      => $p. 'misc/cancel_pkg.html?method=cancel',
490              'label'       => emt('Cancel now'),
491              'actionlabel' => emt('Cancel'),
492              'color'       => '#ff0000',
493              'cust_pkg'    => shift,
494          )
495 }
496
497 sub pkg_uncancel_link {
498   include( '/elements/popup_link-cust_pkg.html',
499              'action'      => $p. 'misc/cancel_pkg.html?method=uncancel',
500              'label'       => emt('Un-cancel'),
501              'actionlabel' => emt('Un-cancel'),
502              #'color'       =>  #?
503              'cust_pkg'    => shift,
504          )
505 }
506
507 sub pkg_expire_link {
508   include( '/elements/popup_link-cust_pkg.html',
509              'action'      => $p. 'misc/cancel_pkg.html?method=expire',
510              'label'       => emt('Cancel later'),
511              'actionlabel' => emt('Expire'),
512              'color'       => '#CC0000',
513              'cust_pkg'    => shift,
514          )
515 }
516
517 sub svc_recharge_link {
518   include( '/elements/popup_link-cust_svc.html',
519              'action'      => $p. 'misc/recharge_svc.html',
520              'label'       => emt('Recharge'),
521              'actionlabel' => emt('Recharge'),
522              'color'       => '#333399',
523              'cust_svc'    => shift,
524          )
525 }
526
527 sub pkg_autosuspend_time {
528   my $cust_pkg = shift or return '';
529   my $days = 7;
530   my $time = time;
531   my $pending_suspend = 0;
532   #this seems to be extremely inefficient...  and is slowing down all customer
533   #views
534   while ( $days > 0 &&
535           scalar(
536             grep { $_->part_event->action eq 'suspend' }
537             @{$cust_pkg->cust_main->due_cust_event( time => $time + 86400*$days,
538                                                     testonly => 1,
539                                                   ) }
540           )
541         )
542   {
543     $pending_suspend = 1;
544     $days--;
545   }
546
547   $pending_suspend ? time + ($days + 1) * 86400 : '';
548
549 }
550
551 </%init>