La comptabilité à double entrée est
un ensemble de règles d'enregistrement des informations financières dans un système de comptabilité financière dans lequel chaque transaction ou événement modifie au moins deux comptes différents du grand livre nominal.
Un compte peut être "débité" ou "crédité", et la somme de tous les crédits doit être égale à la somme de tous les débits.
Comment implémenteriez-vous cela dans une base de données Postgres? Spécification de la DDL suivante:
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'))
);
Remarque: la table transaction_details ne spécifie pas de compte de débit / crédit explicite, car le système doit pouvoir débiter / créditer plusieurs comptes en une seule transaction.
Cette DDL crée l'exigence suivante: Une fois qu'une transaction de base de données est validée sur la table transactions_details, elle doit débiter et créditer le même montant pour chacune transaction_id
, par exemple :
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;
Est-il possible de l'implémenter dans une base de données PostgreSQL? Sans spécifier de tables supplémentaires pour stocker les états de déclenchement.