[freeside-commits] freeside/FS/FS Schema.pm, 1.183, 1.184 AccessRight.pm, 1.45, 1.46 contact_email.pm, NONE, 1.1 contact_phone.pm, NONE, 1.1 contact.pm, NONE, 1.1 phone_type.pm, NONE, 1.1 prospect_main.pm, NONE, 1.1 Setup.pm, 1.19, 1.20 Upgrade.pm, 1.32, 1.33 Mason.pm, 1.22, 1.23 cust_location.pm, 1.5, 1.6 o2m_Common.pm, NONE, 1.1

Ivan,,, ivan at wavetail.420.am
Mon Dec 28 11:18:21 PST 2009


Update of /home/cvs/cvsroot/freeside/FS/FS
In directory wavetail.420.am:/tmp/cvs-serv11618/FS/FS

Modified Files:
	Schema.pm AccessRight.pm Setup.pm Upgrade.pm Mason.pm 
	cust_location.pm 
Added Files:
	contact_email.pm contact_phone.pm contact.pm phone_type.pm 
	prospect_main.pm o2m_Common.pm 
Log Message:
beginning of prospect/CRM/contact work

--- NEW FILE: contact_email.pm ---
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;


--- NEW FILE: o2m_Common.pm ---
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;


Index: Mason.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/Mason.pm,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- Mason.pm	19 Nov 2009 09:43:09 -0000	1.22
+++ Mason.pm	28 Dec 2009 19:18:18 -0000	1.23
@@ -224,6 +224,8 @@
   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 ) {

Index: cust_location.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/cust_location.pm,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- cust_location.pm	27 Dec 2009 01:00:48 -0000	1.5
+++ cust_location.pm	28 Dec 2009 19:18:18 -0000	1.6
@@ -4,6 +4,7 @@
 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 @@
 
   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 @@
   ;
   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 @@
 
   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 @@
   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;

Index: Setup.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/Setup.pm,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- Setup.pm	4 Oct 2009 02:04:49 -0000	1.19
+++ Setup.pm	28 Dec 2009 19:18:18 -0000	1.20
@@ -348,11 +348,12 @@
 
     #not yet....
 
-  #)
-
     #usage classes
     'usage_class' => [],
 
+    #phone types
+    'phone_type' => [],
+
   ;
 
   \%hash;

--- NEW FILE: contact_phone.pm ---
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;


--- NEW FILE: contact.pm ---
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;


--- NEW FILE: phone_type.pm ---
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;


Index: Schema.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/Schema.pm,v
retrieving revision 1.183
retrieving revision 1.184
diff -u -d -r1.183 -r1.184
--- Schema.pm	21 Dec 2009 14:44:09 -0000	1.183
+++ Schema.pm	28 Dec 2009 19:18:18 -0000	1.184
@@ -800,12 +800,84 @@
       '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 @@
       ],
       'primary_key' => 'locationnum',
       'unique'      => [],
-      'index'       => [ [ 'custnum' ],
+      'index'       => [ [ 'prospectnum' ], [ 'custnum' ],
                          [ 'county' ], [ 'state' ], [ 'country' ], [ 'zip' ],
                        ],
     },

--- NEW FILE: prospect_main.pm ---
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;


Index: AccessRight.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/AccessRight.pm,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -d -r1.45 -r1.46
--- AccessRight.pm	14 Dec 2009 01:41:28 -0000	1.45
+++ AccessRight.pm	28 Dec 2009 19:18:18 -0000	1.46
@@ -85,6 +85,20 @@
 
 #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

Index: Upgrade.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/Upgrade.pm,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- Upgrade.pm	19 Nov 2009 09:43:09 -0000	1.32
+++ Upgrade.pm	28 Dec 2009 19:18:18 -0000	1.33
@@ -126,6 +126,9 @@
     #usage_classes if we have none
     'usage_class' => [],
 
+    #phone_type if we have none
+    'phone_type' => [],
+
     #fixup access rights
     'access_right' => [],
 



More information about the freeside-commits mailing list