From 2ca6dc31a9f2e996b313dcaa918a057574de644b Mon Sep 17 00:00:00 2001 From: Aurelien Date: Wed, 17 Jun 2026 12:30:39 +0200 Subject: [PATCH 1/2] feat : ajout d'un parse pour facture #5 --- package-lock.json | 21 +++++++++++-- package.json | 3 +- src/modules/pdf-parse.ts | 65 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 src/modules/pdf-parse.ts diff --git a/package-lock.json b/package-lock.json index b43acfa..2c7deb3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,8 @@ "license": "ISC", "dependencies": { "dotenv": "^17.4.2", - "express": "^5.2.1" + "express": "^5.2.1", + "pdf-parse-fork": "^1.2.0" }, "devDependencies": { "@types/express": "^5.0.6", @@ -147,7 +148,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.3.tgz", "integrity": "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg==", "dev": true, - "license": "MIT", "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } @@ -970,6 +970,11 @@ "node": ">= 0.6" } }, + "node_modules/node-ensure": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/node-ensure/-/node-ensure-0.0.0.tgz", + "integrity": "sha512-DRI60hzo2oKN1ma0ckc6nQWlHU69RH6xN0sjQTjMpChPfTYvKZdcQFfdYK2RWbJcKyUizSIy/l8OTGxMAM1QDw==" + }, "node_modules/nodemon": { "version": "3.1.14", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", @@ -1061,6 +1066,18 @@ "url": "https://opencollective.com/express" } }, + "node_modules/pdf-parse-fork": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pdf-parse-fork/-/pdf-parse-fork-1.2.0.tgz", + "integrity": "sha512-ovXkJaTtw8PfLNhBThKHKsZlT6WrCkVKY/QgsDK5GiD/tuL2qzezSlHpEgqHCnq3r/0GOq3NZ+won78KL/dAjQ==", + "dependencies": { + "debug": "^4.3.4", + "node-ensure": "^0.0.0" + }, + "engines": { + "node": ">=6.8.1" + } + }, "node_modules/picomatch": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", diff --git a/package.json b/package.json index fd63cea..f70560d 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ }, "dependencies": { "dotenv": "^17.4.2", - "express": "^5.2.1" + "express": "^5.2.1", + "pdf-parse-fork": "^1.2.0" }, "devDependencies": { "@types/express": "^5.0.6", diff --git a/src/modules/pdf-parse.ts b/src/modules/pdf-parse.ts new file mode 100644 index 0000000..ec63171 --- /dev/null +++ b/src/modules/pdf-parse.ts @@ -0,0 +1,65 @@ +const fs = require('fs'); +const pdfParse = require('pdf-parse-fork'); + +function pdf_parse(travel: string){ + interface PdfData { + text: string; + } + + let fournisseur = ''; + let date = ''; + + interface tab_res { + marque : string; + date_achats : string; + } + + const dataBuffer = fs.readFileSync(travel); + + pdfParse(dataBuffer) + .then((data: PdfData) => { + // on regarde si c'est auchan ou metro + const regexAuchan = /auchan/i; + if (regexAuchan.test(data.text)) { + fournisseur = "Auchan" + + // on regarde la date d'achat avec une expression reguliere pour auchan + const regexDate = /(\d{2})\/(\d{2})\/(\d{4})/; + const correspondance = data.text.match(regexDate); + if (correspondance) { + date = correspondance[0] + } else { + date = "non trouvé" + } + + } 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 = data.text.match(regexDate); + if (correspondance) { + date = correspondance[0] + } else { + date = "non trouvé" + } + } + + // on renvoie les valeur avec un seul objet + + const res : tab_res = { + marque: fournisseur, + date_achats: date + } + + console.log(res); + + }) + + + .catch((error: unknown) => { + console.error("Erreur :", error); + }); +} + +export default pdf_parse; \ No newline at end of file From 00949c60c5cd5f17f3e46c26baa98f0b10dd6f85 Mon Sep 17 00:00:00 2001 From: Aurelien Date: Thu, 18 Jun 2026 20:46:12 +0200 Subject: [PATCH 2/2] chore : modification du parse pour avoir la liste des produit #5 --- src/modules/pdf-parse.ts | 47 +++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/src/modules/pdf-parse.ts b/src/modules/pdf-parse.ts index ec63171..c1490fd 100644 --- a/src/modules/pdf-parse.ts +++ b/src/modules/pdf-parse.ts @@ -9,11 +9,23 @@ function pdf_parse(travel: string){ let fournisseur = ''; let date = ''; - interface tab_res { - marque : string; - date_achats : string; + interface DetailProduit { + quantité: number; + prixHT: number; + TVA: string; } + const productsList: { [key: string]: DetailProduit } = {}; + + interface tab_res { + marque: string; + date_achats: string; + products: { + [nomProduit: string]: DetailProduit; + }; + } + + const dataBuffer = fs.readFileSync(travel); pdfParse(dataBuffer) @@ -31,6 +43,30 @@ function pdf_parse(travel: string){ } else { date = "non trouvé" } + + // on prend la liste des produits et leurs detail pour auchan + const lignes = data.text.split('\n'); + + // Expressions régulières pour détecter les lignes de produits Auchan + const regexLigneProduit = /^(\d{13})(?!\d)(.+?)(\d+,\d+)\s+(\d+)\s+(\d+,\d+)\s+(\d+,\d+)\s+(\d+,\d+)$/; + + lignes.forEach((ligne: string) => { + const match = ligne.trim().match(regexLigneProduit); + + if (match) { + const nomProduit = match[1].trim(); + const quantite = parseInt(match[4], 10); + const prixHT = parseFloat(match[2].replace(',', '.')); + const tva = match[6].replace(',', '.') + "%"; + + productsList[nomProduit] = { + quantité: quantite, + prixHT: prixHT, + TVA: tva + }; + } + }); + } else { fournisseur = "Metro" @@ -48,8 +84,9 @@ function pdf_parse(travel: string){ // on renvoie les valeur avec un seul objet const res : tab_res = { - marque: fournisseur, - date_achats: date + marque: fournisseur, + date_achats: date, + products: productsList } console.log(res);