143 lines
4.6 KiB
TypeScript
143 lines
4.6 KiB
TypeScript
import * as fs from 'fs';
|
|
const pdfjsLib = require('pdfjs-dist');
|
|
|
|
|
|
async function pdf_parse(travel: string) {
|
|
interface product_details {
|
|
quantity: number;
|
|
price_ht: number;
|
|
tva: string;
|
|
}
|
|
|
|
interface res {
|
|
brand: string;
|
|
purchase_date: string;
|
|
products: {
|
|
[product_name: string]: product_details;
|
|
};
|
|
}
|
|
|
|
const product_list: { [key: string]: product_details } = {};
|
|
let supplier = '';
|
|
let date = '';
|
|
|
|
const pdf_path = travel;
|
|
|
|
try {
|
|
// Lecture du fichier binaire du PDF et conversion pour PDF.js
|
|
const data_buffer = new Uint8Array(fs.readFileSync(pdf_path));
|
|
|
|
// Chargement du document par PDF.js
|
|
const loading_task = pdfjsLib.getDocument({ data: data_buffer });
|
|
const pdf = await loading_task.promise;
|
|
|
|
let text = '';
|
|
|
|
// Boucle pour extraire le text de chaque page du PDF
|
|
for (let i = 1; i <= pdf.numPages; i++) {
|
|
const page = await pdf.getPage(i);
|
|
const text_content = await page.getTextContent();
|
|
|
|
// On récupère chaque fragment de text trouvé graphiquement sur la page et on les sépare par un saut de ligne
|
|
const text_page = text_content.items.map((item: any) => item.str).join('\n');
|
|
text += text_page + '\n';
|
|
}
|
|
|
|
const regex_auchan = /auchan/i.test(text);
|
|
|
|
// on regarde si c'est auchan ou metro
|
|
|
|
if (regex_auchan) {
|
|
supplier = "Auchan";
|
|
|
|
// on regarde la date d'achat avec une expression reguliere pour auchan
|
|
const regex_date = /(\d{2})\/(\d{2})\/(\d{4})/;
|
|
const corres = text.match(regex_date);
|
|
if (corres) {
|
|
date = corres[0]
|
|
} else {
|
|
date = "non trouvé"
|
|
}
|
|
|
|
// Découpage en lignes pour l'analyse et cration d'un tableau de toutes les lignes
|
|
const lines = text.split('\n').map(l => l.trim()).filter(l => l.length > 0);
|
|
|
|
// Algorithme de recherche verticale pour Auchan
|
|
for (let i = 0; i < lines.length; i++) {
|
|
// Si la ligne correspond exactement à un code-barres à 13 chiffres
|
|
if (/^\d{13}$/.test(lines[i])) {
|
|
const product_name = lines[i + 1];
|
|
const qte = lines[i + 3];
|
|
const price = lines[i + 4];
|
|
const tva = lines[i + 5];
|
|
|
|
product_list[product_name] = {
|
|
quantity: parseInt(qte, 10),
|
|
price_ht: parseFloat(price.replace(',', '.')),
|
|
tva: tva.replace(',', '.').trim() + "%"
|
|
};
|
|
}
|
|
}
|
|
|
|
} else {
|
|
supplier = "METRO";
|
|
|
|
// on regarde la date d'achat avec une expression reguliere pour metro
|
|
const regex_date = /(\d{2})-(\d{2})-(\d{4})/;
|
|
const corres = text.match(regex_date);
|
|
if (corres) {
|
|
date = corres[0];
|
|
} else {
|
|
date = "non trouvé";
|
|
}
|
|
|
|
// Découpage en lignes pour l'analyse et cration d'un tableau de toutes les lignes
|
|
const lines = text.split('\n').map(l => l.trim()).filter(l => l.length > 0);
|
|
|
|
// Algorithme de recherche verticale pour metro
|
|
for (let i = 0; i < lines.length; i++) {
|
|
// Si la ligne correspond exactement à un code-barres à 13 chiffres
|
|
if (/^\d{13}$/.test(lines[i])) {
|
|
const product_name = lines[i + 1];
|
|
const qte = lines[i + 4];
|
|
const price = lines[i + 5];
|
|
const tva = lines[i + 6];
|
|
|
|
let tva_final = "";
|
|
|
|
if (tva == "B"){
|
|
tva_final = "5.5%";
|
|
}
|
|
|
|
else {
|
|
tva_final = "20%";
|
|
}
|
|
|
|
|
|
product_list[product_name] = {
|
|
quantity: parseInt(qte, 10),
|
|
price_ht: parseFloat(price.replace(',', '.')),
|
|
tva: tva_final
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
// Construction de l'objet final
|
|
const result: res = {
|
|
brand: supplier,
|
|
purchase_date: date,
|
|
products: product_list
|
|
};
|
|
|
|
console.log(result);
|
|
return result;
|
|
|
|
|
|
} catch (e) {
|
|
console.error("Erreur :", e);
|
|
}
|
|
}
|
|
|
|
|
|
export default pdf_parse; |