hit the database slightly less. this page still takes forever with lots of
[freeside.git] / httemplate / search / cust_main.cgi
1 <%
2 #<!-- $Id: cust_main.cgi,v 1.13 2001-11-01 00:16:24 ivan Exp $ -->
3
4 use strict;
5 #use vars qw( $conf %ncancelled_pkgs %all_pkgs $cgi @cust_main $sortby );
6 use vars qw( $conf %all_pkgs $cgi @cust_main $sortby );
7 use CGI;
8 use CGI::Carp qw(fatalsToBrowser);
9 use IO::Handle;
10 use String::Approx qw(amatch);
11 use FS::UID qw(cgisuidsetup);
12 use FS::Record qw(qsearch qsearchs dbdef);
13 use FS::CGI qw(header menubar eidiot popurl table);
14 use FS::cust_main;
15 use FS::cust_svc;
16
17 $cgi = new CGI;
18 cgisuidsetup($cgi);
19
20 $conf = new FS::Conf;
21
22 if ( $cgi->param('browse') ) {
23   my $query = $cgi->param('browse');
24   if ( $query eq 'custnum' ) {
25     $sortby=\*custnum_sort;
26     @cust_main=qsearch('cust_main',{});  
27   } elsif ( $query eq 'last' ) {
28     $sortby=\*last_sort;
29     @cust_main=qsearch('cust_main',{});  
30   } elsif ( $query eq 'company' ) {
31     $sortby=\*company_sort;
32     @cust_main=qsearch('cust_main',{});
33   } else {
34     die "unknown browse field $query";
35   }
36 } else {
37   @cust_main=();
38   &cardsearch if $cgi->param('card_on') && $cgi->param('card');
39   &lastsearch if $cgi->param('last_on') && $cgi->param('last_text');
40   &companysearch if $cgi->param('company_on') && $cgi->param('company_text');
41   &referralsearch if $cgi->param('referral_custnum');
42 }
43
44 @cust_main = grep { $_->ncancelled_pkgs || ! $_->all_pkgs } @cust_main
45   if $cgi->param('showcancelledcustomers') eq '0' #see if it was set by me
46      || ( $conf->exists('hidecancelledcustomers')
47            && ! $cgi->param('showcancelledcustomers') );
48 if ( $conf->exists('hidecancelledpackages' ) ) {
49   %all_pkgs = map { $_->custnum => [ $_->ncancelled_pkgs ] } @cust_main;
50 } else {
51   %all_pkgs = map { $_->custnum => [ $_->all_pkgs ] } @cust_main;
52 }
53
54 if ( scalar(@cust_main) == 1 && ! $cgi->param('referral_custnum') ) {
55   print $cgi->redirect(popurl(2). "view/cust_main.cgi?". $cust_main[0]->custnum);
56   exit;
57 } elsif ( scalar(@cust_main) == 0 ) {
58   eidiot "No matching customers found!\n";
59 } else { 
60
61   my($total)=scalar(@cust_main);
62   print header("Customer Search Results",menubar(
63     'Main Menu', popurl(2)
64   )), "$total matching customers found ";
65   if ( $cgi->param('showcancelledcustomers') eq '0' #see if it was set by me
66        || ( $conf->exists('hidecancelledcustomers')
67             && ! $cgi->param('showcancelledcustomers')
68           )
69      ) {
70     $cgi->param('showcancelledcustomers', 1);
71     print qq!( <a href="!. $cgi->self_url. qq!">show cancelled customers</a> )!;
72   } else {
73     $cgi->param('showcancelledcustomers', 0);
74     print qq!( <a href="!. $cgi->self_url. qq!">hide cancelled customers</a> )!;
75   }
76   if ( $cgi->param('referral_custnum') ) {
77     $cgi->param('referral_custnum') =~ /^(\d+)$/
78       or eidiot "Illegal referral_custnum\n";
79     my $referral_custnum = $1;
80     my $cust_main = qsearchs('cust_main', { custnum => $referral_custnum } );
81     print '<FORM METHOD=POST>'.
82           qq!<INPUT TYPE="hidden" NAME="referral_custnum" VALUE="$referral_custnum">!.
83           'referrals of <A HREF="'. popurl(2).
84           "view/cust_main.cgi?$referral_custnum\">$referral_custnum: ".
85           ( $cust_main->company
86             || $cust_main->last. ', '. $cust_main->first ).
87           '</A>';
88     print "\n",<<END;
89       <SCRIPT>
90       function changed(what) {
91         what.form.submit();
92       }
93       </SCRIPT>
94 END
95     print ' <SELECT NAME="referral_depth" SIZE="1" onChange="changed(this)">';
96     my $max = 8; #config file
97     $cgi->param('referral_depth') =~ /^(\d*)$/ 
98       or eidiot "Illegal referral_depth";
99     my $referral_depth = $1;
100
101     foreach my $depth ( 1 .. $max ) {
102       print '<OPTION',
103             ' SELECTED'x($depth == $referral_depth),
104             ">$depth";
105     }
106     print "</SELECT> levels deep".
107           '<NOSCRIPT> <INPUT TYPE="submit" VALUE="change"></NOSCRIPT>'.
108           '</FORM>';
109   }
110   print "<BR>", &table(), <<END;
111       <TR>
112         <TH></TH>
113         <TH>(bill) name</TH>
114         <TH>company</TH>
115 END
116
117 if ( defined dbdef->table('cust_main')->column('ship_last') ) {
118   print <<END;
119       <TH>(service) name</TH>
120       <TH>company</TH>
121 END
122 }
123
124 print <<END;
125         <TH>Packages</TH>
126         <TH COLSPAN=2>Services</TH>
127       </TR>
128 END
129
130   my(%saw,$cust_main);
131   foreach $cust_main (
132     sort $sortby grep(!$saw{$_->custnum}++, @cust_main)
133   ) {
134     my($custnum,$last,$first,$company)=(
135       $cust_main->custnum,
136       $cust_main->getfield('last'),
137       $cust_main->getfield('first'),
138       $cust_main->company,
139     );
140
141     my(@lol_cust_svc);
142     my($rowspan)=0;#scalar( @{$all_pkgs{$custnum}} );
143     foreach ( @{$all_pkgs{$custnum}} ) {
144       my(@cust_svc) = qsearch( 'cust_svc', { 'pkgnum' => $_->pkgnum } );
145       push @lol_cust_svc, \@cust_svc;
146       $rowspan += scalar(@cust_svc) || 1;
147     }
148
149     #my($rowspan) = scalar(@{$all_pkgs{$custnum}});
150     my($view) = popurl(2). "view/cust_main.cgi?$custnum";
151     print <<END;
152     <TR>
153       <TD ROWSPAN=$rowspan><A HREF="$view"><FONT SIZE=-1>$custnum</FONT></A></TD>
154       <TD ROWSPAN=$rowspan><A HREF="$view"><FONT SIZE=-1>$last, $first</FONT></A></TD>
155       <TD ROWSPAN=$rowspan><A HREF="$view"><FONT SIZE=-1>$company</FONT></A></TD>
156 END
157     if ( defined dbdef->table('cust_main')->column('ship_last') ) {
158       my($ship_last,$ship_first,$ship_company)=(
159         $cust_main->ship_last || $cust_main->getfield('last'),
160         $cust_main->ship_last ? $cust_main->ship_first : $cust_main->first,
161         $cust_main->ship_last ? $cust_main->ship_company : $cust_main->company,
162       );
163 print <<END;
164       <TD ROWSPAN=$rowspan><A HREF="$view"><FONT SIZE=-1>$ship_last, $ship_first</FONT></A></TD>
165       <TD ROWSPAN=$rowspan><A HREF="$view"><FONT SIZE=-1>$ship_company</FONT></A></TD>
166 END
167     }
168
169     my($n1)='';
170     foreach ( @{$all_pkgs{$custnum}} ) {
171       my($pkgnum) = ($_->pkgnum);
172       my($pkg) = $_->part_pkg->pkg;
173       my $comment = $_->part_pkg->comment;
174       my($pkgview) = popurl(2). "/view/cust_pkg.cgi?$pkgnum";
175       my @cust_svc = @{shift @lol_cust_svc};
176       #my(@cust_svc) = qsearch( 'cust_svc', { 'pkgnum' => $_->pkgnum } );
177       my $rowspan = scalar(@cust_svc) || 1;
178
179       print $n1, qq!<TD ROWSPAN=$rowspan><A HREF="$pkgview"><FONT SIZE=-1>$pkg - $comment</FONT></A></TD>!;
180       my($n2)='';
181       foreach my $cust_svc ( @cust_svc ) {
182          my($label, $value, $svcdb) = $cust_svc->label;
183          my($svcnum) = $cust_svc->svcnum;
184          my($sview) = popurl(2). "/view";
185          print $n2,qq!<TD><A HREF="$sview/$svcdb.cgi?$svcnum"><FONT SIZE=-1>$label</FONT></A></TD>!,
186                qq!<TD><A HREF="$sview/$svcdb.cgi?$svcnum"><FONT SIZE=-1>$value</FONT></A></TD>!;
187          $n2="</TR><TR>";
188       }
189       #print qq!</TR><TR>\n!;
190       $n1="</TR><TR>";
191     }
192     print "</TR>";
193   }
194  
195   print <<END;
196     </TABLE>
197   </BODY>
198 </HTML>
199 END
200
201 }
202
203 #
204
205 sub last_sort {
206   $a->getfield('last') cmp $b->getfield('last');
207 }
208
209 sub company_sort {
210   return -1 if $a->company && ! $b->company;
211   return 1 if ! $a->company && $b->company;
212   $a->getfield('company') cmp $b->getfield('company');
213 }
214
215 sub custnum_sort {
216   $a->getfield('custnum') <=> $b->getfield('custnum');
217 }
218
219 sub cardsearch {
220
221   my($card)=$cgi->param('card');
222   $card =~ s/\D//g;
223   $card =~ /^(\d{13,16})$/ or eidiot "Illegal card number\n";
224   my($payinfo)=$1;
225
226   push @cust_main, qsearch('cust_main',{'payinfo'=>$payinfo, 'payby'=>'CARD'});
227   $sortby=\*last_sort;
228 }
229
230 sub referralsearch {
231   $cgi->param('referral_custnum') =~ /^(\d+)$/
232     or eidiot "Illegal referral_custnum";
233   my $cust_main = qsearchs('cust_main', { 'custnum' => $1 } )
234     or eidiot "Customer $1 not found";
235   my $depth;
236   if ( $cgi->param('referral_depth') ) {
237     $cgi->param('referral_depth') =~ /^(\d+)$/
238       or eidiot "Illegal referral_depth";
239     $depth = $1;
240   } else {
241     $depth = 1;
242   }
243   push @cust_main, $cust_main->referral_cust_main($depth);
244   $sortby=\*last_sort;
245 }
246
247 sub lastsearch {
248   my(%last_type);
249   foreach ( $cgi->param('last_type') ) {
250     $last_type{$_}++;
251   }
252
253   $cgi->param('last_text') =~ /^([\w \,\.\-\']*)$/
254     or eidiot "Illegal last name";
255   my($last)=$1;
256
257   if ( $last_type{'Exact'}
258        && ! $last_type{'Fuzzy'} 
259      #  && ! $last_type{'Sound-alike'}
260   ) {
261
262     push @cust_main, qsearch('cust_main',{'last'=>$last});
263
264     push @cust_main, qsearch('cust_main',{'ship_last'=>$last})
265       if defined dbdef->table('cust_main')->column('ship_last');
266
267   } else {
268
269     &FS::cust_main::check_and_rebuild_fuzzyfiles;
270     my $all_last = &FS::cust_main::all_last;
271
272     my %last;
273     if ($last_type{'Fuzzy'}) { 
274       foreach ( amatch($last, [ qw(i) ], @$all_last) ) {
275         $last{$_}++; 
276       }
277     }
278
279     #if ($last_type{'Sound-alike'}) {
280     #}
281
282     foreach ( keys %last ) {
283       push @cust_main, qsearch('cust_main',{'last'=>$_});
284       push @cust_main, qsearch('cust_main',{'ship_last'=>$_})
285         if defined dbdef->table('cust_main')->column('ship_last');
286     }
287
288   }
289   $sortby=\*last_sort;
290 }
291
292 sub companysearch {
293
294   my(%company_type);
295   foreach ( $cgi->param('company_type') ) {
296     $company_type{$_}++ 
297   };
298
299   $cgi->param('company_text') =~ /^([\w \,\.\-\']*)$/
300     or eidiot "Illegal company";
301   my($company)=$1;
302
303   if ( $company_type{'Exact'}
304        && ! $company_type{'Fuzzy'} 
305      #  && ! $company_type{'Sound-alike'}
306   ) {
307
308     push @cust_main, qsearch('cust_main',{'company'=>$company});
309
310     push @cust_main, qsearch('cust_main',{'ship_company'=>$company})
311       if defined dbdef->table('cust_main')->column('ship_last');
312
313   } else {
314
315     &FS::cust_main::check_and_rebuild_fuzzyfiles;
316     my $all_company = &FS::cust_main::all_company;
317
318     my %company;
319     if ($company_type{'Fuzzy'}) { 
320       foreach ( amatch($company, [ qw(i) ], @$all_company ) ) {
321         $company{$_}++;
322       }
323     }
324
325     #if ($company_type{'Sound-alike'}) {
326     #}
327
328     foreach ( keys %company ) {
329       push @cust_main, qsearch('cust_main',{'company'=>$_});
330       push @cust_main, qsearch('cust_main',{'ship_company'=>$_})
331         if defined dbdef->table('cust_main')->column('ship_last');
332     }
333
334   }
335   $sortby=\*company_sort;
336
337 }
338 %>