70ce991f704421abf275af1bac0093413b84ae37
[freeside.git] / htdocs / search / cust_main.cgi
1 #!/usr/bin/perl -Tw
2 #
3 # process/cust_main.cgi: Search for customers (process form)
4 #
5 # Usage: post form to:
6 #        http://server.name/path/cust_main.cgi
7 #
8 # Note: Should be run setuid freeside as user nobody.
9 #
10 # ivan@voicenet.com 96-dec-12
11 #
12 # rewrite ivan@sisd.com 98-mar-4
13 #
14 # now does browsing too ivan@sisd.com 98-mar-6
15 #
16 # Changes to allow page to work at a relative position in server
17 #       bmccane@maxbaud.net     98-apr-3
18 #
19 # display total, use FS::CGI ivan@sisd.com 98-jul-17
20
21 use strict;
22 use CGI::Request;
23 use CGI::Carp qw(fatalsToBrowser);
24 use IO::Handle;
25 use IPC::Open2;
26 use FS::UID qw(cgisuidsetup);
27 use FS::Record qw(qsearch qsearchs);
28 use FS::CGI qw(header idiot);
29
30 my($fuzziness)=2; #fuzziness for fuzzy searches, see man agrep
31                   #0-4: 0=no fuzz, 4=very fuzzy (too much fuzz!)
32
33 my($req)=new CGI::Request;
34 &cgisuidsetup($req->cgi);
35
36 my(@cust_main);
37 my($sortby);
38
39 my($query)=$req->cgi->var('QUERY_STRING');
40 if ( $query eq 'custnum' ) {
41   $sortby=\*custnum_sort;
42   @cust_main=qsearch('cust_main',{});  
43 } elsif ( $query eq 'last' ) {
44   $sortby=\*last_sort;
45   @cust_main=qsearch('cust_main',{});  
46 } elsif ( $query eq 'company' ) {
47   $sortby=\*company_sort;
48   @cust_main=qsearch('cust_main',{});  
49 } else {
50   &cardsearch if ($req->param('card_on') );
51   &lastsearch if ($req->param('last_on') );
52   &companysearch if ($req->param('company_on') );
53 }
54
55 if ( scalar(@cust_main) == 1 ) {
56   $req->cgi->redirect("../view/cust_main.cgi?". $cust_main[0]->custnum);
57   exit;
58 } elsif ( scalar(@cust_main) == 0 ) {
59   idiot "No matching customers found!\n";
60   exit;
61 } else { 
62
63   my($total)=scalar(@cust_main);
64   CGI::Base::SendHeaders(); # one guess
65   print header("Customer Search Results",''), <<END;
66
67     $total matching customers found
68     <TABLE BORDER=4 CELLSPACING=0 CELLPADDING=0>
69       <TR>
70         <TH>Cust. #</TH>
71         <TH>Contact name</TH>
72         <TH>Company</TH>
73       </TR>
74 END
75
76   my($lines)=16;
77   my($lcount)=$lines;
78   my(%saw,$cust_main);
79   foreach $cust_main (
80     sort $sortby grep(!$saw{$_->custnum}++, @cust_main)
81   ) {
82     my($custnum,$last,$first,$company)=(
83       $cust_main->custnum,
84       $cust_main->getfield('last'),
85       $cust_main->getfield('first'),
86       $cust_main->company,
87     );
88     print <<END;
89     <TR>
90       <TD><A HREF="../view/cust_main.cgi?$custnum"><FONT SIZE=-1>$custnum</FONT></A></TD>
91       <TD><FONT SIZE=-1>$last, $first</FONT></TD>
92       <TD><FONT SIZE=-1>$company</FONT></TD>
93     </TR>
94 END
95     if ($lcount-- == 0) { # lots of little tables instead of one big one
96       $lcount=$lines;
97       print <<END;   
98   </TABLE>
99   <TABLE BORDER=4 CELLSPACING=0 CELLPADDING=0>
100     <TR>
101       <TH>Cust. #</TH>
102       <TH>Contact name</TH>
103       <TH>Company<TH>
104     </TR>
105 END
106     }
107   }
108  
109   print <<END;
110     </TABLE>
111     </CENTER>
112   </BODY>
113 </HTML>
114 END
115
116 }
117
118 #
119
120 sub last_sort {
121   $a->getfield('last') cmp $b->getfield('last');
122 }
123
124 sub company_sort {
125   $a->getfield('company') cmp $b->getfield('company');
126 }
127
128 sub custnum_sort {
129   $a->getfield('custnum') <=> $b->getfield('custnum');
130 }
131
132 sub cardsearch {
133
134   my($card)=$req->param('card');
135   $card =~ s/\D//g;
136   $card =~ /^(\d{13,16})$/ or do { idiot "Illegal card number\n"; exit; };
137   my($payinfo)=$1;
138
139   push @cust_main, qsearch('cust_main',{'payinfo'=>$payinfo, 'payby'=>'CARD'});
140
141 }
142
143 sub lastsearch {
144   my(%last_type);
145   foreach ( $req->param('last_type') ) {
146     $last_type{$_}++;
147   }
148
149   $req->param('last_text') =~ /^([\w \,\.\-\']*)$/
150     or do { idiot "Illegal last name"; exit; };
151   my($last)=$1;
152
153   if ( $last_type{'Exact'}
154        && ! $last_type{'Fuzzy'} 
155      #  && ! $last_type{'Sound-alike'}
156   ) {
157
158     push @cust_main, qsearch('cust_main',{'last'=>$last});
159
160   } else {
161
162     my(%last);
163
164     my(@all_last)=map $_->getfield('last'), qsearch('cust_main',{});
165     if ($last_type{'Fuzzy'}) { 
166       my($reader,$writer) = ( new IO::Handle, new IO::Handle );
167       open2($reader,$writer,'agrep',"-$fuzziness",'-i','-k',
168             substr($last,0,30));
169       print $writer join("\n",@all_last),"\n";
170       close $writer;
171       while (<$reader>) {
172         chop;
173         $last{$_}++;
174       } 
175       close $reader;
176     }
177
178     #if ($last_type{'Sound-alike'}) {
179     #}
180
181     foreach ( keys %last ) {
182       push @cust_main, qsearch('cust_main',{'last'=>$_});
183     }
184
185   }
186   $sortby=\*last_sort;
187 }
188
189 sub companysearch {
190
191   my(%company_type);
192   foreach ( $req->param('company_type') ) {
193     $company_type{$_}++ 
194   };
195
196   $req->param('company_text') =~ /^([\w \,\.\-\']*)$/
197     or do { idiot "Illegal company"; exit; };
198   my($company)=$1;
199
200   if ( $company_type{'Exact'}
201        && ! $company_type{'Fuzzy'} 
202      #  && ! $company_type{'Sound-alike'}
203   ) {
204
205     push @cust_main, qsearch('cust_main',{'company'=>$company});
206
207   } else {
208
209     my(%company);
210     my(@all_company)=map $_->company, qsearch('cust_main',{});
211
212     if ($company_type{'Fuzzy'}) { 
213       my($reader,$writer) = ( new IO::Handle, new IO::Handle );
214       open2($reader,$writer,'agrep',"-$fuzziness",'-i','-k',
215             substr($company,0,30));
216       print $writer join("\n",@all_company),"\n";
217       close $writer;
218       while (<$reader>) {
219         chop;
220         $company{$_}++;
221       }
222       close $reader;
223     }
224
225     #if ($company_type{'Sound-alike'}) {
226     #}
227
228     foreach ( keys %company ) {
229       push @cust_main, qsearch('cust_main',{'company'=>$_});
230     }
231
232   }
233   $sortby=\*company_sort;
234
235 }