From a4f61bf3d895fbb65d8c2469a2dde626ff32e62c Mon Sep 17 00:00:00 2001 From: Claude VM Date: Tue, 19 May 2026 22:44:25 +0300 Subject: [PATCH] feat(geoportal-v2): manual fetch flag + friendlier pool-exhausted error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two operational gaps observed after PR3 deep-enrich rollout: 1. Raw \"Eroare: no_available_account\" surfaced when the eTerra account pool hit its hourly quota. Replace with a plain-language note ("Pool-ul ANCPI e temporar epuizat — încearcă peste câteva minute"). Same friendly treatment for the other common orchestrator errors: no_immovable_match, parcel_not_found, eterra_fetch_failed. 2. Marius wants the auto-trigger (fires on sparse-data load) and the explicit "Citește din ANCPI" button to be separable on the orchestrator side. Casual map browsing burns through the 500/h quota with auto-triggers; a working session that needs 20-30 specific parcels shouldn't be starved. refreshFromAncpi now takes { manual?: boolean }. The button passes manual: true → request body includes manualOverride: true. The auto-trigger useEffect calls it with no argument (manual defaults to false). gis-api / orchestrator can later route manualOverride to a separate-quota bucket or skip the per-hour check entirely. Until then the flag is harmless (orchestrator ignores unknown fields). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../geoportal/v2/feature-info-panel.tsx | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/modules/geoportal/v2/feature-info-panel.tsx b/src/modules/geoportal/v2/feature-info-panel.tsx index 552d4b1..a07697f 100644 --- a/src/modules/geoportal/v2/feature-info-panel.tsx +++ b/src/modules/geoportal/v2/feature-info-panel.tsx @@ -409,7 +409,7 @@ export function FeatureInfoPanel({ feature, onClose, basic = false }: Props) { }; }, [isCladiri, feature.siruta, feature.cadastralRef, basic]); - const refreshFromAncpi = useCallback(async () => { + const refreshFromAncpi = useCallback(async (opts: { manual?: boolean } = {}) => { if (!feature.siruta || !feature.cadastralRef) { setError("missing_siruta_or_cad"); return; @@ -419,9 +419,16 @@ export function FeatureInfoPanel({ feature, onClose, basic = false }: Props) { try { // PR3 deep-enrich path: gis-api orchestrates the eTerra round-trip // and persists NR_CF / ADRESA / PROPRIETARI + tech fields in gis_core - // (30-day cache; force=true bypasses). After this returns the + // (30-day cache; force=true bypasses cache). After this returns the // central record is canonical — we re-fetch it via parcela.get or // parcela.find so the panel sees what's actually in gis_core. + // + // manualOverride=true is set when the user explicitly pressed the + // "Citește din ANCPI" button (vs the auto-trigger that fires on + // sparse-data load). gis-api/orchestrator can treat this as a + // separate-quota bucket so casual map browsing doesn't starve a + // user who needs to fetch 20-30 specific parcels in a working + // session. Until orchestrator supports it the flag is ignored. const enrichResp = await fetch("/api/gis/parcel/enrich", { method: "POST", headers: { "Content-Type": "application/json" }, @@ -429,6 +436,7 @@ export function FeatureInfoPanel({ feature, onClose, basic = false }: Props) { siruta: feature.siruta, cadastralRef: feature.cadastralRef, force: true, + ...(opts.manual ? { manualOverride: true } : {}), }), }); if (!enrichResp.ok) { @@ -658,7 +666,17 @@ export function FeatureInfoPanel({ feature, onClose, basic = false }: Props) { {error && error !== "forbidden" && (
- Eroare: {error} + + {error === "no_available_account" + ? "Pool-ul ANCPI e temporar epuizat — încearcă din nou peste câteva minute (cota orară se resetează automat)." + : error === "no_immovable_match" + ? "Parcela nu există în baza eTerra (cadref + SIRUTA nu se potrivesc)." + : error === "parcel_not_found" + ? "Parcela nu există în baza centrală gis_core." + : error === "eterra_fetch_failed" + ? "eTerra ANCPI nu răspunde momentan. Reîncearcă în 1-2 minute." + : `Eroare: ${error}`} +
)} @@ -920,7 +938,7 @@ export function FeatureInfoPanel({ feature, onClose, basic = false }: Props) {