\. --TRUNCATE TABLE "Vente"; --TRUNCATE TABLE "Panier"; DROP PROCEDURE insertVente IF EXISTS CASCADE; CREATE PROCEDURE insertVente ( IN venteDate DATE , IN venteClient INTEGER , IN venteProduit INTEGER , IN venteQuantité DECIMAL ) MODIFIES SQL DATA BEGIN ATOMIC DECLARE panierID INTEGER DEFAULT NULL; DECLARE venteFacturable BOOLEAN DEFAULT FALSE; DECLARE venteID INTEGER DEFAULT NULL; -- CorrectnessNote: seule la date et le client -- font partie des critères pour décider -- si le panier existe déjà où non. SET panierID = SELECT ID FROM "Panier" WHERE "Panier".date = venteDate AND "Panier".client = venteClient; IF panierID IS NULL THEN SET venteFacturable = SELECT facturable FROM "Client" WHERE "Client".ID = venteClient; INSERT INTO "Panier"(date, client, facturable) VALUES (venteDate, venteClient, venteFacturable); SET panierID = IDENTITY(); END IF; -- CorrectnessNote: la quantité ne fait pas partie des critères -- pour décider si la vente existe déjà ou non. SET venteID = SELECT ID FROM "Vente" WHERE "Vente".panier = panierID AND "Vente".produit = venteProduit; IF venteID IS NULL THEN INSERT INTO "Vente"(panier, produit, quantité) VALUES (panierID, venteProduit, venteQuantité); END IF; END .; DROP PROCEDURE insertVentesParAbonnement IF EXISTS; CREATE PROCEDURE insertVentesParAbonnement(IN finalDate DATE) MODIFIES SQL DATA BEGIN ATOMIC -- ExplanationNote: gère chaque jour l'un après l'autre. for_days: FOR SELECT day FROM UNNEST (SEQUENCE_ARRAY(DATE '2025-04-07', finalDate, 1 DAY)) WITH ORDINALITY as T(day, I) DO -- ExplanationNote: pour un jour donné, -- gère chaque abonnement l'un après l'autre. for_abos: FOR SELECT ID as aboID , client as aboClient , produit as aboProduit , quantité as aboQuantité , période as aboP FROM "Abonnement" JOIN "Période" ON "Période".ID = "Abonnement".période AND "Période".nom = DAYNAME(day) DO CALL insertVente(day, aboClient, aboProduit, aboQuantité); END FOR for_abos; END FOR for_days; END; .; CALL insertVentesParAbonnement(DATE '2025-04-07' + 7 DAY); -- `insertFactureClient(client)` -- crée une facture pour tous les paniers -- de `client`. DROP PROCEDURE insertFactureClient IF EXISTS; CREATE PROCEDURE insertFactureClient(IN selClient INTEGER) MODIFIES SQL DATA BEGIN ATOMIC DECLARE factureID INTEGER DEFAULT NULL; -- Si le client a des paniers `facturable`s sans `facture`. IF CARDINALITY(ARRAY (SELECT ID FROM "Panier" WHERE client = selClient AND facturable AND facture IS NULL )) > 0 THEN -- Crée une nouvelle facture -- et référence celle-ci dans tous les paniers -- non-facturés jusque là. INSERT INTO "Facture"(date) VALUES (CURRENT_DATE); SET factureID = IDENTITY(); UPDATE "Panier" SET facture = factureID WHERE facture IS NULL AND client = selClient ; END IF; END; .; \i sql/show.sql --call prix_à_date(CURRENT_DATE); SELECT "Prod".nom_complet, date, euros FROM TABLE (prix_à_date(CURRENT_DATE)) AS PD JOIN TABLE (choisirUnProduit()) AS "Prod" ON "Prod".ID = produit ; CALL insertFactureClient(0); CALL insertFactureClient(1); CALL insertFactureClient(2); SELECT * FROM "Panier" ; SELECT * FROM "Client" ; \p . \p Factures des clients DROP VIEW "Factures" IF EXISTS; CREATE VIEW "Factures" AS SELECT "Facture".ID, --ANY_VALUE ("Facture".date) as facture_date, --ANY_VALUE ("Client".ID) as client, --ANY_VALUE ("Panier".ID) as panier, --ANY_VALUE ("Panier".date) as panier_date, --ARRAY_AGG -- ("Vente".ID) as ventes, --ARRAY_AGG "Produit".ID as produit, "Vente".quantité as quantité, "PrixÁDate".euros as euros --GROUP_CONCAT --("PrixÁDate".euros * "Vente".quantité SEPARATOR ', ') as prix_quantifié FROM "Panier" JOIN "Facture" ON "Facture".ID = "Panier".facture JOIN "Client" ON "Client".ID = "Panier".client JOIN "Vente" ON "Vente".panier = "Panier".ID JOIN "Produit" ON "Produit".ID = "Vente".produit JOIN TABLE (prix_à_date("Panier".date)) AS "PrixÁDate" ON "PrixÁDate".produit = "Produit".ID ORDER BY "Facture".ID , "Facture".date , "Client".ID , "Panier".ID , "Panier".date , "Produit".ID ; SELECT * FROM "Factures"; \i modèles/Facture.Paniers.sql \i modèles/Facture.Totaux.sql