Merge branch 'xss_fixes' of https://github.com/mcreenan/Freeside
[freeside.git] / httemplate / search / cust_pkg.cgi
1 <& elements/search.html,
2                   'html_init'   => $html_init, 
3                   'title'       => emt('Package Search Results'), 
4                   'name'        => 'packages',
5                   'query'       => $sql_query,
6                   'count_query' => $count_query,
7                   'header'      => [ emt('#'),
8                                      emt('Quan.'),
9                                      emt('Package'),
10                                      emt('Class'),
11                                      emt('Status'),
12                                      emt('Ordered by'),
13                                      emt('Setup'),
14                                      emt('Base Recur'),
15                                      emt('Freq.'),
16                                      emt('Setup'),
17                                      emt('Last bill'),
18                                      emt('Next bill'),
19                                      emt('Adjourn'),
20                                      emt('Susp.'),
21                                      emt('Susp. delay'),
22                                      emt('Expire'),
23                                      emt('Contract end'),
24                                      emt('Changed'),
25                                      emt('Cancel'),
26                                      emt('Reason'),
27                                      FS::UI::Web::cust_header(
28                                        $cgi->param('cust_fields')
29                                      ),
30                                      emt('Services'),
31                                    ],
32                   'fields'      => [
33                     'pkgnum',
34                     'quantity',
35                     sub { $_[0]->pkg; },
36                     'classname',
37                     sub { ucfirst(shift->status); },
38                     'otaker',
39                     sub { sprintf( $money_char.'%.2f',
40                                    shift->part_pkg->option('setup_fee'),
41                                  );
42                         },
43                     sub { my $c = shift;
44                           sprintf( $money_char.'%.2f',
45                                    $c->part_pkg->base_recur($c)
46                                  );
47                         },
48                     sub { FS::part_pkg::freq_pretty(shift); },
49
50                     ( map { time_or_blank($_) }
51           qw( setup last_bill bill adjourn susp dundate expire contract_end change_date cancel ) ),
52
53                     sub { my $self = shift;
54                           my $return = '';
55                           foreach my $action ( qw ( cancel susp ) ) {
56                             my $reason = $self->last_reason($action);
57                             $return = $reason->reason if $reason;
58                             last if $return;
59                           }
60                           $return;
61                         },
62
63                     \&FS::UI::Web::cust_fields,
64                     sub {
65                       my $cust_pkg = shift;
66                       my $type = $cgi->param('_type') || '';
67                       if ($type =~ /xls|csv/) {
68                         my $cust_svc = $cust_pkg->primary_cust_svc;
69                         if($cust_svc) {
70                           return join ": ",($cust_svc->label)[0,1];
71                         }
72                         else {
73                           return '';
74                         }
75                       }
76                       else {
77                           [ $process_svc_labels->( $cust_pkg ) ]
78                       }
79                     }
80                   ],
81                   'color' => [
82                     '',
83                     '',
84                     '',
85                     '',
86                     sub { shift->statuscolor; },
87                     '',
88                     '',
89                     '',
90                     '',
91                     '',
92                     '',
93                     '',
94                     '',
95                     '',
96                     '',
97                     '',
98                     '',
99                     '',
100                     '',
101                     '',
102                     FS::UI::Web::cust_colors(),
103                     '',
104                   ],
105                   'style' => [ '', '', '', '', 'b', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
106                                FS::UI::Web::cust_styles() ],
107                   'size'  => [ '', '', '', '', '-1' ],
108                   'align' => 'rrlcccrrlrrrrrrrrrrl'. FS::UI::Web::cust_aligns(). 'r',
109                   'links' => [
110                     $link,
111                     $link,
112                     $link,
113                     '',
114                     '',
115                     '',
116                     '',
117                     '',
118                     '',
119                     '',
120                     '',
121                     '',
122                     '',
123                     '',
124                     '',
125                     '',
126                     '', # link to changed-from package?
127                     '',
128                     '',
129                     '',
130                     ( map { $_ ne 'Cust. Status' ? $clink : '' }
131                           FS::UI::Web::cust_header(
132                                                     $cgi->param('cust_fields')
133                                                   )
134                     ),
135                     '',
136                   ],
137 &>
138 <%init>
139
140 my $curuser = $FS::CurrentUser::CurrentUser;
141
142 die "access denied"
143   unless $curuser->access_right('List packages');
144
145 my $conf = new FS::Conf;
146 my $money_char = $conf->config('money_char') || '$';
147
148 my %search_hash = ();
149
150 #some false laziness w/misc/bulk_change_pkg.cgi
151   
152 $search_hash{'query'} = $cgi->keywords;
153
154 #scalars
155 for (qw( agentnum custnum magic status custom cust_fields pkgbatch )) {
156   $search_hash{$_} = $cgi->param($_) if $cgi->param($_);
157 }
158
159 #arrays
160 for my $param (qw( pkgpart classnum )) {
161   $search_hash{$param} = [ $cgi->param($param) ]
162     if grep { $_ eq $param } $cgi->param;
163 }
164
165 #scalars that need to be passed if empty
166 for my $param (qw( censustract censustract2 )) {
167   $search_hash{$param} = $cgi->param($param) || ''
168     if grep { $_ eq $param } $cgi->param;
169 }
170
171 my $report_option = $cgi->param('report_option');
172 $search_hash{report_option} = $report_option if $report_option;
173
174 for my $param (grep /^report_option_any/, $cgi->param) {
175   $search_hash{$param} = $cgi->param($param);
176 }
177
178 ###
179 # parse dates
180 ###
181
182 #false laziness w/report_cust_pkg.html
183 my %disable = (
184   'all'             => {},
185   'one-time charge' => { 'last_bill'=>1, 'bill'=>1, 'adjourn'=>1, 'susp'=>1, 'expire'=>1, 'cancel'=>1, 'contract_end'=>1, 'dundate'=>1, },
186   'active'          => { 'susp'=>1, 'cancel'=>1 },
187   'suspended'       => { 'cancel' =>1, 'dundate'=>1, },
188   'cancelled'       => {},
189   ''                => {},
190 );
191
192 foreach my $field (qw( setup last_bill bill adjourn susp expire contract_end change_date cancel active )) {
193
194   my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi, $field);
195
196   next if $beginning == 0 && $ending == 4294967295
197        or $disable{$cgi->param('status')}->{$field};
198
199   $search_hash{$field} = [ $beginning, $ending ];
200
201 }
202
203 my $sql_query = FS::cust_pkg->search(\%search_hash);
204 my $count_query = delete($sql_query->{'count_query'});
205
206 my $show = $curuser->default_customer_view =~ /^(jumbo|packages)$/
207              ? ''
208              : ';show=packages';
209
210 my $link = sub {
211   my $self = shift;
212   my $frag = 'cust_pkg'. $self->pkgnum; #hack for IE ignoring real #fragment
213   [ "${p}view/cust_main.cgi?custnum=".$self->custnum.
214                            "$show;fragment=$frag#cust_pkg",
215     'pkgnum'
216   ];
217 };
218
219 my $clink = sub {
220   my $cust_pkg = shift;
221   $cust_pkg->cust_main_custnum
222     ? [ "${p}view/cust_main.cgi?", 'custnum' ] 
223     : '';
224 };
225
226 sub time_or_blank {
227    my $column = shift;
228    return sub {
229      my $record = shift;
230      my $value = $record->get($column); #mmm closures
231      $value ? time2str('%b %d %Y', $value ) : '';
232    };
233 }
234
235 my $html_init = sub {
236   my $query = shift;
237   my $text = '';
238   my $curuser = $FS::CurrentUser::CurrentUser;
239
240   if ( $curuser->access_right('Bulk change customer packages') ) {
241     $text .= include('/elements/init_overlib.html').
242              include( '/elements/popup_link.html',
243                'label'       => emt('Change these packages'),
244                'action'      => "${p}misc/bulk_change_pkg.cgi?$query",
245                'actionlabel' => emt('Change Packages'),
246                'width'       => 569,
247                'height'      => 210,
248              ). '<BR>';
249
250     if ( $curuser->access_right('Edit customer package dates') ) {
251       $text .= include( '/elements/popup_link.html',
252                  'label'       => emt('Increment next bill date'),
253                  'action'      => "${p}misc/bulk_pkg_increment_bill.cgi?$query",
254                  'actionlabel' => emt('Increment Bill Date'),
255                  'width'       => 569,
256                  'height'      => 210,
257               ). '<BR>';
258     }
259     $text .= include( '/elements/email-link.html',
260                 'search_hash' => \%search_hash,
261                 'table'       => 'cust_pkg',
262                 ). '<BR><BR>';
263   }
264   return $text;
265 };
266
267 my $large_pkg_size = $conf->config('cust_pkg-large_pkg_size');
268
269 my $process_svc_labels = sub {
270   my $cust_pkg = shift;
271   my @out;
272   foreach my $part_svc ( $cust_pkg->part_svc) {
273     # some false laziness with view/cust_main/packages/services.html
274
275     my $num_cust_svc = $cust_pkg->num_cust_svc( $part_svc->svcpart );
276
277     if ( $large_pkg_size > 0 and $large_pkg_size <= $num_cust_svc ) {
278       my $href = $p.'search/cust_pkg_svc.html?svcpart='.$part_svc->svcpart.
279           ';pkgnum='.$cust_pkg->pkgnum;
280       push @out, [
281         { 'data'  => $part_svc->svc . ':',
282           'align' => 'right',
283           'rowspan' => 2 },
284         { 'data'  => mt('(view all [_1])', $num_cust_svc),
285           'data_style' => 'b',
286           'align' => 'left',
287           'link'  => $href, },
288       ],
289       [
290         { 'data'  => include('/elements/search-cust_svc.html',
291                         'svcpart' => $part_svc->svcpart,
292                         'pkgnum'  => $cust_pkg->pkgnum,
293                     ),
294           'align' => 'left' },
295       ];
296     }
297     else {
298       foreach ( map { [ $_->label ] } @{ $part_svc->cust_pkg_svc } ) {
299         push @out, [ 
300         { 'data' => $_->[0]. ':',
301           'align'=> 'right', },
302         { 'data' => $_->[1],
303           'align'=> 'left',
304           'link' => $p. 'view/' .
305           $_->[2]. '.cgi?'. $_->[3], },
306         ];
307       }
308     }
309   } #foreach $cust_pkg
310   return @out;
311 };
312
313 </%init>