X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=FS%2FFS%2Fprospect_main.pm;h=5d909a3ea0020ebc355708fe8b7c444e5311771d;hp=369029bab206be67e6952919444f842f82e0a323;hb=57bb423fe457ba4e13726877f53bcdf944f828f8;hpb=63a268637b2d51a8766412617724b9436439deb6 diff --git a/FS/FS/prospect_main.pm b/FS/FS/prospect_main.pm index 369029bab..5d909a3ea 100644 --- a/FS/FS/prospect_main.pm +++ b/FS/FS/prospect_main.pm @@ -1,16 +1,53 @@ package FS::prospect_main; +use base qw( FS::Quotable_Mixin FS::o2m_Common FS::Record ); use strict; -use base qw( FS::o2m_Common FS::Record ); -use vars qw( $DEBUG ); +use vars qw( $DEBUG @location_fields ); use Scalar::Util qw( blessed ); -use FS::Record qw( dbh qsearch ); #qsearchs ); -use FS::agent; +use FS::Conf; +use FS::Record qw( dbh qsearch qsearchs ); use FS::cust_location; -use FS::contact; +use FS::cust_main; $DEBUG = 0; +#started as false laziness w/cust_main/Location.pm + +use Carp qw(carp); + +my $init = 0; +BEGIN { + # set up accessors for location fields + if (!$init) { + no strict 'refs'; + @location_fields = + qw( address1 address2 city county state zip country district + latitude longitude coord_auto censustract censusyear geocode + addr_clean ); + + foreach my $f (@location_fields) { + *{"FS::prospect_main::$f"} = sub { + carp "WARNING: tried to set cust_main.$f with accessor" if (@_ > 1); + my @cust_location = shift->cust_location or return ''; + #arbitrarily picking the first because the UI only lets you add one + $cust_location[0]->$f + }; + } + $init++; + } +} + +#debugging shim--probably a performance hit, so remove this at some point +sub get { + my $self = shift; + my $field = shift; + if ( $DEBUG and grep { $_ eq $field } @location_fields ) { + carp "WARNING: tried to get() location field $field"; + $self->$field; + } + $self->FS::Record::get($field); +} + =head1 NAME FS::prospect_main - Object methods for prospect_main records @@ -41,14 +78,17 @@ from FS::Record. The following fields are currently supported: primary key -=item company +=item agentnum -company +Agent (see L) -=item locationnum +=item refnum -locationnum +Referral (see L) +=item company + +company =back @@ -203,14 +243,62 @@ sub check { my $error = $self->ut_numbern('prospectnum') - || $self->ut_foreign_key('agentnum', 'agent', 'agentnum' ) - || $self->ut_text('company') + || $self->ut_foreign_key( 'agentnum', 'agent', 'agentnum' ) + || $self->ut_foreign_keyn( 'refnum', 'part_referral', 'refnum' ) + || $self->ut_textn('company') + || $self->ut_foreign_keyn( 'taxstatusnum', 'tax_status', 'taxstatusnum' ) ; return $error if $error; + my $company = $self->company; + $company =~ s/^\s+//; + $company =~ s/\s+$//; + $company =~ s/\s+/ /g; + $self->company($company); + $self->SUPER::check; } +=item name + +Returns a name for this prospect, as a string (company name for commercial +prospects, contact name for residential prospects). + +=cut + +sub name { + my $self = shift; + return $self->company if $self->company; + + my $prospect_contact = ($self->prospect_contact)[0]; #first contact? good enough for now + my $contact = $prospect_contact->contact if $prospect_contact; + return $contact->line if $prospect_contact && $contact; + + #address? + + 'Prospect #'. $self->prospectnum; +} + +=item contact_firstlast + +If this prospect has a company, returns the empty string. If not, returns the +first contact's first and last name. + +Primarily intended for use in quotation substitutions, like the FS::cust_main +method of the same name. + +=cut + +sub contact_firstlast { + my $self = shift; + return '' if $self->company; + my @contacts = $self->contact; + #return '' unless @contacts; + warn $contacts[0]->first; + warn $contacts[0]->get('last'); + $contacts[0]->first. ' '. $contacts[0]->get('last'); +} + =item contact Returns the contacts (see L) associated with this prospect. @@ -219,7 +307,117 @@ Returns the contacts (see L) associated with this prospect. sub contact { my $self = shift; - qsearch( 'contact', { 'prospectnum' => $self->prospectnum } ); + my $search = { + table => 'contact', + addl_from => ' JOIN prospect_contact USING (contactnum)', + extra_sql => ' WHERE prospect_contact.prospectnum = '.$self->prospectnum, + }; + + #classnum argument like FS::cust_main->contact? + + qsearch($search); +} + +=item cust_location + +Returns the locations (see L) associated with this prospect. + +=cut + +sub cust_location { + my $self = shift; + qsearch({ + 'table' => 'cust_location', + 'hashref' => { 'prospectnum' => $self->prospectnum, + 'custnum' => '', + }, + 'order_by' => 'ORDER BY country, LOWER(state), LOWER(city), LOWER(county), LOWER(address1), LOWER(address2)', + }); +} + +=item qual + +Returns the qualifications (see L) associated with this prospect. + +=item agent + +Returns the agent (see L) for this customer. + +=item tax_status + +Returns the external tax status, as an FS::tax_status object, or the empty +string if there is no tax status. + +=cut + +sub tax_status { + my $self = shift; + if ( $self->taxstatusnum ) { + qsearchs('tax_status', { 'taxstatusnum' => $self->taxstatusnum } ); + } else { + return ''; + } +} + +=item taxstatus + +Returns the tax status code if there is one. + +=cut + +sub taxstatus { + my $self = shift; + my $tax_status = $self->tax_status; + $tax_status + ? $tax_status->taxstatus + : ''; +} + +=item convert_cust_main + +Converts this prospect to a customer. + +If there is an error, returns an error message, otherwise, returns the +newly-created FS::cust_main object. + +=cut + +sub convert_cust_main { + my $self = shift; + + my @cust_location = $self->cust_location; + #the interface only allows one, so we're just gonna go with that for now + + my @contact = map $_->contact, $self->prospect_contact; + + #XXX i'm not compatible with cust_main-require_phone (which is kind of a + # pre-contact thing anyway) + + my $cust_main = new FS::cust_main { + 'bill_location' => $cust_location[0], + 'ship_location' => $cust_location[0], + ( map { $_ => $self->$_ } qw( agentnum refnum company taxstatusnum ) ), + }; + + $cust_main->refnum( FS::Conf->new->config('referraldefault') || 1 ) + unless $cust_main->refnum; + + #XXX again, arbitrary, if one contact was "billing", that would be better + if ( $contact[0] ) { + $cust_main->set($_, $contact[0]->get($_)) foreach qw( first last ); + } else { + $cust_main->set('first', 'Unknown'); + $cust_main->set('last', 'Unknown'); + } + + #v3 payby no longer allowed + #$cust_main->payby('BILL'); + #$cust_main->paydate('12/2037'); + + $cust_main->insert( {}, + 'prospectnum' => $self->prospectnum, + ) + or $cust_main; } =item search HASHREF @@ -243,15 +441,18 @@ sub search { my @where = (); my $orderby; - ## - # parse agent - ## - + #agent if ( $params->{'agentnum'} =~ /^(\d+)$/ and $1 ) { push @where, "prospect_main.agentnum = $1"; } + #refnum + if ( $params->{'refnum'} =~ /^(\d+)$/ and $1 ) { + push @where, + "prospect_main.refnum = $1"; + } + ## # setup queries, subs, etc. for the search ## @@ -261,7 +462,7 @@ sub search { # here is the agent virtualization push @where, $FS::CurrentUser::CurrentUser->agentnums_sql; - my $extra_sql = scalar(@where) ? ' WHERE '. join(' AND ', @where) : ''; + my $extra_sql = scalar(@where) ? ' WHERE prospect_main.custnum IS NULL AND '. join(' AND ', @where) : ''; my $count_query = "SELECT COUNT(*) FROM prospect_main $extra_sql"; @@ -278,6 +479,16 @@ sub search { } +# stub this so that calling ->cust_bill doesn't return an empty string +sub cust_bill { + return; +} + +# XXX should have real localization here eventually +sub locale { + FS::Conf->new->config('locale'); +} + =back =head1 BUGS