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