La contabilidad de doble entrada es
un conjunto de reglas para registrar información financiera en un sistema de contabilidad financiera en el que cada transacción o evento cambia al menos dos cuentas contables nominales diferentes.
Una cuenta puede ser "debitada" o "acreditada", y la suma de todos los créditos debe ser igual a la suma de todos los débitos.
¿Cómo implementaría esto en una base de datos Postgres? Especificando el siguiente DDL:
CREATE TABLE accounts(
account_id serial NOT NULL PRIMARY KEY,
account_name varchar(64) NOT NULL
);
CREATE TABLE transactions(
transaction_id serial NOT NULL PRIMARY KEY,
transaction_date date NOT NULL
);
CREATE TABLE transactions_details(
id serial8 NOT NULL PRIMARY KEY,
transaction_id integer NOT NULL
REFERENCES transactions (transaction_id)
ON UPDATE CASCADE
ON DELETE CASCADE
DEFERRABLE INITIALLY DEFERRED,
account_id integer NOT NULL
REFERENCES accounts (account_id)
ON UPDATE CASCADE
ON DELETE RESTRICT
NOT DEFERRABLE INITIALLY IMMEDIATE,
amount decimal(19,6) NOT NULL,
flag varchar(1) NOT NULL CHECK (flag IN ('C','D'))
);
Nota: la tabla transacción_detalles no especifica una cuenta explícita de débito / crédito, porque el sistema debería poder debitar / acreditar más de una cuenta en una sola transacción.
Este DDL crea el siguiente requisito: después de que una transacción de base de datos se confirma en la tabla transacciones_detalles, debe debitar y acreditar la misma cantidad para cada uno transaction_id
, por ejemplo :
INSERT INTO accounts VALUES (100, 'Accounts receivable');
INSERT INTO accounts VALUES (200, 'Revenue');
INSERT INTO transactions VALUES (1, CURRENT_DATE);
-- The following must succeed
BEGIN;
INSERT INTO transactions_details VALUES (DEFAULT, 1, 100, '1000'::decimal, 'D');
INSERT INTO transactions_details VALUES (DEFAULT, 1, 200, '1000'::decimal, 'C');
COMMIT;
-- But this must raise some error
BEGIN;
INSERT INTO transactions_details VALUES (DEFAULT, 1, 100, '1000'::decimal, 'D');
INSERT INTO transactions_details VALUES (DEFAULT, 1, 200, '500'::decimal, 'C');
COMMIT;
¿Es posible implementar esto en una base de datos PostgreSQL? Sin especificar tablas adicionales para almacenar estados de activación.