/** * Structured PO number generator. * Format: COMPANY_CODE/VESSEL_CODE/PO_ID/FY * - COMPANY_CODE: company.code (fallback "PMS") * - VESSEL_CODE: vessel.code (fallback "GEN") * - PO_ID: globally sequential integer, starting from 200 * - FY: Indian financial year "XXYY" e.g. "2526" for Apr 2025–Mar 2026 * * Example: PMS/HNR1/200/2526 */ import { db } from "@/lib/db"; /** Indian financial year string. April–March cycle. */ function currentFY(): string { const now = new Date(); const month = now.getMonth() + 1; // 1-indexed const year = now.getFullYear(); const fyStart = month >= 4 ? year : year - 1; const fyEnd = fyStart + 1; return `${fyStart}-${String(fyEnd).slice(-2)}`; } /** Find the next sequential PO ID (min 200) by scanning existing structured PO numbers. */ async function nextPoId(): Promise { const pos = await db.purchaseOrder.findMany({ select: { poNumber: true } }); // Floor at 8999 so the first generated ID is 9000, avoiding clashes with // imported POs that retain their original IDs (which typically start from 1). let maxId = 8999; for (const { poNumber } of pos) { const parts = poNumber.split("/"); if (parts.length === 4) { const n = parseInt(parts[2], 10); if (!isNaN(n) && n > maxId) maxId = n; } } return maxId + 1; } /** * Generate a structured PO number. * Pass vesselId and companyId so we can resolve their codes from the DB. * Either may be null — sensible defaults are used. */ export async function generatePoNumber( vesselId?: string | null, companyId?: string | null, ): Promise { const [vessel, company, id] = await Promise.all([ vesselId ? db.vessel .findUnique({ where: { id: vesselId }, select: { code: true } }) : null, companyId ? db.company.findUnique({ where: { id: companyId }, select: { code: true } }) : null, nextPoId(), ]); const companyCode = company?.code ?? "PMS"; const vesselCode = vessel?.code ?? "GEN"; const fy = currentFY(); return `${companyCode}/${vesselCode}/${id}/${fy}`; } /** Parse a structured PO number into its parts. Returns null for old-format numbers. */ export function parsePoNumber(poNumber: string): { companyCode: string; vesselCode: string; poId: number; fy: string; } | null { const parts = poNumber.split("/"); if (parts.length !== 4) return null; const poId = parseInt(parts[2], 10); if (isNaN(poId)) return null; return { companyCode: parts[0], vesselCode: parts[1], poId, fy: parts[3] }; }