<& elements/search.html, 'title' => $title, 'name' => 'packages', 'query' => $sql_query, 'count_query' => $count_query, 'header' => [ emt('#'), emt('Quantity'), emt('Package'), emt('Class'), emt('Sales Person'), emt('Ordered by'), emt('Setup Fee'), emt('Base Recur'), emt('Freq.'), emt('Setup'), emt('Last bill'), emt('Next bill'), emt('Susp.'), emt('Changed'), emt('Cancel'), @reason_header, FS::UI::Web::cust_header( $cgi->param('cust_fields') ), #emt('Services'), # even harder ], 'fields' => [ 'pkgnum', 'quantity', 'pkg', 'classname', 'salesperson', 'otaker', sub { sprintf( $money_char.'%.2f', shift->part_pkg->option('setup_fee'), ); }, sub { my $c = shift; sprintf( $money_char.'%.2f', $c->part_pkg->base_recur($c) ); }, sub { FS::part_pkg::freq_pretty(shift); }, ( map { time_or_blank($_) } qw( setup last_bill bill susp change_date cancel ) ), @reason_fields, \&FS::UI::Web::cust_fields, ], 'sort_fields' => [ 'cust_pkg.pkgnum', ('') x 5, # can use as-is ('') x 3, # can't use at all # use the plain SQL column names qw( setup last_bill bill susp change_date cancel ), @reason_blank, # cust_fields can take care of themselves ], 'color' => [ ('') x 15, @reason_blank, FS::UI::Web::cust_colors(), ], 'style' => [ ('') x 15, @reason_blank, FS::UI::Web::cust_styles() ], 'size' => [ '', '', '', '', '-1' ], 'align' => 'rrlcccrrlrrrrrr'.$reason_align. FS::UI::Web::cust_aligns(). 'r', 'links' => [ $link, $link, $link, ('') x 12, @reason_blank, ( map { $_ ne 'Cust. Status' ? $clink : '' } FS::UI::Web::cust_header( $cgi->param('cust_fields') ) ), ], &> <%once> my %title = ( 'active' => 'Active packages as of ', 'setup' => 'Packages started between ', 'cancel' => 'Packages canceled between ', 'susp' => 'Packages suspended between ', 'unsusp' => 'Packages unsuspended between ', ); <%init> my $curuser = $FS::CurrentUser::CurrentUser; die "access denied" unless $curuser->access_right('List packages'); my $conf = new FS::Conf; my $money_char = $conf->config('money_char') || '$'; my %search_hash = (); # pass a very limited set of parameters through #scalars for (qw( agentnum zip )) { $search_hash{$_} = $cgi->param($_) if length($cgi->param($_)); } #arrays / comma-separated lists for my $param (qw( pkgpart classnum refnum towernum )) { my @values = map { split(',') } $cgi->param($param); $search_hash{$param} = \@values if scalar(@values); } ### # do not pass dates to FS::cust_pkg->search; use the special churn_fromwhere # logic. ### my $pkg_query = FS::cust_pkg->search(\%search_hash); #warn Dumper $pkg_query; my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi); my $status = $cgi->param('status'); my $title = emt($title{$status}) . time2str('%b %o %Y', $beginning); if ($status ne 'active') { $title .= emt(' to ') . time2str('%b %o %Y', $ending); } my ($from, @where) = FS::h_cust_pkg->churn_fromwhere_sql($status, $beginning, $ending); push @where, "freq != '0'"; # split off the primary table name $from =~ s/^(\w+)(.*)$/$2/s; my $table = $1; # merge with $pkg_query $from .= ' ' . $pkg_query->{addl_from}; my $extra_sql; if ($pkg_query->{extra_sql}) { $extra_sql = $pkg_query->{extra_sql} . ' AND '; } else { $extra_sql = 'WHERE '; } $extra_sql .= join(' AND ', @where); my $sql_query = { 'select' => $pkg_query->{select}, 'table' => $table, 'addl_from' => $from, 'extra_sql' => $extra_sql, }; warn (Dumper $sql_query) if $cgi->param('debug'); my $count_query = "SELECT COUNT(*) FROM $table $from $extra_sql"; my $show = $curuser->default_customer_view =~ /^(jumbo|packages)$/ ? '' : ';show=packages'; my $link = sub { my $self = shift; my $frag = 'cust_pkg'. $self->pkgnum; #hack for IE ignoring real #fragment [ "${p}view/cust_main.cgi?custnum=".$self->custnum. "$show;fragment=$frag#cust_pkg", 'pkgnum' ]; }; my $clink = sub { my $cust_pkg = shift; $cust_pkg->cust_main_custnum ? [ "${p}view/cust_main.cgi?", 'custnum' ] : ''; }; sub time_or_blank { my $column = shift; return sub { my $record = shift; my $value = $record->get($column); #mmm closures $value ? time2str('%b %d %Y', $value ) : ''; }; } my (@reason_header,@reason_fields,@reason_blank); my $reason_align = ''; if ($status eq 'cancel') { push @reason_header, emt('Cancel Reason'); push @reason_fields, sub { my $c = shift; my $cust_pkg_reason = $c->last_cust_pkg_reason('cancel'); $cust_pkg_reason ? $cust_pkg_reason->reason->reason : ''; }; push @reason_blank, ''; $reason_align = 'l'; }