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
@@ -391,6 +391,8 @@ export function ParcelSyncModule() {
withGeometry: number;
remoteGisCount: number;
noGeomCount: number;
matchedByRef: number;
matchedById: number;
qualityBreakdown: {
withCadRef: number;
withPaperCad: number;
@@ -407,6 +409,7 @@ export function ParcelSyncModule() {
localDbEnriched: number;
localDbEnrichedComplete: number;
localSyncFresh: boolean;
scannedAt: string;
} | null>(null);
const [noGeomScanSiruta, setNoGeomScanSiruta] = useState(""); // siruta for which scan was done
@@ -718,6 +721,8 @@ export function ParcelSyncModule() {
withGeometry: 0,
remoteGisCount: 0,
noGeomCount: 0,
matchedByRef: 0,
matchedById: 0,
qualityBreakdown: emptyQuality,
localDbTotal: 0,
localDbWithGeom: 0,
@@ -725,6 +730,7 @@ export function ParcelSyncModule() {
localDbEnriched: 0,
localDbEnrichedComplete: 0,
localSyncFresh: false,
scannedAt: "",
};
try {
const res = await fetch("/api/eterra/no-geom-scan", {
@@ -746,6 +752,8 @@ export function ParcelSyncModule() {
withGeometry: Number(data.withGeometry ?? 0),
remoteGisCount: Number(data.remoteGisCount ?? 0),
noGeomCount: Number(data.noGeomCount ?? 0),
matchedByRef: Number(data.matchedByRef ?? 0),
matchedById: Number(data.matchedById ?? 0),
qualityBreakdown: {
withCadRef: Number(qb.withCadRef ?? 0),
withPaperCad: Number(qb.withPaperCad ?? 0),
@@ -762,6 +770,7 @@ export function ParcelSyncModule() {
localDbEnriched: Number(data.localDbEnriched ?? 0),
localDbEnrichedComplete: Number(data.localDbEnrichedComplete ?? 0),
localSyncFresh: Boolean(data.localSyncFresh),
scannedAt: String(data.scannedAt ?? new Date().toISOString()),
});
}
} catch {
@@ -2601,7 +2610,7 @@ export function ParcelSyncModule() {
</span>{" "}
imobile în eTerra:{" "}
<span className="text-emerald-600 dark:text-emerald-400 font-medium">
{noGeomScan.remoteGisCount.toLocaleString("ro-RO")}
{noGeomScan.withGeometry.toLocaleString("ro-RO")}
</span>{" "}
cu geometrie,{" "}
<span className="font-semibold text-amber-600 dark:text-amber-400">
@@ -2609,15 +2618,25 @@ export function ParcelSyncModule() {
</span>{" "}
<span className="font-medium">fără geometrie</span>
</p>
{noGeomScan.withGeometry <
noGeomScan.remoteGisCount && (
<p className="text-[10px] text-muted-foreground/70 mt-0.5">
{noGeomScan.withGeometry.toLocaleString("ro-RO")}{" "}
din{" "}
{noGeomScan.remoteGisCount.toLocaleString("ro-RO")}{" "}
features GIS au corespondent în lista de imobile
</p>
)}
<p className="text-[10px] text-muted-foreground/70 mt-0.5">
Layer GIS:{" "}
<span className="font-medium">
{noGeomScan.remoteGisCount.toLocaleString("ro-RO")}
</span>
{" features (se descarcă toate)"}
{noGeomScan.remoteGisCount !== noGeomScan.withGeometry && (
<>
{" · "}
{noGeomScan.withGeometry.toLocaleString("ro-RO")} potrivite
cu lista de imobile
{noGeomScan.matchedByRef > 0 && noGeomScan.matchedById > 0 && (
<span className="text-muted-foreground/50">
{" "}({noGeomScan.matchedByRef} cadRef + {noGeomScan.matchedById} ID)
</span>
)}
</>
)}
</p>
<p className="text-[11px] text-muted-foreground mt-0.5">
Cele fără geometrie există în baza de date eTerra dar
nu au contur desenat în layerul GIS.