feat(address): collecteur BAN + intégration enrich/address + PDF
- Géocodage via api-adresse.data.gouv.fr (BAN) - Endpoint enrich/address: collecte réelle + génération PDF - Intégration UI existante (Collecter/Voir PDF/JSON)
This commit is contained in:
parent
8e3daad446
commit
0c9d01404f
61
backend/collectors/addressCollector.js
Normal file
61
backend/collectors/addressCollector.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/**
|
||||||
|
* Collecteur Adresses
|
||||||
|
* Géocodage via BAN (api-adresse.data.gouv.fr) et scaffold pour risques
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fetch = require('node-fetch')
|
||||||
|
|
||||||
|
const USER_AGENT = '4NK-IA-Front/1.0 (Document Analysis Tool)'
|
||||||
|
const REQUEST_TIMEOUT_MS = 12000
|
||||||
|
|
||||||
|
async function geocodeBAN(address) {
|
||||||
|
const q = [address.street, address.postalCode, address.city, address.country]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(' ')
|
||||||
|
const url = `https://api-adresse.data.gouv.fr/search/?q=${encodeURIComponent(q)}&limit=1`
|
||||||
|
const start = Date.now()
|
||||||
|
try {
|
||||||
|
const res = await fetch(url, {
|
||||||
|
headers: { 'User-Agent': USER_AGENT, 'Accept': 'application/json' },
|
||||||
|
timeout: REQUEST_TIMEOUT_MS,
|
||||||
|
})
|
||||||
|
if (!res.ok) throw new Error(`HTTP ${res.status}`)
|
||||||
|
const json = await res.json()
|
||||||
|
const f = json.features && json.features[0]
|
||||||
|
if (!f) {
|
||||||
|
return { success: true, duration: Date.now() - start, score: 0, lat: null, lon: null, label: null }
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
duration: Date.now() - start,
|
||||||
|
score: f.properties && typeof f.properties.score === 'number' ? f.properties.score : null,
|
||||||
|
lat: f.geometry?.coordinates ? f.geometry.coordinates[1] : null,
|
||||||
|
lon: f.geometry?.coordinates ? f.geometry.coordinates[0] : null,
|
||||||
|
label: f.properties?.label || null,
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return { success: false, duration: Date.now() - start, error: e.message }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function collectAddressData(address) {
|
||||||
|
// Étape 1: Géocodage BAN
|
||||||
|
const geocode = await geocodeBAN(address)
|
||||||
|
|
||||||
|
// Étape 2: Risques (placeholder, à compléter avec GéoRisque/GéoFoncier)
|
||||||
|
const risks = []
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: geocode.success,
|
||||||
|
geocode,
|
||||||
|
risks,
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
sources: ['ban']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
collectAddressData,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -20,6 +20,7 @@ const pdf = require('pdf-parse')
|
|||||||
const { searchBodaccGelAvoirs, generateBodaccSummary } = require('./collectors/bodaccCollector')
|
const { searchBodaccGelAvoirs, generateBodaccSummary } = require('./collectors/bodaccCollector')
|
||||||
const { searchCompanyInfo, generateCompanySummary } = require('./collectors/inforgreffeCollector')
|
const { searchCompanyInfo, generateCompanySummary } = require('./collectors/inforgreffeCollector')
|
||||||
const { generatePersonPdf, generateCompanyPdf, generateAddressPdf } = require('./collectors/pdfGenerator')
|
const { generatePersonPdf, generateCompanyPdf, generateAddressPdf } = require('./collectors/pdfGenerator')
|
||||||
|
const { collectAddressData } = require('./collectors/addressCollector')
|
||||||
|
|
||||||
const app = express()
|
const app = express()
|
||||||
const PORT = process.env.PORT || 3001
|
const PORT = process.env.PORT || 3001
|
||||||
@ -2617,16 +2618,16 @@ app.post('/api/folders/:folderHash/files/:fileHash/enrich/:kind', async (req, re
|
|||||||
if (fs.existsSync(cacheFile)) {
|
if (fs.existsSync(cacheFile)) {
|
||||||
const cacheData = JSON.parse(fs.readFileSync(cacheFile, 'utf8'))
|
const cacheData = JSON.parse(fs.readFileSync(cacheFile, 'utf8'))
|
||||||
const persons = cacheData.entities?.persons || []
|
const persons = cacheData.entities?.persons || []
|
||||||
|
|
||||||
for (const person of persons) {
|
for (const person of persons) {
|
||||||
if (person.lastName) {
|
if (person.lastName) {
|
||||||
console.log(`[Enrich] Recherche Bodacc pour: ${person.firstName} ${person.lastName}`)
|
console.log(`[Enrich] Recherche Bodacc pour: ${person.firstName} ${person.lastName}`)
|
||||||
result = await searchBodaccGelAvoirs(person.lastName, person.firstName)
|
result = await searchBodaccGelAvoirs(person.lastName, person.firstName)
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
const summary = generateBodaccSummary(result.results, person.lastName, person.firstName)
|
const summary = generateBodaccSummary(result.results, person.lastName, person.firstName)
|
||||||
result.summary = summary
|
result.summary = summary
|
||||||
|
|
||||||
// Génération du PDF
|
// Génération du PDF
|
||||||
try {
|
try {
|
||||||
await generatePersonPdf(person, result, pdfPath)
|
await generatePersonPdf(person, result, pdfPath)
|
||||||
@ -2645,12 +2646,12 @@ app.post('/api/folders/:folderHash/files/:fileHash/enrich/:kind', async (req, re
|
|||||||
if (fs.existsSync(cacheFile)) {
|
if (fs.existsSync(cacheFile)) {
|
||||||
const cacheData = JSON.parse(fs.readFileSync(cacheFile, 'utf8'))
|
const cacheData = JSON.parse(fs.readFileSync(cacheFile, 'utf8'))
|
||||||
const companies = cacheData.entities?.companies || []
|
const companies = cacheData.entities?.companies || []
|
||||||
|
|
||||||
for (const company of companies) {
|
for (const company of companies) {
|
||||||
if (company.name) {
|
if (company.name) {
|
||||||
console.log(`[Enrich] Recherche Inforgreffe pour: ${company.name}`)
|
console.log(`[Enrich] Recherche Inforgreffe pour: ${company.name}`)
|
||||||
result = await searchCompanyInfo(company.name, company.siren)
|
result = await searchCompanyInfo(company.name, company.siren)
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
// Génération du PDF
|
// Génération du PDF
|
||||||
try {
|
try {
|
||||||
@ -2665,17 +2666,25 @@ app.post('/api/folders/:folderHash/files/:fileHash/enrich/:kind', async (req, re
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (kind === 'address') {
|
} else if (kind === 'address') {
|
||||||
// Placeholder pour les adresses (géocodage à implémenter)
|
// Géocodage réel via BAN
|
||||||
result = {
|
const cacheFile = path.join(cachePath, `${fileHash}.json`)
|
||||||
success: true,
|
let addressData = { street: '', city: '', postalCode: '', country: 'France' }
|
||||||
duration: 1000,
|
if (fs.existsSync(cacheFile)) {
|
||||||
message: 'Enrichissement adresse en cours de développement',
|
const cacheData = JSON.parse(fs.readFileSync(cacheFile, 'utf8'))
|
||||||
data: { placeholder: true }
|
const addresses = cacheData.entities?.addresses || []
|
||||||
|
if (addresses.length > 0) {
|
||||||
|
addressData = {
|
||||||
|
street: addresses[0].street || '',
|
||||||
|
city: addresses[0].city || '',
|
||||||
|
postalCode: addresses[0].postalCode || '',
|
||||||
|
country: addresses[0].country || 'France',
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
result = await collectAddressData(addressData)
|
||||||
// Génération du PDF placeholder
|
|
||||||
|
// Génération du PDF avec données géocodées
|
||||||
try {
|
try {
|
||||||
const addressData = { street: 'Adresse', city: 'Ville' }
|
|
||||||
await generateAddressPdf(addressData, result, pdfPath)
|
await generateAddressPdf(addressData, result, pdfPath)
|
||||||
pdfGenerated = true
|
pdfGenerated = true
|
||||||
} catch (pdfError) {
|
} catch (pdfError) {
|
||||||
@ -2690,7 +2699,7 @@ app.post('/api/folders/:folderHash/files/:fileHash/enrich/:kind', async (req, re
|
|||||||
startedAt: status.startedAt,
|
startedAt: status.startedAt,
|
||||||
finishedAt: new Date().toISOString(),
|
finishedAt: new Date().toISOString(),
|
||||||
message: result?.success ? 'Collecte terminée' : 'Erreur de collecte',
|
message: result?.success ? 'Collecte terminée' : 'Erreur de collecte',
|
||||||
sources: result?.sources ? Object.keys(result.sources) :
|
sources: result?.sources ? Object.keys(result.sources) :
|
||||||
(kind === 'person') ? ['bodacc_gel_avoirs'] :
|
(kind === 'person') ? ['bodacc_gel_avoirs'] :
|
||||||
(kind === 'company') ? ['kbis_inforgreffe', 'societe_com'] :
|
(kind === 'company') ? ['kbis_inforgreffe', 'societe_com'] :
|
||||||
['cadastre', 'georisque', 'geofoncier'],
|
['cadastre', 'georisque', 'geofoncier'],
|
||||||
@ -2698,12 +2707,12 @@ app.post('/api/folders/:folderHash/files/:fileHash/enrich/:kind', async (req, re
|
|||||||
pdfGenerated
|
pdfGenerated
|
||||||
}
|
}
|
||||||
fs.writeFileSync(statusPath, JSON.stringify(done, null, 2))
|
fs.writeFileSync(statusPath, JSON.stringify(done, null, 2))
|
||||||
|
|
||||||
console.log(`[Enrich] Terminé pour ${kind}:`, done.state)
|
console.log(`[Enrich] Terminé pour ${kind}:`, done.state)
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`[Enrich] Erreur enrichissement ${kind}:`, error.message)
|
console.error(`[Enrich] Erreur enrichissement ${kind}:`, error.message)
|
||||||
|
|
||||||
const errorStatus = {
|
const errorStatus = {
|
||||||
kind,
|
kind,
|
||||||
state: 'error',
|
state: 'error',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user