use FS::cust_location;
use FS::cust_payby;
-use FS::ClientAPI::MyAccount::quotation; # just for code organization
+# for code organization
+use FS::ClientAPI::MyAccount::contact;
+use FS::ClientAPI::MyAccount::quotation;
$DEBUG = 0;
$me = '[FS::ClientAPI::MyAccount]';
return { error => 'Incorrect contact password.' }
unless $contact->authenticate_password($p->{'password'});
+ $session->{'contactnum'} = $contact->contactnum;
+
my @cust_contact = grep $_->selfservice_access, $contact->cust_contact;
if ( scalar(@cust_contact) == 1 ) {
$session->{'custnum'} = $cust_contact[0]->custnum;
my $payby = delete $validate->{'payby'};
- my $error = $cust_main->realtime_bop( $FS::payby::payby2bop{$payby}, $amount,
- 'quiet' => 1,
- 'manual' => 1,
- 'selfservice' => 1,
- 'paynum_ref' => \$paynum,
- %$validate,
- );
- return { 'error' => $error } if $error;
-
- #no error, so order the fee package if applicable...
- my $conf = new FS::Conf;
- my $fee_pkgpart = $conf->config('selfservice_process-pkgpart', $cust_main->agentnum);
- my $fee_skip_first = $conf->exists('selfservice_process-skip_first');
-
- if ( $fee_pkgpart and ! $fee_skip_first || scalar($cust_main->cust_pay) ) {
-
- my $cust_pkg = new FS::cust_pkg { 'pkgpart' => $fee_pkgpart };
-
- $error = $cust_main->order_pkg( 'cust_pkg' => $cust_pkg );
- return { 'error' => "payment processed successfully, but error ordering fee: $error" }
- if $error;
-
- #and generate an invoice for it now too
- $error = $cust_main->bill( 'pkg_list' => [ $cust_pkg ] );
- return { 'error' => "payment processed and fee ordered sucessfully, but error billing fee: $error" }
- if $error;
-
- }
-
- $cust_main->apply_payments;
-
if ( $validate->{'save'} ) {
my $new = new FS::cust_main { $cust_main->hash };
if ($payby eq 'CARD' || $payby eq 'DCRD') {
stateid stateid_state );
$new->set( 'payby' => $validate->{'auto'} ? 'CHEK' : 'DCHK' );
}
- $new->set( 'payinfo' => $cust_main->card_token || $validate->{'payinfo'} );
+ $new->payinfo( $validate->{'payinfo'} ); #to properly set paymask
$new->set( 'paydate' => $validate->{'paydate'} );
my $error = $new->replace($cust_main);
if ( $error ) {
#return { 'error' => $error };
#XXX just warn verosely for now so i can figure out how these happen in
# the first place, eventually should redirect them to the "change
- #address" page but indicate the payment did process??
+ #address" page but indicate if the payment processed?
delete($validate->{'payinfo'}); #don't want to log this!
warn "WARNING: error changing customer info when processing payment (not returning to customer as a processing error): $error\n".
"NEW: ". Dumper($new)."\n".
"OLD: ". Dumper($cust_main)."\n".
"PACKET: ". Dumper($validate)."\n";
- #} else {
- #not needed...
- #$cust_main = $new;
+ } else {
+ $cust_main = $new;
}
}
+ my $error = $cust_main->realtime_bop( $FS::payby::payby2bop{$payby}, $amount,
+ 'quiet' => 1,
+ 'manual' => 1,
+ 'selfservice' => 1,
+ 'paynum_ref' => \$paynum,
+ %$validate,
+ );
+ return { 'error' => $error } if $error;
+
+ #no error, so order the fee package if applicable...
+ my $conf = new FS::Conf;
+ my $fee_pkgpart = $conf->config('selfservice_process-pkgpart', $cust_main->agentnum);
+ my $fee_skip_first = $conf->exists('selfservice_process-skip_first');
+
+ if ( $fee_pkgpart and ! $fee_skip_first || scalar($cust_main->cust_pay) ) {
+
+ my $cust_pkg = new FS::cust_pkg { 'pkgpart' => $fee_pkgpart };
+
+ $error = $cust_main->order_pkg( 'cust_pkg' => $cust_pkg );
+ return { 'error' => "payment processed successfully, but error ordering fee: $error" }
+ if $error;
+
+ #and generate an invoice for it now too
+ $error = $cust_main->bill( 'pkg_list' => [ $cust_pkg ] );
+ return { 'error' => "payment processed and fee ordered sucessfully, but error billing fee: $error" }
+ if $error;
+
+ }
+
+ $cust_main->apply_payments;
+
my $cust_pay = '';
my $receipt_html = '';
if ($paynum) {
if ( $conf->exists('signup_server-realtime') ) {
- my $bill_error = _do_bop_realtime( $cust_main, $status, 'no_credit'=>1 );
+ my $bill_error = _do_bop_realtime( $cust_main, $status, 'no_invoice_void'=>1 );
if ($bill_error) {
$err_or_cust_pkg->suspend;
my $old_balance = $cust_main->balance;
- my $bill_error = $cust_main->bill
- || $cust_main->apply_payments_and_credits;
+ my @cust_bill;
+ my $bill_error = $cust_main->bill(
+ 'return_bill' => \@cust_bill,
+ );
+
+ $bill_error ||= $cust_main->apply_payments_and_credits;
$bill_error ||= $cust_main->realtime_collect('selfservice' => 1)
if $cust_main->payby =~ /^(CARD|CHEK)$/;
)
)
{
- unless ( $opt{'no_credit'} ) {
- #this makes sense. credit is "un-doing" the invoice
- my $conf = new FS::Conf;
- $cust_main->credit( sprintf("%.2f", $cust_main->balance-$old_balance ),
- 'self-service decline',
- reason_type=>$conf->config('signup_credit_type'),
- );
- $cust_main->apply_credits( 'order' => 'newest' );
+ unless ( $opt{'no_invoice_void'} ) {
+
+ #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;
+ }
+
}
return { 'error' => '_decline', 'bill_error' => $bill_error };
}
-# sub contact_passwd {
-# my $p = shift;
-# my($context, $session, $custnum) = _custoragent_session_custnum($p);
-# return { 'error' => $session } if $context eq 'error';
-#
-# return { 'error' => 'Not logged in as a contact.' }
-# unless $session->{'contactnum'};
-#
-# return { 'error' => "New passwords don't match." }
-# if $p->{'new_password'} ne $p->{'new_password2'};
-#
-# return { 'error' => 'Enter new password' }
-# unless length($p->{'new_password'});
-#
-# #my $search = { 'custnum' => $custnum };
-# #$search->{'agentnum'} = $session->{'agentnum'} if $context eq 'agent';
-# $custnum =~ /^(\d+)$/ or die "illegal custnum";
-# my $search = " AND selfservice_access IS NOT NULL ".
-# " AND selfservice_access = 'Y' ".
-# " AND ( disabled IS NULL OR disabled = '' )".
-# " AND custnum IS NOT NULL AND custnum = $1";
-# $search .= " AND agentnum = ". $session->{'agentnum'} if $context eq 'agent';
-#
-# my $contact = qsearchs( {
-# 'table' => 'contact',
-# 'addl_from' => 'LEFT JOIN cust_main USING ( custnum ) ',
-# 'hashref' => { 'contactnum' => $session->{'contactnum'}, },
-# 'extra_sql' => $search, #important
-# } )
-# or return { 'error' => "Email not found" }; #? how did we get logged in?
-# # deleted since then?
-#
-# my $error = '';
-#
-# # use these svc_acct length restrictions??
-# my $conf = new FS::Conf;
-# $error = 'Password too short.'
-# if length($p->{'new_password'}) < ($conf->config('passwordmin') || 6);
-# $error = 'Password too long.'
-# if length($p->{'new_password'}) > ($conf->config('passwordmax') || 8);
-#
-# $error ||= $contact->change_password($p->{'new_password'});
-#
-# return { 'error' => $error, };
-#
-# }
-
sub reset_passwd {
my $p = shift;
my($username, $domain) = split('@', $p->{'email'});
my $svc_domain = qsearchs('svc_domain', { 'domain' => $domain } );
if ( $svc_domain ) {
- $svc_acct = qsearchs('svc_acct', { 'username' => $p->{'username'},
+ $svc_acct = qsearchs('svc_acct', { 'username' => $username,
'domsvc' => $svc_domain->svcnum }
);
if ( $svc_acct ) {
my $reset_session = {
'svcnum' => $svc_acct->svcnum,
- 'agentnum' =>
+ 'agentnum' => $svc_acct->cust_main->agentnum,
};
my $timeout = '1 hour'; #?