Bug 13323: Tax rate can change on receiving
[koha.git] / t / Prices.t
1 use Modern::Perl;
2 use Test::More;
3 use Test::MockModule;
4
5 use t::lib::Mocks;
6
7 use Module::Load::Conditional qw/check_install/;
8
9 BEGIN {
10     if ( check_install( module => 'Test::DBIx::Class' ) ) {
11         plan tests => 17;
12     } else {
13         plan skip_all => "Need Test::DBIx::Class"
14     }
15 }
16
17 use_ok('C4::Acquisition');
18 use_ok('C4::Bookseller');
19 use_ok('C4::Context');
20 use_ok('Koha::Number::Price');
21
22 t::lib::Mocks::mock_preference( 'gist', '0.02|0.05|0.196' );
23
24 use Test::DBIx::Class {
25     schema_class => 'Koha::Schema',
26     connect_info => ['dbi:SQLite:dbname=:memory:','',''],
27     connect_opts => { name_sep => '.', quote_char => '`', },
28     fixture_class => '::Populate',
29 }, 'Currency' ;
30
31 my $db = Test::MockModule->new('Koha::Database');
32 $db->mock( _new_schema => sub { return Schema(); } );
33
34 fixtures_ok [
35     Currency => [
36         [ qw/ currency symbol rate active / ],
37         [[ 'my_cur', '€', 1, 1, ]],
38     ],
39 ], 'add currency fixtures';
40
41 my $bookseller_module = Test::MockModule->new('Koha::Acquisition::Bookseller');
42
43 my ( $basketno_0_0,  $basketno_1_1,  $basketno_1_0,  $basketno_0_1 );
44 my ( $invoiceid_0_0, $invoiceid_1_1, $invoiceid_1_0, $invoiceid_0_1 );
45 my $today;
46
47 for my $currency_format ( qw( US FR ) ) {
48     t::lib::Mocks::mock_preference( 'CurrencyFormat', $currency_format );
49     subtest 'Configuration 1: 0 0' => sub {
50         plan tests => 8;
51         $bookseller_module->mock(
52             'fetch',
53             sub {
54                 return { listincgst => 0, invoiceincgst => 0 };
55             }
56         );
57
58         my $biblionumber_0_0 = 42;
59
60         my $order_0_0 = {
61             biblionumber     => $biblionumber_0_0,
62             quantity         => 2,
63             listprice        => 82.000000,
64             unitprice        => 73.80000,
65             quantityreceived => 2,
66             basketno         => $basketno_0_0,
67             invoiceid        => $invoiceid_0_0,
68             rrp              => 82.00,
69             ecost            => 73.80,
70             tax_rate         => 0.0500,
71             discount         => 10.0000,
72             datereceived     => $today
73         };
74         $order_0_0 = C4::Acquisition::populate_order_with_prices(
75             {
76                 order        => $order_0_0,
77                 booksellerid => 'just_something',
78                 ordering     => 1,
79             }
80         );
81
82         compare(
83             {
84                 got      => $order_0_0->{rrp_tax_included},
85                 expected => 86.10,
86                 conf     => '0 0',
87                 field    => 'rrp_tax_included'
88             }
89         );
90         compare(
91             {
92                 got      => $order_0_0->{rrp_tax_excluded},
93                 expected => 82.00,
94                 conf     => '0 0',
95                 field    => 'rrp_tax_excluded'
96             }
97         );
98         compare(
99             {
100                 got      => $order_0_0->{ecost_tax_included},
101                 expected => 77.49,
102                 conf     => '0 0',
103                 field    => 'ecost_tax_included'
104             }
105         );
106         compare(
107             {
108                 got      => $order_0_0->{ecost_tax_excluded},
109                 expected => 73.80,
110                 conf     => '0 0',
111                 field    => 'ecost_tax_excluded'
112             }
113         );
114         compare(
115             {
116                 got      => $order_0_0->{tax_value_on_ordering},
117                 expected => 7.38,
118                 conf     => '0 0',
119                 field    => 'tax_value'
120             }
121         );
122
123         #
124         $order_0_0 = C4::Acquisition::populate_order_with_prices(
125             {
126                 order        => $order_0_0,
127                 booksellerid => 'just_something',
128                 receiving    => 1,
129             }
130         );
131
132         compare(
133             {
134                 got      => $order_0_0->{unitprice_tax_included},
135                 expected => 77.49,
136                 conf     => '0 0',
137                 field    => 'unitprice_tax_included'
138             }
139         );
140         compare(
141             {
142                 got      => $order_0_0->{unitprice_tax_excluded},
143                 expected => 73.80,
144                 conf     => '0 0',
145                 field    => 'unitprice_tax_excluded'
146             }
147         );
148         compare(
149             {
150                 got      => $order_0_0->{tax_value_on_receiving},
151                 expected => 7.38,
152                 conf     => '0 0',
153                 field    => 'tax_value'
154             }
155         );
156     };
157
158     subtest 'Configuration 1: 1 1' => sub {
159         plan tests => 8;
160         $bookseller_module->mock(
161             'fetch',
162             sub {
163                 return { listincgst => 1, invoiceincgst => 1 };
164             }
165         );
166
167         my $biblionumber_1_1 = 43;
168         my $order_1_1        = {
169             biblionumber     => $biblionumber_1_1,
170             quantity         => 2,
171             listprice        => 82.000000,
172             unitprice        => 73.800000,
173             quantityreceived => 2,
174             basketno         => $basketno_1_1,
175             invoiceid        => $invoiceid_1_1,
176             rrp              => 82.00,
177             ecost            => 73.80,
178             tax_rate         => 0.0500,
179             discount         => 10.0000,
180             datereceived     => $today
181         };
182
183         $order_1_1 = C4::Acquisition::populate_order_with_prices(
184             {
185                 order        => $order_1_1,
186                 booksellerid => 'just_something',
187                 ordering     => 1,
188             }
189         );
190
191         compare(
192             {
193                 got      => $order_1_1->{rrp_tax_included},
194                 expected => 82.00,
195                 conf     => '1 1',
196                 field    => 'rrp_tax_included'
197             }
198         );
199         compare(
200             {
201                 got      => $order_1_1->{rrp_tax_excluded},
202                 expected => 78.10,
203                 conf     => '1 1',
204                 field    => 'rrp_tax_excluded'
205             }
206         );
207         compare(
208             {
209                 got      => $order_1_1->{ecost_tax_included},
210                 expected => 73.80,
211                 conf     => '1 1',
212                 field    => 'ecost_tax_included'
213             }
214         );
215         compare(
216             {
217                 got      => $order_1_1->{ecost_tax_excluded},
218                 expected => 70.29,
219                 conf     => '1 1',
220                 field    => 'ecost_tax_excluded'
221             }
222         );
223         compare(
224             {
225                 got      => $order_1_1->{tax_value_on_ordering},
226                 expected => 7.03,
227                 conf     => '1 1',
228                 field    => 'tax_value'
229             }
230         );
231
232         $order_1_1 = C4::Acquisition::populate_order_with_prices(
233             {
234                 order        => $order_1_1,
235                 booksellerid => 'just_something',
236                 receiving    => 1,
237             }
238         );
239
240         compare(
241             {
242                 got      => $order_1_1->{unitprice_tax_included},
243                 expected => 73.80,
244                 conf     => '1 1',
245                 field    => 'unitprice_tax_included'
246             }
247         );
248         compare(
249             {
250                 got      => $order_1_1->{unitprice_tax_excluded},
251                 expected => 70.29,
252                 conf     => '1 1',
253                 field    => 'unitprice_tax_excluded'
254             }
255         );
256         compare(
257             {
258                 got      => $order_1_1->{tax_value_on_receiving},
259                 expected => 7.03,
260                 conf     => '1 1',
261                 field    => 'tax_value'
262             }
263         );
264     };
265
266     subtest 'Configuration 1: 1 0' => sub {
267         plan tests => 8;
268         $bookseller_module->mock(
269             'fetch',
270             sub {
271                 return { listincgst => 1, invoiceincgst => 0 };
272             }
273         );
274
275         my $biblionumber_1_0 = 44;
276         my $order_1_0        = {
277             biblionumber     => $biblionumber_1_0,
278             quantity         => 2,
279             listprice        => 82.000000,
280             unitprice        => 70.290000,
281             quantityreceived => 2,
282             basketno         => $basketno_1_1,
283             invoiceid        => $invoiceid_1_1,
284             rrp              => 82.00,
285             ecost            => 73.80,
286             tax_rate         => 0.0500,
287             discount         => 10.0000,
288             datereceived     => $today
289         };
290
291         $order_1_0 = C4::Acquisition::populate_order_with_prices(
292             {
293                 order        => $order_1_0,
294                 booksellerid => 'just_something',
295                 ordering     => 1,
296             }
297         );
298
299         compare(
300             {
301                 got      => $order_1_0->{rrp_tax_included},
302                 expected => 82,
303                 conf     => '1 0',
304                 field    => 'rrp_tax_included'
305             }
306         );
307         compare(
308             {
309                 got      => $order_1_0->{rrp_tax_excluded},
310                 expected => 78.10,
311                 conf     => '1 0',
312                 field    => 'rrp_tax_excluded'
313             }
314         );
315         compare(
316             {
317                 got      => $order_1_0->{ecost_tax_included},
318                 expected => 73.80,
319                 conf     => '1 0',
320                 field    => 'ecost_tax_included'
321             }
322         );
323         compare(
324             {
325                 got      => $order_1_0->{ecost_tax_excluded},
326                 expected => 70.29,
327                 conf     => '1 0',
328                 field    => 'ecost_tax_excluded'
329             }
330         );
331         compare(
332             {
333                 got      => $order_1_0->{tax_value_on_ordering},
334                 expected => 7.03,
335                 conf     => '1 0',
336                 field    => 'tax_value'
337             }
338         );
339
340         $order_1_0 = C4::Acquisition::populate_order_with_prices(
341             {
342                 order        => $order_1_0,
343                 booksellerid => 'just_something',
344                 receiving    => 1,
345             }
346         );
347
348         compare(
349             {
350                 got      => $order_1_0->{unitprice_tax_included},
351                 expected => 73.80,
352                 conf     => '1 0',
353                 field    => 'unitprice_tax_included'
354             }
355         );
356         compare(
357             {
358                 got      => $order_1_0->{unitprice_tax_excluded},
359                 expected => 70.29,
360                 conf     => '1 0',
361                 field    => 'unitprice_tax_excluded'
362             }
363         );
364         compare(
365             {
366                 got      => $order_1_0->{tax_value_on_receiving},
367                 expected => 7.03,
368                 conf     => '1 0',
369                 field    => 'tax_value'
370             }
371         );
372     };
373
374     subtest 'Configuration 1: 0 1' => sub {
375         plan tests => 8;
376         $bookseller_module->mock(
377             'fetch',
378             sub {
379                 return { listincgst => 0, invoiceincgst => 1 };
380             }
381         );
382
383         my $biblionumber_0_1 = 45;
384         my $order_0_1        = {
385             biblionumber     => $biblionumber_0_1,
386             quantity         => 2,
387             listprice        => 82.000000,
388             unitprice        => 77.490000,
389             quantityreceived => 2,
390             basketno         => $basketno_1_1,
391             invoiceid        => $invoiceid_1_1,
392             rrp              => 82.00,
393             ecost            => 73.80,
394             tax_rate         => 0.0500,
395             discount         => 10.0000,
396             datereceived     => $today
397         };
398
399         $order_0_1 = C4::Acquisition::populate_order_with_prices(
400             {
401                 order        => $order_0_1,
402                 booksellerid => 'just_something',
403                 ordering     => 1,
404             }
405         );
406
407         compare(
408             {
409                 got      => $order_0_1->{rrp_tax_included},
410                 expected => 86.10,
411                 conf     => '0 1',
412                 field    => 'rrp_tax_included'
413             }
414         );
415         compare(
416             {
417                 got      => $order_0_1->{rrp_tax_excluded},
418                 expected => 82.00,
419                 conf     => '0 1',
420                 field    => 'rrp_tax_excluded'
421             }
422         );
423         compare(
424             {
425                 got      => $order_0_1->{ecost_tax_included},
426                 expected => 77.49,
427                 conf     => '0 1',
428                 field    => 'ecost_tax_included'
429             }
430         );
431         compare(
432             {
433                 got      => $order_0_1->{ecost_tax_excluded},
434                 expected => 73.80,
435                 conf     => '0 1',
436                 field    => 'ecost_tax_excluded'
437             }
438         );
439         compare(
440             {
441                 got      => $order_0_1->{tax_value_on_ordering},
442                 expected => 7.38,
443                 conf     => '0 1',
444                 field    => 'tax_value'
445             }
446         );
447
448         $order_0_1 = C4::Acquisition::populate_order_with_prices(
449             {
450                 order        => $order_0_1,
451                 booksellerid => 'just_something',
452                 receiving    => 1,
453             }
454         );
455
456         compare(
457             {
458                 got      => $order_0_1->{unitprice_tax_included},
459                 expected => 77.49,
460                 conf     => '0 1',
461                 field    => 'unitprice_tax_included'
462             }
463         );
464         compare(
465             {
466                 got      => $order_0_1->{unitprice_tax_excluded},
467                 expected => 73.80,
468                 conf     => '0 1',
469                 field    => 'unitprice_tax_excluded'
470             }
471         );
472         compare(
473             {
474                 got      => $order_0_1->{tax_value_on_receiving},
475                 expected => 7.38,
476                 conf     => '0 1',
477                 field    => 'tax_value'
478             }
479         );
480     };
481 }
482
483 sub compare {
484     my ($params) = @_;
485     is(
486         Koha::Number::Price->new( $params->{got} )->format,
487         Koha::Number::Price->new( $params->{expected} )->format,
488 "configuration $params->{conf}: $params->{field} should be correctly calculated"
489     );
490 }
491
492 # format_for_editing
493 for my $currency_format ( qw( US FR ) ) {
494     t::lib::Mocks::mock_preference( 'CurrencyFormat', $currency_format );
495     is( Koha::Number::Price->new( 1234567 )->format_for_editing, '1234567.00', 'format_for_editing should return unformated integer part with 2 decimals' );
496     is( Koha::Number::Price->new( 1234567.89 )->format_for_editing, '1234567.89', 'format_for_editing should return unformated integer part with 2 decimals' );
497 }