Checkpoint: Migration complète localStorage → BDD : useBudgetData, ParametresContext, Budget2027, DsiCapex, DsiOpex, ImportModal (indicateur inventaires + suppression double-écriture). Ajout procédures tRPC : inventaire.listMeta, inventaire.getStats, opex.initFromSource, opex.deleteAll, opex.cloneFromN1. 14 tests Vitest passants. 0 erreur TypeScript.
This commit is contained in:
@@ -255,9 +255,12 @@ interface ImportModalProps {
|
||||
export function ImportModal({ open, onClose }: ImportModalProps) {
|
||||
const { annee } = useAnnee();
|
||||
const utils = trpc.useUtils();
|
||||
const { data: inventaireMetaList } = trpc.inventaire.listMeta.useQuery();
|
||||
const importInventaireMutation = trpc.inventaire.import.useMutation({
|
||||
onSuccess: () => {
|
||||
utils.inventaire.get.invalidate();
|
||||
utils.inventaire.listMeta.invalidate();
|
||||
utils.inventaire.getStats.invalidate();
|
||||
window.dispatchEvent(new CustomEvent('budgetsi_inventaire_updated', { detail: { annee } }));
|
||||
},
|
||||
});
|
||||
@@ -537,31 +540,6 @@ export function ImportModal({ open, onClose }: ImportModalProps) {
|
||||
// ── Envoyer à la base de données via tRPC ──────────────────────────────────
|
||||
const result = await importInventaireMutation.mutateAsync({ annee, filename: file.name, postes: postesPayload });
|
||||
|
||||
// ── Aussi sauvegarder dans localStorage pour compatibilité avec les pages existantes ──
|
||||
const etablissementsArray = Array.from(etabData.entries()).map(([code, d]) => ({
|
||||
code,
|
||||
nom: d.nom,
|
||||
fixes: d.fixes,
|
||||
portables: d.portables,
|
||||
stats: {
|
||||
nb_fixes_total: d.fixes.length,
|
||||
nb_portables_total: d.portables.length,
|
||||
nb_fixes_renouveler: 0,
|
||||
nb_portables_renouveler: 0,
|
||||
nb_fixes_sans_date: d.fixes.filter(f => f.age_ans === null).length,
|
||||
nb_portables_sans_date: d.portables.filter(p => p.age_ans === null).length,
|
||||
budget_fixes: 0,
|
||||
budget_portables: 0,
|
||||
budget_total: 0,
|
||||
},
|
||||
}));
|
||||
const inventaireData = {
|
||||
meta: { date_calcul: new Date().toISOString(), date_reference: `${annee}-01-01`, nb_etablissements: etabData.size, total_fixes: nbFixes, total_portables: nbPortables, filename: file.name },
|
||||
etablissements: etablissementsArray,
|
||||
};
|
||||
localStorage.setItem(getInventaireStorageKey(annee), JSON.stringify(inventaireData));
|
||||
localStorage.setItem(`budgetsi_inventaire_import_${annee}`, JSON.stringify({ filename: file.name, date: new Date().toISOString(), size: file.size, nbLignes: rows.length - 1, nbEtablissements: etabData.size, nbFixes, nbPortables, format: useIsiFormat ? 'isi-app' : 'classique' }));
|
||||
|
||||
// ── Upsert établissements dans la BDD ──────────────────────────────────────
|
||||
for (const [code, info] of Array.from(etabData.entries())) {
|
||||
try {
|
||||
@@ -871,8 +849,9 @@ export function ImportModal({ open, onClose }: ImportModalProps) {
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-2 p-3">
|
||||
{[2025, 2026, 2027, 2028, 2029, 2030].map(yr => {
|
||||
const hasData = !!localStorage.getItem(`budgetsi_inventaire_data_${yr}`);
|
||||
const meta = (() => { try { const d = localStorage.getItem(`budgetsi_inventaire_import_${yr}`); return d ? JSON.parse(d) : null; } catch { return null; } })();
|
||||
const metaRow = inventaireMetaList?.find(m => m.annee === yr);
|
||||
const hasData = !!metaRow;
|
||||
const meta = metaRow ? { filename: metaRow.filename, nbLignes: (metaRow.nbFixes ?? 0) + (metaRow.nbPortables ?? 0), date: metaRow.dateImport?.toISOString() ?? '' } : null;
|
||||
return (
|
||||
<div
|
||||
key={yr}
|
||||
|
||||
Reference in New Issue
Block a user