summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authoraurynn_cmd <aurynn_cmd@4979c152-3d1c-0410-bac9-87ea11338e46>2008-06-30 20:56:17 +0000
committeraurynn_cmd <aurynn_cmd@4979c152-3d1c-0410-bac9-87ea11338e46>2008-06-30 20:56:17 +0000
commit49174fdc16c696dcc0f8d4124cb0749f91b6bb4d (patch)
treeb107f877241a59616a231fe3d3e27351a456de2d /sql
parent96f9480b7c2d8a62e34133d6dfd16f1dee23a330 (diff)
Adding the reconciliation SQL stuff. Testing my SVN interface.
git-svn-id: https://ledger-smb.svn.sourceforge.net/svnroot/ledger-smb/trunk@2177 4979c152-3d1c-0410-bac9-87ea11338e46
Diffstat (limited to 'sql')
-rw-r--r--sql/Pg-database.sql4
-rw-r--r--sql/modules/Reconciliaton.sql292
2 files changed, 180 insertions, 116 deletions
diff --git a/sql/Pg-database.sql b/sql/Pg-database.sql
index c9f2bea3..ca907d50 100644
--- a/sql/Pg-database.sql
+++ b/sql/Pg-database.sql
@@ -270,8 +270,8 @@ CREATE TABLE company_to_contact (
company_id integer not null references company(id) ON DELETE CASCADE,
contact_class_id integer references contact_class(id) not null,
contact text check(contact ~ '[[:alnum:]_]') not null,
- description text not null,
- PRIMARY KEY (company_id,contact_class_id,contact));
+ description text,
+ PRIMARY KEY (company_id, contact_class_id, contact));
COMMENT ON TABLE company_to_contact IS $$ To keep track of the relationship between multiple contact methods and a single company $$;
diff --git a/sql/modules/Reconciliaton.sql b/sql/modules/Reconciliaton.sql
index ddb03230..5bc88c0e 100644
--- a/sql/modules/Reconciliaton.sql
+++ b/sql/modules/Reconciliaton.sql
@@ -1,6 +1,31 @@
-BEGIN;
+CREATE TABLE reports (
+ id bigserial primary key not null,
+ report_id int NOT NULL,
+ scn int, -- What is SCN?
+ their_balance numeric,
+ our_balance numeric,
+ errorcode INT,
+ user int references entity(id) not null, -- why ois this not an entity reference?
+ corrections INT NOT NULL DEFAULT 0
+ clear_time TIMESTAMP NOT NULL,
+ insert_time TIMESTAMPTZ NOT NULL DEFAULT now(),
+ ledger_id int REFERENCES acc_trans(entry_id),
+ overlook boolean not null default 'f',
+ approved boolean not null default 'f'
+);
+
+
+CREATE TABLE report_corrections (
+ id serial primary key not null,
+ correction_id int not null default 1,
+ entry references reports(id) not null,
+ user references entity(id) not null, -- why is this not an entity reference?
+ reason text not null,
+ insert_time timestamptz not null default now()
+);
+
-- to correct OUR wrong amount.
-CREATE OR REPLACE FUNCTION reconciliation_correct_ledger (in_report_id INT, in_id int, in_new_amount NUMERIC, reason TEXT) returns INT AS $$
+CREATE OR REPLACE FUNCTION reconciliation__correct_ledger (in_report_id INT, in_id int, in_new_amount NUMERIC, reason TEXT) returns INT AS $$
DECLARE
new_code INT;
@@ -9,36 +34,30 @@ CREATE OR REPLACE FUNCTION reconciliation_correct_ledger (in_report_id INT, in_i
in_user TEXT;
full_reason TEXT;
BEGIN
- select session_user into in_user; -- safer than current_user
+ select into in_user from current_user;
- select * into current_row from pending_reports
- where pending_reports.id = in_report_id and pending_reports.id = in_id;
- select * into l_row from acc_trans where entry_id = current_row.lid;
+ select into current_row from reports where reports.id = in_report_id and reports.id = in_id;
+ select into l_row from acc_trans where entry_id = current_row.lid;
IF NOT FOUND THEN
RAISE EXCEPTION 'No such id % in this report.', in_scn;
END IF;
- IF in_user <> current_row.entered_by THEN
+ IF user <> current_row.user THEN
IF current_row.our_balance <> in_new_amount AND in_new_amount = current_row.their_balance THEN
- update pending_reports
- set corrections = corrections + 1,
- new_balance = in_new_amount,
+ update reports pr
+ set pr.corrections = reports.corrections + 1,
+ pr.new_balance = in_new_amount,
error_code = 0
where id = in_report_id and scn = in_scn;
return 0;
-- After that, it is required to update the general ledger.
- full_reason := 'User % is filing a reconciliation correction '
- || 'on the general ledger, changing amount % to ' ||
- 'amount %.\n' ||
- 'Their reason given is: %',
- in_user, current_row.our_balance, in_new_amount, reason;
-
- select update_ledger(current_row.lid, in_new_amount,
- full_reason);
- ELSIF current_row.our_balance = in_new_amount THEN
+ full_reason := "User % is filing a reconciliation correction on the general ledger, changing amount % to amount %.
+ Their reason given is: %", in_user, current_row.our_balance, in_new_amount, reason;
+ select update_ledger(current_row.lid, in_new_amount, full_reason)
+ ELSE IF current_row.our_balance = in_new_amount THEN
-- This should be something, does it equal the original
-- balance? If so, there's no change.
return current_row.error_code;
@@ -51,33 +70,30 @@ CREATE OR REPLACE FUNCTION reconciliation_correct_ledger (in_report_id INT, in_i
$$ language 'plpgsql';
-- to correct an incorrect bank statement value.
-CREATE OR REPLACE FUNCTION reconciliation_correct_bank_statement (in_report_id INT, in_id int, in_new_amount NUMERIC) returns INT AS $$
+CREATE OR REPLACE FUNCTION reconciliation__correct_bank_statement (in_report_id INT, in_id int, in_new_amount NUMERIC) returns INT AS $$
DECLARE
new_code INT;
current_row RECORD;
in_user TEXT;
BEGIN
- select SESSION_USER into in_user;
- select * into current_row from pending_reports
- where pending_reports.id = in_report_id
- and pending_reports.scn = in_scn;
-
+ select into in_user from current_user;
+ select into current_row from reports where reports.id = in_report_id and reports.scn = in_scn;
IF NOT FOUND THEN
RAISE EXCEPTION 'No such SCN % in this report.', in_scn;
END IF;
- IF in_user <> current_row.entered_by THEN
+ IF user <> current_row.user THEN
IF current_row.their_balance <> in_new_amount AND in_new_amount = current_row.our_balance THEN
- update pending_reports
- set corrections = corrections + 1,
- new_balance = in_new_amount,
+ update reports pr
+ set pr.corrections = reports.corrections + 1,
+ pr.new_balance = in_new_amount,
error_code = 0
where id = in_report_id and scn = in_scn;
return 0;
- ELSIF current_row.their_balance = in_new_amount THEN
+ ELSE IF current_row.their_balance = in_new_amount THEN
-- This should be something, does it equal the original
-- balance? If so, there's no change.
return current_row.error_code;
@@ -90,97 +106,88 @@ CREATE OR REPLACE FUNCTION reconciliation_correct_bank_statement (in_report_id I
$$ language 'plpgsql';
-CREATE OR REPLACE FUNCTION reconciliation_correct_passthrough ( in_report_id int, in_id int ) returns INT AS $$
+CREATE OR REPLACE reconciliation__correct_passthrough ( in_report_id int, in_id int ) returns INT AS $$
DECLARE
in_user TEXT;
- pending_entry pending_reports;
+ pending_entry reports;
BEGIN
- select SESSION_USER into in_user;
+ select into in_user from current_user;
- select * into pending_entry from pending_reports
- where report_id = in_report_id and id = in_id;
+ select into pending_entry from reports where report_id = in_report_id and id = in_id;
IF NOT FOUND THEN
-- Raise an exception.
- RAISE EXCEPTION 'Cannot find entry.';
- ELSIF pending_entry.errorcode <> 4 THEN
+ RAISE EXCEPTION "Cannot find entry.";
+ ELSE IF pending_entry.errorcode <> 4 THEN
-- Only error codes of 4 may be "passed through" safely.
- RAISE EXCEPTION 'Selected entry not permitted to be passed through.';
+ RAISE EXCEPTION "Selected entry not permitted to be passed through.";
ELSE
-- Then we mark it passthroughable, and "approve" will overlook it.
- update pending_reports set overlook = 't', errorcode = 0 where report_id = in_report_id and id = in_id;
+ update reports set overlook = 't', errorcode = 0 where report_id = in_report_id and id = in_id;
return 0;
END IF;
END;
$$ language 'plpgsql';
-CREATE OR REPLACE FUNCTION reconciliation_correct_bank_charge (in_report_id int, in_id int) returns INT AS $$
+CREATE OR REPLACE FUNCTION reconciliation__correct_bank_charge (in_report_id int, in_id int) returns INT AS $$
DECLARE
in_user TEXT;
- pending_entry pending_reports;
+ pending_entry reports;
BEGIN
- select * into pending_entry from pending_reports
- where report_id = in_report_id and id = in_id;
-
IF NOT FOUND THEN
-- Raise an exception.
- RAISE EXCEPTION 'Cannot find entry with ID % in report %.', in_id, in_report_id;
- ELSIF pending_entry.errorcode <> 2 THEN
- -- Only error codes of 4 may be "passed through" safely.
- RAISE EXCEPTION 'Attempt to retroactively add a non-bank-charge entry to the ledger.';
+ RAISE EXCEPTION "Cannot find entry with ID % in report %.", in_id, in_report_id;
+ ELSE IF pending_entry.errorcode <> 2 THEN
+ -- Only error codes of 2 may be "passed through" safely.
+ RAISE EXCEPTION "Attempt to retroactively add a non-bank-charge entry to the ledger.";
ELSE
-- Then we mark it passthroughable, and "approve" will overlook it.
- select create_entry (pending_entry.their_balance, 'payable', pending_entry.clear_time, 'Bank charge');
+ select create_entry (pending_entry.their_balance, 'payable', pending_entry.clear_date, 'Bank charge');
- update pending_reports set errorcode = 0 where report_id = in_report_id and id = in_id;
+ update reports set errorcode = 0 where report_id = in_report_id and id = in_id;
return 0;
END IF;
END;
$$ LANGUAGE 'plpgsql';
-CREATE OR REPLACE FUNCTION reconciliation_correct_unaccounted_charge (in_report_id int, in_id int, reason TEXT) RETURNS INT AS $$
+CREATE OR REPLACE FUNCTION reconciliation__correct_unaccounted_charge (in_report_id int, in_id int, reason TEXT) RETURNS INT AS $$
DECLARE
in_user TEXT;
- pending_entry pending_reports;
+ pending_entry reports;
note TEXT;
BEGIN
- select * into pending_entry from pending_reports
- where report_id = in_report_id and id = in_id;
-
IF NOT FOUND THEN
-- Raise an exception.
- RAISE EXCEPTION 'Cannot find entry with ID % in report %.', in_id, in_report_id;
- ELSIF pending_entry.errorcode <> 3 THEN
- -- Only error codes of 4 may be "passed through" safely.
- RAISE EXCEPTION 'Not an unaccounted charge; cannot be retroactively added to the ledger.';
+ RAISE EXCEPTION "Cannot find entry with ID % in report %.", in_id, in_report_id;
+ ELSE IF pending_entry.errorcode <> 3 THEN
+ -- Only error codes of 3 may be "passed through" safely.
+ RAISE EXCEPTION "Not an unaccounted charge; cannot be retroactively added to the ledger.";
ELSE
-- Then we mark it passthroughable, and "approve" will overlook it.
- note := 'Retroactive addition of an unaccounted entry, of value '
- || pending_entry || '. \n' ||
- 'Being added by user ' || in_user || ' with the following ' ||
- 'explanation: ' || in_reason;
+ note := 'Retroactive addition of an unaccounted entry, of value %.
+ Being added by user % with the following explanation: %', pending_entry.their_balance, in_user, in_reason;
- select create_entry (pending_entry.their_balance, 'payable', pending_entry.clear_time,note);
+ select create_entry (pending_entry.their_balance, 'payable', pending_entry.clear_date,note);
- update pending_reports set errorcode = 0 where report_id = in_report_id and id = in_id;
- return 0;
+ update reports set errorcode = 0 where report_id = in_report_id and id = in_id;
+ return in_id;
END IF;
END;
$$ language 'plpgsql';
-CREATE OR REPLACE FUNCTION reconciliation_report_approve (in_report_id INT) returns INT as $$
+CREATE OR REPLACE FUNCTION reconciliation__report_approve (in_report_id INT) returns INT as $$
-- Does some basic checks before allowing the approval to go through;
-- moves the approval to "reports", I guess, or some other "final" table.
@@ -190,25 +197,25 @@ CREATE OR REPLACE FUNCTION reconciliation_report_approve (in_report_id INT) retu
DECLARE
current_row RECORD;
- completed pending_reports;
+ completed reports;
total_errors INT;
in_user TEXT;
BEGIN
- select SESSION_USER into in_user;
- select * into current_row from pending_reports where report_id = in_report_id;
+ select into in_user current_user;
+ select into current_row distinct on user * from reports where report_id = in_report_id;
IF NOT FOUND THEN
- RAISE EXCEPTION 'Fatal Error: Pending report % not found', in_report_id;
+ RAISE EXCEPTION "Fatal Error: Pending report % not found", in_report_id;
END IF;
- IF current_row.entered_by = in_user THEN
- RAISE EXCEPTION 'Fatal Error: User % cannot self-approve report!', in_user;
+ IF current_row.user = in_user THEN
+ RAISE EXCEPTION "Fatal Error: User % cannot self-approve report!", in_user;
END IF;
- SELECT INTO total_errors count(*) from pending_reports where report_id = in_report_id and error_code <> 0;
+ SELECT INTO total_errors count(*) from reports where report_id = in_report_id and error_code <> 0;
IF total_errors <> 0 THEN
- RAISE EXCEPTION 'Fatal Error: Cannot approve while % uncorrected errors remain.', total_errors;
+ RAISE EXCEPTION "Fatal Error: Cannot approve while % uncorrected errors remain.", total_errors;
END IF;
-- so far, so good. Different user, and no errors remain. Therefore, we can move it to completed reports.
@@ -217,34 +224,38 @@ CREATE OR REPLACE FUNCTION reconciliation_report_approve (in_report_id INT) retu
-- in_user, to note who approved the report, than the user who
-- filed it. This may require clunkier syntax..
- insert into reports
- (report_id, scn, their_balance, our_balance, coentered_by,
- correction )
- SELECT report_id, scn, their_balance, our_balance, code, entered_by,
- corrections
- FROM pending_reports
- WHERE report_id = in_report_id;
+ --
+
+ update reports set approved = 't', clear_time = now() where report_id = in_report_id;
return 1;
END;
$$ language 'plpgsql';
-CREATE OR REPLACE FUNCTION reconciliation_new_report_id () returns BIGINT as $$
+CREATE OR REPLACE FUNCTION reconciliation__new_report_id () returns INT as $$
- SELECT nextval('pending_reports_id_seq');
+ SELECT nextval('pending_report_report_id_seq');
$$ language 'sql';
-create or replace function reconciliation_add_entry(in_report_id INT, in_scn INT, in_amount INT, in_account INT, in_user TEXT, in_date TIMESTAMP) RETURNS INT AS $$
- DECLARE
+create or replace function reconciliation__add_entry(
+ in_report_id INT,
+ in_scn INT,
+ in_amount INT,
+ in_account INT,
+ in_user TEXT,
+ in_date TIMESTAMP
+) RETURNS INT AS $$
+
+ DELCARE
la RECORD;
errorcode INT;
our_value NUMERIC;
lid INT;
BEGIN
- SELECT * INTO la FROM acc_trans gl
+ SELECT INTO la FROM acc_trans gl
WHERE gl.source = in_scn
and gl.account = in_account
and gl.amount = in_amount;
@@ -268,7 +279,7 @@ create or replace function reconciliation_add_entry(in_report_id INT, in_scn INT
our_value := 0;
END IF;
- ELSif la.amount <> in_amount THEN
+ ELSE if la.amount <> in_amount THEN
errorcode := 1;
our_value := la.amount;
@@ -283,13 +294,13 @@ create or replace function reconciliation_add_entry(in_report_id INT, in_scn INT
END IF;
- INSERT INTO pending_reports (
+ INSERT INTO reports (
report_id,
scn,
their_balance,
our_balance,
error_code,
- entered_by,
+ user,
clear_time,
ledger_id
)
@@ -297,7 +308,7 @@ create or replace function reconciliation_add_entry(in_report_id INT, in_scn INT
in_report_id,
in_scn,
in_amount,
- gl.balance,
+ gl.amount,
errorcode,
in_user,
in_date,
@@ -312,26 +323,26 @@ create or replace function reconciliation_add_entry(in_report_id INT, in_scn INT
END;
$$ language 'plpgsql';
-create or replace function reconciliation_pending_transactions (in_report_id INT, in_month TIMESTAMP, in_user INT) RETURNS setof int as $$
+create or replace function reconciliation__pending_transactions (in_report_id INT, in_month TIMESTAMP, in_user INT) RETURNS setof int as $$
DECLARE
gl_row acc_trans;
BEGIN
FOR gl_row IN
- select gl.* from acc_trans gl, pending_reports pr
+ select gl.* from acc_trans gl, reports pr
where gl.cleared = 'f'
and date_trunc('month',gl.transdate) <= date_trunc('month', in_month)
and gl.entry_id <> pr.lid
LOOP
- INSERT INTO pending_reports (
+ INSERT INTO reports (
report_id,
scn,
their_balance,
our_balance,
error_code,
- entered_by,
+ user,
clear_time,
ledger_id
)
@@ -351,12 +362,12 @@ create or replace function reconciliation_pending_transactions (in_report_id INT
$$ language plpgsql;
-CREATE OR REPLACE FUNCTION reconciliation_report (in_report_id INT) RETURNS setof pending_reports as $$
+CREATE OR REPLACE FUNCTION reconciliation__report (in_report_id INT) RETURNS setof reports as $$
DECLARE
- row pending_reports;
+ row reports;
BEGIN
- FOR row IN select * from pending_reports where report_id = in_report_id LOOP
+ FOR row IN select * from reports where report_id = in_report_id LOOP
RETURN NEXT row;
@@ -365,19 +376,19 @@ CREATE OR REPLACE FUNCTION reconciliation_report (in_report_id INT) RETURNS seto
$$ language 'plpgsql';
-CREATE OR REPLACE FUNCTION reconciliation_get_total (in_report_id INT) returns pending_reports AS $$
+CREATE OR REPLACE FUNCTION reconciliation__get_total (in_report_id INT) returns setof reports AS $$
DECLARE
- row pending_reports;
+ row reports;
BEGIN
- SELECT * INTO row FROM pending_reports
+ SELECT INTO row FROM reports
WHERE ledger_id IS NULL
and report_id = in_report_id
AND scn = -1;
IF NOT FOUND THEN -- I think this is a fairly major error condition
- RAISE EXCEPTION 'No Bank Total found.';
+ RAISE EXCEPTION "No Bank Total found.";
ELSE
return row;
END IF;
@@ -385,15 +396,15 @@ CREATE OR REPLACE FUNCTION reconciliation_get_total (in_report_id INT) returns p
$$ language 'plpgsql';
-CREATE OR REPLACE FUNCTION reconciliation_corrections (in_report_id INT, in_id INT) returns setof report_corrections AS $$
+CREATE OR REPLACE FUNCTION reconciliation__corrections (in_report_id INT, in_id INT) returns setof report_corrections AS $$
DECLARE
corr report_corrections;
BEGIN
- SELECT * INTO corr FROM report_corrections WHERE report_id = in_report_id AND id = in_id LIMIT 1;
+ SELECT INTO corr FROM report_corrections WHERE report_id = in_report_id AND id = in_id LIMIT 1;
IF NOT FOUND THEN
- RAISE EXCEPTION 'No corrections for selected entry.';
+ RAISE EXCEPTION "No corrections for selected entry.";
ELSE
FOR corr IN select * from report_corrections WHERE report_id = in_report_id AND id = in_id LOOP
RETURN NEXT corr;
@@ -401,25 +412,78 @@ CREATE OR REPLACE FUNCTION reconciliation_corrections (in_report_id INT, in_id I
END IF;
END;
-$$ language 'plpgsql';
+$$ language 'plplsql';
+
+CREATE OR REPLACE FUNCTION reconciliation__single_entry (in_report_id INT, in_id INT) returns setof reports AS $$
-CREATE OR REPLACE FUNCTION reconciliation_single_entry
-(in_report_id INT, in_id INT)
-returns pending_reports AS
-$$
DECLARE
- row pending_reports;
+ row reports;
BEGIN
- SELECT * INTO row FROM pending_reports WHERE report_id = in_report_id and id = in_id LIMIT 1;
+ SELECT INTO row FROM reports WHERE report_id = in_report_id and id = in_id LIMIT 1;
-- if there's more than one, that's a Bad Thing
IF NOT FOUND THEN
- RAISE EXCEPTION 'Could not find selected report entry';
+ RAISE EXCEPTION "Could not find selected report entry";
ELSE
RETURN row;
END IF;
END;
$$ language 'plpgsql';
-COMMIT;
+
+CREATE OR REPLACE FUNCTION reconciliation__search (
+ in_date_begin DATE,
+ in_date_end DATE,
+ in_account TEXT,
+ in_status BOOLEAN
+) RETURNS setof reports AS $$
+
+ DECLARE
+ row reports;
+ statement text;
+ where_stmt text;
+ BEGIN
+ IF in_date_begin IS NOT NULL
+ or in_date_end IS NOT NULL
+ or in_account IS NOT NULL
+ or in_status IS NOT NULL
+ THEN
+ statement = "select pr.* from reports pr ";
+ statement = statement + "join acc_trans at on pr.ledger_id = at.entry_id ";
+
+ IF in_account IS NOT NULL THEN
+
+ statement = statement + "join chart c on at.chart_id = c.id ";
+ where_stmt = "c.accno =~ " + quote_literal(in_account) + " AND ";
+ END IF;
+
+ IF in_date_begin IS NOT NULL THEN
+ where_stmt = where_stmt + "insert_time >= " + quote_literal(in_date_begin) + " AND ";
+ END IF;
+
+ IF in_date_end IS NOT NULL THEN
+ where_stmt = where_stmt + "insert_time <= " + quote_literal(in_date_end) + " AND ";
+ END IF;
+
+ IF in_status IS NOT NULL THEN
+
+ if in_status == 't'::bool THEN
+ where_stmt = where_stmt + " approved = 't'::bool AND ";
+ ELSIF in_status == 'f'::bool THEN
+ where_stmt = where_stmt + " approved = 'f'::bool AND ";
+ END IF;
+
+ END IF;
+
+ FOR row in EXECUTE statement LOOP
+ RETURN NEXT row;
+ END LOOP;
+ ELSE
+
+ FOR row IN SELECT * FROM reports LOOP
+ RETURN NEXT row;
+ END LOOP;
+
+ END IF;
+ END; \ No newline at end of file