feat(parcel-sync): owner name search (proprietar) in Search tab
- New search mode toggle: Nr. Cadastral / Proprietar - Owner search queries: 1. Local DB first (enrichment PROPRIETARI/PROPRIETARI_VECHI ILIKE) 2. eTerra API fallback (tries personName/titularName/ownerName filter keys) - DB search works offline (no eTerra connection needed) — uses enriched data - New API route: POST /api/eterra/search-owner - New eterra-client method: searchImmovableByOwnerName() - Owner results show source badge (DB local / eTerra online) - Results can be added to saved list and exported as CSV - Relaxed search tab guard: only requires UAT selection (not eTerra connection) - Cadastral search still requires eTerra connection (shows hint when offline)
This commit is contained in:
@@ -643,6 +643,86 @@ export class EterraClient {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search immovable list by owner/titular name.
|
||||
*
|
||||
* Uses the same `/api/immovable/list` endpoint, with a `personName`
|
||||
* filter key. eTerra supports partial matching on this field.
|
||||
*
|
||||
* Falls back to `titularName` key if personName returns empty.
|
||||
*
|
||||
* @returns Paginated response with `content[]`, `totalPages`, `totalElements`
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
async searchImmovableByOwnerName(
|
||||
workspaceId: string | number,
|
||||
adminUnitId: string | number,
|
||||
ownerName: string,
|
||||
page = 0,
|
||||
size = 20,
|
||||
): Promise<any> {
|
||||
const url = `${BASE_URL}/api/immovable/list`;
|
||||
const baseFilters: Array<{
|
||||
value: string | number;
|
||||
type: "NUMBER" | "STRING";
|
||||
key: string;
|
||||
op: string;
|
||||
}> = [
|
||||
{
|
||||
value: Number(workspaceId),
|
||||
type: "NUMBER",
|
||||
key: "workspace.nomenPk",
|
||||
op: "=",
|
||||
},
|
||||
{
|
||||
value: Number(adminUnitId),
|
||||
type: "NUMBER",
|
||||
key: "adminUnit.nomenPk",
|
||||
op: "=",
|
||||
},
|
||||
{ value: -1, type: "NUMBER", key: "inscrisCF", op: "=" },
|
||||
];
|
||||
|
||||
// Try primary key: personName (used in some eTerra versions)
|
||||
const keysToTry = ["personName", "titularName", "ownerName"];
|
||||
for (const filterKey of keysToTry) {
|
||||
try {
|
||||
const filters = [
|
||||
...baseFilters,
|
||||
{
|
||||
value: ownerName,
|
||||
type: "STRING" as const,
|
||||
key: filterKey,
|
||||
op: "=",
|
||||
},
|
||||
];
|
||||
const payload = { filters, nrElements: size, page, sorters: [] };
|
||||
const result = await this.requestRaw(() =>
|
||||
this.client.post(url, payload, {
|
||||
headers: { "Content-Type": "application/json;charset=UTF-8" },
|
||||
timeout: this.timeoutMs,
|
||||
}),
|
||||
);
|
||||
// If we got content back (even empty), it means the key is valid
|
||||
if (result && typeof result === "object" && "content" in result) {
|
||||
console.log(
|
||||
`[searchByOwner] Key "${filterKey}" worked — ${(result as any).totalElements ?? 0} results`,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(
|
||||
`[searchByOwner] Key "${filterKey}" failed:`,
|
||||
e instanceof Error ? e.message : e,
|
||||
);
|
||||
// Try next key
|
||||
}
|
||||
}
|
||||
|
||||
// All keys failed — return empty result
|
||||
return { content: [], totalElements: 0, totalPages: 0 };
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all counties (workspaces) from eTerra nomenclature.
|
||||
* Returns array of { nomenPk, name, parentNomenPk, ... }
|
||||
|
||||
Reference in New Issue
Block a user