X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2FClientAPI%2FMyAccount.pm;h=cbc3dba90f8806a1b7826ef0e3c0df0c68cfc0b2;hb=08ba9f8e8d5c7dc641817d3fa7580faf3a38b50a;hp=ad73aaf55dd322c5079bb9c2bca30d1c8b85e418;hpb=1748e50c012a65ecb729f15e09169f5d8122a3b1;p=freeside.git diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index ad73aaf55..cbc3dba90 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -1,13 +1,14 @@ package FS::ClientAPI::MyAccount; use strict; -use vars qw($cache); -use subs qw(_cache); +use vars qw( $cache $DEBUG ); +use subs qw( _cache _provision ); +use Data::Dumper; use Digest::MD5 qw(md5_hex); use Date::Format; use Business::CreditCard; use Time::Duration; -use FS::CGI qw(small_custview); #doh +use FS::UI::Web::small_custview qw(small_custview); #less doh use FS::UI::Web; use FS::UI::bytecount; use FS::Conf; @@ -17,14 +18,19 @@ use FS::Misc qw(card_types); use FS::ClientAPI_SessionCache; use FS::svc_acct; use FS::svc_domain; +use FS::svc_phone; use FS::svc_external; use FS::part_svc; use FS::cust_main; use FS::cust_bill; use FS::cust_main_county; use FS::cust_pkg; +use FS::payby; +use FS::acct_rt_transaction; use HTML::Entities; +$DEBUG = 0; + #false laziness with FS::cust_main BEGIN { eval "use Time::Local;"; @@ -40,42 +46,85 @@ use vars qw( @cust_main_editable_fields ); ship_first ship_last ship_company ship_address1 ship_address2 ship_city ship_state ship_zip ship_country ship_daytime ship_night ship_fax payby payinfo payname paystart_month paystart_year payissue payip + ss paytype paystate stateid stateid_state ); -use subs qw(_provision); - sub _cache { $cache ||= new FS::ClientAPI_SessionCache( { 'namespace' => 'FS::ClientAPI::MyAccount', } ); } +sub login_info { + my $p = shift; + + my $conf = new FS::Conf; + + my %info = ( + 'phone_login' => $conf->exists('selfservice_server-phone_login'), + 'single_domain'=> scalar($conf->config('selfservice_server-single_domain')), + ); + + return \%info; + +} + #false laziness w/FS::ClientAPI::passwd::passwd sub login { my $p = shift; - my $svc_domain = qsearchs('svc_domain', { 'domain' => $p->{'domain'} } ) - or return { error => 'Domain '. $p->{'domain'}. ' not found' }; + my $conf = new FS::Conf; - my $svc_acct = qsearchs( 'svc_acct', { 'username' => $p->{'username'}, - 'domsvc' => $svc_domain->svcnum, } - ); - return { error => 'User not found.' } unless $svc_acct; + my $svc_x = ''; + if ( $p->{'domain'} eq 'svc_phone' + && $conf->exists('selfservice_server-phone_login') ) { - my $conf = new FS::Conf; - my $pkg_svc = $svc_acct->cust_svc->pkg_svc; - return { error => 'Only primary user may log in.' } - if $conf->exists('selfservice_server-primary_only') - && ( ! $pkg_svc || $pkg_svc->primary_svc ne 'Y' ); + my $svc_phone = qsearchs( 'svc_phone', { 'phonenum' => $p->{'username'} } ); + return { error => 'Number not found.' } unless $svc_phone; + + #XXX? + #my $pkg_svc = $svc_acct->cust_svc->pkg_svc; + #return { error => 'Only primary user may log in.' } + # if $conf->exists('selfservice_server-primary_only') + # && ( ! $pkg_svc || $pkg_svc->primary_svc ne 'Y' ); + + return { error => 'Incorrect PIN.' } + unless $svc_phone->check_pin($p->{'password'}); + + $svc_x = $svc_phone; + + } else { + + my $svc_domain = qsearchs('svc_domain', { 'domain' => $p->{'domain'} } ) + or return { error => 'Domain '. $p->{'domain'}. ' not found' }; + + my $svc_acct = qsearchs( 'svc_acct', { 'username' => $p->{'username'}, + 'domsvc' => $svc_domain->svcnum, } + ); + return { error => 'User not found.' } unless $svc_acct; + + #my $pkg_svc = $svc_acct->cust_svc->pkg_svc; + #return { error => 'Only primary user may log in.' } + # if $conf->exists('selfservice_server-primary_only') + # && ( ! $pkg_svc || $pkg_svc->primary_svc ne 'Y' ); + my $cust_svc = $svc_acct->cust_svc; + my $part_pkg = $cust_svc->cust_pkg->part_pkg; + return { error => 'Only primary user may log in.' } + if $conf->exists('selfservice_server-primary_only') + && $cust_svc->svcpart != $part_pkg->svcpart('svc_acct'); + + return { error => 'Incorrect password.' } + unless $svc_acct->check_password($p->{'password'}); - return { error => 'Incorrect password.' } - unless $svc_acct->check_password($p->{'password'}); + $svc_x = $svc_acct; + + } my $session = { - 'svcnum' => $svc_acct->svcnum, + 'svcnum' => $svc_x->svcnum, }; - my $cust_pkg = $svc_acct->cust_svc->cust_pkg; + my $cust_pkg = $svc_x->cust_svc->cust_pkg; if ( $cust_pkg ) { my $cust_main = $cust_pkg->cust_main; $session->{'custnum'} = $cust_main->custnum; @@ -86,7 +135,8 @@ sub login { $session_id = md5_hex(md5_hex(time(). {}. rand(). $$)) } until ( ! defined _cache->get($session_id) ); #just in case - _cache->set( $session_id, $session, '1 hour' ); + my $timeout = $conf->config('selfservice-session_timeout') || '1 hour'; + _cache->set( $session_id, $session, $timeout ); return { 'error' => '', 'session_id' => $session_id, @@ -110,6 +160,14 @@ sub customer_info { return { 'error' => $session } if $context eq 'error'; my %return; + + my $conf = new FS::Conf; + if ($conf->exists('cust_main-require_address2')) { + $return{'require_address2'} = '1'; + }else{ + $return{'require_address2'} = ''; + } + if ( $custnum ) { #customer record my $search = { 'custnum' => $custnum }; @@ -119,6 +177,8 @@ sub customer_info { $return{balance} = $cust_main->balance; + $return{tickets} = [ ($cust_main->tickets) ]; + my @open = map { { invnum => $_->invnum, @@ -128,7 +188,6 @@ sub customer_info { } $cust_main->open_cust_bill; $return{open_invoices} = \@open; - my $conf = new FS::Conf; $return{small_custview} = small_custview( $cust_main, $conf->config('countrydefault') ); @@ -148,6 +207,27 @@ sub customer_info { $return{'postal_invoicing'} = 0 < ( grep { $_ eq 'POST' } $cust_main->invoicing_list ); + if (scalar($conf->config('support_packages'))) { + my @support_services = (); + foreach ($cust_main->support_services) { + my $seconds = $_->svc_x->seconds; + my $time_remaining = (($seconds < 0) ? '-' : '' ). + int(abs($seconds)/3600)."h". + sprintf("%02d",(abs($seconds)%3600)/60)."m"; + my $cust_pkg = $_->cust_pkg; + my $pkgnum = ''; + my $pkg = ''; + $pkgnum = $cust_pkg->pkgnum if $cust_pkg; + $pkg = $cust_pkg->part_pkg->pkg if $cust_pkg; + push @support_services, { svcnum => $_->svcnum, + time => $time_remaining, + pkgnum => $pkgnum, + pkg => $pkg, + }; + } + $return{support_services} = \@support_services; + } + } elsif ( $session->{'svcnum'} ) { #no customer record my $svc_acct = qsearchs('svc_acct', { 'svcnum' => $session->{'svcnum'} } ) @@ -182,13 +262,46 @@ sub edit_info { $new->set( $_ => $p->{$_} ) foreach grep { exists $p->{$_} } @cust_main_editable_fields; - if ( $p->{'payby'} =~ /^(CARD|DCRD)$/ ) { + my $payby = ''; + if (exists($p->{'payby'})) { + $p->{'payby'} =~ /^([A-Z]{4})$/ + or return { 'error' => "illegal_payby " . $p->{'payby'} }; + $payby = $1; + } + + if ( $payby =~ /^(CARD|DCRD)$/ ) { + $new->paydate($p->{'year'}. '-'. $p->{'month'}. '-01'); + if ( $new->payinfo eq $cust_main->paymask ) { $new->payinfo($cust_main->payinfo); } else { - $new->paycvv($p->{'paycvv'}); + $new->payinfo($p->{'payinfo'}); + } + + $new->set( 'payby' => $p->{'auto'} ? 'CARD' : 'DCRD' ); + + }elsif ( $payby =~ /^(CHEK|DCHK)$/ ) { + my $payinfo; + $p->{'payinfo1'} =~ /^([\dx]+)$/ + or return { 'error' => "illegal account number ". $p->{'payinfo1'} }; + my $payinfo1 = $1; + $p->{'payinfo2'} =~ /^([\dx]+)$/ + or return { 'error' => "illegal ABA/routing number ". $p->{'payinfo2'} }; + my $payinfo2 = $1; + $payinfo = $payinfo1. '@'. $payinfo2; + + if ( $payinfo eq $cust_main->paymask ) { + $new->payinfo($cust_main->payinfo); + } else { + $new->payinfo($payinfo); } + + $new->set( 'payby' => $p->{'auto'} ? 'CHEK' : 'DCHK' ); + + }elsif ( $payby =~ /^(BILL)$/ ) { + } elsif ( $payby ) { #notyet ready + return { 'error' => "unknown payby $payby" }; } my @invoicing_list; @@ -237,6 +350,16 @@ sub payment_info { 'card_types' => card_types(), + 'paytypes' => [ @FS::cust_main::paytypes ], + + 'paybys' => [ $conf->config('signup_server-payby') ], + + 'stateid_label' => FS::Msgcat::_gettext('stateid'), + 'stateid_state_label' => FS::Msgcat::_gettext('stateid_state'), + + 'show_ss' => $conf->exists('show_ss'), + 'show_stateid' => $conf->exists('show_stateid'), + 'show_paystate' => $conf->exists('show_bankstate'), }; } @@ -260,15 +383,25 @@ sub payment_info { $return{$_} = $cust_main->get($_) for qw(address1 address2 city state zip); $return{payby} = $cust_main->payby; + $return{stateid_state} = $cust_main->stateid_state; if ( $cust_main->payby =~ /^(CARD|DCRD)$/ ) { $return{card_type} = cardtype($cust_main->payinfo); - $return{payinfo} = $cust_main->payinfo; + $return{payinfo} = $cust_main->paymask; @return{'month', 'year'} = $cust_main->paydate_monthyear; } + if ( $cust_main->payby =~ /^(CHEK|DCHK)$/ ) { + my ($payinfo1, $payinfo2) = split '@', $cust_main->paymask; + $return{payinfo1} = $payinfo1; + $return{payinfo2} = $payinfo2; + $return{paytype} = $cust_main->paytype; + $return{paystate} = $cust_main->paystate; + + } + #doubleclick protection my $_date = time; $return{paybatch} = "webui-MyAccount-$_date-$$-". rand() * 2**32; @@ -303,25 +436,38 @@ sub process_payment { or return { 'error' => gettext('illegal_text'). " paybatch: ". $p->{'paybatch'} }; my $paybatch = $1; + $p->{'payby'} =~ /^([A-Z]{4})$/ + or return { 'error' => "illegal_payby " . $p->{'payby'} }; + my $payby = $1; + + #false laziness w/process/payment.cgi my $payinfo; my $paycvv = ''; - #if ( $payby eq 'CHEK' ) { - # - # $p->{'payinfo1'} =~ /^(\d+)$/ - # or return { 'error' => "illegal account number ". $p->{'payinfo1'} }; - # my $payinfo1 = $1; - # $p->{'payinfo2'} =~ /^(\d+)$/ - # or return { 'error' => "illegal ABA/routing number ". $p->{'payinfo2'} }; - # my $payinfo2 = $1; - # $payinfo = $payinfo1. '@'. $payinfo2; - # - #} elsif ( $payby eq 'CARD' ) { + if ( $payby eq 'CHEK' || $payby eq 'DCHK' ) { + + $p->{'payinfo1'} =~ /^([\dx]+)$/ + or return { 'error' => "illegal account number ". $p->{'payinfo1'} }; + my $payinfo1 = $1; + $p->{'payinfo2'} =~ /^([\dx]+)$/ + or return { 'error' => "illegal ABA/routing number ". $p->{'payinfo2'} }; + my $payinfo2 = $1; + $payinfo = $payinfo1. '@'. $payinfo2; + + $payinfo = $cust_main->payinfo + if $cust_main->paymask eq $payinfo; + + } elsif ( $payby eq 'CARD' || $payby eq 'DCRD' ) { $payinfo = $p->{'payinfo'}; + + $payinfo = $cust_main->payinfo + if $cust_main->paymask eq $payinfo; + $payinfo =~ s/\D//g; $payinfo =~ /^(\d{13,16})$/ or return { 'error' => gettext('invalid_card') }; # . ": ". $self->payinfo $payinfo = $1; + validate($payinfo) or return { 'error' => gettext('invalid_card') }; # . ": ". $self->payinfo return { 'error' => gettext('unknown_card_type') } @@ -339,19 +485,23 @@ sub process_payment { } } - #} else { - # die "unknown payby $payby"; - #} + } else { + die "unknown payby $payby"; + } - my $error = $cust_main->realtime_bop( 'CC', $p->{'amount'}, + my %payby2fields = ( + 'CARD' => [ qw( paystart_month paystart_year payissue address1 address2 city state zip payip ) ], + 'CHEK' => [ qw( ss paytype paystate stateid stateid_state payip ) ], + ); + + my $error = $cust_main->realtime_bop( $FS::payby::payby2bop{$payby}, $p->{'amount'}, 'quiet' => 1, 'payinfo' => $payinfo, 'paydate' => $p->{'year'}. '-'. $p->{'month'}. '-01', 'payname' => $payname, 'paybatch' => $paybatch, 'paycvv' => $paycvv, - map { $_ => $p->{$_} } qw( paystart_month paystart_year payissue payip - address1 address2 city state zip ) + map { $_ => $p->{$_} } @{ $payby2fields{$payby} } ); return { 'error' => $error } if $error; @@ -359,11 +509,19 @@ sub process_payment { if ( $p->{'save'} ) { my $new = new FS::cust_main { $cust_main->hash }; - $new->set( $_ => $p->{$_} ) - foreach qw( payname paystart_month paystart_year payissue payip - address1 address2 city state zip payinfo ); + if ($payby eq 'CARD' || $payby eq 'DCRD') { + $new->set( $_ => $p->{$_} ) + foreach qw( payname paystart_month paystart_year payissue payip + address1 address2 city state zip payinfo ); + $new->set( 'payby' => $p->{'auto'} ? 'CARD' : 'DCRD' ); + } elsif ($payby eq 'CHEK' || $payby eq 'DCHK') { + $new->set( $_ => $p->{$_} ) + foreach qw( payname payip paytype paystate + stateid stateid_state ); + $new->set( 'payinfo' => $payinfo ); + $new->set( 'payby' => $p->{'auto'} ? 'CHEK' : 'DCHK' ); + } $new->set( 'paydate' => $p->{'year'}. '-'. $p->{'month'}. '-01' ); - $new->set( 'payby' => $p->{'auto'} ? 'CARD' : 'DCRD' ); my $error = $new->replace($cust_main); return { 'error' => $error } if $error; $cust_main = $new; @@ -373,6 +531,24 @@ sub process_payment { } +sub process_payment_order_pkg { + my $p = shift; + + my $hr = process_payment($p); + return $hr if $hr->{'error'}; + + order_pkg($p); +} + +sub process_payment_order_renew { + my $p = shift; + + my $hr = process_payment($p); + return $hr if $hr->{'error'}; + + order_renew($p); +} + sub process_prepay { my $p = shift; @@ -430,7 +606,7 @@ sub invoice { return { 'error' => '', 'invnum' => $invnum, 'invoice_text' => join('', $cust_bill->print_text ), - 'invoice_html' => $cust_bill->print_html, + 'invoice_html' => $cust_bill->print_html( { unsquelch_cdr => 1 } ), }; } @@ -580,14 +756,14 @@ sub list_svcs { 'username' => $svc_x->username, 'email' => $svc_x->email, 'seconds' => $svc_x->seconds, - 'upbytes' => $svc_x->upbytes, - 'downbytes' => $svc_x->downbytes, - 'totalbytes'=> $svc_x->totalbytes, + 'upbytes' => FS::UI::bytecount::display_bytecount($svc_x->upbytes), + 'downbytes' => FS::UI::bytecount::display_bytecount($svc_x->downbytes), + 'totalbytes'=> FS::UI::bytecount::display_bytecount($svc_x->totalbytes), 'recharge_amount' => $part_pkg->option('recharge_amount', 1), 'recharge_seconds' => $part_pkg->option('recharge_seconds', 1), - 'recharge_upbytes' => $part_pkg->option('recharge_upbytes', 1), - 'recharge_downbytes' => $part_pkg->option('recharge_downbytes', 1), - 'recharge_totalbytes' => $part_pkg->option('recharge_totalbytes', 1), + 'recharge_upbytes' => FS::UI::bytecount::display_bytecount($part_pkg->option('recharge_upbytes', 1)), + 'recharge_downbytes' => FS::UI::bytecount::display_bytecount($part_pkg->option('recharge_downbytes', 1)), + 'recharge_totalbytes' => FS::UI::bytecount::display_bytecount($part_pkg->option('recharge_totalbytes', 1)), # more... }; } @@ -597,8 +773,48 @@ sub list_svcs { } +sub _list_svc_usage { + my($svc_acct, $begin, $end) = @_; + my @usage = (); + foreach my $part_export ( + map { qsearch ( 'part_export', { 'exporttype' => $_ } ) } + qw (sqlradius sqlradius_withdomain') + ) { + + push @usage, @ { $part_export->usage_sessions($begin, $end, $svc_acct) }; + } + (@usage); +} + sub list_svc_usage { - my $p = shift; + _usage_details(\&_list_svc_usage, @_); +} + +sub _list_support_usage { + my($svc_acct, $begin, $end) = @_; + my @usage = (); + foreach ( grep { $begin <= $_->_date && $_->_date <= $end } + qsearch('acct_rt_transaction', { 'svcnum' => $svc_acct->svcnum }) + ) { + push @usage, { 'seconds' => $_->seconds, + 'support' => $_->support, + '_date' => $_->_date, + 'id' => $_->transaction_id, + 'creator' => $_->creator, + 'subject' => $_->subject, + 'status' => $_->status, + 'ticketid' => $_->ticketid, + }; + } + (@usage); +} + +sub list_support_usage { + _usage_details(\&_list_support_usage, @_); +} + +sub _usage_details { + my ($callback, $p) = (shift,shift); my($context, $session, $custnum) = _custoragent_session_custnum($p); return { 'error' => $session } if $context eq 'error'; @@ -618,18 +834,8 @@ sub list_svc_usage { $p->{beginning} = $svc_acct->cust_svc->cust_pkg->last_bill; $p->{ending} = $end; } - my @usage = (); - foreach my $part_export ( - map { qsearch ( 'part_export', { 'exporttype' => $_ } ) } - qw (sqlradius sqlradius_withdomain') - ) { - - push @usage, @ { $part_export->usage_sessions($p->{beginning}, - $p->{ending}, - $svc_acct) - }; - } + my (@usage) = &$callback($svc_acct,$p->{beginning},$p->{ending}); #kinda false laziness with FS::cust_main::bill, but perhaps #we should really change this bit to DateTime and DateTime::Duration @@ -665,7 +871,6 @@ sub list_svc_usage { my $previous = timelocal_nocheck($psec,$pmin,$phour,$pmday,$pmon,$pyear); my $next = timelocal_nocheck($nsec,$nmin,$nhour,$nmday,$nmon,$nyear); - { 'error' => '', 'svcnum' => $p->{svcnum}, @@ -688,6 +893,7 @@ sub order_pkg { my $cust_main = qsearchs('cust_main', $search ) or return { 'error' => "unknown custnum $custnum" }; + my $status = $cust_main->status; #false laziness w/ClientAPI/Signup.pm my $cust_pkg = new FS::cust_pkg ( { @@ -759,7 +965,7 @@ sub order_pkg { my $conf = new FS::Conf; if ( $conf->exists('signup_server-realtime') ) { - my $bill_error = _do_bop_realtime( $cust_main ); + my $bill_error = _do_bop_realtime( $cust_main, $status ); if ($bill_error) { $cust_pkg->cancel('quiet'=>1); @@ -787,6 +993,7 @@ sub change_pkg { my $cust_main = qsearchs('cust_main', $search ) or return { 'error' => "unknown custnum $custnum" }; + my $status = $cust_main->status; my $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $p->{pkgnum} } ) or return { 'error' => "unknown package $p->{pkgnum}" }; @@ -800,7 +1007,7 @@ sub change_pkg { my $conf = new FS::Conf; if ( $conf->exists('signup_server-realtime') ) { - my $bill_error = _do_bop_realtime( $cust_main ); + my $bill_error = _do_bop_realtime( $cust_main, $status ); if ($bill_error) { $newpkg[0]->suspend; @@ -828,6 +1035,7 @@ sub order_recharge { my $cust_main = qsearchs('cust_main', $search ) or return { 'error' => "unknown custnum $custnum" }; + my $status = $cust_main->status; my $cust_svc = qsearchs( 'cust_svc', { 'svcnum' => $p->{'svcnum'} } ) or return { 'error' => "unknown service " . $p->{'svcnum'} }; @@ -851,9 +1059,9 @@ sub order_recharge { my $conf = new FS::Conf; if ( $conf->exists('signup_server-realtime') && !$bill_error ) { - $bill_error = _do_bop_realtime( $cust_main ); + $bill_error = _do_bop_realtime( $cust_main, $status ); - if ('bill_error') { + if ($bill_error) { return $bill_error; } else { my $error = $svc_x->recharge (\%vhash); @@ -871,21 +1079,24 @@ sub order_recharge { } sub _do_bop_realtime { - my ($cust_main) = @_; + my ($cust_main, $status) = (shift, shift); my $old_balance = $cust_main->balance; - my $bill_error = $cust_main->bill; - - $cust_main->apply_payments_and_credits; - $bill_error = $cust_main->collect('realtime' => 1); + my $bill_error = $cust_main->bill + || $cust_main->apply_payments_and_credits + || $cust_main->collect('realtime' => 1); if ( $cust_main->balance > $old_balance && $cust_main->balance > 0 - && $cust_main->payby !~ /^(BILL|DCRD|DCHK)$/ ) { + && ( $cust_main->payby !~ /^(BILL|DCRD|DCHK)$/ ? + 1 : $status eq 'suspended' ) ) { #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' ); + 'self-service decline', + 'reason_type' => $conf->config('signup_credit_type'), + ); $cust_main->apply_credits( 'order' => 'newest' ); return { 'error' => '_decline', 'bill_error' => $bill_error }; @@ -894,6 +1105,64 @@ sub _do_bop_realtime { ''; } +sub renew_info { + my $p = shift; + + my($context, $session, $custnum) = _custoragent_session_custnum($p); + return { 'error' => $session } if $context eq 'error'; + + my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) + or return { 'error' => "unknown custnum $custnum" }; + + my @cust_pkg = sort { $a->bill <=> $b->bill } + grep { $_->part_pkg->freq ne '0' } + $cust_main->ncancelled_pkgs; + + #return { 'error' => 'No active packages to renew.' } unless @cust_pkg; + + my $total = 0; + + my @array = map { + $total += $_->part_pkg->base_recur; + my $renew_date = $_->part_pkg->add_freq($_->bill); + { + 'bill_date' => $_->bill, + 'bill_date_pretty' => time2str('%x', $_->bill), + 'renew_date' => $renew_date, + 'renew_date_pretty' => time2str('%x', $renew_date), + 'amount' => sprintf('.%2f', $total), + }; + } + @cust_pkg; + + return { 'dates' => \@array }; + +} + +sub order_renew { + my $p = shift; + + my($context, $session, $custnum) = _custoragent_session_custnum($p); + return { 'error' => $session } if $context eq 'error'; + + my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) + or return { 'error' => "unknown custnum $custnum" }; + + my $date = $p->{'date'}; + + my $now = time; + + #freeside-daily -n -d $date fs_daily $custnum + $cust_main->bill_and_collect( 'time' => $date, + 'invoice_time' => $now, + 'actual_time' => $now, + 'check_freq' => '1d', + ); + + return { 'error' => '' }; + +} + sub cancel_pkg { my $p = shift; my $session = _cache->get($p->{'session_id'}) @@ -917,15 +1186,26 @@ sub cancel_pkg { sub provision_acct { my $p = shift; + warn "provision_acct called\n" + if $DEBUG; return { 'error' => gettext('passwords_dont_match') } if $p->{'_password'} ne $p->{'_password2'}; return { 'error' => gettext('empty_password') } unless length($p->{'_password'}); + + if ($p->{'domsvc'}) { + my %domains = domain_select_hash FS::svc_acct(map { $_ => $p->{$_} } + qw ( svcpart pkgnum ) ); + return { 'error' => gettext('invalid_domain') } + unless ($domains{$p->{'domsvc'}}); + } + warn "provision_acct calling _provision\n" + if $DEBUG; _provision( 'FS::svc_acct', - [qw(username _password)], - [qw(username _password)], + [qw(username _password domsvc)], + [qw(username _password domsvc)], $p, @_ ); @@ -944,6 +1224,8 @@ sub provision_external { sub _provision { my( $class, $fields, $return_fields, $p ) = splice(@_, 0, 4); + warn "_provision called for $class\n" + if $DEBUG; my($context, $session, $custnum) = _custoragent_session_custnum($p); return { 'error' => $session } if $context eq 'error'; @@ -955,27 +1237,42 @@ sub _provision { my $pkgnum = $p->{'pkgnum'}; + warn "searching for custnum $custnum pkgnum $pkgnum\n" + if $DEBUG; my $cust_pkg = qsearchs('cust_pkg', { 'custnum' => $custnum, 'pkgnum' => $pkgnum, } ) or return { 'error' => "unknown pkgnum $pkgnum" }; + warn "searching for svcpart ". $p->{'svcpart'}. "\n" + if $DEBUG; my $part_svc = qsearchs('part_svc', { 'svcpart' => $p->{'svcpart'} } ) or return { 'error' => "unknown svcpart $p->{'svcpart'}" }; + warn "creating $class record\n" + if $DEBUG; my $svc_x = $class->new( { 'pkgnum' => $p->{'pkgnum'}, 'svcpart' => $p->{'svcpart'}, map { $_ => $p->{$_} } @$fields } ); + warn "inserting $class record\n" + if $DEBUG; my $error = $svc_x->insert; - $svc_x = qsearchs($svc_x->table, { 'svcnum' => $svc_x->svcnum }) - unless $error; - return { 'svc' => $part_svc->svc, - 'error' => $error, - map { $_ => $svc_x->get($_) } @$return_fields - }; + unless ( $error ) { + warn "finding inserted record for svcnum ". $svc_x->svcnum. "\n" + if $DEBUG; + $svc_x = qsearchs($svc_x->table, { 'svcnum' => $svc_x->svcnum }) + } + + my $return = { 'svc' => $part_svc->svc, + 'error' => $error, + map { $_ => $svc_x->get($_) } @$return_fields + }; + warn "_provision returning ". Dumper($return). "\n" + if $DEBUG; + return $return; }