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