summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xLedgerSMB/AM.pm34
-rwxr-xr-xLedgerSMB/Form.pm2
-rwxr-xr-xLedgerSMB/IR.pm42
-rwxr-xr-xLedgerSMB/IS.pm80
-rwxr-xr-xLedgerSMB/OE.pm159
-rwxr-xr-xLedgerSMB/Tax.pm100
-rwxr-xr-xLedgerSMB/Taxes/Simple.pm64
-rwxr-xr-xbin/mozilla/aa.pl120
-rwxr-xr-xbin/mozilla/am.pl20
-rwxr-xr-xbin/mozilla/ic.pl4
-rwxr-xr-xbin/mozilla/io.pl9
-rwxr-xr-xbin/mozilla/ir.pl20
-rwxr-xr-xbin/mozilla/is.pl30
-rwxr-xr-xbin/mozilla/oe.pl22
-rwxr-xr-xbin/mozilla/pos.pl30
-rwxr-xr-xsql/Canada-French_General-chart.sql2
-rwxr-xr-xsql/Pg-tables.sql12
-rw-r--r--sql/Pg-upgrade-2.6.18-2.6.19.sql20
18 files changed, 447 insertions, 323 deletions
diff --git a/LedgerSMB/AM.pm b/LedgerSMB/AM.pm
index c1576aed..82b58534 100755
--- a/LedgerSMB/AM.pm
+++ b/LedgerSMB/AM.pm
@@ -35,7 +35,7 @@
#======================================================================
package AM;
-
+use LedgerSMB::Tax;
sub get_account {
@@ -1479,15 +1479,18 @@ sub defaultaccounts {
sub taxes {
my ($self, $myconfig, $form) = @_;
+ my $taxaccounts = '';
# connect to database
my $dbh = $form->{dbh};
my $query = qq|
- SELECT c.id, c.accno, c.description,
- t.rate * 100 AS rate, t.taxnumber, t.validto
+ SELECT c.id, c.accno, c.description,
+ t.rate * 100 AS rate, t.taxnumber, t.validto,
+ t.pass, m.taxmodulename
FROM chart c
JOIN tax t ON (c.id = t.chart_id)
+ JOIN taxmodule m ON (t.taxmodule_id = m.taxmodule_id)
ORDER BY 3, 6|;
my $sth = $dbh->prepare($query);
@@ -1495,6 +1498,21 @@ sub taxes {
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
push @{ $form->{taxrates} }, $ref;
+ $taxaccounts .= " " . $ref{accno};
+ }
+
+ $sth->finish;
+
+ $query = qq|
+ SELECT taxmodule_id, taxmodulename FROM taxmodule
+ ORDER BY 2|;
+
+ $sth = $dbh->prepare($query);
+ $sth->execute || $form->dberror($query);
+
+ while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
+ $form->{"taxmodule_".$ref->{taxmodule_id}} =
+ $ref->{taxmodulename};
}
$sth->finish;
@@ -1516,16 +1534,20 @@ sub save_taxes {
$query = qq|
- INSERT INTO tax (chart_id, rate, taxnumber, validto)
- VALUES (?, ?, ?, ?)|;
+ INSERT INTO tax (chart_id, rate, taxnumber, validto,
+ pass, taxmodule_id)
+ VALUES (?, ?, ?, ?, ?, ?)|;
my $sth = $dbh->prepare($query);
foreach my $item (split / /, $form->{taxaccounts}) {
my ($chart_id, $i) = split /_/, $item;
my $rate = $form->parse_amount(
$myconfig, $form->{"taxrate_$i"}) / 100;
+ my $validto = $form->{"validto_$i"};
+ $validto = undef if not $validto;
my @queryargs = ($chart_id, $rate, $form->{"taxnumber_$i"},
- $form->{"validto_$i"});
+ $validto, $form->{"pass_$i"},
+ $form->{"taxmodule_id_$i"});
$sth->execute(@queryargs) || $form->dberror($query);
}
diff --git a/LedgerSMB/Form.pm b/LedgerSMB/Form.pm
index cd30803b..e5fa4f61 100755
--- a/LedgerSMB/Form.pm
+++ b/LedgerSMB/Form.pm
@@ -1579,7 +1579,7 @@ sub check_exchangerate {
my $sth = $self->{dbh}->prepare($query);
$sth->execute($currenct, $transdate);
- my ($exchangerate) = $sth->fetchrow_array($query);
+ my ($exchangerate) = $sth->fetchrow_array;
$sth->finish;
$self->{dbh}->commit;
diff --git a/LedgerSMB/IR.pm b/LedgerSMB/IR.pm
index 92e2c964..9f2da830 100755
--- a/LedgerSMB/IR.pm
+++ b/LedgerSMB/IR.pm
@@ -32,6 +32,7 @@
#======================================================================
package IR;
+use LedgerSMB::Tax;
use LedgerSMB::PriceMatrix;
sub post_invoice {
@@ -172,33 +173,24 @@ sub post_invoice {
my $linetotal = $form->round_amount($amount, 2);
$fxdiff += $amount - $linetotal;
- @taxaccounts = split / /, $form->{"taxaccounts_$i"};
+ @taxaccounts = Tax::init_taxes($form, $form->{"taxaccounts_$i"});
- $ml = 1;
- $tax = 0;
- $fxtax = 0;
+ $tax = Math::BigFloat->bzero();
+ $fxtax = Math::BigFloat->bzero();
- for (0 .. 1) {
- $taxrate = 0;
-
- # add tax rates
- for (@taxaccounts) {
- $taxrate += $form->{"${_}_rate"} if ($form->{"${_}_rate"} * $ml) > 0;
- }
-
- if ($form->{taxincluded}) {
- $tax += $amount = $linetotal * ($taxrate / (1 + ($taxrate * $ml)));
- $form->{"sellprice_$i"} -= $amount / $form->{"qty_$i"};
- } else {
- $tax += $amount = $linetotal * $taxrate;
- $fxtax += $fxlinetotal * $taxrate;
- }
-
- for (@taxaccounts) {
- $form->{acc_trans}{$form->{id}}{$_}{amount} += $amount * $form->{"${_}_rate"} / $taxrate if ($form->{"${_}_rate"} * $ml) > 0;
- }
-
- $ml = -1;
+ if ($form->{taxincluded}) {
+ $tax += $amount = Tax::calculate_taxes(\@taxaccounts, $form,
+ $linetotal, 1);
+ $form->{"sellprice_$i"} -= $amount / $form{"qty_$i"};
+ } else {
+ $tax += $amount = Tax::calculate_taxes(\@taxaccounts, $form,
+ $linetotal, 0);
+ $fxtax += Tax::calculate_taxes(\@taxaccounts, $form,
+ $fxlinetotal, 0);
+ }
+
+ for (@taxaccounts) {
+ $form->{acc_trans}{$form->{id}}{$_->account}{amount} += $_->value;
}
$grossamount = $form->round_amount($linetotal, 2);
diff --git a/LedgerSMB/IS.pm b/LedgerSMB/IS.pm
index eda3a984..0b38b3a8 100755
--- a/LedgerSMB/IS.pm
+++ b/LedgerSMB/IS.pm
@@ -32,6 +32,7 @@
#======================================================================
package IS;
+use LedgerSMB::Tax;
use LedgerSMB::PriceMatrix;
sub invoice_details {
@@ -263,44 +264,30 @@ sub invoice_details {
$form->{"linetotal_$i"} = $form->format_amount($myconfig, $linetotal, 2);
push(@{ $form->{linetotal} }, $form->{"linetotal_$i"});
- @taxaccounts = split / /, $form->{"taxaccounts_$i"};
+ @taxaccounts = Tax::init_taxes($form, $form->{"taxaccounts_$i"});
my $ml = 1;
my @taxrates = ();
$tax = 0;
- for (0 .. 1) {
- $taxrate = 0;
-
- for (@taxaccounts) { $taxrate += $form->{"${_}_rate"} if ($form->{"${_}_rate"} * $ml) > 0 }
-
- $taxrate *= $ml;
- $taxamount = $linetotal * $taxrate / (1 + $taxrate);
- $taxbase = ($linetotal - $taxamount);
-
- foreach $item (@taxaccounts) {
- if (($form->{"${item}_rate"} * $ml) > 0) {
-
- push @taxrates, $form->{"${item}_rate"} * 100;
-
- if ($form->{taxincluded}) {
- $taxaccounts{$item} += $linetotal * $form->{"${item}_rate"} / (1 + $taxrate);
- $taxbase{$item} += $taxbase;
- } else {
- $taxbase{$item} += $linetotal;
- $taxaccounts{$item} += $linetotal * $form->{"${item}_rate"};
- }
- }
- }
+ if ($form->{taxincluded}) {
+ $taxamount = Tax::calculate_taxes(\@taxaccounts, $form, $linetotal, 1);
+ $taxbase = ($linetotal - $taxamount);
+ $tax += Tax::extract_taxes(\@taxaccounts, $form, $linetotal);
+ } else {
+ $taxamount = Tax::calculate_taxes(\@taxaccounts, $form, $linetotal, 0);
+ $tax += Tax::apply_taxes(\@taxaccounts, $form, $linetotal);
+ }
+ foreach $item (@taxaccounts) {
+ push @taxrates, 100 * $item->rate;
+ $taxaccounts{$item->account} += $item->value;
if ($form->{taxincluded}) {
- $tax += $linetotal * ($taxrate / (1 + ($taxrate * $ml)));
+ $taxbase{$item->account} += $taxbase;
} else {
- $tax += $linetotal * $taxrate;
+ $taxbase{$item->account} += $linetotal;
}
-
- $ml *= -1;
}
push(@{ $form->{lineitems} }, { amount => $linetotal, tax => $form->round_amount($tax, 2) });
@@ -699,31 +686,20 @@ sub post_invoice {
my $linetotal = $form->round_amount($amount, 2);
$fxdiff += $amount - $linetotal;
- @taxaccounts = split / /, $form->{"taxaccounts_$i"};
+ @taxaccounts = Tax::init_taxes($form, $form->{"taxaccounts_$i"});
$ml = 1;
$tax = 0;
$fxtax = 0;
- for (0 .. 1) {
- $taxrate = 0;
-
- # add tax rates
- for (@taxaccounts) { $taxrate += $form->{"${_}_rate"} if ($form->{"${_}_rate"} * $ml) > 0 }
-
- if ($form->{taxincluded}) {
- $tax += $amount = $linetotal * ($taxrate / (1 + ($taxrate * $ml)));
- $form->{"sellprice_$i"} -= $amount / $form->{"qty_$i"};
- $fxtax += $fxlinetotal * ($taxrate / (1 + ($taxrate * $ml)));
- } else {
- $tax += $amount = $linetotal * $taxrate;
- $fxtax += $fxlinetotal * $taxrate;
- }
-
- for (@taxaccounts) {
- $form->{acc_trans}{$form->{id}}{$_}{amount} += $amount * $form->{"${_}_rate"} / $taxrate if ($form->{"${_}_rate"} * $ml) > 0;
- }
-
- $ml = -1;
+ if ($form->{taxincluded}) {
+ $tax += $amount = Tax::calculate_taxes(\@taxaccounts, $form,
+ $linetotal, 1);
+ $form->{"sellprice_$i"} -= $amount / $form->{"qty_$i"};
+ $fxtax += Tax::calculate_taxes(\@taxaccounts, $form, $linetotal, 1);
+ } else {
+ $tax += $amount = Tax::calculate_taxes(\@taxaccounts, $form,
+ $linetotal, 0);
+ $fxtax += Tax::calculate_taxes(\@taxaccounts, $form, $linetotal, 0);
}
$grossamount = $form->round_amount($linetotal, 2);
@@ -832,7 +808,11 @@ sub post_invoice {
$invnetamount = $amount;
$amount = 0;
- for (split / /, $form->{taxaccounts}) { $amount += $form->{acc_trans}{$form->{id}}{$_}{amount} = $form->round_amount($form->{acc_trans}{$form->{id}}{$_}{amount}, 2) }
+ for (split / /, $form->{taxaccounts}) {
+ $amount +=
+ $form->{acc_trans}{$form->{id}}{$_}{amount} =
+ $form->round_amount($form->{acc_trans}{$form->{id}}{$_}{amount}, 2);
+ }
$invamount = $invnetamount + $amount;
$diff = 0;
diff --git a/LedgerSMB/OE.pm b/LedgerSMB/OE.pm
index 9ebbad19..0d9ab99d 100755
--- a/LedgerSMB/OE.pm
+++ b/LedgerSMB/OE.pm
@@ -33,7 +33,7 @@
#======================================================================
package OE;
-
+use LedgerSMB::Tax;
sub transactions {
my ($self, $myconfig, $form) = @_;
@@ -419,67 +419,52 @@ sub save {
$form->{"sellprice_$i"} * $form->{"qty_$i"}, 2
);
- @taxaccounts = split / /, $form->{"taxaccounts_$i"};
- $taxrate = 0;
- $taxdiff = 0;
-
- for (@taxaccounts) { $taxrate += $form->{"${_}_rate"} }
-
+ @taxaccounts = Tax::init_taxes($form,
+ $form->{"taxaccounts_$i"});
if ($form->{taxincluded}) {
- $taxamount = $linetotal * $taxrate
- / (1 + $taxrate);
- $taxbase = $linetotal - $taxamount;
- # we are not keeping a natural price,
- # do not round
- $form->{"sellprice_$i"} =
- $form->{"sellprice_$i"}
- * (1 / (1 + $taxrate));
+ $taxamount = Tax::calculate_taxes(\@taxaccounts,
+ $form, $linetotal, 1);
+ $form->{"sellprice_$i"} = Tax::extract_taxes(\@taxaccounts,
+ $form, $form->{"sellprice_$i"});
+ $taxbase = Tax::extract_taxes(\@taxaccounts,
+ $form, $linetotal);
} else {
- $taxamount = $linetotal * $taxrate;
+ $taxamount = Tax::apply_taxes(\@taxaccounts,
+ $form, $linetotal);
$taxbase = $linetotal;
}
-
- if (@taxaccounts && $form->round_amount($taxamount, 2)
- == 0) {
- if ($form->{taxincluded}) {
+
+ if (@taxaccounts && $form->round_amount($taxamount, 2)
+ == 0) {
+ if ($form->{taxincluded}) {
foreach $item (@taxaccounts) {
$taxamount =
$form->round_amount(
-
- $linetotal
- * $form->{"${item}_rate"}
- / (1 + abs(
- $form->{"${item}_rate"}
- )), 2
- );
-
- $taxaccounts{$item} +=
+ $item->value, 2);
+ $taxaccounts{$item->account} +=
$taxamount;
- $taxdiff += $taxamount;
-
- $taxbase{$item} += $taxbase;
+ $taxdiff += $taxamount;
+ $taxbase{$item->account} +=
+ $taxbase;
}
- $taxaccounts{$taxaccounts[0]}
+ $taxaccounts{$taxaccounts[0]->account}
+= $taxdiff;
- } else {
+ } else {
foreach $item (@taxaccounts) {
- $taxaccounts{$item} +=
- $linetotal *
- $form->{"${item}_rate"};
- $taxbase{$item} += $taxbase;
+ $taxaccounts{$item->account} +=
+ $item->value;
+ $taxbase{$item->account} +=
+ $taxbase;
}
}
} else {
foreach $item (@taxaccounts) {
- $taxaccounts{$item} +=
- $taxamount *
- $form->{"${item}_rate"} /
- $taxrate;
- $taxbase{$item} += $taxbase;
+ $taxaccounts{$item->account} +=
+ $item->value;
+ $taxbase{$item->account} += $taxbase;
}
}
-
$netamount += $form->{"sellprice_$i"}
* $form->{"qty_$i"};
@@ -939,7 +924,7 @@ sub retrieve {
$sth->finish;
# get recurring transaction
- $form->get_recurring($dbh);
+ $form->get_recurring;
@queries = $form->run_custom_queries('oe', 'SELECT');
$form->{dbh}->commit;
@@ -1328,66 +1313,39 @@ sub order_details {
$myconfig, $linetotal, 2);
push(@{ $form->{linetotal} }, $form->{"linetotal_$i"});
- @taxaccounts = split / /, $form->{"taxaccounts_$i"};
+ @taxaccounts = Tax::init_taxes($form,
+ $form->{"taxaccounts_$i"});
my $ml = 1;
my @taxrates = ();
$tax = 0;
- for (0 .. 1) {
- $taxrate = 0;
-
- for (@taxaccounts) {
- $taxrate += $form->{"${_}_rate"}
- if ($form->{"${_}_rate"} * $ml)
- > 0;
- }
-
- $taxrate *= $ml;
- $taxamount = $linetotal * $taxrate
- / (1 + $taxrate);
- $taxbase = ($linetotal - $taxamount);
-
- foreach $item (@taxaccounts) {
- if (($form->{"${item}_rate"} * $ml)
- > 0) {
-
- push @taxrates,
- $form->{"${item}_rate"}
- * 100;
-
- if ($form->{taxincluded}) {
-
- $taxaccounts{$item}
- += $linetotal
- * $form->{"${item}_rate"}
- /
- (1 + $taxrate);
-
- $taxbase{$item}
- += $taxbase;
- } else {
- $taxbase{$item}
- += $linetotal;
-
- $taxaccounts{$item}
- += $linetotal
- * $form->{"${item}_rate"};
-
- }
- }
- }
-
+ $taxamount = Tax::calculate_taxes(\@taxaccounts,
+ $form, $linetotal, 1);
+ $taxbase = Tax::extract_taxes(\@taxaccounts,
+ $form, $linetotal);
+ foreach $item (@taxaccounts) {
+ push @taxrates, Math::BigFloat->new(100) *
+ $item->rate;
if ($form->{taxincluded}) {
- $tax += $linetotal
- * ($taxrate
- / (1 + ($taxrate * $ml)));
+ $taxaccounts{$item->account} +=
+ $item->value;
+ $taxbase{$item->account} += $taxbase;
} else {
- $tax += $linetotal * $taxrate;
+ Tax::apply_taxes(\@taxaccounts, $form,
+ $linetotal);
+ $taxbase{$item->account} += $linetotal;
+ $taxaccounts{$item->account} +=
+ $item->value;
}
-
- $ml *= -1;
+ }
+ if ($form->{taxincluded}) {
+ $tax += Tax::calculate_taxes(\@taxaccounts,
+ $form, $linetotal, 1);
+ } else {
+ $tax += Tax::calculate_taxes(\@taxaccounts,
+ $form, $linetotal, 0);
}
push(@{ $form->{lineitems} },
@@ -2422,19 +2380,24 @@ sub generate_orders {
$sth->execute($parts_id) || $form->dberror($query);
my $rate = 0;
+ my $taxes = '';
while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
$description = $ref->{description};
$unit = $ref->{unit};
$rate += $tax{$ref->{accno}};
+ $taxes .= "$ref->{accno} ";
}
- $sth->finish;
+ $sth->finish;
+ chop $taxes;
+ my @taxaccounts = Tax::init_taxes($form, $taxes);
$netamount += $linetotal;
if ($taxincluded) {
$amount += $linetotal;
} else {
$amount += $form->round_amount(
- $linetotal * (1 + $rate), 2);
+ Tax::apply_taxes(\@taxaccounts, $form,
+ $linetotal), 2);
}
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;
diff --git a/LedgerSMB/Taxes/Simple.pm b/LedgerSMB/Taxes/Simple.pm
new file mode 100755
index 00000000..57777be4
--- /dev/null
+++ b/LedgerSMB/Taxes/Simple.pm
@@ -0,0 +1,64 @@
+#=====================================================================
+#
+# Simple Tax support module for LedgerSMB
+# Taxes::Simple
+# 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:
+#
+# calculate_tax - calculates tax on subtotal
+# apply_tax - sets $value to the tax value for the subtotal
+# extract_tax - sets $value to the tax value on a tax-included subtotal
+#
+#====================================================================
+package Taxes::Simple;
+
+use Class::Struct;
+use Math::BigFloat;
+
+struct Taxes::Simple => {
+ taxnumber => '$',
+ description => '$',
+ rate => 'Math::BigFloat',
+ chart => '$',
+ account => '$',
+ value => 'Math::BigFloat',
+ pass => '$'
+};
+
+sub calculate_tax {
+ my ($self, $form, $subtotal, $extract, $passrate) = @_;
+ my $rate = $self->rate;
+ my $tax = $subtotal * $rate / (Math::BigFloat->bone() + $passrate);
+ $tax = $subtotal * $rate if not $extract;
+ return $tax;
+}
+
+sub apply_tax {
+ my ($self, $form, $subtotal) = @_;
+ my $tax = $self->calculate_tax($form, $subtotal, 0);
+ $self->value($tax);
+ return $tax;
+}
+
+sub extract_tax {
+ my ($self, $form, $subtotal, $passrate) = @_;
+ my $tax = $self->calculate_tax($form, $subtotal, 1, $passrate);
+ $self->value($tax);
+ return $tax;
+}
+
+1;
diff --git a/bin/mozilla/aa.pl b/bin/mozilla/aa.pl
index 4f6665dc..6e0b09ac 100755
--- a/bin/mozilla/aa.pl
+++ b/bin/mozilla/aa.pl
@@ -44,6 +44,8 @@
#
#======================================================================
+use LedgerSMB::Tax;
+
# any custom scripts for this one
if (-f "$form->{path}/custom_aa.pl") {
eval { require "$form->{path}/custom_aa.pl"; };
@@ -257,7 +259,8 @@ sub create_links {
if ($form->{taxincluded}) {
$diff = 0;
- # add tax to individual amounts
+ # add tax to individual amounts
+ # XXX needs alteration for conditional taxes
for $i (1 .. $form->{rowcount}) {
if ($netamount) {
$amount = $form->{"amount_$i"} * (1 + $tax / $netamount);
@@ -272,53 +275,26 @@ sub create_links {
# taxincluded is terrible to calculate
# this works only if all taxes are checked
- @taxaccounts = split / /, $form->{taxaccounts};
+ @taxaccounts = Tax::init_taxes($form, $form->{taxaccounts});
if ($form->{id}) {
if ($form->{taxincluded}) {
- $ml = 1;
+ $amount = Tax::calculate_taxes(\@taxaccounts, $form,
+ $form->{invtotal}, 1);
+ $tax = $form->round_amount($amount, 2);
- for (0 .. 1) {
- $taxrate = 0;
- $diff = 0;
-
- for (@taxaccounts) { $taxrate += $form->{"${_}_rate"} if ($form->{"${_}_rate"} * $ml) > 0 }
- $taxrate *= $ml;
-
- foreach $item (@taxaccounts) {
-
- if (($form->{"${item}_rate"} * $ml) > 0) {
- if ($taxrate) {
- $amount = $form->{invtotal} * $form->{"${item}_rate"} / (1 + $taxrate);
- $tax = $form->round_amount($amount, 2);
- $tax{$item} = $form->round_amount($amount - $diff, 2);
- $diff = $tax{$item} - ($amount - $diff);
-
- if ($tax) {
- if ($form->{"tax_$item"} == $tax{$item}) {
- $form->{"calctax_$item"} = 1;
- }
- }
- }
- }
- }
- $ml *= -1;
+ } else {
+ $tax = $form->round_amount(Tax::calculate_taxes(\@taxaccounts,
+ $form, $netamount, 0));
}
-
- } else {
- for (@taxaccounts) {
- $tax = $form->round_amount($netamount * $form->{"${_}_rate"}, 2);
- if ($tax) {
- if ($form->{"tax_$_"} == $tax) {
- $form->{"calctax_$_"} = 1;
- }
+ foreach $item (@taxaccounts) {
+ $tax{$item->account} = $form->round_amount($item->value, 2);
+ $form->{"calctax_".$item->account} = 1 if $item->value and (
+ $tax{$item->account} == $form->{"tax_".$item->account});
}
- }
- }
-
} else {
- for (@taxaccounts) { $form->{"calctax_$_"} = 1 }
+ for (@taxaccounts) { $form->{"calctax_".$_->account} = 1 }
}
@@ -830,61 +806,21 @@ sub update {
for (@taxaccounts) { $form->{"tax_$_"} = $form->parse_amount(\%myconfig, $form->{"tax_$_"}) }
+ @taxaccounts = Tax::init_taxes($form, $form->{taxaccounts});
if ($form->{taxincluded}) {
-
- $ml = 1;
-
- for (0 .. 1) {
- $taxrate = 0;
- $diff = 0;
-
- for (@taxaccounts) {
- if (($form->{"${_}_rate"} * $ml) > 0) {
- if ($form->{"calctax_$_"}) {
- $taxrate += $form->{"${_}_rate"};
- } else {
- if ($form->{checktax}) {
- if ($form->{"tax_$_"}) {
- $taxrate += $form->{"${_}_rate"};
- }
- }
- }
- }
- }
-
- $taxrate *= $ml;
-
- foreach $item (@taxaccounts) {
- if (($form->{"${item}_rate"} * $ml) > 0) {
-
- if ($taxrate) {
- $a = $form->{invtotal} * $form->{"${item}_rate"} / (1 + $taxrate);
- $b = $form->round_amount($a, 2);
- $tax = $form->round_amount($a - $diff, 2);
- $diff = $b - ($a - $diff);
- }
- $form->{"tax_$item"} = $tax if $form->{"calctax_$item"};
-
- $form->{"select$form->{ARAP}_tax_$item"} = qq|<option>$item--$form->{"${item}_description"}|;
- $totaltax += $form->{"tax_$item"};
- }
- }
- $ml *= -1;
- }
- $totaltax += $form->round_amount($diff, 2);
-
- $form->{checktax} = 1;
-
+ $totaltax = Tax::calculate_taxes(\@taxaccounts, $form,
+ $form->{invtotal}, 1);
} else {
- foreach $item (@taxaccounts) {
- $form->{"calctax_$item"} = 1 if $form->{calctax};
-
- if ($form->{"calctax_$item"}) {
- $form->{"tax_$item"} = $form->round_amount($form->{invtotal} * $form->{"${item}_rate"}, 2);
- }
- $form->{"select$form->{ARAP}_tax_$item"} = qq|<option>$item--$form->{"${item}_description"}|;
- $totaltax += $form->{"tax_$item"};
+ $totaltax = Tax::calculate_taxes(\@taxaccounts, $form,
+ $form->{invtotal}, 0);
+ }
+ foreach $item (@taxaccounts) {
+ $taccno = $item->account;
+ if ($form->{calctax}) {
+ $form->{"calctax_$taccno"} = 1;
+ $form->{"tax_$taccno"} = $form->round_amount($item->value, 2);
}
+ $form->{"select$form->{ARAP}_tax_$taccno"} = qq|<option>$taccno--$form->{"${taccno}_description"}|;
}
$form->{invtotal} = ($form->{taxincluded}) ? $form->{invtotal} : $form->{invtotal} + $totaltax;
diff --git a/bin/mozilla/am.pl b/bin/mozilla/am.pl
index 9be1c020..666b5522 100755
--- a/bin/mozilla/am.pl
+++ b/bin/mozilla/am.pl
@@ -1868,7 +1868,9 @@ sub taxes {
$form->{"taxrate_$i"} = $form->format_amount(\%myconfig, $ref->{rate});
$form->{"taxdescription_$i"} = $ref->{description};
- for (qw(taxnumber validto)) { $form->{"${_}_$i"} = $ref->{$_} }
+ for (qw(taxnumber validto pass taxmodulename)) {
+ $form->{"${_}_$i"} = $ref->{$_};
+ }
$form->{taxaccounts} .= "$ref->{id}_$i ";
}
chop $form->{taxaccounts};
@@ -1901,6 +1903,8 @@ sub display_taxes {
<th>|.$locale->text('Rate').qq| (%)</th>
<th>|.$locale->text('Number').qq|</th>
<th>|.$locale->text('Valid To').qq|</th>
+ <th>|.$locale->text('Order').qq|</th>
+ <th>|.$locale->text('Tax Rules').qq|</th>
</tr>
|;
@@ -1926,8 +1930,18 @@ sub display_taxes {
<td><input name="taxrate_$i" size=6 value=$form->{"taxrate_$i"}></td>
<td><input name="taxnumber_$i" value="$form->{"taxnumber_$i"}"></td>
<td><input name="validto_$i" size=11 value="$form->{"validto_$i"}" title="$myconfig{dateformat}"></td>
- </tr>
-|;
+ <td><input name="pass_$i" size=6 value="$form->{"pass_$i"}"></td>
+ <td><select name="taxmodule_id_$i" size=1>|;
+ foreach my $taxmodule (sort keys %$form) {
+ next if ($taxmodule !~ /^taxmodule_/);
+ my $modulenum = $taxmodule;
+ $modulenum =~ s/^taxmodule_//;
+ print '<option label="'.$form->{$taxmodule}.'" value="'.$modulenum . '"';
+ print " SELECTED " if $form->{$taxmodule} eq $form->{"taxmodulename_$i"};
+ print " />\n";
+ }
+ print qq|</select></td>
+ </tr> |;
$sametax = $form->{"taxdescription_$i"};
}
diff --git a/bin/mozilla/ic.pl b/bin/mozilla/ic.pl
index 99eb7f5c..16e67d24 100755
--- a/bin/mozilla/ic.pl
+++ b/bin/mozilla/ic.pl
@@ -42,6 +42,7 @@
use LedgerSMB::IC;
+use LedgerSMB::Tax;
require "$form->{path}/io.pl";
@@ -2981,7 +2982,8 @@ sub save {
$amount = $form->{"sellprice_$i"} * (1 - $form->{"discount_$i"} / 100) * $form->{"qty_$i"};
for (split / /, $form->{"taxaccounts_$i"}) { $form->{"${_}_base"} += $amount }
if (!$form->{taxincluded}) {
- for (split / /, $form->{"taxaccounts_$i"}) { $amount += ($form->{"${_}_base"} * $form->{"${_}_rate"}) }
+ my @taxlist= Tax::init_taxes($form, $form->{"taxaccounts_$i"});
+ $amount += Tax::calculate_taxes(\@taxlist, $form, $amount, 0);
}
$ml = 1;
diff --git a/bin/mozilla/io.pl b/bin/mozilla/io.pl
index d81fa34c..b2ea21b2 100755
--- a/bin/mozilla/io.pl
+++ b/bin/mozilla/io.pl
@@ -38,6 +38,8 @@
#
#######################################################################
+use LedgerSMB::Tax;
+
# any custom scripts for this one
if (-f "$form->{path}/custom_io.pl") {
eval { require "$form->{path}/custom_io.pl"; };
@@ -504,7 +506,8 @@ sub item_selected {
$amount = $form->{"sellprice_$i"} * (1 - $form->{"discount_$i"} / 100) * $form->{"qty_$i"};
for (split / /, $form->{"taxaccounts_$i"}) { $form->{"${_}_base"} += $amount }
if (!$form->{taxincluded}) {
- for (split / /, $form->{"taxaccounts_$i"}) { $amount += ($form->{"${_}_base"} * $form->{"${_}_rate"}) }
+ my @taxlist= Tax::init_taxes($form, $form->{"taxaccounts_$i"});
+ $amount += Tax::calculate_taxes(\@taxlist, $form, $amount, 0);
}
$form->{creditremaining} -= $amount;
@@ -840,7 +843,9 @@ sub invoicetotal {
}
if (!$form->{taxincluded}) {
- for (split / /, $form->{taxaccounts}) { $form->{oldinvtotal} += ($form->{"${_}_base"} * $form->{"${_}_rate"}) }
+ my @taxlist= Tax::init_taxes($form, $form->{taxaccounts});
+ $form->{oldinvtotal} += Tax::calculate_taxes(\@taxlist, $form,
+ $amount, 0);
}
$form->{oldtotalpaid} = 0;
diff --git a/bin/mozilla/ir.pl b/bin/mozilla/ir.pl
index 35f9975b..be87e9eb 100755
--- a/bin/mozilla/ir.pl
+++ b/bin/mozilla/ir.pl
@@ -41,6 +41,7 @@
use LedgerSMB::IR;
use LedgerSMB::PE;
+use LedgerSMB::Tax;
require "$form->{path}/io.pl";
require "$form->{path}/arap.pl";
@@ -422,11 +423,14 @@ sub form_footer {
}
if (!$form->{taxincluded}) {
-
- foreach $item (split / /, $form->{taxaccounts}) {
+ my @taxset = Tax::init_taxes($form, $form->{taxaccounts});
+ $form->{invtotal} += $form->round_amount(
+ Tax::calculate_taxes(\@taxset, $form, $form->{invsubtotal}, 0), 2);
+ foreach $taxobj (@taxset) {
+ $item = $taxobj->account;
if ($form->{"${item}_base"}) {
- $form->{invtotal} += $form->{"${item}_total"} = $form->round_amount($form->{"${item}_base"} * $form->{"${item}_rate"}, 2);
- $form->{"${item}_total"} = $form->format_amount(\%myconfig, $form->{"${item}_total"}, 2);
+ $form->{"${item}_total"} = $form->format_amount(\%myconfig,
+ $form->round_amount($taxobj->value, 2), 2);
$tax .= qq|
<tr>
@@ -673,7 +677,10 @@ sub import_text {
$amount = $form->{"sellprice_$i"} * $form->{"qty_$i"} * (1 - $form->{"discount_$i"} / 100);
map { $form->{"${_}_base"} = 0 } (split / /, $form->{taxaccounts});
map { $form->{"${_}_base"} += $amount } (split / /, $form->{"taxaccounts_$i"});
- map { $amount += ($form->{"${_}_base"} * $form->{"${_}_rate"}) } split / /, $form->{"taxaccounts_$i"} if !$form->{taxincluded};
+ if (!$form->{taxincluded}) {
+ my @taxes = Tax::init_taxes($form, $form->{taxaccounts});
+ $amount += (Tax::calculate_taxes(\@taxes, $form, $amount, 0));
+ }
$form->{creditremaining} -= $amount;
@@ -794,7 +801,8 @@ sub update {
for (split / /, $form->{taxaccounts}) { $form->{"${_}_base"} = 0 }
for (split / /, $form->{"taxaccounts_$i"}) { $form->{"${_}_base"} += $amount }
if (!$form->{taxincluded}) {
- for (split / /, $form->{"taxaccounts_$i"}) { $amount += ($form->{"${_}_base"} * $form->{"${_}_rate"}) }
+ my @taxes = Tax::init_taxes($form, $form->{"taxaccounts_$i"});
+ $amount += (Tax::calculate_taxes(\@taxes, $form, $amount, 0));
}
$form->{creditremaining} -= $amount;
diff --git a/bin/mozilla/is.pl b/bin/mozilla/is.pl
index 5696dd11..c93c2337 100755
--- a/bin/mozilla/is.pl
+++ b/bin/mozilla/is.pl
@@ -46,6 +46,7 @@
use LedgerSMB::IS;
use LedgerSMB::PE;
+use LedgerSMB::Tax;
require "$form->{path}/arap.pl";
require "$form->{path}/io.pl";
@@ -470,19 +471,19 @@ sub form_footer {
if (!$form->{taxincluded}) {
- for (split / /, $form->{taxaccounts}) {
- if ($form->{"${_}_base"}) {
- $form->{"${_}_total"} = $form->round_amount($form->{"${_}_base"} * $form->{"${_}_rate"}, 2);
- $form->{invtotal} += $form->{"${_}_total"};
- $form->{"${_}_total"} = $form->format_amount(\%myconfig, $form->{"${_}_total"}, 2);
-
- $tax .= qq|
- <tr>
- <th align=right>$form->{"${_}_description"}</th>
- <td align=right>$form->{"${_}_total"}</td>
- </tr>
-|;
- }
+ my @taxes = Tax::init_taxes($form, $form->{taxaccounts});
+ $form->{invtotal} += Tax::calculate_taxes(\@taxes, $form,
+ $form->{invsubtotal}, 0);
+ foreach $item (@taxes) {
+ my $taccno = $item->account;
+ $form->{"${taccno}_total"} = $form->format_amount(\%myconfig,
+ $item->value, 2);
+ $tax .= qq|
+ <tr>
+ <th align=right>$form->{"${taccno}_description"}</th>
+ <td align=right>$form->{"${taccno}_total"}</td>
+ </tr>
+ | if $item->value;
}
$form->{invsubtotal} = $form->format_amount(\%myconfig, $form->{invsubtotal}, 2, 0);
@@ -813,7 +814,8 @@ sub update {
for (split / /, $form->{taxaccounts}) { $form->{"${_}_base"} = 0 }
for (split / /, $form->{"taxaccounts_$i"}) { $form->{"${_}_base"} += $amount }
if (!$form->{taxincluded}) {
- for (split / /, $form->{"taxaccounts_$i"}) { $amount += ($form->{"${_}_base"} * $form->{"${_}_rate"}) }
+ my @taxes = Tax::init_taxes($form, $form->{"taxaccounts_$i"});
+ $amount += Tax::calculate_taxes(\@taxes, $form, $amount, 0);
}
$form->{creditremaining} -= $amount;
diff --git a/bin/mozilla/oe.pl b/bin/mozilla/oe.pl
index b0910db5..d4b4bba3 100755
--- a/bin/mozilla/oe.pl
+++ b/bin/mozilla/oe.pl
@@ -44,6 +44,7 @@ use LedgerSMB::OE;
use LedgerSMB::IR;
use LedgerSMB::IS;
use LedgerSMB::PE;
+use LedgerSMB::Tax;
require "$form->{path}/arap.pl";
require "$form->{path}/io.pl";
@@ -600,19 +601,21 @@ sub form_footer {
if (!$form->{taxincluded}) {
- for (split / /, $form->{taxaccounts}) {
- if ($form->{"${_}_base"}) {
- $form->{invtotal} += $form->{"${_}_total"} = $form->round_amount($form->{"${_}_base"} * $form->{"${_}_rate"}, 2);
- $form->{"${_}_total"} = $form->format_amount(\%myconfig, $form->{"${_}_total"}, 2);
+ my @taxes = Tax::init_taxes($form, $form->{taxaccounts});
+ $form->{invtotal} += Tax::calculate_taxes(\@taxes,
+ $form, $form->{invsubtotal}, 0);
+ foreach my $item (@taxes) {
+ my $taccno = $item->account;
+ $form->{"${taccno}_total"} = $form->format_amount(\%myconfig,
+ $item->value, 2);
$tax .= qq|
<tr>
- <th align=right>$form->{"${_}_description"}</th>
- <td align=right>$form->{"${_}_total"}</td>
+ <th align=right>$form->{"${taccno}_description"}</th>
+ <td align=right>$form->{"${taccno}_total"}</td>
</tr>
-|;
+ | if $item->value;
}
- }
$form->{invsubtotal} = $form->format_amount(\%myconfig, $form->{invsubtotal}, 2, 0);
@@ -917,7 +920,8 @@ sub update {
for (split / /, $form->{taxaccounts}) { $form->{"${_}_base"} = 0 }
for (split / /, $form->{"taxaccounts_$i"}) { $form->{"${_}_base"} += $amount }
if (!$form->{taxincluded}) {
- for (split / /, $form->{taxaccounts}) { $amount += ($form->{"${_}_base"} * $form->{"${_}_rate"}) }
+ my @taxes = Tax::init_taxes($form, $form->{taxaccounts});
+ $amount += Tax::calculate_taxes(\@taxes, $form, $amount, 0);
}
$form->{creditremaining} -= $amount;
diff --git a/bin/mozilla/pos.pl b/bin/mozilla/pos.pl
index f7f817ea..ef2fbd92 100755
--- a/bin/mozilla/pos.pl
+++ b/bin/mozilla/pos.pl
@@ -40,6 +40,7 @@
#
#=====================================================================
+use LedgerSMB::Tax;
1;
# end
@@ -376,19 +377,22 @@ sub form_footer {
if (!$form->{taxincluded}) {
- for (split / /, $form->{taxaccounts}) {
- if ($form->{"${_}_base"}) {
- $form->{"${_}_total"} = $form->round_amount($form->{"${_}_base"} * $form->{"${_}_rate"}, 2);
- $form->{invtotal} += $form->{"${_}_total"};
- $form->{"${_}_total"} = $form->format_amount(\%myconfig, $form->{"${_}_total"}, 2, 0);
-
- $tax .= qq|
- <tr>
- <th align=right>$form->{"${_}_description"}</th>
- <td align=right>$form->{"${_}_total"}</td>
- </tr>
-|;
- }
+ my @taxes = Tax::init_taxes($form, $form->{taxaccounts});
+ $form->{invtotal} += Tax::calculate_taxes(\@taxes, $form,
+ $form->{invsubtotal}, 0);
+
+ foreach my $item (@taxes) {
+ my $taccno = $item->account;
+
+ $form->{"${taccno}_total"} = $form->format_amount(\%myconfig,
+ $item->value, 2, 0);
+
+ $tax .= qq|
+ <tr>
+ <th align=right>$form->{"${taccno}_description"}</th>
+ <td align=right>$form->{"${taccno}_total"}</td>
+ </tr>
+ | if $item->value;
}
$form->{invsubtotal} = $form->format_amount(\%myconfig, $form->{invsubtotal}, 2, 0);
diff --git a/sql/Canada-French_General-chart.sql b/sql/Canada-French_General-chart.sql
index 647dd121..add09a73 100755
--- a/sql/Canada-French_General-chart.sql
+++ b/sql/Canada-French_General-chart.sql
@@ -73,6 +73,6 @@ INSERT INTO chart (accno,description,charttype,category,link,gifi_accno) VALUES
INSERT INTO chart (accno,description,charttype,category,link,gifi_accno) VALUES ('5800', 'Taxes d''affaires, droits d''adhésion et permis', 'A', 'E', 'AP_amount', '8760');
--
insert into tax (chart_id,rate) values ((select id from chart where accno = '2310'),0.06);
-insert into tax (chart_id,rate) values ((select id from chart where accno = '2320'),0.08025);
+insert into tax (chart_id,rate,pass) values ((select id from chart where accno = '2320'),0.08,1);
--
update defaults set inventory_accno_id = (select id from chart where accno = '1520'), income_accno_id = (select id from chart where accno = '4020'), expense_accno_id = (select id from chart where accno = '5010'), fxgain_accno_id = (select id from chart where accno = '4450'), fxloss_accno_id = (select id from chart where accno = '4450'), curr = 'CAD:USD:EUR', weightunit = 'kg';
diff --git a/sql/Pg-tables.sql b/sql/Pg-tables.sql
index 42471a15..40a81af8 100755
--- a/sql/Pg-tables.sql
+++ b/sql/Pg-tables.sql
@@ -12,7 +12,7 @@ CREATE SEQUENCE jcitemsid;
SELECT nextval ('jcitemsid');
--
-create table transactions (
+CREATE TABLE transactions (
id int PRIMARY KEY,
table_name text
);
@@ -243,12 +243,20 @@ CREATE TABLE partstax (
PRIMARY KEY (parts_id, chart_id)
);
--
+CREATE TABLE taxmodule (
+ taxmodule_id serial PRIMARY KEY,
+ taxmodulename text NOT NULL
+};
+--
CREATE TABLE tax (
chart_id int PRIMARY KEY,
rate numeric,
taxnumber text,
validto date,
- FOREIGN KEY (chart_id) REFERENCES chart (id)
+ pass integer DEFAULT 0 NOT NULL,
+ taxmodule_id int,
+ FOREIGN KEY (chart_id) REFERENCES chart (id),
+ FOREIGN KEY (taxmodule_id) REFERENCES taxmodule (taxmodule_id)
);
--
CREATE TABLE customertax (
diff --git a/sql/Pg-upgrade-2.6.18-2.6.19.sql b/sql/Pg-upgrade-2.6.18-2.6.19.sql
index 07541bde..d8e304f3 100644
--- a/sql/Pg-upgrade-2.6.18-2.6.19.sql
+++ b/sql/Pg-upgrade-2.6.18-2.6.19.sql
@@ -120,3 +120,23 @@ SET DEFAULT nextval('shipto_entry_id_seq');
UPDATE shipto SET entry_id = nextval('shipto_entry_id_seq');
ALTER TABLE shipto ADD PRIMARY KEY (entry_id);
+
+CREATE TABLE taxmodule (
+ taxmodule_id serial PRIMARY KEY,
+ taxmodulename text NOT NULL
+);
+
+INSERT INTO taxmodule (
+ taxmodule_id, taxmodulename
+ ) VALUES (
+ 1, 'Simple'
+);
+
+LOCK tax IN EXCLUSIVE MODE;
+ALTER TABLE tax ADD COLUMN pass int DEFAULT 0;
+UPDATE tax SET pass = 0;
+ALTER TABLE tax ALTER COLUMN pass SET NOT NULL;
+
+ALTER TABLE tax ADD COLUMN taxmodule_id int REFERENCES taxmodule DEFAULT 1;
+UPDATE tax SET taxmodule_id = 1;
+ALTER TABLE tax ALTER COLUMN taxmodule_id SET NOT NULL;