feat(search): separate active/old owners, improve address format, debug area fields

- Proprietari split into proprietariActuali + proprietariVechi (radiati)
  based on cancelled/isActive/radiat/status/radiationDate fields
- UI shows owners separated: actuali bold, vechi strikethrough
- CSV export has separate PROPRIETARI_ACTUALI / PROPRIETARI_VECHI columns
- Address: use addressDescription directly when present (>3 chars)
- Add county to address fallback
- Try area/areaValue/areaMP/suprafata fields for surface
- Debug logging: log immovable item keys + partTwoRegs sample on first search
This commit is contained in:
AI Assistant
2026-03-06 21:53:18 +02:00
parent 6b8feb9075
commit 6eae4fa1c5
2 changed files with 105 additions and 21 deletions
+64 -12
View File
@@ -57,7 +57,12 @@ async function resolveWorkspace(
); );
const wsId = features?.[0]?.attributes?.WORKSPACE_ID; const wsId = features?.[0]?.attributes?.WORKSPACE_ID;
console.log("[resolveWorkspace] ArcGIS WORKSPACE_ID for", siruta, "→", wsId); console.log(
"[resolveWorkspace] ArcGIS WORKSPACE_ID for",
siruta,
"→",
wsId,
);
if (wsId != null) { if (wsId != null) {
const numWs = Number(wsId); const numWs = Number(wsId);
if (Number.isFinite(numWs)) { if (Number.isFinite(numWs)) {
@@ -68,7 +73,10 @@ async function resolveWorkspace(
} }
} }
} catch (e) { } catch (e) {
console.log("[resolveWorkspace] ArcGIS query failed:", e instanceof Error ? e.message : e); console.log(
"[resolveWorkspace] ArcGIS query failed:",
e instanceof Error ? e.message : e,
);
} }
return null; return null;
@@ -94,10 +102,16 @@ function formatAddress(item?: any) {
const address = item?.immovableAddresses?.[0]?.address ?? null; const address = item?.immovableAddresses?.[0]?.address ?? null;
if (!address) return ""; if (!address) return "";
const parts: string[] = []; const parts: string[] = [];
if (address.addressDescription) parts.push(address.addressDescription); // addressDescription may contain the full text address already
if (address.addressDescription) {
const desc = String(address.addressDescription).trim();
// If it looks like a complete address (has comma or street), use it directly
if (desc.length > 3) return desc;
}
if (address.street) parts.push(`Str. ${address.street}`); if (address.street) parts.push(`Str. ${address.street}`);
if (address.buildingNo) parts.push(`Nr. ${address.buildingNo}`); if (address.buildingNo) parts.push(`Nr. ${address.buildingNo}`);
if (address.locality?.name) parts.push(address.locality.name); if (address.locality?.name) parts.push(address.locality.name);
if (address.county?.name) parts.push(`Jud. ${address.county.name}`);
return parts.length ? parts.join(", ") : ""; return parts.length ? parts.join(", ") : "";
} }
@@ -144,6 +158,8 @@ export type ParcelDetail = {
categorieFolosinta: string; categorieFolosinta: string;
adresa: string; adresa: string;
proprietari: string; proprietari: string;
proprietariActuali: string;
proprietariVechi: string;
suprafata: number | null; suprafata: number | null;
solicitant: string; solicitant: string;
immovablePk: string; immovablePk: string;
@@ -256,6 +272,8 @@ export async function POST(req: Request) {
categorieFolosinta: "", categorieFolosinta: "",
adresa: "", adresa: "",
proprietari: "", proprietari: "",
proprietariActuali: "",
proprietariVechi: "",
suprafata: null, suprafata: null,
solicitant: "", solicitant: "",
immovablePk: "", immovablePk: "",
@@ -272,16 +290,23 @@ export async function POST(req: Request) {
let nrCFVechi = ""; let nrCFVechi = "";
let nrTopo = String(item?.topNo ?? item?.paperCadNo ?? ""); let nrTopo = String(item?.topNo ?? item?.paperCadNo ?? "");
let addressText = formatAddress(item); let addressText = formatAddress(item);
let proprietari = ""; let proprietariActuali: string[] = [];
let proprietariVechi: string[] = [];
let solicitant = ""; let solicitant = "";
let intravilan = ""; let intravilan = "";
let categorie = ""; let categorie = "";
let suprafata: number | null = null; let suprafata: number | null = null;
const areaStr = item?.area ?? item?.areaValue; // Try multiple area fields
const areaStr = item?.area ?? item?.areaValue ?? item?.areaMP ?? item?.suprafata;
if (areaStr != null) { if (areaStr != null) {
const parsed = Number(areaStr); const parsed = Number(areaStr);
if (Number.isFinite(parsed)) suprafata = parsed; 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 });
} }
// 2. Fetch documentation data (CF, proprietari) // 2. Fetch documentation data (CF, proprietari)
@@ -310,19 +335,41 @@ export async function POST(req: Request) {
} }
} }
// Extract owners from partTwoRegs // Extract owners from partTwoRegs — separate active vs cancelled
const owners: string[] = []; const activeOwners: string[] = [];
const cancelledOwners: string[] = [];
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
(docResponse?.partTwoRegs ?? []).forEach((reg: any) => { const regs = docResponse?.partTwoRegs ?? [];
if (regs.length > 0) {
console.log("[search] partTwoRegs[0] keys:", Object.keys(regs[0]));
console.log("[search] partTwoRegs sample:", JSON.stringify(regs[0]).slice(0, 500));
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
regs.forEach((reg: any) => {
if ( if (
String(reg?.nodeType ?? "").toUpperCase() === "P" && String(reg?.nodeType ?? "").toUpperCase() === "P" &&
reg?.nodeName reg?.nodeName
) { ) {
const name = String(reg.nodeName).trim(); const name = String(reg.nodeName).trim();
if (name) owners.push(name); if (!name) return;
// Check if this entry is cancelled/radiated
const isCancelled =
reg?.cancelled === true ||
reg?.isActive === false ||
reg?.radiat === true ||
String(reg?.status ?? "").toUpperCase() === "RADIAT" ||
String(reg?.status ?? "").toUpperCase() === "CANCELLED" ||
reg?.radiationDate != null;
if (isCancelled) {
cancelledOwners.push(name);
} else {
activeOwners.push(name);
}
} }
}); });
proprietari = Array.from(new Set(owners)).join("; "); proprietariActuali = Array.from(new Set(activeOwners));
proprietariVechi = Array.from(new Set(cancelledOwners))
.filter((n) => !proprietariActuali.includes(n));
} catch { } catch {
// Documentation fetch failed — continue with basic data // Documentation fetch failed — continue with basic data
} }
@@ -371,6 +418,7 @@ export async function POST(req: Request) {
} }
} }
const allOwners = [...proprietariActuali, ...proprietariVechi];
results.push({ results.push({
nrCad: String(item?.identifierDetails ?? cadNr), nrCad: String(item?.identifierDetails ?? cadNr),
nrCF, nrCF,
@@ -379,7 +427,9 @@ export async function POST(req: Request) {
intravilan, intravilan,
categorieFolosinta: categorie, categorieFolosinta: categorie,
adresa: addressText, adresa: addressText,
proprietari, proprietari: allOwners.join("; "),
proprietariActuali: proprietariActuali.join("; "),
proprietariVechi: proprietariVechi.join("; "),
suprafata, suprafata,
solicitant, solicitant,
immovablePk: immPkStr, immovablePk: immPkStr,
@@ -396,6 +446,8 @@ export async function POST(req: Request) {
categorieFolosinta: "", categorieFolosinta: "",
adresa: "", adresa: "",
proprietari: "", proprietari: "",
proprietariActuali: "",
proprietariVechi: "",
suprafata: null, suprafata: null,
solicitant: "", solicitant: "",
immovablePk: "", immovablePk: "",
@@ -705,7 +705,8 @@ export function ParcelSyncModule() {
"INTRAVILAN", "INTRAVILAN",
"CATEGORIE_FOLOSINTA", "CATEGORIE_FOLOSINTA",
"ADRESA", "ADRESA",
"PROPRIETARI", "PROPRIETARI_ACTUALI",
"PROPRIETARI_VECHI",
"SOLICITANT", "SOLICITANT",
]; ];
const rows = items.map((p) => [ const rows = items.map((p) => [
@@ -717,7 +718,8 @@ export function ParcelSyncModule() {
p.intravilan, p.intravilan,
`"${(p.categorieFolosinta ?? "").replace(/"/g, '""')}"`, `"${(p.categorieFolosinta ?? "").replace(/"/g, '""')}"`,
`"${(p.adresa ?? "").replace(/"/g, '""')}"`, `"${(p.adresa ?? "").replace(/"/g, '""')}"`,
`"${(p.proprietari ?? "").replace(/"/g, '""')}"`, `"${(p.proprietariActuali ?? p.proprietari ?? "").replace(/"/g, '""')}"`,
`"${(p.proprietariVechi ?? "").replace(/"/g, '""')}"`,
`"${(p.solicitant ?? "").replace(/"/g, '""')}"`, `"${(p.solicitant ?? "").replace(/"/g, '""')}"`,
]); ]);
const csv = [headers.join(","), ...rows.map((r) => r.join(","))].join("\n"); const csv = [headers.join(","), ...rows.map((r) => r.join(","))].join("\n");
@@ -1026,7 +1028,13 @@ export function ParcelSyncModule() {
? `Categorie: ${p.categorieFolosinta}` ? `Categorie: ${p.categorieFolosinta}`
: null, : null,
p.adresa ? `Adresă: ${p.adresa}` : null, p.adresa ? `Adresă: ${p.adresa}` : null,
p.proprietari p.proprietariActuali
? `Proprietari actuali: ${p.proprietariActuali}`
: null,
p.proprietariVechi
? `Proprietari vechi: ${p.proprietariVechi}`
: null,
!p.proprietariActuali && !p.proprietariVechi && p.proprietari
? `Proprietari: ${p.proprietari}` ? `Proprietari: ${p.proprietari}`
: null, : null,
p.solicitant p.solicitant
@@ -1112,12 +1120,36 @@ export function ParcelSyncModule() {
<span>{p.adresa}</span> <span>{p.adresa}</span>
</div> </div>
)} )}
{p.proprietari && ( {(p.proprietariActuali || p.proprietariVechi) && (
<div className="col-span-2 lg:col-span-3"> <div className="col-span-2 lg:col-span-4">
<span className="text-xs text-muted-foreground block"> {p.proprietariActuali && (
Proprietari <div className="mb-1">
</span> <span className="text-xs text-muted-foreground block">
<span>{p.proprietari}</span> Proprietari actuali
</span>
<span className="font-medium text-sm">
{p.proprietariActuali}
</span>
</div>
)}
{p.proprietariVechi && (
<div>
<span className="text-xs text-muted-foreground block">
Proprietari vechi (radiați)
</span>
<span className="text-xs text-muted-foreground/70 line-through">
{p.proprietariVechi}
</span>
</div>
)}
{!p.proprietariActuali && !p.proprietariVechi && p.proprietari && (
<div>
<span className="text-xs text-muted-foreground block">
Proprietari
</span>
<span>{p.proprietari}</span>
</div>
)}
</div> </div>
)} )}
{p.solicitant && ( {p.solicitant && (