Améliorationde l'import

This commit is contained in:
2026-07-04 18:55:40 +02:00
parent 11790c63fe
commit b138bc53ee
3 changed files with 180 additions and 8 deletions
+47 -3
View File
@@ -122,6 +122,21 @@ router.post('/apply', (req, res, next) => {
const { rows } = parseFile(tempPath, origName || 'file.xlsx');
// Résolution plateforme_id / investissement_id : accepte un ID numérique OU un nom
// (ex. colonne "Plateforme" contenant "BienPrêter" plutôt qu'un ID) — cf. resolveRefId.
let platIdSet = new Set(), platNameMap = new Map();
if (module === 'depots_retraits' || module === 'investissements') {
const platRows = db.prepare('SELECT id, nom FROM plateformes WHERE user_id = ?').all(req.user.id);
platIdSet = new Set(platRows.map(p => p.id));
platNameMap = new Map(platRows.map(p => [normalizeName(p.nom), p.id]));
}
let invIdSet = new Set(), invNameMap = new Map();
if (module === 'remboursements') {
const invRows = db.prepare('SELECT id, nom_projet FROM investissements WHERE investisseur_id = ?').all(req.investisseur.id);
invIdSet = new Set(invRows.map(i => i.id));
invNameMap = new Map(invRows.map(i => [normalizeName(i.nom_projet), i.id]));
}
let inserted = 0, skipped = 0;
const errors = [];
@@ -144,7 +159,7 @@ router.post('/apply', (req, res, next) => {
VALUES (?,?,?,?,?,?,?,?)
`).run(
req.investisseur.id,
Number(v('plateforme_id')),
resolveRefId(v('plateforme_id'), platIdSet, platNameMap, 'Plateforme'),
normaliseDate(v('date_operation')),
normaliseType(v('type')),
num(v('montant')),
@@ -162,7 +177,7 @@ router.post('/apply', (req, res, next) => {
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
`).run(
req.investisseur.id,
Number(v('plateforme_id')),
resolveRefId(v('plateforme_id'), platIdSet, platNameMap, 'Plateforme'),
String(v('nom_projet')),
v('emetteur') || null,
normaliseDate(v('date_souscription')),
@@ -192,7 +207,7 @@ router.post('/apply', (req, res, next) => {
prelev_forfaitaire, interets_nets, net_recu, statut, source)
VALUES (?,?,?,?,?,?,?,?,?,?,?)
`).run(
Number(v('investissement_id')),
resolveRefId(v('investissement_id'), invIdSet, invNameMap, 'Investissement'),
normaliseDate(v('date_remb')),
capital, cashback, bruts, ps, pf, interets_nets, net_recu,
v('statut') || 'paye',
@@ -496,6 +511,35 @@ function stripAccents(s) {
return String(s).normalize('NFD').replace(/[̀-ͯ]/g, '');
}
/** Normalise un nom pour comparaison insensible à la casse/accents (ex. plateforme, projet) */
function normalizeName(s) {
return stripAccents(String(s || ''))
.toLowerCase()
.trim()
.replace(/\s+/g, ' ');
}
/**
* Résout une valeur de colonne (ID numérique OU nom texte) vers l'ID cible réel.
* - Si la valeur est un entier, elle doit correspondre à un ID existant (idSet).
* - Sinon, elle est recherchée par nom normalisé (nameMap) — insensible casse/accents.
* Lève une erreur explicite si rien ne correspond (la ligne sera ignorée par l'appelant).
*/
function resolveRefId(value, idSet, nameMap, label) {
if (value === undefined || value === null || String(value).trim() === '') {
throw new Error(`${label} manquant`);
}
const raw = String(value).trim();
if (/^\d+$/.test(raw)) {
const id = Number(raw);
if (idSet.has(id)) return id;
throw new Error(`${label} #${id} introuvable`);
}
const id = nameMap.get(normalizeName(raw));
if (id == null) throw new Error(`${label} "${raw}" introuvable`);
return id;
}
/** Convertit une valeur monétaire en nombre (gère "€", espaces, virgule décimale) */
function num(v) {
if (v === undefined || v === null || v === '') return 0;