-
- } else {
- # leave this as is for now
-
- my $name = $taxline->{'name'};
- my $amount = $taxline->{'amount'};
-
- #warn "adding $amount as $name\n";
- $taxname{ $name } ||= [];
- push @{ $taxname{ $name } }, $tax;
-
- $tax_amount{ $tax } += $amount;
-
- # link records between cust_main_county/tax_rate and cust_location
- $tax_rate_location{ $tax } ||= [];
- my $taxratelocationnum =
- $tax_object->tax_rate_location->taxratelocationnum;
- push @{ $tax_rate_location{ $tax } },
- {
- 'taxnum' => $tax_object->taxnum,
- 'taxtype' => ref($tax_object),
- 'amount' => sprintf('%.2f', $amount ),
- 'locationtaxid' => $tax_object->location,
- 'taxratelocationnum' => $taxratelocationnum,
- };
- } #if ref($tax_object)...
- } #foreach keys %$taxlisthash
+ }
+ }
+ $DB::single = 1; # XXX
+
+ # all first-tier taxes are calculated. now for tax on tax:
+
+ foreach my $taxable_item ( @$cust_bill_pkg ) {
+ # taxes that apply to this item
+ my $this_has_tax = $item_has_tax{$taxable_item};
+
+ my $location = $taxable_item->tax_location;
+ foreach my $tax_id (keys %$this_has_tax) {
+ my ($class, $taxnum) = split(' ', $tax_id);
+ # internal taxes don't support tax_on_tax, so we don't bother with
+ # them here.
+ next unless $class eq 'FS::tax_rate';
+
+ # for each tax item that was calculated in phase 1, get the
+ # tax definition
+ my $tax_object = FS::tax_rate->by_key($taxnum);
+ # and find all taxes that apply to it in this location
+ my @tot = $tax_object->tax_on_tax( $location );
+ next if !@tot;
+ warn "found possible taxed taxnum $taxnum\n"
+ if $DEBUG > 2;
+ # Calculate ToT separately for each taxable item, and only if _that
+ # item_ is already taxed under the ToT. This is counterintuitive.
+ # See RT#5243.
+ foreach my $tot (@tot) {
+ my $tot_id = ref($tot) . ' ' . $tot->taxnum;
+ warn "checking taxnum ".$tot->taxnum.
+ " which we call ". $tot->taxname ."\n"
+ if $DEBUG > 2;
+ if ( exists $this_has_tax->{ $tot_id } ) {
+ warn "calculating tax on tax: taxnum ".$tot->taxnum." on $taxnum\n"
+ if $DEBUG;
+ my @taxlines = $tot->taxline(
+ $this_has_tax->{ $tax_id }, # the first-stage tax
+ 'custnum' => $self->custnum,
+ 'invoice_time' => $invoice_time,
+ );
+ next if (!@taxlines); # it didn't apply after all
+ if (!ref($taxlines[0])) {
+ warn "error evaluating $tot_id TOT on custnum ".
+ $self->custnum."\n";
+ return $taxlines[0];
+ }
+ foreach my $taxline (@taxlines) {
+ push @{ $taxname{ $taxline->itemdesc } }, $taxline;
+ }
+ } # if $has_tax
+ } # foreach my $tot (tax-on-tax rate definition)
+ } # foreach $taxnum (first-tier rate definition)
+ } # foreach $taxable_item