feat(grid): ajout algorithme score produit avec parametrage dynamique et page d'aide

This commit is contained in:
Michael committed 2026-02-21 04:00:51 +01:00
1 parent f540e4f2b3
commit 3544c0c898
67 files changed
+19476 -15

No files matched your search

+137
View File
@@ -0,0 +1,137 @@
-- ================================================================
-- 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;