fix: scan numbers always add up, match quality tracking, pipeline audit

SCAN DISPLAY:
- Use matchedCount (withGeometry) for 'cu geometrie' — ALWAYS adds up
  with noGeomCount to equal totalImmovables (ground truth arithmetic)
- Show remoteGisCount separately as 'Layer GIS: N features (se descarca toate)'
- When remoteGisCount != matchedCount, show matching detail with breakdown
  (X potrivite + cadRef/ID split) so mismatches are transparent
- Workflow preview step 1 still uses remoteGisCount (correct: all GIS
  features get downloaded regardless of matching)

MATCH QUALITY TRACKING:
- New fields: matchedByRef, matchedById in NoGeomScanResult
- Track how many immovables matched by cadastral ref vs by IMMOVABLE_ID
- Console log match quality for server-side debugging
- scannedAt timestamp for audit trail

PIPELINE AUDIT (export report):
- New 'pipeline' section in export_report.json with full trace:
  syncedGis, noGeometry (imported/cleaned/skipped), enriched, finalDb
- raport_calitate.txt now has PIPELINE section before quality analysis
  showing exactly what happened at each step
- Capture noGeomCleaned + noGeomSkipped in addition to noGeomImported
This commit is contained in:
AI Assistant
2026-03-07 21:22:29 +02:00
parent 1e6888a32a
commit 531c3b0858
3 changed files with 96 additions and 13 deletions
+39 -1
View File
@@ -256,6 +256,8 @@ export async function POST(req: Request) {
/* Phase 1b: Import no-geometry parcels (optional) */
/* ══════════════════════════════════════════════════════════ */
let noGeomImported = 0;
let noGeomCleaned = 0;
let noGeomSkipped = 0;
if (hasNoGeom && weights.noGeom > 0) {
setPhaseState("Import parcele fără geometrie", weights.noGeom, 1);
const noGeomClient = await EterraClient.create(
@@ -282,6 +284,8 @@ export async function POST(req: Request) {
pushProgress();
} else {
noGeomImported = noGeomResult.imported;
noGeomCleaned = noGeomResult.cleaned;
noGeomSkipped = noGeomResult.skipped;
const cleanedNote =
noGeomResult.cleaned > 0
? `, ${noGeomResult.cleaned} vechi șterse`
@@ -626,6 +630,26 @@ export async function POST(req: Request) {
siruta: validated.siruta,
generatedAt: new Date().toISOString(),
source: "local-db (sync-first)",
pipeline: {
syncedGis: {
terenuri: terenuriNeedsSync ? "descărcat" : "din cache",
cladiri: cladiriNeedsSync ? "descărcat" : "din cache",
},
noGeometry: hasNoGeom
? {
imported: noGeomImported,
cleaned: noGeomCleaned,
skipped: noGeomSkipped,
}
: "dezactivat",
enriched: validated.mode === "magic" ? "da" : "nu",
finalDb: {
total: dbTerenuri.length,
withGeometry: withGeomRecords.length,
noGeometry: noGeomRecords.length,
cladiri: cladiriGeoFeatures.length,
},
},
terenuri: {
count: terenuriGeoFeatures.length,
totalInDb: dbTerenuri.length,
@@ -665,7 +689,21 @@ export async function POST(req: Request) {
` Generat: ${new Date().toISOString().replace("T", " ").slice(0, 19)}`,
`══════════════════════════════════════════════════════════`,
``,
`REZUMAT GENERAL`,
`PIPELINE — CE S-A ÎNTÂMPLAT`,
`─────────────────────────────────────────────────────────`,
` 1. Sync GIS terenuri: ${terenuriNeedsSync ? "descărcat din eTerra" : "din cache local (date proaspete)"}`,
` 2. Sync GIS clădiri: ${cladiriNeedsSync ? "descărcat din eTerra" : "din cache local (date proaspete)"}`,
...(hasNoGeom
? [
` 3. Import fără geometrie: ${fmt(noGeomImported)} noi importate` +
(noGeomCleaned > 0 ? `, ${fmt(noGeomCleaned)} vechi șterse` : "") +
(noGeomSkipped > 0 ? `, ${fmt(noGeomSkipped)} filtrate/skip` : ""),
]
: [` 3. Import fără geometrie: dezactivat`]),
` 4. Îmbogățire (CF, prop.): da`,
` 5. Generare fișiere: GPKG + CSV + raport`,
``,
`STARE FINALĂ BAZĂ DE DATE`,
`─────────────────────────────────────────────────────────`,
` Total parcele în baza de date: ${fmt(dbTerenuri.length)}`,
` • Cu geometrie (contur GIS): ${fmt(withGeomRecords.length)}`,