4e67c29267
Shows all available eTerra fields for a parcel + buildings: - GIS layer attributes (raw from ArcGIS) - Immovable parcel details (intravilan, categories) - Immovable list entry (address, areas) - Documentation data (owners, registrations) - Local DB state (enrichment, sync dates) Usage: /api/eterra/debug-fields?siruta=161829&cadRef=77102 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
188 lines
6.1 KiB
TypeScript
188 lines
6.1 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { EterraClient } from "@/modules/parcel-sync/services/eterra-client";
|
|
import { PrismaClient } from "@prisma/client";
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
/**
|
|
* GET /api/eterra/debug-fields?siruta=161829&cadRef=77102
|
|
*
|
|
* Diagnostic endpoint — shows all available fields from eTerra + local DB
|
|
* for a specific parcel and its buildings.
|
|
*/
|
|
export async function GET(request: Request) {
|
|
const url = new URL(request.url);
|
|
const siruta = url.searchParams.get("siruta") ?? "161829";
|
|
const cadRef = url.searchParams.get("cadRef") ?? "77102";
|
|
|
|
const username = process.env.ETERRA_USERNAME;
|
|
const password = process.env.ETERRA_PASSWORD;
|
|
if (!username || !password) {
|
|
return NextResponse.json({ error: "ETERRA creds missing" }, { status: 500 });
|
|
}
|
|
|
|
const result: Record<string, unknown> = {
|
|
query: { siruta, cadRef },
|
|
timestamp: new Date().toISOString(),
|
|
};
|
|
|
|
try {
|
|
const client = await EterraClient.create(username, password);
|
|
|
|
// 1. GIS layer: TERENURI_ACTIVE — raw attributes
|
|
const terenuri = await client.listLayerByWhere(
|
|
{ id: "TERENURI_ACTIVE", name: "TERENURI_ACTIVE", endpoint: "aut" },
|
|
`ADMIN_UNIT_ID=${siruta} AND IS_ACTIVE=1 AND NATIONAL_CADASTRAL_REFERENCE='${cadRef}'`,
|
|
{ limit: 1, outFields: "*" },
|
|
);
|
|
const parcelAttrs = terenuri[0]?.attributes ?? null;
|
|
result.gis_parcela = {
|
|
found: !!parcelAttrs,
|
|
fields: parcelAttrs
|
|
? Object.entries(parcelAttrs)
|
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
.map(([k, v]) => ({ field: k, value: v, type: typeof v }))
|
|
: [],
|
|
};
|
|
|
|
// 2. GIS layer: CLADIRI_ACTIVE — buildings on this parcel
|
|
const cladiri = await client.listLayerByWhere(
|
|
{ id: "CLADIRI_ACTIVE", name: "CLADIRI_ACTIVE", endpoint: "aut" },
|
|
`ADMIN_UNIT_ID=${siruta} AND IS_ACTIVE=1 AND NATIONAL_CADASTRAL_REFERENCE LIKE '${cadRef}-%'`,
|
|
{ limit: 20, outFields: "*" },
|
|
);
|
|
result.gis_cladiri = {
|
|
count: cladiri.length,
|
|
buildings: cladiri.map((c) => {
|
|
const a = c.attributes;
|
|
return {
|
|
cadastralRef: a.NATIONAL_CADASTRAL_REFERENCE,
|
|
fields: Object.entries(a)
|
|
.sort(([x], [y]) => x.localeCompare(y))
|
|
.filter(([, v]) => v != null && v !== "" && v !== 0)
|
|
.map(([k, v]) => ({ field: k, value: v, type: typeof v })),
|
|
};
|
|
}),
|
|
};
|
|
|
|
// 3. Immovable details (enrichment source)
|
|
const immId = parcelAttrs?.IMMOVABLE_ID;
|
|
const wsId = parcelAttrs?.WORKSPACE_ID;
|
|
if (immId && wsId) {
|
|
try {
|
|
const details = await client.fetchImmovableParcelDetails(
|
|
wsId as string | number,
|
|
immId as string | number,
|
|
);
|
|
result.immovable_parcel_details = {
|
|
count: details.length,
|
|
items: details,
|
|
};
|
|
} catch (e) {
|
|
result.immovable_parcel_details = {
|
|
error: e instanceof Error ? e.message : String(e),
|
|
};
|
|
}
|
|
|
|
// 4. Immovable list entry (address source)
|
|
try {
|
|
const listResponse = await client.fetchImmovableListByAdminUnit(
|
|
wsId as number,
|
|
siruta,
|
|
0,
|
|
5,
|
|
true,
|
|
);
|
|
const items = (listResponse?.content ?? []) as Record<string, unknown>[];
|
|
// Find our specific immovable
|
|
const match = items.find(
|
|
(item) => String(item.immovablePk) === String(immId) ||
|
|
String(item.identifierDetails ?? "").includes(cadRef),
|
|
);
|
|
result.immovable_list_entry = {
|
|
totalInUat: listResponse?.totalElements ?? "?",
|
|
matchFound: !!match,
|
|
entry: match ?? null,
|
|
note: "Acest obiect contine campul immovableAddresses cu adresa completa",
|
|
};
|
|
} catch (e) {
|
|
result.immovable_list_entry = {
|
|
error: e instanceof Error ? e.message : String(e),
|
|
};
|
|
}
|
|
|
|
// 5. Documentation data (owner source)
|
|
try {
|
|
const docResponse = await client.fetchDocumentationData(
|
|
wsId as number,
|
|
[String(immId)],
|
|
);
|
|
const immovables = docResponse?.immovables ?? [];
|
|
const regs = docResponse?.partTwoRegs ?? [];
|
|
result.documentation_data = {
|
|
immovablesCount: immovables.length,
|
|
immovables: immovables.slice(0, 3),
|
|
registrationsCount: regs.length,
|
|
registrations: regs.slice(0, 10),
|
|
note: "partTwoRegs contine proprietarii (nodeType=P, nodeStatus=-1=radiat)",
|
|
};
|
|
} catch (e) {
|
|
result.documentation_data = {
|
|
error: e instanceof Error ? e.message : String(e),
|
|
};
|
|
}
|
|
}
|
|
|
|
// 6. Local DB data (what we have stored)
|
|
const dbParcel = await prisma.gisFeature.findFirst({
|
|
where: { layerId: "TERENURI_ACTIVE", siruta, cadastralRef: cadRef },
|
|
select: {
|
|
objectId: true,
|
|
cadastralRef: true,
|
|
areaValue: true,
|
|
isActive: true,
|
|
enrichment: true,
|
|
enrichedAt: true,
|
|
geometrySource: true,
|
|
},
|
|
});
|
|
const dbBuildings = await prisma.gisFeature.findMany({
|
|
where: {
|
|
layerId: "CLADIRI_ACTIVE",
|
|
siruta,
|
|
cadastralRef: { startsWith: `${cadRef}-` },
|
|
},
|
|
select: {
|
|
objectId: true,
|
|
cadastralRef: true,
|
|
areaValue: true,
|
|
attributes: true,
|
|
},
|
|
});
|
|
result.local_db = {
|
|
parcel: dbParcel
|
|
? {
|
|
objectId: dbParcel.objectId,
|
|
cadastralRef: dbParcel.cadastralRef,
|
|
areaValue: dbParcel.areaValue,
|
|
enrichedAt: dbParcel.enrichedAt,
|
|
geometrySource: dbParcel.geometrySource,
|
|
enrichment: dbParcel.enrichment,
|
|
}
|
|
: null,
|
|
buildings: dbBuildings.map((b) => ({
|
|
objectId: b.objectId,
|
|
cadastralRef: b.cadastralRef,
|
|
areaValue: b.areaValue,
|
|
is_legal: (b.attributes as Record<string, unknown>)?.IS_LEGAL,
|
|
})),
|
|
};
|
|
} catch (e) {
|
|
result.error = e instanceof Error ? e.message : String(e);
|
|
}
|
|
|
|
return NextResponse.json(result, {
|
|
headers: { "Content-Type": "application/json; charset=utf-8" },
|
|
});
|
|
}
|