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