move query logic from perl to sql for scalability
[freeside.git] / httemplate / search / cust_bill.cgi
1 <%
2
3 my $conf = new FS::Conf;
4 my $maxrecords = $conf->config('maxsearchrecordsperpage');
5
6 my $orderby = ''; #removeme
7
8 my $limit = '';
9 $limit .= "LIMIT $maxrecords" if $maxrecords;
10
11 my $offset = $cgi->param('offset') || 0;
12 $limit .= " OFFSET $offset" if $offset;
13
14 my $total;
15
16 my(@cust_bill, $sortby);
17 if ( $cgi->keywords ) {
18   my($query) = $cgi->keywords;
19   my $open_sql =
20     "having 0 != charged - coalesce(sum(cust_bill_pay.amount),0)
21                          - coalesce(sum(cust_credit_bill.amount),0)";
22   my $having = '';
23   my $where = '';
24   if ( $query eq 'invnum' ) {
25     $sortby = \*invnum_sort;
26     #@cust_bill = qsearch('cust_bill', {} );
27   } elsif ( $query eq 'date' ) {
28     $sortby = \*date_sort;
29     #@cust_bill = qsearch('cust_bill', {} );
30   } elsif ( $query eq 'custnum' ) {
31     $sortby = \*custnum_sort;
32     #@cust_bill = qsearch('cust_bill', {} );
33   } elsif ( $query eq 'OPEN_invnum' ) {
34     $sortby = \*invnum_sort;
35     #@cust_bill = grep $_->owed != 0, qsearch('cust_bill', {} );
36     $having = $open_sql;
37   } elsif ( $query eq 'OPEN_date' ) {
38     $sortby = \*date_sort;
39     #@cust_bill = grep $_->owed != 0, qsearch('cust_bill', {} );
40     $having = $open_sql;
41   } elsif ( $query eq 'OPEN_custnum' ) {
42     $sortby = \*custnum_sort;
43     #@cust_bill = grep $_->owed != 0, qsearch('cust_bill', {} );
44     $having = $open_sql;
45   } elsif ( $query =~ /^OPEN(\d+)_invnum$/ ) {
46     my $open = $1 * 86400;
47     $sortby = \*invnum_sort;
48     #@cust_bill =
49     #  grep $_->owed != 0 && $_->_date < time - $open, qsearch('cust_bill', {} );
50     $having = $open_sql;
51     $where = "where cust_bill._date < ". (time-$open);
52   } elsif ( $query =~ /^OPEN(\d+)_date$/ ) {
53     my $open = $1 * 86400;
54     $sortby = \*date_sort;
55     #@cust_bill =
56     #  grep $_->owed != 0 && $_->_date < time - $open, qsearch('cust_bill', {} );
57     $having = $open_sql;
58     $where = "where cust_bill._date < ". (time-$open);
59   } elsif ( $query =~ /^OPEN(\d+)_custnum$/ ) {
60     my $open = $1 * 86400;
61     $sortby = \*custnum_sort;
62     #@cust_bill =
63     #  grep $_->owed != 0 && $_->_date < time - $open, qsearch('cust_bill', {} );
64     $having = $open_sql;
65     $where = "where cust_bill._date < ". (time-$open);
66   } else {
67     die "unknown query string $query";
68   }
69   @cust_bill = qsearch(
70     'cust_bill',
71     {},
72     'cust_bill.*,
73      charged - coalesce(sum(cust_bill_pay.amount),0)
74               - coalesce(sum(cust_credit_bill.amount),0) as owed',
75     "left outer join cust_bill_pay using ( invnum )
76      left outer join cust_credit_bill using ( invnum )
77      $where
78      group by ". join(', ', map "cust_bill.$_", fields('cust_bill') ). ' '.
79      $having
80   );
81 } else {
82   $cgi->param('invnum') =~ /^\s*(FS-)?(\d+)\s*$/;
83   my $invnum = $2;
84   @cust_bill = qsearchs('cust_bill', { 'invnum' => $invnum } );
85   $sortby = \*invnum_sort;
86 }
87
88 if ( scalar(@cust_bill) == 1 ) {
89   my $invnum = $cust_bill[0]->invnum;
90   print $cgi->redirect(popurl(2). "view/cust_bill.cgi?$invnum");  #redirect
91 } elsif ( scalar(@cust_bill) == 0 ) {
92 %>
93 <!-- mason kludge -->
94 <%
95   eidiot("Invoice not found.");
96 } else {
97 %>
98 <!-- mason kludge -->
99 <%
100   $total = scalar(@cust_bill);
101   print header("Invoice Search Results", menubar(
102           'Main Menu', popurl(2)
103         )), "$total matching invoices found<BR>", &table(), <<END;
104       <TR>
105         <TH></TH>
106         <TH>Balance</TH>
107         <TH>Amount</TH>
108         <TH>Date</TH>
109         <TH>Contact name</TH>
110         <TH>Company</TH>
111       </TR>
112 END
113
114   my(%saw, $cust_bill);
115   my($tot_balance, $tot_amount) = (0, 0);
116   foreach $cust_bill (
117     sort $sortby grep(!$saw{$_->invnum}++, @cust_bill)
118   ) {
119     my($invnum, $owed, $charged, $date ) = (
120       $cust_bill->invnum,
121       sprintf("%.2f", $cust_bill->owed),
122       sprintf("%.2f", $cust_bill->charged),
123       $cust_bill->_date,
124     );
125     my $pdate = time2str("%b %d %Y", $date);
126
127     $tot_balance += $owed;
128     $tot_amount += $charged;
129
130     my $rowspan = 1;
131
132     my $view = popurl(2). "view/cust_bill.cgi?$invnum";
133     print <<END;
134       <TR>
135         <TD ROWSPAN=$rowspan><A HREF="$view"><FONT SIZE=-1>$invnum</FONT></A></TD>
136         <TD ROWSPAN=$rowspan ALIGN="right"><A HREF="$view"><FONT SIZE=-1>\$$owed</FONT></A></TD>
137         <TD ROWSPAN=$rowspan ALIGN="right"><A HREF="$view"><FONT SIZE=-1>\$$charged</FONT></A></TD>
138         <TD ROWSPAN=$rowspan><A HREF="$view"><FONT SIZE=-1>$pdate</FONT></A></TD>
139 END
140     my $custnum = $cust_bill->custnum;
141     my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } );
142     if ( $cust_main ) {
143       my $cview = popurl(2). "view/cust_main.cgi?". $cust_main->custnum;
144       my ( $name, $company ) = (
145         $cust_main->last. ', '. $cust_main->first,
146         $cust_main->company,
147       );
148       print <<END;
149         <TD ROWSPAN=$rowspan><A HREF="$cview"><FONT SIZE=-1>$name</FONT></A></TD>
150         <TD ROWSPAN=$rowspan><A HREF="$cview"><FONT SIZE=-1>$company</FONT></A></TD>
151 END
152     } else {
153       print <<END
154         <TD ROWSPAN=$rowspan COLSPAN=2>WARNING: couldn't find cust_main.custnum $custnum (cust_bill.invnum $invnum)</TD>
155 END
156     }
157
158     print "</TR>";
159   }
160   $tot_balance = sprintf("%.2f", $tot_balance);
161   $tot_amount = sprintf("%.2f", $tot_amount);
162   print <<END;
163       <TR><TD></TD><TH><FONT SIZE=-1>Total</FONT></TH><TH><FONT SIZE=-1>Total</FONT></TH></TR>
164       <TR><TD></TD><TD ALIGN="right"><FONT SIZE=-1>\$$tot_balance</FONT></TD><TD ALIGN="right"><FONT SIZE=-1>\$$tot_amount</FONT></TD></TD></TR>
165     </TABLE>
166   </BODY>
167 </HTML>
168 END
169
170 }
171
172 #
173
174 sub invnum_sort {
175   $a->invnum <=> $b->invnum;
176 }
177
178 sub custnum_sort {
179   $a->custnum <=> $b->custnum || $a->invnum <=> $b->invnum;
180 }
181
182 sub date_sort {
183   $a->_date <=> $b->_date || $a->invnum <=> $b->invnum;
184 }
185 %>