resanomaliedoublejustifavecqrcode
This commit is contained in:
@@ -2091,11 +2091,24 @@ app.post('/api/notes', authenticateToken, upload.any(), async (req, res) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── QR par ligne : téléchargement + upload en parallèle ──────────
|
// ── QR par ligne : ne re-télécharge/ré-upload que si le client n'a pas déjà le fichier ──
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
lignesParsed.map(async (ligne, i) => {
|
lignesParsed.map(async (ligne, i) => {
|
||||||
const ligneQrRef = ligne.qrNoteRef;
|
const ligneQrRef = ligne.qrNoteRef;
|
||||||
if (!ligneQrRef) return;
|
if (!ligneQrRef) return;
|
||||||
|
|
||||||
|
// ✅ Si le client a déjà reçu ce fichier via le polling QR (origin 'qr'),
|
||||||
|
// il est déjà dans ligne.qrFiles avec son uploadUrl d'origine.
|
||||||
|
// Pas besoin de re-télécharger/ré-uploader : on évite ainsi le doublon
|
||||||
|
// causé par un nouveau nom de fichier (basé sur la référence finale de la note).
|
||||||
|
const dejaRecuParClient = Array.isArray(ligne.qrFiles) &&
|
||||||
|
ligne.qrFiles.some(f => !f.origin || f.origin === 'qr');
|
||||||
|
|
||||||
|
if (dejaRecuParClient) {
|
||||||
|
console.log(`✅ QR ligne ${i} (${ligneQrRef}) : fichier déjà reçu côté client, pas de re-upload`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const qrLigne = await pool.request()
|
const qrLigne = await pool.request()
|
||||||
.input('noteRef', sql.NVarChar, ligneQrRef)
|
.input('noteRef', sql.NVarChar, ligneQrRef)
|
||||||
@@ -2534,9 +2547,18 @@ app.put('/api/notes/:id', authenticateToken, upload.any(), async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QR par ligne
|
// QR par ligne
|
||||||
|
// QR par ligne — skip si le client a déjà le fichier (évite doublon)
|
||||||
for (let i = 0; i < lignesParsed.length; i++) {
|
for (let i = 0; i < lignesParsed.length; i++) {
|
||||||
const ligneQrRef = lignesParsed[i].qrNoteRef;
|
const ligneQrRef = lignesParsed[i].qrNoteRef;
|
||||||
if (!ligneQrRef) continue;
|
if (!ligneQrRef) continue;
|
||||||
|
|
||||||
|
const dejaRecuParClient = Array.isArray(lignesParsed[i].qrFiles) &&
|
||||||
|
lignesParsed[i].qrFiles.some(f => !f.origin || f.origin === 'qr');
|
||||||
|
if (dejaRecuParClient) {
|
||||||
|
console.log(`✅ [CAS1] QR ligne ${i} (${ligneQrRef}) : fichier déjà reçu côté client, pas de re-upload`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const qrLigne = await pool.request()
|
const qrLigne = await pool.request()
|
||||||
.input('noteRef', sql.NVarChar, ligneQrRef)
|
.input('noteRef', sql.NVarChar, ligneQrRef)
|
||||||
|
|||||||
@@ -1951,13 +1951,14 @@ export default function NouvelleNote({
|
|||||||
const s = await r.json();
|
const s = await r.json();
|
||||||
if (s.uploaded) {
|
if (s.uploaded) {
|
||||||
clearInterval(qrPollingRefs.current[depenseId]);
|
clearInterval(qrPollingRefs.current[depenseId]);
|
||||||
|
delete qrPollingRefs.current[depenseId]; // ✅ empêche un 2e tick concurrent de re-déclencher la fusion
|
||||||
setDepenses(prev => prev.map(d => d.id === depenseId
|
setDepenses(prev => prev.map(d => d.id === depenseId
|
||||||
? {
|
? {
|
||||||
...d, qrUploaded: true, qrLink: null,
|
...d, qrUploaded: true, qrLink: null,
|
||||||
qrFiles: [
|
qrFiles: [
|
||||||
...(d.qrFiles ?? []),
|
...(d.qrFiles ?? []),
|
||||||
...(Array.isArray(s.files) ? s.files.map((f: any) => ({ ...f, origin: 'qr' as const })) : [])
|
...(Array.isArray(s.files) ? s.files.map((f: any) => ({ ...f, origin: 'qr' as const })) : [])
|
||||||
]
|
].filter((f, i, arr) => arr.findIndex(x => x.uploadUrl === f.uploadUrl) === i) // ✅ dédup par URL
|
||||||
}
|
}
|
||||||
: d));
|
: d));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user