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