From 6bf8310ef6779c6ff0f30f0ef9c523e9c87369fc Mon Sep 17 00:00:00 2001 From: SJCoetz Date: Mon, 3 Aug 2026 17:44:38 +0200 Subject: [PATCH] fix(stock-purchase-send): use DASHBOARD_URL for outcomeUrl (was req.nextUrl.origin) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit \`req.nextUrl.origin\` inside the Next.js process resolves to the container bind address (e.g. \`0.0.0.0:3000\`), which the n8n container can't reach — the v4 workflow's outcome callback fails with \`ECONNREFUSED 0.0.0.0:3000\` and the stock PO gets stuck on \`sending\` because the dashboard never receives the status-flip callback. Mirror the customer-PO route: build the callback URL from \`process.env.DASHBOARD_URL\` (with trailing-slash trim). When \`DASHBOARD_URL\` is unset the outcomeUrl is empty, and the workflow's "outcomeUrl missing" branch fires cleanly. Co-Authored-By: Claude Co-authored-by: Orca --- src/app/api/v1/stock-purchases/[id]/send-email/route.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/app/api/v1/stock-purchases/[id]/send-email/route.ts b/src/app/api/v1/stock-purchases/[id]/send-email/route.ts index f143063..5f1bdac 100644 --- a/src/app/api/v1/stock-purchases/[id]/send-email/route.ts +++ b/src/app/api/v1/stock-purchases/[id]/send-email/route.ts @@ -91,7 +91,12 @@ export async function POST( const { getAdminPocketBase } = await import("@/lib/server/pocketbase-admin"); const adminPb = await getAdminPocketBase(); const pbUrl = process.env.NEXT_PUBLIC_POCKETBASE_URL || process.env.PB_URL || ""; - const dashboardBaseUrl = req.nextUrl.origin; + // Build the callback base URL from DASHBOARD_URL — NOT + // `req.nextUrl.origin`. Inside the Next.js process the origin + // resolves to the bind address (e.g. `0.0.0.0:3000`), which the + // n8n container can't reach. DASHBOARD_URL is the same env var + // the customer-PO route uses for this purpose. + const dashboardBaseUrl = (process.env.DASHBOARD_URL || "").replace(/\/+$/, ""); if (result.failure) { return NextResponse.json(