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