X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2FClientAPI%2FPrepaidPhone.pm;h=2cea3c23184be09747ea0d3e9e8556d318c2570a;hb=8b8d621a1bb4e9abaa1f0edab5190d302e6a6e99;hp=2d6297a8aee4632119cc77da537f0f2ea64243a9;hpb=92adead1404db357a11b58f38c2b4403381a2809;p=freeside.git diff --git a/FS/FS/ClientAPI/PrepaidPhone.pm b/FS/FS/ClientAPI/PrepaidPhone.pm index 2d6297a8a..2cea3c231 100644 --- a/FS/FS/ClientAPI/PrepaidPhone.pm +++ b/FS/FS/ClientAPI/PrepaidPhone.pm @@ -1,13 +1,14 @@ package FS::ClientAPI::PrepaidPhone; use strict; -#use vars qw($DEBUG $me); +use vars qw($DEBUG $me); use FS::Record qw(qsearchs); +use FS::Conf; use FS::rate; use FS::svc_phone; -#$DEBUG = 0; -#$me = '[FS::ClientAPI::PrepaidPhone]'; +$DEBUG = 0; +$me = '[FS::ClientAPI::PrepaidPhone]'; #TODO: # - shared-secret auth? (set a conf value) @@ -53,60 +54,119 @@ sub call_time { my $src = $packet->{'src'}; my $dst = $packet->{'dst'}; - my $number; + my $chargeto; + my $rateby; #my $conf = new FS::Conf; #if ( #XXX toll-free? collect? # $phonenum = $dst; #} else { #use the src to find the customer - $number = $src; + $chargeto = $src; + $rateby = $dst; #} my( $countrycode, $phonenum ); - if ( $number #this is an interesting regex to parse out 1&2 digit countrycodes + if ( $chargeto #an interesting regex to parse out 1&2 digit countrycodes =~ /^(2[078]|3[0-469]|4[013-9]|5[1-8]|6[0-6]|7|8[1-469]|9[0-58])(\d*)$/ - || $number =~ /^(\d{3})(\d*)$/ + || $chargeto =~ /^(\d{3})(\d*)$/ ) { $countrycode = $1; $phonenum = $2; } else { - return { 'error' => "unparsable number: $number" }; + return { 'error' => "unparsable billing number: $chargeto" }; } + my $svc_phone = qsearchs('svc_phone', { 'countrycode' => $countrycode, 'phonenum' => $phonenum, } ); unless ( $svc_phone ) { - return { 'custnum' => '', - 'seconds' => 0, - #'balance' => 0, - }; + return { 'error' => "can't find customer for +$countrycode $phonenum" }; +# return { 'custnum' => '', +# 'seconds' => 0, +# #'balance' => 0, +# }; }; my $cust_pkg = $svc_phone->cust_svc->cust_pkg; - my $part_pkg = $cust_pkg->part_pkg; my $cust_main = $cust_pkg->cust_main; + my $part_pkg = $cust_pkg->part_pkg; + my @part_pkg = ( $part_pkg, map $_->dst_pkg, $part_pkg->bill_part_pkg_link ); + #XXX uuh, behavior indeterminate if you have more than one voip_cdr+prefix + #add-on, i guess. + warn "$me ". scalar(@part_pkg). ': '. + join('/', map { $_->plan. $_->option('rating_method') } @part_pkg ) + if $DEBUG; + @part_pkg = + grep { $_->plan eq 'voip_cdr' && $_->option('rating_method') eq 'prefix' } + @part_pkg; + my %return = ( 'custnum' => $cust_pkg->custnum, #'balance' => $cust_pkg->cust_main->balance, ); - return \%return unless $part_pkg->plan eq 'voip_cdr' - && $part_pkg->option('rating_method') eq 'prefix'; + warn "$me: ". scalar(@part_pkg). ': '. + join('/', map { $_->plan. $_->option('rating_method') } @part_pkg ) + if $DEBUG; + return \%return unless @part_pkg; + + warn "$me searching for rate ". $part_pkg[0]->option('ratenum') + if $DEBUG; + + my $rate = qsearchs('rate', { 'ratenum'=>$part_pkg[0]->option('ratenum') } ); - my $rate = qsearchs('rate', { 'ratenum' => $part_pkg->option('ratenum') } ); + unless ( $rate ) { + my $error = 'ratenum '. $part_pkg[0]->option('ratenum'). ' not found'; + warn "$me $error" + if $DEBUG; + return { 'error'=>$error }; + } + + warn "$me found rate ". $rate->ratenum + if $DEBUG; #rate the call and arrive at a max # of seconds for the customer's balance - my $rate_detail = $rate->dest_detail({ 'countrycode' => $countrycode, - 'phonenum' => $phonenum, + + my( $rate_countrycode, $rate_phonenum ); + if ( $rateby #this is an interesting regex to parse out 1&2 digit countrycodes + =~ /^(2[078]|3[0-469]|4[013-9]|5[1-8]|6[0-6]|7|8[1-469]|9[0-58])(\d*)$/ + || $rateby =~ /^(\d{3})(\d*)$/ + ) + { + $rate_countrycode = $1; + $rate_phonenum = $2; + } else { + return { 'error' => "unparsable rating number: $rateby" }; + } + + my $rate_detail = $rate->dest_detail({ 'countrycode' => $rate_countrycode, + 'phonenum' => $rate_phonenum, }); + unless ( $rate_detail ) { + return { 'error'=>"can't find rate for +$rate_countrycode $rate_phonenum"}; + } + + unless ( $rate_detail->min_charge > 0 ) { + #XXX no charge?? return lots of seconds, a default, 0 or what? + #return { 'error' => '0 rate for +$rate_countrycode $rate_phonenum; prepaid service not available" }; + #customer wants no default for now# $return{'seconds'} = 1800; #half hour?! + return \%return; + } + + my $balance = FS::ClientAPI::PrepaidPhone->prepaid_phone_balance( $cust_pkg ); #XXX granularity? included minutes? another day... + if ( $balance >= 0 ) { + return { 'error'=>'No balance' }; + } else { + $return{'seconds'} = int(60 * abs($balance) / $rate_detail->min_charge); + } - $return{'seconds'} = int(60 * $cust_main->balance / $rate_detail->min_charge); + warn "$me returning seconds: ". $return{'seconds'}; return \%return; @@ -173,12 +233,17 @@ Customer balance. sub phonenum_balance { my $packet = shift; + warn "$me phonenum_balance called with countrycode ".$packet->{'countrycode'}. + " and phonenum ". $packet->{'phonenum'}. "\n" + if $DEBUG; + my $svc_phone = qsearchs('svc_phone', { 'countrycode' => ( $packet->{'countrycode'} || 1 ), 'phonenum' => $packet->{'phonenum'}, }); unless ( $svc_phone ) { + warn "$me no phone number found\n" if $DEBUG; return { 'custnum' => '', 'balance' => 0, }; @@ -186,11 +251,72 @@ sub phonenum_balance { my $cust_pkg = $svc_phone->cust_svc->cust_pkg; + my $balance = FS::ClientAPI::PrepaidPhone->prepaid_phone_balance( $cust_pkg ); + + warn "$me returning $balance balance for pkgnum ". $cust_pkg->pkgnum. + ", custnum ". $cust_pkg->custnum + if $DEBUG; + return { 'custnum' => $cust_pkg->custnum, - 'balance' => $cust_pkg->cust_main->balance, + 'balance' => $balance, }; } +sub prepaid_phone_balance { + my $class = shift; # i guess + my ($cust_pkg) = @_; + + my $conf = new FS::Conf; + + my $pkg_balances = $conf->config_bool('pkg-balances'); + + my $balance = $pkg_balances ? $cust_pkg->balance + : $cust_pkg->cust_main->balance; + + if ( $conf->config_bool('cdr-prerate') ) { + my @cust_pkg = $pkg_balances ? ( $cust_pkg ) + : ( $cust_pkg->cust_main->ncancelled_pkgs ); + foreach my $cust_pkg ( @cust_pkg ) { + + #we only support prerated CDRs with "VOIP/telco CDR rating (standard)" + # and "Phone numbers (svc_phone.phonenum)" CDR service matching for now + my $part_pkg = $cust_pkg->part_pkg; + next unless $part_pkg->plan eq 'voip_cdr' + && ($part_pkg->option('cdr_svc_method') || 'svc_phone.phonenum') + eq 'svc_phone.phonenum' + && ! $part_pkg->option('bill_inactive_svcs'); + #XXX skip when there's included minutes + + #select prerated cdrs & subtract them from balance + + # false laziness w/ part_pkg/voip_cdr.pm sorta + + my %options = ( + 'disable_src' => $part_pkg->option('disable_src'), + 'default_prefix' => $part_pkg->option('default_prefix'), + 'cdrtypenum' => $part_pkg->option('use_cdrtypenum'), + 'calltypenum' => $part_pkg->option('use_calltypenum'), + 'status' => 'rated', + 'by_svcnum' => 1, + ); # $last_bill, $$sdate ) + + my @cust_svc = grep { $_->part_svc->svcdb eq 'svc_phone' } + $cust_pkg->cust_svc; + foreach my $cust_svc ( @cust_svc ) { + + my $svc_x = $cust_svc->svc_x; + my $sum_cdr = $svc_x->sum_cdrs(%options); + $balance += $sum_cdr->rated_price; + + } + + } + } + + $balance; + +} + 1;