Pointez la caméra vers le QR Code collé sur un bac.
La caméra arrière s'ouvre pour lire les QR codes des bacs.
✅
QR Code lu !
▸ Mode simulation (sans caméra)
Fournitures & Mouvements
Liste des stocks, emprunts en cours et journal des modifications.
0Articles
0À renouveler / Épuisés
Liste des Stocks
Emprunts Actifs de Matériel
Fourniture
Catégorie
Emprunteur
Date d'emprunt
Actions
Journal des modifications récentes
Configuration & Aide
Lier votre Google Sheet
Collez simplement l'URL de votre feuille Google Sheets. L'application en extraira automatiquement l'identifiant.
Assurez-vous que la feuille est partagée en lecture « Tout le monde avec le lien ».
Synchronisation automatique (optionnel)
Pour que chaque modification de stock se synchronise directement dans Google Sheets, déployez le script ci-dessous sur votre feuille,
puis collez ici l'URL obtenue.
📋 Voir les instructions (déployer le script Google)
Ouvrez votre Google Sheet
Menu Extensions > Apps Script
Supprimez le code existant et collez le script ci-dessous
Cliquez Déployer > Nouveau déploiement > type Application Web
Exécuter en tant que : Moi — Accès : Tout le monde
Validez et copiez l'URL générée (se terminant par /exec)
/* ================================================
Débrouill'Stock — Script de synchronisation
Coller dans Extensions › Apps Script › Déployer
================================================ */
var CATEGORY_SHEETS = {
"Régie": "régie",
"Bureau": "fournitures bureau ",
"Verrerie": "verrerie",
"Outillage": "atelier",
"Secours": "secours",
"Numérique": "numérique",
"Jeux": "jeux",
"Bibliothèque": "bibliothèque"
};
var QTY_COL = { "régie":2, "fournitures bureau ":2, "verrerie":2, "atelier":2, "secours":2, "numérique":2, "jeux":null, "bibliothèque":null };
var RENOUV_COL = { "régie":4, "fournitures bureau ":5, "verrerie":5, "atelier":5, "secours":5, "numérique":5, "jeux":null, "bibliothèque":null };
function doGet(e) {
try {
var p = e.parameter;
if (!p || !p.name) return ok({error:"Paramètres manquants"});
p.quantity = parseInt(p.quantity) || 0;
p.delta = parseInt(p.delta) || 0;
var ss = SpreadsheetApp.getActiveSpreadsheet();
// 1. Chercher l'onglet de la catégorie
var sheetName = CATEGORY_SHEETS[p.category] || null;
var updated = false;
if (sheetName) {
var sheet = ss.getSheetByName(sheetName);
if (sheet) updated = updateItem(sheet, sheetName, p);
}
// 2. Fallback : chercher dans tous les onglets
if (!updated) {
var sheets = ss.getSheets();
for (var i = 0; i < sheets.length && !updated; i++) {
var sn = sheets[i].getName().toLowerCase().trim();
if (sn === "inventaire" || sn === "tableau entrée et sortie") continue;
updated = updateItem(sheets[i], sn, p);
}
}
// 2b. Mettre à jour aussi l'onglet Inventaire (Quantité=col5, État=col4)
var invSheet = ss.getSheetByName("Inventaire");
if (invSheet) updateInventaire(invSheet, p);
// 3. Journaliser dans "Tableau entrée et sortie"
if (p.delta && p.delta !== 0) {
var log = ss.getSheetByName("Tableau entrée et sortie");
if (log) {
log.appendRow([new Date(), p.user||"Animateur", p.name, "",
Math.abs(p.delta), new Date().toLocaleDateString("fr-FR"), "Bon état","",""]);
}
}
return ok({success:true, updated:updated});
} catch(err) { return ok({success:false, error:err.toString()}); }
}
function updateItem(sheet, sheetName, p) {
var data = sheet.getDataRange().getValues();
var sn = sheetName.toLowerCase().trim();
var qc = (QTY_COL[sn] !== undefined) ? QTY_COL[sn] : 2;
var rc = (RENOUV_COL[sn] !== undefined) ? RENOUV_COL[sn] : null;
for (var i = 1; i < data.length; i++) {
if (!data[i][0]) continue;
if (String(data[i][0]).trim().toLowerCase() === String(p.name).trim().toLowerCase()) {
if (qc !== null && p.quantity !== undefined) sheet.getRange(i+1, qc+1).setValue(p.quantity);
if (rc !== null) sheet.getRange(i+1, rc+1).setValue(statusToRenouv(p.status, p.quantity));
return true;
}
}
return false;
}
function updateInventaire(sheet, p) {
var data = sheet.getDataRange().getValues();
for (var i = 1; i < data.length; i++) {
if (!data[i][0]) continue;
if (String(data[i][0]).trim().toLowerCase() === String(p.name).trim().toLowerCase()) {
sheet.getRange(i+1, 6).setValue(p.quantity); // Quantité = col F (index 5, 1-based=6)
sheet.getRange(i+1, 5).setValue(p.status); // État = col E (index 4, 1-based=5)
return true;
}
}
return false;
}
function statusToRenouv(status, qty) {
if (status === "Épuisé" || qty === 0) return "Aucun stock";
if (status === "À renouveler") return "Manque de stock";
return "Suffisant";
}
function ok(obj) {
return ContentService.createTextOutput(JSON.stringify(obj))
.setMimeType(ContentService.MimeType.JSON);
}