feat: quality analysis for no-geom parcels + raport_calitate.txt

Scan phase:
- qualityBreakdown on NoGeomScanResult: withCadRef, withPaperCad,
  withPaperCf, withArea, useful vs empty counts
- UI scan card shows quality grid before deciding to export

Export phase:
- Comprehensive enrichment quality analysis: owners, CF, address,
  area, category, building — split by with-geom vs no-geom
- raport_calitate.txt in ZIP: human-readable Romanian report with
  per-category breakdowns and percentage stats
- export_report.json includes full qualityAnalysis object
- Progress completion note shows quality summary inline
This commit is contained in:
AI Assistant
2026-03-07 19:23:57 +02:00
parent 53914c7fc3
commit 681b52e816
3 changed files with 334 additions and 11 deletions
@@ -391,6 +391,14 @@ export function ParcelSyncModule() {
withGeometry: number;
remoteGisCount: number;
noGeomCount: number;
qualityBreakdown: {
withCadRef: number;
withPaperCad: number;
withPaperCf: number;
withArea: number;
useful: number;
empty: number;
};
localDbTotal: number;
localDbWithGeom: number;
localDbNoGeom: number;
@@ -693,11 +701,20 @@ export function ParcelSyncModule() {
setNoGeomScanning(true);
setNoGeomScan(null);
setNoGeomScanSiruta(s);
const emptyQuality = {
withCadRef: 0,
withPaperCad: 0,
withPaperCf: 0,
withArea: 0,
useful: 0,
empty: 0,
};
const emptyResult = {
totalImmovables: 0,
withGeometry: 0,
remoteGisCount: 0,
noGeomCount: 0,
qualityBreakdown: emptyQuality,
localDbTotal: 0,
localDbWithGeom: 0,
localDbNoGeom: 0,
@@ -719,11 +736,20 @@ export function ParcelSyncModule() {
console.warn("[no-geom-scan]", data.error);
setNoGeomScan(emptyResult);
} else {
const qb = (data.qualityBreakdown ?? {}) as Record<string, unknown>;
setNoGeomScan({
totalImmovables: Number(data.totalImmovables ?? 0),
withGeometry: Number(data.withGeometry ?? 0),
remoteGisCount: Number(data.remoteGisCount ?? 0),
noGeomCount: Number(data.noGeomCount ?? 0),
qualityBreakdown: {
withCadRef: Number(qb.withCadRef ?? 0),
withPaperCad: Number(qb.withPaperCad ?? 0),
withPaperCf: Number(qb.withPaperCf ?? 0),
withArea: Number(qb.withArea ?? 0),
useful: Number(qb.useful ?? 0),
empty: Number(qb.empty ?? 0),
},
localDbTotal: Number(data.localDbTotal ?? 0),
localDbWithGeom: Number(data.localDbWithGeom ?? 0),
localDbNoGeom: Number(data.localDbNoGeom ?? 0),
@@ -2612,6 +2638,70 @@ export function ParcelSyncModule() {
Include și parcelele fără geometrie la export
</span>
</label>
{/* Quality breakdown of no-geom items */}
{scanDone && noGeomScan.noGeomCount > 0 && (
<div className="ml-7 p-2 rounded-md bg-muted/40 space-y-1">
<p className="text-[11px] font-medium text-muted-foreground">
Calitate date (din{" "}
{noGeomScan.noGeomCount.toLocaleString("ro-RO")} fără
geometrie):
</p>
<div className="grid grid-cols-2 gap-x-4 gap-y-0.5 text-[11px] text-muted-foreground">
<span>
Cu nr. cadastral eTerra:{" "}
<span className="font-medium text-foreground">
{noGeomScan.qualityBreakdown.withCadRef.toLocaleString(
"ro-RO",
)}
</span>
</span>
<span>
Cu nr. CF pe hârtie:{" "}
<span className="font-medium text-foreground">
{noGeomScan.qualityBreakdown.withPaperCf.toLocaleString(
"ro-RO",
)}
</span>
</span>
<span>
Cu nr. cad. pe hârtie:{" "}
<span className="font-medium text-foreground">
{noGeomScan.qualityBreakdown.withPaperCad.toLocaleString(
"ro-RO",
)}
</span>
</span>
<span>
Cu suprafață:{" "}
<span className="font-medium text-foreground">
{noGeomScan.qualityBreakdown.withArea.toLocaleString(
"ro-RO",
)}
</span>
</span>
</div>
<div className="flex items-center gap-3 text-[11px] pt-0.5 border-t border-muted-foreground/10">
<span>
Utilizabile:{" "}
<span className="font-semibold text-emerald-600 dark:text-emerald-400">
{noGeomScan.qualityBreakdown.useful.toLocaleString(
"ro-RO",
)}
</span>
</span>
{noGeomScan.qualityBreakdown.empty > 0 && (
<span>
Fără date identificare:{" "}
<span className="font-semibold text-rose-600 dark:text-rose-400">
{noGeomScan.qualityBreakdown.empty.toLocaleString(
"ro-RO",
)}
</span>
</span>
)}
</div>
</div>
)}
{includeNoGeom && (
<p className="text-[11px] text-muted-foreground ml-7">
Vor fi importate în DB și incluse în CSV + Magic GPKG