summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Kohler <ivan@freeside.biz>2014-09-16 06:41:00 -0700
committerIvan Kohler <ivan@freeside.biz>2014-09-16 06:41:00 -0700
commitd2acdd4d53071f9e0f9718e14532cb009cda1a85 (patch)
treed37bee5fe01624661dbd500aae4bb46b30283a2c
parenta1c723188509e9e251b233672e68327bb4ad42e7 (diff)
convert prospects to customers via quotations, RT#20688
-rw-r--r--FS/FS/prospect_main.pm53
-rw-r--r--FS/FS/quotation.pm73
-rw-r--r--httemplate/edit/prospect_main.html6
-rw-r--r--httemplate/search/prospect_main.html2
-rw-r--r--httemplate/view/prospect_main.html22
5 files changed, 152 insertions, 4 deletions
diff --git a/FS/FS/prospect_main.pm b/FS/FS/prospect_main.pm
index 55b12f2..5148143 100644
--- a/FS/FS/prospect_main.pm
+++ b/FS/FS/prospect_main.pm
@@ -6,6 +6,7 @@ use vars qw( $DEBUG @location_fields );
use Scalar::Util qw( blessed );
use FS::Record qw( dbh qsearch ); # qsearchs );
use FS::cust_location;
+use FS::cust_main;
$DEBUG = 0;
@@ -78,7 +79,11 @@ primary key
=item agentnum
-Agent
+Agent (see L<FS::agent>)
+
+=item refnum
+
+Referral (see L<FS::part_referral>)
=item company
@@ -237,7 +242,8 @@ sub check {
my $error =
$self->ut_numbern('prospectnum')
- || $self->ut_foreign_key('agentnum', 'agent', 'agentnum' )
+ || $self->ut_foreign_key( 'agentnum', 'agent', 'agentnum' )
+ || $self->ut_foreign_key( 'refnum', 'part_referral', 'refnum' )
|| $self->ut_textn('company')
;
return $error if $error;
@@ -292,6 +298,49 @@ Returns the qualifications (see L<FS::qual>) associated with this prospect.
Returns the agent (see L<FS::agent>) for this customer.
+=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 = $self->contact;
+
+ #XXX define one contact type as "billing", then we could pick just that one
+ my @invoicing_list = map $_->emailaddress, map $_->contact_email, @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 ) ),
+ };
+
+ #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');
+ }
+
+ $cust_main->insert( {}, \@invoicing_list,
+ 'prospectnum' => $self->prospectnum,
+ )
+ or $cust_main;
+}
+
=item search HASHREF
(Class method)
diff --git a/FS/FS/quotation.pm b/FS/FS/quotation.pm
index cf6652f..9d47857 100644
--- a/FS/FS/quotation.pm
+++ b/FS/FS/quotation.pm
@@ -3,7 +3,11 @@ use base qw( FS::Template_Mixin FS::cust_main_Mixin FS::otaker_Mixin FS::Record
);
use strict;
+use Tie::RefHash;
use FS::CurrentUser;
+use FS::UID qw( dbh );
+use FS::cust_main;
+use FS::cust_pkg;
=head1 NAME
@@ -194,6 +198,75 @@ sub _items_total {
sub enable_previous { 0 }
+=item convert_cust_main
+
+If this quotation already belongs to a customer, then returns that customer, as
+an FS::cust_main object.
+
+Otherwise, creates a new customer (FS::cust_main object and record, and
+associated) based on this quotation's prospect, then orders this quotation's
+packages as real packages for the 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_main = $self->cust_main;
+ return $cust_main if $cust_main; #already converted, don't again
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ $cust_main = $self->prospect_main->convert_cust_main;
+ unless ( ref($cust_main) ) { # eq 'FS::cust_main' ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $cust_main;
+ }
+
+ $self->prospectnum('');
+ $self->custnum( $cust_main->custnum );
+ my $error = $self->replace || $self->order;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+ $cust_main;
+
+}
+
+=item order
+
+This method is for use with quotations which are already associated with a customer.
+
+Orders this quotation's packages as real packages for the customer.
+
+If there is an error, returns an error message, otherwise returns false.
+
+=cut
+
+sub order {
+ my $self = shift;
+
+ tie my %cust_pkg, 'Tie::RefHash',
+ map { FS::cust_pkg->new({ pkgpart => $_->pkgpart,
+ quantity => $_->quantity,
+ })
+ => [] #services
+ }
+ $self->quotation_pkg ;
+
+ $self->cust_main->order_pkgs( \%cust_pkg );
+
+}
+
=back
=head1 CLASS METHODS
diff --git a/httemplate/edit/prospect_main.html b/httemplate/edit/prospect_main.html
index d398541..da5c6ce 100644
--- a/httemplate/edit/prospect_main.html
+++ b/httemplate/edit/prospect_main.html
@@ -3,6 +3,7 @@
'table' => 'prospect_main',
'labels' => { 'prospectnum' => 'Prospect',
'agentnum' => 'Agent',
+ 'refnum' => 'Advertising source',
'company' => 'Company',
'contactnum' => 'Contact',
'locationnum' => '&nbsp;',
@@ -13,6 +14,11 @@
'empty_label' => 'Select agent',
'colspan' => 6,
},
+ { 'field' => 'refnum',
+ 'type' => 'select-part_referral',
+ 'empty_label' => 'Select advertising source',
+ 'colspan' => 6,
+ },
{ 'field' => 'residential_commercial',
'type' => 'radio',
'options' => [ 'Residential', 'Commercial', ],
diff --git a/httemplate/search/prospect_main.html b/httemplate/search/prospect_main.html
index ab37b90..4798f58 100644
--- a/httemplate/search/prospect_main.html
+++ b/httemplate/search/prospect_main.html
@@ -23,6 +23,8 @@
'', #link to contact edit???
],
'agent_virt' => 1,
+ 'disableable' => 1,
+ 'disabled_statuspos' => 2,
&>
<%init>
diff --git a/httemplate/view/prospect_main.html b/httemplate/view/prospect_main.html
index 6c4595d..689b422 100644
--- a/httemplate/view/prospect_main.html
+++ b/httemplate/view/prospect_main.html
@@ -11,7 +11,11 @@
<TR>
<TD ALIGN="right">Prospect #</TD>
- <TD BGCOLOR="#FFFFFF"><B><% $prospectnum %></B></TD>
+ <TD BGCOLOR="#FFFFFF"><B><% $prospectnum %></B>
+% if ( $prospect_main->disabled ) {
+ <B>(DISABLED)</B>
+% }
+ </TD>
</TR>
%unless ( scalar(@agentnums) == 1
@@ -19,7 +23,15 @@
% my $agent = qsearchs('agent',{ 'agentnum' => $prospect_main->agentnum } );
<TR>
<TD ALIGN="right">Agent</TD>
- <TD BGCOLOR="#ffffff"><% $agent->agentnum %>: <% $agent->agent %></TD>
+ <TD BGCOLOR="#ffffff"><% $agent->agentnum %>: <% $agent->agent |h %></TD>
+ </TR>
+%}
+
+%unless ( ! $prospect_main->refnum ) { # || scalar(@part_referral) == 1 ) {
+% my $part_referral = qsearchs('part_referral',{ 'refnum' => $prospect_main->refnum } );
+ <TR>
+ <TD ALIGN="right">Advertising source</TD>
+ <TD BGCOLOR="#ffffff"><% $part_referral->referral |h %></TD>
</TR>
%}
@@ -76,6 +88,9 @@
<TR>
<TH CLASS="grid" BGCOLOR="#cccccc">#</TH>
<TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Date') |h %></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Setup') |h %></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Recurring') |h %></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"></TH>
</TR>
% foreach my $quotation (@quotations) {
% if ( $bgcolor eq $bgcolor1 ) {
@@ -88,6 +103,9 @@
<TR>
<TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $a %><% $quotation->quotationnum %></A></TD>
<TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $a %><% time2str($date_format, $quotation->_date) |h %></A></TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $a %><% $quotation->total_setup |h %></A></TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $a %><% $quotation->total_recur |h %></A></TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><A HREF="<%$p%>edit/process/quotation_convert.html?quotationnum=<% $quotation->quotationnum %>">Convert to customer</A></TD>
</TR>
% }
</TABLE>