From 76d6fe17d02b77301619065ad43d7300432e977c Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Wed, 1 Apr 2015 01:54:21 -0500 Subject: CCH tax exemptions + 4.x tax system, #34223 --- FS/FS/TaxEngine.pm | 83 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 28 deletions(-) (limited to 'FS/FS/TaxEngine.pm') diff --git a/FS/FS/TaxEngine.pm b/FS/FS/TaxEngine.pm index a146c54..0972fb7 100644 --- a/FS/FS/TaxEngine.pm +++ b/FS/FS/TaxEngine.pm @@ -14,22 +14,22 @@ FS::TaxEngine - Base class for tax calculation engines. =head1 USAGE 1. At the start of creating an invoice, create an FS::TaxEngine object. -2. Each time a sale item is added to the invoice, call C on the +2. Each time a sale item is added to the invoice, call L on the TaxEngine. - -- If the TaxEngine is "batch" style (Billsoft): 3. Set the "pending" flag on the invoice. 4. Insert the invoice and its line items. + +- If the TaxEngine is "batch" style (Billsoft): 5. After creating all invoices for the day, call FS::TaxEngine::process_tax_batch. This will create the tax items for all of the pending invoices, clear the "pending" flag, and call - C on each of the billed customers. + L on each of the billed customers. - If not (the internal tax system, CCH): -3. After adding all sale items, call C on the TaxEngine to +5. After adding all sale items, call L on the TaxEngine to produce a list of tax line items. -4. Append the tax line items to the invoice. -5. Insert the invoice. +6. Append the tax line items to the invoice. +7. Update the invoice with the new charged amount and clear the pending flag. =head1 CLASS METHODS @@ -48,15 +48,15 @@ indicate that the package is being billed on cancellation. sub new { my $class = shift; my %opt = @_; + my $conf = FS::Conf->new; if ($class eq 'FS::TaxEngine') { - my $conf = FS::Conf->new; my $subclass = $conf->config('enable_taxproducts') || 'internal'; $class .= "::$subclass"; local $@; eval "use $class"; die "couldn't load $class: $@\n" if $@; } - my $self = { items => [], taxes => {}, %opt }; + my $self = { items => [], taxes => {}, conf => $conf, %opt }; bless $self, $class; } @@ -84,33 +84,36 @@ Returns a hashref of metadata about this tax method, including: Adds the CUST_BILL_PKG object as a taxable sale on this invoice. -=item calculate_taxes CUST_BILL +=item calculate_taxes INVOICE Calculates the taxes on the taxable sales and returns a list of -L objects to add to the invoice. There is a base -implementation of this, which calls the C method to calculate -each individual tax. +L objects to add to the invoice. The base implementation +is to call L to produce a list of "raw" tax line items, +then L to combine those with the same itemdesc. =cut sub calculate_taxes { my $self = shift; - my $conf = FS::Conf->new; - my $cust_bill = shift; - my @tax_line_items; - # keys are tax names (as printed on invoices / itemdesc ) - # values are arrayrefs of taxlines - my %taxname; + my @raw_taxlines = $self->make_taxlines($cust_bill); - # keys are taxnums - # values are (cumulative) amounts - my %tax_amount; + my @real_taxlines = $self->consolidate_taxlines(@raw_taxlines); - # keys are taxnums - # values are arrayrefs of cust_tax_exempt_pkg objects - my %tax_exemption; + if ( $cust_bill and $cust_bill->get('invnum') ) { + $_->set('invnum', $cust_bill->get('invnum')) foreach @real_taxlines; + } + return \@real_taxlines; +} + +sub make_taxlines { + my $self = shift; + my $conf = $self->{conf}; + + my $cust_bill = shift; + + my @taxlines; # For each distinct tax rate definition, calculate the tax and exemptions. foreach my $taxnum ( keys %{ $self->{taxes} } ) { @@ -127,10 +130,35 @@ sub calculate_taxes { # with their link records die $taxline unless ref($taxline); - push @{ $taxname{ $taxline->itemdesc } }, $taxline; + push @taxlines, $taxline; } #foreach $taxnum + return @taxlines; +} + +sub consolidate_taxlines { + + my $self = shift; + my $conf = $self->{conf}; + + my @raw_taxlines = @_; + my @tax_line_items; + + # keys are tax names (as printed on invoices / itemdesc ) + # values are arrayrefs of taxlines + my %taxname; + # collate these by itemdesc + foreach my $taxline (@raw_taxlines) { + my $taxname = $taxline->itemdesc; + $taxname{$taxname} ||= []; + push @{ $taxname{$taxname} }, $taxline; + } + + # keys are taxnums + # values are (cumulative) amounts + my %tax_amount; + my $link_table = $self->info->{link_table}; # For each distinct tax name (the values set as $taxline->itemdesc), # create a consolidated tax item with the total amount and all the links @@ -138,7 +166,6 @@ sub calculate_taxes { foreach my $taxname ( keys %taxname ) { my @tax_links; my $tax_cust_bill_pkg = FS::cust_bill_pkg->new({ - 'invnum' => $cust_bill->invnum, 'pkgnum' => 0, 'recur' => 0, 'sdate' => '', @@ -185,7 +212,7 @@ sub calculate_taxes { push @tax_line_items, $tax_cust_bill_pkg; } - \@tax_line_items; + @tax_line_items; } =head1 CLASS METHODS -- cgit v1.1