Revision eb0c10b0
Von Moritz Bunkus vor mehr als 15 Jahren hinzugefügt
SL/AccTransCorrections.pm | ||
---|---|---|
1 |
package AccTransCorrections; |
|
2 |
|
|
3 |
use strict; |
|
4 |
|
|
5 |
use List::Util qw(first); |
|
6 |
|
|
7 |
use SL::DBUtils; |
|
8 |
use SL::Taxkeys; |
|
9 |
|
|
10 |
sub new { |
|
11 |
my $type = shift; |
|
12 |
|
|
13 |
my $self = {}; |
|
14 |
|
|
15 |
bless $self, $type; |
|
16 |
|
|
17 |
$self->{taxkeys} = Taxkeys->new(); |
|
18 |
|
|
19 |
return $self; |
|
20 |
} |
|
21 |
|
|
22 |
sub _fetch_transactions { |
|
23 |
$main::lxdebug->enter_sub(); |
|
24 |
|
|
25 |
my $self = shift; |
|
26 |
my %params = @_; |
|
27 |
|
|
28 |
my $myconfig = \%main::myconfig; |
|
29 |
my $form = $main::form; |
|
30 |
|
|
31 |
my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig); |
|
32 |
|
|
33 |
my (@where, @values) = ((), ()); |
|
34 |
|
|
35 |
if ($params{transdate_from}) { |
|
36 |
push @where, qq|at.transdate >= ?|; |
|
37 |
push @values, $params{transdate_from}; |
|
38 |
} |
|
39 |
|
|
40 |
if ($params{transdate_to}) { |
|
41 |
push @where, qq|at.transdate <= ?|; |
|
42 |
push @values, $params{transdate_to}; |
|
43 |
} |
|
44 |
# $params{trans_id} = 3150; |
|
45 |
if ($params{trans_id}) { |
|
46 |
push @where, qq|at.trans_id = ?|; |
|
47 |
push @values, $params{trans_id}; |
|
48 |
} |
|
49 |
|
|
50 |
my $where = ''; |
|
51 |
if (scalar @where) { |
|
52 |
$where = 'WHERE ' . join(' AND ', map { "($_)" } @where); |
|
53 |
} |
|
54 |
|
|
55 |
my $query = qq! |
|
56 |
SELECT at.oid, at.*, |
|
57 |
c.accno, c.description AS chartdescription, c.charttype, c.category AS chartcategory, c.link AS chartlink, |
|
58 |
COALESCE(gl.reference, COALESCE(ap.invnumber, ar.invnumber)) AS reference, |
|
59 |
COALESCE(ap.invoice, COALESCE(ar.invoice, FALSE)) AS invoice, |
|
60 |
CASE |
|
61 |
WHEN gl.id IS NOT NULL THEN gl.storno AND (gl.storno_id IS NOT NULL) |
|
62 |
WHEN ap.id IS NOT NULL THEN ap.storno AND (ap.storno_id IS NOT NULL) |
|
63 |
ELSE ar.storno AND (ar.storno_id IS NOT NULL) |
|
64 |
END AS is_storno, |
|
65 |
CASE |
|
66 |
WHEN gl.id IS NOT NULL THEN 'gl' |
|
67 |
WHEN ap.id IS NOT NULL THEN 'ap' |
|
68 |
ELSE 'ar' |
|
69 |
END AS module |
|
70 |
|
|
71 |
FROM acc_trans at |
|
72 |
LEFT JOIN chart c ON (at.chart_id = c.id) |
|
73 |
LEFT JOIN gl ON (at.trans_id = gl.id) |
|
74 |
LEFT JOIN ap ON (at.trans_id = ap.id) |
|
75 |
LEFT JOIN ar ON (at.trans_id = ar.id) |
|
76 |
$where |
|
77 |
ORDER BY at.trans_id, at.oid |
|
78 |
!; |
|
79 |
|
|
80 |
my @transactions = (); |
|
81 |
my $last_trans = undef; |
|
82 |
|
|
83 |
foreach my $entry (@{ selectall_hashref_query($form, $dbh, $query, @values) }) { |
|
84 |
if (!$last_trans || ($last_trans->[0]->{trans_id} != $entry->{trans_id})) { |
|
85 |
$last_trans = []; |
|
86 |
push @transactions, $last_trans; |
|
87 |
} |
|
88 |
|
|
89 |
push @{ $last_trans }, $entry; |
|
90 |
} |
|
91 |
|
|
92 |
$main::lxdebug->leave_sub(); |
|
93 |
|
|
94 |
return @transactions; |
|
95 |
} |
|
96 |
|
|
97 |
sub _prepare_data { |
|
98 |
$main::lxdebug->enter_sub(); |
|
99 |
|
|
100 |
my $self = shift; |
|
101 |
my %params = @_; |
|
102 |
|
|
103 |
my $transaction = $params{transaction}; |
|
104 |
my $callback = $params{callback}; |
|
105 |
|
|
106 |
my $myconfig = \%main::myconfig; |
|
107 |
my $form = $main::form; |
|
108 |
|
|
109 |
my $data = { |
|
110 |
'credit' => { |
|
111 |
'num' => 0, |
|
112 |
'sum' => 0, |
|
113 |
'entries' => [], |
|
114 |
'tax_sum' => 0, |
|
115 |
'tax_entries' => [], |
|
116 |
}, |
|
117 |
'debit' => { |
|
118 |
'num' => 0, |
|
119 |
'sum' => 0, |
|
120 |
'entries' => [], |
|
121 |
'tax_sum' => 0, |
|
122 |
'tax_entries' => [], |
|
123 |
}, |
|
124 |
'payments' => [], |
|
125 |
}; |
|
126 |
|
|
127 |
foreach my $entry (@{ $transaction }) { |
|
128 |
$entry->{chartlinks} = { map { $_ => 1 } split(m/:/, $entry->{chartlink}) }; |
|
129 |
delete $entry->{chartlink}; |
|
130 |
} |
|
131 |
|
|
132 |
# Verkn?pfungen zwischen Steuerschl?sseln und zum Zeitpunkt der Transaktion |
|
133 |
# g?ltigen Steuers?tze |
|
134 |
my %all_taxes = $self->{taxkeys}->get_full_tax_info('transdate' => $transaction->[0]->{transdate}); |
|
135 |
|
|
136 |
my ($trans_type, $previous_non_tax_entry); |
|
137 |
my $sum = 0; |
|
138 |
my $first_sub_trans = 1; |
|
139 |
|
|
140 |
my $storno_mult = $transaction->[0]->{is_storno} ? -1 : 1; |
|
141 |
|
|
142 |
# Aufteilung der Buchungspositionen in Soll-, Habenseite sowie |
|
143 |
# getrennte Auflistung der Positionen, die auf Steuerkonten gebucht werden. |
|
144 |
foreach my $entry (@{ $transaction }) { |
|
145 |
if (!$first_sub_trans && ($entry->{chartlinks}->{AP_paid} || $entry->{chartlinks}->{AR_paid})) { |
|
146 |
push @{ $data->{payments} }, $entry; |
|
147 |
next; |
|
148 |
} |
|
149 |
|
|
150 |
my $tax_info = $all_taxes{taxkeys}->{ $entry->{taxkey} }; |
|
151 |
if ($tax_info) { |
|
152 |
$entry->{taxdescription} = $tax_info->{taxdescription} . ' ' . $form->format_amount($myconfig, $tax_info->{taxrate} * 100) . ' %'; |
|
153 |
} |
|
154 |
|
|
155 |
if ($entry->{chartlinks}->{AP}) { |
|
156 |
$trans_type = 'AP'; |
|
157 |
} elsif ($entry->{chartlinks}->{AR}) { |
|
158 |
$trans_type = 'AR'; |
|
159 |
} |
|
160 |
|
|
161 |
my $idx = 0 < ($entry->{amount} * $storno_mult) ? 'credit' : 'debit'; |
|
162 |
|
|
163 |
if ($entry->{chartlinks}->{AP_tax} || $entry->{chartlinks}->{AR_tax}) { |
|
164 |
$data->{$idx}->{tax_sum} += $entry->{amount}; |
|
165 |
push @{ $data->{$idx}->{tax_entries} }, $entry; |
|
166 |
|
|
167 |
if ($previous_non_tax_entry) { |
|
168 |
$previous_non_tax_entry->{tax_entry} = $entry; |
|
169 |
undef $previous_non_tax_entry; |
|
170 |
} |
|
171 |
|
|
172 |
} else { |
|
173 |
$data->{$idx}->{sum} += $entry->{amount}; |
|
174 |
push @{ $data->{$idx}->{entries} }, $entry; |
|
175 |
|
|
176 |
$previous_non_tax_entry = $entry; |
|
177 |
} |
|
178 |
|
|
179 |
$sum += $entry->{amount}; |
|
180 |
|
|
181 |
if (abs($sum) < 0.02) { |
|
182 |
$sum = 0; |
|
183 |
$first_sub_trans = 0; |
|
184 |
} |
|
185 |
} |
|
186 |
|
|
187 |
# Alle Eintr?ge entfernen, die die Gegenkonten zu Zahlungsein- und |
|
188 |
# -ausg?ngen darstellen. |
|
189 |
foreach my $payment (@{ $data->{payments} }) { |
|
190 |
my $idx = 0 < $payment->{amount} ? 'debit' : 'credit'; |
|
191 |
|
|
192 |
foreach my $i (0 .. scalar(@{ $data->{$idx}->{entries} }) - 1) { |
|
193 |
my $entry = $data->{$idx}->{entries}->[$i]; |
|
194 |
|
|
195 |
next if ((($payment->{amount} * -1) != $entry->{amount}) || ($payment->{transdate} ne $entry->{transdate})); |
|
196 |
|
|
197 |
splice @{ $data->{$idx}->{entries} }, $i, 1; |
|
198 |
|
|
199 |
last; |
|
200 |
} |
|
201 |
} |
|
202 |
|
|
203 |
delete $data->{payments}; |
|
204 |
|
|
205 |
map { $data->{$_}->{num} = scalar @{ $data->{$_}->{entries} } } qw(credit debit); |
|
206 |
|
|
207 |
my $info = $transaction->[0]; |
|
208 |
my $script = ($info->{module} eq 'ar') && $info->{invoice} ? 'is' |
|
209 |
: ($info->{module} eq 'ap') && $info->{invoice} ? 'ir' |
|
210 |
: $info->{module}; |
|
211 |
|
|
212 |
my %common_args = ( |
|
213 |
'data' => $data, |
|
214 |
'trans_type' => $trans_type, |
|
215 |
'all_taxes' => { %all_taxes }, |
|
216 |
'transaction' => $transaction, |
|
217 |
'full_analysis' => $params{full_analysis}, |
|
218 |
'problem' => { |
|
219 |
'data' => $info, |
|
220 |
'link' => $script . ".pl?action=edit${callback}&id=" . $info->{trans_id}, |
|
221 |
}, |
|
222 |
); |
|
223 |
|
|
224 |
$main::lxdebug->leave_sub(); |
|
225 |
|
|
226 |
return %common_args; |
|
227 |
} |
|
228 |
|
|
229 |
sub _group_sub_transactions { |
|
230 |
$main::lxdebug->enter_sub(); |
|
231 |
|
|
232 |
my $self = shift; |
|
233 |
my $transaction = shift; |
|
234 |
|
|
235 |
my @sub_transactions = (); |
|
236 |
my $sum = 0; |
|
237 |
|
|
238 |
foreach my $i (0 .. scalar(@{ $transaction }) - 1) { |
|
239 |
my $entry = $transaction->[$i]; |
|
240 |
|
|
241 |
if (abs($sum) <= 0.01) { |
|
242 |
push @sub_transactions, []; |
|
243 |
$sum = 0; |
|
244 |
} |
|
245 |
$sum += $entry->{amount}; |
|
246 |
|
|
247 |
push @{ $sub_transactions[-1] }, $entry; |
|
248 |
} |
|
249 |
|
|
250 |
$main::lxdebug->leave_sub(); |
|
251 |
|
|
252 |
return @sub_transactions; |
|
253 |
} |
|
254 |
|
|
255 |
# Problemfall: Verkaufsrechnungen, bei denen Buchungen auf Warenbestandskonten |
|
256 |
# mit Steuerschl?ssel != 0 durchgef?hrt wurden. Richtig w?re, dass alle |
|
257 |
# Steuerschl?ssel f?r solche Warenbestandsbuchungen 0 sind. |
|
258 |
sub _check_trans_invoices_inventory_with_taxkeys { |
|
259 |
$main::lxdebug->enter_sub(); |
|
260 |
|
|
261 |
my $self = shift; |
|
262 |
my %params = @_; |
|
263 |
|
|
264 |
if (!$params{transaction}->[0]->{invoice}) { |
|
265 |
$main::lxdebug->leave_sub(); |
|
266 |
return 0; |
|
267 |
} |
|
268 |
|
|
269 |
my @sub_transactions = $self->_group_sub_transactions($params{transaction}); |
|
270 |
|
|
271 |
foreach my $sub_transaction (@sub_transactions) { |
|
272 |
my $is_cogs = first { $_->{chartlinks}->{IC_cogs} } @{ $sub_transaction }; |
|
273 |
next unless ($is_cogs); |
|
274 |
|
|
275 |
my $needs_fixing = first { $_->{taxkey} != 0 } @{ $sub_transaction }; |
|
276 |
next unless ($needs_fixing); |
|
277 |
|
|
278 |
$params{problem}->{type} = 'invoice_inventory_with_taxkeys'; |
|
279 |
push @{ $self->{invoice_inventory_taxkey_problems} }, $params{problem}; |
|
280 |
|
|
281 |
$main::lxdebug->leave_sub(); |
|
282 |
|
|
283 |
return 1; |
|
284 |
} |
|
285 |
|
|
286 |
$main::lxdebug->leave_sub(); |
|
287 |
|
|
288 |
return 0; |
|
289 |
} |
|
290 |
|
|
291 |
# Problemfall: Kreditorenbuchungen, bei denen mit Umsatzsteuerschl?sseln |
|
292 |
# gebucht wurde und Debitorenbuchungen, bei denen mit Vorsteuerschl?sseln |
|
293 |
# gebucht wurde. |
|
294 |
sub _check_trans_ap_ar_wrong_taxkeys { |
|
295 |
$main::lxdebug->enter_sub(); |
|
296 |
|
|
297 |
my $self = shift; |
|
298 |
my %params = @_; |
|
299 |
|
|
300 |
my $retval = 0; |
|
301 |
|
|
302 |
if (!$params{transaction}->[0]->{invoice} |
|
303 |
&& (( ($params{transaction}->[0]->{module} eq 'ap') |
|
304 |
&& (first { my $taxkey = $_->{taxkey}; first { $taxkey == $_ } (2, 3, 12, 13) } @{ $params{transaction} })) |
|
305 |
|| |
|
306 |
( ($params{transaction}->[0]->{module} eq 'ar') |
|
307 |
&& (first { my $taxkey = $_->{taxkey}; first { $taxkey == $_ } (8, 9, 18, 19) } @{ $params{transaction} })))) { |
|
308 |
$params{problem}->{type} = 'ap_ar_wrong_taxkeys'; |
|
309 |
push @{ $self->{ap_ar_taxkey_problems} }, $params{problem}; |
|
310 |
|
|
311 |
$retval = 1; |
|
312 |
} |
|
313 |
|
|
314 |
$main::lxdebug->leave_sub(); |
|
315 |
|
|
316 |
return $retval; |
|
317 |
} |
|
318 |
|
|
319 |
# Problemfall: Splitbuchungen, die mehrere Haben- und Sollkonten ansprechen. |
|
320 |
# Aber nur f?r Debitoren- und Kreditorenbuchungen, weil das bei Einkaufs- und |
|
321 |
# Verkaufsrechnungen hingegen v?llig normal ist. |
|
322 |
sub _check_trans_split_multiple_credit_and_debit { |
|
323 |
$main::lxdebug->enter_sub(); |
|
324 |
|
|
325 |
my $self = shift; |
|
326 |
my %params = @_; |
|
327 |
|
|
328 |
my $retval = 0; |
|
329 |
|
|
330 |
if ( !$params{transaction}->[0]->{invoice} |
|
331 |
&& (1 < $params{data}->{credit}->{num}) |
|
332 |
&& (1 < $params{data}->{debit}->{num})) { |
|
333 |
$params{problem}->{type} = 'split_multiple_credit_and_debit'; |
|
334 |
push @{ $self->{problems} }, $params{problem}; |
|
335 |
|
|
336 |
$retval = 1; |
|
337 |
} |
|
338 |
|
|
339 |
$main::lxdebug->leave_sub(); |
|
340 |
|
|
341 |
return $retval; |
|
342 |
} |
|
343 |
|
|
344 |
# Problemfall: Buchungen, bei denen Steuersummen nicht mit den Summen |
|
345 |
# ?bereinstimmen, die nach ausgew?hltem Steuerschl?ssel h?tten auftreten m?ssen. |
|
346 |
sub _check_trans_wrong_taxkeys { |
|
347 |
$main::lxdebug->enter_sub(); |
|
348 |
|
|
349 |
my $self = shift; |
|
350 |
my %params = @_; |
|
351 |
|
|
352 |
my $form = $main::form; |
|
353 |
|
|
354 |
my %data = %{ $params{data} }; |
|
355 |
my $transaction = $params{transaction}; |
|
356 |
|
|
357 |
if ( $transaction->[0]->{invoice} |
|
358 |
|| $transaction->[0]->{ob_transaction} |
|
359 |
|| $transaction->[0]->{cb_transaction} |
|
360 |
|| (!scalar @{ $data{credit}->{entries} } && !scalar @{ $data{debit}->{entries} }) |
|
361 |
|| ( ($transaction->[0]->{module} eq 'gl') |
|
362 |
&& (!scalar @{ $data{credit}->{entries} } || !scalar @{ $data{debit}->{entries} }))) { |
|
363 |
$main::lxdebug->leave_sub(); |
|
364 |
return 0; |
|
365 |
} |
|
366 |
|
|
367 |
my $retval = 0; |
|
368 |
|
|
369 |
my ($side, $other_side); |
|
370 |
if ( (grep { $_->{taxkey} * 1 } @{ $data{credit}->{entries} }) |
|
371 |
|| (scalar @{ $data{credit}->{tax_entries} })) { |
|
372 |
$side = 'credit'; |
|
373 |
$other_side = 'debit'; |
|
374 |
|
|
375 |
} elsif ( (grep { $_->{taxkey} * 1 } @{ $data{debit}->{entries} }) |
|
376 |
|| (scalar @{ $data{debit}->{tax_entries} })) { |
|
377 |
$side = 'debit'; |
|
378 |
$other_side = 'credit'; |
|
379 |
} |
|
380 |
|
|
381 |
if (!$side) { |
|
382 |
$main::lxdebug->leave_sub(); |
|
383 |
return 0; |
|
384 |
} |
|
385 |
|
|
386 |
my $expected_tax = 0; |
|
387 |
my %num_entries_per_chart = (); |
|
388 |
my $num_taxed_entries = 0; |
|
389 |
|
|
390 |
foreach my $entry (@{ $data{$side}->{entries} }) { |
|
391 |
my $taxinfo = $params{all_taxes}->{taxkeys}->{$entry->{taxkey}} || { }; |
|
392 |
$entry->{expected_tax} = $entry->{amount} * $taxinfo->{taxrate}; |
|
393 |
$expected_tax += $entry->{expected_tax}; |
|
394 |
|
|
395 |
$num_taxed_entries++ if ($taxinfo->{taxrate} * 1); |
|
396 |
|
|
397 |
my $chart_key = $entry->{chart_id} . "-" . $entry->{taxkey}; |
|
398 |
$num_entries_per_chart{$chart_key} ||= 0; |
|
399 |
$num_entries_per_chart{$chart_key}++; |
|
400 |
} |
|
401 |
|
|
402 |
# $main::lxdebug->message(0, "side $side trans_id $transaction->[0]->{trans_id} expected tax $expected_tax actual tax $data{$side}->{tax_sum}"); |
|
403 |
|
|
404 |
if (abs($expected_tax - $data{$side}->{tax_sum}) >= (0.01 * ($num_taxed_entries + 1))) { |
|
405 |
if ($params{full_analysis}) { |
|
406 |
my $storno_mult = $data{$side}->{entries}->[0]->{is_storno} ? -1 : 1; |
|
407 |
|
|
408 |
foreach my $entry (@{ $data{$other_side}->{entries} }) { |
|
409 |
$entry->{display_amount} = $form->round_amount(abs($entry->{amount}) * $storno_mult, 2); |
|
410 |
} |
|
411 |
|
|
412 |
foreach my $entry (@{ $data{$side}->{entries} }) { |
|
413 |
$entry->{actual_tax} = $form->round_amount(abs($entry->{tax_entry} ? $entry->{tax_entry}->{amount} : 0), 2); |
|
414 |
$entry->{expected_tax} = $form->round_amount(abs($entry->{expected_tax}), 2); |
|
415 |
$entry->{taxkey_error} = ( $entry->{taxkey} && !$entry->{tax_entry}) |
|
416 |
|| (!$entry->{taxkey} && $entry->{tax_entry}) |
|
417 |
|| (abs($entry->{expected_tax} - $entry->{actual_tax}) >= 0.02); |
|
418 |
$entry->{tax_entry_oid} = $entry->{tax_entry}->{oid}; |
|
419 |
delete $entry->{tax_entry}; |
|
420 |
|
|
421 |
$entry->{display_amount} = $form->round_amount(abs($entry->{amount}) * $storno_mult, 2); |
|
422 |
$entry->{display_actual_tax} = $entry->{actual_tax} * $storno_mult; |
|
423 |
$entry->{display_expected_tax} = $entry->{expected_tax} * $storno_mult; |
|
424 |
|
|
425 |
if ($entry->{taxkey_error}) { |
|
426 |
$self->{negative_taxkey_filter} ||= { |
|
427 |
'ar' => { map { $_ => 1 } ( 8, 9, 18, 19) }, |
|
428 |
'ap' => { map { $_ => 1 } (1, 2, 3, 12, 13) }, |
|
429 |
'gl' => { }, |
|
430 |
}; |
|
431 |
|
|
432 |
$entry->{correct_taxkeys} = []; |
|
433 |
|
|
434 |
my %all_taxes = $self->{taxkeys}->get_full_tax_info('transdate' => $entry->{transdate}); |
|
435 |
|
|
436 |
foreach my $taxkey (sort { $a <=> $b } keys %{ $all_taxes{taxkeys} }) { |
|
437 |
next if ($self->{negative_taxkey_filter}->{ $entry->{module} }->{$taxkey}); |
|
438 |
|
|
439 |
my $tax_info = $all_taxes{taxkeys}->{$taxkey}; |
|
440 |
|
|
441 |
next if ((!$tax_info || (0 == $tax_info->{taxrate} * 1)) && $entry->{tax_entry_oid}); |
|
442 |
|
|
443 |
push @{ $entry->{correct_taxkeys} }, { |
|
444 |
'taxkey' => $taxkey, |
|
445 |
'tax' => $form->round_amount(abs($entry->{amount}) * $tax_info->{taxrate}, 2), |
|
446 |
'description' => sprintf("%s %d%%", $tax_info->{taxdescription}, int($tax_info->{taxrate} * 100)), |
|
447 |
}; |
|
448 |
} |
|
449 |
} |
|
450 |
} |
|
451 |
} |
|
452 |
|
|
453 |
if (first { $_ > 1 } values %num_entries_per_chart) { |
|
454 |
$params{problem}->{type} = 'wrong_taxkeys'; |
|
455 |
} else { |
|
456 |
$params{problem}->{type} = 'wrong_taxes'; |
|
457 |
} |
|
458 |
|
|
459 |
$params{problem}->{acc_trans} = { %data }; |
|
460 |
push @{ $self->{problems} }, $params{problem}; |
|
461 |
|
|
462 |
$retval = 1; |
|
463 |
} |
|
464 |
|
|
465 |
$main::lxdebug->leave_sub(); |
|
466 |
|
|
467 |
return $retval; |
|
468 |
} |
|
469 |
|
|
470 |
# Inaktiver Code f?r das Erraten m?glicher Verteilungen von |
|
471 |
# Steuerschl?sseln. Deaktiviert, weil er exponentiell Zeit |
|
472 |
# ben?tigt. |
|
473 |
|
|
474 |
# if (abs($expected_tax - $data{$side}->{tax_sum}) >= 0.02) { |
|
475 |
# my @potential_taxkeys = $trans_type eq 'AP' ? (0, 8, 9) : (0, 1, 2, 3); |
|
476 |
|
|
477 |
# $main::lxdebug->dump(0, "pota", \@potential_taxkeys); |
|
478 |
|
|
479 |
# # ?ber alle Kombinationen aus Buchungss?tzen und potenziellen Steuerschl?sseln |
|
480 |
# # iterieren und jeweils die Summe ermitteln. |
|
481 |
# my $num_entries = scalar @{ $data{$side}->{entries} }; |
|
482 |
# my @taxkey_indices = (0) x $num_entries; |
|
483 |
|
|
484 |
# my @solutions = (); |
|
485 |
|
|
486 |
# my $start_time = time(); |
|
487 |
|
|
488 |
# $main::lxdebug->message(0, "num_entries $num_entries"); |
|
489 |
|
|
490 |
# while ($num_entries == scalar @taxkey_indices) { |
|
491 |
# my @tax_cache = (); |
|
492 |
|
|
493 |
# # Berechnen der Steuersumme f?r die aktuell angenommenen Steuerschl?ssel. |
|
494 |
# my $tax_sum = 0; |
|
495 |
# foreach my $i (0 .. $num_entries - 1) { |
|
496 |
# my $taxkey = $potential_taxkeys[$taxkey_indices[$i]]; |
|
497 |
# my $entry = $data{$side}->{entries}->[$i]; |
|
498 |
# my $taxinfo = $all_taxes{taxkeys}->{ $taxkey } || { }; |
|
499 |
# $tax_cache[$i] = $entry->{amount} * $taxinfo->{taxrate}; |
|
500 |
# $tax_sum += $tax_cache[$i]; |
|
501 |
# } |
|
502 |
|
|
503 |
# # Entspricht die Steuersumme mit den aktuell angenommenen Steuerschl?sseln |
|
504 |
# # der verbuchten Steuersumme? Wenn ja, dann ist das eine potenzielle |
|
505 |
# # L?sung. |
|
506 |
# if (abs($tax_sum - $data{$side}->{tax_sum}) < 0.02) { |
|
507 |
# push @solutions, { |
|
508 |
# 'taxkeys' => [ @potential_taxkeys[@taxkey_indices] ], |
|
509 |
# 'taxes' => [ @tax_cache ], |
|
510 |
# } |
|
511 |
# } |
|
512 |
|
|
513 |
# # Weiterz?hlen der Steuerschl?sselindices zum Interieren ?ber |
|
514 |
# # alle m?glichen Kombinationen. |
|
515 |
# my $i = 0; |
|
516 |
# while (1) { |
|
517 |
# $taxkey_indices[$i]++; |
|
518 |
# last if ($taxkey_indices[$i] < scalar @potential_taxkeys); |
|
519 |
|
|
520 |
# $taxkey_indices[$i] = 0; |
|
521 |
# $i++; |
|
522 |
# } |
|
523 |
|
|
524 |
# my $now = time(); |
|
525 |
# if (($now - $start_time) >= 5) { |
|
526 |
# $main::lxdebug->message(0, " " . join("", @taxkey_indices)); |
|
527 |
# $start_time = $now; |
|
528 |
# } |
|
529 |
# } |
|
530 |
|
|
531 |
# foreach my $solution (@solutions) { |
|
532 |
# $solution->{rows} = []; |
|
533 |
# $solution->{changes} = []; |
|
534 |
# my $error = 0; |
|
535 |
|
|
536 |
# foreach my $i (0 .. $num_entries - 1) { |
|
537 |
# if ($solution->{taxes}->[$i]) { |
|
538 |
# my $tax_rounded = $form->round_amount($solution->{taxes}->[$i] + $error, 2); |
|
539 |
# $error = $solution->{taxes}->[$i] + $error - $tax_rounded; |
|
540 |
# $solution->{taxes}->[$i] = $tax_rounded; |
|
541 |
# } |
|
542 |
|
|
543 |
# my $entry = $data{$side}->{entries}->[$i]; |
|
544 |
# my $tax_entry = $all_taxes{taxkeys}->{ $solution->{taxkeys}->[$i] }; |
|
545 |
|
|
546 |
# push @{ $solution->{rows} }, { |
|
547 |
# %{ $entry }, |
|
548 |
# %{ $tax_entry }, |
|
549 |
# 'taxamount' => $solution->{taxes}->[$i], |
|
550 |
# }; |
|
551 |
|
|
552 |
# $solution->{rows}->[$i]->{taxdescription} .= ' ' . $form->format_amount(\%myconfig, $tax_entry->{taxrate} * 100) . ' %'; |
|
553 |
|
|
554 |
# push @{ $solution->{changes} }, { |
|
555 |
# 'oid' => $entry->{oid}, |
|
556 |
# 'taxkey' => $solution->{taxkeys}->[$i], |
|
557 |
# }; |
|
558 |
# } |
|
559 |
|
|
560 |
# push @{ $solution->{rows} }, @{ $data{$other_side}->{entries} }; |
|
561 |
|
|
562 |
# delete @{ $solution }{ qw(taxes taxkeys) }; |
|
563 |
# } |
|
564 |
|
|
565 |
# $problem->{type} = 'wrong_taxkeys'; |
|
566 |
# $problem->{solutions} = [ @solutions ]; |
|
567 |
# $problem->{acc_trans} = { %data }; |
|
568 |
# push @problems, $problem; |
|
569 |
|
|
570 |
# next; |
|
571 |
# } |
|
572 |
|
|
573 |
sub analyze { |
|
574 |
$main::lxdebug->enter_sub(); |
|
575 |
|
|
576 |
my $self = shift; |
|
577 |
my %params = @_; |
|
578 |
|
|
579 |
my $myconfig = \%main::myconfig; |
|
580 |
my $form = $main::form; |
|
581 |
|
|
582 |
my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig); |
|
583 |
|
|
584 |
my @transactions = $self->_fetch_transactions(%params, 'dbh' => $dbh); |
|
585 |
|
|
586 |
if (!scalar @transactions) { |
|
587 |
$main::lxdebug->leave_sub(); |
|
588 |
return (); |
|
589 |
} |
|
590 |
|
|
591 |
my $callback = $params{callback} ? '&callback=' . $params{callback} : ''; |
|
592 |
|
|
593 |
$self->{problems} = []; |
|
594 |
$self->{ap_ar_taxkey_problems} = []; |
|
595 |
$self->{invoice_inventory_taxkey_problems} = []; |
|
596 |
|
|
597 |
foreach my $transaction (@transactions) { |
|
598 |
my %common_args = $self->_prepare_data('transaction' => $transaction, 'callback' => $callback, 'full_analysis' => $params{full_analysis}); |
|
599 |
|
|
600 |
next if ($self->_check_trans_ap_ar_wrong_taxkeys(%common_args)); |
|
601 |
next if ($self->_check_trans_invoices_inventory_with_taxkeys(%common_args)); |
|
602 |
next if ($self->_check_trans_split_multiple_credit_and_debit(%common_args)); |
|
603 |
next if ($self->_check_trans_wrong_taxkeys(%common_args)); |
|
604 |
} |
|
605 |
|
|
606 |
my @problems = @{ $self->{problems} }; |
|
607 |
|
|
608 |
if (0 != scalar @{ $self->{ap_ar_taxkey_problems} }) { |
|
609 |
my $problem = { |
|
610 |
'type' => 'ap_ar_wrong_taxkeys', |
|
611 |
'ap_problems' => [ grep { $_->{data}->{module} eq 'ap' } @{ $self->{ap_ar_taxkey_problems} } ], |
|
612 |
'ar_problems' => [ grep { $_->{data}->{module} eq 'ar' } @{ $self->{ap_ar_taxkey_problems} } ], |
|
613 |
}; |
|
614 |
unshift @problems, $problem; |
|
615 |
} |
|
616 |
|
|
617 |
if (0 != scalar @{ $self->{invoice_inventory_taxkey_problems} }) { |
|
618 |
my $problem = { |
|
619 |
'type' => 'invoice_inventory_with_taxkeys', |
|
620 |
'ap_problems' => [ grep { $_->{data}->{module} eq 'ap' } @{ $self->{invoice_inventory_taxkey_problems} } ], |
|
621 |
'ar_problems' => [ grep { $_->{data}->{module} eq 'ar' } @{ $self->{invoice_inventory_taxkey_problems} } ], |
|
622 |
}; |
|
623 |
unshift @problems, $problem; |
|
624 |
} |
|
625 |
|
|
626 |
$main::lxdebug->leave_sub(); |
|
627 |
|
|
628 |
|
|
629 |
return @problems; |
|
630 |
} |
|
631 |
|
|
632 |
sub fix_ap_ar_wrong_taxkeys { |
|
633 |
$main::lxdebug->enter_sub(); |
|
634 |
|
|
635 |
my $self = shift; |
|
636 |
my %params = @_; |
|
637 |
|
|
638 |
my $myconfig = \%main::myconfig; |
|
639 |
my $form = $main::form; |
|
640 |
|
|
641 |
my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig); |
|
642 |
|
|
643 |
my $query = qq|SELECT 'ap' AS module, |
|
644 |
at.oid, at.trans_id, at.chart_id, at.amount, at.taxkey, at.transdate, |
|
645 |
c.link |
|
646 |
FROM acc_trans at |
|
647 |
LEFT JOIN chart c ON (at.chart_id = c.id) |
|
648 |
WHERE (trans_id IN (SELECT id FROM ap WHERE NOT invoice)) |
|
649 |
AND (taxkey IN (2, 3, 12, 13)) |
|
650 |
|
|
651 |
UNION |
|
652 |
|
|
653 |
SELECT 'ar' AS module, |
|
654 |
at.oid, at.trans_id, at.chart_id, at.amount, at.taxkey, at.transdate, |
|
655 |
c.link |
|
656 |
FROM acc_trans at |
|
657 |
LEFT JOIN chart c ON (at.chart_id = c.id) |
|
658 |
WHERE (trans_id IN (SELECT id FROM ar WHERE NOT invoice)) |
|
659 |
AND (taxkey IN (8, 9, 18, 19)) |
|
660 |
|
|
661 |
ORDER BY trans_id, oid|; |
|
662 |
|
|
663 |
my $sth = prepare_execute_query($form, $dbh, $query); |
|
664 |
my @transactions; |
|
665 |
|
|
666 |
while (my $ref = $sth->fetchrow_hashref()) { |
|
667 |
if ((!scalar @transactions) || ($ref->{trans_id} != $transactions[-1]->[0]->{trans_id})) { |
|
668 |
push @transactions, []; |
|
669 |
} |
|
670 |
|
|
671 |
push @{ $transactions[-1] }, $ref; |
|
672 |
} |
|
673 |
|
|
674 |
$sth->finish(); |
|
675 |
|
|
676 |
@transactions = grep { (scalar(@transactions) % 2) == 0 } @transactions; |
|
677 |
|
|
678 |
my %taxkey_replacements = ( |
|
679 |
2 => 8, |
|
680 |
3 => 9, |
|
681 |
8 => 2, |
|
682 |
9 => 3, |
|
683 |
12 => 18, |
|
684 |
13 => 19, |
|
685 |
18 => 12, |
|
686 |
19 => 13, |
|
687 |
); |
|
688 |
|
|
689 |
my %bad_taxkeys = ( |
|
690 |
'ap' => { map { $_ => 1 } (2, 3, 12, 13) }, |
|
691 |
'ar' => { map { $_ => 1 } (8, 9, 18, 19) }, |
|
692 |
); |
|
693 |
|
|
694 |
my @corrections = (); |
|
695 |
|
|
696 |
foreach my $transaction (@transactions) { |
|
697 |
|
|
698 |
for (my $i = 0; $i < scalar @{ $transaction }; $i += 2) { |
|
699 |
my ($non_tax_idx, $tax_idx) = abs($transaction->[$i]->{amount}) > abs($transaction->[$i + 1]->{amount}) ? ($i, $i + 1) : ($i + 1, $i); |
|
700 |
my ($non_tax, $tax) = @{ $transaction }[$non_tax_idx, $tax_idx]; |
|
701 |
|
|
702 |
last if ($non_tax->{link} =~ m/(:?AP|AR)_tax(:?$|:)/); |
|
703 |
last if ($tax->{link} !~ m/(:?AP|AR)_tax(:?$|:)/); |
|
704 |
|
|
705 |
next if (!$bad_taxkeys{ $non_tax->{module} }->{ $non_tax->{taxkey} }); |
|
706 |
|
|
707 |
my %all_taxes = $self->{taxkeys}->get_full_tax_info('transdate' => $non_tax->{transdate}); |
|
708 |
|
|
709 |
push @corrections, ({ 'oid' => $non_tax->{oid}, |
|
710 |
'taxkey' => $taxkey_replacements{$non_tax->{taxkey}}, |
|
711 |
}, |
|
712 |
{ |
|
713 |
'oid' => $tax->{oid}, |
|
714 |
'taxkey' => $taxkey_replacements{$non_tax->{taxkey}}, |
|
715 |
'chart_id' => $all_taxes{taxkeys}->{ $taxkey_replacements{$non_tax->{taxkey}} }->{taxchart_id}, |
|
716 |
}); |
|
717 |
} |
|
718 |
} |
|
719 |
|
|
720 |
if (scalar @corrections) { |
|
721 |
my $q_taxkey_only = qq|UPDATE acc_trans SET taxkey = ? WHERE oid = ?|; |
|
722 |
my $h_taxkey_only = prepare_query($form, $dbh, $q_taxkey_only); |
|
723 |
|
|
724 |
my $q_taxkey_chart_id = qq|UPDATE acc_trans SET taxkey = ?, chart_id = ? WHERE oid = ?|; |
|
725 |
my $h_taxkey_chart_id = prepare_query($form, $dbh, $q_taxkey_chart_id); |
|
726 |
|
|
727 |
foreach my $entry (@corrections) { |
|
728 |
if ($entry->{chart_id}) { |
|
729 |
do_statement($form, $h_taxkey_chart_id, $q_taxkey_chart_id, $entry->{taxkey}, $entry->{chart_id}, $entry->{oid}); |
|
730 |
} else { |
|
731 |
do_statement($form, $h_taxkey_only, $q_taxkey_only, $entry->{taxkey}, $entry->{oid}); |
|
732 |
} |
|
733 |
} |
|
734 |
|
|
735 |
$h_taxkey_only->finish(); |
|
736 |
$h_taxkey_chart_id->finish(); |
|
737 |
|
|
738 |
$dbh->commit() unless ($params{dbh}); |
|
739 |
} |
|
740 |
|
|
741 |
$main::lxdebug->leave_sub(); |
|
742 |
} |
|
743 |
|
|
744 |
sub fix_invoice_inventory_with_taxkeys { |
|
745 |
$main::lxdebug->enter_sub(); |
|
746 |
|
|
747 |
my $self = shift; |
|
748 |
my %params = @_; |
|
749 |
|
|
750 |
my $myconfig = \%main::myconfig; |
|
751 |
my $form = $main::form; |
|
752 |
|
|
753 |
my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig); |
|
754 |
|
|
755 |
my $query = qq|SELECT at.oid, at.*, c.link |
|
756 |
FROM acc_trans at |
|
757 |
LEFT JOIN ar ON (at.trans_id = ar.id) |
|
758 |
LEFT JOIN chart c ON (at.chart_id = c.id) |
|
759 |
WHERE (ar.invoice) |
|
760 |
|
|
761 |
UNION |
|
762 |
|
|
763 |
SELECT at.oid, at.*, c.link |
|
764 |
FROM acc_trans at |
|
765 |
LEFT JOIN ap ON (at.trans_id = ap.id) |
|
766 |
LEFT JOIN chart c ON (at.chart_id = c.id) |
|
767 |
WHERE (ap.invoice) |
|
768 |
|
|
769 |
ORDER BY trans_id, oid|; |
|
770 |
|
|
771 |
my $sth = prepare_execute_query($form, $dbh, $query); |
|
772 |
my @transactions; |
|
773 |
|
|
774 |
while (my $ref = $sth->fetchrow_hashref()) { |
|
775 |
if ((!scalar @transactions) || ($ref->{trans_id} != $transactions[-1]->[0]->{trans_id})) { |
|
776 |
push @transactions, []; |
|
777 |
} |
|
778 |
|
|
779 |
push @{ $transactions[-1] }, $ref; |
|
780 |
} |
|
781 |
|
|
782 |
$sth->finish(); |
|
783 |
|
|
784 |
my @corrections = (); |
|
785 |
|
|
786 |
foreach my $transaction (@transactions) { |
|
787 |
my @sub_transactions = $self->_group_sub_transactions($transaction); |
|
788 |
|
|
789 |
foreach my $sub_transaction (@sub_transactions) { |
|
790 |
my $is_cogs = first { $_->{link} =~ m/IC_cogs/ } @{ $sub_transaction }; |
|
791 |
next unless ($is_cogs); |
|
792 |
|
|
793 |
foreach my $entry (@{ $sub_transaction }) { |
|
794 |
next if ($entry->{taxkey} == 0); |
|
795 |
push @corrections, $entry->{oid}; |
|
796 |
} |
|
797 |
} |
|
798 |
} |
|
799 |
|
|
800 |
if (@corrections) { |
|
801 |
$query = qq|UPDATE acc_trans SET taxkey = 0 WHERE oid = ?|; |
|
802 |
$sth = prepare_query($form, $dbh, $query); |
|
803 |
|
|
804 |
foreach my $oid (@corrections) { |
|
805 |
do_statement($form, $sth, $query, $oid); |
|
806 |
} |
|
807 |
|
|
808 |
$sth->finish(); |
|
809 |
|
|
810 |
$dbh->commit() unless ($params{dbh}); |
|
811 |
# $dbh->rollback(); |
|
812 |
} |
|
813 |
|
|
814 |
$main::lxdebug->leave_sub(); |
|
815 |
} |
|
816 |
|
|
817 |
sub fix_wrong_taxkeys { |
|
818 |
$main::lxdebug->enter_sub(); |
|
819 |
|
|
820 |
my $self = shift; |
|
821 |
my %params = @_; |
|
822 |
|
|
823 |
Common::check_params(\%params, qw(fixes)); |
|
824 |
|
|
825 |
my $myconfig = \%main::myconfig; |
|
826 |
my $form = $main::form; |
|
827 |
|
|
828 |
my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig); |
|
829 |
|
|
830 |
my $q_taxkey_only = qq|UPDATE acc_trans SET taxkey = ? WHERE oid = ?|; |
|
831 |
my $h_taxkey_only = prepare_query($form, $dbh, $q_taxkey_only); |
|
832 |
|
|
833 |
my $q_taxkey_chart = qq|UPDATE acc_trans SET taxkey = ?, chart_id = ? WHERE oid = ?|; |
|
834 |
my $h_taxkey_chart = prepare_query($form, $dbh, $q_taxkey_chart); |
|
835 |
|
|
836 |
my $q_transdate = qq|SELECT transdate FROM acc_trans WHERE oid = ?|; |
|
837 |
my $h_transdate = prepare_query($form, $dbh, $q_transdate); |
|
838 |
|
|
839 |
foreach my $fix (@{ $params{fixes} }) { |
|
840 |
next unless ($fix->{oid}); |
|
841 |
|
|
842 |
do_statement($form, $h_taxkey_only, $q_taxkey_only, conv_i($fix->{taxkey}), conv_i($fix->{oid})); |
|
843 |
|
|
844 |
next unless ($fix->{tax_entry_oid}); |
|
845 |
|
|
846 |
do_statement($form, $h_transdate, $q_transdate, conv_i($fix->{tax_entry_oid})); |
|
847 |
my ($transdate) = $h_transdate->fetchrow_array(); |
|
848 |
|
|
849 |
my %all_taxes = $self->{taxkeys}->get_full_tax_info('transdate' => $transdate); |
|
850 |
my $tax_info = $all_taxes{taxkeys}->{ $fix->{taxkey} }; |
|
851 |
|
|
852 |
next unless ($tax_info); |
|
853 |
|
|
854 |
do_statement($form, $h_taxkey_chart, $q_taxkey_chart, conv_i($fix->{taxkey}), conv_i($tax_info->{taxchart_id}), conv_i($fix->{tax_entry_oid})); |
|
855 |
} |
|
856 |
|
|
857 |
$h_taxkey_only->finish(); |
|
858 |
$h_taxkey_chart->finish(); |
|
859 |
$h_transdate->finish(); |
|
860 |
|
|
861 |
# $dbh->rollback(); |
|
862 |
$dbh->commit() unless ($params{dbh}); |
|
863 |
|
|
864 |
$main::lxdebug->leave_sub(); |
|
865 |
} |
|
866 |
|
|
867 |
sub delete_transaction { |
|
868 |
$main::lxdebug->enter_sub(); |
|
869 |
|
|
870 |
my $self = shift; |
|
871 |
my %params = @_; |
|
872 |
|
|
873 |
Common::check_params(\%params, qw(trans_id)); |
|
874 |
|
|
875 |
my $myconfig = \%main::myconfig; |
|
876 |
my $form = $main::form; |
|
877 |
|
|
878 |
my $dbh = $params{dbh} || $form->get_standard_dbh($myconfig); |
|
879 |
|
|
880 |
do_query($form, $dbh, qq|UPDATE ar SET storno_id = NULL WHERE storno_id = ?|, conv_i($params{trans_id})); |
|
881 |
do_query($form, $dbh, qq|UPDATE ap SET storno_id = NULL WHERE storno_id = ?|, conv_i($params{trans_id})); |
|
882 |
do_query($form, $dbh, qq|UPDATE gl SET storno_id = NULL WHERE storno_id = ?|, conv_i($params{trans_id})); |
|
883 |
|
|
884 |
do_query($form, $dbh, qq|DELETE FROM ar WHERE id = ?|, conv_i($params{trans_id})); |
|
885 |
do_query($form, $dbh, qq|DELETE FROM ap WHERE id = ?|, conv_i($params{trans_id})); |
|
886 |
do_query($form, $dbh, qq|DELETE FROM gl WHERE id = ?|, conv_i($params{trans_id})); |
|
887 |
do_query($form, $dbh, qq|DELETE FROM acc_trans WHERE trans_id = ?|, conv_i($params{trans_id})); |
|
888 |
|
|
889 |
# $dbh->rollback(); |
|
890 |
$dbh->commit() unless ($params{dbh}); |
|
891 |
|
|
892 |
$main::lxdebug->leave_sub(); |
|
893 |
} |
|
894 |
|
|
895 |
1; |
SL/Locale.pm | ||
---|---|---|
85 | 85 |
$self->{charset} = Common::DEFAULT_CHARSET; |
86 | 86 |
} |
87 | 87 |
|
88 |
my $db_charset = $main::dbcharset || Common::DEFAULT_CHARSET; |
|
88 |
my $db_charset = $main::dbcharset || Common::DEFAULT_CHARSET;
|
|
89 | 89 |
|
90 |
$self->{iconv} = Text::Iconv->new($self->{charset}, $db_charset); |
|
91 |
$self->{iconv_reverse} = Text::Iconv->new($db_charset, $self->{charset}); |
|
92 |
$self->{iconv_english} = Text::Iconv->new('ASCII', $db_charset); |
|
93 |
$self->{iconv_iso8859} = Text::Iconv->new('ISO-8859-15', $db_charset); |
|
90 |
$self->{iconv} = Text::Iconv->new($self->{charset}, $db_charset); |
|
91 |
$self->{iconv_reverse} = Text::Iconv->new($db_charset, $self->{charset}); |
|
92 |
$self->{iconv_english} = Text::Iconv->new('ASCII', $db_charset); |
|
93 |
$self->{iconv_iso8859} = Text::Iconv->new('ISO-8859-15', $db_charset); |
|
94 |
$self->{iconv_to_iso8859} = Text::Iconv->new($db_charset, 'ISO-8859-15'); |
|
94 | 95 |
|
95 | 96 |
$self->_read_special_chars_file($country); |
96 | 97 |
} |
SL/Taxkeys.pm | ||
---|---|---|
1 |
package Taxkeys; |
|
2 |
|
|
3 |
use strict; |
|
4 |
|
|
5 |
use Memoize; |
|
6 |
|
|
7 |
use SL::DBUtils; |
|
8 |
|
|
9 |
sub new { |
|
10 |
my $type = shift; |
|
11 |
|
|
12 |
my $self = {}; |
|
13 |
|
|
14 |
bless $self, $type; |
|
15 |
|
|
16 |
return $self->_init(); |
|
17 |
} |
|
18 |
|
|
19 |
sub DESTROY { |
|
20 |
my $self = shift; |
|
21 |
|
|
22 |
$self->_finish_statements(); |
|
23 |
} |
|
24 |
|
|
25 |
sub _init { |
|
26 |
my $self = shift; |
|
27 |
|
|
28 |
$self->{handles} = { }; |
|
29 |
$self->{queries} = { }; |
|
30 |
|
|
31 |
memoize 'get_tax_info'; |
|
32 |
memoize 'get_full_tax_info'; |
|
33 |
|
|
34 |
return $self; |
|
35 |
} |
|
36 |
|
|
37 |
sub _finish_statements { |
|
38 |
$main::lxdebug->enter_sub(); |
|
39 |
|
|
40 |
my $self = shift; |
|
41 |
|
|
42 |
foreach my $idx (keys %{ $self->{handles} }) { |
|
43 |
$self->{handles}->{$idx}->finish(); |
|
44 |
delete $self->{handles}->{$idx}; |
|
45 |
} |
|
46 |
|
|
47 |
$main::lxdebug->leave_sub(); |
|
48 |
} |
|
49 |
|
|
50 |
sub get_tax_info { |
|
51 |
$main::lxdebug->enter_sub(); |
|
52 |
|
|
53 |
my $self = shift; |
|
54 |
my %params = @_; |
|
55 |
|
|
56 |
Common::check_params(\%params, qw(transdate taxkey)); |
|
57 |
|
|
58 |
my $myconfig = \%main::myconfig; |
|
59 |
my $form = $main::form; |
|
60 |
|
|
61 |
if (!$self->{handles}->{get_tax_info}) { |
|
62 |
$self->{queries}->{get_tax_info} = qq| |
|
63 |
SELECT t.rate AS taxrate, t.taxnumber, t.taxdescription, t.chart_id AS taxchart_id, |
|
64 |
c.accno AS taxaccno, c.description AS taxaccount |
|
65 |
FROM taxkeys tk |
|
66 |
LEFT JOIN tax t ON (tk.tax_id = t.id) |
|
67 |
LEFT JOIN chart c ON (t.chart_id = c.id) |
|
68 |
WHERE tk.id = |
|
69 |
(SELECT id |
|
70 |
FROM taxkeys |
|
71 |
WHERE (taxkey_id = ?) |
|
72 |
AND (startdate <= ?) |
|
73 |
ORDER BY startdate DESC |
|
74 |
LIMIT 1) |
|
75 |
|; |
|
76 |
|
|
77 |
$self->{handles}->{get_tax_info} = prepare_query($form, $params{dbh} || $form->get_standard_dbh($myconfig), $self->{queries}->{get_tax_info}); |
|
78 |
} |
|
79 |
|
|
80 |
my $sth = $self->{handles}->{get_tax_info}; |
|
81 |
do_statement($form, $sth, $self->{queries}->{get_tax_info}, $params{taxkey}, $params{transdate}); |
|
82 |
|
|
83 |
my $ref = $sth->fetchrow_hashref() || { }; |
|
84 |
|
|
85 |
$main::lxdebug->leave_sub(); |
|
86 |
|
|
87 |
return $ref; |
|
88 |
} |
|
89 |
|
|
90 |
sub get_full_tax_info { |
|
91 |
$main::lxdebug->enter_sub(); |
|
92 |
|
|
93 |
my $self = shift; |
|
94 |
my %params = @_; |
|
95 |
|
|
96 |
Common::check_params(\%params, qw(transdate)); |
|
97 |
|
|
98 |
my $myconfig = \%main::myconfig; |
|
99 |
my $form = $main::form; |
|
100 |
|
|
101 |
my %tax_info = ( |
|
102 |
'taxkeys' => { }, |
|
103 |
'taxchart_ids' => { }, |
|
104 |
); |
|
105 |
|
|
106 |
my @all_taxkeys = map { $_->{taxkey} } (selectall_hashref_query($form, $form->get_standard_dbh(), qq|SELECT DISTINCT taxkey FROM tax WHERE taxkey IS NOT NULL|)); |
|
107 |
|
|
108 |
foreach my $taxkey (@all_taxkeys) { |
|
109 |
my $ref = $self->get_tax_info('transdate' => $params{transdate}, 'taxkey' => $taxkey); |
|
110 |
|
|
111 |
$tax_info{taxkeys}->{$taxkey} = $ref; |
|
112 |
$tax_info{accnos}->{$ref->{taxchart_id}} = $ref if ($ref->{taxchart_id}); |
|
113 |
} |
|
114 |
|
|
115 |
$main::lxdebug->leave_sub(); |
|
116 |
|
|
117 |
return %tax_info; |
|
118 |
} |
|
119 |
|
|
120 |
1; |
SL/Template/Plugin/LxERP.pm | ||
---|---|---|
90 | 90 |
} |
91 | 91 |
} |
92 | 92 |
|
93 |
sub abs { |
|
94 |
my $self = shift; |
|
95 |
my $var = shift; |
|
96 |
|
|
97 |
return $var < 0 ? $var * -1 : $var; |
|
98 |
} |
|
99 |
|
|
93 | 100 |
1; |
acctranscorrections.pl | ||
---|---|---|
1 |
link am.pl |
bin/mozilla/acctranscorrections.pl | ||
---|---|---|
1 |
use SL::AccTransCorrections; |
|
2 |
use SL::Form; |
|
3 |
use SL::User; |
|
4 |
use Data::Dumper; |
|
5 |
use YAML; |
|
6 |
|
|
7 |
require "bin/mozilla/common.pl"; |
|
8 |
|
|
9 |
sub analyze_filter { |
|
10 |
$lxdebug->enter_sub(); |
|
11 |
|
|
12 |
$form->{jsscript} = 1; |
|
13 |
$form->{title} = $locale->text('General ledger corrections'); |
|
14 |
$form->header(); |
|
15 |
print $form->parse_html_template('acctranscorrections/analyze_filter'); |
|
16 |
|
|
17 |
$lxdebug->leave_sub(); |
|
18 |
} |
|
19 |
|
|
20 |
sub analyze { |
|
21 |
$lxdebug->enter_sub(); |
|
22 |
|
|
23 |
$form->{title} = $locale->text('General ledger corrections'); |
|
24 |
|
|
25 |
delete @{ $form }{qw(transdate_from transdate_to)} if ($form->{scope} eq 'full'); |
|
26 |
|
|
27 |
my $callback = 'acctranscorrections.pl?action=analyze'; |
|
28 |
map { $callback .= "&${_}=" . $form->escape($form->{$_}) } grep { $form->{$_} } qw(transdate_from transdate_to); |
|
29 |
$callback = $form->escape($callback); |
|
30 |
|
|
31 |
my $analyzer = AccTransCorrections->new(); |
|
32 |
|
|
33 |
my %params = map { $_ => $form->{$_} } qw(transdate_from transdate_to); |
|
34 |
my @problems = $analyzer->analyze(%params, 'callback' => $callback); |
|
35 |
|
|
36 |
if (!scalar @problems) { |
|
37 |
$form->show_generic_information($locale->text('No problems were recognized.')); |
|
38 |
|
|
39 |
$lxdebug->leave_sub(); |
|
40 |
return; |
|
41 |
} |
|
42 |
|
|
43 |
$form->header(); |
|
44 |
print $form->parse_html_template('acctranscorrections/analyze_overview', |
|
45 |
{ 'PROBLEMS' => \@problems, |
|
46 |
'callback' => $callback, |
|
47 |
}); |
|
48 |
|
|
49 |
$lxdebug->leave_sub(); |
|
50 |
} |
|
51 |
|
|
52 |
sub assistant { |
|
53 |
$lxdebug->enter_sub(); |
|
54 |
|
|
55 |
$form->{title} = $locale->text('Assistant for general ledger corrections'); |
|
56 |
|
|
57 |
$form->isblank('trans_id', $locale->text('Transaction ID missing.')); |
|
58 |
|
|
59 |
my $analyzer = AccTransCorrections->new(); |
|
60 |
my ($problem) = $analyzer->analyze('trans_id' => $form->{trans_id}, 'full_analysis' => 1); |
|
61 |
|
|
62 |
if (!$problem) { |
|
63 |
my $module = |
|
64 |
$form->{trans_module} eq 'ar' ? $locale->text('AR Transaction') |
|
65 |
: $form->{trans_module} eq 'ap' ? $locale->text('AP Transaction') |
|
66 |
: $locale->text('General Ledger Transaction'); |
|
67 |
|
|
68 |
$form->show_generic_information($locale->text('The assistant could not find anything wrong with #1. Maybe the problem has been solved in the meantime.', |
|
69 |
"$module $form->{trans_reference}")); |
|
70 |
|
|
71 |
$lxdebug->leave_sub(); |
|
72 |
return; |
|
73 |
} |
|
74 |
|
|
75 |
if ($problem->{type} eq 'wrong_taxkeys') { |
|
76 |
assistant_for_wrong_taxkeys($problem); |
|
77 |
|
|
78 |
} elsif ($problem->{type} eq 'wrong_taxes') { |
|
79 |
assistant_for_wrong_taxkeys($problem); |
|
80 |
# assistant_for_wrong_taxes($problem); |
|
81 |
|
|
82 |
} else { |
|
83 |
$form->show_generic_error($locale->text('Unknown problem type.')); |
|
84 |
} |
|
85 |
|
|
86 |
$lxdebug->leave_sub(); |
|
87 |
} |
|
88 |
|
|
89 |
sub assistant_for_ap_ar_wrong_taxkeys { |
|
90 |
$lxdebug->enter_sub(); |
|
91 |
|
|
92 |
$form->{title} = $locale->text('Assistant for general ledger corrections'); |
|
93 |
|
|
94 |
$form->header(); |
|
95 |
print $form->parse_html_template('acctranscorrections/assistant_for_ap_ar_wrong_taxkeys'); |
|
96 |
|
|
97 |
$lxdebug->leave_sub(); |
|
98 |
} |
|
99 |
|
|
100 |
sub fix_ap_ar_wrong_taxkeys { |
|
101 |
$lxdebug->enter_sub(); |
|
102 |
|
|
103 |
my $analyzer = AccTransCorrections->new(); |
|
104 |
$analyzer->fix_ap_ar_wrong_taxkeys(); |
|
105 |
|
|
106 |
$form->{title} = $locale->text('Assistant for general ledger corrections'); |
|
107 |
$form->header(); |
|
108 |
print $form->parse_html_template('acctranscorrections/fix_ap_ar_wrong_taxkeys'); |
|
109 |
|
|
110 |
$lxdebug->leave_sub(); |
|
111 |
} |
|
112 |
|
|
113 |
sub assistant_for_invoice_inventory_with_taxkeys { |
|
114 |
$lxdebug->enter_sub(); |
|
115 |
|
|
116 |
$form->{title} = $locale->text('Assistant for general ledger corrections'); |
|
117 |
|
|
118 |
$form->header(); |
|
119 |
print $form->parse_html_template('acctranscorrections/assistant_for_invoice_inventory_with_taxkeys'); |
|
120 |
|
|
121 |
$lxdebug->leave_sub(); |
|
122 |
} |
|
123 |
|
|
124 |
sub fix_invoice_inventory_with_taxkeys { |
|
125 |
$lxdebug->enter_sub(); |
|
126 |
|
|
127 |
my $analyzer = AccTransCorrections->new(); |
|
128 |
$analyzer->fix_invoice_inventory_with_taxkeys(); |
|
129 |
|
|
130 |
$form->{title} = $locale->text('Assistant for general ledger corrections'); |
|
131 |
$form->header(); |
|
132 |
print $form->parse_html_template('acctranscorrections/fix_invoice_inventory_with_taxkeys'); |
|
133 |
|
|
134 |
$lxdebug->leave_sub(); |
|
135 |
} |
|
136 |
|
|
137 |
sub assistant_for_wrong_taxes { |
|
138 |
$lxdebug->enter_sub(); |
|
139 |
|
|
140 |
my $problem = shift; |
|
141 |
|
|
142 |
$form->{title} = $locale->text('Assistant for general ledger corrections'); |
|
143 |
|
|
144 |
$form->header(); |
|
145 |
print $form->parse_html_template('acctranscorrections/assistant_for_wrong_taxes', { 'problem' => $problem, }); |
|
146 |
|
|
147 |
$lxdebug->leave_sub(); |
|
148 |
} |
|
149 |
|
|
150 |
sub assistant_for_wrong_taxkeys { |
|
151 |
$lxdebug->enter_sub(); |
|
152 |
|
|
153 |
my $problem = shift; |
|
154 |
|
|
155 |
$form->{title} = $locale->text('Assistant for general ledger corrections'); |
|
156 |
|
|
157 |
$form->header(); |
|
158 |
print $form->parse_html_template('acctranscorrections/assistant_for_wrong_taxkeys', { 'problem' => $problem, }); |
|
159 |
|
|
160 |
$lxdebug->leave_sub(); |
|
161 |
} |
|
162 |
|
|
163 |
sub fix_wrong_taxkeys { |
|
164 |
$lxdebug->enter_sub(); |
|
165 |
|
|
166 |
my $fixes = ref $form->{fixes} eq 'ARRAY' ? $form->{fixes} : []; |
|
167 |
|
|
168 |
my $analyzer = AccTransCorrections->new(); |
|
169 |
$analyzer->fix_wrong_taxkeys('fixes' => $fixes); |
|
170 |
|
|
171 |
$form->{title} = $locale->text('Assistant for general ledger corrections'); |
|
172 |
$form->header(); |
|
173 |
print $form->parse_html_template('acctranscorrections/fix_wrong_taxkeys'); |
|
174 |
|
|
175 |
$lxdebug->leave_sub(); |
|
176 |
} |
|
177 |
|
|
178 |
sub delete_transaction { |
|
179 |
$lxdebug->enter_sub(); |
|
180 |
|
|
181 |
$form->{title} = $locale->text('Delete transaction'); |
|
182 |
$form->header(); |
|
183 |
|
|
184 |
if (!$form->{confirmation}) { |
|
185 |
print $form->parse_html_template('acctranscorrections/delete_transaction_confirmation'); |
|
186 |
} else { |
|
187 |
my $analyzer = AccTransCorrections->new(); |
|
188 |
$analyzer->delete_transaction('trans_id' => $form->{trans_id}); |
|
189 |
|
|
190 |
print $form->parse_html_template('acctranscorrections/delete_transaction'); |
|
191 |
} |
|
192 |
|
|
193 |
$lxdebug->leave_sub(); |
|
194 |
} |
|
195 |
|
|
196 |
sub redirect { |
|
197 |
$lxdebug->enter_sub(); |
|
198 |
|
|
199 |
$form->redirect('Missing callbcak'); |
|
200 |
|
|
201 |
$lxdebug->leave_sub(); |
|
202 |
} |
|
203 |
|
|
204 |
sub dispatcher { |
|
205 |
foreach my $action (qw(fix_wrong_taxkeys delete_transaction)) { |
|
206 |
if ($form->{"action_${action}"}) { |
|
207 |
call_sub($action); |
|
208 |
return; |
|
209 |
} |
|
210 |
} |
|
211 |
|
|
212 |
$form->error($locale->text('No action defined.')); |
|
213 |
} |
|
214 |
|
|
215 |
1; |
locale/de/acctranscorrections | ||
---|---|---|
1 |
#!/usr/bin/perl |
|
2 |
|
|
3 |
$self->{texts} = { |
|
4 |
'ADDED' => 'Hinzugef?gt', |
|
5 |
'AP' => 'Einkauf', |
|
6 |
'AP Transaction' => 'Kreditorenbuchung', |
|
7 |
'AR' => 'Verkauf', |
|
8 |
'AR Transaction' => 'Debitorenbuchung', |
|
9 |
'Address' => 'Adresse', |
|
10 |
'Advance turnover tax return' => 'Umsatzsteuervoranmeldung', |
|
11 |
'All reports' => 'Alle Berichte (Kontenübersicht, Summen- u. Saldenliste, GuV, BWA, Bilanz, Projektbuchungen)', |
|
12 |
'Assistant for general ledger corrections' => 'Assistent f?r die Korrektur von Hauptbucheintr?gen', |
|
13 |
'Attempt to call an undefined sub named \'%s\'' => 'Es wurde versucht, eine nicht definierte Unterfunktion namens \'%s\' aufzurufen.', |
|
14 |
'Bcc' => 'Bcc', |
|
15 |
'Bin List' => 'Lagerliste', |
|
16 |
'Binding to the LDAP server as "#1" failed. Please check config/authentication.pl.' => 'Die Anmeldung am LDAP-Server als "#1" schlug fehl. Bitte überprüfen Sie die Angaben in config/authentication.pl.', |
|
17 |
'CANCELED' => 'Storniert', |
|
18 |
'Cc' => 'Cc', |
|
19 |
'Change Lx-Office installation settings (all menu entries beneath \'System\')' => 'Verändern der Lx-Office-Installationseinstellungen (Menüpunkte unterhalb von \'System\')', |
|
20 |
'Confirmation' => 'Auftragsbest?tigung', |
|
21 |
'Contact' => 'Kontakt', |
|
22 |
'Create and edit RFQs' => 'Lieferantenanfragen erfassen und bearbeiten', |
|
23 |
'Create and edit customers and vendors' => 'Kunden und Lieferanten erfassen und bearbeiten', |
|
24 |
'Create and edit dunnings' => 'Mahnungen erfassen und bearbeiten', |
|
25 |
'Create and edit invoices and credit notes' => 'Rechnungen und Gutschriften erfassen und bearbeiten', |
|
26 |
'Create and edit parts, services, assemblies' => 'Artikel, Dienstleistungen, Erzeugnisse erfassen und bearbeiten', |
|
27 |
'Create and edit projects' => 'Projekte erfassen und bearbeiten', |
|
28 |
'Create and edit purchase delivery orders' => 'Lieferscheine von Lieferanten erfassen und bearbeiten', |
|
29 |
'Create and edit purchase orders' => 'Lieferantenaufträge erfassen und bearbeiten', |
|
30 |
'Create and edit sales delivery orders' => 'Lieferscheine für Kunden erfassen und bearbeiten', |
|
31 |
'Create and edit sales orders' => 'Auftragsbestätigungen erfassen und bearbeiten', |
|
32 |
'Create and edit sales quotations' => 'Angebote erfassen und bearbeiten', |
|
33 |
'Create and edit vendor invoices' => 'Eingangsrechnungen erfassen und bearbeiten', |
|
34 |
'Credit Note' => 'Gutschrift', |
|
35 |
'Customer Number' => 'Kundennummer', |
|
36 |
'Customer details' => 'Kundendetails', |
|
37 |
'DATEV Export' => 'DATEV-Export', |
|
38 |
'DELETED' => 'Gel?scht', |
|
39 |
'DUNNING STARTED' => 'Mahnprozess gestartet', |
|
40 |
'Dataset upgrade' => 'Datenbankaktualisierung', |
|
41 |
'Date' => 'Datum', |
|
42 |
'Delete transaction' => 'Buchung l?schen', |
|
43 |
'Delivery Order' => 'Lieferschein', |
|
44 |
'Dependency loop detected:' => 'Schleife in den Abhängigkeiten entdeckt:', |
|
45 |
'Directory' => 'Verzeichnis', |
|
46 |
'ELSE' => 'Zusatz', |
|
47 |
'Enter longdescription' => 'Langtext eingeben', |
|
48 |
'Error in database control file \'%s\': %s' => 'Fehler in Datenbankupgradekontrolldatei \'%s\': %s', |
|
49 |
'File' => 'Datei', |
|
50 |
'General Ledger Transaction' => 'Dialogbuchung', |
|
51 |
'General ledger and cash' => 'Finanzbuchhaltung und Zahlungsverkehr', |
|
52 |
'General ledger corrections' => 'Korrekturen im Hauptbuch', |
|
53 |
'History' => 'Historie', |
|
54 |
'Invoice' => 'Rechnung', |
|
55 |
'MAILED' => 'Gesendet', |
|
56 |
'Manage license keys' => 'Lizenzschlüssel verwalten', |
|
57 |
'Mark as paid?' => 'Als bezahlt markieren?', |
|
58 |
'Marked as paid' => 'Als bezahlt markiert', |
|
59 |
'Master Data' => 'Stammdaten', |
|
60 |
'May set the BCC field when sending emails' => 'Beim Verschicken von Emails das Feld \'BCC\' setzen', |
|
61 |
'Message' => 'Nachricht', |
|
62 |
'Missing \'description\' field.' => 'Fehlendes Feld \'description\'.', |
|
63 |
'Missing \'tag\' field.' => 'Fehlendes Feld \'tag\'.', |
|
64 |
'Missing parameter #1 in call to sub #2.' => 'Fehlernder Parameter \'#1\' in Funktionsaufruf \'#2\'.', |
|
65 |
'Missing parameter (at least one of #1) in call to sub #2.' => 'Fehlernder Parameter (mindestens einer aus \'#1\') in Funktionsaufruf \'#2\'.', |
|
66 |
'More than one control file with the tag \'%s\' exist.' => 'Es gibt mehr als eine Kontrolldatei mit dem Tag \'%s\'.', |
|
67 |
'Name' => 'Name', |
|
68 |
'No %s was found matching the search parameters.' => 'Es wurde kein %s gefunden, auf den die Suchparameter zutreffen.', |
|
69 |
'No Customer was found matching the search parameters.' => 'Zu dem Suchbegriff wurde kein Endkunde gefunden', |
|
70 |
'No Vendor was found matching the search parameters.' => 'Zu dem Suchbegriff wurde kein H?ndler gefunden', |
|
71 |
'No action defined.' => 'Keine Aktion definiert.', |
|
72 |
'No customer has been selected yet.' => 'Es wurde noch kein Kunde ausgew?hlt.', |
|
73 |
'No or an unknown authenticantion module specified in "config/authentication.pl".' => 'Es wurde kein oder ein unbekanntes Authentifizierungsmodul in "config/authentication.pl" angegeben.', |
|
74 |
'No part was found matching the search parameters.' => 'Es wurde kein Artikel gefunden, auf den die Suchparameter zutreffen.', |
|
75 |
'No problems were recognized.' => 'Es wurden keine Probleme gefunden.', |
|
76 |
'No vendor has been selected yet.' => 'Es wurde noch kein Lieferant ausgew?hlt.', |
|
77 |
'Others' => 'Andere', |
|
78 |
'PAYMENT POSTED' => 'Rechung gebucht', |
|
79 |
'POSTED' => 'Gebucht', |
|
80 |
'POSTED AS NEW' => 'Als neu gebucht', |
|
81 |
'PRINTED' => 'Gedruckt', |
|
82 |
'Packing List' => 'Lieferschein', |
|
83 |
'Part Number' => 'Artikelnummer', |
|
84 |
'Part description' => 'Artikelbeschreibung', |
|
85 |
'Pick List' => 'Packliste', |
|
86 |
'Please enter values' => 'Bitte Werte eingeben', |
|
87 |
'Preview' => 'Druckvorschau', |
|
88 |
'Proforma Invoice' => 'Proformarechnung', |
|
89 |
'Purchase Order' => 'Lieferantenauftrag', |
|
90 |
'Quotation' => 'Angebot', |
|
91 |
'RFQ' => 'Anfrage', |
|
92 |
'Receipt, payment, reconciliation' => 'Zahlungseingang, Zahlungsausgang, Kontenabgleich', |
|
93 |
'Reports' => 'Berichte', |
|
94 |
'SAVED' => 'Gespeichert', |
|
95 |
'SAVED FOR DUNNING' => 'Gespeichert', |
|
96 |
'SCREENED' => 'Angezeigt', |
|
97 |
'Select a Customer' => 'Endkunde ausw?hlen', |
|
98 |
'Select a customer' => 'Einen Kunden auswählen', |
|
99 |
'Select a part' => 'Artikel auswählen', |
|
100 |
'Select a vendor' => 'Einen Lieferanten auswählen', |
|
101 |
'Storno Invoice' => 'Stornorechnung', |
|
102 |
'Storno Packing List' => 'Stornolieferschein', |
|
103 |
'Subject' => 'Betreff', |
|
104 |
'The \'tag\' field must only consist of alphanumeric characters or the carachters - _ ( )' => 'Das Feld \'tag\' darf nur aus alphanumerischen Zeichen und den Zeichen - _ ( ) bestehen.', |
|
105 |
'The LDAP server "#1:#2" is unreachable. Please check config/authentication.pl.' => 'Der LDAP-Server "#1:#2" ist nicht erreichbar. Bitte überprüfen Sie die Angaben in config/authentication.pl.', |
|
106 |
'The assistant could not find anything wrong with #1. Maybe the problem has been solved in the meantime.' => 'Der Korrekturassistent konnte kein Problem bei #1 feststellen. Eventuell wurde das Problem in der Zwischenzeit bereits behoben.', |
|
107 |
'The config file "config/authentication.pl" contained invalid Perl code:' => 'Die Konfigurationsdatei "config/authentication.pl" enthielt ungütigen Perl-Code:', |
|
108 |
'The config file "config/authentication.pl" was not found.' => 'Die Konfigurationsdatei "config/authentication.pl" wurde nicht gefunden.', |
|
109 |
'The connection to the LDAP server cannot be encrypted (SSL/TLS startup failure). Please check config/authentication.pl.' => 'Die Verbindung zum LDAP-Server kann nicht verschlüsselt werden (Fehler bei SSL/TLS-Initialisierung). Bitte überprüfen Sie die Angaben in config/authentication.pl.', |
|
110 |
'The connection to the authentication database failed:' => 'Die Verbindung zur Authentifizierungsdatenbank schlug fehl:', |
|
111 |
'The connection to the template database failed:' => 'Die Verbindung zur Vorlagendatenbank schlug fehl:', |
|
112 |
'The creation of the authentication database failed:' => 'Das Anlegen der Authentifizierungsdatenbank schlug fehl:', |
|
113 |
'To (email)' => 'An', |
|
114 |
'Transaction ID missing.' => 'Die Buchungs-ID fehlt.', |
|
115 |
'Transactions, AR transactions, AP transactions' => 'Dialogbuchen, Debitorenrechnungen, Kreditorenrechnungen', |
|
116 |
'Trying to call a sub without a name' => 'Es wurde versucht, eine Unterfunktion ohne Namen aufzurufen.', |
|
117 |
'Unit' => 'Einheit', |
|
118 |
'Unknown dependency \'%s\'.' => 'Unbekannte Abhängigkeit \'%s\'.', |
|
119 |
'Unknown problem type.' => 'Unbekannter Problem-Typ', |
|
120 |
'Value' => 'Wert', |
|
121 |
'Variable' => 'Variable', |
|
122 |
'Vendor details' => 'Lieferantendetails', |
|
123 |
'View warehouse content' => 'Lagerbestand ansehen', |
|
124 |
'Warehouse management' => 'Lagerverwaltung/Bestandsver?nderung', |
|
125 |
'You do not have the permissions to access this function.' => 'Sie verfügen nicht über die notwendigen Rechte, um auf diese Funktion zuzugreifen.', |
|
126 |
'[email]' => '[email]', |
|
127 |
'bin_list' => 'Lagerliste', |
|
128 |
'config/authentication.pl: Key "DB_config" is missing.' => 'config/authentication.pl: Das Schlüsselwort "DB_config" fehlt.', |
|
129 |
'config/authentication.pl: Key "LDAP_config" is missing.' => 'config/authentication.pl: Der Schlüssel "LDAP_config" fehlt.', |
|
130 |
'config/authentication.pl: Missing parameters in "DB_config". Required parameters are "host", "db" and "user".' => 'config/authentication.pl: Fehlende Parameter in "DB_config". Benötigte Parameter sind "host", "db" und "user".', |
|
131 |
'config/authentication.pl: Missing parameters in "LDAP_config". Required parameters are "host", "attribute" and "base_dn".' => 'config/authentication.pl: Fehlende Parameter in "LDAP_config". Benötigt werden "host", "attribute" und "base_dn".', |
|
132 |
'customer' => 'Kunde', |
|
133 |
'invoice' => 'Rechnung', |
|
134 |
'no' => 'nein', |
|
135 |
'packing_list' => 'Versandliste', |
|
136 |
'pick_list' => 'Entnahmeliste', |
|
137 |
'proforma' => 'Proforma', |
|
138 |
'purchase_order' => 'Auftrag', |
|
139 |
'request_quotation' => 'Angebotsanforderung', |
|
140 |
'sales_order' => 'Kundenauftrag', |
|
141 |
'sales_quotation' => 'Verkaufsangebot', |
|
142 |
'vendor' => 'Lieferant', |
|
143 |
'yes' => 'ja', |
|
144 |
}; |
|
145 |
|
|
146 |
$self->{subs} = { |
|
147 |
'E' => 'E', |
|
148 |
'H' => 'H', |
|
149 |
'J' => 'J', |
|
150 |
'NTI' => 'NTI', |
|
151 |
'Q' => 'Q', |
|
152 |
'analyze' => 'analyze', |
|
153 |
'analyze_filter' => 'analyze_filter', |
|
154 |
'assistant' => 'assistant', |
|
155 |
'assistant_for_ap_ar_wrong_taxkeys' => 'assistant_for_ap_ar_wrong_taxkeys', |
|
156 |
'assistant_for_invoice_inventory_with_taxkeys' => 'assistant_for_invoice_inventory_with_taxkeys', |
|
157 |
'assistant_for_wrong_taxes' => 'assistant_for_wrong_taxes', |
|
158 |
'assistant_for_wrong_taxkeys' => 'assistant_for_wrong_taxkeys', |
|
159 |
'build_std_url' => 'build_std_url', |
|
160 |
'calculate_qty' => 'calculate_qty', |
|
161 |
'call_sub' => 'call_sub', |
|
162 |
'cov_selection_internal' => 'cov_selection_internal', |
|
163 |
'delete_transaction' => 'delete_transaction', |
|
164 |
'delivery_customer_selection' => 'delivery_customer_selection', |
|
165 |
'dispatcher' => 'dispatcher', |
|
166 |
'fix_ap_ar_wrong_taxkeys' => 'fix_ap_ar_wrong_taxkeys', |
|
167 |
'fix_invoice_inventory_with_taxkeys' => 'fix_invoice_inventory_with_taxkeys', |
|
168 |
'fix_wrong_taxkeys' => 'fix_wrong_taxkeys', |
|
169 |
'format_dates' => 'format_dates', |
|
170 |
'mark_as_paid_common' => 'mark_as_paid_common', |
|
171 |
'part_selection_internal' => 'part_selection_internal', |
|
172 |
'redirect' => 'redirect', |
|
173 |
'reformat_numbers' => 'reformat_numbers', |
|
174 |
'retrieve_partunits' => 'retrieve_partunits', |
|
175 |
'select_part' => 'select_part', |
|
176 |
'select_part_internal' => 'select_part_internal', |
|
177 |
'set_longdescription' => 'set_longdescription', |
|
178 |
'show_history' => 'show_history', |
Auch abrufbar als: Unified diff
Korrekturmodul für das Hauptbuch implementiert
Frührere Lx-Office-Versionen enthalten einige Bugs und Features,
die den Export von Buchungsdaten ins DATEV-Format verhindern und
allgemein zu ungültigen und/oder unlogischen Einträgen in acc_trans
führen. Mit Hilfe dieses Modules, das über den Menüpunkt "System ->
Korrekturen -> Korrekturen im Hauptbuch" erreichbar ist, können die
Auswirkungen dieser Bugs und Features teils automatisch, teils manuell
behoben werden.