allow non-integer minutes in CDR usage pools, #5738, see also #28308
[freeside.git] / httemplate / view / cust_main / packages / package.html
1 <TD CLASS="inv package" BGCOLOR="<% $bgcolor %>" VALIGN="top" <%$style%>>
2   <TABLE CLASS="inv package"> 
3
4
5     <TR>
6       <TD COLSPAN=2>
7         <% $opt{before_pkg_callback}
8              ? &{ $opt{before_pkg_callback} }( $cust_pkg )
9              : ''
10         %>
11         <A NAME="cust_pkg<% $cust_pkg->pkgnum %>"
12            ID  ="cust_pkg<% $cust_pkg->pkgnum %>"
13         ><% $opt{show_pkgnum} ? $cust_pkg->pkgnum.': ' : '' %><B><% $part_pkg->pkg |h %></B></A>
14 %
15 %       my $custom_comment;
16 %       if ( 0 && FS::part_pkg::flat->can('price_info') eq $part_pkg->can('price_info') ) {
17 %         #perf hack / disabled in 4.x (feature pricing / cust_pkg_usageprice incompatible, well, harder)
18 %
19 %         $part_pkg->{"_$_"} = $part_pkg->option($_) || 0
20 %           foreach grep !defined($part_pkg->{"_$_"} ), qw(setup_fee recur_fee);
21 %           
22 %         my $str = '';
23 %         $str = $opt{money_char} . $part_pkg->{_setup_fee}.
24 %                ($part_pkg->{_recur_fee} ? ' setup' : ' one-time')
25 %           if $part_pkg->{_setup_fee};
26 %         $str .= ', ' if $part_pkg->{_setup_fee} && $part_pkg->{_recur_fee};
27 %         $str .= $opt{money_char}. $part_pkg->{_recur_fee}.
28 %                 '/'. $part_pkg->freq_pretty
29 %           if $part_pkg->{_recur_fee};
30 %         $str;
31 %
32 %         $custom_comment = 
33 %           ( $part_pkg->custom ? '(CUSTOM) ' : '' ).
34 %           $part_pkg->comment.
35 %           ( ($part_pkg->custom || $part_pkg->comment) ? ' - ' : '' ).
36 %           ($str || 'No charge');
37 %
38 %       } else {
39 %         $custom_comment = $part_pkg->custom_comment('cust_pkg'=>$cust_pkg);
40 %       }
41         <% $custom_comment ? ' - ' : '' %>
42         <% $custom_comment |h %>
43       </TD>
44     </TR>
45
46
47     <TR>
48       <TD COLSPAN=2>
49         <FONT SIZE=-1>
50
51 %         if ( $part_pkg->freq eq '0' and !$opt{no_links} ) {
52 %           # One-time charge.  Nothing you can do with this, unless:
53 %           if ( $curuser->access_right('Modify one-time charge') ) {
54                 (&nbsp;<%onetime_change_link($cust_pkg)%>&nbsp;)
55                 <BR>
56 %           }
57 %
58 %         } elsif ( !$cust_pkg->get('cancel') and !$opt{no_links} ) {
59 %
60 %           if ( $change_from ) {
61 %             # This is the target package for a future change.
62 %             # Nothing you can do with it besides modify/cancel the 
63 %             # future change, and that's on the current package.
64 %           } elsif ( $supplemental ) {
65 %             # Supplemental packages can't be changed independently.
66 %             # Show only "Add comments" and "Add invoice details".
67 %           } else {
68 %             # the usual case: links to change package definition,
69 %             # discount, and customization
70 %             my $br = 0;
71 %             if ( $curuser->access_right('Change customer package') ) {
72 %               $br=1;
73                 (&nbsp;<%pkg_change_link($cust_pkg)%>&nbsp;)
74 %             } 
75 %
76 %             if ( $curuser->access_right('Discount customer package')
77 %                  && $part_pkg->can_discount
78 %                  && ! scalar( @{ $cust_pkg->{_cust_pkg_discount_active} } )
79 %                  && ! scalar($cust_pkg->part_pkg->part_pkg_discount)
80 %                )
81 %             {
82 %               $br=1;
83                 (&nbsp;<%pkg_discount_link($cust_pkg)%>&nbsp;)
84 %             }
85 %
86 %             if ( $curuser->access_right('Customize customer package') ) {
87 %               $br=1;
88                 (&nbsp;<%pkg_customize_link($cust_pkg,$part_pkg)%>&nbsp;)
89 %             } 
90 %
91               <% $br ? '<BR>' : '' %>
92 %           } 
93
94 %           if (    (    $curuser->access_right('Billing event reports')
95 %                     || $curuser->access_right('View customer billing events')
96 %                   )
97 %                && $cust_pkg->num_cust_event
98 %              ) {
99               (&nbsp;<%pkg_event_link($cust_pkg)%>&nbsp;)
100 %           }
101 %         } #!$supplemental
102
103         </FONT>
104       </TD>
105     </TR>
106
107
108     <TR>
109       <TD COLSPAN=2>
110
111 %       my $change_quan_label = 'Change quantity';
112 %       if ( $cust_pkg->quantity > 1 ) {
113 %         $change_quan_label = 'change';
114           &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<% mt('Quantity:') |h %> 
115           <B><% $cust_pkg->quantity %></B>
116 %       }
117
118 %       if ( $curuser->access_right('Change customer package')
119 %              && ! $cust_pkg->get('cancel')
120 %              && ! $supplemental
121 %              && $part_pkg->freq ne '0'
122 %              && ! $opt{no_links}
123 %              && $opt{'invoice-unitprice'}
124 %          )
125 %       {
126           <FONT SIZE="-1">
127             (&nbsp;<% pkg_change_quantity_link($cust_pkg, $change_quan_label) %>&nbsp;)
128           </FONT>
129 %       }
130
131       </TD>
132     </TR>
133
134
135     <TR>
136       <TD COLSPAN=2>
137
138 %       my $change_sales_label = 'Change sales person';
139 %       if ( $cust_pkg->salesnum ) {
140 %         $change_sales_label = 'change';
141           &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<% mt('Sales Person:') |h %> 
142           <B><% $cust_pkg->salesperson |h %></B>
143 %       }
144
145 %       if ( $curuser->access_right('Change customer package')
146 %              && ! $cust_pkg->get('cancel')
147 %              && ! $supplemental
148 %              #&& $part_pkg->freq ne '0'
149 %              && ! $opt{no_links}
150 %          )
151 %       {
152         <FONT SIZE="-1">
153           (&nbsp;<% pkg_change_salesnum_link($cust_pkg, $change_sales_label) %>&nbsp;)
154         </FONT>
155 %     }
156
157       </TD>
158     </TR>
159
160
161 %   my $editi = $curuser->access_right('Edit customer package invoice details');
162 %   my $editc = $curuser->access_right('Edit customer package comments');
163 %   my @cust_pkg_detail = $cust_pkg->cust_pkg_detail;
164 %   my @invoice_detail = grep { $_->detailtype eq 'I' } @cust_pkg_detail;
165 %   my @comments       = grep { $_->detailtype eq 'C' } @cust_pkg_detail;
166 %
167 %   if ( scalar(@invoice_detail) || scalar(@comments) || $editi || $editc ) {
168 %
169 %     my $editlink = $p. 'edit/cust_pkg_detail.html?pkgnum='. $cust_pkg->pkgnum.
170 %                    ';detailtype=';
171
172       <TR>
173
174 %       if ( @invoice_detail ) {
175           <TD VALIGN="top">
176             <& /elements/table-grid.html &>
177               <TR>
178                 <TH BGCOLOR="#dddddd" STYLE="border-bottom: dashed 1px black; padding-bottom: 1px">
179                   <FONT SIZE="-1">
180                     <% mt('Invoice details') |h %> 
181 %                   if ( $editi && ! $cust_pkg->get('cancel') && ! $opt{no_links} ) {
182                       (<& /elements/popup_link.html, { 
183                                     'action'      => $editlink. 'I',
184                                     'label'       => emt('edit'),
185                                     'actionlabel' => emt('Edit invoice details'),
186                                     'color'       => '#333399',
187                                     'width'       => 763,
188                                  }
189                        &>)
190 %                   }
191                   </FONT>
192                 </TH>
193               </TR>
194 %             foreach my $cust_pkg_detail ( @invoice_detail ) {
195                 <TR>
196                   <TD><FONT SIZE="-1">&nbsp;-&nbsp;<% $cust_pkg_detail->detail |h %></FONT></TD>
197                 </TR>
198 %             }
199             </TABLE>
200           </TD>
201 %       } else {
202           <TD>
203 %           if ( $editi && ! $cust_pkg->get('cancel') && ! $opt{no_links} ) {
204               <FONT SIZE="-1">
205                 (&nbsp;<% include('/elements/popup_link.html', { 
206                                'action'      => $editlink. 'I',
207                                'label'       => emt('Add invoice details'),
208                                'actionlabel' => emt('Add invoice details'),
209                                'color'       => '#333399',
210                                'width'       => 763,
211                             })
212                   %>&nbsp;)
213               </FONT>
214 %           }
215           </TD>
216 %       }
217
218 %       if ( @comments ) { 
219           <TD VALIGN="top">
220             <& /elements/table-grid.html &>
221               <TR>
222                 <TH BGCOLOR="#dddddd" STYLE="border-bottom: dashed 1px black; padding-bottom: 1px">
223                   <FONT SIZE="-1">
224                     <% mt('Comments') |h %> 
225 %                   if ( $editc && ! $opt{no_links} ) {
226                       (<& /elements/popup_link.html, { 
227                                     'action'      => $editlink. 'C',
228                                     'label'       => emt('edit'),
229                                     'actionlabel' => emt('Edit comments'),
230                                     'color'       => '#333399',
231                                     'width'       => 763,
232                                  }
233                        &>)
234 %                   }
235                   </FONT>
236                 </TH>
237               </TR>
238 %             foreach my $cust_pkg_detail ( @comments ) {
239                 <TR>
240                   <TD><FONT SIZE="-1">&nbsp;-&nbsp;<% $cust_pkg_detail->detail |h %></FONT></TD>
241                 </TR>
242 %             }
243             </TABLE>
244           </TD>
245 %       } else {
246           <TD>
247 %           if ( $editc && ! $opt{no_links} ) {
248               <FONT SIZE="-1">
249                 (&nbsp;<& /elements/popup_link.html, { 
250                                'action'      => $editlink. 'C',
251                                'label'       => emt('Add comments'),
252                                'actionlabel' => emt('Add comments'),
253                                'color'       => '#333399',
254                                'width'       => 763,
255                             }
256                   &>&nbsp;)
257               </FONT>
258 %           }
259           </TD>
260 %       }
261
262       </TR>
263
264
265 %   }
266   </TABLE>
267
268 % if ( @cust_pkg_usage ) {
269   <TABLE CLASS="usage inv">
270     <TR><TH COLSPAN=4><% mt('Included usage') %></TH></TR>
271 %   foreach my $usage (@cust_pkg_usage) {
272 %     my $part = $usage->part_pkg_usage;
273 %     my $ratio = 255 * ($usage->minutes / $part->minutes);
274 %     $ratio = 255 if $ratio > 255; # because rollover
275 %     my $color = sprintf('STYLE="font-weight: bold; color: #%02x%02x00"', 255 - $ratio, $ratio);
276 %     my $trstyle = '';
277 %     $trstyle = ' CLASS="shared"' if $part->shared;
278     <TR<%$trstyle%>>
279       <TD ALIGN="right"><% $part->description %>: </TD>
280       <TD <%$color%> ALIGN="right"><% sprintf('%.1f', $usage->minutes) %></TD>
281       <TD <%$color%>> / </TD>
282       <TD <%$color%>><% $part->minutes %></TD>
283 %     if ( $part->shared ) {
284       <TD><I>(shared)</I></TD>
285 %     }
286     </TR>
287 %   }
288   </TABLE>
289 % }
290
291 </TD>
292
293 <%init>
294
295 my %opt = @_;
296
297 my $bgcolor  = $opt{'bgcolor'};
298 my $cust_pkg = $opt{'cust_pkg'};
299 my $part_pkg = $opt{'part_pkg'};
300
301 my $curuser = $FS::CurrentUser::CurrentUser;
302
303 my $countrydefault = $opt{'countrydefault'} || 'US';
304 my $statedefault   = $opt{'statedefault'}
305                      || ($countrydefault eq 'US' ? 'CA' : '');
306
307 # put a marker on the left edge of this column
308 # if this package is somehow special
309 my $supplemental = $opt{'supplemental'} || 0;
310 my $change_from = $opt{'change_from'} || 0;
311 my $style = '';
312 if ( $supplemental or $change_from ) {
313   $style = 'border-left-width: '.($supplemental + $change_from)*30 . 'px; '.
314            'border-color: ';
315   if ( $supplemental ) {
316     $style .= '#bbbbff';
317   } elsif ( $change_from ) {
318     $style .= '#bbffbb';
319   }
320   $style = qq!STYLE="$style"!;
321 }
322
323 $cust_pkg->pkgnum =~ /^(\d+)$/;
324 my $pkgnum = $1;
325 my @cust_pkg_usage = qsearch({
326   'select'    => 'cust_pkg_usage.*',
327   'table'     => 'cust_pkg_usage',
328   'addl_from' => ' JOIN part_pkg_usage USING (pkgusagepart)',
329   'extra_sql' => " WHERE pkgnum = $1",
330   'order_by'  => ' ORDER BY priority ASC, description ASC',
331 });
332
333 #subroutines
334
335 #false laziness w/status.html
336 sub pkg_link {
337   my($action, $label, $cust_pkg) = @_;
338   return '' unless $cust_pkg;
339   qq!<a href="$p$action.cgi?!. $cust_pkg->pkgnum. qq!">$label</a>!;
340 }
341
342 sub pkg_change_link {
343   my $cust_pkg = shift;
344   my $locationnum = $cust_pkg->locationnum;
345   include( '/elements/popup_link-cust_pkg.html',
346     'action'      => $p. "misc/change_pkg.cgi?locationnum=$locationnum",
347     'label'       => emt('Change package'),
348     'actionlabel' => emt('Change'),
349     'cust_pkg'    => $cust_pkg,
350     'width'       => 960,
351     'height'      => 490,
352   );
353 }
354
355 sub onetime_change_link {
356   my $cust_pkg = shift;
357   my $pkgnum = $cust_pkg->pkgnum;
358   include( '/elements/popup_link-cust_pkg.html',
359     'action'      => $p. "edit/quick-charge.html?change_pkgnum=$pkgnum",
360     'label'       => emt('Modify one-time charge'),
361     'actionlabel' => emt('Modify'),
362     'cust_pkg'    => $cust_pkg,
363     'width'       => 690,
364     'height'      => 380,
365   );
366 }
367
368 sub pkg_change_location_link {
369   my $cust_pkg = shift;
370   my $pkgpart = $cust_pkg->pkgpart;
371   include( '/elements/popup_link-cust_pkg.html',
372     'action'      => $p. "misc/change_pkg.cgi?locationnum=-1;pkgpart=$pkgpart;".
373                      "address1=;address2=;city=;county=;state=$statedefault;".
374                      "zip=;country=$countrydefault",
375     'label'       => emt('Change location'),
376     'actionlabel' => emt('Change'),
377     'cust_pkg'    => $cust_pkg,
378     'width'       => 960,
379     'height'      => 490,
380   );
381 }
382
383 sub pkg_change_quantity_link {
384   my( $cust_pkg, $label ) = @_;
385   include( '/elements/popup_link-cust_pkg.html',
386     'action'      => $p. 'edit/cust_pkg_quantity.html?',
387     'label'       => emt($label),
388     'actionlabel' => emt('Change'),
389     'cust_pkg'    => $cust_pkg,
390     'width'       => 390,
391     'height'      => 220,
392   );
393 }
394
395 sub pkg_change_salesnum_link {
396   my( $cust_pkg, $label ) = @_;
397   include( '/elements/popup_link-cust_pkg.html',
398     'action'      => $p. 'edit/cust_pkg_salesnum.html?',
399     'label'       => emt($label),
400     'actionlabel' => emt('Change'),
401     'cust_pkg'    => $cust_pkg,
402     'width'       => 390,
403     'height'      => 220,
404   );
405 }
406
407 sub pkg_discount_link {
408   my $cust_pkg = shift or return '';
409   include( '/elements/popup_link-cust_pkg.html',
410     'action'      => $p.'edit/cust_pkg_discount.html',
411     'label'       => emt('Discount'),
412     'actionlabel' => emt('Discount'),
413     'cust_pkg'    => $cust_pkg,
414     'width'       => 616,
415   );
416 }
417
418 sub pkg_customize_link {
419   my $cust_pkg = shift or return '';
420   my $part_pkg = shift;
421   my $custnum = $cust_pkg->custnum;
422   qq!<A HREF="${p}edit/part_pkg.cgi?!.
423     "clone=". $part_pkg->pkgpart. ';'.
424     "pkgnum=". $cust_pkg->pkgnum.
425     qq!">!.emt('Customize').'</A>';
426 }
427
428 sub pkg_event_link {
429   my($cust_pkg) = @_;
430   qq!<a href="${p}search/cust_event.html?pkgnum=!. $cust_pkg->pkgnum. qq!">!.
431   emt('View package events').
432   '</a>';
433 }
434
435 </%init>