[freeside-commits] branch master updated. fec48523d3cf056da08813f9b2b7d633b27aaf8d

Mark Wells mark at 420.am
Thu Mar 1 12:35:39 PST 2012


The branch, master has been updated
       via  fec48523d3cf056da08813f9b2b7d633b27aaf8d (commit)
      from  0924aec8b98b4056357bfdd19f45686a3e9008e2 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit fec48523d3cf056da08813f9b2b7d633b27aaf8d
Author: Mark Wells <mark at freeside.biz>
Date:   Thu Mar 1 12:34:46 2012 -0800

    duplicate address checking for new customers, #16582

diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index d84ca00..4b2bc30 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -3603,6 +3603,17 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'cust_main-check_unique',
+    'section'     => '',
+    'description' => 'Warn before creating a customer record where these fields duplicate another customer.',
+    'type'        => 'select',
+    'multiple'    => 1,
+    'select_hash' => [ 
+      'address1' => 'Billing address',
+    ],
+  },
+
+  {
     'key'         => 'svc_acct-display_paid_time_remaining',
     'section'     => '',
     'description' => 'Show paid time remaining in addition to time remaining.',
diff --git a/httemplate/edit/cust_main.cgi b/httemplate/edit/cust_main.cgi
index 14825d0..d2c0cb7 100755
--- a/httemplate/edit/cust_main.cgi
+++ b/httemplate/edit/cust_main.cgi
@@ -195,7 +195,7 @@ function samechanged(what) {
     <INPUT TYPE="hidden" NAME="<% $hidden %>" VALUE="">
 % } 
 
-<& cust_main/bottomfixup.html &>
+<& cust_main/bottomfixup.html, 'custnum' => $custnum &>
 
 <BR>
 <INPUT TYPE    = "button"
diff --git a/httemplate/edit/cust_main/bottomfixup.html b/httemplate/edit/cust_main/bottomfixup.html
index 1b29c67..60edcc1 100644
--- a/httemplate/edit/cust_main/bottomfixup.html
+++ b/httemplate/edit/cust_main/bottomfixup.html
@@ -1,19 +1,23 @@
-<% include('/elements/init_overlib.html') %>
+<& /elements/init_overlib.html &>
 
-<% include( '/elements/xmlhttp.html',
-              'url'  => $p.'misc/xmlhttp-cust_main-address_standardize.html',
-              'subs' => [ 'address_standardize' ],
-              #'method' => 'POST', #could get too long?
-          )
-%>
+<& /elements/xmlhttp.html,
+  url  => $p.'misc/xmlhttp-cust_main-address_standardize.html',
+  subs => [ 'address_standardize' ],
+  #'method' => 'POST', #could get too long?
+&>
 
-<% include( '/elements/xmlhttp.html',
-              'url'  => $p.'misc/xmlhttp-cust_main-censustract.html',
-              'subs' => [ 'censustract' ],
-              #'method' => 'POST', #could get too long?
-          )
-%>
+<& /elements/xmlhttp.html,
+  url  => $p.'misc/xmlhttp-cust_main-censustract.html',
+  subs => [ 'censustract' ],
+  #'method' => 'POST', #could get too long?
+&>
+
+<INPUT TYPE="hidden" NAME="duplicate_of_custnum" VALUE="">
+<& /elements/xmlhttp.html,
+  url  => $p.'misc/xmlhttp-cust_main-duplicates.html',
+  subs => [ 'duplicates_form' ]
+&>
 
 <SCRIPT TYPE="text/javascript">
-  <% include('bottomfixup.js') %>
+<& bottomfixup.js, @_ &>
 </SCRIPT>
diff --git a/httemplate/edit/cust_main/bottomfixup.js b/httemplate/edit/cust_main/bottomfixup.js
index 6b30cbc..800864b 100644
--- a/httemplate/edit/cust_main/bottomfixup.js
+++ b/httemplate/edit/cust_main/bottomfixup.js
@@ -1,6 +1,48 @@
+<%init>
+my %opt = @_; # custnum
+my $conf = new FS::Conf;
+
+my $company_latitude  = $conf->config('company_latitude');
+my $company_longitude = $conf->config('company_longitude');
+
+my @fixups = ('copy_payby_fields', 'standardize_locations');
+
+push @fixups, 'fetch_censustract'
+    if $conf->exists('cust_main-require_censustract');
+
+push @fixups, 'check_unique'
+    if $conf->exists('cust_main-check_unique') and !$opt{'custnum'};
+
+push @fixups, 'do_submit'; # always last
+</%init>
+
+var fixups = <% encode_json(\@fixups) %>;
+var fixup_position;
+
+%# state machine to deal with all the asynchronous stuff we're doing
+%# call this after each fixup on success:
+function submit_continue() {
+  window[ fixups[fixup_position++] ].call();
+}
+
+%# or on failure:
+function submit_abort() {
+  fixup_position = 0;
+  document.CustomerForm.submitButton.disabled = false;
+  cClick();
+}
+
 function bottomfixup(what) {
+  fixup_position = 0;
+  document.CustomerForm.submitButton.disabled = true;
+  submit_continue();
+}
+
+function do_submit() {
+  document.CustomerForm.submit();
+}
 
-%# ../cust_main.cgi
+function copy_payby_fields() {
   var layervars = new Array(
     'payauto', 'billday',
     'payinfo', 'payinfo1', 'payinfo2', 'payinfo3', 'paytype',
@@ -18,20 +60,17 @@ function bottomfixup(what) {
                  cf.elements[field]
                );
   }
-
-  //this part does USPS address correction
-  standardize_locations();
-
+  submit_continue();
 }
 
+%# call submit_continue() on completion...
+%# otherwise not touching standardize_locations for now
 <% include( '/elements/standardize_locations.js',
-            'callback', 'post_geocode();'
+            'callback' => 'submit_continue();'
           )
 %>
 
-function post_geocode() {
-
-% if ( $conf->exists('cust_main-require_censustract') ) {
+function fetch_censustract() {
 
   //alert('fetch census tract data');
   var cf = document.CustomerForm;
@@ -46,12 +85,6 @@ function post_geocode() {
 
   censustract( census_data, update_censustract );
 
-% }else{
-
-  document.CustomerForm.submit();
-
-% }
-
 }
 
 var set_censustract;
@@ -77,7 +110,7 @@ function update_censustract(arg) {
   set_censustract = function () {
 
     cf.elements['censustract'].value = newcensus;
-    cf.submit();
+    submit_continue();
 
   }
 
@@ -112,12 +145,12 @@ function update_censustract(arg) {
 
     choose_censustract = choose_censustract +
       '<TR><TD ALIGN="center">' +
-        '<BUTTON TYPE="button" onClick="document.CustomerForm.submit();"><IMG SRC="<%$p%>images/error.png" ALT=""> Use entered census tract </BUTTON>' + 
+        '<BUTTON TYPE="button" onClick="submit_continue();"><IMG SRC="<%$p%>images/error.png" ALT=""> Use entered census tract </BUTTON>' + 
       '</TD><TD ALIGN="center">' +
         '<BUTTON TYPE="button" onClick="set_censustract();"><IMG SRC="<%$p%>images/tick.png" ALT=""> Use calculated census tract </BUTTON>' + 
       '</TD></TR>' +
       '<TR><TD COLSPAN=2 ALIGN="center">' +
-        '<BUTTON TYPE="button" onClick="document.CustomerForm.submitButton.disabled=false; parent.cClick();"><IMG SRC="<%$p%>images/cross.png" ALT=""> Cancel submission</BUTTON></TD></TR>' +
+        '<BUTTON TYPE="button" onClick="submit_abort();"><IMG SRC="<%$p%>images/cross.png" ALT=""> Cancel submission</BUTTON></TD></TR>' +
         
       '</TABLE></CENTER>';
 
@@ -125,7 +158,7 @@ function update_censustract(arg) {
 
   } else {
 
-    cf.submit();
+    submit_continue();
 
   }
 
@@ -153,12 +186,24 @@ function copyelement(from, to) {
   //alert(from + " (" + from.type + "): " + to.name + " => " + to.value);
 }
 
-<%init>
-
-my $conf = new FS::Conf;
+function check_unique() {
+  var search_hash = new Object;
+% foreach ($conf->config('cust_main-check_unique')) {
+  search_hash['<% $_ %>'] = document.CustomerForm.elements['<% $_ %>'].value;
+% }
 
-my $company_latitude  = $conf->config('company_latitude');
-my $company_longitude = $conf->config('company_longitude');
+%# supported in IE8+, Firefox 3.5+, WebKit, Opera 10.5+
+  duplicates_form(JSON.stringify(search_hash), confirm_unique);
+}
 
+function confirm_unique(arg) {
+  if ( arg.match(/\S/) ) {
+%# arg contains a complete form to choose an existing customer, or not
+  overlib( arg, CAPTION, 'Duplicate customer', STICKY, AUTOSTATUSCAP, 
+      CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, 
+      268, BGCOLOR, '#333399', CGCOLOR, '#333399', TEXTSIZE, 3 );
+  } else { // no duplicates
+    submit_continue();
+  }
+}
 
-</%init>
diff --git a/httemplate/edit/process/cust_main.cgi b/httemplate/edit/process/cust_main.cgi
index f75e2a6..994f9b7 100755
--- a/httemplate/edit/process/cust_main.cgi
+++ b/httemplate/edit/process/cust_main.cgi
@@ -66,6 +66,16 @@ my $new = new FS::cust_main ( {
   } fields('cust_main')
 } );
 
+$cgi->param('duplicate_of_custnum') =~ /^(\d+)$/;
+my $duplicate_of = $1;
+if ( $duplicate_of ) {
+  # then negate all changes to the customer; the only change we should
+  # make is to order a package, if requested
+  $new = qsearchs('cust_main', { 'custnum' => $duplicate_of })
+  # this should never happen
+    or die "nonexistent existing customer (custnum $duplicate_of)";
+}
+
 if ( defined($cgi->param('same')) && $cgi->param('same') eq "Y" ) {
   $new->setfield("ship_$_", '') foreach qw(
     last first company address1 address2 city county state zip
@@ -122,7 +132,7 @@ my @exempt_groups = grep /\S/, $conf->config('tax-cust_exempt-groups');
 my @tax_exempt = grep { $cgi->param("tax_$_") eq 'Y' } @exempt_groups;
 
 #perhaps this stuff should go to cust_main.pm
-if ( $new->custnum eq '' ) {
+if ( $new->custnum eq '' or $duplicate_of ) {
 
   my $cust_pkg = '';
   my $svc;
@@ -216,23 +226,31 @@ if ( $new->custnum eq '' ) {
 
   }
 
+
   use Tie::RefHash;
   tie my %hash, 'Tie::RefHash';
   %hash = ( $cust_pkg => [ $svc ] ) if $cust_pkg;
-  $error ||= $new->insert( \%hash, \@invoicing_list,
+  if ( $duplicate_of ) {
+    # order the package and service normally
+    $error ||= $new->order_pkgs( \%hash ) if $cust_pkg;
+  }
+  else {
+    # create the customer
+    $error ||= $new->insert( \%hash, \@invoicing_list,
                            'tax_exemption'=> \@tax_exempt,
                            'prospectnum'  => scalar($cgi->param('prospectnum')),
-                         );
+                           );
 
-  my $conf = new FS::Conf;
-  if ( $conf->exists('backend-realtime') && ! $error ) {
+    my $conf = new FS::Conf;
+    if ( $conf->exists('backend-realtime') && ! $error ) {
 
-    my $berror =    $new->bill
-                 || $new->apply_payments_and_credits
-                 || $new->collect( 'realtime' => 1 );
-    warn "Warning, error billing during backend-realtime: $berror" if $berror;
+      my $berror =    $new->bill
+                   || $new->apply_payments_and_credits
+                   || $new->collect( 'realtime' => 1 );
+      warn "Warning, error billing during backend-realtime: $berror" if $berror;
 
-  }
+    }
+  } #if $duplicate_of
   
 } else { #create old record object
 
diff --git a/httemplate/misc/xmlhttp-cust_main-duplicates.html b/httemplate/misc/xmlhttp-cust_main-duplicates.html
new file mode 100644
index 0000000..6654b3e
--- /dev/null
+++ b/httemplate/misc/xmlhttp-cust_main-duplicates.html
@@ -0,0 +1,68 @@
+% if ( @cust_main ) {
+<CENTER><BR><B>Duplicate customer</B><BR>
+Choose an existing customer
+<TABLE WIDTH="300px">
+<FORM name="DuplicateForm">
+% foreach (@cust_main) {
+%   my $custnum = $_->custnum;
+<TR>
+  <TD ALIGN="right" VALIGN="top"><B><% $custnum %>: </B></TD>
+  <TD ALIGN="left">
+    <% $_->name %>—<B><FONT COLOR="#<%$_->statuscolor%>"><%$_->ucfirst_cust_status%></FONT></B><BR>
+<% $_->address1 %><BR>
+<% $_->city %>, <% $_->state %>  <% $_->zip %>
+  </TD>
+  <TD ALIGN="center">
+    <INPUT TYPE="radio" NAME="dup_custnum" VALUE="<%$custnum%>">
+  </TD>
+</TR>
+% } #foreach cust_main
+</FORM>
+</TABLE>
+<TABLE WIDTH="100%">
+<TR>
+  <TD ALIGN="center">
+    <BUTTON TYPE="button" onclick="submit_continue();">
+      <IMG SRC="<%$p%>images/error.png"> Create a new customer
+    </BUTTON>
+  </TD>
+  <TD ALIGN="center">
+    <BUTTON TYPE="button" onclick="<% $set_to_customer %>">
+      <IMG SRC="<%$p%>images/tick.png"> Use the selected customer
+    </BUTTON>
+  </TD>
+</TR>
+<TR>
+  <TD COLSPAN=2 ALIGN="center">
+    <BUTTON TYPE="button" onclick="submit_abort();">
+      <IMG SRC="<%$p%>images/cross.png"> Cancel submission
+    </BUTTON>
+  </TD>
+</TR>
+% }
+%# else return nothing
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('List customers');
+
+my $conf = new FS::Conf;
+
+my $sub = $cgi->param('sub');
+my $hashref = decode_json($cgi->param('arg'));
+my @cust_main = qsearch('cust_main', $hashref);
+
+my $set_to_customer = <<EOF;
+  var custnum_array = document.getElementsByName('dup_custnum');
+  var custnum;
+  for(i=0; i<custnum_array.length; i++) {
+    if(custnum_array[i].checked) {
+      custnum = custnum_array[i].value;
+    }
+  }
+  //alert('Setting to customer '+custnum);
+  document.CustomerForm.elements['duplicate_of_custnum'].value = custnum;
+  submit_continue();
+EOF
+
+</%init>
diff --git a/httemplate/misc/xmlhttp-cust_main-search.cgi b/httemplate/misc/xmlhttp-cust_main-search.cgi
index 6f02312..68c5bf5 100644
--- a/httemplate/misc/xmlhttp-cust_main-search.cgi
+++ b/httemplate/misc/xmlhttp-cust_main-search.cgi
@@ -22,6 +22,21 @@
 %   my $return = $inv ? findbycustnum($inv->custnum,0) : [];
 <% objToJson($return) %>
 % } 
+% elsif ( $sub eq 'exact_search' ) {
+%   # XXX possibly should query each element separately
+%   my $hashref = decode_json($cgi->param('arg'));
+%   my @cust_main = qsearch('cust_main', $hashref);
+%   my $return = [];
+%   foreach (@cust_main) {
+%     push @$return, {
+%       custnum => $_->custnum,
+%       name => $_->name_short,
+%       address1 => $_->address1,
+%       city => $_->city,
+%     };
+%   }
+<% objToJson($return) %>
+% }
 <%init>
 
 my $conf = new FS::Conf;

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/Conf.pm                                     |   11 +++
 httemplate/edit/cust_main.cgi                     |    2 +-
 httemplate/edit/cust_main/bottomfixup.html        |   32 ++++---
 httemplate/edit/cust_main/bottomfixup.js          |   95 +++++++++++++++------
 httemplate/edit/process/cust_main.cgi             |   38 ++++++--
 httemplate/misc/xmlhttp-cust_main-duplicates.html |   68 +++++++++++++++
 httemplate/misc/xmlhttp-cust_main-search.cgi      |   15 +++
 7 files changed, 211 insertions(+), 50 deletions(-)
 create mode 100644 httemplate/misc/xmlhttp-cust_main-duplicates.html




More information about the freeside-commits mailing list