Améliorationde l'import
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user