+
+ if ( length($old->paycvv) && $new->paycvv =~ /^\s*\*+\s*$/ ) {
+ $new->paycvv($old->paycvv);
+ }
+ if ($new->ss =~ /xx/) {
+ $new->ss($old->ss);
+ }
+ if ($new->stateid =~ /^xxx/) {
+ $new->stateid($old->stateid);
+ }
+ if ( $new->payby =~ /^(CARD|DCRD)$/
+ && ( $new->payinfo =~ /xx/
+ || $new->payinfo =~ /^\s*N\/A\s+\(tokenized\)\s*$/
+ )
+ )
+ {
+ $new->payinfo($old->payinfo);
+
+ } elsif ( $new->payby =~ /^(CHEK|DCHK)$/ && $new->payinfo =~ /xx/ ) {
+ #fix for #3085 "edit of customer's routing code only surprisingly causes
+ #nothing to happen...
+ # this probably won't do the right thing when we don't have the
+ # public key (can't actually get the real $old->payinfo)
+ my($new_account, $new_aba) = split('@', $new->payinfo);
+ my($old_account, $old_aba) = split('@', $old->payinfo);
+ $new_account = $old_account if $new_account =~ /xx/;
+ $new_aba = $old_aba if $new_aba =~ /xx/;
+ $new->payinfo($new_account.'@'.$new_aba);
+ }
+
+ if ( ! $conf->exists('cust_main-edit_signupdate') or
+ ! $new->signupdate ) {
+ $new->signupdate($old->signupdate);
+ }
+
+ warn "$me calling $new -> replace( $old, \ @invoicing_list )" if $DEBUG;
+ local($FS::cust_main::DEBUG) = $DEBUG if $DEBUG;
+ local($FS::Record::DEBUG) = $DEBUG if $DEBUG;
+
+ local($Data::Dumper::Sortkeys) = 1;
+ warn Dumper({ new => $new, old => $old }) if $DEBUG;
+
+ $error ||= $new->replace( $old, \@invoicing_list,
+ 'tax_exemption' => \%tax_exempt,
+ );
+
+ warn "$me returned from replace" if $DEBUG;
+
+}
+
+unless ( $error ) { #XXX i guess i should be transactional... all in the insert
+ # or replace call
+ my @contact_fields = qw( classnum first last title comment emailaddress );
+ foreach my $phone_type ( qsearch({table=>'phone_type', order_by=>'weight'}) ) {
+ push @contact_fields, 'phonetypenum'.$phone_type->phonetypenum;
+ }
+
+ $error = $new->process_o2m( 'table' => 'contact',
+ 'fields' => \@contact_fields,
+ 'params' => scalar($cgi->Vars),
+ );