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;
console.log("[resolveWorkspace] ArcGIS WORKSPACE_ID for", siruta, "→", wsId);
console.log(
"[resolveWorkspace] ArcGIS WORKSPACE_ID for",
siruta,
"→",
wsId,
);
if (wsId != null) {
const numWs = Number(wsId);
if (Number.isFinite(numWs)) {
@@ -68,7 +73,10 @@ async function resolveWorkspace(
}
}
} 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;
@@ -94,10 +102,16 @@ function formatAddress(item?: any) {
const address = item?.immovableAddresses?.[0]?.address ?? null;
if (!address) return "";
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.buildingNo) parts.push(`Nr. ${address.buildingNo}`);
if (address.locality?.name) parts.push(address.locality.name);
if (address.county?.name) parts.push(`Jud. ${address.county.name}`);
return parts.length ? parts.join(", ") : "";
}
@@ -144,6 +158,8 @@ export type ParcelDetail = {
categorieFolosinta: string;
adresa: string;
proprietari: string;
proprietariActuali: string;
proprietariVechi: string;
suprafata: number | null;
solicitant: string;
immovablePk: string;
@@ -256,6 +272,8 @@ export async function POST(req: Request) {
categorieFolosinta: "",
adresa: "",
proprietari: "",
proprietariActuali: "",
proprietariVechi: "",
suprafata: null,
solicitant: "",
immovablePk: "",
@@ -272,16 +290,23 @@ export async function POST(req: Request) {
let nrCFVechi = "";
let nrTopo = String(item?.topNo ?? item?.paperCadNo ?? "");
let addressText = formatAddress(item);
let proprietari = "";
let proprietariActuali: string[] = [];
let proprietariVechi: string[] = [];
let solicitant = "";
let intravilan = "";
let categorie = "";
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) {
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)
@@ -310,19 +335,41 @@ export async function POST(req: Request) {
}
}
// Extract owners from partTwoRegs
const owners: string[] = [];
// Extract owners from partTwoRegs — separate active vs cancelled
const activeOwners: string[] = [];
const cancelledOwners: string[] = [];
// 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 (
String(reg?.nodeType ?? "").toUpperCase() === "P" &&
reg?.nodeName
) {
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 {
// Documentation fetch failed — continue with basic data
}
@@ -371,6 +418,7 @@ export async function POST(req: Request) {
}
}
const allOwners = [...proprietariActuali, ...proprietariVechi];
results.push({
nrCad: String(item?.identifierDetails ?? cadNr),
nrCF,
@@ -379,7 +427,9 @@ export async function POST(req: Request) {
intravilan,
categorieFolosinta: categorie,
adresa: addressText,
proprietari,
proprietari: allOwners.join("; "),
proprietariActuali: proprietariActuali.join("; "),
proprietariVechi: proprietariVechi.join("; "),
suprafata,
solicitant,
immovablePk: immPkStr,
@@ -396,6 +446,8 @@ export async function POST(req: Request) {
categorieFolosinta: "",
adresa: "",
proprietari: "",
proprietariActuali: "",
proprietariVechi: "",
suprafata: null,
solicitant: "",
immovablePk: "",
@@ -705,7 +705,8 @@ export function ParcelSyncModule() {
"INTRAVILAN",
"CATEGORIE_FOLOSINTA",
"ADRESA",
"PROPRIETARI",
"PROPRIETARI_ACTUALI",
"PROPRIETARI_VECHI",
"SOLICITANT",
];
const rows = items.map((p) => [
@@ -717,7 +718,8 @@ export function ParcelSyncModule() {
p.intravilan,
`"${(p.categorieFolosinta ?? "").replace(/"/g, '""')}"`,
`"${(p.adresa ?? "").replace(/"/g, '""')}"`,
`"${(p.proprietari ?? "").replace(/"/g, '""')}"`,
`"${(p.proprietariActuali ?? p.proprietari ?? "").replace(/"/g, '""')}"`,
`"${(p.proprietariVechi ?? "").replace(/"/g, '""')}"`,
`"${(p.solicitant ?? "").replace(/"/g, '""')}"`,
]);
const csv = [headers.join(","), ...rows.map((r) => r.join(","))].join("\n");
@@ -1026,7 +1028,13 @@ export function ParcelSyncModule() {
? `Categorie: ${p.categorieFolosinta}`
: 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}`
: null,
p.solicitant
@@ -1112,14 +1120,38 @@ export function ParcelSyncModule() {
<span>{p.adresa}</span>
</div>
)}
{p.proprietari && (
<div className="col-span-2 lg:col-span-3">
{(p.proprietariActuali || p.proprietariVechi) && (
<div className="col-span-2 lg:col-span-4">
{p.proprietariActuali && (
<div className="mb-1">
<span className="text-xs text-muted-foreground block">
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>
)}
{p.solicitant && (
<div className="col-span-2">
<span className="text-xs text-muted-foreground block">