fix(ancpi): find NEW orderId after submit, track known IDs in queue

submitOrder now captures the previous orderId BEFORE submitting, then
searches for a NEW orderId that isn't in the knownOrderIds set. Queue
passes knownOrderIds between sequential items to prevent duplicate
orderId assignment (unique constraint violation).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
AI Assistant
2026-03-23 02:43:21 +02:00
parent c452bd9fb7
commit 6c60572a3e
2 changed files with 67 additions and 11 deletions
+18 -8
View File
@@ -124,10 +124,14 @@ async function processQueue(): Promise<void> {
if (g.__epayQueueProcessing) return; // already running
g.__epayQueueProcessing = true;
// Track all orderIds from this batch to avoid duplicates
const knownOrderIds = new Set<string>();
try {
while (g.__epayQueue && g.__epayQueue.length > 0) {
const item = g.__epayQueue.shift()!;
await processItem(item);
const orderId = await processItem(item, knownOrderIds);
if (orderId) knownOrderIds.add(orderId);
}
} finally {
g.__epayQueueProcessing = false;
@@ -145,7 +149,10 @@ async function updateStatus(
});
}
async function processItem(item: QueueItem): Promise<void> {
async function processItem(
item: QueueItem,
knownOrderIds: Set<string>,
): Promise<string | null> {
const { extractId, input } = item;
try {
@@ -155,7 +162,7 @@ async function processItem(item: QueueItem): Promise<void> {
await updateStatus(extractId, "failed", {
errorMessage: "Nu ești conectat la ePay.",
});
return;
return null;
}
const client = await EpayClient.create(creds.username, creds.password);
@@ -167,7 +174,7 @@ async function processItem(item: QueueItem): Promise<void> {
await updateStatus(extractId, "failed", {
errorMessage: `Credite insuficiente: ${credits}. Reîncărcați contul pe epay.ancpi.ro.`,
});
return;
return null;
}
// Step 2: Add to cart
@@ -216,10 +223,10 @@ async function processItem(item: QueueItem): Promise<void> {
await updateStatus(extractId, "failed", {
errorMessage: "Salvarea metadatelor în ePay a eșuat.",
});
return;
return null;
}
const orderId = await client.submitOrder();
const orderId = await client.submitOrder(knownOrderIds);
await updateStatus(extractId, "polling", { orderId });
@@ -242,7 +249,7 @@ async function processItem(item: QueueItem): Promise<void> {
epayStatus: finalStatus.status,
errorMessage: `Comanda ${finalStatus.status.toLowerCase()}.`,
});
return;
return null;
}
// Step 6: Download PDF
@@ -254,7 +261,7 @@ async function processItem(item: QueueItem): Promise<void> {
epayStatus: finalStatus.status,
errorMessage: "Nu s-a găsit documentul PDF în comanda finalizată.",
});
return;
return null;
}
await updateStatus(extractId, "downloading", {
@@ -303,9 +310,12 @@ async function processItem(item: QueueItem): Promise<void> {
console.log(
`[epay-queue] Completed: ${input.nrCadastral}${path} (credits: ${newCredits})`,
);
return orderId;
} catch (error) {
const message = error instanceof Error ? error.message : "Eroare necunoscută";
console.error(`[epay-queue] Failed: ${input.nrCadastral}:`, message);
await updateStatus(extractId, "failed", { errorMessage: message });
return null;
}
}