use base 'FS::TaxEngine';
use FS::Conf;
use FS::Record qw(qsearch qsearchs dbh);
-use JSON;
+use Cpanel::JSON::XS;
use XML::Simple qw(XMLin);
use LWP::UserAgent;
use HTTP::Request::Common;
# $DEBUG = 2; # prints decoded request and response (noisy, be careful)
# $DEBUG = 3; # prints raw response from the API, ridiculously unreadable
-our $json = JSON->new->pretty(1);
+our $json = Cpanel::JSON::XS->new->pretty(1);
our %taxproduct_cache;
my @lines = map { $self->build_item($_) }
$cust_bill->cust_bill_pkg;
+ return if !@lines;
+
my $ClientNumber = $conf->config('suretax-client_number')
or die "suretax-client_number config required.\n";
my $ValidationKey = $conf->config('suretax-validation_key')
my @items;
my $recur_without_usage = $cust_bill_pkg->recur;
+ # use the _configured_ tax location as 'Zipcode' (respecting
+ # tax-ship_address and tax-pkg_address configs)
my $location = $cust_bill_pkg->tax_location;
- my ($svc_zip, $svc_plus4) = split('-', $location->zip);
+ my ($zip, $plus4) = split('-', $location->zip);
+
+ # and the _real_ location as 'P2PZipcode'
+ my $svc_location = $location;
+ if ( $cust_bill_pkg->pkgnum ) {
+ $svc_location = $cust_bill_pkg->cust_pkg->cust_location;
+ }
+ my ($svc_zip, $svc_plus4) = split('-', $svc_location->zip);
my $startdate =
DateTime->from_epoch( epoch => $cust_bill->_date )->strftime('%m-%d-%Y');
'OrigNumber' => '',
'TermNumber' => '',
'BillToNumber' => '',
- 'Zipcode' => $self->{bill_zip},
- 'Plus4' => ($self->{bill_plus4} ||= '0000'),
+ 'Zipcode' => $zip,
+ 'Plus4' => ($plus4 ||= '0000'),
'P2PZipcode' => $svc_zip,
'P2PPlus4' => ($svc_plus4 ||= '0000'),
# we don't support Order Placement/Approval zip codes
while ( my $cdr = $cdrs->fetch ) {
my $calldate =
DateTime->from_epoch( epoch => $cdr->startdate )->strftime('%m-%d-%Y');
- # determine the tax situs rule; it's different (probably more accurate)
- # if the call has PSTN phone numbers at both ends
- my $tsr = $TSR_CALL_OTHER;
- if ( $cdr->charged_party =~ /^\d{10}$/ and
- $cdr->src =~ /^\d{10}$/ and
- $cdr->dst =~ /^\d{10}$/ ) {
- $tsr = $TSR_CALL_NPANXX;
- }
my %hash = (
%base_item,
'LineNumber' => 'C' . $cdr->acctid,
- 'OrigNumber' => $cdr->src,
- 'TermNumber' => $cdr->dst,
- 'BillToNumber' => $cdr->charged_party,
+ 'OrigNumber' => '',
+ 'TermNumber' => '',
+ 'BillToNumber' => '',
'TransDate' => $calldate,
'Revenue' => $cdr->rated_price, # 4 decimal places
'Units' => 0, # right?
'CallDuration' => $cdr->duration,
- 'TaxSitusRule' => $tsr,
+ 'TaxSitusRule' => $TSR_CALL_OTHER,
'TransTypeCode' => $taxproduct,
);
+ # determine the tax situs rule; it's different (probably more accurate)
+ # if the call has PSTN phone numbers at both ends
+ if ( $cdr->charged_party =~ /^\d{10}$/ and
+ $cdr->src =~ /^\d{10}$/ and
+ $cdr->dst =~ /^\d{10}$/ and
+ !$cdr->is_tollfree ) {
+ $hash{TaxSitusRule} = $TSR_CALL_NPANXX;
+ $hash{OrigNumber} = $cdr->src;
+ $hash{TermNumber} = $cdr->dst;
+ $hash{BillToNumber} = $cdr->charged_party;
+ }
+
push @items, \%hash;
} # while ($cdrs->fetch)
if !$taxproduct;
my $tsr = $TSR_GENERAL;
+ # when billing on cancellation there are no units
+ my $units = $self->{cancel} ? 0 : $cust_bill_pkg->units;
my %hash = (
%base_item,
'LineNumber' => 'R' . $billpkgnum,
'Revenue' => $recur_without_usage, # 4 decimal places
- 'Units' => $cust_bill_pkg->units,
+ 'Units' => $units,
'TaxSitusRule' => $tsr,
'TransTypeCode' => $taxproduct,
);
# assemble the request hash
my $request = $self->build_request;
+ if (!$request) {
+ warn "no taxable items in invoice; skipping SureTax request\n" if $DEBUG;
+ return;
+ }
warn "sending SureTax request\n" if $DEBUG;
my $request_json = $json->encode($request);