use strict;
use vars qw( $DEBUG $me );
+use subs qw( _myaccount_cache );
use Data::Dumper;
use Tie::RefHash;
use Digest::SHA qw(sha512_hex);
use FS::reg_code;
use FS::payby;
use FS::banned_pay;
+use FS::part_tag;
+use FS::cust_payby;
$DEBUG = 1;
$me = '[FS::ClientAPI::Signup]';
'nomadix' => $conf->exists('signup_server-nomadix'),
'payby' => [ $conf->config('signup_server-payby') ],
'card_types' => card_types(),
- 'paytypes' => [ @FS::cust_main::paytypes ],
+ 'paytypes' => [ FS::cust_payby->paytypes ],
'cvv_enabled' => 1,
'require_cvv' => $conf->exists('signup-require_cvv'),
'stateid_enabled' => $conf->exists('show_stateid'),
'paystate_enabled' => $conf->exists('show_bankstate'),
+ 'exempt_groups' => [ grep /\S/, $conf->config('tax-cust_exempt-groups') ],
'ship_enabled' => 1,
'msgcat' => $msgcat,
'label' => $label,
#shares some stuff with htdocs/edit/process/cust_main.cgi... take any
# common that are still here and library them.
+
+ my %cust_main = (
+ 'agentnum' => $agentnum,
+ 'refnum' => $packet->{refnum}
+ || $conf->config('signup_server-default_refnum'),
+ 'tagnum' => [ FS::part_tag->default_tags ],
+
+ ( map { $_ => $packet->{$_} } qw(
+ salesnum
+ ss stateid stateid_state
+ locale
+ referral_custnum comments
+ )
+ ),
+
+ );
+
+ my %insert_options = ();
+ if ( $packet->{payby} =~ /^(CARD|DCRD|CHEK|DCHK)$/ ) {
+ $insert_options{cust_payby} = [
+ new FS::cust_payby {
+ map { $_ => $packet->{$_} } qw(
+ payby
+ payinfo paycvv paydate payname paystate paytype
+ paystart_month paystart_year payissue
+ payip
+ ),
+ }
+ ];
+ }
+
my $template_custnum = $conf->config('signup_server-prepaid-template-custnum');
my $cust_main;
if ( $template_custnum && $packet->{prepaid_shortform} ) {
my $template_cust = qsearchs('cust_main', { 'custnum' => $template_custnum } );
return { 'error' => 'Configuration error' } unless $template_cust;
$cust_main = new FS::cust_main ( {
- 'agentnum' => $agentnum,
- 'refnum' => $packet->{refnum}
- || $conf->config('signup_server-default_refnum'),
-
- ( map { $_ => $template_cust->$_ } qw(
- last first company daytime night fax
- )
+ %cust_main,
+ map { $_ => $template_cust->$_ } qw(
+ last first company daytime night fax mobile
),
-
- ( map { $_ => $packet->{$_} } qw(
- ss stateid stateid_state
-
- payby
- payinfo paycvv paydate payname paystate paytype
- paystart_month paystart_year payissue
- payip
-
- referral_custnum comments
- )
- ),
-
} );
$bill_hash = { $template_cust->bill_location->location_hash };
} else {
$cust_main = new FS::cust_main ( {
- #'custnum' => '',
- 'agentnum' => $agentnum,
- 'refnum' => $packet->{refnum}
- || $conf->config('signup_server-default_refnum'),
-
+ %cust_main,
map { $_ => $packet->{$_} } qw(
- last first ss company
- daytime night fax stateid stateid_state
- payby
- payinfo paycvv paydate payname paystate paytype
- paystart_month paystart_year payissue
- payip
+ last first company daytime night fax mobile
override_ban_warn
- referral_custnum comments
),
-
} );
}
);
}
- $cust_main->payby('BILL') # MCRD better?
+ $cust_main->payby('BILL') # MCRD better? no, that's for something else
if $gw && $gw->gateway_namespace eq 'Business::OnlineThirdPartyPayment';
}
&& ! $cust_main->paycvv
&& $conf->exists('signup-require_cvv');
- $cust_main->payinfo($cust_main->daytime)
- if $cust_main->payby eq 'LECB' && ! $cust_main->payinfo;
-
my @invoicing_list = $packet->{'invoicing_list'}
? split( /\s*\,\s*/, $packet->{'invoicing_list'} )
: ();
+ my @exempt_groups = grep /\S/, $conf->config('tax-cust_exempt-groups');
+ my @tax_exempt = grep { $packet->{"tax_$_"} eq 'Y' } @exempt_groups;
+ $insert_options{'tax_exemption'} = {
+ map { $_ => $packet->{"tax_$_".'_num'} } @tax_exempt
+ };
+
$packet->{'pkgpart'} =~ /^(\d+)$/ or '' =~ /^()$/;
my $pkgpart = $1;
return { 'error' => 'Please select a package' } unless $pkgpart; #msgcat
my $part_pkg =
qsearchs( 'part_pkg', { 'pkgpart' => $pkgpart } )
or return { 'error' => "WARNING: unknown pkgpart: $pkgpart" };
- my $svcpart = $part_pkg->svcpart($svc_x);
my $reg_code = '';
if ( $packet->{'reg_code'} ) {
#my $error = $cust_pkg->check;
#return { 'error' => $error } if $error;
- #should be all auto-magic and shit
my @svc = ();
- if ( $svc_x eq 'svc_acct' ) {
+ unless ( $svc_x eq 'none' ) {
- my $svc = new FS::svc_acct {
- 'svcpart' => $svcpart,
- map { $_ => $packet->{$_} }
- qw( username _password sec_phrase popnum domsvc ),
- };
+ my $svcpart = $part_pkg->svcpart($svc_x);
+ #should be all auto-magic and shit
+ if ( $svc_x eq 'svc_acct' ) {
- my @acct_snarf;
- my $snarfnum = 1;
- while ( exists($packet->{"snarf_machine$snarfnum"})
- && length($packet->{"snarf_machine$snarfnum"}) ) {
- my $acct_snarf = new FS::acct_snarf ( {
- 'machine' => $packet->{"snarf_machine$snarfnum"},
- 'protocol' => $packet->{"snarf_protocol$snarfnum"},
- 'username' => $packet->{"snarf_username$snarfnum"},
- '_password' => $packet->{"snarf_password$snarfnum"},
- } );
- $snarfnum++;
- push @acct_snarf, $acct_snarf;
- }
- $svc->child_objects( \@acct_snarf );
- push @svc, $svc;
+ my $svc = new FS::svc_acct {
+ 'svcpart' => $svcpart,
+ map { $_ => $packet->{$_} }
+ qw( username _password sec_phrase popnum domsvc ),
+ };
+
+ my $error = $svc->is_password_allowed($packet->{_password});
+ return { error => $error } if $error;
+
+ my @acct_snarf;
+ my $snarfnum = 1;
+ while ( exists($packet->{"snarf_machine$snarfnum"})
+ && length($packet->{"snarf_machine$snarfnum"}) ) {
+ my $acct_snarf = new FS::acct_snarf ( {
+ 'machine' => $packet->{"snarf_machine$snarfnum"},
+ 'protocol' => $packet->{"snarf_protocol$snarfnum"},
+ 'username' => $packet->{"snarf_username$snarfnum"},
+ '_password' => $packet->{"snarf_password$snarfnum"},
+ } );
+ $snarfnum++;
+ push @acct_snarf, $acct_snarf;
+ }
+ $svc->child_objects( \@acct_snarf );
+ push @svc, $svc;
- } elsif ( $svc_x eq 'svc_phone' ) {
+ } elsif ( $svc_x eq 'svc_phone' ) {
- push @svc, new FS::svc_phone ( {
- 'svcpart' => $svcpart,
- map { $_ => $packet->{$_} }
- qw( countrycode phonenum sip_password pin ),
- } );
+ push @svc, new FS::svc_phone ( {
+ 'svcpart' => $svcpart,
+ map { $_ => $packet->{$_} }
+ qw( countrycode phonenum sip_password pin ),
+ } );
- } elsif ( $svc_x eq 'svc_pbx' ) {
+ } elsif ( $svc_x eq 'svc_pbx' ) {
- push @svc, new FS::svc_pbx ( {
- 'svcpart' => $svcpart,
- map { $_ => $packet->{$_} }
- qw( id title ),
- } );
+ push @svc, new FS::svc_pbx ( {
+ 'svcpart' => $svcpart,
+ map { $_ => $packet->{$_} }
+ qw( id title ),
+ } );
- } else {
- die "unknown signup service $svc_x";
+ } else {
+ die "unknown signup service $svc_x";
+ }
+
}
if ($packet->{'mac_addr'} && $conf->exists('signup_server-mac_addr_svcparts'))
\%hash,
\@invoicing_list,
'depend_jobnum' => $placeholder->jobnum,
+ %insert_options,
);
if ( $error ) {
my $perror = $placeholder->delete;
#warn "$me Billing customer...\n" if $Debug;
- my $bill_error = $cust_main->bill( 'depend_jobnum'=>$placeholder->jobnum );
+ my @cust_bill;
+ my $bill_error = $cust_main->bill(
+ 'depend_jobnum' => $placeholder->jobnum,
+ 'return_bill' => \@cust_bill,
+ );
#warn "$me error billing new customer: $bill_error"
# if $bill_error;
if ( $cust_main->balance > 0 ) {
- #this makes sense. credit is "un-doing" the invoice
- $cust_main->credit( $cust_main->balance, 'signup server decline',
- 'reason_type' => $conf->config('signup_credit_type'),
- );
- $cust_main->apply_credits;
+ #this used to apply a credit, but now we can void invoices...
+ foreach my $cust_bill (@cust_bill) {
+ my $voiderror = $cust_bill->void('automatic payment failed');
+ warn "Error voiding cust bill after decline: $voiderror" if $voiderror;
+ }
#should check list for errors...
#$cust_main->suspend;
#false laziness w/ above
# fresh restart to support "free account" portals with 3.x/4.x-style
# addressless accounts
+# and a contact (for self-service login)
sub new_customer_minimal {
my $packet = shift;
# common that are still here and library them.
my $cust_main = new FS::cust_main ( {
- #'custnum' => '',
- 'agentnum' => $agentnum,
- 'refnum' => $packet->{refnum}
- || $conf->config('signup_server-default_refnum'),
- 'payby' => 'BILL',
+ 'agentnum' => $agentnum,
+ 'refnum' => $packet->{refnum}
+ || $conf->config('signup_server-default_refnum'),
+ 'tagnum' => [ FS::part_tag->default_tags ],
map { $_ => $packet->{$_} } qw(
- last first ss company
- daytime night fax
+ salesnum
+ last first company daytime night fax mobile
+ ss stateid stateid_state
+
+ locale
),
} );
+ my %opt = ();
+ if ( $packet->{payby} =~ /^(CARD|DCRD|CHEK|DCHK)$/ ) {
+ $opt{cust_payby} = [
+ new FS::cust_payby {
+ map { $_ => $packet->{$_} } qw(
+ payby
+ payinfo paycvv paydate payname paystate paytype
+ paystart_month paystart_year payissue
+ payip
+ ),
+ }
+ ];
+ }
+
+ if ( grep length($packet->{$_}), FS::cust_main->location_fields ) {
+ my $bill_hash;
+ foreach my $f (FS::cust_main->location_fields) {
+ $bill_hash->{$f} = $packet->{$f};
+ }
+ my $bill_location = FS::cust_location->new($bill_hash);
+ $cust_main->set('bill_location' => $bill_location);
+ $cust_main->set('ship_location' => $bill_location);
+ }
+
my @invoicing_list = $packet->{'invoicing_list'}
? split( /\s*\,\s*/, $packet->{'invoicing_list'} )
: ();
+ use Tie::RefHash;
+ tie my %hash, 'Tie::RefHash', ();
+ my @svc = ();
+
$packet->{'pkgpart'} =~ /^(\d+)$/ or '' =~ /^()$/;
my $pkgpart = $1;
- return { 'error' => 'Please select a package' } unless $pkgpart; #msgcat
- my $part_pkg =
- qsearchs( 'part_pkg', { 'pkgpart' => $pkgpart } )
- or return { 'error' => "WARNING: unknown pkgpart: $pkgpart" };
- my $svcpart = $part_pkg->svcpart($svc_x);
+ if ( $pkgpart ) {
- my $cust_pkg = new FS::cust_pkg ( {
- #later#'custnum' => $custnum,
- 'pkgpart' => $packet->{'pkgpart'},
- } );
- #my $error = $cust_pkg->check;
- #return { 'error' => $error } if $error;
+ my $part_pkg =
+ qsearchs( 'part_pkg', { 'pkgpart' => $pkgpart } )
+ or return { 'error' => "WARNING: unknown pkgpart: $pkgpart" };
- #should be all auto-magic and shit
- my @svc = ();
- if ( $svc_x eq 'svc_acct' ) {
+ my $cust_pkg = new FS::cust_pkg ( {
+ #later#'custnum' => $custnum,
+ 'pkgpart' => $packet->{'pkgpart'},
+ } );
+ #my $error = $cust_pkg->check;
+ #return { 'error' => $error } if $error;
- my $svc = new FS::svc_acct {
- 'svcpart' => $svcpart,
- map { $_ => $packet->{$_} }
- qw( username _password sec_phrase popnum domsvc ),
- };
+ unless ( $svc_x eq 'none' ) {
- push @svc, $svc;
+ my $svcpart = $part_pkg->svcpart($svc_x);
+ #should be all auto-magic and shit
+ if ( $svc_x eq 'svc_acct' ) {
- } elsif ( $svc_x eq 'svc_phone' ) {
+ my $svc = new FS::svc_acct {
+ 'svcpart' => $svcpart,
+ map { $_ => $packet->{$_} }
+ qw( username _password sec_phrase popnum domsvc ),
+ };
- push @svc, new FS::svc_phone ( {
- 'svcpart' => $svcpart,
- map { $_ => $packet->{$_} }
- qw( countrycode phonenum sip_password pin ),
- } );
+ push @svc, $svc;
- } elsif ( $svc_x eq 'svc_pbx' ) {
+ } elsif ( $svc_x eq 'svc_phone' ) {
- push @svc, new FS::svc_pbx ( {
- 'svcpart' => $svcpart,
- map { $_ => $packet->{$_} }
- qw( id title ),
+ push @svc, new FS::svc_phone ( {
+ 'svcpart' => $svcpart,
+ map { $_ => $packet->{$_} }
+ qw( countrycode phonenum sip_password pin ),
} );
-
- } else {
- die "unknown signup service $svc_x";
+
+ } elsif ( $svc_x eq 'svc_pbx' ) {
+
+ push @svc, new FS::svc_pbx ( {
+ 'svcpart' => $svcpart,
+ map { $_ => $packet->{$_} }
+ qw( id title ),
+ } );
+
+ } else {
+ die "unknown signup service $svc_x";
+ }
+
+ }
+
+ foreach my $svc ( @svc ) {
+ my $y = $svc->setdefault; # arguably should be in new method
+ return { 'error' => $y } if $y && !ref($y);
+ #$error = $svc->check;
+ #return { 'error' => $error } if $error;
+ }
+
+ use Tie::RefHash;
+ tie my %hash, 'Tie::RefHash';
+ $hash{ $cust_pkg } = \@svc;
+
}
- foreach my $svc ( @svc ) {
- my $y = $svc->setdefault; # arguably should be in new method
- return { 'error' => $y } if $y && !ref($y);
- #$error = $svc->check;
- #return { 'error' => $error } if $error;
+ if ( $invoicing_list[0] && $packet->{'_password'} ) {
+ $opt{'contact'} = [
+ new FS::contact { 'first' => $cust_main->first,
+ 'last' => $cust_main->get('last'),
+ '_password' => $packet->{'_password'},
+ 'emailaddress' => $invoicing_list[0],
+ 'selfservice_access' => 'Y',
+ }
+ ];
}
- use Tie::RefHash;
- tie my %hash, 'Tie::RefHash';
- %hash = ( $cust_pkg => \@svc );
- #msgcat
my $error = $cust_main->insert(
\%hash,
\@invoicing_list,
+ %opt,
);
return { 'error' => $error } if $error;
my $session_id;
do {
- $session_id = sha1_hex(time(). {}. rand(). $$)
+ $session_id = sha512_hex(time(). {}. rand(). $$)
} until ( ! defined _myaccount_cache->get($session_id) ); #just in case
- _cache->set( $session_id, $session, '1 hour' ); # 1 hour?
+ _myaccount_cache->set( $session_id, $session, '1 hour' ); # 1 hour?
my %return = ( 'error' => '',
'signup_service' => $svc_x,
'custnum' => $cust_main->custnum,
'session_id' => $session_id,
+ map { $_ => $cust_main->$_ } qw( first last company ),
);
if ( $svc[0] ) {