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