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",
92 'buchungstext' => 'Testcustomer',
93 'buchungstext' => 'Testcustomer',
94 'datum' => '05.01.2017',
95 'gegenkonto' => '1400',
97 'kost1' => 'Kostenstelle DATEV-Schnittstelle 2018',
98 'kost2' => 'Crowd-Funding September 2017',
102 ], "trans_id datev check ok";
105 $datev1->generate_datev_data;
106 # TODO for cmp_deeply we need to sort the incoming data structure (see below)
107 cmp_bag $datev1->generate_datev_lines, [
109 'belegfeld1' => "\x{de} sales \x{a5}& inv\x{f6}ice",
110 'buchungstext' => 'Testcustomer',
111 'datum' => '01.01.2017',
112 'gegenkonto' => '8400',
113 'konto' => $customer->customernumber,
114 'kost1' => 'Kostenstelle DATEV-Schnittstelle 2018',
115 'kost2' => 'Crowd-Funding September 2017',
120 'belegfeld1' => "\x{de} sales \x{a5}& inv\x{f6}ice",
121 'buchungstext' => 'Testcustomer',
122 'datum' => '01.01.2017',
123 'gegenkonto' => '8300',
124 'konto' => $customer->customernumber,
125 'kost1' => 'Kostenstelle DATEV-Schnittstelle 2018',
126 'kost2' => 'Crowd-Funding September 2017',
131 'belegfeld1' => "\x{de} sales \x{a5}& inv\x{f6}ice",
132 'buchungstext' => 'Testcustomer',
133 'datum' => '05.01.2017',
134 'gegenkonto' => $customer->customernumber,
136 'kost1' => 'Kostenstelle DATEV-Schnittstelle 2018',
137 'kost2' => 'Crowd-Funding September 2017',
141 ], "trans_id datev check use_pk ok";
144 my $startdate = DateTime->new(year => 2017, month => 1, day => 1);
145 my $enddate = DateTime->new(year => 2017, month => 12, day => 31);
147 # check conversion to csv
148 $datev1->from($startdate);
149 $datev1->to($enddate);
150 # reset use_pk for csv_buchungsexport
152 $datev1->generate_datev_data;
155 my $datev_csv = SL::DATEV::CSV->new(datev_lines => $datev1->generate_datev_lines,
158 locked => $datev1->locked,
163 # we need sort, because pay_invoice is not acc_trans_id order safe
164 my @data_csv = sort { $a->[0] cmp $b->[0] } @{ $datev_csv->lines };
165 # warnings should be undef -> no array elements at all
166 is(scalar @{ $datev_csv->warnings }, 0);
169 cmp_deeply($data_csv[1], [ '535', 'S', 'EUR', '', '', '', '1400', '8300', '', '0101', "\x{de} sales \x{a5}& i",
170 '', '', 'Testcustomer', '', '', '', '', '', '', '', '',
171 '', '', '', '', '', '', '', '', '', '', '', '', '',
172 '', 'Kostenst', 'Crowd-Fu', '', '', '', '', '', '', '', '',
173 '', '', '', '', '', '', '', '', '', '', '', '', '',
174 '', '', '', '', '', '', '', '', '', '', '', '', '',
175 '', '', '', '', '', '', '', '', '', '', '', '', '',
176 '', '', '', '', '', '', '', '', '', '', '', '', '',
177 '', '', '', '', '', '', '', '', '', '', '', '', '',
181 cmp_deeply($data_csv[0], [ '249,9', 'S', 'EUR', '', '', '', '1400', '8400', '', '0101', "\x{de} sales \x{a5}& i",
182 '', '', 'Testcustomer', '', '', '', '', '', '', '', '',
183 '', '', '', '', '', '', '', '', '', '', '', '', '',
184 '', 'Kostenst', 'Crowd-Fu', '', '', '', '', '', '', '', '',
185 '', '', '', '', '', '', '', '', '', '', '', '', '',
186 '', '', '', '', '', '', '', '', '', '', '', '', '',
187 '', '', '', '', '', '', '', '', '', '', '', '', '',
188 '', '', '', '', '', '', '', '', '', '', '', '', '',
189 '', '', '', '', '', '', '', '', '', '', '', '', '',
192 cmp_deeply($data_csv[2], [ '784,9', 'S', 'EUR', '', '', '', '1200', '1400', '', '0501', "\x{de} sales \x{a5}& i",
193 '', '', 'Testcustomer', '', '', '', '', '', '', '', '',
194 '', '', '', '', '', '', '', '', '', '', '', '', '',
195 '', 'Kostenst', 'Crowd-Fu', '', '', '', '', '', '', '', '',
196 '', '', '', '', '', '', '', '', '', '', '', '', '',
197 '', '', '', '', '', '', '', '', '', '', '', '', '',
198 '', '', '', '', '', '', '', '', '', '', '', '', '',
199 '', '', '', '', '', '', '', '', '', '', '', '', '',
200 '', '', '', '', '', '', '', '', '', '', '', '', '',
203 my $march_9 = DateTime->new(year => 2017, month => 3, day => 9);
204 my $invoice2 = create_sales_invoice(
205 invnumber => "2 sales invoice",
206 customer => $customer,
209 intnotes => 'booked in March',
212 invoiceitems => [ create_invoice_item(part => $part1, qty => 6, sellprice => 70),
213 create_invoice_item(part => $part2, qty => 20, sellprice => 50),
217 my $credit_note = create_credit_note(
218 invnumber => 'Gutschrift 34',
219 customer => $customer,
222 intnotes => 'booked in February',
225 invoiceitems => [ create_invoice_item(part => $part1, qty => 3, sellprice => 70),
226 create_invoice_item(part => $part2, qty => 10, sellprice => 50),
230 my $datev = SL::DATEV->new(
235 $datev->generate_datev_data(from_to => $datev->fromto);
236 my $datev_lines = $datev->generate_datev_lines;
237 my $umsatzsumme = sum map { $_->{umsatz} } @{ $datev_lines };
238 cmp_ok($::form->round_amount($umsatzsumme,2), '==', 3924.5, "Sum of all bookings ok");
240 $datev->generate_datev_data(use_pk => 1, from_to => $datev->fromto);
241 $datev_lines = $datev->generate_datev_lines;
243 note('testing purchase invoice');
244 my $purchase_invoice = create_ap_transaction(
251 itime => $date, # make sure itime is 1.1., as gldatefrom tests for itime!
255 chart => SL::DB::Manager::Chart->find_by(accno => '3400'),
259 chart => SL::DB::Manager::Chart->find_by(accno => '3300'),
265 $datev1 = SL::DATEV->new(
266 dbh => $purchase_invoice->db->dbh,
267 trans_id => $purchase_invoice->id,
270 $datev1->generate_datev_data;
271 cmp_deeply $datev1->generate_datev_lines, [
273 'belegfeld1' => 'ap1',
274 'buchungstext' => 'Testvendor',
275 'datum' => '01.01.2017',
276 'gegenkonto' => '1600',
284 'belegfeld1' => 'ap1',
285 'buchungstext' => 'Testvendor',
286 'datum' => '01.01.2017',
287 'gegenkonto' => '1600',
294 ], "trans_id datev check purchase_invoice ok";
296 $datev1->generate_datev_data;
297 cmp_deeply $datev1->generate_datev_lines, [
299 'belegfeld1' => 'ap1',
300 'buchungstext' => 'Testvendor',
301 'datum' => '01.01.2017',
302 'gegenkonto' => $vendor->vendornumber,
310 'belegfeld1' => 'ap1',
311 'buchungstext' => 'Testvendor',
312 'datum' => '01.01.2017',
313 'gegenkonto' => $vendor->vendornumber,
320 ], "trans_id datev check purchase_invoice use_pk ok";
322 note('testing gldatefrom');
323 # test an order with transdate in january, but that was booked in march
324 # gldatefrom in DATEV.pm checks for itime, not gldate!!!
325 $datev = SL::DATEV->new(
328 to => DateTime->new(year => 2017, month => 01, day => 31),
331 $::form = Support::TestSetup->create_new_form;
332 $::form->{gldatefrom} = DateTime->new(year => 2017, month => 3, day => 1)->to_kivitendo;
334 $datev->generate_datev_data(from_to => $datev->fromto);
335 $datev_lines = $datev->generate_datev_lines;
336 $umsatzsumme = sum map { $_->{umsatz} } @{ $datev_lines };
337 cmp_ok($umsatzsumme, '==', 1569.8, "Sum of bookings made after March 1st (only invoice2) ok");
339 $::form->{gldatefrom} = DateTime->new(year => 2017, month => 5, day => 1)->to_kivitendo;
340 $datev->generate_datev_data(from_to => $datev->fromto);
341 cmp_deeply $datev->generate_datev_lines, [], "no bookings for January made after May 1st: ok";
347 SL::DB::Manager::AccTransaction->delete_all(all => 1);
348 SL::DB::Manager::InvoiceItem->delete_all( all => 1);
349 SL::DB::Manager::Invoice->delete_all( all => 1);
350 SL::DB::Manager::PurchaseInvoice->delete_all(all => 1);
351 SL::DB::Manager::Customer->delete_all( all => 1);
352 SL::DB::Manager::Part->delete_all( all => 1);
353 SL::DB::Manager::Project->delete_all( all => 1);
354 SL::DB::Manager::Department->delete_all( all => 1);
355 SL::DATEV->clean_temporary_directories;