add agent type list to package def browse, RT#4880
[freeside.git] / httemplate / browse / part_pkg.cgi
1 <% include( 'elements/browse.html',
2                  'title'                 => 'Package Definitions',
3                  'html_init'             => $html_init,
4                  'name'                  => 'package definitions',
5                  'disableable'           => 1,
6                  'disabled_statuspos'    => 3,
7                  'agent_virt'            => 1,
8                  'agent_null_right'      => [ $edit, $edit_global ],
9                  'agent_null_right_link' => $edit_global,
10                  'agent_pos'             => 5,
11                  'query'                 => { 'select'    => $select,
12                                               'table'     => 'part_pkg',
13                                               'hashref'   => {},
14                                               'extra_sql' => $extra_sql,
15                                               'order_by'  => "ORDER BY $orderby"
16                                             },
17                  'count_query'           => $count_query,
18                  'header'                => \@header,
19                  'fields'                => \@fields,
20                  'links'                 => \@links,
21                  'align'                 => $align,
22              )
23 %>
24 <%init>
25
26 my $curuser = $FS::CurrentUser::CurrentUser;
27
28 my $edit        = 'Edit package definitions';
29 my $edit_global = 'Edit global package definitions';
30 my $acl_edit        = $curuser->access_right($edit);
31 my $acl_edit_global = $curuser->access_right($edit_global);
32 my $acl_config      = $curuser->access_right('Configuration'); #to edit services
33                                                                #and agent types
34
35 die "access denied"
36   unless $acl_edit || $acl_edit_global;
37
38 my $conf = new FS::Conf;
39 my $taxclasses = $conf->exists('enable_taxclasses');
40 my $money_char = $conf->config('money_char') || '$';
41
42 my $select = '*';
43 my $orderby = 'pkgpart';
44 if ( $cgi->param('active') ) {
45   $orderby = 'num_active DESC';
46 }
47
48 my $extra_sql = '';
49
50 unless ( $acl_edit_global ) {
51   $extra_sql .= ' WHERE '.  FS::part_pkg->curuser_pkgs_sql;
52 }
53
54 my $agentnums = join(',', $curuser->agentnums);
55 my $count_cust_pkg = "
56   SELECT COUNT(*) FROM cust_pkg LEFT JOIN cust_main USING ( custnum )
57     WHERE cust_pkg.pkgpart = part_pkg.pkgpart
58       AND cust_main.agentnum IN ($agentnums)
59 ";
60
61 $select = "
62
63   *,
64
65   ( $count_cust_pkg
66       AND ( cancel IS NULL OR cancel = 0 )
67       AND ( susp IS NULL OR susp = 0 )
68   ) AS num_active,
69
70   ( $count_cust_pkg
71       AND ( cancel IS NULL OR cancel = 0 )
72       AND susp IS NOT NULL AND susp != 0
73   ) AS num_suspended,
74
75   ( $count_cust_pkg
76       AND cancel IS NOT NULL AND cancel != 0
77   ) AS num_cancelled
78
79 ";
80
81 my $html_init;
82 #unless ( $cgi->param('active') ) {
83   $html_init = qq!
84     One or more service definitions are grouped together into a package 
85     definition and given pricing information.  Customers purchase packages
86     rather than purchase services directly.<BR><BR>
87     <FORM METHOD="POST" ACTION="${p}edit/part_pkg.cgi">
88     <A HREF="${p}edit/part_pkg.cgi"><I>Add a new package definition</I></A>
89     or
90     !.include('/elements/select-part_pkg.html', 'element_name' => 'clone' ). qq!
91     <INPUT TYPE="submit" VALUE="Clone existing package">
92     </FORM>
93     <BR><BR>
94   !;
95 #}
96
97 # ------
98
99 my $link = [ $p.'edit/part_pkg.cgi?', 'pkgpart' ];
100
101 my @header = ( '#', 'Package', 'Comment' );
102 my @fields = ( 'pkgpart', 'pkg', 'comment' );
103 my $align = 'rll';
104 my @links = ( $link, $link, '' );
105
106 unless ( 0 ) { #already showing only one class or something?
107   push @header, 'Class';
108   push @fields, sub { shift->classname || '(none)'; };
109   $align .= 'l';
110 }
111
112 tie my %plans, 'Tie::IxHash', %{ FS::part_pkg::plan_info() };
113
114 tie my %plan_labels, 'Tie::IxHash',
115   map {  $_ => ( $plans{$_}->{'shortname'} || $plans{$_}->{'name'} ) }
116       keys %plans;
117
118 push @header, 'Pricing';
119 $align .= 'r'; #?
120 push @fields, sub {
121   my $part_pkg = shift;
122   (my $plan = $plan_labels{$part_pkg->plan} ) =~ s/ /&nbsp;/g;
123   my $is_recur = ( $part_pkg->freq ne '0' );
124
125   [
126     [
127       { data =>$plan,
128         align=>'center',
129         colspan=>2,
130       },
131     ],
132     [
133       { data =>$money_char.
134                sprintf('%.2f', $part_pkg->option('setup_fee') ),
135         align=>'right'
136       },
137       { data => ( $is_recur ? ' setup' : ' one-time' ),
138         align=>'left',
139       },
140     ],
141     [
142       { data=>( $is_recur
143                   ? $money_char.sprintf('%.2f ', $part_pkg->option('recur_fee') )
144                   : $part_pkg->freq_pretty
145               ),
146         align=> ( $is_recur ? 'right' : 'center' ),
147         colspan=> ( $is_recur ? 1 : 2 ),
148       },
149       ( $is_recur
150         ?  { data => ( $is_recur ? $part_pkg->freq_pretty : '' ),
151              align=>'left',
152            }
153         : ()
154       ),
155     ],
156     ( map { 
157             my $dst_pkg = $_->dst_pkg;
158             [ 
159               { data => 'Add-on:&nbsp;'.$dst_pkg->pkg_comment,
160                 align=>'center', #?
161                 colspan=>2,
162               }
163             ]
164           }
165       $part_pkg->bill_part_pkg_link
166     ),
167   ];
168
169 #  $plan_labels{$part_pkg->plan}.'<BR>'.
170 #    $money_char.sprintf('%.2f setup<BR>', $part_pkg->option('setup_fee') ).
171 #    ( $part_pkg->freq ne '0'
172 #      ? $money_char.sprintf('%.2f ', $part_pkg->option('recur_fee') )
173 #      : ''
174 #    ).
175 #    $part_pkg->freq_pretty; #.'<BR>'
176 };
177
178 ###
179 # Agent goes here if displayed
180 ###
181
182 #agent type
183 if ( $acl_edit_global ) {
184   #really we just want a count, but this is fine unless someone has tons
185   my @all_agent_types = map {$_->typenum} qsearch('agent_type',{});
186   if ( scalar(@all_agent_types) > 1 ) {
187     push @header, 'Agent types';
188     my $typelink = $p. 'edit/agent_type.cgi?';
189     push @fields, sub { my $part_pkg = shift;
190                         [
191                           map { warn $_;
192                                 my $agent_type = $_->agent_type;
193                                 warn $agent_type;
194                                 [ 
195                                   { 'data'  => $agent_type->atype, #escape?
196                                     'align' => 'left',
197                                     'link'  => ( $acl_config
198                                                    ? $typelink.
199                                                      $agent_type->typenum
200                                                    : ''
201                                                ),
202                                   },
203                                 ];
204                               }
205                               $part_pkg->type_pkgs
206                         ];
207                       };
208     $align .= 'l';
209   }
210 }
211
212 #if ( $cgi->param('active') ) {
213   push @header, 'Customer<BR>packages';
214   my %col = (
215     'active'          => '00CC00',
216     'suspended'       => 'FF9900',
217     'cancelled'       => 'FF0000',
218     #'one-time charge' => '000000',
219     'charge'          => '000000',
220   );
221   my $cust_pkg_link = $p. 'search/cust_pkg.cgi?pkgpart=';
222   push @fields, sub { my $part_pkg = shift;
223                       [
224                         map {
225                               my $magic = $_;
226                               my $label = $_;
227                               if ( $magic eq 'active' && $part_pkg->freq == 0 ) {
228                                 $magic = 'inactive';
229                                 #$label = 'one-time charge',
230                                 $label = 'charge',
231                               }
232                           
233                               [
234                                 {
235                                  'data'  => '<B><FONT COLOR="#'. $col{$label}. '">'.
236                                             $part_pkg->get("num_$_").
237                                             '</FONT></B>',
238                                  'align' => 'right',
239                                 },
240                                 {
241                                  'data'  => $label.
242                                               ( $part_pkg->get("num_$_") != 1
243                                                 && $label =~ /charge$/
244                                                   ? 's'
245                                                   : ''
246                                               ),
247                                  'align' => 'left',
248                                  'link'  => ( $part_pkg->get("num_$_")
249                                                 ? $cust_pkg_link.
250                                                   $part_pkg->pkgpart.
251                                                   ";magic=$magic"
252                                                 : ''
253                                             ),
254                                 },
255                               ],
256                             } (qw( active suspended cancelled ))
257                       ]; };
258   $align .= 'r';
259 #}
260
261 if ( $taxclasses ) {
262   push @header, 'Taxclass';
263   push @fields, sub { shift->taxclass() || '&nbsp;'; };
264   $align .= 'l';
265 }
266
267 push @header, 'Plan options',
268               'Services';
269               #'Service', 'Quan', 'Primary';
270
271 push @fields, 
272               sub {
273                     my $part_pkg = shift;
274                     if ( $part_pkg->plan ) {
275
276                       my %options = $part_pkg->options;
277
278                       [ map { 
279                               [
280                                 { 'data'  => $_,
281                                   'align' => 'right',
282                                 },
283                                 { 'data'  => $part_pkg->format($_,$options{$_}),
284                                   'align' => 'left',
285                                 },
286                               ];
287                             }
288                         grep { $options{$_} =~ /\S/ } 
289                         grep { $_ !~ /^(setup|recur)_fee$/ }
290                         keys %options
291                       ];
292
293                     } else {
294
295                       [ map { [
296                                 { 'data'  => uc($_),
297                                   'align' => 'right',
298                                 },
299                                 {
300                                   'data'  => $part_pkg->$_(),
301                                   'align' => 'left',
302                                 },
303                               ];
304                             }
305                         (qw(setup recur))
306                       ];
307
308                     }
309
310                   },
311
312               sub {
313                     my $part_pkg = shift;
314
315                     [ 
316                       (map {
317                              my $pkg_svc = $_;
318                              my $part_svc = $pkg_svc->part_svc;
319                              my $svc = $part_svc->svc;
320                              if ( $pkg_svc->primary_svc =~ /^Y/i ) {
321                                $svc = "<B>$svc (PRIMARY)</B>";
322                              }
323                              $svc =~ s/ +/&nbsp;/g;
324
325                              [
326                                {
327                                  'data'  => '<B>'. $pkg_svc->quantity. '</B>',
328                                  'align' => 'right'
329                                },
330                                {
331                                  'data'  => $svc,
332                                  'align' => 'left',
333                                  'link'  => ( $acl_config
334                                                 ? $p. 'edit/part_svc.cgi?'.
335                                                   $part_svc->svcpart
336                                                 : ''
337                                             ),
338                                },
339                              ];
340                            }
341                       sort {     $b->primary_svc =~ /^Y/i
342                              <=> $a->primary_svc =~ /^Y/i
343                            }
344                            $part_pkg->pkg_svc('disable_linked'=>1)
345                       ),
346                       ( map { 
347                               my $dst_pkg = $_->dst_pkg;
348                               [
349                                 { data => 'Add-on:&nbsp;'.$dst_pkg->pkg_comment,
350                                   align=>'center', #?
351                                   colspan=>2,
352                                 }
353                               ]
354                             }
355                         $part_pkg->svc_part_pkg_link
356                       )
357                     ];
358
359                   };
360
361 $align .= 'lrl'; #rr';
362
363 # --------
364
365 my $count_query = "SELECT COUNT(*) FROM part_pkg $extra_sql";
366
367 </%init>