From d367b5f736f2bb3193beab813c4ea2892b3092af Mon Sep 17 00:00:00 2001 From: AI Assistant Date: Mon, 23 Mar 2026 01:27:30 +0200 Subject: [PATCH] fix(ancpi): add SearchEstate debug logging, try without uatId, add cart first SearchEstate might need active cart and/or different headers. Add X-Requested-With: XMLHttpRequest, make uatId optional, log raw response (type, length, sample), and add-to-cart before searching. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/app/api/ancpi/test/route.ts | 25 ++++++++----- .../parcel-sync/services/epay-client.ts | 37 ++++++++++++++----- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/src/app/api/ancpi/test/route.ts b/src/app/api/ancpi/test/route.ts index 1bf492f..d813b74 100644 --- a/src/app/api/ancpi/test/route.ts +++ b/src/app/api/ancpi/test/route.ts @@ -81,26 +81,31 @@ export async function GET(req: Request) { const client = await EpayClient.create(username, password); const countyIdx = resolveEpayCountyIndex("Cluj")!; - // Try SearchEstate with different uatId values to find what works const results: Record = {}; - // Test 1: uatId=-1 (maybe "all") - results["345295_uatNeg1"] = await client.searchEstate("345295", countyIdx, -1).catch((e: Error) => ({ error: e.message })); + // First add to cart — SearchEstate might only work with active cart + let basketRowId: number | null = null; + try { + basketRowId = await client.addToCart(14200); + results["_basketRowId"] = basketRowId; + } catch (e) { + results["_cartError"] = (e as Error).message; + } - // Test 2: uatId=0 - results["345295_uat0"] = await client.searchEstate("345295", countyIdx, 0).catch((e: Error) => ({ error: e.message })); + // Test SearchEstate: without uatId (optional now) + results["345295_noUat"] = await client.searchEstate("345295", countyIdx).catch((e: Error) => ({ error: e.message })); - // Test 3: uatId=24 (from spec: Cluj-Napoca is index 24) + // Test with uatId=24 (spec says Cluj-Napoca) results["345295_uat24"] = await client.searchEstate("345295", countyIdx, 24).catch((e: Error) => ({ error: e.message })); - // Test 4: no uatId at all — modify searchEstate to support optional - // For now just try a few indices for Feleacu/Florești - results["63565_uat0"] = await client.searchEstate("63565", countyIdx, 0).catch((e: Error) => ({ error: e.message })); - results["88089_uat0"] = await client.searchEstate("88089", countyIdx, 0).catch((e: Error) => ({ error: e.message })); + // Other parcels without uatId + results["63565_noUat"] = await client.searchEstate("63565", countyIdx).catch((e: Error) => ({ error: e.message })); + results["88089_noUat"] = await client.searchEstate("88089", countyIdx).catch((e: Error) => ({ error: e.message })); return NextResponse.json({ step: "search", countyIdx, + basketRowId, results, }); } diff --git a/src/modules/parcel-sync/services/epay-client.ts b/src/modules/parcel-sync/services/epay-client.ts index 960793d..cb280ea 100644 --- a/src/modules/parcel-sync/services/epay-client.ts +++ b/src/modules/parcel-sync/services/epay-client.ts @@ -329,33 +329,52 @@ export class EpayClient { async searchEstate( identifier: string, countyIdx: number, - uatId: number, + uatId?: number, ): Promise { return this.retryOnAuthFail(async () => { const body = new URLSearchParams(); body.set("identifier", identifier); body.set("countyId", String(countyIdx)); - body.set("uatId", String(uatId)); + if (uatId != null && uatId >= 0) { + body.set("uatId", String(uatId)); + } const response = await this.client.post( `${BASE_URL}/SearchEstate.action`, body.toString(), { - headers: { "Content-Type": "application/x-www-form-urlencoded" }, + headers: { + "Content-Type": "application/x-www-form-urlencoded", + Accept: "application/json, text/plain, */*", + "X-Requested-With": "XMLHttpRequest", + }, timeout: DEFAULT_TIMEOUT_MS, }, ); const data = response.data; + + // Log raw response for debugging + const rawStr = typeof data === "string" ? data : JSON.stringify(data); + console.log( + `[epay] SearchEstate(${identifier}, county=${countyIdx}, uat=${uatId ?? "none"}):`, + `type=${typeof data}, len=${rawStr?.length ?? 0}, sample=${rawStr?.slice(0, 300)}`, + ); + if (Array.isArray(data)) return data as EpaySearchResult[]; - // Sometimes wrapped in a string if (typeof data === "string") { - try { - const parsed = JSON.parse(data); - if (Array.isArray(parsed)) return parsed as EpaySearchResult[]; - } catch { - // Not JSON + // Try JSON parse + const trimmed = data.trim(); + if (trimmed.startsWith("[") || trimmed.startsWith("{")) { + try { + const parsed = JSON.parse(trimmed); + if (Array.isArray(parsed)) return parsed as EpaySearchResult[]; + // Wrapped in object? + if (parsed?.results) return parsed.results as EpaySearchResult[]; + } catch { + // Not JSON + } } }