% if ( $error ) {
% $cgi->param('error', $error);
-%
-<% $cgi->redirect(popurl(2). "cust_main.cgi?". $cgi->query_string ) %>
+% # workaround for create_uri_query's mangling of unicode characters,
+% # false laziness with FS::Record::ut_coord
+% use charnames ':full';
+% for my $pre (qw(bill ship)) {
+% foreach (qw( latitude longitude)) {
+% my $coord = $cgi->param($pre.'_'.$_);
+% $coord =~ s/\N{DEGREE SIGN}\s*$//;
+% $cgi->param($pre.'_'.$_, $coord);
+% }
+% }
+% my $query = $m->scomp('/elements/create_uri_query', 'secure'=>1);
+<% $cgi->redirect(popurl(2). "cust_main.cgi?$query" ) %>
%
% } else {
%
-<% $cgi->redirect(popurl(3). "view/cust_main.cgi?". $new->custnum) %>
+<% $cgi->redirect( -uri => popurl(3). "view/cust_main.cgi?". $new->custnum,
+ -cookie => CGI::Cookie->new(
+ -name => 'freeside_status',
+ -value => mt($freeside_status),
+ -expires => '+5m',
+ ),
+ )
+%>
%
% }
<%once>
</%once>
<%init>
-die "access denied"
- unless $FS::CurrentUser::CurrentUser->access_right('Edit customer');
+my $curuser = $FS::CurrentUser::CurrentUser;
+die "access denied" unless $curuser->access_right('Edit customer');
my $conf = new FS::Conf;
$cgi->param('refnum', (split(/:/, ($cgi->param('refnum'))[0] ))[0] );
-my $payby = $cgi->param('payby');
-
-my %noauto = (
- 'CARD' => 'DCRD',
- 'CHEK' => 'DCHK',
-);
-$payby = $noauto{$payby}
- if ! $cgi->param('payauto') && exists $noauto{$payby};
+#my @invoicing_list = split( /\s*\,\s*/, $cgi->param('invoicing_list') );
+#push @invoicing_list, 'POST' if $cgi->param('invoicing_list_POST');
+#push @invoicing_list, 'FAX' if $cgi->param('invoicing_list_FAX');
+#$cgi->param('invoicing_list', join(',', @invoicing_list) );
+
+my $agentnum = $cgi->param('agentnum');
+
+# is this actually used? if so, we need to clone locations...
+# but I can't find anything that sets this parameter to a non-empty value
+# yes, fec48523d3cf056da08813f9b2b7d633b27aaf8d for #16582 is where it came in,
+# for "duplicate address checking for new customers". afaict still in
+# edit/cust_main/bottomfixup.html (and working?)
+$cgi->param('duplicate_of_custnum') =~ /^(\d+)$/;
+my $duplicate_of = $1;
+
+# if this is enabled, enforce it
+if ( $conf->exists('agent-ship_address', $cgi->param('agentnum')) ) {
+ my $agent = FS::agent->by_key($cgi->param('agentnum'));
+ my $agent_cust_main = $agent->agent_cust_main;
+ if ( $agent_cust_main ) {
+ my $agent_location = $agent_cust_main->ship_location;
+ foreach (qw(address1 city state zip country latitude longitude district)) {
+ $cgi->param("ship_$_", $agent_location->get($_));
+ }
+ }
+}
-$cgi->param('payby', $payby);
+my %locations;
+for my $pre (qw(bill ship)) {
-if ( $payby ) {
- if ( $payby eq 'CHEK' || $payby eq 'DCHK' ) {
- $cgi->param('payinfo',
- $cgi->param('payinfo1'). '@'. $cgi->param('payinfo2') );
+ my %hash;
+ foreach ( FS::cust_main->location_fields ) {
+ $hash{$_} = scalar($cgi->param($pre.'_'.$_));
}
- $cgi->param('paydate',
- $cgi->param( 'exp_month' ). '-'. $cgi->param( 'exp_year' ) );
+ $hash{'custnum'} = $cgi->param('custnum');
+ warn Dumper \%hash if $DEBUG;
+ $locations{$pre} = FS::cust_location->new(\%hash);
}
-my @invoicing_list = split( /\s*\,\s*/, $cgi->param('invoicing_list') );
-push @invoicing_list, 'POST' if $cgi->param('invoicing_list_POST');
-push @invoicing_list, 'FAX' if $cgi->param('invoicing_list_FAX');
-$cgi->param('invoicing_list', join(',', @invoicing_list) );
-
+if ( ($cgi->param('same') || '') eq 'Y' ) {
+ $locations{ship} = $locations{bill};
+}
#create new record object
+# but explicitly avoid setting ship_ fields
my $new = new FS::cust_main ( {
- map {
- $_, scalar($cgi->param($_))
-# } qw(custnum agentnum last first ss company address1 address2 city county
-# state zip daytime night fax payby payinfo paydate payname tax
-# otaker refnum)
- } fields('cust_main')
+ (map { ( $_, scalar($cgi->param($_)) ) } (fields('cust_main'))),
+ (map { ( "ship_$_", '' ) } (FS::cust_main->location_fields))
} );
-if ( defined($cgi->param('same')) && $cgi->param('same') eq "Y" ) {
- $new->setfield("ship_$_", '') foreach qw(
- last first company address1 address2 city county state zip
- country daytime night fax
- );
+warn Dumper( $new ) if $DEBUG > 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)";
+}
+
+for my $pre (qw(bill ship)) {
+ $new->set($pre.'_location', $locations{$pre});
+ $new->set($pre.'_locationnum', $locations{$pre}->locationnum);
+}
+
+if ( $cgi->param('no_credit_limit') ) {
+ $new->setfield('credit_limit', '');
}
-my %usedatetime = ( 'birthdate' => 1 );
+#$new->tagnum( [ $cgi->param('tagnum') ] );
+my $params = $cgi->Vars;
+$new->tagnum( [
+ map { /^tagnum(\d+)/ && $1 }
+ grep { /^tagnum(\d+)/ && $cgi->param($_) } keys %$params
+] );
+
+$error ||= $new->set_national_id_from_cgi( $cgi );
+
+my %usedatetime = ( 'birthdate' => 1,
+ 'spouse_birthdate' => 1,
+ 'anniversary_date' => 1,
+ );
-foreach my $dfield (qw( birthdate signupdate )) {
+foreach my $dfield (qw(
+ signupdate birthdate spouse_birthdate anniversary_date
+)) {
if ( $cgi->param($dfield) && $cgi->param($dfield) =~ /^([ 0-9\-\/]{0,10})$/) {
if ( $dt ) {
$parsed = $dt->epoch;
} else {
- # $error ||= $cgi->param('birthdate') . " is an invalid birthdate:" . $parser->errmsg;
$error ||= "Invalid $dfield: $value";
}
$new->setfield('paid', $cgi->param('paid') )
if $cgi->param('paid');
-my @exempt_groups = grep /\S/, $conf->config('tax-cust_exempt-groups');
-my @tax_exempt = grep { $cgi->param("tax_$_") eq 'Y' } @exempt_groups;
+my %options = ();
+if ( $curuser->access_right('Edit customer tax exemptions') ) {
+ my @exempt_groups = grep /\S/, $conf->config('tax-cust_exempt-groups');
+ my @tax_exempt = grep { $cgi->param("tax_$_") eq 'Y' } @exempt_groups;
+ $options{'tax_exemption'} = {
+ map { $_ => scalar($cgi->param("tax_$_".'_num')) } @tax_exempt
+ };
+}
+
+$options{'cust_payby_params'} = scalar($cgi->Vars);
+
+if ( $cgi->param('residential_commercial') eq 'Residential' ) {
+
+ my $email = $cgi->param('invoice_email') || '';
+ if ( length($email) == 0 and $conf->exists('cust_main-require_invoicing_list_email', $agentnum) ) {
+ $error = 'Email address required';
+ }
+
+ $options{'invoicing_list'} = [ split(/\s*,\s*/, $email) ];
+ # XXX really should include the phone numbers in here also
+
+} else {
+
+ # contact UI is enabled
+ $options{'contact_params'} = scalar($cgi->Vars);
+
+ if ($conf->exists('cust_main-require_invoicing_list_email', $agentnum)) {
+ my $has_email = 0;
+ foreach my $prefix (grep /^contactnum\d+$/, $cgi->param) {
+ if ( length($cgi->param($prefix . '_emailaddress'))
+ and $cgi->param($prefix . '_invoice_dest') ) {
+ $has_email = 1;
+ last;
+ }
+ }
+ $error = "At least one contact must receive email invoices"
+ unless $has_email;
+ }
+
+}
+
+# kind of a hack, but some tax data vendors require a status and others
+# don't.
+my $vendor = $conf->config('tax_data_vendor');
+if ( $vendor eq 'avalara' or $vendor eq 'suretax' ) {
+ if ( ! $cgi->param('taxstatusnum') ) {
+ $error ||= 'Tax status required';
+ }
+}
#perhaps this stuff should go to cust_main.pm
-if ( $new->custnum eq '' ) {
+my $freeside_status = '';
+if ( $new->custnum eq '' or $duplicate_of ) {
+
+ $freeside_status = 'Customer added';
my $cust_pkg = '';
my $svc;
$cust_pkg = new FS::cust_pkg ( {
#later 'custnum' => $custnum,
- 'pkgpart' => $pkgpart,
+ 'pkgpart' => $pkgpart,
+ 'locationnum' => scalar($cgi->param('locationnum')),
+ 'salesnum' => scalar($cgi->param('salesnum')),
} );
- #$error ||= $cust_pkg->check;
-
- #$cust_svc = new FS::cust_svc ( { 'svcpart' => $svcpart } );
- #$error ||= $cust_svc->check;
my $part_svc = qsearchs('part_svc', { 'svcpart' => $svcpart } );
my $svcdb = $part_svc->svcdb;
} elsif ( $svcdb eq 'svc_phone' ) {
my %svc_phone = (
- 'svcpart' => $svcpart,
- map { $_ => scalar($cgi->param($_)) }
- qw( countrycode phonenum sip_password pin phone_name )
- );
+ 'svcpart' => $svcpart,
+ map { $_ => scalar($cgi->param($_)) }
+ qw( countrycode phonenum sip_password pin phone_name )
+ );
$svc = new FS::svc_phone \%svc_phone;
+ } elsif ( $svcdb eq 'svc_dsl' ) {
+
+ my %svc_dsl = (
+ 'svcpart' => $svcpart,
+ ( map { $_ => scalar($cgi->param("ship_$_")) || scalar($cgi->param($_))}
+ qw( first last company )
+ ),
+ ( map { $_ => scalar($cgi->param($_)) }
+ qw( loop_type phonenum password isp_chg isp_prev vendor_qual_id )
+ ),
+ 'desired_due_date' => time, #XXX enter?
+ 'vendor_order_type' => 'NEW',
+ );
+ $svc = new FS::svc_dsl \%svc_dsl;
+
} else {
die "$svcdb not handled on new customer yet";
}
- #$error ||= $svc_acct->check;
-
}
+
use Tie::RefHash;
tie my %hash, 'Tie::RefHash';
%hash = ( $cust_pkg => [ $svc ] ) if $cust_pkg;
- $error ||= $new->insert( \%hash, \@invoicing_list,
- 'tax_exemption' => \@tax_exempt,
- );
+ 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,
+ %options,
+ 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
+ $freeside_status = 'Customer edited';
+
my $old = qsearchs( 'cust_main', { 'custnum' => $new->custnum } );
$error ||= "Old record not found!" unless $old;
- 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($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;
+ warn "$me calling $new -> replace( $old )" if $DEBUG;
local($FS::cust_main::DEBUG) = $DEBUG if $DEBUG;
local($FS::Record::DEBUG) = $DEBUG if $DEBUG;
- $error ||= $new->replace( $old, \@invoicing_list,
- 'tax_exemption' => \@tax_exempt,
- );
+ local($Data::Dumper::Sortkeys) = 1;
+ warn Dumper({ new => $new, old => $old, options => \%options}) if $DEBUG;
+
+ $error ||= $new->replace( $old, %options );
warn "$me returned from replace" if $DEBUG;