taxproduct selection for one time charges
[freeside.git] / httemplate / view / cust_main / packages.html
1 <A NAME="cust_pkg"><FONT SIZE="+2">Packages</FONT></A><BR>
2
3 % if ( $curuser->access_right('One-time charge') ) {
4
5 <SCRIPT TYPE="text/javascript">
6
7 function taxproductmagic(which) {
8   var str = '';
9   var elements = which.form.elements;
10   for (var i = 0; i<elements.length; i++) {
11     if (elements[i].name == 'taxproductnum'){
12       document.getElementById('taxproductnum').value = elements[i].value;
13       continue;
14     }
15     if (elements[i].name == 'taxproductnum_description'){
16       continue;
17     }
18     if (str.length){str += ';';}
19     str += elements[i].name + '=' + escape(elements[i].value);
20   }
21   document.getElementById('charge_storage').value = str;
22   cClick();
23   overlib( OLiframeContent('<% $p %>/browse/part_pkg_taxproduct.cgi?_type=select&id=taxproductnum&onclick=taxproductquickchargemagic&taxproductnum='+document.getElementById('taxproductnum').value, 1000, 400, 'tax_product_popup'), CAPTION, 'Select product', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK);
24 }
25
26 function taxproductquickchargemagic() {
27   var str = document.getElementById('charge_storage').value;
28   if (str.length){str += ';';}
29   str += 'magic=taxproductnum;taxproductnum=';
30   str += escape(document.getElementById('taxproductnum').value);
31   cClick();
32   overlib( OLiframeContent('<% $p %>/edit/quick-charge.html?'+str, 545, 336, 'One-time charge'), CAPTION, 'One-time charge', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK, BGCOLOR, '#333399', CGCOLOR, '#333399', CLOSETEXT, 'Close');
33
34 }
35
36 function taxoverridemagic(which) {
37   var str = '';
38   var elements = which.ownerDocument.QuickChargeForm.elements;
39   for (var i = 0; i<elements.length; i++) {
40     if (elements[i].name == 'tax_override'){
41       document.getElementById('tax_override').value = elements[i].value;
42       continue;
43     }
44     if (str.length){str += ';';}
45     str += elements[i].name + '=' + escape(elements[i].value);
46   }
47   document.getElementById('charge_storage').value = str;
48   cClick();
49   overlib( OLiframeContent('<% $p %>/edit/part_pkg_taxoverride.html?element_name=tax_override;onclick=taxoverridequickchargemagic;selected='+document.getElementById('tax_override').value, 1100, 600, 'tax_product_popup'), CAPTION, 'Edit product tax overrides', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK);
50 }
51
52 function taxoverridequickchargemagic() {
53   var str = document.getElementById('charge_storage').value;
54   if (str.length){str += ';';}
55   str += 'magic=taxoverride;tax_override=';
56   str += document.getElementById('tax_override').value;
57   cClick();
58   overlib( OLiframeContent('<% $p %>/edit/quick-charge.html?'+str, 545, 336, 'One-time charge'), CAPTION, 'One-time charge', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK, BGCOLOR, '#333399', CGCOLOR, '#333399', CLOSETEXT, 'Close');
59
60 }
61
62 </SCRIPT>
63 <FORM NAME='quickcharge'>
64   <INPUT NAME="taxproductnum"  ID="taxproductnum"  TYPE="hidden">
65   <INPUT NAME="tax_override"   ID="tax_override"   TYPE="hidden">
66   <INPUT NAME="charge_storage" ID="charge_storage" TYPE="hidden">
67   <INPUT NAME="taxproductnum_description"  ID="taxproductnum_description" TYPE="hidden">
68 </FORM>
69 % } 
70
71 % my $s = 0;
72 % if ( $curuser->access_right('Order customer package') ) { 
73   <% $s++ ? ' | ' : '' %>
74   <% order_pkg_link($cust_main) %>
75 % } 
76
77 % if ( $curuser->access_right('One-time charge')
78 %        && $conf->config('payby-default') ne 'HIDE'
79 %      ) {
80 %
81   <% $s++ ? ' | ' : '' %>
82   <% include('/elements/popup_link.html',
83      { 
84        'action'      => $p. 'edit/quick-charge.html?custnum='. $cust_main->custnum,
85        'label'       => 'One-time charge',
86        'actionlabel' => 'One-time charge',
87        'color'       => '#333399',
88        'width'       => 545,
89      })
90   %>
91 % } 
92
93 % if ( $curuser->access_right('Bulk change customer packages') ) { 
94   <% $s++ ? ' | ' : '' %>
95   <A HREF="<% $p %>edit/cust_pkg.cgi?<% $cust_main->custnum %>">Bulk order and cancel packages</A> (preserves services)
96 % } 
97
98
99 <BR><BR>
100 % if ( @$packages ) { 
101
102 Current packages
103 % } 
104 % if ( $cust_main->num_cancelled_pkgs ) {
105 %     if ( $cgi->param('showcancelledpackages') eq '0' #see if it was set by me
106 %          || ( $conf->exists('hidecancelledpackages')
107 %               && ! $cgi->param('showcancelledpackages')
108 %             )
109 %        )
110 %     {
111 %       $cgi->param('showcancelledpackages', 1);
112 %
113
114   ( <a href="<% $cgi->self_url %>">show
115 %   } else {
116 %       $cgi->param('showcancelledpackages', 0);
117 %
118
119   ( <a href="<% $cgi->self_url %>">hide
120 %   } 
121
122  cancelled packages</a> )
123 % } 
124 % if ( @$packages ) { 
125
126
127 <% include('/elements/table-grid.html') %>
128 % my $bgcolor1 = '#eeeeee';
129 %   my $bgcolor2 = '#ffffff';
130 %   my $bgcolor = '';
131
132 <TR>
133   <TH CLASS="grid" BGCOLOR="#cccccc">Package</TH>
134   <TH CLASS="grid" BGCOLOR="#cccccc">Status</TH>
135   <TH CLASS="grid" BGCOLOR="#cccccc">Services</TH>
136 </TR>
137
138 %foreach my $cust_pkg (@$packages) {
139 %
140 %  my $part_pkg = $cust_pkg->part_pkg;
141 %
142 %  if ( $bgcolor eq $bgcolor1 ) {
143 %    $bgcolor = $bgcolor2;
144 %  } else {
145 %    $bgcolor = $bgcolor1;
146 %  }
147
148
149 <!--pkgnum: <% $cust_pkg->pkgnum %>-->
150 <TR>
151
152   <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
153
154     <A NAME="cust_pkg<% $cust_pkg->pkgnum %>" ID="cust_pkg<% $cust_pkg->pkgnum %>"><% $cust_pkg->pkgnum %></A>:
155     <% $part_pkg->pkg %> - <% $part_pkg->comment %>
156     <BR>
157
158 %   if ( $cust_pkg->quantity > 1 ) {
159         &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quantity: <B><% $cust_pkg->quantity %></B><BR>
160 %   }
161
162     <FONT SIZE=-1>
163 % unless ( $cust_pkg->get('cancel') ) { 
164 %   my $br = 0;
165 %   if ( $curuser->access_right('Change customer package') ) { $br=1;
166
167             (&nbsp;<%pkg_change_link($cust_pkg)%>&nbsp;)
168 %   } 
169 %   if ( $curuser->access_right('Edit customer package dates') ) { $br=1;
170
171             (&nbsp;<%pkg_dates_link($cust_pkg)%>&nbsp;)
172 %   } 
173 %   if ( $curuser->access_right('Customize customer package') ) { $br=1;
174
175             (&nbsp;<%pkg_customize_link($cust_pkg,$cust_main->custnum)%>&nbsp;)
176 %   } 
177     <% $br ? '<BR>' : '' %>
178 % } 
179
180 % if ( $cust_pkg->num_cust_event
181 %      && (    $curuser->access_right('Billing event reports')
182 %           || $curuser->access_right('View customer billing events')
183 %         )
184 %    ) {
185     (&nbsp;<%pkg_event_link($cust_pkg)%>&nbsp;)
186 % }
187
188     </FONT>
189
190   </TD>
191
192   <TD CLASS="inv" BGCOLOR="<% $bgcolor %>">
193     <TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%">
194 %
195 %  sub myfreq {
196 %    my $part_pkg = shift;
197 %    my $freq = $part_pkg->freq_pretty;
198 %    $freq =~ s/ /&nbsp;/g;
199 %    $freq;
200 %  }
201 %
202 %  #this should use cust_pkg->status and cust_pkg->statuscolor eventually
203 %  #my $colspan = $conf->exists('cust_pkg-display_times') ? 8 : 4;
204 %  #my $width = $conf->exists('cust_pkg-display_times') ? '38%' : '56%';
205 %
206 %  #false laziness w/edit/REAL_cust_pkg.cgi
207 %  my( $billed_or_prepaid, $last_bill_or_renewed, $next_bill_or_prepaid_until );
208 %  unless ( $part_pkg->is_prepaid ) {
209 %    $billed_or_prepaid = 'billed';
210 %    $last_bill_or_renewed = 'Last&nbsp;bill';
211 %    $next_bill_or_prepaid_until = 'Next&nbsp;bill';
212 %  } else {
213 %    $billed_or_prepaid = 'prepaid';
214 %    $last_bill_or_renewed = 'Renewed';
215 %    $next_bill_or_prepaid_until = 'Prepaid&nbsp;until';
216 %  }
217 %
218 %
219 % if ( $cust_pkg->get('cancel') ) { #status: cancelled
220 %   my $cpr = $cust_pkg->last_cust_pkg_reason('cancel');
221
222     <% pkg_status_row($cust_pkg, 'Cancelled', 'cancel', 'color'=>'FF0000', conf=>$conf ) %>
223
224     <% pkg_status_row_colspan(
225          ( $cpr ? $cpr->reasontext. ' by '. $cpr->otaker : '' ), '',
226          'align' => 'right', 'color' => 'ff0000', 'size' => '-2',
227        )
228     %>
229
230 %   unless ( $cust_pkg->get('setup') ) { 
231
232         <% pkg_status_row_colspan('Never billed') %>
233
234 %   } else { 
235
236        <% pkg_status_row( $cust_pkg, 'Setup', 'setup', conf=>$conf ) %>
237        <% pkg_status_row_changed( $cust_pkg, conf=>$conf ) %>
238        <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', conf=>$conf, curuser=>$curuser ) %>
239        <% pkg_status_row_if( $cust_pkg, 'Suspended', 'susp', conf=>$conf, curuser=>$curuser ) %>
240
241 %   } 
242 %
243 % } else { 
244 %
245 %   if ( $cust_pkg->get('susp') ) { #status: suspended
246 %     my $cpr = $cust_pkg->last_cust_pkg_reason('susp');
247
248     <% pkg_status_row( $cust_pkg, 'Suspended', 'susp', 'color'=>'FF9900', conf=>$conf ) %>
249
250     <% pkg_status_row_colspan(
251          ( $cpr ? $cpr->reasontext. ' by '. $cpr->otaker : '' ), '',
252          'align' => 'right', 'color' => 'FF9900', 'size' => '-2',
253        )
254     %>
255
256 %   unless ( $cust_pkg->get('setup') ) { 
257       <% pkg_status_row_colspan('Never billed') %>
258 %   } else { 
259       <% pkg_status_row($cust_pkg, 'Setup', 'setup', conf=>$conf ) %>
260 %   } 
261
262     <% pkg_status_row_changed( $cust_pkg, conf=>$conf ) %>
263     <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', conf=>$conf, curuser=>$curuser ) %>
264 %   # pkg_status_row($cust_pkg, 'Next bill', 'bill', conf=>$conf)
265     <% pkg_status_row_if( $cust_pkg, 'Expires', 'expire', conf=>$conf, curuser=>$curuser ) %>
266
267     <TR>
268       <TD COLSPAN=<%$colspan%>>
269         <FONT SIZE=-1>
270 %         if ( $curuser->access_right('Unsuspend customer package') ) { 
271             (&nbsp;<% pkg_unsuspend_link($cust_pkg) %>&nbsp;)
272 %         } 
273 %         if ( $curuser->access_right('Cancel customer package immediately') ) {
274             (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
275 %         } 
276         </FONT>
277       </TD>
278     </TR>
279
280 %   } else { #status: active
281 %
282 %     unless ( $cust_pkg->get('setup') ) { #not setup
283 %
284 %       unless ( $part_pkg->freq ) { 
285
286           <% pkg_status_row_colspan('Not&nbsp;yet&nbsp;billed&nbsp;(one-time&nbsp;charge)') %>
287
288           <TR>
289             <TD COLSPAN=<%$colspan%>>
290               <FONT SIZE=-1>
291 %               if ( $curuser->access_right('Cancel customer package immediately') ) { 
292                   (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
293 %               } 
294               </FONT>
295             </TD>
296           </TR>
297
298 %       } else { 
299
300          <% pkg_status_row_colspan("Not&nbsp;yet&nbsp;billed&nbsp;($billed_or_prepaid&nbsp;". myfreq($part_pkg). ')' ) %>
301
302 %       } 
303 %
304 %     } else { #setup
305 %
306 %       unless ( $part_pkg->freq ) { 
307
308           <% pkg_status_row_colspan('One-time&nbsp;charge') %>
309
310           <% pkg_status_row($cust_pkg, 'Billed', 'setup', conf=>$conf) %>
311
312 %       } else { 
313 %
314 %         if (scalar($cust_pkg->overlimit)) {
315
316             <% pkg_status_row_colspan(
317                  'Overlimit',
318                  $billed_or_prepaid. '&nbsp;'. myfreq($part_pkg),
319                  'color' => 'FFD000',
320                )
321             %>
322
323 %         } else {
324             <% pkg_status_row_colspan(
325                  'Active',
326                  $billed_or_prepaid. '&nbsp;'. myfreq($part_pkg),
327                  'color' => '00CC00',
328                )
329             %>
330 %         } 
331
332           <% pkg_status_row($cust_pkg, 'Setup', 'setup', conf=>$conf) %>
333
334 %       } 
335 %
336 %     } 
337
338       <% pkg_status_row_changed( $cust_pkg, conf=>$conf ) %>
339       <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', conf=>$conf, curuser=>$curuser ) %>
340       <% pkg_status_row_if( $cust_pkg, $next_bill_or_prepaid_until, 'bill', conf=>$conf, curuser=>$curuser ) %>
341       <% pkg_status_row_if( $cust_pkg, 'Will suspend on', 'adjourn', conf=>$conf, curuser=>$curuser ) %>
342       <% pkg_status_row_if( $cust_pkg, 'Expires', 'expire', conf=>$conf, curuser=>$curuser ) %>
343
344 %     if ( $part_pkg->freq ) { 
345
346         <TR>
347           <TD COLSPAN=<%$colspan%>>
348             <FONT SIZE=-1>
349 %             if ( $curuser->access_right('Suspend customer package') ) { 
350                 (&nbsp;<% pkg_suspend_link($cust_pkg) %>&nbsp;)
351 %             } 
352 %             if ( $curuser->access_right('Suspend customer package later') ) { 
353                 (&nbsp;<% pkg_adjourn_link($cust_pkg) %>&nbsp;)
354 %             } 
355 %             if ( $curuser->access_right('Cancel customer package immediately') ) { 
356                 (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
357 %             } 
358 %             if ( $curuser->access_right('Cancel customer package later') ) { 
359                 (&nbsp;<% pkg_expire_link($cust_pkg) %>&nbsp;)
360 %             } 
361
362             <FONT>
363           </TD>
364         </TR>
365 %     }
366 %
367 %   } 
368 % } 
369
370 </TABLE>
371 </TD>
372
373 <TD CLASS="inv" BGCOLOR="<% $bgcolor %>">
374   <TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%">
375
376 %  #foreach my $svcpart (sort {$a->{svcpart} <=> $b->{svcpart}} @{$pkg->{svcparts}}) {
377 %  foreach my $part_svc ( $cust_pkg->part_svc ) {
378
379 %    #foreach my $service (@{$svcpart->{services}}) {
380 %    foreach my $cust_svc ( @{ $part_svc->cust_pkg_svc } ) {
381
382       <TR>
383         <TD ALIGN="right" VALIGN="top"><% FS::UI::Web::svc_link($m, $part_svc, $cust_svc) %></TD>
384         <TD STYLE="padding-bottom:0px"><B><% FS::UI::Web::svc_label_link($m, $part_svc, $cust_svc) %></B></TD>
385         <TD><% FS::UI::Web::svc_export_links($m, $part_svc, $cust_svc) %></TD>
386       </TR>
387
388       <TR>
389         <TD ALIGN="right" COLSPAN="3" VALIGN="top" STYLE="padding-bottom:1px;padding-top:0px"><FONT SIZE="-2" COLOR="#FFD000">
390
391             <% $cust_svc->overlimit ? "Overlimit: ". time2str('%b %o %Y' . ($conf->exists('cust_pkg-display_times') ? ' %l:%M %P' : ''), $cust_svc->overlimit) : '' %>
392           </FONT></TD>
393       </TR>
394
395       <TR>
396         <TD ALIGN="right" VALIGN="top" STYLE="padding-bottom:5px;padding-top:0px"><FONT SIZE="-2">
397
398 %         if ( $curuser->access_right('Recharge customer service')
399 %              && $part_svc->svcdb eq 'svc_acct'
400 %              && (    $cust_svc->svc_x->seconds    ne ''
401 %                   || $cust_svc->svc_x->upbytes    ne ''
402 %                   || $cust_svc->svc_x->downbytes  ne ''
403 %                   || $cust_svc->svc_x->totalbytes ne ''
404 %                 )
405 %         ) { 
406             (&nbsp;<%svc_recharge_link($cust_svc)%>&nbsp;)
407 %         } 
408           </FONT></TD>
409
410           <TD ALIGN="right" VALIGN="top" STYLE="padding-bottom:5px;padding-top:0px"><FONT SIZE="-2">
411
412 %         if ( $curuser->access_right('Unprovision customer service') ) { 
413             (&nbsp;<%svc_unprovision_link($cust_svc)%>&nbsp;)
414 %         } 
415           </FONT></TD>
416         </TR>
417 %   } 
418
419 %   if (    ! $cust_pkg->get('cancel')
420 %        && $curuser->access_right('Provision customer service') 
421 %        && $part_svc->num_avail
422 %      ) {
423
424       <TR>
425         <TD COLSPAN=3 ALIGN="center" STYLE="padding-bottom:4px;padding-top:0px">
426           <B><% svc_provision_link($cust_pkg, $part_svc, $conf, $curuser) %></B>
427         </TD>
428       </TR>
429
430 %   } 
431
432 % } 
433
434 </TABLE>
435 </TD>
436 % } #end display packages
437 %
438
439
440 </TABLE>
441 % } else { 
442
443 <BR>
444 % } 
445 % if ( $cgi->param('fragment') =~ /^cust_pkg(\d+)$/ ) {
446   <SCRIPT>
447     // IE-specific hack.  other browsers listen to #fragments
448     // is this even working?  or is the #target redirection just working cause
449     // we set the URL params differently?
450     var el = document.getElementById( 'cust_pkg<% $1 %>' );
451     if ( el ) el.scrollIntoView(true);
452   </SCRIPT>
453 % }
454 <%init>
455
456 my( $cust_main ) = @_;
457 my $conf = new FS::Conf;
458
459 my $curuser = $FS::CurrentUser::CurrentUser;
460
461 my $packages = get_packages($cust_main, $conf);
462
463 my $colspan = $conf->exists('cust_pkg-display_times') ? 8 : 4;
464 my $width = $conf->exists('cust_pkg-display_times') ? '38%' : '56%';
465
466 sub pkg_status_row {
467   my( $cust_pkg, $title, $field, %opt ) = @_;
468
469   my $color = $opt{'color'};
470
471   my $html = qq(<TR><TD WIDTH="<%$width%>" ALIGN="right">);
472   $html   .= qq(<FONT COLOR="#$color"><B>) if length($color);
473   $html   .= qq($title&nbsp;);
474   $html   .= qq(</B></FONT>) if length($color);
475   $html   .= qq(</TD>);
476   $html   .= pkg_datestr($cust_pkg, $field, $opt{conf}).'</TR>';
477
478   $html;
479 }
480
481 sub pkg_status_row_if {
482   my( $cust_pkg, $title, $field, %opt ) = @_;
483   
484   $title = '<FONT SIZE=-1>(&nbsp;'. pkg_unadjourn_link($cust_pkg). '&nbsp;)&nbsp;</FONT>'. $title
485     if ( $field eq 'adjourn' &&
486          $opt{curuser}->access_right('Suspend customer package later')
487        );
488
489   $title = '<FONT SIZE=-1>(&nbsp;'. pkg_unexpire_link($cust_pkg). '&nbsp;)&nbsp;</FONT>'. $title
490     if ( $field eq 'expire' &&
491          $opt{curuser}->access_right('Cancel customer package later')
492        );
493
494   $cust_pkg->get($field) ? pkg_status_row($cust_pkg, $title, $field, %opt) : '';
495 }
496
497 sub pkg_status_row_changed {
498   my( $cust_pkg, %opt ) = @_;
499   return '' unless $cust_pkg->change_date;
500   my $html = pkg_status_row( $cust_pkg, 'Package&nbsp;changed', 'change_date', conf=>$opt{'conf'} );
501   my $old = $cust_pkg->old_cust_pkg;
502   if ( $old ) {
503     my $part_pkg = $old->part_pkg;
504     my $label = 'Changed from '. $cust_pkg->change_pkgnum. ': '.
505                 $part_pkg->pkg. ' - '. $part_pkg->comment;
506     $html .= pkg_status_row_colspan( $label, '', size=>'-1', align=>'right' );
507   }
508   $html;
509 }
510
511 sub pkg_status_row_colspan {
512   my($title, $addl, %opt) = @_;
513
514   my $align = $opt{'align'} ? 'ALIGN="'. $opt{'align'}.'"' : '';
515   my $color = $opt{'color'} ? 'COLOR="#'.$opt{'color'}.'"' : '';
516   my $size  = $opt{'size'}  ? 'SIZE="'.  $opt{'size'}. '"' : '';
517
518   my $html = qq(<TR><TD COLSPAN=$colspan $align>);
519   $html   .= qq(<FONT $color $size>) if length($color) || $size;
520   $html   .= qq(<B>) if $color && !$size;
521   $html   .= $title;
522   $html   .= qq(</B>) if $color && !$size;
523   $html   .= qq(</FONT>) if length($color) || $size;
524   $html   .= ",&nbsp;$addl" if length($addl);
525   $html   .= qq(</TD></TR>);
526
527   $html;
528
529 }
530
531 #subroutines
532
533 sub get_packages {
534   my $cust_main = shift or return undef;
535   my $conf = shift;
536   
537   my @packages = ();
538   my $method;
539   if (  $cgi->param('showcancelledpackages') eq '0' #see if it was set by me
540      || ( $conf->exists('hidecancelledpackages')
541            && ! $cgi->param('showcancelledpackages') )
542      )
543   {
544     $method = 'ncancelled_pkgs';
545   } else {
546     $method = 'all_pkgs';
547   }
548
549   [ $cust_main->$method() ];
550 }
551
552 sub svc_provision_link {
553   my ($cust_pkg, $part_svc, $conf, $curuser) = @_;
554   ( my $svc_nbsp = $part_svc->svc ) =~ s/\s+/&nbsp;/g;
555   my $num_avail = $part_svc->num_avail;
556   my $pkgnum_svcpart = "pkgnum=". $cust_pkg->pkgnum. ';'.
557                        "svcpart=". $part_svc->svcpart;
558   my $url;
559   if ( $part_svc->svcdb eq 'svc_external' #could be generalized
560        && $conf->exists('svc_external-skip_manual')
561   ) {
562     $url = "${p}edit/process/". $part_svc->svcdb. ".cgi?$pkgnum_svcpart";
563   } else {
564     $url = svc_url(
565                     'm'        => $m,
566                     'action'   => 'edit',
567                     'part_svc' => $part_svc, 
568                     'query'    => $pkgnum_svcpart,
569                   );
570     #$url = "${p}edit/$svcpart->{svcdb}.cgi?$pkgnum_svcpart";
571   }
572
573   my $link = qq!<A CLASS="provision" HREF="$url">!.
574              "Provision&nbsp;$svc_nbsp&nbsp;($num_avail)</A>";
575   if ( $conf->exists('legacy_link')
576        && $curuser->access_right('View/link unlinked services')
577      )
578   {
579     $link .= '<BR>'.
580              qq!<A CLASS="provision" HREF="${p}misc/link.cgi?!.
581              qq!$pkgnum_svcpart">!.
582             "Link&nbsp;to&nbsp;legacy&nbsp;$svc_nbsp&nbsp;($num_avail)</A>";
583   }
584   $link;
585 }
586
587 sub svc_unprovision_link {
588   my $cust_svc = shift or return '';
589   qq!<A HREF="javascript:areyousure('${p}misc/unprovision.cgi?!. $cust_svc->svcnum.
590   qq!', 'Permanently unprovision and delete this service?')">Unprovision</A>!;
591 }
592
593 sub pkg_datestr {
594   my($cust_pkg, $field, $conf) = @_ or return '';
595   return '&nbsp;' unless $cust_pkg->get($field);
596   my $format = '<TD align="left"><B>%b</B></TD>'.
597                '<TD align="right"><B>&nbsp;%o,</B></TD>'.
598                '<TD align="right"><B>&nbsp;%Y</B></TD>';
599   #$format .= '&nbsp;<FONT SIZE=-3>%l:%M:%S%P&nbsp;%z</FONT>'
600   $format .= '<TD ALIGN="right"><B>&nbsp;%l</TD>'.
601              '<TD ALIGN="center"><B>:</B></TD>'.
602              '<TD ALIGN="left"><B>%M</B></TD>'.
603              '<TD ALIGN="left"><B>&nbsp;%P</B></TD>'
604     if $conf->exists('cust_pkg-display_times');
605   my $strip = time2str($format, $cust_pkg->get($field) );
606   $strip =~ s/ (\d)/$1/g;
607   $strip;
608 }
609
610 sub pkg_change_link { include( '/elements/popup_link-cust_pkg.html',
611                                { 'action'      => $p. 'misc/change_pkg.cgi?dummy=value',
612                                  'label'       => 'Change&nbsp;package',
613                                  'actionlabel' => 'Change',
614                                  'cust_pkg'    => shift,
615                                }
616                              )
617                      }
618
619 sub pkg_suspend_link { include( '/elements/popup_link-cust_pkg.html',
620                                 { 'action'      => $p. 'misc/cancel_pkg.html?method=suspend',
621                                   'label'       => 'Suspend&nbsp;now',
622                                   'actionlabel' => 'Suspend',
623                                   'color'       => '#FF9900',
624                                   'cust_pkg'    => shift,
625                                 }
626                               )
627                      }
628
629
630 sub pkg_adjourn_link { include( '/elements/popup_link-cust_pkg.html',
631                                 { 'action'      => $p. 'misc/cancel_pkg.html?method=adjourn',
632                                   'label'       => 'Suspend&nbsp;later',
633                                   'actionlabel' => 'Adjourn',
634                                   'color'       => '#CC6600',
635                                   'cust_pkg'    => shift,
636                                 }
637                               )
638                      }
639
640 sub pkg_unsuspend_link { pkg_link('misc/unsusp_pkg',    'Unsuspend',           @_ ); }
641 sub pkg_dates_link     { pkg_link('edit/REAL_cust_pkg', 'Edit&nbsp;dates',     @_ ); }
642 sub pkg_unadjourn_link     { pkg_link('misc/unadjourn_pkg', 'Abort',               @_ ); }
643 sub pkg_unexpire_link      { pkg_link('misc/unexpire_pkg',  'Abort',               @_ ); }
644
645 sub pkg_cancel_link { include( '/elements/popup_link-cust_pkg.html',
646                                { 'action'      => $p. 'misc/cancel_pkg.html?method=cancel',
647                                  'label'       => 'Cancel&nbsp;now',
648                                  'actionlabel' => 'Cancel',
649                                  'color'       => '#ff0000',
650                                  'cust_pkg'    => shift,
651                                }
652                              )
653                     }
654
655 sub pkg_expire_link { include( '/elements/popup_link-cust_pkg.html',
656                                { 'action'      => $p. 'misc/cancel_pkg.html?method=expire',
657                                  'label'       => 'Cancel&nbsp;later',
658                                  'actionlabel' => 'Expire', #"Cancel package $num later"
659                                  'color'       => '#CC0000',
660                                  'cust_pkg'    => shift,
661                                }
662                              )
663                     }
664
665 sub svc_recharge_link { include( '/elements/popup_link-cust_svc.html',
666                                  { 'action'      => $p. 'misc/recharge_svc.html',
667                                    'label'       => 'Recharge',
668                                    'actionlabel' => 'Recharge',
669                                    'color'       => '#333399',
670                                    'cust_svc'    => shift,
671                                  }
672                                )
673                       }
674
675 sub order_pkg_link { include( '/elements/popup_link-cust_main.html',
676                               { 'action'      => $p. 'misc/order_pkg.html',
677                                 'label'       => 'Order&nbsp;new&nbsp;package',
678                                 'actionlabel' => 'Order new package',
679                                 'color'       => '#333399',
680                                 'cust_main'   => shift,
681                                 'closetext'   => 'Close',
682                               }
683                             )
684                    }
685
686 sub pkg_event_link {
687   my($cust_pkg) = @_;
688   qq!<a href="${p}search/cust_event.html?pkgnum=!. $cust_pkg->pkgnum. qq!">!.
689   'View package events'.
690   '</a>';
691 }
692
693 sub pkg_link {
694   my($action, $label, $cust_pkg) = @_;
695   return '' unless $cust_pkg;
696   qq!<a href="$p$action.cgi?!. $cust_pkg->pkgnum. qq!">$label</a>!;
697 }
698
699 sub pkg_customize_link {
700   my $cust_pkg = shift or return '';
701   my $custnum = $cust_pkg->custnum;
702   qq!<A HREF="${p}edit/part_pkg.cgi?!.
703     "clone=". $cust_pkg->part_pkg->pkgpart. ';'.
704     "pkgnum=". $cust_pkg->pkgnum.
705     qq!">Customize</A>!;
706 }
707
708 </%init>