3 use Test::Deep qw(cmp_deeply cmp_bag);
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;
16 Support::TestSetup::login();
20 my $dbh = SL::DB->client->dbh;
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;
32 my $part1 = new_part(partnumber => '19', description => 'Part 19%')->save;
35 description => 'Part 7%',
36 buchungsgruppen_id => $buchungsgruppe7->id,
39 my $invoice = create_sales_invoice(
40 invnumber => "Þ sales ¥& invöice",
41 customer => $customer,
44 intnotes => 'booked in February',
47 invoiceitems => [ create_invoice_item(part => $part1, qty => 3, sellprice => 70),
48 create_invoice_item(part => $part2, qty => 10, sellprice => 50),
50 department_id => $department->id,
51 globalproject_id => $project->id,
53 $invoice->pay_invoice(chart_id => $bank->id,
54 amount => $invoice->open_amount,
55 transdate => $payment_date->to_kivitendo,
59 my $datev1 = SL::DATEV->new(
60 dbh => $invoice->db->dbh,
61 trans_id => $invoice->id,
64 $datev1->generate_datev_data;
66 my @data_datev = sort { $a->{umsatz} <=> $b->{umsatz} } @{ $datev1->generate_datev_lines() };
67 cmp_deeply \@data_datev, [
69 'belegfeld1' => "\x{de} sales \x{a5}& inv\x{f6}ice",
70 'buchungstext' => 'Testcustomer',
71 'datum' => '01.01.2017',
72 'gegenkonto' => '8400',
74 'kost1' => 'Kostenstelle DATEV-Schnittstelle 2018',
75 'kost2' => 'Crowd-Funding September 2017',
80 'belegfeld1' => "\x{de} sales \x{a5}& inv\x{f6}ice",
81 'buchungstext' => 'Testcustomer',
82 'datum' => '01.01.2017',
83 'gegenkonto' => '8300',
85 'kost1' => 'Kostenstelle DATEV-Schnittstelle 2018',
86 'kost2' => 'Crowd-Funding September 2017',
91 'belegfeld1' => "\x{de} sales \x{a5}& inv\x{f6}ice",
94 'buchungstext' => 'Testcustomer',
95 'buchungstext' => 'Testcustomer',
96 'datum' => '05.01.2017',
97 'gegenkonto' => '1400',
99 'kost1' => 'Kostenstelle DATEV-Schnittstelle 2018',
100 'kost2' => 'Crowd-Funding September 2017',
104 ], "trans_id datev check ok";
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, [
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',
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',
133 'belegfeld1' => "\x{de} sales \x{a5}& inv\x{f6}ice",
134 'buchungstext' => 'Testcustomer',
135 'datum' => '05.01.2017',
136 'gegenkonto' => $customer->customernumber,
138 'kost1' => 'Kostenstelle DATEV-Schnittstelle 2018',
139 'kost2' => 'Crowd-Funding September 2017',
143 ], "trans_id datev check use_pk ok";
146 my $startdate = DateTime->new(year => 2017, month => 1, day => 1);
147 my $enddate = DateTime->new(year => 2017, month => 12, day => 31);
149 # check conversion to csv
150 $datev1->from($startdate);
151 $datev1->to($enddate);
152 # reset use_pk for csv_buchungsexport
154 $datev1->generate_datev_data;
157 my $datev_csv = SL::DATEV::CSV->new(datev_lines => $datev1->generate_datev_lines,
160 locked => $datev1->locked,
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);
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 '', '', '', '', '', '', '', '', '', '', '', '', '',
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 '', '', '', '', '', '', '', '', '', '', '', '', '',
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 '', '', '', '', '', '', '', '', '', '', '', '', '',
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,
211 intnotes => 'booked in March',
214 invoiceitems => [ create_invoice_item(part => $part1, qty => 6, sellprice => 70),
215 create_invoice_item(part => $part2, qty => 20, sellprice => 50),
219 my $credit_note = create_credit_note(
220 invnumber => 'Gutschrift 34',
221 customer => $customer,
224 intnotes => 'booked in February',
227 invoiceitems => [ create_invoice_item(part => $part1, qty => 3, sellprice => 70),
228 create_invoice_item(part => $part2, qty => 10, sellprice => 50),
232 my $datev = SL::DATEV->new(
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");
242 $datev->generate_datev_data(use_pk => 1, from_to => $datev->fromto);
243 $datev_lines = $datev->generate_datev_lines;
245 note('testing purchase invoice');
246 my $purchase_invoice = create_ap_transaction(
253 itime => $date, # make sure itime is 1.1., as gldatefrom tests for itime!
257 chart => SL::DB::Manager::Chart->find_by(accno => '3400'),
261 chart => SL::DB::Manager::Chart->find_by(accno => '3300'),
267 $datev1 = SL::DATEV->new(
268 dbh => $purchase_invoice->db->dbh,
269 trans_id => $purchase_invoice->id,
272 $datev1->generate_datev_data;
273 cmp_deeply $datev1->generate_datev_lines, [
275 'belegfeld1' => 'ap1',
276 'buchungstext' => 'Testvendor',
277 'datum' => '01.01.2017',
278 'gegenkonto' => '1600',
286 'belegfeld1' => 'ap1',
287 'buchungstext' => 'Testvendor',
288 'datum' => '01.01.2017',
289 'gegenkonto' => '1600',
296 ], "trans_id datev check purchase_invoice ok";
298 $datev1->generate_datev_data;
299 cmp_deeply $datev1->generate_datev_lines, [
301 'belegfeld1' => 'ap1',
302 'buchungstext' => 'Testvendor',
303 'datum' => '01.01.2017',
304 'gegenkonto' => $vendor->vendornumber,
312 'belegfeld1' => 'ap1',
313 'buchungstext' => 'Testvendor',
314 'datum' => '01.01.2017',
315 'gegenkonto' => $vendor->vendornumber,
322 ], "trans_id datev check purchase_invoice use_pk ok";
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(
330 to => DateTime->new(year => 2017, month => 01, day => 31),
333 $::form = Support::TestSetup->create_new_form;
334 $::form->{gldatefrom} = DateTime->new(year => 2017, month => 3, day => 1)->to_kivitendo;
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");
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";
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;