/** * CollectFlow - Core Grid Types */ /** One row in the data grid, representing a product at a store for one period. */ export interface VenteProduit { id: number; codein: string; codeFournisseur: string | null; nomFournisseur: string | null; libelle1: string | null; gtin: string | null; reference: string | null; codeGamme: GammeCode | null; codeGammeInit: GammeCode | null; code3: string | null; libelle3: string | null; magasin: string; codeMagasin: string | null; annee: number | null; mois: number | null; periode: string; quantite: number | null; montantMvt: number | null; margeMvt: number | null; } /** A/B/C/Z status codes for product categories, but can be any string from DB (like 'Aucune') */ export type GammeCode = string; /** A product row with its 12-month sales history and computed KPIs */ export interface ProductRow { codein: string; codeFournisseur: string; nomFournisseur: string; /** Dernier fournisseur enregistré pour cet article (artfou1.no_id DESC). Peut différer du fournisseur consulté. */ fournisseurPrincipalCode?: string; fournisseurPrincipalNom?: string; libelle1: string; gtin: string; reference: string; code1: string; libelleNiveau1: string; code2: string; libelleNiveau2: string; code3: string; libelle3: string; codeGamme: GammeCode | null; codeGammeInit: GammeCode | null; /** Draft gamme value before saving */ codeGammeDraft: GammeCode | null; /** 12-month sales quantities, indexed by YYYYMM key */ sales12m: Record; /** End-of-month stock levels, indexed by YYYYMM key */ stock12m: Record; /** Monthly reception quantities, indexed by YYYYMM key */ receptions12m: Record; /** Per-store breakdown (site → YYYYMM → qty) — always present even in TOTAL mode */ sales12mByStore?: Record>; /** Per-store stock breakdown (site → YYYYMM → stock fin de mois) */ stock12mByStore?: Record>; /** Per-store reception breakdown (site → YYYYMM → qté reçue) */ receptions12mByStore?: Record>; /** Per-store last delivery/reception date (site → ISO date string) */ derniereLivraisonByStore?: Record; /** Per-store CA totals */ caByStore?: Record; /** Per-store quantity totals */ quantiteByStore?: Record; /** Per-store margin totals */ margeByStore?: Record; totalQuantite: number; totalCa: number; totalMarge: number; tauxMarge: number; workingStores: string[]; /** Rotation normalisée : unités vendues / magasin / mois */ unitsPerStorePerMonth?: number; /** CA normalisé : € / magasin / an */ caPerStorePerYear?: number; /** Produit récent (≤ 3 mois de données) */ isRecent?: boolean; /** Seul produit du fournisseur dans le lot */ isLastProduct?: boolean; /** Top 30% CA du lot fournisseur */ isTop30Supplier?: boolean; /** SQL Server internal ID — nécessaire pour /api/articles/:noid/mensuel */ noid?: number; /** Données stock & approvisionnement (API FF Nancy) */ pcb?: number; // Conditionnement (pack size) prixAchat?: number; // PA / PRMP prixVente?: number; // PV central stockActuel?: number; // Stock dispo agrégé tous sites stockTotal?: number; // Qte en stock agrégé stockValeur?: number; // Valeur stock agrégée pa?: number; // PRMP (alias prixAchat) derniereVente?: string; // ISO date de dernière vente derniereLivraison?: string; // ISO date de dernière réception nbJoursDerniereVente?: number; // Nb jours sans vente commandesEnCours?: number; // Qté en commande fournisseur /** Moyennes de comparaison pour l'IA */ avgQtyFournisseur?: number; avgQtyRayon?: number; /** Poids relatifs (%) du produit chez le fournisseur */ shareCa?: number; shareMarge?: number; shareQty?: number; /** Référentiels globaux */ totalFournisseurCa?: number; /** Code centrale (clé jointure Qlik, format 10000XXXXXX) */ codeCentrale?: string; /** Données réseau Qlik (~270 magasins) */ caReseau?: number; qteReseau?: number; nbMagasinsReseau?: number; /** CA moyen par magasin réseau (productivité normalisée présence) */ caParMagasinReseau?: number; /** Taux de marge réseau (ratio brut Qlik, ex 0.32 = 32%) */ margePctReseau?: number; /** Taux de présence réseau = nbMagasinsReseau / 270 */ tauxPresenceReseau?: number; /** Quantité vendue réseau par mois : { "YYYY-MM": qté } (tendance / modal). */ qteReseauByMonth?: Record | null; /** Fraîcheur des données réseau (ISO) */ networkFetchedAt?: string; } /** Summary bar totals for the currently visible/filtered rows */ export interface GridSummary { totalProducts: number; totalRows: number; totalQuantite: number; totalCa: number; totalMarge: number; tauxMargeGlobal: number; } /** Filters applied to the grid */ export interface GridFilters { magasin: string | null; codeFournisseur: string | null; code1: string | null; code2: string | null; code3: string | null; codeGamme: GammeCode | null; search: string; }