From 4aa8e6c32404911fd736177199c414b620254ff3 Mon Sep 17 00:00:00 2001 From: AI Assistant Date: Fri, 6 Mar 2026 22:16:14 +0200 Subject: [PATCH] fix(search): use legalArea/measuredArea + nodeStatus=-1 for radiated owners - Area: use measuredArea/legalArea from immovable list and documentation (actual fields from eTerra API, not area/areaValue which don't exist) - Owners: detect radiated via nodeStatus === -1 on ancestor I (inscription) nodes. Walk up parentId tree from P (person) I A C. nodeStatus: -1=radiated, 0=active, 2=pending - Remove debug logging (data structure now understood) --- src/app/api/eterra/search/route.ts | 105 +++++++++++++---------------- 1 file changed, 46 insertions(+), 59 deletions(-) diff --git a/src/app/api/eterra/search/route.ts b/src/app/api/eterra/search/route.ts index 0fcebda..7cd2730 100644 --- a/src/app/api/eterra/search/route.ts +++ b/src/app/api/eterra/search/route.ts @@ -111,19 +111,19 @@ function formatAddress(item?: any) { const streetName = typeof address.street === "string" ? address.street - : address.street?.name ?? ""; + : (address.street?.name ?? ""); if (streetName) parts.push(`Str. ${streetName}`); if (address.buildingNo) parts.push(`Nr. ${address.buildingNo}`); // locality can also be a string or object const localityName = typeof address.locality === "string" ? address.locality - : address.locality?.name ?? ""; + : (address.locality?.name ?? ""); if (localityName) parts.push(localityName); const countyName = typeof address.county === "string" ? address.county - : address.county?.name ?? ""; + : (address.county?.name ?? ""); if (countyName) parts.push(`Jud. ${countyName}`); return parts.length ? parts.join(", ") : ""; } @@ -310,24 +310,20 @@ export async function POST(req: Request) { let categorie = ""; let suprafata: number | null = null; - // Try multiple area fields - const areaStr = - item?.area ?? item?.areaValue ?? item?.areaMP ?? item?.suprafata; - if (areaStr != null) { - const parsed = Number(areaStr); - if (Number.isFinite(parsed) && parsed > 0) suprafata = parsed; - } - // Log raw item keys once for debugging (first item only) - if (results.length === 0) { - console.log( - "[search] immovable item keys:", - Object.keys(item ?? {}), - ); - console.log("[search] area fields:", { - area: item?.area, - areaValue: item?.areaValue, - areaMP: item?.areaMP, - }); + // Area: use measuredArea first, then legalArea as fallback + for (const areaField of [ + item?.measuredArea, + item?.legalArea, + item?.area, + item?.areaValue, + ]) { + if (areaField != null) { + const parsed = Number(areaField); + if (Number.isFinite(parsed) && parsed > 0) { + suprafata = parsed; + break; + } + } } // 2. Fetch documentation data (CF, proprietari) @@ -350,60 +346,50 @@ export async function POST(req: Request) { if (oldCF && oldCF !== nrCF) nrCFVechi = oldCF; } if (docImm.topNo) nrTopo = String(docImm.topNo); - if (docImm.area != null) { - const docArea = Number(docImm.area); - if (Number.isFinite(docArea)) suprafata = docArea; + // Try measuredArea/legalArea from doc too + for (const af of [ + docImm.measuredArea, + docImm.legalArea, + docImm.area, + ]) { + if (af != null) { + const docArea = Number(af); + if (Number.isFinite(docArea) && docArea > 0) { + suprafata = docArea; + break; + } + } } } // Extract owners from partTwoRegs — separate active vs cancelled - // using tree structure: "P" (person) nodes are children of - // inscription nodes. If a parent inscription has radiationDate, - // its person entries are former owners. + // Tree: C (cerere) → A (act) → I (inscription) → P (person) + // nodeStatus === -1 on an "I" node means it's radiated. + // Walk up from each "P" to its parent "I", check nodeStatus. const activeOwners: string[] = []; const cancelledOwners: string[] = []; // eslint-disable-next-line @typescript-eslint/no-explicit-any const regs: any[] = docResponse?.partTwoRegs ?? []; - if (regs.length > 0 && results.length === 0) { - console.log( - "[search] partTwoRegs count:", - regs.length, - "types:", - [...new Set(regs.map((r: any) => r?.nodeType))], - ); - // Log first 3 entries fully - regs.slice(0, 3).forEach((r: any, i: number) => - console.log(`[search] partTwoRegs[${i}]:`, JSON.stringify(r).slice(0, 600)), - ); - // Log last 3 entries - regs.slice(-3).forEach((r: any, i: number) => - console.log(`[search] partTwoRegs[${regs.length - 3 + i}]:`, JSON.stringify(r).slice(0, 600)), - ); - } // Build nodeId → entry map for tree traversal // eslint-disable-next-line @typescript-eslint/no-explicit-any - const nodeMap = new Map(); + const nodeMap = new Map(); for (const reg of regs) { - const nid = reg?.nodeId ?? reg?.id; - if (nid != null) nodeMap.set(nid, reg); + if (reg?.nodeId != null) nodeMap.set(Number(reg.nodeId), reg); } - // Check if an entry or any ancestor is radiated + // Check if an entry or any ancestor "I" inscription is radiated + // nodeStatus: -1 = radiated, 0 = active, 2 = pending // eslint-disable-next-line @typescript-eslint/no-explicit-any - const isRadiated = (entry: any): boolean => { - // Direct checks on the entry itself - if (entry?.radiationDate != null) return true; - if (entry?.cancelled === true) return true; - if (entry?.isActive === false) return true; - if (entry?.closed === true) return true; - const st = String(entry?.status ?? "").toUpperCase(); - if (st === "RADIAT" || st === "CANCELLED" || st === "CLOSED") return true; + const isRadiated = (entry: any, depth = 0): boolean => { + if (!entry || depth > 10) return false; + // nodeStatus === -1 means radiated/cancelled + if (entry?.nodeStatus === -1) return true; // Walk up to parent - const pid = entry?.parentNodeId ?? entry?.parentId; + const pid = entry?.parentId; if (pid != null) { - const parent = nodeMap.get(pid); - if (parent) return isRadiated(parent); + const parent = nodeMap.get(Number(pid)); + if (parent) return isRadiated(parent, depth + 1); } return false; }; @@ -412,7 +398,8 @@ export async function POST(req: Request) { if ( String(reg?.nodeType ?? "").toUpperCase() !== "P" || !reg?.nodeName - ) continue; + ) + continue; const name = String(reg.nodeName).trim(); if (!name) continue; if (isRadiated(reg)) {