Files
CollectFlow/docs/database-schema.sql
T

138 lines
5.1 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- ================================================================
-- TABLE : ventes_produits
-- Import Excel Ventes Fournisseurs
-- Structure : 1 ligne = 1 produit × 1 magasin × 1 période
--
-- Stratégie : UPSERT sur (codein, magasin, periode)
-- → Chaque import met à jour les données existantes
-- → L'historique des anciens mois est conservé automatiquement
-- → On peut ré-importer le même fichier plusieurs fois sans doublons
-- ================================================================
DROP TABLE IF EXISTS ventes_produits;
CREATE TABLE ventes_produits (
id SERIAL PRIMARY KEY,
-- Identification produit
codein VARCHAR(20) NOT NULL, -- Code interne produit
code_fournisseur VARCHAR(20), -- Code fournisseur (ex: G009)
nom_fournisseur VARCHAR(255), -- Nom fournisseur (ex: GLAMA INTERNATIONAL)
libelle1 VARCHAR(500), -- Libellé produit
gtin VARCHAR(30), -- Code-barres GTIN/EAN
reference VARCHAR(100), -- Référence fournisseur
colisage NUMERIC(10,5), -- Colisage
-- Gamme & Nomenclature
code_gamme VARCHAR(20), -- CODE : gamme (A, Z, Aucune)
code3 VARCHAR(20), -- Code nomenclature (ex: 320211)
libelle3 VARCHAR(500), -- Libellé nomenclature
-- Dimension magasin & période
magasin VARCHAR(20) NOT NULL, -- HOUDEMONT, NANCY, TOTAL
code_magasin VARCHAR(10), -- 579, 292, ALL
annee SMALLINT, -- 2025, 2026
mois SMALLINT, -- 1..12
periode VARCHAR(10) NOT NULL, -- 202508, 202509, ... ou TOTAL
-- Métriques (valeurs négatives = ventes clients, sens comptable)
quantite NUMERIC(12,2),
montant_mvt NUMERIC(14,4),
marge_mvt NUMERIC(14,4),
-- Métadonnées d'import
imported_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-- Contrainte UNIQUE pour l'UPSERT
CONSTRAINT uq_ventes_produit_magasin_periode
UNIQUE (codein, magasin, periode)
);
-- ================================================================
-- INDEX pour les performances Metabase
-- ================================================================
CREATE INDEX idx_ventes_codein ON ventes_produits(codein);
CREATE INDEX idx_ventes_fournisseur ON ventes_produits(code_fournisseur);
CREATE INDEX idx_ventes_gamme ON ventes_produits(code_gamme);
CREATE INDEX idx_ventes_code3 ON ventes_produits(code3);
CREATE INDEX idx_ventes_magasin ON ventes_produits(magasin);
CREATE INDEX idx_ventes_periode ON ventes_produits(periode);
CREATE INDEX idx_ventes_annee_mois ON ventes_produits(annee, mois);
CREATE INDEX idx_ventes_codein_magasin ON ventes_produits(codein, magasin, periode);
CREATE INDEX idx_ventes_updated_at ON ventes_produits(updated_at);
-- Trigger pour mettre à jour updated_at automatiquement à chaque UPSERT
CREATE OR REPLACE FUNCTION fn_update_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trg_ventes_updated_at
BEFORE UPDATE ON ventes_produits
FOR EACH ROW
EXECUTE FUNCTION fn_update_updated_at();
-- ================================================================
-- VUES utiles pour Metabase
-- ================================================================
-- Vue synthèse par fournisseur & magasin
CREATE OR REPLACE VIEW v_ca_fournisseur AS
SELECT
code_fournisseur,
nom_fournisseur,
magasin,
annee,
mois,
periode,
SUM(ABS(quantite)) AS quantite_totale,
SUM(ABS(montant_mvt)) AS ca_total,
SUM(ABS(marge_mvt)) AS marge_totale,
CASE WHEN SUM(ABS(montant_mvt)) > 0
THEN ROUND(SUM(ABS(marge_mvt)) / SUM(ABS(montant_mvt)) * 100, 2)
ELSE 0 END AS taux_marge
FROM ventes_produits
WHERE magasin != 'TOTAL'
AND periode != 'TOTAL'
GROUP BY code_fournisseur, nom_fournisseur, magasin, annee, mois, periode;
-- Vue synthèse par nomenclature & magasin
CREATE OR REPLACE VIEW v_ca_nomenclature AS
SELECT
code3,
libelle3,
magasin,
annee,
mois,
periode,
SUM(ABS(quantite)) AS quantite_totale,
SUM(ABS(montant_mvt)) AS ca_total,
SUM(ABS(marge_mvt)) AS marge_totale,
CASE WHEN SUM(ABS(montant_mvt)) > 0
THEN ROUND(SUM(ABS(marge_mvt)) / SUM(ABS(montant_mvt)) * 100, 2)
ELSE 0 END AS taux_marge
FROM ventes_produits
WHERE magasin != 'TOTAL'
AND periode != 'TOTAL'
GROUP BY code3, libelle3, magasin, annee, mois, periode;
-- Vue synthèse par gamme & magasin
CREATE OR REPLACE VIEW v_ca_gamme AS
SELECT
code_gamme,
magasin,
annee,
mois,
periode,
SUM(ABS(quantite)) AS quantite_totale,
SUM(ABS(montant_mvt)) AS ca_total,
SUM(ABS(marge_mvt)) AS marge_totale
FROM ventes_produits
WHERE magasin != 'TOTAL'
AND periode != 'TOTAL'
GROUP BY code_gamme, magasin, annee, mois, periode;