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:
@@ -10,10 +10,11 @@ export const runtime = "nodejs";
|
|||||||
export const dynamic = "force-dynamic";
|
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:
|
* ePay internal county IDs = eTerra WORKSPACE_IDs.
|
||||||
* shoppingCartCompleteInformation → judeteNom → nomenclatorUAT → saveMetadata
|
* ePay UAT IDs = SIRUTA codes.
|
||||||
|
* Zero discovery calls needed!
|
||||||
*/
|
*/
|
||||||
export async function GET(req: Request) {
|
export async function GET(req: Request) {
|
||||||
const url = new URL(req.url);
|
const url = new URL(req.url);
|
||||||
@@ -26,9 +27,6 @@ export async function GET(req: Request) {
|
|||||||
return NextResponse.json({ error: "ANCPI credentials not configured" });
|
return NextResponse.json({ error: "ANCPI credentials not configured" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const normalize = (s: string) =>
|
|
||||||
s.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toUpperCase().trim();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// ── login ──
|
// ── login ──
|
||||||
if (step === "login") {
|
if (step === "login") {
|
||||||
@@ -38,75 +36,39 @@ export async function GET(req: Request) {
|
|||||||
return NextResponse.json({ step: "login", success: true, credits });
|
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") {
|
if (step === "uats") {
|
||||||
const client = await EpayClient.create(username, password);
|
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 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 }[] = [];
|
let uatList: { id: number; value: string }[] = [];
|
||||||
if (clujCounty) {
|
if (clujCounty) {
|
||||||
uatList = await client.getUatList(clujCounty.id);
|
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({
|
return NextResponse.json({
|
||||||
step: "uats",
|
step: "uats",
|
||||||
totalCounties: counties.length,
|
totalCounties: counties.length,
|
||||||
countiesFirst5: counties.slice(0, 5),
|
|
||||||
clujCounty,
|
clujCounty,
|
||||||
|
note: clujCounty?.id === 127
|
||||||
|
? "CONFIRMED: ePay county ID = WORKSPACE_ID (127)"
|
||||||
|
: `WARNING: expected 127, got ${clujCounty?.id}`,
|
||||||
totalUats: uatList.length,
|
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!)
|
// ── order ── (USES 3 CREDITS!)
|
||||||
|
// Uses WORKSPACE_ID as county ID, SIRUTA as UAT ID — zero discovery
|
||||||
if (step === "order") {
|
if (step === "order") {
|
||||||
if (!getEpayCredentials()) {
|
if (!getEpayCredentials()) {
|
||||||
createEpaySession(username, password, 0);
|
createEpaySession(username, password, 0);
|
||||||
@@ -117,15 +79,37 @@ export async function GET(req: Request) {
|
|||||||
createEpaySession(username, password, credits);
|
createEpaySession(username, password, credits);
|
||||||
|
|
||||||
if (credits < 3) {
|
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
|
// workspacePk=127 (CLUJ), SIRUTA codes as UAT IDs
|
||||||
// Queue handles getCountyList + getUatList internally
|
|
||||||
const parcels = [
|
const parcels = [
|
||||||
{ nrCadastral: "345295", judetName: "CLUJ", uatName: "Cluj-Napoca", judetIndex: 0, uatId: 0 },
|
{
|
||||||
{ nrCadastral: "63565", judetName: "CLUJ", uatName: "Feleacu", judetIndex: 0, uatId: 0 },
|
nrCadastral: "345295",
|
||||||
{ nrCadastral: "88089", judetName: "CLUJ", uatName: "Floresti", judetIndex: 0, uatId: 0 },
|
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[] = [];
|
const ids: string[] = [];
|
||||||
@@ -137,8 +121,14 @@ export async function GET(req: Request) {
|
|||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
step: "order",
|
step: "order",
|
||||||
credits,
|
credits,
|
||||||
message: `Enqueued ${ids.length} orders. Queue resolves county/UAT IDs automatically.`,
|
message: `Enqueued ${ids.length} orders (4 requests each, zero discovery).`,
|
||||||
orderIds: ids,
|
orderIds: ids,
|
||||||
|
parcels: parcels.map((p, i) => ({
|
||||||
|
nrCadastral: p.nrCadastral,
|
||||||
|
uatName: p.uatName,
|
||||||
|
siruta: p.siruta,
|
||||||
|
extractId: ids[i],
|
||||||
|
})),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -175,42 +175,39 @@ async function processItem(item: QueueItem): Promise<void> {
|
|||||||
const basketRowId = await client.addToCart(input.prodId ?? 14200);
|
const basketRowId = await client.addToCart(input.prodId ?? 14200);
|
||||||
await updateStatus(extractId, "cart", { basketRowId });
|
await updateStatus(extractId, "cart", { basketRowId });
|
||||||
|
|
||||||
// Step 3: Resolve internal county + UAT IDs
|
// Step 3: Save metadata + submit order
|
||||||
await updateStatus(extractId, "searching");
|
// ePay internal county IDs = eTerra WORKSPACE_IDs
|
||||||
const counties = await client.getCountyList();
|
// ePay UAT IDs = SIRUTA codes
|
||||||
const normalize = (s: string) =>
|
// So we can skip all discovery calls!
|
||||||
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
|
|
||||||
await updateStatus(extractId, "ordering");
|
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 nrCF = input.nrCF ?? input.nrCadastral;
|
||||||
const saved = await client.saveMetadata(
|
const saved = await client.saveMetadata(
|
||||||
basketRowId,
|
basketRowId,
|
||||||
countyMatch.id,
|
countyInternalId,
|
||||||
countyMatch.value,
|
countyName,
|
||||||
uatMatch.id,
|
uatInternalId,
|
||||||
uatMatch.value,
|
uatName,
|
||||||
nrCF,
|
nrCF,
|
||||||
input.nrCadastral,
|
input.nrCadastral,
|
||||||
process.env.ANCPI_DEFAULT_SOLICITANT_ID || "14452",
|
process.env.ANCPI_DEFAULT_SOLICITANT_ID || "14452",
|
||||||
|
|||||||
Reference in New Issue
Block a user