#===================================================================== # SQL-Ledger Accounting # Copyright (C) 2002 # # Author: Dieter Simader # Email: dsimader@sql-ledger.org # Web: http://www.sql-ledger.org # # Contributors: # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #====================================================================== # # Account reconciliation routines # #====================================================================== package RC; sub paymentaccounts { my ($self, $myconfig, $form) = @_; # connect to database my $dbh = $form->dbconnect($myconfig); my $query = qq|SELECT accno, description FROM chart WHERE link LIKE '%_paid%' AND (category = 'A' OR category = 'L') ORDER BY accno|; my $sth = $dbh->prepare($query); $sth->execute || $form->dberror($query); while (my $ref = $sth->fetchrow_hashref(NAME_lc)) { push @{ $form->{PR} }, $ref; } $sth->finish; $form->all_years($dbh, $myconfig); $dbh->disconnect; } sub payment_transactions { my ($self, $myconfig, $form) = @_; # connect to database, turn AutoCommit off my $dbh = $form->dbconnect_noauto($myconfig); my $query; my $sth; $query = qq|SELECT category FROM chart WHERE accno = '$form->{accno}'|; ($form->{category}) = $dbh->selectrow_array($query); my $cleared; ($form->{fromdate}, $form->{todate}) = $form->from_to($form->{year}, $form->{month}, $form->{interval}) if $form->{year} && $form->{month}; my $transdate = qq| AND ac.transdate < date '$form->{fromdate}'|; if (! $form->{fromdate}) { $cleared = qq| AND ac.cleared = '1'|; $transdate = ""; } # get beginning balance $query = qq|SELECT sum(ac.amount) FROM acc_trans ac JOIN chart c ON (c.id = ac.chart_id) WHERE c.accno = '$form->{accno}' $transdate $cleared |; ($form->{beginningbalance}) = $dbh->selectrow_array($query); # fx balance $query = qq|SELECT sum(ac.amount) FROM acc_trans ac JOIN chart c ON (c.id = ac.chart_id) WHERE c.accno = '$form->{accno}' AND ac.fx_transaction = '1' $transdate $cleared |; ($form->{fx_balance}) = $dbh->selectrow_array($query); $transdate = ""; if ($form->{todate}) { $transdate = qq| AND ac.transdate <= date '$form->{todate}'|; } # get statement balance $query = qq|SELECT sum(ac.amount) FROM acc_trans ac JOIN chart c ON (c.id = ac.chart_id) WHERE c.accno = '$form->{accno}' $transdate |; ($form->{endingbalance}) = $dbh->selectrow_array($query); # fx balance $query = qq|SELECT sum(ac.amount) FROM acc_trans ac JOIN chart c ON (c.id = ac.chart_id) WHERE c.accno = '$form->{accno}' AND ac.fx_transaction = '1' $transdate |; ($form->{fx_endingbalance}) = $dbh->selectrow_array($query); $cleared = qq| AND ac.cleared = '0'| unless $form->{fromdate}; if ($form->{report}) { $cleared = qq| AND NOT (ac.cleared = '0' OR ac.cleared = '1')|; if ($form->{cleared}) { $cleared = qq| AND ac.cleared = '1'|; } if ($form->{outstanding}) { $cleared = ($form->{cleared}) ? "" : qq| AND ac.cleared = '0'|; } if (! $form->{fromdate}) { $form->{beginningbalance} = 0; $form->{fx_balance} = 0; } } if ($form->{summary}) { $query = qq|SELECT ac.transdate, ac.source, sum(ac.amount) AS amount, ac.cleared FROM acc_trans ac JOIN chart ch ON (ac.chart_id = ch.id) WHERE ch.accno = '$form->{accno}' AND ac.amount >= 0 AND ac.fx_transaction = '0' $cleared|; $query .= " AND ac.transdate >= '$form->{fromdate}'" if $form->{fromdate}; $query .= " AND ac.transdate <= '$form->{todate}'" if $form->{todate}; $query .= " GROUP BY ac.source, ac.transdate, ac.cleared"; $query .= qq| UNION SELECT ac.transdate, ac.source, sum(ac.amount) AS amount, ac.cleared FROM acc_trans ac JOIN chart ch ON (ac.chart_id = ch.id) WHERE ch.accno = '$form->{accno}' AND ac.amount < 0 AND ac.fx_transaction = '0' $cleared|; $query .= " AND ac.transdate >= '$form->{fromdate}'" if $form->{fromdate}; $query .= " AND ac.transdate <= '$form->{todate}'" if $form->{todate}; $query .= " GROUP BY ac.source, ac.transdate, ac.cleared"; $query .= " ORDER BY 1,2"; } else { $query = qq|SELECT ac.transdate, ac.source, ac.fx_transaction, ac.amount, ac.cleared, g.id, g.description FROM acc_trans ac JOIN chart ch ON (ac.chart_id = ch.id) JOIN gl g ON (g.id = ac.trans_id) WHERE ch.accno = '$form->{accno}' AND ac.fx_transaction = '0' $cleared|; $query .= " AND ac.transdate >= '$form->{fromdate}'" if $form->{fromdate}; $query .= " AND ac.transdate <= '$form->{todate}'" if $form->{todate}; $query .= qq| UNION SELECT ac.transdate, ac.source, ac.fx_transaction, ac.amount, ac.cleared, a.id, n.name FROM acc_trans ac JOIN chart ch ON (ac.chart_id = ch.id) JOIN ar a ON (a.id = ac.trans_id) JOIN customer n ON (n.id = a.customer_id) WHERE ch.accno = '$form->{accno}' AND ac.fx_transaction = '0' $cleared|; $query .= " AND ac.transdate >= '$form->{fromdate}'" if $form->{fromdate}; $query .= " AND ac.transdate <= '$form->{todate}'" if $form->{todate}; $query .= qq| UNION SELECT ac.transdate, ac.source, ac.fx_transaction, ac.amount, ac.cleared, a.id, n.name FROM acc_trans ac JOIN chart ch ON (ac.chart_id = ch.id) JOIN ap a ON (a.id = ac.trans_id) JOIN vendor n ON (n.id = a.vendor_id) WHERE ch.accno = '$form->{accno}' AND ac.fx_transaction = '0' $cleared|; $query .= " AND ac.transdate >= '$form->{fromdate}'" if $form->{fromdate}; $query .= " AND ac.transdate <= '$form->{todate}'" if $form->{todate}; $query .= " ORDER BY 1,2,3"; } $sth = $dbh->prepare($query); $sth->execute || $form->dberror($query); my $dr; my $cr; my $fxs; if ($form->{summary}) { $query = qq|SELECT ac.amount, ac.cleared FROM acc_trans ac JOIN ar a ON (a.id = ac.trans_id) JOIN customer n ON (n.id = a.customer_id) WHERE ac.fx_transaction = '1' AND n.name = ? AND ac.transdate = ? AND ac.trans_id IN (SELECT id FROM ar a JOIN acc_trans ac ON (a.id = ac.trans_id) WHERE ac.source = ?) AND ac.cleared = ? AND NOT (ac.chart_id IN (SELECT fxgain_accno_id FROM defaults UNION SELECT fxloss_accno_id FROM defaults)) |; $query .= qq| UNION SELECT ac.amount, ac.cleared FROM acc_trans ac JOIN ap a ON (a.id = ac.trans_id) JOIN vendor n ON (n.id = a.vendor_id) WHERE ac.fx_transaction = '1' AND n.name = ? AND ac.transdate = ? AND ac.trans_id IN (SELECT id FROM ap a JOIN acc_trans ac ON (a.id = ac.trans_id) WHERE ac.source = ?) AND ac.cleared = ? AND NOT (ac.chart_id IN (SELECT fxgain_accno_id FROM defaults UNION SELECT fxloss_accno_id FROM defaults)) |; } else { $query = qq|SELECT ac.amount, ac.cleared FROM acc_trans ac WHERE ac.trans_id = ? AND ac.fx_transaction = '1' $cleared AND NOT (ac.chart_id IN (SELECT fxgain_accno_id FROM defaults UNION SELECT fxloss_accno_id FROM defaults)) |; } $fxs = $dbh->prepare($query); if ($form->{summary}) { $query = qq|SELECT c.name FROM customer c JOIN ar a ON (c.id = a.customer_id) JOIN acc_trans ac ON (a.id = ac.trans_id) WHERE ac.transdate = ? AND ac.source = ? AND ac.amount > 0 $cleared UNION SELECT v.name FROM vendor v JOIN ap a ON (v.id = a.vendor_id) JOIN acc_trans ac ON (a.id = ac.trans_id) WHERE ac.transdate = ? AND ac.source = ? AND ac.amount > 0 $cleared UNION SELECT g.description FROM gl g JOIN acc_trans ac ON (g.id = ac.trans_id) WHERE ac.transdate = ? AND ac.source = ? AND ac.amount > 0 $cleared |; $query .= " ORDER BY 1"; $dr = $dbh->prepare($query); $query = qq|SELECT c.name FROM customer c JOIN ar a ON (c.id = a.customer_id) JOIN acc_trans ac ON (a.id = ac.trans_id) WHERE ac.transdate = ? AND ac.source = ? AND ac.amount < 0 $cleared UNION SELECT v.name FROM vendor v JOIN ap a ON (v.id = a.vendor_id) JOIN acc_trans ac ON (a.id = ac.trans_id) WHERE ac.transdate = ? AND ac.source = ? AND ac.amount < 0 $cleared UNION SELECT g.description FROM gl g JOIN acc_trans ac ON (g.id = ac.trans_id) WHERE ac.transdate = ? AND ac.source = ? AND ac.amount < 0 $cleared |; $query .= " ORDER BY 1"; $cr = $dbh->prepare($query); } my $name; my $ref; my $xfref; while ($ref = $sth->fetchrow_hashref(NAME_lc)) { if ($form->{summary}) { if ($ref->{amount} > 0) { $dr->execute($ref->{transdate}, $ref->{source}, $ref->{transdate}, $ref->{source}, $ref->{transdate}, $ref->{source}); $ref->{oldcleared} = $ref->{cleared}; $ref->{name} = (); while (($name) = $dr->fetchrow_array) { push @{ $ref->{name} }, $name; } $dr->finish; } else { $cr->execute($ref->{transdate}, $ref->{source}, $ref->{transdate}, $ref->{source}, $ref->{transdate}, $ref->{source}); $ref->{oldcleared} = $ref->{cleared}; $ref->{name} = (); while (($name) = $cr->fetchrow_array) { push @{ $ref->{name} }, $name; } $cr->finish; } } else { push @{ $ref->{name} }, $ref->{description}; } push @{ $form->{PR} }, $ref; # include fx transactions $amount = 0; $addfx = 0; $ref->{oldcleared} = $ref->{cleared}; if ($form->{summary}) { foreach $name (@{ $ref->{name} }) { $fxs->execute($name, $ref->{transdate}, $ref->{source}, $ref->{cleared}, $name, $ref->{transdate}, $ref->{source}, $ref->{cleared}); while ($fxref = $fxs->fetchrow_hashref(NAME_lc)) { $addfx = 1; $amount += $fxref->{amount}; } $fxs->finish; } } else { $fxs->execute($ref->{id}); while ($fxref = $fxs->fetchrow_hashref(NAME_lc)) { $addfx = 1; $amount += $fxref->{amount}; } $fxs->finish; } if ($addfx) { $fxref = (); map { $fxref->{$_} = $ref->{$_} } keys %$ref; $fxref->{fx_transaction} = 1; $fxref->{name} = (); $fxref->{source} = ""; $fxref->{transdate} = ""; $fxref->{amount} = $amount; push @{ $form->{PR} }, $fxref; } } $sth->finish; $dbh->disconnect; } sub reconcile { my ($self, $myconfig, $form) = @_; # connect to database my $dbh = $form->dbconnect($myconfig); my $query = qq|SELECT id FROM chart WHERE accno = '$form->{accno}'|; my ($chart_id) = $dbh->selectrow_array($query); $chart_id *= 1; $query = qq|SELECT trans_id FROM acc_trans WHERE source = ? AND transdate = ? AND cleared = '0'|; my $sth = $dbh->prepare($query) || $form->dberror($query); my $i; my $trans_id; $query = qq|UPDATE acc_trans SET cleared = '1' WHERE cleared = '0' AND trans_id = ? AND transdate = ? AND chart_id = $chart_id|; my $tth = $dbh->prepare($query) || $form->dberror($query); # clear flags for $i (1 .. $form->{rowcount}) { if ($form->{"cleared_$i"} && ! $form->{"oldcleared_$i"}) { if ($form->{summary}) { $sth->execute($form->{"source_$i"}, $form->{"transdate_$i"}) || $form->dberror; while (($trans_id) = $sth->fetchrow_array) { $tth->execute($trans_id, $form->{"transdate_$i"}) || $form->dberror; $tth->finish; } $sth->finish; } else { $tth->execute($form->{"id_$i"}, $form->{"transdate_$i"}) || $form->dberror; $tth->finish; } } } $dbh->disconnect; } 1;