fix(parcel-sync): paperCfNo bug, status filter, enrichment robustness

BUGS FIXED:
- paperCfNo does NOT exist in eTerra API — field is paperLbNo
  Renamed withPaperCf → withPaperLb everywhere (type, scan, UI)
- Area fields: only measuredArea and legalArea exist on immovable/list
  Removed phantom area/areaValue/suprafata checks from import filter

FILTERING TIGHTENED:
- Quality gate now requires status=1 (active) in eTerra
- Items with status≠1 are filtered out before import
- Quality breakdown adds: withActiveStatus, withLandbook counters
- Import attributes now store MEASURED_AREA, LEGAL_AREA, HAS_LANDBOOK
- workspace.nomenPk used instead of workspacePk for accuracy

ENRICHMENT ROBUSTNESS:
- Area fallback: when AREA_VALUE is missing (no-geom), enrichment
  now falls back to listItem.measuredArea/legalArea from immovable list
- Post-enrichment verification: logs 100% coverage or warns about gaps
- EnrichResult type extended with totalFeatures + unenrichedCount

UI UPDATES:
- Quality grid shows 6 stats: cadRef, CF/LB, paperCad, area, active, landbook
- Filter explanation updated: 'inactive sau fără date' instead of old text
This commit is contained in:
AI Assistant
2026-03-07 20:25:05 +02:00
parent af2631920f
commit f9594fff71
3 changed files with 132 additions and 65 deletions
@@ -20,6 +20,8 @@ const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
export type EnrichResult = {
siruta: string;
enrichedCount: number;
totalFeatures?: number;
unenrichedCount?: number;
buildingCrossRefs: number;
status: "done" | "error";
error?: string;
@@ -545,8 +547,21 @@ export async function enrichFeatures(
const buildLegal = build.has ? (build.legal ? 1 : 0) : 0;
if (hasBuilding) buildingCrossRefs += 1;
const areaValue =
// Area: prefer GIS AREA_VALUE, fall back to measuredArea/legalArea from
// immovable list (important for no-geometry features where AREA_VALUE
// may have been stored from measuredArea at import time, or may be null).
let areaValue =
typeof attrs.AREA_VALUE === "number" ? attrs.AREA_VALUE : null;
if (areaValue == null && listItem) {
areaValue =
(typeof listItem.measuredArea === "number" &&
listItem.measuredArea > 0
? listItem.measuredArea
: null) ??
(typeof listItem.legalArea === "number" && listItem.legalArea > 0
? listItem.legalArea
: null);
}
const enrichment: FeatureEnrichment = {
NR_CAD: cadRefRaw,
@@ -585,6 +600,19 @@ export async function enrichFeatures(
}
}
// ── Post-enrichment verification ──
// Check that ALL features now have enrichment (no gaps)
const unenriched = terenuri.length - enrichedCount;
if (unenriched > 0) {
console.warn(
`[enrich] ${unenriched}/${terenuri.length} features remain unenriched for siruta=${siruta}`,
);
} else {
console.log(
`[enrich] ✓ 100% enrichment: ${enrichedCount}/${terenuri.length} features for siruta=${siruta}`,
);
}
push({
phase: "Îmbogățire completă",
status: "done",
@@ -596,6 +624,8 @@ export async function enrichFeatures(
return {
siruta,
enrichedCount,
totalFeatures: terenuri.length,
unenrichedCount: unenriched,
buildingCrossRefs,
status: "done",
};