summaryrefslogtreecommitdiff
path: root/LedgerSMB/Tax.pm
diff options
context:
space:
mode:
Diffstat (limited to 'LedgerSMB/Tax.pm')
-rwxr-xr-xLedgerSMB/Tax.pm100
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;