📱

Écran Trop Petit

Cette documentation technique nécessite un écran plus large pour une consultation optimale.

Veuillez utiliser une tablette (iPad, etc.) ou un ordinateur pour accéder au contenu.

📱 💻 🖥️

🎯 Objectif du Guide

Ce guide fournit toutes les spécifications techniques nécessaires pour développer l'application complète, indépendamment de la technologie choisie.

⚠️ Important : Les exemples de code et structures de données sont fournis à titre indicatif. Vous êtes libre d'adapter selon votre stack technologique.

📊 Modèle de Données

Entité : Restaurant

{
  id: string (unique),
  nom: string,
  type: "stock-principal" | "cuisine-centrale" | "restaurant",
  adresse: string (optionnel),
  telephone: string (optionnel),
  email: string (optionnel),
  actif: boolean,
  dateCreation: date,
  dateModification: date
}

Exemples :
{
  id: "R001",
  nom: "Stock Principal",
  type: "stock-principal"
}

{
  id: "R002",
  nom: "Cuisine Centrale",
  type: "cuisine-centrale"
}

{
  id: "R003",
  nom: "FF Paul Langevin",
  type: "restaurant",
  adresse: "Bd Paul Langevin, Abidjan"
}

Entité : Article

{
  code: string (unique, clé primaire),
  designation: string,
  categorie: string,
  unite: string,
  typeArticle: "matiere-brute" | "produit-semi-fini",
  format: string (optionnel - pour FF Koumassi),
  prixUnitaireMoyen: number (optionnel),
  actif: boolean,
  dateCreation: date,
  dateModification: date
}

Exemples :
// Matière brute
{
  code: "LLC-MB-BOEUF-HACHE",
  designation: "Bœuf haché frais",
  categorie: "Viandes",
  unite: "kg",
  typeArticle: "matiere-brute",
  actif: true
}

// Produit semi-fini
{
  code: "LLC-SF-BOUL-BOEUF",
  designation: "Boulettes de bœuf",
  categorie: "Produits transformés",
  unite: "pièce",
  typeArticle: "produit-semi-fini",
  actif: true
}

Entité : Nomenclature (Recette de Fabrication)

{
  id: string (unique),
  produitCode: string (référence Article),
  produitDesignation: string,
  quantiteBase: number,
  uniteBase: string,
  
  ingredients: [
    {
      articleCode: string (référence Article),
      designation: string,
      quantiteRequise: number,
      unite: string
    }
  ],
  
  rendementAttendu: number (en %),
  tempsFabrication: number (en minutes),
  instructions: string (texte libre),
  
  actif: boolean,
  dateCreation: date,
  dateModification: date
}

Exemple :
{
  id: "NOM001",
  produitCode: "LLC-SF-BOUL-BOEUF",
  produitDesignation: "Boulettes de bœuf",
  quantiteBase: 100,
  uniteBase: "pièces de 110g",
  
  ingredients: [
    {
      articleCode: "LLC-MB-BOEUF-HACHE",
      designation: "Bœuf haché",
      quantiteRequise: 12,
      unite: "kg"
    },
    {
      articleCode: "LLC-MB-EPICES",
      designation: "Épices mélange",
      quantiteRequise: 0.4,
      unite: "kg"
    },
    {
      articleCode: "LLC-MB-CHAPELURE",
      designation: "Chapelure",
      quantiteRequise: 1,
      unite: "kg"
    },
    {
      articleCode: "LLC-MB-OEUFS",
      designation: "Œufs",
      quantiteRequise: 10,
      unite: "pièce"
    }
  ],
  
  rendementAttendu: 90,
  tempsFabrication: 240,
  instructions: "1. Mélanger tous les ingrédients\n2. Former les boulettes\n3. Cuire...",
  actif: true
}

Entité : Lot

{
  numeroLot: string (unique, format: LOT-YYYYMMDD-NNN),
  articleCode: string (référence Article),
  typeLot: "fournisseur" | "production",
  
  // Si lot fournisseur
  fournisseur: string (optionnel),
  numeroLotFournisseur: string (optionnel),
  
  // Si lot production
  bonFabricationRef: string (optionnel),
  
  quantiteInitiale: number,
  quantiteRestante: number,
  unite: string,
  
  dateFabrication: date (ou date réception si fournisseur),
  dateLimiteUtilisation: date (DLU),
  
  statut: "disponible" | "partiellement-utilise" | "epuise" | "perime",
  
  dateCreation: date,
  dateModification: date
}

Exemples :
// Lot fournisseur
{
  numeroLot: "LOT-FOUR-20250116-001",
  articleCode: "LLC-MB-BOEUF-HACHE",
  typeLot: "fournisseur",
  fournisseur: "SOPAL",
  numeroLotFournisseur: "SOL-20250116-BH",
  quantiteInitiale: 100,
  quantiteRestante: 64,
  unite: "kg",
  dateFabrication: "2025-01-16",
  dateLimiteUtilisation: "2025-01-18",
  statut: "partiellement-utilise"
}

// Lot production
{
  numeroLot: "LOT-20250118-001",
  articleCode: "LLC-SF-BOUL-BOEUF",
  typeLot: "production",
  bonFabricationRef: "BF-2025-001",
  quantiteInitiale: 285,
  quantiteRestante: 135,
  unite: "pièce",
  dateFabrication: "2025-01-18",
  dateLimiteUtilisation: "2025-01-23",
  statut: "partiellement-utilise"
}

Entité : Document

{
  id: string (unique),
  numero: string (format: TYPE-YYYY-NNN, ex: BC-2025-001),
  type: "BRF" | "BRP" | "BSP" | "BF" | "BRETP" | "BC" | "BS" | "BL" | "BR",
  
  restaurantId: string (référence Restaurant),
  restaurantOrigine: string (optionnel, pour transferts),
  restaurantDestination: string (optionnel, pour transferts),
  
  date: date,
  dateCreation: date,
  
  statut: "brouillon" | "valide" | "en-transit" | "livre" | "recu" | "annule",
  
  lignes: [
    {
      articleCode: string,
      designation: string,
      unite: string,
      quantiteCommandee: number (optionnel),
      quantiteLivree: number (optionnel),
      quantiteRecue: number (optionnel),
      quantiteAcceptee: number (optionnel),
      quantiteRefusee: number (optionnel),
      motifRefus: string (optionnel),
      lotNumero: string (optionnel),
      dlu: date (optionnel),
      prixUnitaire: number (optionnel),
      montant: number (optionnel),
      format: string (optionnel),
      poidsTotal: number (optionnel),
      observations: string (optionnel)
    }
  ],
  
  // Champs spécifiques selon type
  fournisseur: string (optionnel, pour BRF),
  numeroDocumentFournisseur: string (optionnel),
  
  produitFabrique: string (optionnel, pour BF),
  rendement: number (optionnel, pour BF),
  
  livreur: string (optionnel, pour BL),
  vehicule: string (optionnel, pour BL),
  heureDepart: datetime (optionnel),
  heureArrivee: datetime (optionnel),
  
  expediteur: string,
  recepteur: string,
  
  observations: string,
  
  dateModification: date
}

Entité : Mouvement de Stock

{
  id: string (unique),
  articleCode: string (référence Article),
  restaurantId: string (référence Restaurant),
  
  type: "entree" | "sortie",
  quantite: number,
  unite: string,
  
  lotNumero: string (optionnel),
  
  prixUnitaire: number (optionnel),
  montant: number (optionnel),
  
  date: datetime,
  
  documentId: string (référence Document),
  documentNumero: string,
  documentType: string,
  
  motif: string (optionnel),
  
  stockAvant: number,
  stockApres: number,
  
  utilisateurId: string,
  dateCreation: date
}

Exemple :
{
  id: "MVT001",
  articleCode: "LLC-SF-BOUL-BOEUF",
  restaurantId: "R001", // Stock Principal
  type: "sortie",
  quantite: 150,
  unite: "pièce",
  lotNumero: "LOT-20250118-001",
  date: "2025-01-19T09:30:00",
  documentId: "DOC123",
  documentNumero: "BS-2025-001",
  documentType: "BS",
  stockAvant: 285,
  stockApres: 135,
  utilisateurId: "USER01"
}

Entité : Stock

{
  id: string (unique),
  articleCode: string (référence Article),
  restaurantId: string (référence Restaurant),
  
  quantiteDisponible: number,
  unite: string,
  
  valeurTotale: number,
  prixUnitaireMoyen: number,
  
  dateMAJ: datetime,
  
  // Pour les produits semi-finis - détail par lot
  lots: [
    {
      numeroLot: string,
      quantite: number,
      dlu: date
    }
  ]
}

Exemple :
{
  id: "STK001",
  articleCode: "LLC-SF-BOUL-BOEUF",
  restaurantId: "R001",
  quantiteDisponible: 135,
  unite: "pièce",
  valeurTotale: 67500, // Si prix 500 FCFA/pièce
  prixUnitaireMoyen: 500,
  dateMAJ: "2025-01-19T09:30:00",
  lots: [
    {
      numeroLot: "LOT-20250118-001",
      quantite: 135,
      dlu: "2025-01-23"
    }
  ]
}

🔢 Règles de Numérotation

Document Format Exemples
Bon Réception Fournisseur BRF-YYYY-NNN BRF-2025-001, BRF-2025-002...
Bon Réquisition Production BRP-YYYY-NNN BRP-2025-001, BRP-2025-002...
Bon Sortie Production BSP-YYYY-NNN BSP-2025-001, BSP-2025-002...
Bon Fabrication BF-YYYY-NNN BF-2025-001, BF-2025-002...
Bon Retour Production BRETP-YYYY-NNN BRETP-2025-001, BRETP-2025-002...
Bon Commande BC-YYYY-NNN BC-2025-001, BC-2025-002...
Bon Sortie BS-YYYY-NNN BS-2025-001, BS-2025-002...
Bon Livraison BL-YYYY-NNN BL-2025-001, BL-2025-002...
Bon Réception BR-YYYY-NNN BR-2025-001, BR-2025-002...
Lot Production LOT-YYYYMMDD-NNN LOT-20250118-001, LOT-20250118-002...

Algorithme de Génération

function genererNumeroDocument(typeDocument) {
  // 1. Récupérer l'année en cours
  annee = getCurrentYear()
  
  // 2. Trouver le dernier numéro pour ce type + année
  dernierNumero = database.query(
    "SELECT MAX(numero) FROM documents 
     WHERE type = ? AND YEAR(date) = ?",
    [typeDocument, annee]
  )
  
  // 3. Incrémenter
  if (dernierNumero exists) {
    nouveauNumero = dernierNumero + 1
  } else {
    nouveauNumero = 1
  }
  
  // 4. Formater avec padding (001, 002, etc.)
  numeroFormate = pad(nouveauNumero, 3) // "001"
  
  // 5. Construire le numéro complet
  return typeDocument + "-" + annee + "-" + numeroFormate
  
  // Exemples de résultats:
  // "BC-2025-001"
  // "BS-2025-045"
  // "BF-2025-012"
}

function genererNumeroLot(date) {
  dateStr = formatDate(date, "YYYYMMDD") // "20250118"
  
  dernierNumero = database.query(
    "SELECT MAX(numeroLot) FROM lots 
     WHERE numeroLot LIKE 'LOT-" + dateStr + "-%'"
  )
  
  if (dernierNumero exists) {
    nouveauNumero = extraireNumero(dernierNumero) + 1
  } else {
    nouveauNumero = 1
  }
  
  numeroFormate = pad(nouveauNumero, 3)
  
  return "LOT-" + dateStr + "-" + numeroFormate
  // Exemple: "LOT-20250118-001"
}
⚠️ CRITIQUE : La génération de numéros doit être "thread-safe" et "transactionnelle" pour éviter les doublons en cas d'accès concurrent.

⚙️ Règles de Gestion Critiques

RG-001 : Stock Jamais Négatif

function validerSortieStock(articleCode, restaurantId, quantite) {
  stockActuel = getStock(articleCode, restaurantId)
  
  if (stockActuel.quantiteDisponible < quantite) {
    throw new Error(
      "Stock insuffisant. Disponible: " + stockActuel.quantiteDisponible + 
      ", Demandé: " + quantite
    )
  }
  
  // OK, peut continuer
}

RG-002 : Validation Irréversible

function validerDocument(documentId) {
  document = getDocument(documentId)
  
  // Vérifier statut
  if (document.statut != "brouillon") {
    throw new Error("Seuls les documents en brouillon peuvent être validés")
  }
  
  // Vérifier cohérence
  validerCoherence(document)
  
  // Transaction atomique
  database.beginTransaction()
  
  try {
    // 1. Mettre à jour le document
    document.statut = "valide"
    document.dateValidation = now()
    saveDocument(document)
    
    // 2. Créer les mouvements de stock SI APPLICABLE
    if (documentImpacteStock(document.type)) {
      creerMouvementsStock(document)
    }
    
    // 3. Mettre à jour les stocks
    if (documentImpacteStock(document.type)) {
      mettreAJourStocks(document)
    }
    
    // 4. Commit
    database.commit()
    
    // ⚠️ APRÈS VALIDATION: IMPOSSIBLE D'ANNULER
    // Seule option: créer un document correctif
    
  } catch (error) {
    database.rollback()
    throw error
  }
}

RG-003 : Calcul Automatique Nomenclature

function calculerBesoinsProduction(produitCode, quantiteSouhaitee) {
  // 1. Récupérer la nomenclature
  nomenclature = getNomenclature(produitCode)
  
  if (!nomenclature || !nomenclature.actif) {
    throw new Error("Aucune nomenclature active pour ce produit")
  }
  
  // 2. Calculer le ratio
  ratio = quantiteSouhaitee / nomenclature.quantiteBase
  
  // 3. Calculer besoins pour chaque ingrédient
  besoins = []
  
  for (ingredient in nomenclature.ingredients) {
    quantiteRequise = ingredient.quantiteRequise * ratio
    stockDispo = getStock(ingredient.articleCode, "STOCK_PRINCIPAL")
    
    besoins.push({
      articleCode: ingredient.articleCode,
      designation: ingredient.designation,
      quantiteRequise: quantiteRequise,
      unite: ingredient.unite,
      stockDisponible: stockDispo.quantiteDisponible,
      suffisant: stockDispo.quantiteDisponible >= quantiteRequise
    })
  }
  
  return {
    produit: produitCode,
    quantiteSouhaitee: quantiteSouhaitee,
    besoins: besoins,
    tousDisponibles: besoins.every(b => b.suffisant)
  }
}

Exemple d'utilisation :
resultat = calculerBesoinsProduction("LLC-SF-BOUL-BOEUF", 300)

// Résultat:
{
  produit: "LLC-SF-BOUL-BOEUF",
  quantiteSouhaitee: 300,
  besoins: [
    {
      articleCode: "LLC-MB-BOEUF-HACHE",
      designation: "Bœuf haché",
      quantiteRequise: 36,
      unite: "kg",
      stockDisponible: 100,
      suffisant: true
    },
    {
      articleCode: "LLC-MB-CHAPELURE",
      designation: "Chapelure",
      quantiteRequise: 3,
      unite: "kg",
      stockDisponible: 2,
      suffisant: false ❌
    }
  ],
  tousDisponibles: false
}

RG-004 : Validation Rendement

function validerBonFabrication(bonFabrication) {
  // Calculer rendement
  totalMatieresConsommees = sum(bonFabrication.matieres.map(m => m.quantite))
  quantiteObtenue = bonFabrication.quantiteObtenue
  
  rendement = (quantiteObtenue / totalMatieresConsommees) * 100
  bonFabrication.rendement = rendement
  
  // Validation selon seuils
  if (rendement > 100) {
    throw new Error(
      "Rendement impossible > 100%. Vérifier les quantités saisies."
    )
  }
  
  if (rendement < 70) {
    return {
      valide: false,
      alerte: "BLOCAGE",
      message: "Rendement anormalement bas (" + rendement + "%). " +
               "Justification obligatoire.",
      requiertJustification: true
    }
  }
  
  if (rendement >= 70 && rendement < 85) {
    return {
      valide: true,
      alerte: "WARNING",
      message: "Rendement faible (" + rendement + "%). Vérifier la production.",
      requiertConfirmation: true
    }
  }
  
  // Rendement 85-100%
  return {
    valide: true,
    alerte: "OK",
    message: "Rendement acceptable (" + rendement + "%)"
  }
}

RG-005 : Gestion DLU et FIFO

function selectionnerLotsPourSortie(articleCode, quantiteDemandee, dateLivraison) {
  // 1. Récupérer tous les lots disponibles de cet article
  lots = database.query(
    "SELECT * FROM lots 
     WHERE articleCode = ? 
     AND statut IN ('disponible', 'partiellement-utilise')
     AND quantiteRestante > 0
     ORDER BY dateLimiteUtilisation ASC", // FIFO: Plus anciens d'abord
    [articleCode]
  )
  
  lotsSelectionnes = []
  quantiteRestante = quantiteDemandee
  alertes = []
  
  for (lot in lots) {
    // Vérifier DLU
    joursRestants = daysBetween(now(), lot.dateLimiteUtilisation)
    joursApresLivraison = daysBetween(dateLivraison, lot.dateLimiteUtilisation)
    
    // Bloquer si DLU dépassée
    if (lot.dateLimiteUtilisation < now()) {
      continue // Lot périmé, ignorer
    }
    
    // Alerter si DLU proche après livraison
    if (joursApresLivraison < 2) {
      alertes.push({
        type: "WARNING",
        lot: lot.numeroLot,
        message: "DLU proche: " + lot.dateLimiteUtilisation + 
                 ". À consommer rapidement par le restaurant."
      })
    }
    
    // Sélectionner le lot
    quantiteAPrendre = Math.min(lot.quantiteRestante, quantiteRestante)
    
    lotsSelectionnes.push({
      numeroLot: lot.numeroLot,
      quantite: quantiteAPrendre,
      dlu: lot.dateLimiteUtilisation
    })
    
    quantiteRestante -= quantiteAPrendre
    
    if (quantiteRestante <= 0) {
      break // Quantité demandée satisfaite
    }
  }
  
  // Vérifier si quantité suffisante
  if (quantiteRestante > 0) {
    throw new Error(
      "Stock insuffisant. Manque: " + quantiteRestante + 
      " (lots disponibles épuisés)"
    )
  }
  
  return {
    lots: lotsSelectionnes,
    alertes: alertes
  }
}

Exemple d'utilisation :
resultat = selectionnerLotsPourSortie(
  "LLC-SF-BOUL-BOEUF", 
  150, 
  "2025-01-19"
)

// Résultat:
{
  lots: [
    {
      numeroLot: "LOT-20250113-001",
      quantite: 45,
      dlu: "2025-01-18"
    },
    {
      numeroLot: "LOT-20250118-001",
      quantite: 105,
      dlu: "2025-01-23"
    }
  ],
  alertes: [
    {
      type: "WARNING",
      lot: "LOT-20250113-001",
      message: "DLU proche: 2025-01-18. À consommer rapidement."
    }
  ]
}

RG-006 : Scan Quotidien DLU

// Tâche planifiée (CRON) à exécuter tous les jours à 6h00
function scanQuotidienDLU() {
  aujourdhui = today()
  demain = addDays(aujourdhui, 1)
  dansDeuJours = addDays(aujourdhui, 2)
  
  // 1. Lots périmés aujourd'hui
  lotsPérimes = database.query(
    "SELECT * FROM lots 
     WHERE dateLimiteUtilisation <= ? 
     AND statut != 'perime'",
    [aujourdhui]
  )
  
  for (lot in lotsPérimes) {
    // Bloquer le lot
    lot.statut = "perime"
    saveLot(lot)
    
    // Notification critique
    envoyerNotification({
      type: "CRITIQUE",
      priorite: "URGENT",
      destinataires: ["gestionnaire.stock@laloui sette.com", "admin@lalou isette.com"],
      sujet: "⚠️ LOT PÉRIMÉ: " + lot.numeroLot,
      message: "Le lot " + lot.numeroLot + " (" + lot.articleCode + ") " +
               "a atteint sa DLU. Quantité à détruire: " + lot.quantiteRestante
    })
  }
  
  // 2. Lots périmant demain
  lotsDemain = database.query(
    "SELECT * FROM lots 
     WHERE dateLimiteUtilisation = ?
     AND statut IN ('disponible', 'partiellement-utilise')",
    [demain]
  )
  
  for (lot in lotsDemain) {
    envoyerNotification({
      type: "ALERTE",
      priorite: "HAUTE",
      destinataires: ["gestionnaire.stock@lalou isette.com"],
      sujet: "⚠️ DLU DEMAIN: " + lot.numeroLot,
      message: "Le lot " + lot.numeroLot + " périme demain. " +
               "Quantité restante: " + lot.quantiteRestante + ". " +
               "À écouler en priorité."
    })
  }
  
  // 3. Lots périmant dans 2 jours
  lotsDansDeuJours = database.query(
    "SELECT * FROM lots 
     WHERE dateLimiteUtilisation = ?
     AND statut IN ('disponible', 'partiellement-utilise')",
    [dansDeuJours]
  )
  
  for (lot in lotsDansDeuJours) {
    envoyerNotification({
      type: "INFO",
      priorite: "NORMALE",
      destinataires: ["gestionnaire.stock@lalou isette.com"],
      sujet: "ℹ️ DLU dans 2 jours: " + lot.numeroLot,
      message: "Le lot " + lot.numeroLot + " périme dans 2 jours. " +
               "Quantité: " + lot.quantiteRestante
    })
  }
  
  // 4. Génération rapport quotidien
  genererRapportDLU(aujourdhui)
}

📄 Génération de Documents

Spécifications PDF

⚠️ CONTRAINTE ABSOLUE : Tous les PDF doivent être en orientation PAYSAGE (landscape), jamais portrait.
Configuration PDF :
{
  format: "A4",
  orientation: "landscape", // ⚠️ OBLIGATOIRE
  marges: {
    top: 20,
    right: 15,
    bottom: 20,
    left: 15
  },
  unite: "mm"
}

Structure de base :

┌─────────────────────────────────────────────────┐
│ EN-TÊTE                                         │
│ - Logo (si disponible)                          │
│ - Nom établissement                             │
│ - Type de document                              │
│ - Numéro document                               │
│ - Date                                          │
├─────────────────────────────────────────────────┤
│ INFORMATIONS DOCUMENT                           │
│ - Restaurant/Fournisseur                        │
│ - Dates                                         │
│ - Références                                    │
├─────────────────────────────────────────────────┤
│ TABLEAU ARTICLES                                │
│ (Largeur maximisée grâce au format paysage)     │
│                                                 │
│ Colonnes selon type de document:                │
│ - Code | Désignation | Unité | Quantités...    │
├─────────────────────────────────────────────────┤
│ PIED DE PAGE                                    │
│ - Observations                                  │
│ - Signatures (Expéditeur / Récepteur)          │
│ - Date d'impression                             │
└─────────────────────────────────────────────────┘

Spécifications Excel

Feuilles à créer selon type:

Pour Bon de Commande / Sortie / Livraison / Réception:
- Feuille 1: "Document" (tableau principal)
- Feuille 2: "Récapitulatif" (totaux, statistiques)

Pour Fiche de Stock:
- Feuille 1: "Fiche Stock" (mouvements détaillés)
- Colonnes:
  * Code Article
  * Désignation
  * Unité
  * Stock Initial (Qté | PU | Montant)
  * Entrées (Qté | PU | Montant)
  * Sorties (Qté | PU | Montant)
  * Stock Final (Qté | PU | Montant)

Mise en forme:
- En-tête: Police gras, fond gris, bordures
- Données: Bordures fines, alternance lignes
- Nombres: Format numérique avec séparateurs milliers
- Montants: Format monétaire (FCFA)
- Largeurs colonnes: Auto-ajustées au contenu

Modèles Spécifiques par Restaurant

Restaurant Colonnes Spécifiques
FF Paul Langevin Standard: Code | Désignation | Unité (g/kg/L) | Qté | Observations
FF Koumassi + Format | Poids Total (calculé)
Ma Glace + Colonne "g" (grammes)
Villa Standard
Casa Mexicana À définir (utiliser standard par défaut)

🔐 Sécurité et Authentification

Profils Utilisateurs

{
  id: string,
  nom: string,
  prenom: string,
  email: string,
  motDePasse: string (hashé),
  profil: "admin" | "stock-principal" | "cuisine-centrale" | "restaurant" | "consultation",
  restaurantAffecte: string (optionnel, pour profils restaurant),
  actif: boolean,
  dateCreation: date,
  derniereConnexion: date
}

Matrice de Droits

Fonctionnalité Admin Stock Principal Cuisine Centrale Restaurant
Gestion utilisateurs
Gestion articles 👁️ Lecture 👁️ Lecture
Gestion nomenclatures 👁️ Lecture
BRF (Réception Fournisseur)
BRP (Réquisition Production) 👁️ Lecture
BSP (Sortie Production) 👁️ Lecture
BF (Fabrication) 👁️ Lecture
BRETP (Retour Production) 👁️ Lecture
BC (Bon Commande) 👁️ Lecture ✅ (Son restaurant)
BS/BL (Sortie/Livraison) 👁️ Lecture
BR (Réception) 👁️ Lecture ✅ (Son restaurant)
Vue stock global 👁️ Stock Principal ❌ (Uniquement son resto)

✅ Critères d'Acceptation

Groupe 1 : Gestion de Base

Groupe 2 : Documents

Groupe 3 : Stock

Groupe 4 : Production

Groupe 5 : Traçabilité

Groupe 6 : Rapports

Groupe 7 : Interface

🎯 Planning de Développement Recommandé

Phase Durée Livrables
Phase 1 : Fondations 3 semaines - Base de données
- Authentification
- CRUD Restaurants & Articles
- Gestion utilisateurs
Phase 2 : Stock Principal 2 semaines - Module stock principal
- BRF (Réception fournisseurs)
- Gestion lots
- Alertes DLU
Phase 3 : Production 3 semaines - Nomenclatures
- Cycle complet production (4 docs)
- Calcul rendement
- Gestion DLU produits
Phase 4 : Restaurants 2 semaines - BC, BS, BL, BR
- Stock restaurants
- FIFO automatique
Phase 5 : Documents & Rapports 2 semaines - Génération PDF/Excel
- Modèles par restaurant
- Rapports
Phase 6 : Tests & Déploiement 1 semaine - Tests complets
- Corrections
- Déploiement
- Formation
Total estimé : 13 semaines pour une application complète et fonctionnelle.

📚 Ressources & Références

Documentation Complète

Fichiers JSON de Référence

Les fichiers JSON originaux fournis par le client se trouvent dans :

d:\TRAVAIL\Docs\Bons - Copie\
├── FF PL\
│   ├── Bon_de_commande_PL.json
│   └── Fiche de stock ff PL.json
├── FF KOUMASSI\
│   └── Bon de commande ff koumassi.json
├── MA GLACE\
│   └── Bon de commande ma glace.json
└── VILLA\
    └── Bon_de commande Villa.json

Contact

Pour toute question ou clarification, contacter le chef de projet.

🎉 Vous avez maintenant toutes les informations nécessaires !

Cette documentation complète vous permet de développer l'application de A à Z.

Bon développement ! 💪