]> wagnertech.de Git - mfinanz.git/blob - t/datev/invoices.t
t/datev/invoices.t nutzt Dev create_ap_transaction
[mfinanz.git] / t / datev / invoices.t
1 use strict;
2 use Test::More;
3 use Test::Deep qw(cmp_deeply cmp_bag);
4
5 use lib 't';
6 use utf8;
7
8 use_ok 'Support::TestSetup';
9 use SL::DATEV qw(:CONSTANTS);
10 use SL::Dev::ALL qw(:ALL);
11 use List::Util qw(sum);
12 use SL::DB::Buchungsgruppe;
13 use SL::DB::Chart;
14 use DateTime;
15
16 Support::TestSetup::login();
17
18 clear_up();
19
20 my $dbh = SL::DB->client->dbh;
21
22 my $buchungsgruppe7 = SL::DB::Manager::Buchungsgruppe->find_by(description => 'Standard 7%') || die "No accounting group for 7\%";
23 my $bank            = SL::DB::Manager::Chart->find_by(description => 'Bank')                 || die 'Can\'t find chart "Bank"';
24 my $date            = DateTime->new(year => 2017, month =>  1, day => 1);
25 my $payment_date    = DateTime->new(year => 2017, month =>  1, day => 5);
26 my $gldate          = DateTime->new(year => 2017, month =>  2, day => 9); # simulate bookings for Jan being made in Feb
27 my $department      = create_department(description => 'Kostenstelle DATEV-Schnittstelle 2018');
28 my $project         = create_project(projectnumber => 2017, description => 'Crowd-Funding September 2017');
29 my $customer        = new_customer(customernumber => '10001', name => 'Testcustomer')->save;
30 my $vendor          = new_vendor(vendornumber => '70001', name => 'Testvendor')->save;
31
32 my $part1 = new_part(partnumber => '19', description => 'Part 19%')->save;
33 my $part2 = new_part(
34   partnumber         => '7',
35   description        => 'Part 7%',
36   buchungsgruppen_id => $buchungsgruppe7->id,
37 )->save;
38
39 my $invoice = create_sales_invoice(
40   invnumber    => "Þ sales ¥& invöice",
41   customer     => $customer,
42   itime        => $gldate,
43   gldate       => $gldate,
44   intnotes     => 'booked in February',
45   taxincluded  => 0,
46   transdate    => $date,
47   invoiceitems => [ create_invoice_item(part => $part1, qty =>  3, sellprice => 70),
48                     create_invoice_item(part => $part2, qty => 10, sellprice => 50),
49                   ],
50   department_id    => $department->id,
51   globalproject_id => $project->id,
52 );
53 $invoice->pay_invoice(chart_id      => $bank->id,
54                       amount        => $invoice->open_amount,
55                       transdate     => $payment_date->to_kivitendo,
56                       memo          => 'foobar',
57                       source        => 'barfoo',
58                      );
59 my $datev1 = SL::DATEV->new(
60   dbh        => $invoice->db->dbh,
61   trans_id   => $invoice->id,
62 );
63
64 $datev1->generate_datev_data;
65
66 my @data_datev   = sort { $a->{umsatz} <=> $b->{umsatz} } @{ $datev1->generate_datev_lines() };
67 cmp_deeply \@data_datev, [
68                                          {
69                                            'belegfeld1'   => "\x{de} sales \x{a5}& inv\x{f6}ice",
70                                            'buchungstext' => 'Testcustomer',
71                                            'datum'        => '01.01.2017',
72                                            'gegenkonto'   => '8400',
73                                            'konto'        => '1400',
74                                            'kost1'        => 'Kostenstelle DATEV-Schnittstelle 2018',
75                                            'kost2'        => 'Crowd-Funding September 2017',
76                                            'umsatz'       => '249.9',
77                                            'waehrung'     => 'EUR',
78                                          },
79                                          {
80                                            'belegfeld1'   => "\x{de} sales \x{a5}& inv\x{f6}ice",
81                                            'buchungstext' => 'Testcustomer',
82                                            'datum'        => '01.01.2017',
83                                            'gegenkonto'   => '8300',
84                                            'konto'        => '1400',
85                                            'kost1'        => 'Kostenstelle DATEV-Schnittstelle 2018',
86                                            'kost2'        => 'Crowd-Funding September 2017',
87                                            'umsatz'       => 535,
88                                            'waehrung'     => 'EUR',
89                                          },
90                                          {
91                                            'belegfeld1'   => "\x{de} sales \x{a5}& inv\x{f6}ice",
92
93
94 'buchungstext' => 'Testcustomer',
95                                            'buchungstext' => 'Testcustomer',
96                                            'datum'        => '05.01.2017',
97                                            'gegenkonto'   => '1400',
98                                            'konto'        => '1200',
99                                            'kost1'        => 'Kostenstelle DATEV-Schnittstelle 2018',
100                                            'kost2'        => 'Crowd-Funding September 2017',
101                                            'umsatz'       => '784.9',
102                                            'waehrung'     => 'EUR',
103                                          },
104                                        ], "trans_id datev check ok";
105
106 $datev1->use_pk(1);
107 $datev1->generate_datev_data;
108 # TODO for cmp_deeply we need to sort the incoming data structure (see below)
109 cmp_bag $datev1->generate_datev_lines, [
110                                          {
111                                            'belegfeld1'   => "\x{de} sales \x{a5}& inv\x{f6}ice",
112                                            'buchungstext' => 'Testcustomer',
113                                            'datum'        => '01.01.2017',
114                                            'gegenkonto'   => '8400',
115                                            'konto'        => $customer->customernumber,
116                                            'kost1'        => 'Kostenstelle DATEV-Schnittstelle 2018',
117                                            'kost2'        => 'Crowd-Funding September 2017',
118                                            'umsatz'       => '249.9',
119                                            'waehrung'     => 'EUR',
120                                          },
121                                          {
122                                            'belegfeld1'   => "\x{de} sales \x{a5}& inv\x{f6}ice",
123                                            'buchungstext' => 'Testcustomer',
124                                            'datum'        => '01.01.2017',
125                                            'gegenkonto'   => '8300',
126                                            'konto'        => $customer->customernumber,
127                                            'kost1'        => 'Kostenstelle DATEV-Schnittstelle 2018',
128                                            'kost2'        => 'Crowd-Funding September 2017',
129                                            'umsatz'       => 535,
130                                            'waehrung'     => 'EUR',
131                                          },
132                                          {
133                                            'belegfeld1'   => "\x{de} sales \x{a5}& inv\x{f6}ice",
134                                            'buchungstext' => 'Testcustomer',
135                                            'datum'        => '05.01.2017',
136                                            'gegenkonto'   => $customer->customernumber,
137                                            'konto'        => '1200',
138                                            'kost1'        => 'Kostenstelle DATEV-Schnittstelle 2018',
139                                            'kost2'        => 'Crowd-Funding September 2017',
140                                            'umsatz'       => '784.9',
141                                            'waehrung'     => 'EUR',
142                                          },
143                                        ], "trans_id datev check use_pk ok";
144
145
146 my $startdate = DateTime->new(year => 2017, month =>  1, day =>  1);
147 my $enddate   = DateTime->new(year => 2017, month => 12, day => 31);
148
149 # check conversion to csv
150 $datev1->from($startdate);
151 $datev1->to($enddate);
152 # reset use_pk for csv_buchungsexport
153 $datev1->use_pk(0);
154 $datev1->generate_datev_data;
155
156
157 my $datev_csv = SL::DATEV::CSV->new(datev_lines  => $datev1->generate_datev_lines,
158                                     from         => $startdate,
159                                     to           => $enddate,
160                                     locked       => $datev1->locked,
161                                    );
162 $datev_csv->lines;
163
164
165 # we need sort, because pay_invoice is not acc_trans_id order safe
166 my @data_csv    = sort { $a->[0] cmp $b->[0] } @{ $datev_csv->lines };
167 # warnings should be undef -> no array elements at all
168 is(scalar @{ $datev_csv->warnings }, 0);
169
170
171 cmp_deeply($data_csv[1], [ '535', 'S', 'EUR', '', '', '', '1400', '8300', '', '0101', "\x{de} sales \x{a5}& i",
172                      '', '', 'Testcustomer', '', '', '', '', '', '', '', '',
173                      '', '', '', '', '', '', '', '', '', '', '', '', '',
174                      '', 'Kostenst', 'Crowd-Fu', '', '', '', '', '', '', '', '',
175                      '', '', '', '', '', '', '', '', '', '', '', '', '',
176                      '', '', '', '', '', '', '', '', '', '', '', '', '',
177                      '', '', '', '', '', '', '', '', '', '', '', '', '',
178                      '', '', '', '', '', '', '', '', '', '', '', '', '',
179                      '', '', '', '', '', '', '', '', '', '', '', '', '',
180                      '', '', '', '', '' ]
181        );
182
183 cmp_deeply($data_csv[0], [ '249,9', 'S', 'EUR', '', '', '', '1400', '8400', '', '0101', "\x{de} sales \x{a5}& i",
184                      '', '', 'Testcustomer', '', '', '', '', '', '', '', '',
185                      '', '', '', '', '', '', '', '', '', '', '', '', '',
186                      '', 'Kostenst', 'Crowd-Fu', '', '', '', '', '', '', '', '',
187                      '', '', '', '', '', '', '', '', '', '', '', '', '',
188                      '', '', '', '', '', '', '', '', '', '', '', '', '',
189                      '', '', '', '', '', '', '', '', '', '', '', '', '',
190                      '', '', '', '', '', '', '', '', '', '', '', '', '',
191                      '', '', '', '', '', '', '', '', '', '', '', '', '',
192                      '', '', '', '', '' ]
193        );
194 cmp_deeply($data_csv[2], [ '784,9', 'S', 'EUR', '', '', '', '1200', '1400', '', '0501', "\x{de} sales \x{a5}& i",
195                      '', '', 'Testcustomer', '', '', '', '', '', '', '', '',
196                      '', '', '', '', '', '', '', '', '', '', '', '', '',
197                      '', 'Kostenst', 'Crowd-Fu', '', '', '', '', '', '', '', '',
198                      '', '', '', '', '', '', '', '', '', '', '', '', '',
199                      '', '', '', '', '', '', '', '', '', '', '', '', '',
200                      '', '', '', '', '', '', '', '', '', '', '', '', '',
201                      '', '', '', '', '', '', '', '', '', '', '', '', '',
202                      '', '', '', '', '', '', '', '', '', '', '', '', '',
203                      '', '', '', '', '' ]
204         );
205 my $march_9 = DateTime->new(year => 2017, month =>  3, day => 9);
206 my $invoice2 = create_sales_invoice(
207   invnumber    => "2 sales invoice",
208   customer     => $customer,
209   itime        => $march_9,
210   gldate       => $march_9,
211   intnotes     => 'booked in March',
212   taxincluded  => 0,
213   transdate    => $date,
214   invoiceitems => [ create_invoice_item(part => $part1, qty =>  6, sellprice => 70),
215                     create_invoice_item(part => $part2, qty => 20, sellprice => 50),
216                   ]
217 );
218
219 my $credit_note = create_credit_note(
220   invnumber    => 'Gutschrift 34',
221   customer     => $customer,
222   itime        => $gldate,
223   gldate       => $gldate,
224   intnotes     => 'booked in February',
225   taxincluded  => 0,
226   transdate    => $date,
227   invoiceitems => [ create_invoice_item(part => $part1, qty =>  3, sellprice => 70),
228                     create_invoice_item(part => $part2, qty => 10, sellprice => 50),
229                   ]
230 );
231
232 my $datev = SL::DATEV->new(
233   dbh        => $dbh,
234   from       => $startdate,
235   to         => $enddate,
236 );
237 $datev->generate_datev_data(from_to => $datev->fromto);
238 my $datev_lines = $datev->generate_datev_lines;
239 my $umsatzsumme = sum map { $_->{umsatz} } @{ $datev_lines };
240 cmp_ok($::form->round_amount($umsatzsumme,2), '==', 3924.5, "Sum of all bookings ok");
241
242 $datev->generate_datev_data(use_pk => 1, from_to => $datev->fromto);
243 $datev_lines = $datev->generate_datev_lines;
244
245 note('testing purchase invoice');
246 my $purchase_invoice = create_ap_transaction(
247   vendor      => $vendor,
248   invnumber   => 'ap1',
249   amount      => '226',
250   netamount   => '200',
251   transdate   => $date,
252   gldate      => $date,
253   itime       => $date, # make sure itime is 1.1., as gldatefrom tests for itime!
254   taxincluded => 0,
255   bookings    => [
256                    {
257                      chart  => SL::DB::Manager::Chart->find_by(accno => '3400'),
258                      amount => 100,
259                    },
260                    {
261                      chart  => SL::DB::Manager::Chart->find_by(accno => '3300'),
262                      amount => 100,
263                    },
264                  ],
265 );
266
267 $datev1 = SL::DATEV->new(
268   dbh        => $purchase_invoice->db->dbh,
269   trans_id   => $purchase_invoice->id,
270 );
271
272 $datev1->generate_datev_data;
273 cmp_deeply $datev1->generate_datev_lines, [
274                                         {
275                                           'belegfeld1'             => 'ap1',
276                                           'buchungstext'           => 'Testvendor',
277                                           'datum'                  => '01.01.2017',
278                                           'gegenkonto'             => '1600',
279                                           'konto'                  => '3400',
280                                           'kost1'                  => undef,
281                                           'kost2'                  => undef,
282                                           'umsatz'                 => 119,
283                                           'waehrung'               => 'EUR'
284                                         },
285                                         {
286                                           'belegfeld1'             => 'ap1',
287                                           'buchungstext'           => 'Testvendor',
288                                           'datum'                  => '01.01.2017',
289                                           'gegenkonto'             => '1600',
290                                           'konto'                  => '3300',
291                                           'kost1'                  => undef,
292                                           'kost2'                  => undef,
293                                           'umsatz'                 => 107,
294                                           'waehrung'               => 'EUR'
295                                         }
296                                        ], "trans_id datev check purchase_invoice ok";
297 $datev1->use_pk(1);
298 $datev1->generate_datev_data;
299 cmp_deeply $datev1->generate_datev_lines, [
300                                         {
301                                           'belegfeld1'             => 'ap1',
302                                           'buchungstext'           => 'Testvendor',
303                                           'datum'                  => '01.01.2017',
304                                           'gegenkonto'             => $vendor->vendornumber,
305                                           'konto'                  => '3400',
306                                           'kost1'                  => undef,
307                                           'kost2'                  => undef,
308                                           'umsatz'                 => 119,
309                                           'waehrung'               => 'EUR'
310                                         },
311                                         {
312                                           'belegfeld1'             => 'ap1',
313                                           'buchungstext'           => 'Testvendor',
314                                           'datum'                  => '01.01.2017',
315                                           'gegenkonto'             => $vendor->vendornumber,
316                                           'konto'                  => '3300',
317                                           'kost1'                  => undef,
318                                           'kost2'                  => undef,
319                                           'umsatz'                 => 107,
320                                           'waehrung'               => 'EUR'
321                                         }
322                                        ], "trans_id datev check purchase_invoice use_pk ok";
323
324 note('testing gldatefrom');
325 # test an order with transdate in january, but that was booked in march
326 # gldatefrom in DATEV.pm checks for itime, not gldate!!!
327 $datev = SL::DATEV->new(
328   dbh        => $dbh,
329   from       => $startdate,
330   to         => DateTime->new(year => 2017, month => 01, day => 31),
331 );
332
333 $::form               = Support::TestSetup->create_new_form;
334 $::form->{gldatefrom} = DateTime->new(year => 2017, month => 3, day => 1)->to_kivitendo;
335
336 $datev->generate_datev_data(from_to => $datev->fromto);
337 $datev_lines = $datev->generate_datev_lines;
338 $umsatzsumme = sum map { $_->{umsatz} } @{ $datev_lines };
339 cmp_ok($umsatzsumme, '==', 1569.8, "Sum of bookings made after March 1st (only invoice2) ok");
340
341 $::form->{gldatefrom} = DateTime->new(year => 2017, month => 5, day => 1)->to_kivitendo;
342 $datev->generate_datev_data(from_to => $datev->fromto);
343 cmp_deeply $datev->generate_datev_lines, [], "no bookings for January made after May 1st: ok";
344
345 done_testing();
346 clear_up();
347
348 sub clear_up {
349   SL::DB::Manager::AccTransaction->delete_all(all => 1);
350   SL::DB::Manager::InvoiceItem->delete_all(   all => 1);
351   SL::DB::Manager::Invoice->delete_all(       all => 1);
352   SL::DB::Manager::PurchaseInvoice->delete_all(all => 1);
353   SL::DB::Manager::Customer->delete_all(      all => 1);
354   SL::DB::Manager::Part->delete_all(          all => 1);
355   SL::DB::Manager::Project->delete_all(       all => 1);
356   SL::DB::Manager::Department->delete_all(    all => 1);
357   SL::DATEV->clean_temporary_directories;
358 };
359
360 1;