From: Moritz Bunkus Date: Fri, 1 Jun 2007 10:13:43 +0000 (+0000) Subject: Die Funktion "Zahlung buchen" bei Eingangsrechnungen komplett umgeschrieben. Sie... X-Git-Tag: release-2.4.3^2~213 X-Git-Url: http://wagnertech.de/git?a=commitdiff_plain;h=d50a9e203b15a930fedfd09d3215e0696555b852;p=kivitendo-erp.git 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. --- diff --git a/SL/IR.pm b/SL/IR.pm index 748a9c159..97b179285 100644 --- a/SL/IR.pm +++ b/SL/IR.pm @@ -37,14 +37,15 @@ package IR; use SL::AM; use SL::Common; use SL::DBUtils; +use SL::MoreCommon; sub post_invoice { $main::lxdebug->enter_sub(); - my ($self, $myconfig, $form) = @_; + my ($self, $myconfig, $form, $provided_dbh, $payments_only) = @_; # connect to database, turn off autocommit - my $dbh = $form->dbconnect_noauto($myconfig); + my $dbh = $provided_dbh ? $provided_dbh : $form->dbconnect_noauto($myconfig); my ($query, $sth, @values, $project_id); my ($allocated, $taxrate, $taxamount, $taxdiff, $item); @@ -54,17 +55,21 @@ sub post_invoice { my $all_units = AM->retrieve_units($myconfig, $form); - if ($form->{id}) { + if (!$payments_only) { + if ($form->{id}) { + &reverse_invoice($dbh, $form); - &reverse_invoice($dbh, $form); - - } else { - ($form->{id}) = selectrow_query($form, $dbh, qq|SELECT nextval('glid')|); + } else { + ($form->{id}) = selectrow_query($form, $dbh, qq|SELECT nextval('glid')|); - do_query($form, $dbh, qq|INSERT INTO ap (id, invnumber) VALUES (?, '')|, $form->{id}); + do_query($form, $dbh, qq|INSERT INTO ap (id, invnumber) VALUES (?, '')|, $form->{id}); + } } - if ($form->{currency} eq $form->{defaultcurrency}) { + my ($currencies) = selectfirst_array_query($form, $dbh, qq|SELECT curr FROM defaults|); + my $defaultcurrency = (split m/:/, $currencies)[0]; + + if ($form->{currency} eq $defaultcurrency) { $form->{exchangerate} = 1; } else { $exchangerate = @@ -172,6 +177,10 @@ sub post_invoice { $form->{"sellprice_$i"} = $form->round_amount($form->{"sellprice_$i"} * $form->{exchangerate}, $decimalplaces); + $lastinventoryaccno = $form->{"inventory_accno_$i"}; + + next if $payments_only; + # update parts table $query = qq|UPDATE parts SET lastcost = ? WHERE id = ?|; @values = ($form->{"sellprice_$i"}, conv_i($form->{"id_$i"})); @@ -247,8 +256,6 @@ sub post_invoice { $sth->finish(); - $lastinventoryaccno = $form->{"inventory_accno_$i"}; - } else { $linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"}, 2); @@ -296,11 +303,15 @@ sub post_invoice { # adjust and round sellprice $form->{"sellprice_$i"} = $form->round_amount($form->{"sellprice_$i"} * $form->{exchangerate}, $decimalplaces); + next if $payments_only; + # update lastcost $query = qq|UPDATE parts SET lastcost = ? WHERE id = ?|; do_query($form, $dbh, $query, $form->{"sellprice_$i"}, conv_i($form->{"id_$i"})); } + next if $payments_only; + # save detail record in invoice table $query = qq|INSERT INTO invoice (trans_id, parts_id, description, qty, base_qty, @@ -385,7 +396,7 @@ sub post_invoice { } # update exchangerate - if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) { + if (($form->{currency} ne $defaultcurrency) && !$exchangerate) { $form->update_exchangerate($dbh, $form->{currency}, $form->{invdate}, 0, $form->{exchangerate}); } @@ -393,7 +404,8 @@ sub post_invoice { foreach my $trans_id (keys %{ $form->{amount} }) { foreach my $accno (keys %{ $form->{amount}{$trans_id} }) { $form->{amount}{$trans_id}{$accno} = $form->round_amount($form->{amount}{$trans_id}{$accno}, 2); - next unless $form->{amount}{$trans_id}{$accno}; + + next if ($payments_only || !$form->{amount}{$trans_id}{$accno}); $query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, taxkey, project_id) VALUES (?, (SELECT id FROM chart WHERE accno = ?), ?, ?, @@ -447,7 +459,7 @@ sub post_invoice { $exchangerate = 0; - if ($form->{currency} eq $form->{defaultcurrency}) { + if ($form->{currency} eq $defaultcurrency) { $form->{"exchangerate_$i"} = 1; } else { $exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{"datepaid_$i"}, 'sell'); @@ -476,7 +488,7 @@ sub post_invoice { $paiddiff = 0; # update exchange rate - if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) { + if (($form->{currency} ne $defaultcurrency) && !$exchangerate) { $form->update_exchangerate($dbh, $form->{currency}, $form->{"datepaid_$i"}, 0, $form->{"exchangerate_$i"}); @@ -496,6 +508,19 @@ sub post_invoice { } } + if ($payments_only) { + $query = qq|UPDATE ap SET paid = ?, datepaid = ? WHERE id = ?|; + do_query($form, $dbh, $query, $form->{paid}, $form->{paid} ? conv_date($form->{datepaid}) : undef, conv_i($form->{id})); + + if (!$provided_dbh) { + $dbh->commit(); + $dbh->disconnect(); + } + + $main::lxdebug->leave_sub(); + return; + } + $amount = $netamount + $tax; # set values which could be empty @@ -569,8 +594,12 @@ sub post_invoice { Common::webdav_folder($form) if ($main::webdav); - my $rc = $dbh->commit; - $dbh->disconnect; + my $rc = 1; + + if (!$provided_dbh) { + $rc = $dbh->commit(); + $dbh->disconnect(); + } $main::lxdebug->leave_sub(); @@ -1177,6 +1206,45 @@ sub item_links { $main::lxdebug->leave_sub(); } +sub _delete_payments { + $main::lxdebug->enter_sub(); + + my ($self, $form, $dbh) = @_; + + my @delete_oids; + + # Delete old payment entries from acc_trans. + my $query = + qq|SELECT oid + FROM acc_trans + WHERE (trans_id = ?) AND fx_transaction + + UNION + + SELECT at.oid + FROM acc_trans at + LEFT JOIN chart c ON (at.chart_id = c.id) + WHERE (trans_id = ?) AND (c.link LIKE '%AP_paid%')|; + push @delete_oids, selectall_array_query($form, $dbh, $query, conv_i($form->{id}), conv_i($form->{id})); + + $query = + qq|SELECT at.oid + FROM acc_trans at + LEFT JOIN chart c ON (at.chart_id = c.id) + WHERE (trans_id = ?) + AND ((c.link = 'AP') OR (c.link LIKE '%:AP') OR (c.link LIKE 'AP:%')) + ORDER BY at.oid + OFFSET 1|; + push @delete_oids, selectall_array_query($form, $dbh, $query, conv_i($form->{id})); + + if (@delete_oids) { + $query = qq|DELETE FROM acc_trans WHERE oid IN (| . join(", ", @delete_oids) . qq|)|; + do_query($form, $dbh, $query); + } + + $main::lxdebug->leave_sub(); +} + sub post_payment { $main::lxdebug->enter_sub(); @@ -1185,138 +1253,78 @@ sub post_payment { # connect to database, turn off autocommit my $dbh = $form->dbconnect_noauto($myconfig); - $form->{datepaid} = $form->{invdate}; + my (%payments, $old_form, $row, $item, $query, %keep_vars); - # total payments, don't move we need it here - for my $i (1 .. $form->{paidaccounts}) { - $form->{"paid_$i"} = $form->parse_amount($myconfig, $form->{"paid_$i"}); - $form->{paid} += $form->{"paid_$i"}; - $form->{datepaid} = $form->{"datepaid_$i"} if ($form->{"datepaid_$i"}); - } - $form->{exchangerate} = - $form->get_exchangerate($dbh, $form->{currency}, $form->{invdate}, "buy"); + my @prior; + push @prior, selectall_hashref_query($form, $dbh, qq|SELECT id, paid, datepaid FROM ap WHERE id = ?|, $form->{id}); + push @prior, selectall_hashref_query($form, $dbh, qq|SELECT * FROM acc_trans WHERE trans_id = ? ORDER BY oid|, $form->{id}); - my $project_id = conv_i($form->{"globalproject_id"}); - # record payments and offsetting AP - for my $i (1 .. $form->{paidaccounts}) { - next if $form->{"paid_$i"} == 0; - my ($accno) = split /--/, $form->{"AP_paid_$i"}; - $form->{"datepaid_$i"} = $form->{invdate} unless $form->{"datepaid_$i"}; - $form->{datepaid} = $form->{"datepaid_$i"}; - $exchangerate = 0; - if (($form->{currency} eq $form->{defaultcurrency}) || ($form->{defaultcurrency} eq "")) { - $form->{"exchangerate_$i"} = 1; + $old_form = save_form(); - } else { - $exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{"datepaid_$i"}, 'buy'); + # Delete all entries in acc_trans from prior payments. + $self->_delete_payments($form, $dbh); - $form->{"exchangerate_$i"} = - ($exchangerate) - ? $exchangerate - : $form->parse_amount($myconfig, $form->{"exchangerate_$i"}); - } + # Save the new payments the user made before cleaning up $form. + map { $payments{$_} = $form->{$_} } grep m/^datepaid_\d+$|^memo_\d+$|^source_\d+$|^exchangerate_\d+$|^paid_\d+$|^AP_paid_\d+$|^paidaccounts$/, keys %{ $form }; - # record AP - $amount = $form->round_amount($form->{"paid_$i"} * $form->{"exchangerate"}, 2) * -1; + # Clean up $form so that old content won't tamper the results. + %keep_vars = map { $_, 1 } qw(login password id); + map { delete $form->{$_} unless $keep_vars{$_} } keys %{ $form }; - $query = - qq|DELETE FROM acc_trans - WHERE (trans_id = ?) - AND (chart_id = (SELECT c.id FROM chart c WHERE c.accno = ?)) - AND (amount = ?) - AND (transdate = ?)|; - @values = (conv_i($form->{id}), $form->{AP}, $amount, conv_date($form->{"datepaid_$i"})); - do_query($form, $dbh, $query, @values); + # Retrieve the invoice from the database. + $self->retrieve_invoice($myconfig, $form); - $query = - qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, taxkey, project_id) - VALUES (?, (SELECT c.id FROM chart c WHERE c.accno = ?), ?, ?, - (SELECT taxkey_id FROM chart WHERE accno = ?), ?)|; - @values = (conv_i($form->{id}), $form->{AP}, $amount, - conv_date($form->{"datepaid_$i"}), $form->{AP}, $project_id); - do_query($form, $dbh, $query, @values); + # Set up the content of $form in the way that IR::post_invoice() expects. + $form->{exchangerate} = $form->format_amount($myconfig, $form->{exchangerate}); - $query = - qq|DELETE FROM acc_trans - WHERE (trans_id = ?) - AND (chart_id=(SELECT c.id FROM chart c WHERE c.accno = ?)) - AND (amount = ?) - AND (transdate = ?) - AND (source = ?) - AND (memo = ?)|; - @values = (conv_i($form->{id}), $accno, $form->{"paid_$i"}, - conv_date($form->{"datepaid_$i"}), $form->{"source_$i"}, - $form->{"memo_$i"}); - do_query($form, $dbh, $query, @values); + for $row (1 .. scalar @{ $form->{invoice_details} }) { + $item = $form->{invoice_details}->[$row - 1]; - $query = - qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, source, memo, taxkey, project_id) - VALUES (?, (SELECT c.id FROM chart c WHERE c.accno = ?), ?, ?, ?, ?, - (SELECT taxkey_id FROM chart WHERE accno = ?), ?)|; - @values = (conv_i($form->{id}), $accno, $form->{"paid_$i"}, - conv_date($form->{"datepaid_$i"}), $form->{"source_$i"}, - $form->{"memo_$i"}, $accno, $project_id); - do_query($form, $dbh, $query, @values); + map { $item->{$_} = $form->format_amount($myconfig, $item->{$_}) } qw(qty sellprice); - # gain/loss - $amount = $form->{"paid_$i"} * $form->{exchangerate} - $form->{"paid_$i"} * $form->{"exchangerate_$i"}; + map { $form->{"${_}_${row}"} = $item->{$_} } keys %{ $item }; + } - if ($amount > 0) { - $form->{fx}{ $form->{fxgain_accno} }{ $form->{"datepaid_$i"} } += $amount; - } else { - $form->{fx}{ $form->{fxloss_accno} }{ $form->{"datepaid_$i"} } += $amount; - } + $form->{rowcount} = scalar @{ $form->{invoice_details} }; - $diff = 0; + delete @{$form}{qw(invoice_details paidaccounts storno paid)}; - # update exchange rate - if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) { - $form->update_exchangerate($dbh, $form->{currency}, - $form->{"datepaid_$i"}, - $form->{"exchangerate_$i"}, 0); - } - } + # Restore the payment options from the user input. + map { $form->{$_} = $payments{$_} } keys %payments; - # record exchange rate differences and gains/losses - foreach my $accno (keys %{ $form->{fx} }) { - foreach my $transdate (keys %{ $form->{fx}{$accno} }) { - $form->{fx}{$accno}{$transdate} = $form->round_amount($form->{fx}{$accno}{$transdate}, 2); - next if $form->{fx}{$accno}{$transdate} == 0; + # Get the AP accno (which is normally done by Form::create_links()). + $query = + qq|SELECT c.accno + FROM acc_trans at + LEFT JOIN chart c ON (at.chart_id = c.id) + WHERE (trans_id = ?) + AND ((c.link = 'AP') OR (c.link LIKE '%:AP') OR (c.link LIKE 'AP:%')) + ORDER BY at.oid + LIMIT 1|; - $query = - qq|DELETE FROM acc_trans - WHERE (trans_id = ?) - AND (chart_id = (SELECT id FROM chart WHERE accno = ?)) - AND (amount = ?) - AND (transdate = ?) - AND (cleared = '0') - AND (fx_transaction = '1')|; - @values = (conv_i($form->{id}), $accno, $form->{fx}{$accno}{$transdate}, $transdate); - do_query($form, $dbh, $query, @values); + ($form->{AP}) = selectfirst_array_query($form, $dbh, $query, conv_i($form->{id})); - $query = - qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, cleared, fx_transaction, taxkey, project_id) - VALUES (?, (SELECT id FROM chart WHERE accno = ?), ?, ?, '0', '1', - (SELECT taxkey_id FROM chart WHERE accno = ?), ?)|; - @values = (conv_i($form->{id}), $accno, $form->{fx}{$accno}{$transdate}, - $transdate, $accno, $project_id); - do_query($form, $dbh, $query, @values); - } - } + # Post the new payments. + $self->post_invoice($myconfig, $form, $dbh, 1); - my $datepaid = $form->{paid} ? qq|'$form->{datepaid}'| : "NULL"; + restore_form($old_form); - # save AP record - my $query = qq|UPDATE ap - SET paid = ?, datepaid = ? - WHERE id = ?|; - @values = ($form->{paid}, $form->{paid} ? conv_date($form->{datepaid}) : undef, conv_i($form->{id})); - do_query($form, $dbh, $query, @values); + my @after; + push @after, selectall_hashref_query($form, $dbh, qq|SELECT id, paid, datepaid FROM ap WHERE id = ?|, $form->{id}); + push @after, selectall_hashref_query($form, $dbh, qq|SELECT * FROM acc_trans WHERE trans_id = ? ORDER BY oid|, $form->{id}); + + foreach my $rows (@prior, @after) { + map { delete @{$_}{qw(itime mtime)} } @{ $rows }; + } + + map { $main::lxdebug->dump_sql_result(0, 'davor ', $_) } @prior; + map { $main::lxdebug->dump_sql_result(0, 'danach', $_) } @after; + my $rc = 1; my $rc = $dbh->commit(); $dbh->disconnect();