feat(parcel-sync): smart delta sync + fix HAS_BUILDING bug

- Fix: geoportal/enrich endpoint now looks up CLADIRI_ACTIVE from DB
  instead of hardcoding HAS_BUILDING=0, BUILD_LEGAL=0
- Quick-count check: skip OBJECTID comparison when remote==local count
- VALID_FROM delta: detect attribute changes on existing parcels and
  mark them for re-enrichment (catches spatial validity changes)
- Early bailout: skip all eTerra API calls when 0 features need enrichment
- Rolling doc check: probe 200 oldest-enriched parcels for new
  documentation activity (catches ownership/CF changes VALID_FROM misses)
- Targeted doc fetch: only fetch documentation for immovable PKs that
  actually need enrichment instead of all 10k+

Daily sync cost reduced from ~300+ API calls / 1-2h to ~6-10 calls / 10-15s.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
AI Assistant
2026-03-30 22:57:02 +03:00
parent 4d1883b459
commit 9e7abfafc8
3 changed files with 409 additions and 33 deletions
+30 -2
View File
@@ -75,6 +75,34 @@ export async function POST(req: Request) {
return NextResponse.json({ error: "Parcela negasita in registrul eTerra" }, { status: 404 });
}
// Building cross-ref: check CLADIRI_ACTIVE in local DB for this parcel
let hasBuilding = 0;
let buildLegal = 0;
const baseCad = cadRef.includes("-") ? cadRef.split("-")[0]! : cadRef;
if (baseCad) {
const cladiri = await prisma.gisFeature.findMany({
where: {
layerId: "CLADIRI_ACTIVE",
siruta: feature.siruta,
OR: [
{ cadastralRef: { startsWith: baseCad + "-" } },
{ cadastralRef: baseCad },
],
},
select: { attributes: true },
});
for (const c of cladiri) {
const attrs = c.attributes as Record<string, unknown>;
hasBuilding = 1;
if (
Number(attrs.IS_LEGAL ?? 0) === 1 ||
String(attrs.IS_LEGAL ?? "").toLowerCase() === "true"
) {
buildLegal = 1;
}
}
}
// Convert to enrichment format (same as enrichFeatures uses)
const enrichment = {
NR_CAD: match.nrCad || cadRef,
@@ -89,8 +117,8 @@ export async function POST(req: Request) {
SOLICITANT: match.solicitant || "",
INTRAVILAN: match.intravilan || "",
CATEGORIE_FOLOSINTA: match.categorieFolosinta || "",
HAS_BUILDING: 0,
BUILD_LEGAL: 0,
HAS_BUILDING: hasBuilding,
BUILD_LEGAL: buildLegal,
};
// Persist