qualification search improvements, RT#7111
[freeside.git] / FS / FS / prospect_main.pm
1 package FS::prospect_main;
2
3 use strict;
4 use base qw( FS::o2m_Common FS::Record );
5 use vars qw( $DEBUG );
6 use Scalar::Util qw( blessed );
7 use FS::Record qw( dbh qsearch ); #qsearchs );
8 use FS::agent;
9 use FS::cust_location;
10 use FS::contact;
11
12 $DEBUG = 0;
13
14 =head1 NAME
15
16 FS::prospect_main - Object methods for prospect_main records
17
18 =head1 SYNOPSIS
19
20   use FS::prospect_main;
21
22   $record = new FS::prospect_main \%hash;
23   $record = new FS::prospect_main { 'column' => 'value' };
24
25   $error = $record->insert;
26
27   $error = $new_record->replace($old_record);
28
29   $error = $record->delete;
30
31   $error = $record->check;
32
33 =head1 DESCRIPTION
34
35 An FS::prospect_main object represents a prospect.  FS::prospect_main inherits
36 from FS::Record.  The following fields are currently supported:
37
38 =over 4
39
40 =item prospectnum
41
42 primary key
43
44 =item agentnum
45
46 Agent
47
48 =item company
49
50 company
51
52 =back
53
54 =head1 METHODS
55
56 =over 4
57
58 =item new HASHREF
59
60 Creates a new prospect.  To add the prospect to the database, see L<"insert">.
61
62 Note that this stores the hash reference, not a distinct copy of the hash it
63 points to.  You can ask the object for a copy with the I<hash> method.
64
65 =cut
66
67 sub table { 'prospect_main'; }
68
69 =item insert
70
71 Adds this record to the database.  If there is an error, returns the error,
72 otherwise returns false.
73
74 =cut
75
76 sub insert {
77   my $self = shift;
78   my %options = @_;
79   warn "FS::prospect_main::insert called on $self with options ".
80        join(', ', map "$_=>$options{$_}", keys %options)
81     if $DEBUG;
82
83   local $SIG{HUP} = 'IGNORE';
84   local $SIG{INT} = 'IGNORE';
85   local $SIG{QUIT} = 'IGNORE';
86   local $SIG{TERM} = 'IGNORE';
87   local $SIG{TSTP} = 'IGNORE';
88   local $SIG{PIPE} = 'IGNORE';
89
90   my $oldAutoCommit = $FS::UID::AutoCommit;
91   local $FS::UID::AutoCommit = 0;
92   my $dbh = dbh;
93
94   warn "  inserting prospect_main record" if $DEBUG;
95   my $error = $self->SUPER::insert;
96   if ( $error ) {
97     $dbh->rollback if $oldAutoCommit;
98     return $error;
99   }
100
101   if ( $options{'cust_location'} ) {
102     warn "  inserting cust_location record" if $DEBUG;
103     my $cust_location = $options{'cust_location'};
104     $cust_location->prospectnum($self->prospectnum);
105     $error = $cust_location->insert;
106     if ( $error ) {
107       $dbh->rollback if $oldAutoCommit;
108       return $error;
109     }
110   }
111
112   warn "  commiting transaction" if $DEBUG;
113   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
114
115   '';
116 }
117
118 =item delete
119
120 Delete this record from the database.
121
122 =cut
123
124 #delete dangling locations?
125
126 =item replace OLD_RECORD
127
128 Replaces the OLD_RECORD with this one in the database.  If there is an error,
129 returns the error, otherwise returns false.
130
131 =cut
132
133 sub replace {
134   my $new = shift;
135
136   my $old = ( blessed($_[0]) && $_[0]->isa('FS::Record') )
137               ? shift
138               : $new->replace_old;
139
140   my %options = @_;
141
142   warn "FS::prospect_main::replace called on $new to replace $old with options".
143        " ". join(', ', map "$_ => ". $options{$_}, keys %options)
144     if $DEBUG;
145
146   local $SIG{HUP} = 'IGNORE';
147   local $SIG{INT} = 'IGNORE';
148   local $SIG{QUIT} = 'IGNORE';
149   local $SIG{TERM} = 'IGNORE';
150   local $SIG{TSTP} = 'IGNORE';
151   local $SIG{PIPE} = 'IGNORE';
152
153   my $oldAutoCommit = $FS::UID::AutoCommit;
154   local $FS::UID::AutoCommit = 0;
155   my $dbh = dbh;
156
157   warn "  replacing prospect_main record" if $DEBUG;
158   my $error = $new->SUPER::replace($old);
159   if ( $error ) {
160     $dbh->rollback if $oldAutoCommit;
161     return $error;
162   }
163
164   if ( $options{'cust_location'} ) {
165     my $cust_location = $options{'cust_location'};
166     $cust_location->prospectnum($new->prospectnum);
167     my $method = $cust_location->locationnum ? 'replace' : 'insert';
168     warn "  ${method}ing cust_location record" if $DEBUG;
169     $error = $cust_location->$method();
170     if ( $error ) {
171       $dbh->rollback if $oldAutoCommit;
172       return $error;
173     }
174   } elsif ( exists($options{'cust_location'}) ) {
175     foreach my $cust_location (
176       qsearch('cust_location', { 'prospectnum' => $new->prospectnum } )
177     ) {
178       $error = $cust_location->delete();
179       if ( $error ) {
180         $dbh->rollback if $oldAutoCommit;
181         return $error;
182       }
183     }
184   }
185
186   warn "  commiting transaction" if $DEBUG;
187   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
188
189   '';
190 }
191
192 =item check
193
194 Checks all fields to make sure this is a valid prospect.  If there is
195 an error, returns the error, otherwise returns false.  Called by the insert
196 and replace methods.
197
198 =cut
199
200 sub check {
201   my $self = shift;
202
203   my $error = 
204     $self->ut_numbern('prospectnum')
205     || $self->ut_foreign_key('agentnum', 'agent', 'agentnum' )
206     || $self->ut_text('company')
207   ;
208   return $error if $error;
209
210   $self->SUPER::check;
211 }
212
213 =item name
214
215 =cut
216
217 sub name {
218   my $self = shift;
219   $self->company; #at least until this is nullable
220 }
221
222 =item contact
223
224 Returns the contacts (see L<FS::contact>) associated with this prospect.
225
226 =cut
227
228 sub contact {
229   my $self = shift;
230   qsearch( 'contact', { 'prospectnum' => $self->prospectnum } );
231 }
232
233 =item cust_location
234
235 Returns the locations (see L<FS::cust_location>) associated with this prospect.
236
237 =cut
238
239 sub cust_location {
240   my $self = shift;
241   qsearch( 'cust_location', { 'prospectnum' => $self->prospectnum } );
242 }
243
244 =item search HASHREF
245
246 (Class method)
247
248 Returns a qsearch hash expression to search for the parameters specified in
249 HASHREF.  Valid parameters are:
250
251 =over 4
252
253 =item agentnum
254
255 =back
256
257 =cut
258
259 sub search {
260   my( $class, $params ) = @_;
261
262   my @where = ();
263   my $orderby;
264
265   ##
266   # parse agent
267   ##
268
269   if ( $params->{'agentnum'} =~ /^(\d+)$/ and $1 ) {
270     push @where,
271       "prospect_main.agentnum = $1";
272   }
273
274   ##
275   # setup queries, subs, etc. for the search
276   ##
277
278   $orderby ||= 'ORDER BY prospectnum';
279
280   # here is the agent virtualization
281   push @where, $FS::CurrentUser::CurrentUser->agentnums_sql;
282
283   my $extra_sql = scalar(@where) ? ' WHERE '. join(' AND ', @where) : '';
284
285   my $count_query = "SELECT COUNT(*) FROM prospect_main $extra_sql";
286   
287   my $sql_query = {
288     'table'         => 'prospect_main',
289     #'select'        => $select,
290     'hashref'       => {},
291     'extra_sql'     => $extra_sql,
292     'order_by'      => $orderby,
293     'count_query'   => $count_query,
294     #'extra_headers' => \@extra_headers,
295     #'extra_fields'  => \@extra_fields,
296   };
297
298 }
299
300 =back
301
302 =head1 BUGS
303
304 =head1 SEE ALSO
305
306 L<FS::Record>, schema.html from the base documentation.
307
308 =cut
309
310 1;
311