[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
FX differences: correction program to be included in Fixes.sql?
- Subject: FX differences: correction program to be included in Fixes.sql?
- From: Erik Huelsmann <..hidden..>
- Date: Wed, 4 Jan 2012 22:13:11 +0100
Hi,
Because I had fractional-cent differences between the AR amount and
the payment amount posted, my invoices kept showing as candidates for
clearing, even though the foreign currency amount added up to 0. The
tip of the 1.3 branch has this issue fixed for general AR/AP
transactions (although I'd very much like verification+confirmation of
the fix).
Even though the 1.3 branch tip has the fix, my database was still off.
So, I worked out the plpgsql function below to fix my ledger. It does
nothing more than select the last AP and fxgain/loss transactions and
use all the characteristics in those postings to create a
fractional-cent posting to make the numbers exact matches.
Remarks? Comments?
BTW: there's one problem running it from Fixes.sql: my ledgersmb user
which I use to run db upgrades isn't a lsmb user. However, when
inserting records, the audittrail trigger is being fired, which tries
to post records in the audit tables. This fails, because the lookup of
the current session user in the users table returns NULL which
violates some key constraint. So we probably need to think where to
include it if not in Fixes.sql.
Bye,
Erik.
CREATE OR REPLACE FUNCTION fixup_ar_ap_fx_differences(link_name text)
RETURNS VOID AS
$$
DECLARE
ap_acc_id int;
fxgain_acc_id int;
fxloss_acc_id int;
transid int;
diff numeric;
trans_date date;
BEGIN
-- Variable initialization
SELECT id INTO ap_acc_id
FROM account acc
JOIN account_link al
ON (acc.id = al.account_id)
WHERE al.description = link_name;
SELECT value::int INTO fxgain_acc_id
FROM defaults
WHERE setting_key = 'fxgain_accno_id';
SELECT value::int into fxloss_acc_id
FROM defaults
WHERE setting_key = 'fxloss_accno_id';
FOR transid, diff IN
-- select transactions with rounding differences
-- which have fx effects. Hopefully there are no
-- others and we're definitely not out to fix those here.
SELECT trans_id, sum(amount)
FROM acc_trans
WHERE chart_id = ap_acc_id
AND trans_id IN (SELECT trans_id
FROM acc_trans
WHERE chart_id = fxgain_acc_id
OR chart_id = fxloss_acc_id)
GROUP BY trans_id
HAVING abs(sum(amount)) <= 0.005 AND sum(amount) <> 0
LOOP
RAISE NOTICE 'trans_id %, diff %', transid, diff;
DECLARE
fx_gainloss_line acc_trans%ROWTYPE;
ap_line acc_trans%ROWTYPE;
diff_multiplier int;
BEGIN
-- select the most recent gain/loss posting
SELECT * INTO fx_gainloss_line
FROM acc_trans
WHERE trans_id = transid
AND (chart_id = fxgain_acc_id
OR chart_id = fxloss_acc_id)
ORDER BY transdate DESC
LIMIT 1;
-- select the most recent ar/ap posting
SELECT * INTO ap_line
FROM acc_trans
WHERE trans_id = transid
AND chart_id = ap_acc_id
ORDER BY transdate DESC
LIMIT 1;
-- Create postings required to make the difference go away
INSERT INTO acc_trans (trans_id, chart_id, amount, transdate,
source, cleared, fx_transaction, project_id, memo, invoice_id,
approved, cleared_on, reconciled_on, voucher_id)
VALUES (fx_gainloss_line.trans_id, fx_gainloss_line.chart_id,
diff, fx_gainloss_line.transdate, 'correction program',
fx_gainloss_line.cleared, fx_gainloss_line.fx_transaction,
fx_gainloss_line.project_id, fx_gainloss_line.memo,
fx_gainloss_line.invoice_id, fx_gainloss_line.approved,
fx_gainloss_line.cleared_on, fx_gainloss_line.reconciled_on,
fx_gainloss_line.voucher_id);
INSERT INTO acc_trans (trans_id, chart_id, amount, transdate,
source, cleared, fx_transaction, project_id, memo, invoice_id,
approved, cleared_on, reconciled_on, voucher_id)
VALUES (ap_line.trans_id, ap_line.chart_id,
diff * -1, ap_line.transdate, 'correction program',
ap_line.cleared, ap_line.fx_transaction,
ap_line.project_id, ap_line.memo,
ap_line.invoice_id, ap_line.approved,
ap_line.cleared_on, ap_line.reconciled_on,
ap_line.voucher_id);
END;
END LOOP;
UPDATE ar
SET paid = amount - (SELECT sum(amount)
FROM acc_trans ac
JOIN account acc ON (ac.chart_id = acc.id)
JOIN account_link al ON (acc.id = al.account_id)
WHERE al.description = 'AR'
AND ac.trans_id = ar.id)
WHERE amount <> paid;
UPDATE ap
SET paid = amount - (SELECT sum(amount)
FROM acc_trans ac
JOIN account acc ON (ac.chart_id = acc.id)
JOIN account_link al ON (acc.id = al.account_id)
WHERE al.description = 'AP'
AND ac.trans_id = ap.id)
WHERE amount <> paid;
END;
$$ LANGUAGE plpgsql;
SELECT fixup_ar_ap_fx_differences('AR');
SELECT fixup_ar_ap_fx_differences('AP');