- if ( exists $this_has_tax->{ $totnum } ) {
- warn "calculating tax on tax: taxnum ".$tot->taxnum." on $taxnum\n"
- if $DEBUG;
- my @taxlines = $tot->taxline_cch(
- $this_has_tax->{ $taxnum }, # the first-stage tax (in an arrayref)
- );
- next if (!@taxlines); # it didn't apply after all
- if (!ref($taxlines[0])) {
- warn "error evaluating TOT ($totnum on $taxnum)\n";
- return $taxlines[0];
- }
- # add these to the taxline queue
- push @raw_taxlines, @taxlines;
- } # if $this_has_tax->{$totnum}
- } # foreach my $tot (tax-on-tax rate definition)
- } # foreach $taxnum (first-tier rate definition)
+ # Calculate ToT separately for each taxable item and class, and only
+ # if _that class on the item_ is already taxed under the ToT. This is
+ # counterintuitive.
+ # See RT#5243 and RT#36380.
+ my $temp_lineitem;
+ foreach my $tot (@tot) {
+ my $totnum = $tot->taxnum;
+ warn "checking taxnum ".$tot->taxnum.
+ " which we call ". $tot->taxname ."\n"
+ if $DEBUG > 2;
+ # note: if the _null class_ on this item is taxed under the ToT,
+ # then this specific class is taxed also (because null class
+ # includes all classes) and so ToT is applicable.
+ if (
+ exists $this_class_has_tax->{ $totnum }
+ or exists $this_has_tax->{''}{ $totnum }
+ ) {
+ warn "calculating tax on tax: taxnum ".$tot->taxnum." on $taxnum\n"
+ if $DEBUG;
+ # construct a line item to calculate tax on
+ $temp_lineitem ||= FS::cust_bill_pkg->new({
+ 'pkgnum' => 0,
+ 'invnum' => $cust_bill->invnum,
+ 'setup' => sum(map $_->amount, @{ $this_class_has_tax->{$taxnum} }),
+ 'recur' => 0,
+ 'itemdesc' => $tax_rate->taxname,
+ 'cust_bill_pkg_tax_rate_location' => $this_class_has_tax->{$taxnum},
+ });
+ my @new_taxlines = $tot->taxline_cch( [ $temp_lineitem ] );
+ next if (!@new_taxlines); # it didn't apply after all
+ if (!ref($new_taxlines[0])) {
+ die "error evaluating TOT ($totnum on $taxnum): $new_taxlines[0]\n";
+ }
+ # add these to the taxline queue
+ push @raw_taxlines, @new_taxlines;
+ } # if $this_has_tax->{$totnum}
+ } # foreach my $tot (tax-on-tax rate definition)
+ } # foreach $taxnum (first-tier rate definition)
+ } # foreach $charge_class