\.
--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
