X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2FClientAPI%2FMyAccount.pm;h=4614af2f5cae7b6c5c0519401b29234706101e33;hb=31f1e1bd302bd88d97d56b20dffad5c5f2388261;hp=336482123ff4096844cef5588236354a6e493c6a;hpb=eb2c0c03d10e1561f8bfbea42b29bdf1b165c52b;p=freeside.git diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index 336482123..4614af2f5 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -11,7 +11,7 @@ use Digest::SHA qw(sha512_hex); use Date::Format; use Time::Duration; use Time::Local qw(timelocal_nocheck); -use Business::CreditCard; +use Business::CreditCard 0.35; use HTML::Entities; use Text::CSV_XS; use Spreadsheet::WriteExcel; @@ -645,6 +645,29 @@ sub customer_info_short { }; } +sub customer_recurring { + my $p = shift; + + my($context, $session, $custnum) = _custoragent_session_custnum($p); + return { 'error' => $session } if $context eq 'error'; + + my %return; + + my $conf = new FS::Conf; + + my $search = { 'custnum' => $custnum }; + $search->{'agentnum'} = $session->{'agentnum'} if $context eq 'agent'; + my $cust_main = qsearchs('cust_main', $search ) + or return { 'error' => "customer_info_short: unknown custnum $custnum" }; + + $return{'display_recurring'} = [ $cust_main->display_recurring ]; + + return { 'error' => '', + 'custnum' => $custnum, + %return, + }; +} + sub billing_history { my $p = shift; @@ -844,8 +867,8 @@ sub payment_info { 'show_paystate' => $conf->exists('show_bankstate'), 'save_unchecked' => $conf->exists('selfservice-save_unchecked'), + 'ach_read_only' => $conf->exists('selfservice-ACH_info_readonly'), - 'credit_card_surcharge_percentage' => scalar($conf->config('credit-card-surcharge-percentage')), }; } @@ -856,6 +879,8 @@ sub payment_info { my %return = %$payment_info; + delete $return{'cust_main_county'} if $p->{'omit_cust_main_county'}; + my $custnum = $session->{'custnum'}; my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) @@ -906,6 +931,8 @@ sub payment_info { $return{payunique} = "webui-MyAccount-$_date-$$-". rand() * 2**32; #new $return{paybatch} = $return{payunique}; #back compat + $return{credit_card_surcharge_percentage} = $conf->config('credit-card-surcharge-percentage', $cust_main->agentnum); + return { 'error' => '', %return, }; @@ -1175,7 +1202,7 @@ sub do_process_payment { #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" } + return { 'error' => "payment processed and fee ordered successfully, but error billing fee: $error" } if $error; } @@ -1575,6 +1602,42 @@ sub list_invoices { }; } +sub list_payments { + my $p = shift; + my $session = _cache->get($p->{'session_id'}) + or return { 'error' => "Can't resume session" }; #better error message + + my $custnum = $session->{'custnum'}; + + my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) + or return { 'error' => "unknown custnum $custnum" }; + + return { 'error' => '', + 'balance' => $cust_main->balance, + 'money_char' => FS::Conf->new->config("money_char") || '$', + 'payments' => [ map $_->SSAPI_getinfo, $cust_main->cust_pay ], + }; +} + +sub payment_receipt { + my $p = shift; + my $session = _cache->get($p->{'session_id'}) + or return { 'error' => "Can't resume session" }; #better error message + + my $custnum = $session->{'custnum'}; + + my $cust_pay = qsearchs('cust_pay', { 'custnum' => $custnum, + 'paynum' => $p->{'paynum'}, + } + ) + or return { 'error' => "unknown payment ". $p->{'paynum'} }; + + return { + 'error' => '', + %{ $cust_pay->SSAPI_getinfo }, + }; +} + sub cancel { my $p = shift; my $session = _cache->get($p->{'session_id'}) @@ -1593,6 +1656,30 @@ sub cancel { } +sub pkg_info { + my $p = shift; + + my($context, $session, $custnum) = _custoragent_session_custnum($p); + return { 'error' => $session } if $context eq 'error'; + + my $pkg = qsearchs({ + 'table' => 'cust_pkg', + 'addl_from' => 'LEFT JOIN part_pkg USING ( pkgpart )', + 'hashref' => { + 'custnum' => $custnum, + 'pkgnum' => $p->{'pkgnum'}, + }, + }) + or return {'error' => 'unknown pkg num $pkgnum'}; + + return { + pkg_label => $pkg->pkg, + pkgpart => $pkg->pkgpart, + classnum => $pkg->classnum, + }; + +} + sub list_pkgs { my $p = shift; @@ -1751,6 +1838,7 @@ sub list_svcs { # @svc_x; my @svcs; # stuff to return to the client + my %bytes_used_total; # for _used columns only foreach my $cust_svc (@cust_svc) { my $svc_x = $cust_svc->svc_x; my($label, $value) = $cust_svc->label; @@ -1772,6 +1860,24 @@ sub list_svcs { # would it make sense to put this in a svc_* method? + if (!$hide_usage and grep(/^$svcdb$/, qw(svc_acct svc_broadband)) and $part_svc->part_export_usage) { + my $last_bill = $cust_pkg->last_bill || 0; + my $now = time; + my $up_used = $cust_svc->attribute_since_sqlradacct($last_bill,$now,'AcctInputOctets'); + my $down_used = $cust_svc->attribute_since_sqlradacct($last_bill,$now,'AcctOutputOctets'); + %hash = ( + %hash, + 'seconds_used' => $cust_svc->seconds_since_sqlradacct($last_bill,$now), + 'upbytes_used' => display_bytecount($up_used), + 'downbytes_used' => display_bytecount($down_used), + 'totalbytes_used' => display_bytecount($up_used + $down_used) + ); + $bytes_used_total{'seconds_used'} += $hash{'seconds_used'}; + $bytes_used_total{'upbytes_used'} += $up_used; + $bytes_used_total{'downbytes_used'} += $down_used; + $bytes_used_total{'totalbytes_used'} += $up_used + $down_used; + } + if ( $svcdb eq 'svc_acct' ) { foreach (qw(username email finger seconds)) { $hash{$_} = $svc_x->$_; @@ -1844,12 +1950,19 @@ sub list_svcs { push @svcs, \%hash; } # foreach $cust_svc + foreach my $field (keys %bytes_used_total) { + if ($field =~ /bytes/) { + $bytes_used_total{$field} = display_bytecount($bytes_used_total{$field}); + } + } + return { 'svcnum' => $session->{'svcnum'}, 'custnum' => $custnum, 'date_format' => $conf->config('date_format') || '%m/%d/%Y', 'view_usage_nodomain' => $conf->exists('selfservice-view_usage_nodomain'), 'svcs' => \@svcs, + 'bytes_used_total' => \%bytes_used_total, 'usage_pools' => [ map { $usage_pools{$_} } sort { $a cmp $b } @@ -2342,7 +2455,7 @@ sub order_pkg { my $conf = new FS::Conf; if ( $conf->exists('signup_server-realtime') ) { - my $bill_error = _do_bop_realtime( $cust_main, $status ); + my $bill_error = _do_bop_realtime( $cust_main, $status, 'collect'=>$p->{run_bill_events} ); if ($bill_error) { $cust_pkg->cancel('quiet'=>1); @@ -2388,10 +2501,14 @@ sub change_pkg { my $err_or_cust_pkg = $cust_pkg->change( 'pkgpart' => $p->{'pkgpart'}, 'quantity' => $p->{'quantity'} || 1, ); + + my $new_pkg = qsearchs('part_pkg', { 'pkgpart' => $p->{pkgpart} } ) + or return { 'error' => "unknown package $p->{pkgpart}" }; return { error=>$err_or_cust_pkg, pkgnum=>$cust_pkg->pkgnum } unless ref($err_or_cust_pkg); + if ( $conf->exists('signup_server-realtime') ) { my $bill_error = _do_bop_realtime( $cust_main, $status, 'no_invoice_void'=>1 ); @@ -2407,7 +2524,7 @@ sub change_pkg { $err_or_cust_pkg->reexport; } - return { error => '', pkgnum => $cust_pkg->pkgnum }; + return { error => '', pkg => $new_pkg->pkg, pkgnum => $err_or_cust_pkg->pkgnum }; } @@ -2468,39 +2585,45 @@ sub order_recharge { sub _do_bop_realtime { my ($cust_main, $status, %opt) = @_; - my $old_balance = $cust_main->balance; - - my @cust_bill; - my $bill_error = $cust_main->bill( - 'return_bill' => \@cust_bill, - ); + my $old_balance = $cust_main->balance; - $bill_error ||= $cust_main->apply_payments_and_credits; + my @cust_bill; + my $bill_error = $cust_main->bill( + 'return_bill' => \@cust_bill, + ); - $bill_error ||= $cust_main->realtime_collect('selfservice' => 1) - if $cust_main->payby =~ /^(CARD|CHEK)$/; + $bill_error ||= $cust_main->apply_payments_and_credits; - if ( $cust_main->balance > $old_balance - && $cust_main->balance > 0 - && ( $cust_main->payby !~ /^(BILL|DCRD|DCHK)$/ - || $status eq 'suspended' - ) - ) - { - unless ( $opt{'no_invoice_void'} ) { + $bill_error ||= $cust_main->realtime_collect('selfservice' => 1) + if $cust_main->payby =~ /^(CARD|CHEK)$/; - #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; - } + if ( $cust_main->balance > $old_balance + && $cust_main->balance > 0 + && ( $cust_main->payby !~ /^(BILL|DCRD|DCHK)$/ + || $status eq 'suspended' + ) + ) + { + 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 }; } - ''; + return { 'error' => '_decline', 'bill_error' => $bill_error }; + } + + if ( $opt{'collect'} ) { + my $collect_error = $cust_main->collect(); + return { 'error' => '_decline', 'bill_error' => $collect_error } + if $collect_error; #? + } + + ''; } sub renew_info { @@ -2606,19 +2729,18 @@ sub cancel_pkg { or return { 'error' => "Can't resume session" }; #better error message my $custnum = $session->{'custnum'}; - my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) or return { 'error' => "unknown custnum $custnum" }; my $pkgnum = $p->{'pkgnum'}; - my $cust_pkg = qsearchs('cust_pkg', { 'custnum' => $custnum, 'pkgnum' => $pkgnum, } ) or return { 'error' => "unknown pkgnum $pkgnum" }; - my $error = $cust_pkg->cancel('quiet' => 1); + my $error = $cust_pkg->cancel( 'quiet' => 1, + 'date' => $p->{'date'}, + ); return { 'error' => $error }; - } sub provision_phone { @@ -3277,6 +3399,13 @@ sub validate_passwd { # end false laziness } + unless ($svc_acct) { + my $conf = new FS::Conf; + my $agentnum = $p->{'agentnum'}; + return { %result, 'password_valid' => 1 } + if $conf->config_bool('password-insecure', $p->{'agentnum'}); + } + $svc_acct ||= new FS::svc_acct {}; my $error = $svc_acct->is_password_allowed($p->{'check_password'});