Files
Snacks-Analytics-backend/src/modules/pdf-parse.ts
Lazanimady Andrianirindrainy dbdebae45e update: purchase.routes.ts pour fonction avec pdf-parse.ts
on peut maintenant envoyer des fichier pdf sur un form et il renvoie un json avec les informations du pdf. dans /new-purchase
2026-06-23 23:46:52 +02:00

132 lines
4.2 KiB
TypeScript

import * as fs from 'fs';
const pdfjsLib = require('pdfjs-dist');
async function pdfParse(travel: string) {
interface DetailProduit {
quantité: number;
prixHT: number;
TVA: string;
}
interface res {
marque: string;
date_achats: string;
products: {
[nomProduit: string]: DetailProduit;
};
}
const productsList: { [key: string]: DetailProduit } = {};
let fournisseur = '';
let date = '';
const cheminPDF = travel;
try {
// Lecture du fichier binaire du PDF et conversion pour PDF.js
const dataBuffer = new Uint8Array(fs.readFileSync(cheminPDF));
// Chargement du document par PDF.js
const loadingTask = pdfjsLib.getDocument({ data: dataBuffer });
const pdf = await loadingTask.promise;
let texte = '';
// Boucle pour extraire le texte de chaque page du PDF
for (let i = 1; i <= pdf.numPages; i++) {
const page = await pdf.getPage(i);
const textContent = await page.getTextContent();
// On récupère chaque fragment de texte trouvé graphiquement sur la page et on les sépare par un saut de ligne
const textePage = textContent.items.map((item: any) => item.str).join('\n');
texte += textePage + '\n';
}
const regexAuchan = /auchan/i.test(texte);
// on regarde si c'est auchan ou metro
if (regexAuchan) {
fournisseur = "Auchan";
// on regarde la date d'achat avec une expression reguliere pour auchan
const regexDate = /(\d{2})\/(\d{2})\/(\d{4})/;
const correspondance = texte.match(regexDate);
if (correspondance) {
date = correspondance[0]
} else {
date = "non trouvé"
}
// Découpage en lignes pour l'analyse
const lignes = texte.split('\n').map(l => l.trim()).filter(l => l.length > 0);
// Algorithme de recherche verticale pour Auchan
for (let i = 0; i < lignes.length; i++) {
// Si la ligne correspond exactement à un code-barres à 13 chiffres
if (/^\d{13}$/.test(lignes[i])) {
const nomProduit = lignes[i + 1];
let idxQuantite = i + 3;
let idxPrixHT = i + 4;
let idxTva = i + 5;
// Gestion de la ligne parasite Eco-participation qui décale le tableau
if (lignes[i + 2] && lignes[i + 2].includes("Eco-participation")) {
idxQuantite += 2;
idxPrixHT += 2;
idxTva += 2;
}
const qte = lignes[idxQuantite];
const prix = lignes[idxPrixHT];
const tva = lignes[idxTva];
let tvaFinal: string;
if (tva) {
tvaFinal = tva.replace(',', '.').trim() + "%";
} else {
tvaFinal = "non trouvé";
}
productsList[nomProduit] = {
quantité: parseInt(qte, 10),
prixHT: parseFloat(prix.replace(',', '.')),
TVA: tvaFinal
};
}
}
} else {
fournisseur = "Metro";
// on regarde la date d'achat avec une expression reguliere pour metro
const regexDate = /(\d{2})-(\d{2})-(\d{4})/;
const correspondance = texte.match(regexDate);
if (correspondance) {
date = correspondance[0]
} else {
date = "non trouvé"
}
}
// Construction de l'objet final
const resultat: res = {
marque: fournisseur,
date_achats: date,
products: productsList
};
return resultat;
} catch (e) {
console.error("Erreur :", e);
}
}
export default pdfParse;