3 use Test::Deep qw(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_bag \@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',
78 'soll_haben_kennzeichen' => 'S',
81 'belegfeld1' => "\x{de} sales \x{a5}& inv\x{f6}ice",
82 'buchungstext' => 'Testcustomer',
83 'datum' => '01.01.2017',
84 'gegenkonto' => '8300',
86 'kost1' => 'Kostenstelle DATEV-Schnittstelle 2018',
87 'kost2' => 'Crowd-Funding September 2017',
90 'soll_haben_kennzeichen' => 'S',
93 'belegfeld1' => "\x{de} sales \x{a5}& inv\x{f6}ice",
96 'buchungstext' => 'Testcustomer',
97 'buchungstext' => 'Testcustomer',
98 'datum' => '05.01.2017',
99 'gegenkonto' => '1400',
101 'kost1' => 'Kostenstelle DATEV-Schnittstelle 2018',
102 'kost2' => 'Crowd-Funding September 2017',
105 'soll_haben_kennzeichen' => 'S',
107 ], "trans_id datev check ok";
110 $datev1->generate_datev_data;
111 cmp_bag $datev1->generate_datev_lines, [
113 'belegfeld1' => "\x{de} sales \x{a5}& inv\x{f6}ice",
114 'buchungstext' => 'Testcustomer',
115 'datum' => '01.01.2017',
116 'gegenkonto' => '8400',
117 'konto' => $customer->customernumber,
118 'kost1' => 'Kostenstelle DATEV-Schnittstelle 2018',
119 'kost2' => 'Crowd-Funding September 2017',
122 'soll_haben_kennzeichen' => 'S',
125 'belegfeld1' => "\x{de} sales \x{a5}& inv\x{f6}ice",
126 'buchungstext' => 'Testcustomer',
127 'datum' => '01.01.2017',
128 'gegenkonto' => '8300',
129 'konto' => $customer->customernumber,
130 'kost1' => 'Kostenstelle DATEV-Schnittstelle 2018',
131 'kost2' => 'Crowd-Funding September 2017',
134 'soll_haben_kennzeichen' => 'S',
137 'belegfeld1' => "\x{de} sales \x{a5}& inv\x{f6}ice",
138 'buchungstext' => 'Testcustomer',
139 'datum' => '05.01.2017',
140 'gegenkonto' => $customer->customernumber,
142 'kost1' => 'Kostenstelle DATEV-Schnittstelle 2018',
143 'kost2' => 'Crowd-Funding September 2017',
146 'soll_haben_kennzeichen' => 'S',
148 ], "trans_id datev check use_pk ok";
151 my $startdate = DateTime->new(year => 2017, month => 1, day => 1);
152 my $enddate = DateTime->new(year => 2017, month => 12, day => 31);
154 # check conversion to csv
155 $datev1->from($startdate);
156 $datev1->to($enddate);
157 # reset use_pk for csv_buchungsexport
159 $datev1->generate_datev_data;
162 my ($datev_ref, $w_ref) = SL::DATEV::CSV->new(datev_lines => $datev1->generate_datev_lines,
165 locked => $datev1->locked,
167 # warnings should be undef -> no array elements at all
168 is(scalar @{ $w_ref }, 0);
170 # splice away the header, because sort won't do
171 # we need sort, because pay_invoice is not acc_trans_id order safe
172 my @data_csv = splice @{ $datev_ref }, 2, 5;
173 @data_csv = sort { $a->[0] cmp $b->[0] } @data_csv;
175 my $cp1252_belegfeld1 = SL::Iconv::convert("UTF-8", "CP1252", 'Þ sales ¥& i');
176 my $cp1252_buchungstext = SL::Iconv::convert("UTF-8", "CP1252", 'Þ sales ¥& invöice');
178 cmp_bag($data_csv[1], [ 535, 'S', 'EUR', undef, undef, undef, '1400', '8300', undef, '0101', $cp1252_belegfeld1,
179 undef, undef, $cp1252_buchungstext, undef, undef, undef, undef, undef, undef, undef, undef,
180 undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef,
181 undef, 'Crowd-Fu', 'Kostenst', undef, undef, undef, undef, undef, undef, undef, undef,
182 undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef,
183 undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef,
184 undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef,
185 undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef,
186 undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef,
187 undef, undef, undef, undef, undef ]
190 cmp_bag($data_csv[0], [ '249,9', 'S', 'EUR', undef, undef, undef, '1400', '8400', undef, '0101', $cp1252_belegfeld1,
191 undef, undef, $cp1252_buchungstext, undef, undef, undef, undef, undef, undef, undef, undef,
192 undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef,
193 undef, 'Crowd-Fu', 'Kostenst', undef, undef, undef, undef, undef, undef, undef, undef,
194 undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef,
195 undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef,
196 undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef,
197 undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef,
198 undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef,
199 undef, undef, undef, undef, undef ]
201 cmp_bag($data_csv[2], [ '784,9', 'S', 'EUR', undef, undef, undef, '1200', '1400', undef, '0501', $cp1252_belegfeld1,
202 undef, undef, $cp1252_buchungstext, undef, undef, undef, undef, undef, undef, undef, undef,
203 undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef,
204 undef, 'Crowd-Fu', 'Kostenst', undef, undef, undef, undef, undef, undef, undef, undef,
205 undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef,
206 undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef,
207 undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef,
208 undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef,
209 undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef,
210 undef, undef, undef, undef, undef ]
212 my $march_9 = DateTime->new(year => 2017, month => 3, day => 9);
213 my $invoice2 = create_sales_invoice(
214 invnumber => "2 sales invoice",
215 customer => $customer,
218 intnotes => 'booked in March',
221 invoiceitems => [ create_invoice_item(part => $part1, qty => 6, sellprice => 70),
222 create_invoice_item(part => $part2, qty => 20, sellprice => 50),
226 my $credit_note = create_credit_note(
227 invnumber => 'Gutschrift 34',
228 customer => $customer,
231 intnotes => 'booked in February',
234 invoiceitems => [ create_invoice_item(part => $part1, qty => 3, sellprice => 70),
235 create_invoice_item(part => $part2, qty => 10, sellprice => 50),
239 my $datev = SL::DATEV->new(
244 $datev->generate_datev_data(from_to => $datev->fromto);
245 my $datev_lines = $datev->generate_datev_lines;
246 my $umsatzsumme = sum map { $_->{umsatz} } @{ $datev_lines };
247 cmp_ok($::form->round_amount($umsatzsumme,2), '==', 3924.5, "Sum of all bookings ok");
249 $datev->generate_datev_data(use_pk => 1, from_to => $datev->fromto);
250 $datev_lines = $datev->generate_datev_lines;
252 note('testing purchase invoice');
253 my $purchase_invoice = new_purchase_invoice();
254 $datev1 = SL::DATEV->new(
255 dbh => $purchase_invoice->db->dbh,
256 trans_id => $purchase_invoice->id,
259 $datev1->generate_datev_data;
260 cmp_bag $datev1->generate_datev_lines, [
262 'belegfeld1' => 'ap1',
263 'buchungstext' => 'Testvendor',
264 'datum' => '01.01.2017',
265 'gegenkonto' => '1600',
269 'soll_haben_kennzeichen' => 'H',
274 'belegfeld1' => 'ap1',
275 'buchungstext' => 'Testvendor',
276 'datum' => '01.01.2017',
277 'gegenkonto' => '1600',
281 'soll_haben_kennzeichen' => 'H',
285 ], "trans_id datev check purchase_invoice ok";
287 $datev1->generate_datev_data;
288 cmp_bag $datev1->generate_datev_lines, [
290 'belegfeld1' => 'ap1',
291 'buchungstext' => 'Testvendor',
292 'datum' => '01.01.2017',
293 'gegenkonto' => $vendor->vendornumber,
297 'soll_haben_kennzeichen' => 'H',
302 'belegfeld1' => 'ap1',
303 'buchungstext' => 'Testvendor',
304 'datum' => '01.01.2017',
305 'gegenkonto' => $vendor->vendornumber,
309 'soll_haben_kennzeichen' => 'H',
313 ], "trans_id datev check purchase_invoice use_pk ok";
315 note('testing gldatefrom');
316 $datev = SL::DATEV->new(
319 to => DateTime->new(year => 2017, month => 01, day => 31),
322 $::form = Support::TestSetup->create_new_form;
323 $::form->{gldatefrom} = DateTime->new(year => 2017, month => 3, day => 1)->to_kivitendo;
325 $datev->generate_datev_data(from_to => $datev->fromto);
326 $datev_lines = $datev->generate_datev_lines;
327 $umsatzsumme = sum map { $_->{umsatz} } @{ $datev_lines };
328 cmp_ok($umsatzsumme, '==', 1569.8, "Sum of bookings made after March 1st (only invoice2) ok");
330 $::form->{gldatefrom} = DateTime->new(year => 2017, month => 5, day => 1)->to_kivitendo;
331 $datev->generate_datev_data(from_to => $datev->fromto);
332 cmp_bag $datev->generate_datev_lines, [], "no bookings for January made after May 1st: ok";
337 sub new_purchase_invoice {
338 # manually create a Kreditorenbuchung from scratch, ap + acc_trans bookings, as no helper exists yet, like $invoice->post.
339 # arap-Booking must come last in the acc_trans order
340 # this function was essentially copied from t/db_helper/payment.t, refactor once $purchase_invoice->post exists
341 my $currency_id = $::instance_conf->get_currency_id;
342 my $employee = SL::DB::Manager::Employee->current || die "No employee";
343 my $taxzone = SL::DB::Manager::TaxZone->find_by( description => 'Inland') || die "No taxzone";
345 my $purchase_invoice = SL::DB::PurchaseInvoice->new(
347 currency_id => $currency_id,
348 employee_id => $employee->id,
357 taxzone_id => $taxzone->id,
360 vendor_id => $vendor->id,
363 my $expense_chart = SL::DB::Manager::Chart->find_by(accno => '3400');
364 my $expense_chart_booking= SL::DB::AccTransaction->new(
366 chart_id => $expense_chart->id,
367 chart_link => $expense_chart->link,
371 tax_id => SL::DB::Manager::Tax->find_by(taxkey => 9)->id,
374 trans_id => $purchase_invoice->id,
376 $expense_chart_booking->save;
378 my $tax_chart = SL::DB::Manager::Chart->find_by(accno => '1576');
379 my $tax_chart_booking= SL::DB::AccTransaction->new(
381 chart_id => $tax_chart->id,
382 chart_link => $tax_chart->link,
386 tax_id => SL::DB::Manager::Tax->find_by(taxkey => 9)->id,
389 trans_id => $purchase_invoice->id,
391 $tax_chart_booking->save;
392 $expense_chart = SL::DB::Manager::Chart->find_by(accno => '3300');
393 $expense_chart_booking= SL::DB::AccTransaction->new(
395 chart_id => $expense_chart->id,
396 chart_link => $expense_chart->link,
400 tax_id => SL::DB::Manager::Tax->find_by(taxkey => 8)->id,
403 trans_id => $purchase_invoice->id,
405 $expense_chart_booking->save;
407 $tax_chart = SL::DB::Manager::Chart->find_by(accno => '1571');
408 $tax_chart_booking= SL::DB::AccTransaction->new(
409 trans_id => $purchase_invoice->id,
410 chart_id => $tax_chart->id,
411 chart_link => $tax_chart->link,
418 tax_id => SL::DB::Manager::Tax->find_by(taxkey => 8)->id,
420 $tax_chart_booking->save;
421 my $arap_chart = SL::DB::Manager::Chart->find_by(accno => '1600');
422 my $arap_booking= SL::DB::AccTransaction->new(
423 trans_id => $purchase_invoice->id,
424 chart_id => $arap_chart->id,
425 chart_link => $arap_chart->link,
432 tax_id => SL::DB::Manager::Tax->find_by(taxkey => 0)->id,
436 return $purchase_invoice;
440 SL::DB::Manager::AccTransaction->delete_all(all => 1);
441 SL::DB::Manager::InvoiceItem->delete_all( all => 1);
442 SL::DB::Manager::Invoice->delete_all( all => 1);
443 SL::DB::Manager::PurchaseInvoice->delete_all(all => 1);
444 SL::DB::Manager::Customer->delete_all( all => 1);
445 SL::DB::Manager::Part->delete_all( all => 1);
446 SL::DB::Manager::Project->delete_all( all => 1);
447 SL::DB::Manager::Department->delete_all( all => 1);
448 SL::DATEV->clean_temporary_directories;