Revision d50a9e20
Von Moritz Bunkus vor mehr als 17 Jahren hinzugefügt
SL/IR.pm | ||
---|---|---|
37 | 37 |
use SL::AM; |
38 | 38 |
use SL::Common; |
39 | 39 |
use SL::DBUtils; |
40 |
use SL::MoreCommon; |
|
40 | 41 |
|
41 | 42 |
sub post_invoice { |
42 | 43 |
$main::lxdebug->enter_sub(); |
43 | 44 |
|
44 |
my ($self, $myconfig, $form) = @_; |
|
45 |
my ($self, $myconfig, $form, $provided_dbh, $payments_only) = @_;
|
|
45 | 46 |
|
46 | 47 |
# connect to database, turn off autocommit |
47 |
my $dbh = $form->dbconnect_noauto($myconfig); |
|
48 |
my $dbh = $provided_dbh ? $provided_dbh : $form->dbconnect_noauto($myconfig);
|
|
48 | 49 |
|
49 | 50 |
my ($query, $sth, @values, $project_id); |
50 | 51 |
my ($allocated, $taxrate, $taxamount, $taxdiff, $item); |
... | ... | |
54 | 55 |
|
55 | 56 |
my $all_units = AM->retrieve_units($myconfig, $form); |
56 | 57 |
|
57 |
if ($form->{id}) { |
|
58 |
if (!$payments_only) { |
|
59 |
if ($form->{id}) { |
|
60 |
&reverse_invoice($dbh, $form); |
|
58 | 61 |
|
59 |
&reverse_invoice($dbh, $form); |
|
60 |
|
|
61 |
} else { |
|
62 |
($form->{id}) = selectrow_query($form, $dbh, qq|SELECT nextval('glid')|); |
|
62 |
} else { |
|
63 |
($form->{id}) = selectrow_query($form, $dbh, qq|SELECT nextval('glid')|); |
|
63 | 64 |
|
64 |
do_query($form, $dbh, qq|INSERT INTO ap (id, invnumber) VALUES (?, '')|, $form->{id}); |
|
65 |
do_query($form, $dbh, qq|INSERT INTO ap (id, invnumber) VALUES (?, '')|, $form->{id}); |
|
66 |
} |
|
65 | 67 |
} |
66 | 68 |
|
67 |
if ($form->{currency} eq $form->{defaultcurrency}) { |
|
69 |
my ($currencies) = selectfirst_array_query($form, $dbh, qq|SELECT curr FROM defaults|); |
|
70 |
my $defaultcurrency = (split m/:/, $currencies)[0]; |
|
71 |
|
|
72 |
if ($form->{currency} eq $defaultcurrency) { |
|
68 | 73 |
$form->{exchangerate} = 1; |
69 | 74 |
} else { |
70 | 75 |
$exchangerate = |
... | ... | |
172 | 177 |
$form->{"sellprice_$i"} = |
173 | 178 |
$form->round_amount($form->{"sellprice_$i"} * $form->{exchangerate}, $decimalplaces); |
174 | 179 |
|
180 |
$lastinventoryaccno = $form->{"inventory_accno_$i"}; |
|
181 |
|
|
182 |
next if $payments_only; |
|
183 |
|
|
175 | 184 |
# update parts table |
176 | 185 |
$query = qq|UPDATE parts SET lastcost = ? WHERE id = ?|; |
177 | 186 |
@values = ($form->{"sellprice_$i"}, conv_i($form->{"id_$i"})); |
... | ... | |
247 | 256 |
|
248 | 257 |
$sth->finish(); |
249 | 258 |
|
250 |
$lastinventoryaccno = $form->{"inventory_accno_$i"}; |
|
251 |
|
|
252 | 259 |
} else { |
253 | 260 |
|
254 | 261 |
$linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"}, 2); |
... | ... | |
296 | 303 |
# adjust and round sellprice |
297 | 304 |
$form->{"sellprice_$i"} = $form->round_amount($form->{"sellprice_$i"} * $form->{exchangerate}, $decimalplaces); |
298 | 305 |
|
306 |
next if $payments_only; |
|
307 |
|
|
299 | 308 |
# update lastcost |
300 | 309 |
$query = qq|UPDATE parts SET lastcost = ? WHERE id = ?|; |
301 | 310 |
do_query($form, $dbh, $query, $form->{"sellprice_$i"}, conv_i($form->{"id_$i"})); |
302 | 311 |
} |
303 | 312 |
|
313 |
next if $payments_only; |
|
314 |
|
|
304 | 315 |
# save detail record in invoice table |
305 | 316 |
$query = |
306 | 317 |
qq|INSERT INTO invoice (trans_id, parts_id, description, qty, base_qty, |
... | ... | |
385 | 396 |
} |
386 | 397 |
|
387 | 398 |
# update exchangerate |
388 |
if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) {
|
|
399 |
if (($form->{currency} ne $defaultcurrency) && !$exchangerate) {
|
|
389 | 400 |
$form->update_exchangerate($dbh, $form->{currency}, $form->{invdate}, 0, $form->{exchangerate}); |
390 | 401 |
} |
391 | 402 |
|
... | ... | |
393 | 404 |
foreach my $trans_id (keys %{ $form->{amount} }) { |
394 | 405 |
foreach my $accno (keys %{ $form->{amount}{$trans_id} }) { |
395 | 406 |
$form->{amount}{$trans_id}{$accno} = $form->round_amount($form->{amount}{$trans_id}{$accno}, 2); |
396 |
next unless $form->{amount}{$trans_id}{$accno}; |
|
407 |
|
|
408 |
next if ($payments_only || !$form->{amount}{$trans_id}{$accno}); |
|
397 | 409 |
|
398 | 410 |
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, taxkey, project_id) |
399 | 411 |
VALUES (?, (SELECT id FROM chart WHERE accno = ?), ?, ?, |
... | ... | |
447 | 459 |
|
448 | 460 |
$exchangerate = 0; |
449 | 461 |
|
450 |
if ($form->{currency} eq $form->{defaultcurrency}) {
|
|
462 |
if ($form->{currency} eq $defaultcurrency) {
|
|
451 | 463 |
$form->{"exchangerate_$i"} = 1; |
452 | 464 |
} else { |
453 | 465 |
$exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{"datepaid_$i"}, 'sell'); |
... | ... | |
476 | 488 |
$paiddiff = 0; |
477 | 489 |
|
478 | 490 |
# update exchange rate |
479 |
if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) {
|
|
491 |
if (($form->{currency} ne $defaultcurrency) && !$exchangerate) {
|
|
480 | 492 |
$form->update_exchangerate($dbh, $form->{currency}, |
481 | 493 |
$form->{"datepaid_$i"}, |
482 | 494 |
0, $form->{"exchangerate_$i"}); |
... | ... | |
496 | 508 |
} |
497 | 509 |
} |
498 | 510 |
|
511 |
if ($payments_only) { |
|
512 |
$query = qq|UPDATE ap SET paid = ?, datepaid = ? WHERE id = ?|; |
|
513 |
do_query($form, $dbh, $query, $form->{paid}, $form->{paid} ? conv_date($form->{datepaid}) : undef, conv_i($form->{id})); |
|
514 |
|
|
515 |
if (!$provided_dbh) { |
|
516 |
$dbh->commit(); |
|
517 |
$dbh->disconnect(); |
|
518 |
} |
|
519 |
|
|
520 |
$main::lxdebug->leave_sub(); |
|
521 |
return; |
|
522 |
} |
|
523 |
|
|
499 | 524 |
$amount = $netamount + $tax; |
500 | 525 |
|
501 | 526 |
# set values which could be empty |
... | ... | |
569 | 594 |
|
570 | 595 |
Common::webdav_folder($form) if ($main::webdav); |
571 | 596 |
|
572 |
my $rc = $dbh->commit; |
|
573 |
$dbh->disconnect; |
|
597 |
my $rc = 1; |
|
598 |
|
|
599 |
if (!$provided_dbh) { |
|
600 |
$rc = $dbh->commit(); |
|
601 |
$dbh->disconnect(); |
|
602 |
} |
|
574 | 603 |
|
575 | 604 |
$main::lxdebug->leave_sub(); |
576 | 605 |
|
... | ... | |
1177 | 1206 |
$main::lxdebug->leave_sub(); |
1178 | 1207 |
} |
1179 | 1208 |
|
1209 |
sub _delete_payments { |
|
1210 |
$main::lxdebug->enter_sub(); |
|
1211 |
|
|
1212 |
my ($self, $form, $dbh) = @_; |
|
1213 |
|
|
1214 |
my @delete_oids; |
|
1215 |
|
|
1216 |
# Delete old payment entries from acc_trans. |
|
1217 |
my $query = |
|
1218 |
qq|SELECT oid |
|
1219 |
FROM acc_trans |
|
1220 |
WHERE (trans_id = ?) AND fx_transaction |
|
1221 |
|
|
1222 |
UNION |
|
1223 |
|
|
1224 |
SELECT at.oid |
|
1225 |
FROM acc_trans at |
|
1226 |
LEFT JOIN chart c ON (at.chart_id = c.id) |
|
1227 |
WHERE (trans_id = ?) AND (c.link LIKE '%AP_paid%')|; |
|
1228 |
push @delete_oids, selectall_array_query($form, $dbh, $query, conv_i($form->{id}), conv_i($form->{id})); |
|
1229 |
|
|
1230 |
$query = |
|
1231 |
qq|SELECT at.oid |
|
1232 |
FROM acc_trans at |
|
1233 |
LEFT JOIN chart c ON (at.chart_id = c.id) |
|
1234 |
WHERE (trans_id = ?) |
|
1235 |
AND ((c.link = 'AP') OR (c.link LIKE '%:AP') OR (c.link LIKE 'AP:%')) |
|
1236 |
ORDER BY at.oid |
|
1237 |
OFFSET 1|; |
|
1238 |
push @delete_oids, selectall_array_query($form, $dbh, $query, conv_i($form->{id})); |
|
1239 |
|
|
1240 |
if (@delete_oids) { |
|
1241 |
$query = qq|DELETE FROM acc_trans WHERE oid IN (| . join(", ", @delete_oids) . qq|)|; |
|
1242 |
do_query($form, $dbh, $query); |
|
1243 |
} |
|
1244 |
|
|
1245 |
$main::lxdebug->leave_sub(); |
|
1246 |
} |
|
1247 |
|
|
1180 | 1248 |
sub post_payment { |
1181 | 1249 |
$main::lxdebug->enter_sub(); |
1182 | 1250 |
|
... | ... | |
1185 | 1253 |
# connect to database, turn off autocommit |
1186 | 1254 |
my $dbh = $form->dbconnect_noauto($myconfig); |
1187 | 1255 |
|
1188 |
$form->{datepaid} = $form->{invdate};
|
|
1256 |
my (%payments, $old_form, $row, $item, $query, %keep_vars);
|
|
1189 | 1257 |
|
1190 |
# total payments, don't move we need it here |
|
1191 |
for my $i (1 .. $form->{paidaccounts}) { |
|
1192 |
$form->{"paid_$i"} = $form->parse_amount($myconfig, $form->{"paid_$i"}); |
|
1193 |
$form->{paid} += $form->{"paid_$i"}; |
|
1194 |
$form->{datepaid} = $form->{"datepaid_$i"} if ($form->{"datepaid_$i"}); |
|
1195 |
} |
|
1196 | 1258 |
|
1197 |
$form->{exchangerate} = |
|
1198 |
$form->get_exchangerate($dbh, $form->{currency}, $form->{invdate}, "buy"); |
|
1259 |
my @prior; |
|
1260 |
push @prior, selectall_hashref_query($form, $dbh, qq|SELECT id, paid, datepaid FROM ap WHERE id = ?|, $form->{id}); |
|
1261 |
push @prior, selectall_hashref_query($form, $dbh, qq|SELECT * FROM acc_trans WHERE trans_id = ? ORDER BY oid|, $form->{id}); |
|
1199 | 1262 |
|
1200 |
my $project_id = conv_i($form->{"globalproject_id"}); |
|
1201 | 1263 |
|
1202 |
# record payments and offsetting AP |
|
1203 |
for my $i (1 .. $form->{paidaccounts}) { |
|
1204 |
next if $form->{"paid_$i"} == 0; |
|
1205 | 1264 |
|
1206 |
my ($accno) = split /--/, $form->{"AP_paid_$i"}; |
|
1207 |
$form->{"datepaid_$i"} = $form->{invdate} unless $form->{"datepaid_$i"}; |
|
1208 |
$form->{datepaid} = $form->{"datepaid_$i"}; |
|
1209 | 1265 |
|
1210 |
$exchangerate = 0; |
|
1211 |
if (($form->{currency} eq $form->{defaultcurrency}) || ($form->{defaultcurrency} eq "")) { |
|
1212 |
$form->{"exchangerate_$i"} = 1; |
|
1266 |
$old_form = save_form(); |
|
1213 | 1267 |
|
1214 |
} else {
|
|
1215 |
$exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{"datepaid_$i"}, 'buy');
|
|
1268 |
# Delete all entries in acc_trans from prior payments.
|
|
1269 |
$self->_delete_payments($form, $dbh);
|
|
1216 | 1270 |
|
1217 |
$form->{"exchangerate_$i"} = |
|
1218 |
($exchangerate) |
|
1219 |
? $exchangerate |
|
1220 |
: $form->parse_amount($myconfig, $form->{"exchangerate_$i"}); |
|
1221 |
} |
|
1271 |
# Save the new payments the user made before cleaning up $form. |
|
1272 |
map { $payments{$_} = $form->{$_} } grep m/^datepaid_\d+$|^memo_\d+$|^source_\d+$|^exchangerate_\d+$|^paid_\d+$|^AP_paid_\d+$|^paidaccounts$/, keys %{ $form }; |
|
1222 | 1273 |
|
1223 |
# record AP |
|
1224 |
$amount = $form->round_amount($form->{"paid_$i"} * $form->{"exchangerate"}, 2) * -1; |
|
1274 |
# Clean up $form so that old content won't tamper the results. |
|
1275 |
%keep_vars = map { $_, 1 } qw(login password id); |
|
1276 |
map { delete $form->{$_} unless $keep_vars{$_} } keys %{ $form }; |
|
1225 | 1277 |
|
1226 |
$query = |
|
1227 |
qq|DELETE FROM acc_trans |
|
1228 |
WHERE (trans_id = ?) |
|
1229 |
AND (chart_id = (SELECT c.id FROM chart c WHERE c.accno = ?)) |
|
1230 |
AND (amount = ?) |
|
1231 |
AND (transdate = ?)|; |
|
1232 |
@values = (conv_i($form->{id}), $form->{AP}, $amount, conv_date($form->{"datepaid_$i"})); |
|
1233 |
do_query($form, $dbh, $query, @values); |
|
1278 |
# Retrieve the invoice from the database. |
|
1279 |
$self->retrieve_invoice($myconfig, $form); |
|
1234 | 1280 |
|
1235 |
$query = |
|
1236 |
qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, taxkey, project_id) |
|
1237 |
VALUES (?, (SELECT c.id FROM chart c WHERE c.accno = ?), ?, ?, |
|
1238 |
(SELECT taxkey_id FROM chart WHERE accno = ?), ?)|; |
|
1239 |
@values = (conv_i($form->{id}), $form->{AP}, $amount, |
|
1240 |
conv_date($form->{"datepaid_$i"}), $form->{AP}, $project_id); |
|
1241 |
do_query($form, $dbh, $query, @values); |
|
1281 |
# Set up the content of $form in the way that IR::post_invoice() expects. |
|
1282 |
$form->{exchangerate} = $form->format_amount($myconfig, $form->{exchangerate}); |
|
1242 | 1283 |
|
1243 |
$query = |
|
1244 |
qq|DELETE FROM acc_trans |
|
1245 |
WHERE (trans_id = ?) |
|
1246 |
AND (chart_id=(SELECT c.id FROM chart c WHERE c.accno = ?)) |
|
1247 |
AND (amount = ?) |
|
1248 |
AND (transdate = ?) |
|
1249 |
AND (source = ?) |
|
1250 |
AND (memo = ?)|; |
|
1251 |
@values = (conv_i($form->{id}), $accno, $form->{"paid_$i"}, |
|
1252 |
conv_date($form->{"datepaid_$i"}), $form->{"source_$i"}, |
|
1253 |
$form->{"memo_$i"}); |
|
1254 |
do_query($form, $dbh, $query, @values); |
|
1284 |
for $row (1 .. scalar @{ $form->{invoice_details} }) { |
|
1285 |
$item = $form->{invoice_details}->[$row - 1]; |
|
1255 | 1286 |
|
1256 |
$query = |
|
1257 |
qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, source, memo, taxkey, project_id) |
|
1258 |
VALUES (?, (SELECT c.id FROM chart c WHERE c.accno = ?), ?, ?, ?, ?, |
|
1259 |
(SELECT taxkey_id FROM chart WHERE accno = ?), ?)|; |
|
1260 |
@values = (conv_i($form->{id}), $accno, $form->{"paid_$i"}, |
|
1261 |
conv_date($form->{"datepaid_$i"}), $form->{"source_$i"}, |
|
1262 |
$form->{"memo_$i"}, $accno, $project_id); |
|
1263 |
do_query($form, $dbh, $query, @values); |
|
1287 |
map { $item->{$_} = $form->format_amount($myconfig, $item->{$_}) } qw(qty sellprice); |
|
1264 | 1288 |
|
1265 |
# gain/loss
|
|
1266 |
$amount = $form->{"paid_$i"} * $form->{exchangerate} - $form->{"paid_$i"} * $form->{"exchangerate_$i"};
|
|
1289 |
map { $form->{"${_}_${row}"} = $item->{$_} } keys %{ $item };
|
|
1290 |
}
|
|
1267 | 1291 |
|
1268 |
if ($amount > 0) { |
|
1269 |
$form->{fx}{ $form->{fxgain_accno} }{ $form->{"datepaid_$i"} } += $amount; |
|
1270 |
} else { |
|
1271 |
$form->{fx}{ $form->{fxloss_accno} }{ $form->{"datepaid_$i"} } += $amount; |
|
1272 |
} |
|
1292 |
$form->{rowcount} = scalar @{ $form->{invoice_details} }; |
|
1273 | 1293 |
|
1274 |
$diff = 0;
|
|
1294 |
delete @{$form}{qw(invoice_details paidaccounts storno paid)};
|
|
1275 | 1295 |
|
1276 |
# update exchange rate |
|
1277 |
if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) { |
|
1278 |
$form->update_exchangerate($dbh, $form->{currency}, |
|
1279 |
$form->{"datepaid_$i"}, |
|
1280 |
$form->{"exchangerate_$i"}, 0); |
|
1281 |
} |
|
1282 |
} |
|
1296 |
# Restore the payment options from the user input. |
|
1297 |
map { $form->{$_} = $payments{$_} } keys %payments; |
|
1283 | 1298 |
|
1284 |
# record exchange rate differences and gains/losses |
|
1285 |
foreach my $accno (keys %{ $form->{fx} }) { |
|
1286 |
foreach my $transdate (keys %{ $form->{fx}{$accno} }) { |
|
1287 |
$form->{fx}{$accno}{$transdate} = $form->round_amount($form->{fx}{$accno}{$transdate}, 2); |
|
1288 |
next if $form->{fx}{$accno}{$transdate} == 0; |
|
1299 |
# Get the AP accno (which is normally done by Form::create_links()). |
|
1300 |
$query = |
|
1301 |
qq|SELECT c.accno |
|
1302 |
FROM acc_trans at |
|
1303 |
LEFT JOIN chart c ON (at.chart_id = c.id) |
|
1304 |
WHERE (trans_id = ?) |
|
1305 |
AND ((c.link = 'AP') OR (c.link LIKE '%:AP') OR (c.link LIKE 'AP:%')) |
|
1306 |
ORDER BY at.oid |
|
1307 |
LIMIT 1|; |
|
1289 | 1308 |
|
1290 |
$query = |
|
1291 |
qq|DELETE FROM acc_trans |
|
1292 |
WHERE (trans_id = ?) |
|
1293 |
AND (chart_id = (SELECT id FROM chart WHERE accno = ?)) |
|
1294 |
AND (amount = ?) |
|
1295 |
AND (transdate = ?) |
|
1296 |
AND (cleared = '0') |
|
1297 |
AND (fx_transaction = '1')|; |
|
1298 |
@values = (conv_i($form->{id}), $accno, $form->{fx}{$accno}{$transdate}, $transdate); |
|
1299 |
do_query($form, $dbh, $query, @values); |
|
1309 |
($form->{AP}) = selectfirst_array_query($form, $dbh, $query, conv_i($form->{id})); |
|
1300 | 1310 |
|
1301 |
$query = |
|
1302 |
qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, cleared, fx_transaction, taxkey, project_id) |
|
1303 |
VALUES (?, (SELECT id FROM chart WHERE accno = ?), ?, ?, '0', '1', |
|
1304 |
(SELECT taxkey_id FROM chart WHERE accno = ?), ?)|; |
|
1305 |
@values = (conv_i($form->{id}), $accno, $form->{fx}{$accno}{$transdate}, |
|
1306 |
$transdate, $accno, $project_id); |
|
1307 |
do_query($form, $dbh, $query, @values); |
|
1308 |
} |
|
1309 |
} |
|
1311 |
# Post the new payments. |
|
1312 |
$self->post_invoice($myconfig, $form, $dbh, 1); |
|
1310 | 1313 |
|
1311 |
my $datepaid = $form->{paid} ? qq|'$form->{datepaid}'| : "NULL";
|
|
1314 |
restore_form($old_form);
|
|
1312 | 1315 |
|
1313 |
# save AP record |
|
1314 |
my $query = qq|UPDATE ap |
|
1315 |
SET paid = ?, datepaid = ? |
|
1316 |
WHERE id = ?|; |
|
1317 |
@values = ($form->{paid}, $form->{paid} ? conv_date($form->{datepaid}) : undef, conv_i($form->{id})); |
|
1318 |
do_query($form, $dbh, $query, @values); |
|
1316 |
my @after; |
|
1317 |
push @after, selectall_hashref_query($form, $dbh, qq|SELECT id, paid, datepaid FROM ap WHERE id = ?|, $form->{id}); |
|
1318 |
push @after, selectall_hashref_query($form, $dbh, qq|SELECT * FROM acc_trans WHERE trans_id = ? ORDER BY oid|, $form->{id}); |
|
1319 |
|
|
1320 |
foreach my $rows (@prior, @after) { |
|
1321 |
map { delete @{$_}{qw(itime mtime)} } @{ $rows }; |
|
1322 |
} |
|
1323 |
|
|
1324 |
map { $main::lxdebug->dump_sql_result(0, 'davor ', $_) } @prior; |
|
1325 |
map { $main::lxdebug->dump_sql_result(0, 'danach', $_) } @after; |
|
1319 | 1326 |
|
1327 |
my $rc = 1; |
|
1320 | 1328 |
my $rc = $dbh->commit(); |
1321 | 1329 |
$dbh->disconnect(); |
1322 | 1330 |
|
Auch abrufbar als: Unified diff
Die Funktion "Zahlung buchen" bei Eingangsrechnungen komplett umgeschrieben. Sie verlässt sich nun nicht mehr auf die aktuellen Daten in $form, um die alten Einträge in acc_trans zu löschen, sondern lädt den vorherigen Stand aus der Datenbank, entfernt darauf basierend die Einträge in acc_trans und lässt IR->post_transaction() selber die Zahlungen eintragen.