diff options
author | ivan <ivan> | 2009-12-28 19:20:25 +0000 |
---|---|---|
committer | ivan <ivan> | 2009-12-28 19:20:25 +0000 |
commit | 03ceab71dad1e5eb366865d304e5e459cc905ce4 (patch) | |
tree | 18b4532289a0237ae694b1ad5c033b25f448bd7c /FS | |
parent | 5950a980cef4968ac59ca8041d2204e6d98e7a3d (diff) |
beginning of prospect/CRM/contact work
Diffstat (limited to 'FS')
-rw-r--r-- | FS/FS.pm | 12 | ||||
-rw-r--r-- | FS/FS/AccessRight.pm | 14 | ||||
-rw-r--r-- | FS/FS/Mason.pm | 2 | ||||
-rw-r--r-- | FS/FS/Schema.pm | 78 | ||||
-rw-r--r-- | FS/FS/Setup.pm | 5 | ||||
-rw-r--r-- | FS/FS/Upgrade.pm | 3 | ||||
-rw-r--r-- | FS/FS/contact.pm | 177 | ||||
-rw-r--r-- | FS/FS/contact_email.pm | 128 | ||||
-rw-r--r-- | FS/FS/contact_phone.pm | 143 | ||||
-rw-r--r-- | FS/FS/cust_location.pm | 19 | ||||
-rw-r--r-- | FS/FS/o2m_Common.pm | 152 | ||||
-rw-r--r-- | FS/FS/phone_type.pm | 137 | ||||
-rw-r--r-- | FS/FS/prospect_main.pm | 292 | ||||
-rw-r--r-- | FS/MANIFEST | 11 | ||||
-rw-r--r-- | FS/t/contact.t | 5 | ||||
-rw-r--r-- | FS/t/contact_email.t | 5 | ||||
-rw-r--r-- | FS/t/contact_phone.t | 5 | ||||
-rw-r--r-- | FS/t/phone_type.t | 5 | ||||
-rw-r--r-- | FS/t/prospect_main.t | 5 |
19 files changed, 1187 insertions, 11 deletions
@@ -232,9 +232,19 @@ L<FS::reason> - Reason class L<FS::cust_pkg_reason> - Package reason class +L<FS::contact> - Contact class + +L<FS::contact_phone> - Contact phone class + +L<FS::phone_type> - Phone type class + +L<FS::contact_email> - Contact email class + +L<FS::prospect_main> - Prospect class + L<FS::cust_main> - Customer class -L<FS::cust_main_location> - Customer location class +L<FS::cust_location> - Customer location class L<FS::cust_main_Mixin> - Mixin class for records that contain fields from cust_main diff --git a/FS/FS/AccessRight.pm b/FS/FS/AccessRight.pm index 44235b113..8e771a9c0 100644 --- a/FS/FS/AccessRight.pm +++ b/FS/FS/AccessRight.pm @@ -85,6 +85,20 @@ assigned to users and/or groups. #well, this is what we have for now. getting better. tie my %rights, 'Tie::IxHash', + + ### + # contact rights + ### + 'Contact and Prospect rights' => [ + 'New prospect', + 'View prospect', + 'Edit prospect', + 'List prospects', + 'Edit contact', #! + #'New contact', + #'View customer contacts', + #'List contacts', + ], ### # basic customer rights diff --git a/FS/FS/Mason.pm b/FS/FS/Mason.pm index bef005881..cc15cd4d9 100644 --- a/FS/FS/Mason.pm +++ b/FS/FS/Mason.pm @@ -224,6 +224,8 @@ if ( -e $addl_handler_use_file ) { use FS::cust_statement; use FS::cust_class; use FS::cust_category; + use FS::prospect_main; + use FS::contact; # Sammath Naur if ( $FS::Mason::addl_handler_use ) { diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 7c6548a89..a039003c7 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -800,12 +800,84 @@ sub tables_hashref { 'index' => [], }, + #eventually for cust_main too + 'contact' => { + 'columns' => [ + 'contactnum', 'serial', '', '', '', '', + 'prospectnum', 'int', 'NULL', '', '', '', + 'custnum', 'int', 'NULL', '', '', '', + 'locationnum', 'int', 'NULL', '', '', '', #not yet +# 'titlenum', 'int', 'NULL', '', '', '', #eg Mr. Mrs. Dr. Rev. + 'last', 'varchar', '', $char_d, '', '', +# 'middle', 'varchar', 'NULL', $char_d, '', '', + 'first', 'varchar', '', $char_d, '', '', + 'title', 'varchar', '', $char_d, '', '', #eg Head Bottle Washer + 'comment', 'varchar', '', $char_d, '', '', + 'disabled', 'char', 'NULL', 1, '', '', + ], + 'primary_key' => 'contactnum', + 'unique' => [], + 'index' => [ [ 'prospectnum' ], [ 'custnum' ], [ 'locationnum' ], + [ 'last' ], [ 'first' ], + ], + }, + + 'contact_phone' => { + 'columns' => [ + 'contactphonenum', 'serial', '', '', '', '', + 'contactnum', 'int', '', '', '', '', + 'phonetypenum', 'int', '', '', '', '', + 'countrycode', 'varchar', '', 3, '', '', + 'phonenum', 'varchar', '', 14, '', '', + 'extension', 'varchar', '', 7, '', '', + #?#'comment', 'varchar', '', $char_d, '', '', + ], + 'primary_key' => 'contactphonenum', + 'unique' => [], + 'index' => [], + }, + + 'phone_type' => { + 'columns' => [ + 'phonetypenum', 'serial', '', '', '', '', + 'typename', 'varchar', '', $char_d, '', '', + 'weight', 'int', '', '', '', '', + ], + 'primary_key' => 'phonetypenum', + 'unique' => [ [ 'typename' ], ], + 'index' => [], + }, + + 'contact_email' => { + 'columns' => [ + 'contactemailnum', 'serial', '', '', '', '', + 'contactnum', 'int', '', '', '', '', + 'emailaddress', 'varchar', '', $char_d, '', '', + ], + 'primary_key' => 'contactemailnum', + 'unique' => [ [ 'emailaddress' ], ], + 'index' => [], + }, + + 'prospect_main' => { + 'columns' => [ + 'prospectnum', 'serial', '', '', '', '', + 'agentnum', 'int', '', '', '', '', + 'company', 'varchar', '', $char_d, '', '', + #'disabled', 'char', 'NULL', 1, '', '', + ], + 'primary_key' => 'prospectnum', + 'unique' => [], + 'index' => [ [ 'company' ], [ 'agentnum' ], ], + }, + #eventually use for billing & ship from cust_main too #for now, just cust_pkg locations - 'cust_location' => { + 'cust_location' => { #'location' now that its prospects too, but... 'columns' => [ 'locationnum', 'serial', '', '', '', '', - 'custnum', 'int', '', '', '', '', + 'prospectnum', 'int', 'NULL', '', '', '', + 'custnum', 'int', 'NULL', '', '', '', 'address1', 'varchar', '', $char_d, '', '', 'address2', 'varchar', 'NULL', $char_d, '', '', 'city', 'varchar', '', $char_d, '', '', @@ -817,7 +889,7 @@ sub tables_hashref { ], 'primary_key' => 'locationnum', 'unique' => [], - 'index' => [ [ 'custnum' ], + 'index' => [ [ 'prospectnum' ], [ 'custnum' ], [ 'county' ], [ 'state' ], [ 'country' ], [ 'zip' ], ], }, diff --git a/FS/FS/Setup.pm b/FS/FS/Setup.pm index edfe912ea..f8c59c5da 100644 --- a/FS/FS/Setup.pm +++ b/FS/FS/Setup.pm @@ -348,11 +348,12 @@ sub initial_data { #not yet.... - #) - #usage classes 'usage_class' => [], + #phone types + 'phone_type' => [], + ; \%hash; diff --git a/FS/FS/Upgrade.pm b/FS/FS/Upgrade.pm index c39680ef7..8cc5c61b8 100644 --- a/FS/FS/Upgrade.pm +++ b/FS/FS/Upgrade.pm @@ -126,6 +126,9 @@ sub upgrade_data { #usage_classes if we have none 'usage_class' => [], + #phone_type if we have none + 'phone_type' => [], + #fixup access rights 'access_right' => [], diff --git a/FS/FS/contact.pm b/FS/FS/contact.pm new file mode 100644 index 000000000..d3ab4118a --- /dev/null +++ b/FS/FS/contact.pm @@ -0,0 +1,177 @@ +package FS::contact; + +use strict; +use base qw( FS::Record ); +use FS::Record qw( qsearch qsearchs ); +use FS::prospect_main; +use FS::cust_main; +use FS::cust_location; + +=head1 NAME + +FS::contact - Object methods for contact records + +=head1 SYNOPSIS + + use FS::contact; + + $record = new FS::contact \%hash; + $record = new FS::contact { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::contact object represents an example. FS::contact inherits from +FS::Record. The following fields are currently supported: + +=over 4 + +=item contactnum + +primary key + +=item prospectnum + +prospectnum + +=item custnum + +custnum + +=item locationnum + +locationnum + +=item last + +last + +=item first + +first + +=item title + +title + +=item comment + +comment + +=item disabled + +disabled + + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new example. To add the example to the database, see L<"insert">. + +Note that this stores the hash reference, not a distinct copy of the hash it +points to. You can ask the object for a copy with the I<hash> method. + +=cut + +# the new method can be inherited from FS::Record, if a table method is defined + +sub table { 'contact'; } + +=item insert + +Adds this record to the database. If there is an error, returns the error, +otherwise returns false. + +=cut + +# the insert method can be inherited from FS::Record + +=item delete + +Delete this record from the database. + +=cut + +# the delete method can be inherited from FS::Record + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database. If there is an error, +returns the error, otherwise returns false. + +=cut + +# the replace method can be inherited from FS::Record + +=item check + +Checks all fields to make sure this is a valid example. If there is +an error, returns the error, otherwise returns false. Called by the insert +and replace methods. + +=cut + +# the check method should currently be supplied - FS::Record contains some +# data checking routines + +sub check { + my $self = shift; + + my $error = + $self->ut_numbern('contactnum') + || $self->ut_foreign_keyn('prospectnum', 'prospect_main', 'prospectnum') + || $self->ut_foreign_keyn('custnum', 'cust_main', 'custnum') + || $self->ut_foreign_keyn('locationnum', 'cust_location', 'locationnum') + || $self->ut_textn('last') + || $self->ut_textn('first') + || $self->ut_textn('title') + || $self->ut_textn('comment') + || $self->ut_enum('disabled', [ '', 'Y' ]) + ; + return $error if $error; + + return "No prospect or customer!" unless $self->prospectnum || $self->custnum; + return "Prospect and customer!" if $self->prospectnum && $self->custnum; + + return "One of first name, last name, or title must have a value" + if ! grep $self->$_(), qw( first last title); + + $self->SUPER::check; +} + +sub line { + my $self = shift; + my $data = $self->first. ' '. $self->last; + $data .= ', '. $self->title + if $self->title; + $data .= ' ('. $self->comment. ')' + if $self->comment; + $data; +} + +=back + +=head1 BUGS + +The author forgot to customize this manpage. + +=head1 SEE ALSO + +L<FS::Record>, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/contact_email.pm b/FS/FS/contact_email.pm new file mode 100644 index 000000000..1276d8d68 --- /dev/null +++ b/FS/FS/contact_email.pm @@ -0,0 +1,128 @@ +package FS::contact_email; + +use strict; +use base qw( FS::Record ); +use FS::Record qw( qsearch qsearchs ); + +=head1 NAME + +FS::contact_email - Object methods for contact_email records + +=head1 SYNOPSIS + + use FS::contact_email; + + $record = new FS::contact_email \%hash; + $record = new FS::contact_email { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::contact_email object represents an example. FS::contact_email inherits from +FS::Record. The following fields are currently supported: + +=over 4 + +=item contactemailnum + +primary key + +=item contactnum + +contactnum + +=item emailaddress + +emailaddress + + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new example. To add the example to the database, see L<"insert">. + +Note that this stores the hash reference, not a distinct copy of the hash it +points to. You can ask the object for a copy with the I<hash> method. + +=cut + +# the new method can be inherited from FS::Record, if a table method is defined + +sub table { 'contact_email'; } + +=item insert + +Adds this record to the database. If there is an error, returns the error, +otherwise returns false. + +=cut + +# the insert method can be inherited from FS::Record + +=item delete + +Delete this record from the database. + +=cut + +# the delete method can be inherited from FS::Record + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database. If there is an error, +returns the error, otherwise returns false. + +=cut + +# the replace method can be inherited from FS::Record + +=item check + +Checks all fields to make sure this is a valid example. If there is +an error, returns the error, otherwise returns false. Called by the insert +and replace methods. + +=cut + +# the check method should currently be supplied - FS::Record contains some +# data checking routines + +sub check { + my $self = shift; + + my $error = + $self->ut_numbern('contactemailnum') + || $self->ut_number('contactnum') + || $self->ut_text('emailaddress') + ; + return $error if $error; + + $self->SUPER::check; +} + +=back + +=head1 BUGS + +The author forgot to customize this manpage. + +=head1 SEE ALSO + +L<FS::Record>, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/contact_phone.pm b/FS/FS/contact_phone.pm new file mode 100644 index 000000000..bb9cf034d --- /dev/null +++ b/FS/FS/contact_phone.pm @@ -0,0 +1,143 @@ +package FS::contact_phone; + +use strict; +use base qw( FS::Record ); +use FS::Record qw( qsearch qsearchs ); + +=head1 NAME + +FS::contact_phone - Object methods for contact_phone records + +=head1 SYNOPSIS + + use FS::contact_phone; + + $record = new FS::contact_phone \%hash; + $record = new FS::contact_phone { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::contact_phone object represents an example. FS::contact_phone inherits from +FS::Record. The following fields are currently supported: + +=over 4 + +=item contactphonenum + +primary key + +=item contactnum + +contactnum + +=item phonetypenum + +phonetypenum + +=item countrycode + +countrycode + +=item phonenum + +phonenum + +=item extension + +extension + + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new example. To add the example to the database, see L<"insert">. + +Note that this stores the hash reference, not a distinct copy of the hash it +points to. You can ask the object for a copy with the I<hash> method. + +=cut + +# the new method can be inherited from FS::Record, if a table method is defined + +sub table { 'contact_phone'; } + +=item insert + +Adds this record to the database. If there is an error, returns the error, +otherwise returns false. + +=cut + +# the insert method can be inherited from FS::Record + +=item delete + +Delete this record from the database. + +=cut + +# the delete method can be inherited from FS::Record + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database. If there is an error, +returns the error, otherwise returns false. + +=cut + +# the replace method can be inherited from FS::Record + +=item check + +Checks all fields to make sure this is a valid example. If there is +an error, returns the error, otherwise returns false. Called by the insert +and replace methods. + +=cut + +# the check method should currently be supplied - FS::Record contains some +# data checking routines + +sub check { + my $self = shift; + + my $error = + $self->ut_numbern('contactphonenum') + || $self->ut_number('contactnum') + || $self->ut_number('phonetypenum') + || $self->ut_text('countrycode') + || $self->ut_text('phonenum') + || $self->ut_text('extension') + ; + return $error if $error; + + $self->SUPER::check; +} + +=back + +=head1 BUGS + +The author forgot to customize this manpage. + +=head1 SEE ALSO + +L<FS::Record>, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/cust_location.pm b/FS/FS/cust_location.pm index 87c6c3eb6..da586f00c 100644 --- a/FS/FS/cust_location.pm +++ b/FS/FS/cust_location.pm @@ -4,6 +4,7 @@ use strict; use base qw( FS::Record ); use Locale::Country; use FS::Record qw( qsearch ); #qsearchs ); +use FS::prospect_main; use FS::cust_main; use FS::cust_main_county; @@ -119,7 +120,8 @@ sub check { my $error = $self->ut_numbern('locationnum') - || $self->ut_foreign_key('custnum', 'cust_main', 'custnum') + || $self->ut_foreign_keyn('prospectnum', 'prospect_main', 'prospectnum') + || $self->ut_foreign_keyn('custnum', 'cust_main', 'custnum') || $self->ut_text('address1') || $self->ut_textn('address2') || $self->ut_text('city') @@ -131,6 +133,9 @@ sub check { ; return $error if $error; + return "No prospect or customer!" unless $self->prospectnum || $self->custnum; + return "Prospect and customer!" if $self->prospectnum && $self->custnum; + unless ( qsearch('cust_main_county', { 'country' => $self->country, 'state' => '', @@ -187,8 +192,10 @@ sub location_label { my $separator = $opt{join_string} || ', '; my $escape = $opt{escape_function} || sub{ shift }; + my $ds = $opt{double_space} || ' '; my $line = ''; - my $cydefault = FS::conf->new->config('countrydefault') || 'US'; + my $cydefault = + $opt{'countrydefault'} || FS::Conf->new->config('countrydefault') || 'US'; my $prefix = ''; my $notfirst = 0; @@ -202,11 +209,13 @@ sub location_label { foreach (qw ( city county state zip ) ) { my $method = "$prefix$_"; if ( $self->$method ) { - $line .= ' (' if $method eq 'county'; - $line .= ($notfirst ? ' ' : $separator). &$escape($self->$method); - $line .= ' )' if $method eq 'county'; + $line .= ($notfirst ? ($method eq 'zip' ? $ds : ' ') : $separator); + $line .= '(' if $method eq 'county'; + $line .= &$escape($self->$method); + $line .= ')' if $method eq 'county'; $notfirst++; } + $line .= ',' if $method eq 'county'; } $line .= $separator. &$escape(code2country($self->country)) if $self->country ne $cydefault; diff --git a/FS/FS/o2m_Common.pm b/FS/FS/o2m_Common.pm new file mode 100644 index 000000000..0e03b52ee --- /dev/null +++ b/FS/FS/o2m_Common.pm @@ -0,0 +1,152 @@ +package FS::o2m_Common; + +use strict; +use vars qw( $DEBUG $me ); +use Carp; +use FS::Schema qw( dbdef ); +use FS::Record qw( qsearch qsearchs dbh ); + +$DEBUG = 0; + +$me = '[FS::o2m_Common]'; + +=head1 NAME + +FS::o2m_Common - Mixin class for tables with a related table + +=head1 SYNOPSIS + +use FS::o2m_Common; + +@ISA = qw( FS::o2m_Common FS::Record ); + +=head1 DESCRIPTION + +FS::o2m_Common is intended as a mixin class for classes which have a +related table. + +=head1 METHODS + +=over 4 + +=item process_o2m OPTION => VALUE, ... + +Available options: + +table (required) - Table into which the records are inserted. + +num_col (optional) - Column in table which links to the primary key of the base table. If not specified, it is assumed this has the same name. + +params (required) - Hashref of keys and values, often passed as C<scalar($cgi->Vars)> from a form. + +fields (required) - Arrayref of field names for each record in table. Pulled from params as "pkeyNN_field" where pkey is table's primary key and NN is the entry's numeric identifier. + +=cut + +#a little more false laziness w/m2m_Common.pm than m2_name_Common.pm +# still, far from the worse of it. at least we're a reuable mixin! +sub process_o2m { + my( $self, %opt ) = @_; + + my $self_pkey = $self->dbdef_table->primary_key; + my $link_sourcekey = $opt{'num_col'} || $self_pkey; + + my $hashref = {}; #$opt{'hashref'} || {}; + $hashref->{$link_sourcekey} = $self->$self_pkey(); + + my $table = $self->_load_table($opt{'table'}); + my $table_pkey = dbdef->table($table)->primary_key; + +# my $link_static = $opt{'link_static'} || {}; + + warn "$me processing o2m from ". $self->table. ".$link_sourcekey". + " to $table\n" + if $DEBUG; + + #if ( ref($opt{'params'}) eq 'ARRAY' ) { + # $opt{'params'} = { map { $_=>1 } @{$opt{'params'}} }; + #} + + local $SIG{HUP} = 'IGNORE'; + local $SIG{INT} = 'IGNORE'; + local $SIG{QUIT} = 'IGNORE'; + local $SIG{TERM} = 'IGNORE'; + local $SIG{TSTP} = 'IGNORE'; + local $SIG{PIPE} = 'IGNORE'; + + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; + + my @fields = grep { /^$table_pkey\d+$/ } + keys %{ $opt{'params'} }; + + my %edits = map { $opt{'params'}->{$_} => $_ } + grep { $opt{'params'}->{$_} } + @fields; + + foreach my $del_obj ( + grep { ! $edits{$_->$table_pkey()} } + qsearch( $table, $hashref ) + ) { + my $error = $del_obj->delete; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } + + foreach my $pkey_value ( keys %edits ) { + my $old_obj = qsearchs( $table, { %$hashref, $table_pkey => $pkey_value } ), + my $add_param = $edits{$pkey_value}; + my %hash = ( $table_pkey => $pkey_value, + map { $_ => $opt{'params'}->{$add_param."_$_"} } + @{ $opt{'fields'} } + ); + #next unless grep { $_ =~ /\S/ } values %hash; + + my $new_obj = "FS::$table"->new( { %$hashref, %hash } ); + my $error = $new_obj->replace($old_obj); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } + + foreach my $add_param ( grep { ! $opt{'params'}->{$_} } @fields ) { + + my %hash = map { $_ => $opt{'params'}->{$add_param."_$_"} } + @{ $opt{'fields'} }; + next unless grep { $_ =~ /\S/ } values %hash; + + my $add_obj = "FS::$table"->new( { %$hashref, %hash } ); + my $error = $add_obj->insert; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } + + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + ''; +} + +sub _load_table { + my( $self, $table ) = @_; + eval "use FS::$table"; + die $@ if $@; + $table; +} + +=back + +=head1 BUGS + +=head1 SEE ALSO + +L<FS::Record> + +=cut + +1; + diff --git a/FS/FS/phone_type.pm b/FS/FS/phone_type.pm new file mode 100644 index 000000000..d2ef465bd --- /dev/null +++ b/FS/FS/phone_type.pm @@ -0,0 +1,137 @@ +package FS::phone_type; + +use strict; +use base qw( FS::Record ); +use FS::Record qw( qsearch ); # qsearchs ); + +=head1 NAME + +FS::phone_type - Object methods for phone_type records + +=head1 SYNOPSIS + + use FS::phone_type; + + $record = new FS::phone_type \%hash; + $record = new FS::phone_type { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::phone_type object represents an phone number type (for example: Work, +Home, Mobile, Fax). FS::phone_type inherits from FS::Record. The following +fields are currently supported: + +=over 4 + +=item phonetypenum + +Primary key + +=item typename + +Type name + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new type. To add the type to the database, see L<"insert">. + +Note that this stores the hash reference, not a distinct copy of the hash it +points to. You can ask the object for a copy with the I<hash> method. + +=cut + +sub table { 'phone_type'; } + +=item insert + +Adds this record to the database. If there is an error, returns the error, +otherwise returns false. + +=item delete + +Delete this record from the database. + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database. If there is an error, +returns the error, otherwise returns false. + +=item check + +Checks all fields to make sure this is a valid type. If there is +an error, returns the error, otherwise returns false. Called by the insert +and replace methods. + +=cut + +sub check { + my $self = shift; + + my $error = + $self->ut_numbern('phonetypenum') + || $self->ut_number('weight') + || $self->ut_text('typename') + ; + return $error if $error; + + $self->SUPER::check; +} + +# Used by FS::Setup to initialize a new database. +sub _populate_initial_data { + my ($class, %opts) = @_; + + my $weight = 10; + + foreach ("Work", "Home", "Mobile", "Fax") { + my $object = $class->new({ 'typename' => $_, + 'weight' => $weight, + }); + my $error = $object->insert; + die "error inserting $class into database: $error\n" + if $error; + + $weight += 10; + } + + ''; + +} + +# Used by FS::Upgrade to migrate to a new database. +sub _upgrade_data { + my $class = shift; + + return $class->_populate_initial_data(@_) + unless scalar( qsearch( 'phone_type', {} ) ); + + ''; + +} + +=back + +=head1 BUGS + +=head1 SEE ALSO + +L<FS::contact_phone>, L<FS::Record>, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/prospect_main.pm b/FS/FS/prospect_main.pm new file mode 100644 index 000000000..369029bab --- /dev/null +++ b/FS/FS/prospect_main.pm @@ -0,0 +1,292 @@ +package FS::prospect_main; + +use strict; +use base qw( FS::o2m_Common FS::Record ); +use vars qw( $DEBUG ); +use Scalar::Util qw( blessed ); +use FS::Record qw( dbh qsearch ); #qsearchs ); +use FS::agent; +use FS::cust_location; +use FS::contact; + +$DEBUG = 0; + +=head1 NAME + +FS::prospect_main - Object methods for prospect_main records + +=head1 SYNOPSIS + + use FS::prospect_main; + + $record = new FS::prospect_main \%hash; + $record = new FS::prospect_main { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::prospect_main object represents a prospect. FS::prospect_main inherits +from FS::Record. The following fields are currently supported: + +=over 4 + +=item prospectnum + +primary key + +=item company + +company + +=item locationnum + +locationnum + + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new prospect. To add the prospect to the database, see L<"insert">. + +Note that this stores the hash reference, not a distinct copy of the hash it +points to. You can ask the object for a copy with the I<hash> method. + +=cut + +sub table { 'prospect_main'; } + +=item insert + +Adds this record to the database. If there is an error, returns the error, +otherwise returns false. + +=cut + +sub insert { + my $self = shift; + my %options = @_; + warn "FS::prospect_main::insert called on $self with options ". + join(', ', map "$_=>$options{$_}", keys %options) + if $DEBUG; + + local $SIG{HUP} = 'IGNORE'; + local $SIG{INT} = 'IGNORE'; + local $SIG{QUIT} = 'IGNORE'; + local $SIG{TERM} = 'IGNORE'; + local $SIG{TSTP} = 'IGNORE'; + local $SIG{PIPE} = 'IGNORE'; + + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; + + warn " inserting prospect_main record" if $DEBUG; + my $error = $self->SUPER::insert; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + + if ( $options{'cust_location'} ) { + warn " inserting cust_location record" if $DEBUG; + my $cust_location = $options{'cust_location'}; + $cust_location->prospectnum($self->prospectnum); + $error = $cust_location->insert; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } + + warn " commiting transaction" if $DEBUG; + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + + ''; +} + +=item delete + +Delete this record from the database. + +=cut + +#delete dangling locations? + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database. If there is an error, +returns the error, otherwise returns false. + +=cut + +sub replace { + my $new = shift; + + my $old = ( blessed($_[0]) && $_[0]->isa('FS::Record') ) + ? shift + : $new->replace_old; + + my %options = @_; + + warn "FS::prospect_main::replace called on $new to replace $old with options". + " ". join(', ', map "$_ => ". $options{$_}, keys %options) + if $DEBUG; + + local $SIG{HUP} = 'IGNORE'; + local $SIG{INT} = 'IGNORE'; + local $SIG{QUIT} = 'IGNORE'; + local $SIG{TERM} = 'IGNORE'; + local $SIG{TSTP} = 'IGNORE'; + local $SIG{PIPE} = 'IGNORE'; + + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; + + warn " replacing prospect_main record" if $DEBUG; + my $error = $new->SUPER::replace($old); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + + if ( $options{'cust_location'} ) { + my $cust_location = $options{'cust_location'}; + $cust_location->prospectnum($new->prospectnum); + my $method = $cust_location->locationnum ? 'replace' : 'insert'; + warn " ${method}ing cust_location record" if $DEBUG; + $error = $cust_location->$method(); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } elsif ( exists($options{'cust_location'}) ) { + foreach my $cust_location ( + qsearch('cust_location', { 'prospectnum' => $new->prospectnum } ) + ) { + $error = $cust_location->delete(); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } + } + + warn " commiting transaction" if $DEBUG; + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + + ''; +} + +=item check + +Checks all fields to make sure this is a valid prospect. If there is +an error, returns the error, otherwise returns false. Called by the insert +and replace methods. + +=cut + +sub check { + my $self = shift; + + my $error = + $self->ut_numbern('prospectnum') + || $self->ut_foreign_key('agentnum', 'agent', 'agentnum' ) + || $self->ut_text('company') + ; + return $error if $error; + + $self->SUPER::check; +} + +=item contact + +Returns the contacts (see L<FS::contact>) associated with this prospect. + +=cut + +sub contact { + my $self = shift; + qsearch( 'contact', { 'prospectnum' => $self->prospectnum } ); +} + +=item search HASHREF + +(Class method) + +Returns a qsearch hash expression to search for the parameters specified in +HASHREF. Valid parameters are: + +=over 4 + +=item agentnum + +=back + +=cut + +sub search { + my( $class, $params ) = @_; + + my @where = (); + my $orderby; + + ## + # parse agent + ## + + if ( $params->{'agentnum'} =~ /^(\d+)$/ and $1 ) { + push @where, + "prospect_main.agentnum = $1"; + } + + ## + # setup queries, subs, etc. for the search + ## + + $orderby ||= 'ORDER BY prospectnum'; + + # here is the agent virtualization + push @where, $FS::CurrentUser::CurrentUser->agentnums_sql; + + my $extra_sql = scalar(@where) ? ' WHERE '. join(' AND ', @where) : ''; + + my $count_query = "SELECT COUNT(*) FROM prospect_main $extra_sql"; + + my $sql_query = { + 'table' => 'prospect_main', + #'select' => $select, + 'hashref' => {}, + 'extra_sql' => $extra_sql, + 'order_by' => $orderby, + 'count_query' => $count_query, + #'extra_headers' => \@extra_headers, + #'extra_fields' => \@extra_fields, + }; + +} + +=back + +=head1 BUGS + +=head1 SEE ALSO + +L<FS::Record>, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/MANIFEST b/FS/MANIFEST index 8a02a1338..74b06a88c 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -463,3 +463,14 @@ FS/class_Common.pm t/class_Common.t FS/category_Common.pm t/category_Common.t +FS/contact.pm +t/contact.t +FS/contact_phone.pm +t/contact_phone.t +FS/phone_type.pm +t/phone_type.t +FS/contact_email.pm +t/contact_email.t +FS/prospect_main.pm +t/prospect_main.t +FS/o2m_Common.pm diff --git a/FS/t/contact.t b/FS/t/contact.t new file mode 100644 index 000000000..bf22bd10b --- /dev/null +++ b/FS/t/contact.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::contact; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/contact_email.t b/FS/t/contact_email.t new file mode 100644 index 000000000..1cd13b628 --- /dev/null +++ b/FS/t/contact_email.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::contact_email; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/contact_phone.t b/FS/t/contact_phone.t new file mode 100644 index 000000000..493ced77a --- /dev/null +++ b/FS/t/contact_phone.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::contact_phone; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/phone_type.t b/FS/t/phone_type.t new file mode 100644 index 000000000..b6bc7935e --- /dev/null +++ b/FS/t/phone_type.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::phone_type; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/prospect_main.t b/FS/t/prospect_main.t new file mode 100644 index 000000000..045c2f041 --- /dev/null +++ b/FS/t/prospect_main.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::prospect_main; +$loaded=1; +print "ok 1\n"; |