diff --git a/banque.md b/banque.md index d04a02d..ea610b1 100644 --- a/banque.md +++ b/banque.md @@ -64,7 +64,7 @@ La banque souhaite désormais que toute personne titulaire d’un compte ait au - Un compte bancaire doit pouvoir appartenir à un ou plusieurs titulaires (compte individuel / compte joint). - Chaque compte dispose d’un numéro de compte (_account number_) unique, d’un solde, d'une date d'ouverture et une date de clôture. - Le solde des comptes ne peuvent être négatifs. -- Dans le cas d'un compte joint, les parts de propriété d'un compte doivent pouvoir être précisées. +- Dans le cas d'un compte joint, les parts (_share_) de propriété d'un compte doivent pouvoir être précisées. ### 2.1 Exemple de données @@ -221,10 +221,6 @@ create table account_holder ( * la procédure doit lever une **erreur explicite** (`RAISE EXCEPTION`) ; * aucune insertion ne doit être faite (transaction annulée). ---- - -## 💡 Aide - * Les tableaux peuvent être parcourus avec une boucle : ```sql @@ -249,33 +245,30 @@ create table account_holder ( --- -## ✅ Exemple d’appel - -### Cas valide : +### Exemples d’appel ```sql call create_account( 'FR761234567890', 'Compte commun', - array[1, 2], + array[1, 5], array[0.5, 0.5] ); ``` -➡️ Crée un compte partagé 50/50 entre les titulaires 1 et 2. +Crée un compte partagé 50/50 entre les titulaires 1 et 2. -### Cas invalide : ```sql call create_account( 'FR009999999999', 'Compte déséquilibré', - array[1, 2], + array[1, 5], array[0.7, 0.4] ); ``` -❌ Doit refuser la création avec une erreur claire : +Doit refuser la création avec une erreur claire : ``` ERROR: La somme des parts (1.1000) doit être égale à 1.0000 diff --git a/banque.sql b/banque.sql index 9859ea5..4ca5145 100644 --- a/banque.sql +++ b/banque.sql @@ -234,6 +234,7 @@ begin end if; -- Calcul de la somme des parts + -- select sum(unnest(p_shares)) into v_sum; for i in 1..array_length(p_shares, 1) loop v_sum := v_sum + p_shares[i]; end loop; @@ -264,3 +265,109 @@ begin end; $$; + +create or replace procedure record_operation( + p_account_id int, + p_kind text, + p_amount numeric, + p_description text default null +) +language plpgsql +as $$ +declare + v_balance numeric(12,2); +begin + -- Vérification du type d’opération + if p_kind not in ('DEPOSIT', 'WITHDRAWAL') then + raise exception 'Type d’opération invalide : % (attendu: DEPOSIT ou WITHDRAWAL)', p_kind; + end if; + + -- Vérification que le compte existe + if not exists (select 1 from account where id = p_account_id) then + raise exception 'Le compte % n’existe pas.', p_account_id; + end if; + + -- Calcul du solde actuel + select coalesce(sum(case when kind = 'DEPOSIT' then amount else -amount end), 0) + into v_balance + from operation + where account_id = p_account_id; + + -- Vérification du solde si retrait + if p_kind = 'WITHDRAWAL' and v_balance < p_amount then + raise exception 'Fonds insuffisants : solde actuel %.2f, retrait demandé %.2f', + v_balance, p_amount; + end if; + + -- Insertion de l’opération + insert into operation(account_id, kind, amount, description) + values (p_account_id, p_kind, p_amount, p_description); + + raise notice 'Opération enregistrée : % de %.2f sur compte %', + p_kind, p_amount, p_account_id; +end; +$$; + +CREATE TABLE transaction ( + id SERIAL PRIMARY KEY, + account_id INT NOT NULL REFERENCES account(id), + amount NUMERIC(12, 2) NOT NULL CHECK (amount <> 0), + operation_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE OR REPLACE PROCEDURE deposit(p_account_id INT, p_amount NUMERIC) +LANGUAGE plpgsql +AS $$ +BEGIN + IF p_amount <= 0 THEN + RAISE EXCEPTION 'Deposit amount must be positive'; + END IF; + + UPDATE account + SET balance = balance + p_amount + WHERE id = p_account_id; + + IF NOT FOUND THEN + RAISE EXCEPTION 'Account % not found', p_account_id; + END IF; + + INSERT INTO transaction (account_id, amount) + VALUES (p_account_id, p_amount); +END; +$$; + +CREATE OR REPLACE PROCEDURE withdraw(p_account_id INT, p_amount NUMERIC) +LANGUAGE plpgsql +AS $$ +DECLARE + current_balance NUMERIC; +BEGIN + IF p_amount <= 0 THEN + RAISE EXCEPTION 'Withdraw amount must be positive'; + END IF; + + SELECT balance INTO current_balance + FROM account + WHERE id = p_account_id; + + IF NOT FOUND THEN + RAISE EXCEPTION 'Account % not found', p_account_id; + END IF; + + IF current_balance < p_amount THEN + RAISE EXCEPTION 'Insufficient funds: balance = %, attempted withdrawal = %', + current_balance, p_amount; + END IF; + + UPDATE account + SET balance = balance - p_amount + WHERE id = p_account_id; + + INSERT INTO transaction (account_id, amount) + VALUES (p_account_id, -p_amount); +END; +$$; + + + +