diff --git a/src/controllers/transferController.ts b/src/controllers/transferController.ts index b5e5b0d..05b0ca3 100644 --- a/src/controllers/transferController.ts +++ b/src/controllers/transferController.ts @@ -438,3 +438,60 @@ export async function MidsuitPaymentV2(req: Request, res: Response) { return res.status(200).json(result); } } + +export async function paymentStatus(req: Request, res: Response) { + try { + const { c_invoice_id, startdate, enddate } = req.query as any; + if (!c_invoice_id) { + return res.status(400).json({ error: "c_invoice_id is required" }); + } + + const where: any = { c_invoice_id: Number(c_invoice_id) }; + if (startdate || enddate) { + where.created_at = {} as any; + if (startdate) { + const s = new Date(String(startdate)); + where.created_at.gte = s; + } + if (enddate) { + const e = new Date(String(enddate)); + // include the whole end day by setting to end of day if time not provided + if (!String(enddate).includes("T")) { + e.setHours(23, 59, 59, 999); + } + where.created_at.lte = e; + } + } + + const rows = await db.transactions_lines.findMany({ + where: { + ...where, + not: { + c_invoice_id: null, + }, + }, + include: { transactions: true }, + orderBy: { created_at: "desc" }, + }); + + const result = rows.map((r: any) => ({ + id: r.id, + transaction_id: r.transaction_id, + amount: r.amount, + documentno: r.documentno, + c_invoice_id: r.c_invoice_id, + created_at: r.created_at, + tenant_id: r.tenant_id, + transaction_status: r.transactions ? r.transactions.status : null, + transaction_reference: r.transactions ? r.transactions.referenceNo : null, + })); + + return res.json({ count: result.length, data: result }); + } catch (err) { + console.error("paymentStatus error", err); + return res.status(500).json({ + error: "internal_error", + detail: err instanceof Error ? err.message : String(err), + }); + } +} diff --git a/src/lib/dbPools.ts b/src/lib/dbPools.ts index d1950b5..b0100b1 100644 --- a/src/lib/dbPools.ts +++ b/src/lib/dbPools.ts @@ -58,8 +58,6 @@ export async function getPoolForDbId(db_id: string) { max: 10, idleTimeoutMillis: 30000, }); - - // poolCache.set(db_id, { pool, lastUsed: Date.now() }); return pool; } diff --git a/src/lib/gate.ts b/src/lib/gate.ts index 7d351f4..074f81f 100644 --- a/src/lib/gate.ts +++ b/src/lib/gate.ts @@ -1,5 +1,6 @@ import path from "path"; import { pathToFileURL } from "url"; +import fs from "fs"; export async function callGate(opts: { client: string; @@ -12,49 +13,42 @@ export async function callGate(opts: { // candidate paths to try (dev and prod) const candidates = [ - // development / ts-node: src .ts - // path.join(process.cwd(), "src", "lib", "bank", client, `${action}.ts`), - // // compiled production: dist .js - // path.join(process.cwd(), "dist", "lib", "bank", client, `${action}.js`), - // // relative to this file (useful when running from dist/lib) - // path.join(__dirname, "bank", client, `${action}.ts`), + path.join(__dirname, "bank", client, `${action}.ts`), path.join(__dirname, "bank", client, `${action}.js`), - // path.join(__dirname, "..", "lib", "bank", client, `${action}.js`), ]; let lastErr: any = null; + let existsFile = null as any; for (const candidate of candidates) { try { - // prefer require when available (CommonJS build) - // require expects a path without file:// - // but dynamic import needs a file:// URL for absolute paths - let mod: any; - try { - // eslint-disable-next-line @typescript-eslint/no-var-requires - mod = require(candidate); - } catch (reqErr) { - // try dynamic import with file:// URL - const url = pathToFileURL(candidate).href; - // eslint-disable-next-line no-await-in-loop - mod = await import(url); + if (fs.existsSync(candidate)) { + existsFile = candidate; + break; } - - if (!mod || typeof mod.default !== "function") { - throw new Error( - `handler at ${candidate} not found or default export not a function` - ); - } - - // call the handler with (user, session, data) - return await mod.default({ user, session, data }); - } catch (err) { - lastErr = err; - // try next candidate - continue; - } + } catch (ex) {} + } + if (!existsFile) { + throw new Error(`handler not found for gate: ${client}/${action}`); + } + let mod: any; + try { + // eslint-disable-next-line @typescript-eslint/no-var-requires + mod = require(existsFile); + } catch (reqErr) { + // try dynamic import with file:// URL + const url = pathToFileURL(existsFile).href; + // eslint-disable-next-line no-await-in-loop + mod = await import(url); } - throw lastErr || new Error("handler not found for gate"); + if (!mod || typeof mod.default !== "function") { + throw new Error( + `handler at ${existsFile} not found or default export not a function` + ); + } + + // call the handler with (user, session, data) + return await mod.default({ user, session, data }); } export default callGate; diff --git a/src/routes/index.ts b/src/routes/index.ts index a59571f..1c6306b 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -75,6 +75,10 @@ export const setRoutes = () => { router.post("/api/transfer", authMiddleware, async (req, res) => transferController.MidsuitPayment(req, res) ); + // Payment status lookup by c_invoice_id (optionally limit by startdate/enddate) + router.get("/api/va/status", authMiddleware, async (req, res) => + transferController.paymentStatus(req, res) + ); // Signature generation for testing (uses PRIVATE_KEY_PATH file) router.post("/generate-signature", (req, res) => signController.generateSignature(req, res)