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 '', '', '', '', '', '', '', '', '', '', '',
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 '', '', '', '', '', '', '', '', '', '', '',
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 '', '', '', '', '', '', '', '', '', '', '',
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 = new_purchase_invoice();
247 $datev1 = SL::DATEV->new(
248 dbh => $purchase_invoice->db->dbh,
249 trans_id => $purchase_invoice->id,
252 $datev1->generate_datev_data;
253 cmp_deeply $datev1->generate_datev_lines, [
255 'belegfeld1' => 'ap1',
256 'buchungstext' => 'Testvendor',
257 'datum' => '01.01.2017',
258 'gegenkonto' => '1600',
266 'belegfeld1' => 'ap1',
267 'buchungstext' => 'Testvendor',
268 'datum' => '01.01.2017',
269 'gegenkonto' => '1600',
276 ], "trans_id datev check purchase_invoice ok";
278 $datev1->generate_datev_data;
279 cmp_deeply $datev1->generate_datev_lines, [
281 'belegfeld1' => 'ap1',
282 'buchungstext' => 'Testvendor',
283 'datum' => '01.01.2017',
284 'gegenkonto' => $vendor->vendornumber,
292 'belegfeld1' => 'ap1',
293 'buchungstext' => 'Testvendor',
294 'datum' => '01.01.2017',
295 'gegenkonto' => $vendor->vendornumber,
302 ], "trans_id datev check purchase_invoice use_pk ok";
304 note('testing gldatefrom');
305 $datev = SL::DATEV->new(
308 to => DateTime->new(year => 2017, month => 01, day => 31),
311 $::form = Support::TestSetup->create_new_form;
312 $::form->{gldatefrom} = DateTime->new(year => 2017, month => 3, day => 1)->to_kivitendo;
314 $datev->generate_datev_data(from_to => $datev->fromto);
315 $datev_lines = $datev->generate_datev_lines;
316 $umsatzsumme = sum map { $_->{umsatz} } @{ $datev_lines };
317 cmp_ok($umsatzsumme, '==', 1569.8, "Sum of bookings made after March 1st (only invoice2) ok");
319 $::form->{gldatefrom} = DateTime->new(year => 2017, month => 5, day => 1)->to_kivitendo;
320 $datev->generate_datev_data(from_to => $datev->fromto);
321 cmp_deeply $datev->generate_datev_lines, [], "no bookings for January made after May 1st: ok";
326 sub new_purchase_invoice {
327 # manually create a Kreditorenbuchung from scratch, ap + acc_trans bookings, as no helper exists yet, like $invoice->post.
328 # arap-Booking must come last in the acc_trans order
329 # this function was essentially copied from t/db_helper/payment.t, refactor once $purchase_invoice->post exists
330 my $currency_id = $::instance_conf->get_currency_id;
331 my $employee = SL::DB::Manager::Employee->current || die "No employee";
332 my $taxzone = SL::DB::Manager::TaxZone->find_by( description => 'Inland') || die "No taxzone";
334 my $purchase_invoice = SL::DB::PurchaseInvoice->new(
336 currency_id => $currency_id,
337 employee_id => $employee->id,
346 taxzone_id => $taxzone->id,
349 vendor_id => $vendor->id,
352 my $expense_chart = SL::DB::Manager::Chart->find_by(accno => '3400');
353 my $expense_chart_booking= SL::DB::AccTransaction->new(
355 chart_id => $expense_chart->id,
356 chart_link => $expense_chart->link,
360 tax_id => SL::DB::Manager::Tax->find_by(taxkey => 9)->id,
363 trans_id => $purchase_invoice->id,
365 $expense_chart_booking->save;
367 my $tax_chart = SL::DB::Manager::Chart->find_by(accno => '1576');
368 my $tax_chart_booking= SL::DB::AccTransaction->new(
370 chart_id => $tax_chart->id,
371 chart_link => $tax_chart->link,
375 tax_id => SL::DB::Manager::Tax->find_by(taxkey => 9)->id,
378 trans_id => $purchase_invoice->id,
380 $tax_chart_booking->save;
381 $expense_chart = SL::DB::Manager::Chart->find_by(accno => '3300');
382 $expense_chart_booking= SL::DB::AccTransaction->new(
384 chart_id => $expense_chart->id,
385 chart_link => $expense_chart->link,
389 tax_id => SL::DB::Manager::Tax->find_by(taxkey => 8)->id,
392 trans_id => $purchase_invoice->id,
394 $expense_chart_booking->save;
396 $tax_chart = SL::DB::Manager::Chart->find_by(accno => '1571');
397 $tax_chart_booking= SL::DB::AccTransaction->new(
398 trans_id => $purchase_invoice->id,
399 chart_id => $tax_chart->id,
400 chart_link => $tax_chart->link,
407 tax_id => SL::DB::Manager::Tax->find_by(taxkey => 8)->id,
409 $tax_chart_booking->save;
410 my $arap_chart = SL::DB::Manager::Chart->find_by(accno => '1600');
411 my $arap_booking= SL::DB::AccTransaction->new(
412 trans_id => $purchase_invoice->id,
413 chart_id => $arap_chart->id,
414 chart_link => $arap_chart->link,
421 tax_id => SL::DB::Manager::Tax->find_by(taxkey => 0)->id,
425 return $purchase_invoice;
429 SL::DB::Manager::AccTransaction->delete_all(all => 1);
430 SL::DB::Manager::InvoiceItem->delete_all( all => 1);
431 SL::DB::Manager::Invoice->delete_all( all => 1);
432 SL::DB::Manager::PurchaseInvoice->delete_all(all => 1);
433 SL::DB::Manager::Customer->delete_all( all => 1);
434 SL::DB::Manager::Part->delete_all( all => 1);
435 SL::DB::Manager::Project->delete_all( all => 1);
436 SL::DB::Manager::Department->delete_all( all => 1);
437 SL::DATEV->clean_temporary_directories;