fix A/R report
[freeside.git] / httemplate / search / cust_pkg_summary.cgi
1 <& elements/search.html,
2   'title'       => $title,
3   'name'        => 'package types',
4   'query'       => $query,
5   'count_query' => $count_query,
6   'header'      => \@head,
7   'fields'      => \@fields,
8   'links'       => \@links,
9   'align'       => 'clrrrrr',
10   'footer_data' => $totals,
11 &>
12 <%init>
13
14 my $curuser = $FS::CurrentUser::CurrentUser;
15
16 die "access denied"
17   unless $curuser->access_right('Summarize packages');
18
19 my $title = 'Package Summary Report';
20 my ($begin, $end) = FS::UI::Web::parse_beginning_ending($cgi);
21 if($begin > 0) {
22   $title = "$title (".
23     $cgi->param('beginning').' - '.$cgi->param('ending').')';
24 }
25
26 my $agentnums_sql = $curuser->agentnums_sql(
27                       'null'       => 1,
28                       'table'      => 'main',
29                     );
30
31 my $extra_sql = " freq != '0' AND $agentnums_sql";
32
33 #tiny bit of false laziness w/cust_pkg.pm::search
34 if ( grep { $_ eq 'classnum' } $cgi->param ) {
35   if ( $cgi->param('classnum') eq '' ) {
36     $extra_sql .= ' AND main.classnum IS NULL';
37   } elsif ( $cgi->param('classnum') =~ /^(\d+)$/ && $1 ne '0' ) {
38     $extra_sql .= " AND main.classnum = $1 ";
39   }
40 }
41
42 my $active_sql = 'setup IS NOT NULL AND susp IS NULL AND cancel IS NULL';
43 my $suspended_sql = 'setup IS NOT NULL AND susp IS NOT NULL AND cancel IS NULL';
44 my $active_or_suspended_sql = 'setup IS NOT NULL AND cancel IS NULL';
45 my %conds;
46
47 $conds{'before'} = { 'date' => $begin, 'status' => 'active,suspended' };
48 $conds{'after'}  = { 'date' => $end,   'status' => 'active,suspended' };
49 $conds{'active'} = { 'date' => $end,   'status' => 'active' };
50 $conds{'suspended'} = { 'date' => $end, 'status' => 'suspended' };
51
52 my @select;
53 my $totals = FS::part_pkg->new({pkg => 'Total'});
54 foreach my $column (keys %conds) {
55   my $h_search = FS::h_cust_pkg->search($conds{$column});
56   my $count_query = $h_search->{count_query};
57
58   # push a select expression for the total packages with pkgpart=main.pkgpart
59   # (have to quote $column, otherwise mysql thinks before/after are keywords)
60   push @select, "($count_query AND h_cust_pkg.pkgpart = main.pkgpart) AS \"$column\"";
61
62   # and query the total packages with pkgpart=any of the main.pkgparts
63   my $total = FS::Record->scalar_sql($count_query . 
64     " AND h_cust_pkg.pkgpart IN(SELECT pkgpart FROM part_pkg AS main WHERE $extra_sql)"
65   );
66   $totals->set($column => $total);
67 }
68
69 my $query = {
70   'table'       => 'part_pkg',
71   'addl_from'   => 'AS main',
72   'select'      => join(', ', 'main.*', @select),
73   'extra_sql'   => "WHERE $extra_sql",
74 };
75
76 my $count_query = "SELECT COUNT(*) FROM part_pkg AS main WHERE $extra_sql";
77
78 my $baselink = "h_cust_pkg.html?";
79 if ( $cgi->param('classnum') =~ /^\d*$/ ) {
80   $baselink .= "classnum=".$cgi->param('classnum').';';
81 }
82 my @links = ( #arguments to h_cust_pkg.html, except for pkgpart
83   '',
84   '',
85   [ $baselink . "status=active,suspended;date=$begin;pkgpart=", 'pkgpart' ],
86   '',
87   [ $baselink . "status=active,suspended;date=$end;pkgpart=", 'pkgpart' ],
88   [ $baselink . "status=active;date=$end;pkgpart=", 'pkgpart' ],
89   [ $baselink . "status=suspended;date=$end;pkgpart=", 'pkgpart' ],
90 );
91
92 my @head = ('#',
93             'Package',
94             'Before Period',
95             'Sales',
96             'Total',
97             'Active',
98             'Suspended');
99
100 my @fields = (
101   'pkgpart',
102   'pkg',
103   'before',
104   sub { $_[0]->after - $_[0]->before },
105   'after',
106   'active',
107   'suspended',
108   );
109
110 if ( !$begin ) {
111   # remove the irrelevant 'before' column
112   splice(@$_,2,1) foreach \@head, \@fields, \@links;
113 }
114
115 </%init>