Consolidation and extended test runs
[kivitendo-erp.git] / t / form / arap.t
1 use strict;
2 use Test::More;
3
4 use lib 't';
5 use Support::TestSetup;
6 use Carp;
7 use Test::Exception;
8
9 no warnings qw(qw);
10
11 # this test tests the functions calculate_arap and calculate_tax in SL/Form.pm
12 # calculate_arap is used for post_invoice in AR and AP
13 # calculate_tax is used in calculate_arap as well as update in ar/ap/gl and post_transaction in gl
14
15 my $default_manager;
16 my ($ar_tax_19, $ar_tax_7,$ar_tax_0);
17 my $config = {};
18
19 sub reset_state {
20   my %params = @_;
21
22   $params{$_} ||= {} for qw(ar_tax_19 ar_tax_7 ar_tax_0 );
23
24   # delete rowcount lines in form, would be better to reset form completely
25   for my $hv ( 1 .. 10 ) {
26       foreach my $type ( qw(amount tax tax_id tax_chart) ) {
27           delete $::form{"$type\_$hv"};
28       };
29   };
30
31   $default_manager = $::lx_office_conf{system}->{default_manager};
32   if ($default_manager eq "swiss") {
33     $ar_tax_19 = SL::DB::Manager::Tax->find_by(taxkey => 2, rate => 0.08, %{ $params{ar_tax_19} })  || croak "No 8% tax";
34     $ar_tax_7  = SL::DB::Manager::Tax->find_by(taxkey => 3, rate => 0.025,  %{ $params{ar_tax_7} }) || croak "No 2.5% tax";
35     $config->{numberformat} = "1'000.00";
36
37   } else {
38     $ar_tax_19 = SL::DB::Manager::Tax->find_by(taxkey => 3, rate => 0.19,  %{ $params{ar_tax_19} }) || croak "No 19% tax";
39     $ar_tax_7  = SL::DB::Manager::Tax->find_by(taxkey => 2, rate => 0.07,  %{ $params{ar_tax_7} })  || croak "No 7% tax";
40     $config->{numberformat} = '1.000,00';
41   }
42   $ar_tax_0  = SL::DB::Manager::Tax->find_by(taxkey => 0, rate => 0.00,    %{ $params{ar_tax_0} })  || croak "No 0% tax";
43
44 };
45
46 sub arap_test {
47   my ($testcase) = @_;
48
49   reset_state;
50
51   # values from testcase
52   $::form->{taxincluded}     = $testcase->{taxincluded};
53   $::form->{currency}        = $testcase->{currency};
54   $::form->{rowcount}        = scalar @{$testcase->{lines}};
55
56   # parse exchangerate, because it was added in the same numberformat as the
57   # other amounts in the testcases
58   $testcase->{exchangerate}    = $::form->parse_amount(\%::myconfig, $testcase->{exchangerate});
59
60   foreach my $a ( 1 .. scalar @{$testcase->{lines}} ) {
61     my ($taxrate, $form_amount, $netamount, $taxamount, $totalamount) = @{ @{ $testcase->{lines} }[$a-1] };
62     my $tax;
63     if ( $taxrate eq ($default_manager eq "swiss" ? '8' : '19' )) {
64         $tax = $ar_tax_19;
65     } elsif ( $taxrate eq ($default_manager eq "swiss" ? '2,5' : '7' )) {
66         $tax = $ar_tax_7;
67     } elsif ( $taxrate eq '0' ) {
68         $tax = $ar_tax_0;
69     } else {
70         croak "illegal taxrate $taxrate";
71     };
72
73     $::form->{"amount_$a"}   = $form_amount;
74     $::form->{"tax_$a"}      = $taxamount;  # tax according to UI, will recalculate anyway?
75     $::form->{"taxchart_$a"} = $tax->id . '--' . $tax->rate;
76
77   };
78
79   # calculate totals using lines in $::form
80   ($::form->{netamount},$::form->{total_tax},$::form->{amount}) = $::form->calculate_arap($testcase->{'buysell'}, $::form->{taxincluded}, $testcase->{'exchangerate'});
81
82   # create tests comparing calculated and expected values
83   is($::form->format_amount(\%::myconfig , $::form->{total_tax} , 2) , $testcase->{'total_taxamount'} , "total tax   = $testcase->{'total_taxamount'}");
84   is($::form->format_amount(\%::myconfig , $::form->{netamount} , 2) , $testcase->{'total_netamount'} , "netamount   = $testcase->{'total_netamount'}");
85   is($::form->format_amount(\%::myconfig , $::form->{amount}    , 2) , $testcase->{'total_amount'}    , "totalamount = $testcase->{'total_amount'}");
86   is($::form->{taxincluded}, $testcase->{'taxincluded'}, "taxincluded = $testcase->{'taxincluded'}");
87
88 };
89
90 sub calculate_tax_test {
91   my ($amount, $rate, $taxincluded, $net, $tax, $total, $dec) = @_;
92   # amount, rate and taxincluded are the values that we want to calculate with
93   # net, tax and total are the values that we expect, dec is the number of decimals we round to
94
95   my ($calculated_net,$calculated_tax) = $::form->calculate_tax($amount,$rate,$taxincluded,$dec);
96
97   is($tax, $calculated_tax, "calculated tax for taxincluded = $taxincluded for net $amount and rate $rate is = $calculated_tax");
98   is($calculated_net, $net, "calculated net for taxincluded = $taxincluded for net $amount and rate $rate is = $net");
99 };
100
101 my @testline1;
102 my @testline2;
103 my @testline3;
104 my @testline4;
105 my @testline5;
106 my @testline6;
107 my @testline7;
108 my @testline8;
109 my @testline9;
110 my @testline10;
111 my @testline11;
112 my @testline12;
113 my @testline13;
114 my @testline14;
115 my @testline15;
116 my @testline16;
117 my @testline17;
118
119 sub init_testlines {
120   # define the various lines that can be used for the testcases
121   # always use positive values for buy/sell, like in the interface
122   #                   tax  input   net      tax   total  type
123   $default_manager = $::lx_office_conf{system}->{default_manager};
124   if ($default_manager eq "swiss") {
125     @testline1  = qw(8    51,30   47,50   3,80   51,30  sell);
126     @testline2  = qw(8    10,80   10,00   0,80   10,80  sell);
127     @testline3  = qw(2,5  13,79   13,45   0,34   10,80  sell);
128     @testline4  = qw(8   133,08  133,08  10,65  143,73  sell);
129     @testline5  = qw(0   100,00   83,00   0,00   83,00  sell);  # exchangerate of 0,83
130     @testline6  = qw(8    51,30   47,50   3,80   51,30   buy);
131     @testline7  = qw(8   309,86  309,86  24,79  334,65   buy);
132     @testline8  = qw(2,5 124,54  121,50   3,04  124,54   buy);
133     @testline9  = qw(2,5 121,49  121,49   3,04  124,53   buy);
134     @testline10 = qw(2,5 121,50  121,50   3,05  124,55   buy);
135     @testline11 = qw(8    -2,77   -2,77  -0,22   -2,99   buy);
136     @testline12 = qw(2,5  12,88   12,88   0,32   13,20   buy);
137     @testline13 = qw(8    41,93   41,93   3,35   45,28   buy);
138     @testline14 = qw(8    84,65   84,65   6,77   98,42   buy);
139     @testline15 = qw(8     8,39    8,39   0,66    9,05   buy);
140     @testline16 = qw(8    91,42   84,65   6,77   98,42   buy);
141     @testline17 = qw(8     9,06    8,39   0,67    9,06   buy);
142   } else {
143     @testline1  = qw(19   56,53   47,50   9,03   56,53  sell);
144     @testline2  = qw(19   11,90   10,00   1,90   11,90  sell);
145     @testline3  = qw( 7   14,39   13,45   0,94   11,90  sell);
146     @testline4  = qw(19  133,08  133,08  25,29  158,37  sell);
147     @testline5  = qw( 0  100,00   83,00   0,00   83,00  sell);  # exchangerate of 0,83
148     @testline6  = qw(19   56,53   47,50   9,03   56,53   buy);
149     @testline7  = qw(19  309,86  309,86  58,87  368,73   buy);
150     @testline8  = qw( 7  130,00  121,50   8,50  130,00   buy);
151     @testline9  = qw( 7  121,49  121,49   8,50  129,99   buy);
152     @testline10 = qw( 7  121,50  121,50   8,51  130,01   buy);
153     @testline11 = qw(19   -2,77   -2,77  -0,53   -3,30   buy);
154     @testline12 = qw( 7   12,88   12,88   0,90   13,78   buy);
155     @testline13 = qw(19   41,93   41,93   7,97   49,90   buy);
156     @testline14 = qw(19   84,65   84,65  16,08  107,73   buy);
157     @testline15 = qw(19    8,39    8,39   1,59    9,98   buy);
158     @testline16 = qw(19  100,73   84,65  16,08  107,73   buy);
159     @testline17 = qw(19    9,99    8,39   1,60    9,99   buy);
160   }
161 }
162
163 Support::TestSetup::login();
164
165 init_testlines;
166
167 # create testcases, made up of one or more lines, with expected values
168
169 my $testcase1 = {
170     lines           => [ \@testline1 ], # lines to be used in testcase
171     total_amount    => $default_manager eq "swiss" ? '51,30' : '56,53',  # expected result
172     total_netamount => '47,50',  # expected result
173     total_taxamount => $default_manager eq "swiss" ? '3,80' : '9,03',  # expected result
174     # invoice parameters:
175     taxincluded     => 1,
176     exchangerate    => 1,
177     currency        => 'EUR',
178     buysell         => 'sell',
179 };
180
181 my $testcase2 = {
182     lines           => [ \@testline1, \@testline2, \@testline3 ],
183     total_amount    => $default_manager eq "swiss" ? '75,89' : '82,82',
184     total_netamount => '70,95',
185     total_taxamount => $default_manager eq "swiss" ? '4,94' : '11,87',
186     taxincluded     => 1,
187     exchangerate    => 1,
188     currency        => 'EUR',
189     buysell         => 'sell',
190 };
191
192 my $testcase3 = {
193     lines           => [ \@testline4 ],
194     total_amount    => $default_manager eq "swiss" ? '143,73' : '158,37',
195     total_netamount => '133,08',
196     total_taxamount => $default_manager eq "swiss" ? '10,65' : '25,29',
197     taxincluded     => 0,
198     exchangerate    => 1,
199     currency        => 'EUR',
200     buysell         => 'sell',
201 };
202
203 my $testcase4 = {
204     lines           => [ \@testline5 ],
205     total_amount    => '83,00',
206     total_netamount => '83,00',
207     total_taxamount => '0,00',
208     taxincluded     => 0,
209     exchangerate    => '0,83',
210     currency        => 'USD',
211     buysell         => 'sell',
212 };
213
214 my $testcase6 = {
215     lines           => [ \@testline6 ],
216     total_amount    => $default_manager eq "swiss" ? '51,30' : '56,53',
217     total_netamount => '47,50',
218     total_taxamount => $default_manager eq "swiss" ? '3,80' : '9,03',
219     taxincluded     => 1,
220     exchangerate    => 1,
221     currency        => 'EUR',
222     buysell         => 'buy',
223 };
224
225 my $testcase7 = {
226     lines           => [ \@testline7 ],
227     total_netamount => '309,86',
228     total_taxamount => $default_manager eq "swiss" ? '24,79' : '58,87',
229     total_amount    => $default_manager eq "swiss" ? '334,65' : '368,73',
230     taxincluded     => 0,
231     exchangerate    => 1,
232     currency        => 'EUR',
233     buysell         => 'buy',
234 };
235
236 my $testcase8 = {
237     lines           => [ \@testline8 ],
238     total_netamount => '121,50',
239     total_taxamount => $default_manager eq "swiss" ? '3,04' : '8,50',
240     total_amount    => $default_manager eq "swiss" ? '124,54' : '130,00',
241     taxincluded     => 1,
242     exchangerate    => 1,
243     currency        => 'EUR',
244     buysell         => 'buy',
245 };
246
247 my $testcase9 = {
248     lines           => [ \@testline9 ],
249     total_netamount => '121,49',
250     total_taxamount => $default_manager eq "swiss" ? '3,04' : '8,50',
251     total_amount    => $default_manager eq "swiss" ? '124,53' : '129,99',
252     taxincluded     => 0,
253     exchangerate    => 1,
254     currency        => 'EUR',
255     buysell         => 'buy',
256 };
257
258 my $testcase10 = {
259     lines           => [ \@testline10 ],
260     total_netamount => '121,50',
261     total_taxamount => $default_manager eq "swiss" ? '3,04' : '8,51',
262     total_amount    => $default_manager eq "swiss" ? '124,54' : '130,01',
263     taxincluded     => 0,
264     exchangerate    => 1,
265     currency        => 'EUR',
266     buysell         => 'buy',
267 };
268
269 my $testcase11 = {
270     # mixed invoices, -2,77€ net with 19% as credit note, 12,88€ net with 7%
271     lines           => [ \@testline11 , \@testline12 ],
272     total_netamount => '10,11',
273     total_taxamount => $default_manager eq "swiss" ? '0,10' : '0,37',
274     total_amount    => $default_manager eq "swiss" ? '10,21' : '10,48',
275     taxincluded     => 0,
276     exchangerate    => 1,
277     currency        => 'EUR',
278     buysell         => 'buy',
279 };
280
281 my $testcase12 = {
282     # ap transaction, example from bug 2435
283     lines           => [ \@testline13 ],
284     total_netamount => '41,93',
285     total_taxamount => $default_manager eq "swiss" ? '3,35' : '7,97',
286     total_amount    => $default_manager eq "swiss" ? '45,28' : '49,90',
287     taxincluded     => 0,
288     exchangerate    => 1,
289     currency        => 'EUR',
290     buysell         => 'buy',
291 };
292
293 my $testcase13 = {
294     # ap transaction, example from bug 2094, tax not included
295     lines           => [ \@testline14 , \@testline15 ],
296     total_netamount => '93,04',
297     total_taxamount => $default_manager eq "swiss" ? '7,44' : '17,67',
298     total_amount    => $default_manager eq "swiss" ? '100,48' : '110,71',
299     taxincluded     => 0,
300     exchangerate    => 1,
301     currency        => 'EUR',
302     buysell         => 'buy',
303 };
304
305 my $testcase14 = {
306     # ap transaction, example from bug 2094, tax included
307     lines           => [ \@testline16 , \@testline17 ],
308     total_netamount => '93,04',
309     total_taxamount => $default_manager eq "swiss" ? '7,44' : '17,68',
310     total_amount    => $default_manager eq "swiss" ? '100,48' : '110,72',
311     taxincluded     => 1,
312     exchangerate    => 1,
313     currency        => 'EUR',
314     buysell         => 'buy',
315 };
316
317 # run tests
318 arap_test($testcase1);
319 arap_test($testcase2);
320 arap_test($testcase3);
321 arap_test($testcase4);
322 arap_test($testcase6);
323 arap_test($testcase7);
324 arap_test($testcase8);
325 arap_test($testcase9);
326 arap_test($testcase10);
327 arap_test($testcase11);
328 arap_test($testcase12);
329 arap_test($testcase13);
330 arap_test($testcase14);
331
332 # tests for calculate_tax:
333
334 # tests for 1 Cent, calculated tax should be 0
335 calculate_tax_test(0.01,0.07,1,0.01,0.00,0.01,2);
336 calculate_tax_test(0.01,0.19,1,0.01,0.00,0.01,2);
337
338 # tax for rate 7% taxincluded flips at 0.08
339 calculate_tax_test(0.07,0.07,1,0.07,0.00,0.07,2);
340 calculate_tax_test(0.08,0.07,1,0.07,0.01,0.08,2);
341
342 # tax for rate 7% taxexcluded flips at 0.08
343 calculate_tax_test(0.07,0.07,0,0.07,0.00,0.07,2);
344 calculate_tax_test(0.08,0.07,0,0.08,0.01,0.09,2);
345
346 # tax for rate 19% taxexcluded flips at 0.03
347 calculate_tax_test(0.02,0.19,0,0.02,0.00,0.02,2);
348 calculate_tax_test(0.03,0.19,0,0.03,0.01,0.04,2);
349
350 # tax for rate 19% taxincluded flips at 0.04
351 calculate_tax_test(0.03,0.19,1,0.03,0.00,0.03,2);
352 calculate_tax_test(0.04,0.19,1,0.03,0.01,0.04,2);
353
354 calculate_tax_test(8.39,0.19,0,8.39,1.59,9.98,2);
355 calculate_tax_test(9.99,0.19,1,8.39,1.60,9.99,2);
356
357 calculate_tax_test(11.21,0.07,0,11.21,0.78,11.99,2);
358 calculate_tax_test(11.22,0.07,0,11.22,0.79,12.01,2);
359 calculate_tax_test(12.00,0.07,1,11.21,0.79,12.00,2);
360
361 done_testing(82);
362
363 1;