fix(ancpi): ePay county IDs = WORKSPACE_IDs, UAT IDs = SIRUTA codes

Zero discovery calls needed! ePay internal county IDs are identical
to eTerra WORKSPACE_IDs (CLUJ=127, ALBA=10, etc.) and ePay UAT IDs
are SIRUTA codes (Cluj-Napoca=54975, Florești=57706). Queue now
uses workspacePk + siruta directly from GisUat DB.
Flow: AddToCart → saveMetadata → EditCartSubmit → Poll+Download.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
AI Assistant
2026-03-23 02:11:41 +02:00
parent e13a9351be
commit 7fc46f75bd
2 changed files with 82 additions and 95 deletions
+53 -63
View File
@@ -10,10 +10,11 @@ export const runtime = "nodejs";
export const dynamic = "force-dynamic";
/**
* GET /api/ancpi/test?step=login|uats|search|order
* GET /api/ancpi/test?step=login|uats|order
*
* Temporary diagnostic endpoint. Uses the CORRECT ePay flow:
* shoppingCartCompleteInformation → judeteNom → nomenclatorUAT → saveMetadata
* ePay internal county IDs = eTerra WORKSPACE_IDs.
* ePay UAT IDs = SIRUTA codes.
* Zero discovery calls needed!
*/
export async function GET(req: Request) {
const url = new URL(req.url);
@@ -26,9 +27,6 @@ export async function GET(req: Request) {
return NextResponse.json({ error: "ANCPI credentials not configured" });
}
const normalize = (s: string) =>
s.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toUpperCase().trim();
try {
// ── login ──
if (step === "login") {
@@ -38,75 +36,39 @@ export async function GET(req: Request) {
return NextResponse.json({ step: "login", success: true, credits });
}
// ── uats ── Get internal county IDs + UAT list for Cluj
// ── uats ── Verify that ePay county/UAT IDs match our WORKSPACE_ID/SIRUTA
if (step === "uats") {
const client = await EpayClient.create(username, password);
await client.addToCart(14200); // need cart for ShowCartItems context
await client.addToCart(14200);
// Get county list to confirm IDs match WORKSPACE_IDs
const counties = await client.getCountyList();
const clujCounty = counties.find((c) => normalize(c.value) === "CLUJ");
const clujCounty = counties.find((c) =>
c.value.toUpperCase().includes("CLUJ"),
);
// Get UAT list to confirm IDs match SIRUTA codes
let uatList: { id: number; value: string }[] = [];
if (clujCounty) {
uatList = await client.getUatList(clujCounty.id);
}
const clujNapoca = uatList.find((u) => normalize(u.value).includes("CLUJ-NAPOCA"));
const feleacu = uatList.find((u) => normalize(u.value).includes("FELEACU"));
const floresti = uatList.find((u) => normalize(u.value).includes("FLORESTI"));
return NextResponse.json({
step: "uats",
totalCounties: counties.length,
countiesFirst5: counties.slice(0, 5),
clujCounty,
note: clujCounty?.id === 127
? "CONFIRMED: ePay county ID = WORKSPACE_ID (127)"
: `WARNING: expected 127, got ${clujCounty?.id}`,
totalUats: uatList.length,
matches: { clujNapoca, feleacu, floresti },
clujNapoca: uatList.find((u) => u.id === 54975),
feleacu: uatList.find((u) => u.id === 57582),
floresti: uatList.find((u) => u.id === 57706),
});
}
// ── search ── SearchEstate with correct params
if (step === "search") {
const client = await EpayClient.create(username, password);
await client.addToCart(14200);
const counties = await client.getCountyList();
const clujCounty = counties.find((c) => normalize(c.value) === "CLUJ");
if (!clujCounty) {
return NextResponse.json({ error: "CLUJ not found", counties: counties.slice(0, 5) });
}
const uatList = await client.getUatList(clujCounty.id);
const clujNapoca = uatList.find((u) => normalize(u.value).includes("CLUJ-NAPOCA"));
const feleacu = uatList.find((u) => normalize(u.value).includes("FELEACU"));
const floresti = uatList.find((u) => normalize(u.value).includes("FLORESTI"));
const results: Record<string, unknown> = {
clujCountyId: clujCounty.id,
uats: { clujNapoca, feleacu, floresti },
};
// SearchEstate with correct field names: identificator, judet (internal ID), uat (real ID)
if (clujNapoca) {
results["search_345295"] = await client
.searchEstate("345295", clujCounty.id, clujNapoca.id)
.catch((e: Error) => ({ error: e.message }));
}
if (feleacu) {
results["search_63565"] = await client
.searchEstate("63565", clujCounty.id, feleacu.id)
.catch((e: Error) => ({ error: e.message }));
}
if (floresti) {
results["search_88089"] = await client
.searchEstate("88089", clujCounty.id, floresti.id)
.catch((e: Error) => ({ error: e.message }));
}
return NextResponse.json({ step: "search", results });
}
// ── order ── (USES 3 CREDITS!)
// Uses WORKSPACE_ID as county ID, SIRUTA as UAT ID — zero discovery
if (step === "order") {
if (!getEpayCredentials()) {
createEpaySession(username, password, 0);
@@ -117,15 +79,37 @@ export async function GET(req: Request) {
createEpaySession(username, password, credits);
if (credits < 3) {
return NextResponse.json({ error: `Doar ${credits} credite, trebuie 3.` });
return NextResponse.json({
error: `Doar ${credits} credite, trebuie 3.`,
});
}
// Resolve county + UAT IDs through the queue
// Queue handles getCountyList + getUatList internally
// workspacePk=127 (CLUJ), SIRUTA codes as UAT IDs
const parcels = [
{ nrCadastral: "345295", judetName: "CLUJ", uatName: "Cluj-Napoca", judetIndex: 0, uatId: 0 },
{ nrCadastral: "63565", judetName: "CLUJ", uatName: "Feleacu", judetIndex: 0, uatId: 0 },
{ nrCadastral: "88089", judetName: "CLUJ", uatName: "Floresti", judetIndex: 0, uatId: 0 },
{
nrCadastral: "345295",
siruta: "54975", // SIRUTA = ePay UAT ID
judetIndex: 127, // workspacePk = ePay county ID
judetName: "CLUJ",
uatId: 54975,
uatName: "Cluj-Napoca",
},
{
nrCadastral: "63565",
siruta: "57582",
judetIndex: 127,
judetName: "CLUJ",
uatId: 57582,
uatName: "Feleacu",
},
{
nrCadastral: "88089",
siruta: "57706",
judetIndex: 127,
judetName: "CLUJ",
uatId: 57706,
uatName: "Florești",
},
];
const ids: string[] = [];
@@ -137,8 +121,14 @@ export async function GET(req: Request) {
return NextResponse.json({
step: "order",
credits,
message: `Enqueued ${ids.length} orders. Queue resolves county/UAT IDs automatically.`,
message: `Enqueued ${ids.length} orders (4 requests each, zero discovery).`,
orderIds: ids,
parcels: parcels.map((p, i) => ({
nrCadastral: p.nrCadastral,
uatName: p.uatName,
siruta: p.siruta,
extractId: ids[i],
})),
});
}
+29 -32
View File
@@ -175,42 +175,39 @@ async function processItem(item: QueueItem): Promise<void> {
const basketRowId = await client.addToCart(input.prodId ?? 14200);
await updateStatus(extractId, "cart", { basketRowId });
// Step 3: Resolve internal county + UAT IDs
await updateStatus(extractId, "searching");
const counties = await client.getCountyList();
const normalize = (s: string) =>
s.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toUpperCase().trim();
const countyMatch = counties.find(
(c) => normalize(c.value) === normalize(input.judetName),
);
if (!countyMatch) {
await updateStatus(extractId, "failed", {
errorMessage: `Județul "${input.judetName}" nu a fost găsit în ePay. Disponibile: ${counties.slice(0, 5).map((c) => c.value).join(", ")}...`,
});
return;
}
const uats = await client.getUatList(countyMatch.id);
const uatMatch = uats.find(
(u) => normalize(u.value) === normalize(input.uatName),
);
if (!uatMatch) {
await updateStatus(extractId, "failed", {
errorMessage: `UAT "${input.uatName}" nu a fost găsit în ePay pentru ${input.judetName}.`,
});
return;
}
// Step 4: Save metadata + submit order
// Step 3: Save metadata + submit order
// ePay internal county IDs = eTerra WORKSPACE_IDs
// ePay UAT IDs = SIRUTA codes
// So we can skip all discovery calls!
await updateStatus(extractId, "ordering");
// Resolve county ID (workspacePk) and UAT ID (siruta) from our DB
let countyInternalId = input.judetIndex; // might already be workspacePk
let uatInternalId = input.uatId; // might already be SIRUTA
let countyName = input.judetName;
let uatName = input.uatName;
// If siruta is provided, look up workspacePk from GisUat
if (input.siruta) {
const uat = await prisma.gisUat.findUnique({
where: { siruta: input.siruta },
select: { workspacePk: true, county: true, name: true },
});
if (uat?.workspacePk) {
countyInternalId = uat.workspacePk;
uatInternalId = Number(input.siruta);
if (uat.county) countyName = uat.county;
if (uat.name) uatName = uat.name;
}
}
const nrCF = input.nrCF ?? input.nrCadastral;
const saved = await client.saveMetadata(
basketRowId,
countyMatch.id,
countyMatch.value,
uatMatch.id,
uatMatch.value,
countyInternalId,
countyName,
uatInternalId,
uatName,
nrCF,
input.nrCadastral,
process.env.ANCPI_DEFAULT_SOLICITANT_ID || "14452",