feat(ancpi): re-download with CF matching + tooltips + animations
Re-download: all 7 orders re-downloaded using documentsByCadastral for correct CF→document matching. No more hardcoded order→parcel map. Tooltips on all CF extract UI elements: - No extract: "Comandă extras CF (1 credit)" - Valid: "Valid până la DD.MM.YYYY" + "Descarcă extras CF" - Expired: "Expirat pe DD.MM.YYYY" + "Comandă extras CF nou (1 credit)" - Processing: "Comanda în curs de procesare" Animations: Loader2 spinner while ordering, transition to green check. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+179
-136
@@ -86,46 +86,25 @@ export async function GET(req: Request) {
|
||||
});
|
||||
}
|
||||
|
||||
// ── download ── Download PDFs from 5 existing orders
|
||||
// ── download ── Re-download PDFs from all known ePay orders
|
||||
if (step === "download") {
|
||||
const client = await EpayClient.create(username, password);
|
||||
createEpaySession(username, password, await client.getCredits());
|
||||
|
||||
// Known orders from previous test
|
||||
const orderIds = ["9685480", "9685481", "9685482", "9685483", "9685484"];
|
||||
// All known order IDs (MinIO + DB were cleaned, need re-download)
|
||||
// Single orders: mapping unknown — use documentsByCadastral to discover CF
|
||||
const singleOrderIds = ["9685480", "9685481", "9685482", "9685483", "9685484"];
|
||||
// Batch orders: documentsByCadastral maps CF -> doc correctly
|
||||
const batchOrderIds = ["9685487", "9685488"];
|
||||
const allOrderIds = [...singleOrderIds, ...batchOrderIds];
|
||||
|
||||
// Mapping: orderId → nrCadastral (5 orders for 3 parcels)
|
||||
// Orders were for: 345295 (Cluj-Napoca), 63565 (Feleacu), 88089 (Florești)
|
||||
// 5 orders for 3 parcels = some duplicates
|
||||
const orderParcelMap: Record<
|
||||
string,
|
||||
{ nrCadastral: string; judetName: string; uatName: string }
|
||||
> = {
|
||||
"9685480": {
|
||||
nrCadastral: "345295",
|
||||
judetName: "CLUJ",
|
||||
uatName: "Cluj-Napoca",
|
||||
},
|
||||
"9685481": {
|
||||
nrCadastral: "63565",
|
||||
judetName: "CLUJ",
|
||||
uatName: "Feleacu",
|
||||
},
|
||||
"9685482": {
|
||||
nrCadastral: "88089",
|
||||
judetName: "CLUJ",
|
||||
uatName: "Florești",
|
||||
},
|
||||
"9685483": {
|
||||
nrCadastral: "345295",
|
||||
judetName: "CLUJ",
|
||||
uatName: "Cluj-Napoca",
|
||||
},
|
||||
"9685484": {
|
||||
nrCadastral: "63565",
|
||||
judetName: "CLUJ",
|
||||
uatName: "Feleacu",
|
||||
},
|
||||
// UAT name lookup for DB records
|
||||
const uatLookup: Record<string, { uatId: number; uatName: string }> = {
|
||||
"345295": { uatId: 54975, uatName: "Cluj-Napoca" },
|
||||
"63565": { uatId: 57582, uatName: "Feleacu" },
|
||||
"88089": { uatId: 57706, uatName: "Floresti" },
|
||||
"61904": { uatId: 57582, uatName: "Feleacu" },
|
||||
"309952": { uatId: 54975, uatName: "Cluj-Napoca" },
|
||||
};
|
||||
|
||||
const results: Array<{
|
||||
@@ -138,31 +117,18 @@ export async function GET(req: Request) {
|
||||
error?: string;
|
||||
}> = [];
|
||||
|
||||
for (const orderId of orderIds) {
|
||||
const parcelInfo = orderParcelMap[orderId];
|
||||
if (!parcelInfo) {
|
||||
results.push({
|
||||
orderId,
|
||||
nrCadastral: "unknown",
|
||||
status: "error",
|
||||
documents: 0,
|
||||
downloaded: false,
|
||||
error: "No parcel mapping for orderId",
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const orderId of allOrderIds) {
|
||||
try {
|
||||
// Get order status and document info
|
||||
// Get order status — documentsByCadastral maps CF → doc
|
||||
const orderStatus = await client.getOrderStatus(orderId);
|
||||
console.log(
|
||||
`[ancpi-test] Order ${orderId}: status=${orderStatus.status}, docs=${orderStatus.documents.length}`,
|
||||
`[ancpi-test] Order ${orderId}: status=${orderStatus.status}, docs=${orderStatus.documents.length}, byCF=${orderStatus.documentsByCadastral.size}`,
|
||||
);
|
||||
|
||||
if (orderStatus.documents.length === 0) {
|
||||
results.push({
|
||||
orderId,
|
||||
nrCadastral: parcelInfo.nrCadastral,
|
||||
nrCadastral: "unknown",
|
||||
status: orderStatus.status,
|
||||
documents: 0,
|
||||
downloaded: false,
|
||||
@@ -171,94 +137,171 @@ export async function GET(req: Request) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find downloadable PDF document
|
||||
const doc = orderStatus.documents.find(
|
||||
(d) => d.downloadValabil && d.contentType === "application/pdf",
|
||||
);
|
||||
// Process each document by cadastral number from the map
|
||||
if (orderStatus.documentsByCadastral.size > 0) {
|
||||
for (const [cfNumber, doc] of orderStatus.documentsByCadastral) {
|
||||
if (!doc.downloadValabil || doc.contentType !== "application/pdf") {
|
||||
results.push({
|
||||
orderId,
|
||||
nrCadastral: cfNumber,
|
||||
status: orderStatus.status,
|
||||
documents: orderStatus.documents.length,
|
||||
downloaded: false,
|
||||
error: "Document not downloadable or not PDF",
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!doc) {
|
||||
results.push({
|
||||
orderId,
|
||||
nrCadastral: parcelInfo.nrCadastral,
|
||||
status: orderStatus.status,
|
||||
documents: orderStatus.documents.length,
|
||||
downloaded: false,
|
||||
error: "No downloadable PDF found",
|
||||
});
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
// Download the PDF
|
||||
const pdfBuffer = await client.downloadDocument(doc.idDocument, 4);
|
||||
console.log(
|
||||
`[ancpi-test] Downloaded doc ${doc.idDocument} (CF ${cfNumber}): ${pdfBuffer.length} bytes`,
|
||||
);
|
||||
|
||||
// Download the PDF
|
||||
const pdfBuffer = await client.downloadDocument(doc.idDocument, 4);
|
||||
console.log(
|
||||
`[ancpi-test] Downloaded doc ${doc.idDocument}: ${pdfBuffer.length} bytes`,
|
||||
);
|
||||
// Resolve UAT info for this cadastral number
|
||||
const uat = uatLookup[cfNumber];
|
||||
const uatId = uat?.uatId ?? 0;
|
||||
const uatName = uat?.uatName ?? "Necunoscut";
|
||||
|
||||
// Store in MinIO
|
||||
const { path, index } = await storeCfExtract(
|
||||
pdfBuffer,
|
||||
parcelInfo.nrCadastral,
|
||||
{
|
||||
"ancpi-order-id": orderId,
|
||||
"nr-cadastral": parcelInfo.nrCadastral,
|
||||
judet: parcelInfo.judetName,
|
||||
uat: parcelInfo.uatName,
|
||||
"data-document": doc.dataDocument ?? "",
|
||||
stare: orderStatus.status,
|
||||
produs: "EXI_ONLINE",
|
||||
},
|
||||
);
|
||||
// Store in MinIO
|
||||
const { path, index } = await storeCfExtract(
|
||||
pdfBuffer,
|
||||
cfNumber,
|
||||
{
|
||||
"ancpi-order-id": orderId,
|
||||
"nr-cadastral": cfNumber,
|
||||
judet: "CLUJ",
|
||||
uat: uatName,
|
||||
"data-document": doc.dataDocument ?? "",
|
||||
stare: orderStatus.status,
|
||||
produs: "EXI_ONLINE",
|
||||
},
|
||||
);
|
||||
|
||||
// Upsert CfExtract record — find by orderId or create
|
||||
const documentDate = doc.dataDocument
|
||||
? new Date(doc.dataDocument)
|
||||
: new Date();
|
||||
const expiresAt = new Date(documentDate);
|
||||
expiresAt.setDate(expiresAt.getDate() + 30);
|
||||
// Calculate dates
|
||||
const documentDate = doc.dataDocument
|
||||
? new Date(doc.dataDocument)
|
||||
: new Date();
|
||||
const expiresAt = new Date(documentDate);
|
||||
expiresAt.setDate(expiresAt.getDate() + 30);
|
||||
|
||||
// Try to find existing record by orderId
|
||||
const existing = await prisma.cfExtract.findFirst({
|
||||
where: { orderId },
|
||||
});
|
||||
// Always create new records (DB was cleaned)
|
||||
// Increment version for duplicate parcels
|
||||
const maxVersion = await prisma.cfExtract.aggregate({
|
||||
where: { nrCadastral: cfNumber },
|
||||
_max: { version: true },
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
// Update existing record
|
||||
await prisma.cfExtract.update({
|
||||
where: { id: existing.id },
|
||||
data: {
|
||||
status: "completed",
|
||||
epayStatus: orderStatus.status,
|
||||
idDocument: doc.idDocument,
|
||||
documentName: doc.nume,
|
||||
documentDate,
|
||||
minioPath: path,
|
||||
minioIndex: index,
|
||||
completedAt: new Date(),
|
||||
expiresAt,
|
||||
errorMessage: null,
|
||||
},
|
||||
});
|
||||
await prisma.cfExtract.create({
|
||||
data: {
|
||||
orderId,
|
||||
nrCadastral: cfNumber,
|
||||
nrCF: cfNumber,
|
||||
judetIndex: 127,
|
||||
judetName: "CLUJ",
|
||||
uatId,
|
||||
uatName,
|
||||
status: "completed",
|
||||
epayStatus: orderStatus.status,
|
||||
idDocument: doc.idDocument,
|
||||
documentName: doc.nume,
|
||||
documentDate,
|
||||
minioPath: path,
|
||||
minioIndex: index,
|
||||
completedAt: new Date(),
|
||||
expiresAt,
|
||||
version: (maxVersion._max.version ?? 0) + 1,
|
||||
},
|
||||
});
|
||||
|
||||
results.push({
|
||||
orderId,
|
||||
nrCadastral: cfNumber,
|
||||
status: orderStatus.status,
|
||||
documents: orderStatus.documents.length,
|
||||
downloaded: true,
|
||||
minioPath: path,
|
||||
});
|
||||
} catch (dlErr) {
|
||||
const msg = dlErr instanceof Error ? dlErr.message : String(dlErr);
|
||||
console.error(
|
||||
`[ancpi-test] Failed to download doc for CF ${cfNumber} in order ${orderId}:`,
|
||||
msg,
|
||||
);
|
||||
results.push({
|
||||
orderId,
|
||||
nrCadastral: cfNumber,
|
||||
status: "error",
|
||||
documents: orderStatus.documents.length,
|
||||
downloaded: false,
|
||||
error: msg,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Create new record
|
||||
// Fallback: no CF mapping, process first downloadable document
|
||||
const doc = orderStatus.documents.find(
|
||||
(d) => d.downloadValabil && d.contentType === "application/pdf",
|
||||
);
|
||||
if (!doc) {
|
||||
results.push({
|
||||
orderId,
|
||||
nrCadastral: "unknown",
|
||||
status: orderStatus.status,
|
||||
documents: orderStatus.documents.length,
|
||||
downloaded: false,
|
||||
error: "No downloadable PDF and no CF mapping found",
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
// Try to extract CF from document name (e.g. "Extras_Informare_345295.pdf")
|
||||
const cfFromName = doc.nume.match(/(\d{4,})/)?.[1] ?? "unknown";
|
||||
|
||||
const pdfBuffer = await client.downloadDocument(doc.idDocument, 4);
|
||||
console.log(
|
||||
`[ancpi-test] Downloaded doc ${doc.idDocument} (CF from name: ${cfFromName}): ${pdfBuffer.length} bytes`,
|
||||
);
|
||||
|
||||
const uat = uatLookup[cfFromName];
|
||||
const uatId = uat?.uatId ?? 0;
|
||||
const uatName = uat?.uatName ?? "Necunoscut";
|
||||
|
||||
const { path, index } = await storeCfExtract(
|
||||
pdfBuffer,
|
||||
cfFromName,
|
||||
{
|
||||
"ancpi-order-id": orderId,
|
||||
"nr-cadastral": cfFromName,
|
||||
judet: "CLUJ",
|
||||
uat: uatName,
|
||||
"data-document": doc.dataDocument ?? "",
|
||||
stare: orderStatus.status,
|
||||
produs: "EXI_ONLINE",
|
||||
},
|
||||
);
|
||||
|
||||
const documentDate = doc.dataDocument
|
||||
? new Date(doc.dataDocument)
|
||||
: new Date();
|
||||
const expiresAt = new Date(documentDate);
|
||||
expiresAt.setDate(expiresAt.getDate() + 30);
|
||||
|
||||
const maxVersion = await prisma.cfExtract.aggregate({
|
||||
where: { nrCadastral: parcelInfo.nrCadastral },
|
||||
where: { nrCadastral: cfFromName },
|
||||
_max: { version: true },
|
||||
});
|
||||
|
||||
await prisma.cfExtract.create({
|
||||
data: {
|
||||
orderId,
|
||||
nrCadastral: parcelInfo.nrCadastral,
|
||||
nrCF: parcelInfo.nrCadastral,
|
||||
nrCadastral: cfFromName,
|
||||
nrCF: cfFromName,
|
||||
judetIndex: 127,
|
||||
judetName: parcelInfo.judetName,
|
||||
uatId:
|
||||
parcelInfo.uatName === "Cluj-Napoca"
|
||||
? 54975
|
||||
: parcelInfo.uatName === "Feleacu"
|
||||
? 57582
|
||||
: 57706,
|
||||
uatName: parcelInfo.uatName,
|
||||
judetName: "CLUJ",
|
||||
uatId,
|
||||
uatName,
|
||||
status: "completed",
|
||||
epayStatus: orderStatus.status,
|
||||
idDocument: doc.idDocument,
|
||||
@@ -271,16 +314,16 @@ export async function GET(req: Request) {
|
||||
version: (maxVersion._max.version ?? 0) + 1,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
results.push({
|
||||
orderId,
|
||||
nrCadastral: parcelInfo.nrCadastral,
|
||||
status: orderStatus.status,
|
||||
documents: orderStatus.documents.length,
|
||||
downloaded: true,
|
||||
minioPath: path,
|
||||
});
|
||||
results.push({
|
||||
orderId,
|
||||
nrCadastral: cfFromName,
|
||||
status: orderStatus.status,
|
||||
documents: orderStatus.documents.length,
|
||||
downloaded: true,
|
||||
minioPath: path,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
const message =
|
||||
error instanceof Error ? error.message : String(error);
|
||||
@@ -290,7 +333,7 @@ export async function GET(req: Request) {
|
||||
);
|
||||
results.push({
|
||||
orderId,
|
||||
nrCadastral: parcelInfo.nrCadastral,
|
||||
nrCadastral: "unknown",
|
||||
status: "error",
|
||||
documents: 0,
|
||||
downloaded: false,
|
||||
@@ -301,7 +344,7 @@ export async function GET(req: Request) {
|
||||
|
||||
return NextResponse.json({
|
||||
step: "download",
|
||||
totalOrders: orderIds.length,
|
||||
totalOrders: allOrderIds.length,
|
||||
results,
|
||||
summary: {
|
||||
downloaded: results.filter((r) => r.downloaded).length,
|
||||
|
||||
Reference in New Issue
Block a user