diff options
Diffstat (limited to 'LedgerSMB/Tax.pm')
-rwxr-xr-x | LedgerSMB/Tax.pm | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/LedgerSMB/Tax.pm b/LedgerSMB/Tax.pm new file mode 100755 index 00000000..4c7bd121 --- /dev/null +++ b/LedgerSMB/Tax.pm @@ -0,0 +1,100 @@ +#===================================================================== +# +# Tax support module for LedgerSMB +# LedgerSMB::Tax +# Default simple tax application +# +# LedgerSMB +# Small Medium Business Accounting software +# http://www.ledgersmb.org/ +# +# +# Copyright (C) 2006 +# This work contains copyrighted information from a number of sources all used +# with permission. It is released under the GNU General Public License +# Version 2 or, at your option, any later version. See COPYRIGHT file for +# details. +# +# +#====================================================================== +# This package contains tax related functions: +# +# apply_taxes - applies taxes to the given subtotal +# extract_taxes - extracts taxes from the given total +# initialize_taxes - loads taxes from the database +# calculate_taxes - calculates taxes +# +#==================================================================== +package Tax; + +use Math::BigFloat; + +sub init_taxes { + my ($form, $taxaccounts) = @_; + my $dbh = $form->{dbh}; + @taxes = (); + my @accounts = split / /, $taxaccounts; + my $query = qq|SELECT t.taxnumber, c.description, + t.rate, t.chart_id, t.pass, m.taxmodulename + FROM tax t INNER JOIN chart c ON (t.chart_id = c.id) + INNER JOIN taxmodule m ON (t.taxmodule_id = m.taxmodule_id) + WHERE c.accno = ?|; + my $sth = $dbh->prepare($query); + foreach $taxaccount (@accounts) { + $sth->execute(int($taxaccount)) || $form->dberror($query); + my $ref = $sth->fetchrow_hashref; + + my $module = $ref->{'taxmodulename'}; + require "LedgerSMB/Taxes/${module}.pm"; + $module =~ s/\//::/g; + my $tax = (eval 'Taxes::'.$module)->new(); + + $tax->pass($ref->{'pass'}); + $tax->account($taxaccount); + $tax->rate(Math::BigFloat->new($ref->{'rate'})); + $tax->taxnumber($ref->{'taxnumber'}); + $tax->chart($ref->{'chart'}); + $tax->description($ref->{'description'}); + $tax->value(Math::BigFloat->bzero()); + + push @taxes, $tax; + $sth->finish; + } + return @taxes; +} + +sub calculate_taxes { + my ($taxes, $form, $subtotal, $extract) = @_; + my $total = Math::BigFloat->bzero(); + my %passes; + foreach my $tax (@taxes) { + push @{$passes{$tax->pass}}, $tax; + } + my @passkeys = sort keys %passes; + @passkeys = reverse @passkeys if $extract; + foreach my $pass (@passkeys) { + my $passrate = Math::BigFloat->bzero(); + my $passtotal = Math::BigFloat->bzero(); + foreach my $tax (@{$passes{$pass}}) { + $passrate += $tax->rate; + } + foreach my $tax (@{$passes{$pass}}) { + $passtotal += $tax->apply_tax($form, $subtotal + $total) if not $extract; + $passtotal += $tax->extract_tax($form, $subtotal - $total, $passrate) if $extract; + } + $total += $passtotal; + } + return $total; +} + +sub apply_taxes { + my ($taxes, $form, $subtotal) = @_; + return $subtotal + calculate_taxes($taxes, $form, $subtotal, 0); +} + +sub extract_taxes { + my ($taxes, $form, $subtotal) = @_; + return $subtotal - calculate_taxes($taxes, $form, $subtotal, 1); +} + +1; |