+sub get_transdate {
+ $main::lxdebug->enter_sub();
+
+ my ($self, $myconfig, $form) = @_;
+
+ # connect to database
+ my $dbh = $form->dbconnect($myconfig);
+
+ my $query =
+ "SELECT COALESCE(" .
+ " (SELECT transdate FROM ap WHERE id = " .
+ " (SELECT MAX(id) FROM ap) LIMIT 1), " .
+ " current_date)";
+ ($form->{transdate}) = $dbh->selectrow_array($query);
+
+ $dbh->disconnect;
+
+ $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();
+
+ my ($self, $myconfig, $form, $locale) = @_;
+
+ # connect to database, turn off autocommit
+ my $dbh = $form->dbconnect_noauto($myconfig);
+
+ my (%payments, $old_form, $row, $item, $query, %keep_vars);
+
+ $old_form = save_form();
+
+ # Delete all entries in acc_trans from prior payments.
+ $self->_delete_payments($form, $dbh);
+
+ # Save the new payments the user made before cleaning up $form.
+ my $payments_re = '^datepaid_\d+$|^memo_\d+$|^source_\d+$|^exchangerate_\d+$|^paid_\d+$|^paid_project_id_\d+$|^AP_paid_\d+$|^paidaccounts$';
+ map { $payments{$_} = $form->{$_} } grep m/$payments_re/, keys %{ $form };
+
+ # 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 };
+
+ # Retrieve the invoice from the database.
+ $form->create_links('AP', $myconfig, 'vendor', $dbh);
+
+ # Restore the payment options from the user input.
+ map { $form->{$_} = $payments{$_} } keys %payments;
+
+ # Set up the content of $form in the way that AR::post_transaction() expects.
+
+ $self->setup_form($form);
+
+ ($form->{defaultcurrency}) = selectrow_query($form, $dbh, qq|SELECT curr FROM defaults|);
+ $form->{defaultcurrency} = (split m/:/, $form->{defaultcurrency})[0];
+
+ $form->{exchangerate} = $form->format_amount($myconfig, $form->{exchangerate});
+
+ # Get the AP accno.
+ $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|;
+
+ ($form->{APselected}) = selectfirst_array_query($form, $dbh, $query, conv_i($form->{id}));
+
+ # Post the new payments.
+ $self->post_transaction($myconfig, $form, $dbh, 1);
+
+ restore_form($old_form);
+
+ my $rc = $dbh->commit();
+ $dbh->disconnect();
+
+ $main::lxdebug->leave_sub();
+
+ return $rc;
+}
+
+sub setup_form {
+ $main::lxdebug->enter_sub();
+
+ my ($self, $form) = @_;
+
+ my ($exchangerate, $i, $j, $k, $key, $akey, $ref, $index, $taxamount, $totalamount);
+
+ # forex
+ $form->{forex} = $form->{exchangerate};
+ $exchangerate = ($form->{exchangerate}) ? $form->{exchangerate} : 1;
+
+ foreach $key (keys %{ $form->{AP_links} }) {
+ foreach $ref (@{ $form->{AP_links}{$key} }) {
+ if ($key eq "AP_paid") {
+ $form->{"select$key"} .= "<option value=\"$ref->{accno}\">$ref->{accno}--$ref->{description}</option>\n";
+ } else {
+ $form->{"select$key"} .= "<option value=\"$ref->{accno}--$ref->{tax_id}\">$ref->{accno}--$ref->{description}</option>\n";
+ }
+ }
+
+ $form->{$key} = $form->{"select$key"};
+
+ # if there is a value we have an old entry
+ $j = 0;
+ $k = 0;
+
+ for $i (1 .. scalar @{ $form->{acc_trans}{$key} }) {
+
+ if ($key eq "AP_paid") {
+ $j++;
+ $form->{"AP_paid_$j"} = "$form->{acc_trans}{$key}->[$i-1]->{accno}--$form->{acc_trans}{$key}->[$i-1]->{description}";
+ $form->{"paid_$j"} = $form->{acc_trans}{$key}->[$i - 1]->{amount};
+ $form->{"datepaid_$j"} = $form->{acc_trans}{$key}->[$i - 1]->{transdate};
+ $form->{"source_$j"} = $form->{acc_trans}{$key}->[$i - 1]->{source};
+ $form->{"memo_$j"} = $form->{acc_trans}{$key}->[$i - 1]->{memo};
+
+ $form->{"exchangerate_$i"} = $form->{acc_trans}{$key}->[$i - 1]->{exchangerate};
+ $form->{"forex_$j"} = $form->{"exchangerate_$i"};
+ $form->{"AP_paid_$j"} = $form->{acc_trans}{$key}->[$i-1]->{accno};
+ $form->{"paid_project_id_$j"} = $form->{acc_trans}{$key}->[$i - 1]->{project_id};
+ $form->{paidaccounts}++;
+
+ } else {
+ $akey = $key;
+ $akey =~ s/AP_//;
+
+ if (($key eq "AP_tax") || ($key eq "AR_tax")) {
+ $form->{"${key}_$form->{acc_trans}{$key}->[$i-1]->{accno}"} = "$form->{acc_trans}{$key}->[$i-1]->{accno}--$form->{acc_trans}{$key}->[$i-1]->{description}";
+ $form->{"${akey}_$form->{acc_trans}{$key}->[$i-1]->{accno}"} = $form->round_amount($form->{acc_trans}{$key}->[$i - 1]->{amount} / $exchangerate, 2);
+
+ if ($form->{"$form->{acc_trans}{$key}->[$i-1]->{accno}_rate"} > 0) {
+ $totaltax += $form->{"${akey}_$form->{acc_trans}{$key}->[$i-1]->{accno}"};
+ } else {
+ $totalwithholding += $form->{"${akey}_$form->{acc_trans}{$key}->[$i-1]->{accno}"};
+ $withholdingrate += $form->{"$form->{acc_trans}{$key}->[$i-1]->{accno}_rate"};
+ }
+
+ $index = $form->{acc_trans}{$key}->[$i - 1]->{index};
+ $form->{"tax_$index"} = $form->{acc_trans}{$key}->[$i - 1]->{amount} * -1;
+ $totaltax += $form->{"tax_$index"};
+
+ } else {
+ $k++;
+ $form->{"${akey}_$k"} = $form->round_amount($form->{acc_trans}{$key}->[$i - 1]->{amount} / $exchangerate, 2);
+
+ if ($akey eq 'amount') {
+ $form->{rowcount}++;
+ $form->{"${akey}_$i"} *= -1;
+ $totalamount += $form->{"${akey}_$i"};
+ $form->{taxrate} = $form->{acc_trans}{$key}->[$i - 1]->{rate};
+
+ $form->{"projectnumber_$k"} = "$form->{acc_trans}{$key}->[$i-1]->{projectnumber}";
+ $form->{"oldprojectnumber_$k"} = $form->{"projectnumber_$k"};
+ $form->{"project_id_$k"} = "$form->{acc_trans}{$key}->[$i-1]->{project_id}";
+ }
+
+ $form->{"${key}_$k"} = "$form->{acc_trans}{$key}->[$i-1]->{accno}--$form->{acc_trans}{$key}->[$i-1]->{description}";
+
+ my $q_description = quotemeta($form->{acc_trans}{$key}->[$i-1]->{description});
+ $form->{"select${key}"} =~
+ m/<option value=\"
+ ($form->{acc_trans}{$key}->[$i-1]->{accno}--[^\"]*)
+ \">
+ $form->{acc_trans}{$key}->[$i-1]->{accno}
+ --
+ ${q_description}
+ <\/option>\n/x;
+ $form->{"${key}_$k"} = $1;
+
+ if ($akey eq "AP") {
+ $form->{APselected} = $form->{acc_trans}{$key}->[$i-1]->{accno};
+
+ } elsif ($akey eq 'amount') {
+ $form->{"${key}_$k"} = $form->{acc_trans}{$key}->[$i-1]->{accno} . "--" . $form->{acc_trans}{$key}->[$i-1]->{id};
+ $form->{"taxchart_$k"} = $form->{acc_trans}{$key}->[$i-1]->{id} . "--" . $form->{acc_trans}{$key}->[$i-1]->{rate};
+ }
+ }
+ }
+ }
+ }
+
+ $form->{taxincluded} = $taxincluded if ($form->{id});
+ $form->{paidaccounts} = 1 if not defined $form->{paidaccounts};
+
+ if ($form->{taxincluded} && $form->{taxrate} && $totalamount) {
+ # add tax to amounts and invtotal
+ for $i (1 .. $form->{rowcount}) {
+ $taxamount = ($totaltax + $totalwithholding) * $form->{"amount_$i"} / $totalamount;
+ $tax = $form->round_amount($taxamount, 2);
+ $diff += ($taxamount - $tax);
+ $form->{"amount_$i"} += $form->{"tax_$i"};
+ }
+
+ $form->{amount_1} += $form->round_amount($diff, 2);
+ }
+
+ $taxamount = $form->round_amount($taxamount, 2);
+ $form->{invtotal} = $totalamount + $totaltax;
+
+ $main::lxdebug->leave_sub();
+}
+
+sub storno {
+ $main::lxdebug->enter_sub();
+
+ my ($self, $form, $myconfig, $id) = @_;
+
+ my ($query, $new_id, $storno_row, $acc_trans_rows);
+ my $dbh = $form->get_standard_dbh($myconfig);
+
+ $query = qq|SELECT nextval('glid')|;
+ ($new_id) = selectrow_query($form, $dbh, $query);
+
+ $query = qq|SELECT * FROM ap WHERE id = ?|;
+ $storno_row = selectfirst_hashref_query($form, $dbh, $query, $id);
+
+ $storno_row->{id} = $new_id;
+ $storno_row->{storno_id} = $id;
+ $storno_row->{storno} = 't';
+ $storno_row->{invnumber} = 'Storno-' . $storno_row->{invnumber};
+ $storno_row->{amount} *= -1;
+ $storno_row->{netamount} *= -1;
+ $storno_row->{paid} = $storno_row->{amount};
+
+ delete @$storno_row{qw(itime mtime)};
+
+ $query = sprintf 'INSERT INTO ap (%s) VALUES (%s)', join(', ', keys %$storno_row), join(', ', map '?', values %$storno_row);
+ do_query($form, $dbh, $query, (values %$storno_row));
+
+ $query = qq|UPDATE ap SET paid = amount + paid, storno = 't' WHERE id = ?|;
+ do_query($form, $dbh, $query, $id);
+
+ # now copy acc_trans entries
+ $query = qq|SELECT a.*, c.link FROM acc_trans a LEFT JOIN chart c ON a.chart_id = c.id WHERE a.trans_id = ? ORDER BY a.oid|;
+ my $rowref = selectall_hashref_query($form, $dbh, $query, $id);
+
+ # kill all entries containing payments, which are the last 2n rows, of which the last has link =~ /paid/
+ while ($rowref->[-1]{link} =~ /paid/) {
+ splice(@$rowref, -2);
+ }
+
+ for my $row (@$rowref) {
+ delete @$row{qw(itime mtime link)};
+ $query = sprintf 'INSERT INTO acc_trans (%s) VALUES (%s)', join(', ', keys %$row), join(', ', map '?', values %$row);
+ $row->{trans_id} = $new_id;
+ $row->{amount} *= -1;
+ do_query($form, $dbh, $query, (values %$row));
+ }
+
+ $dbh->commit;
+
+ $main::lxdebug->leave_sub();
+}
+