/** * Available Coils Service * * Queries Epicor for coils available for allocation to a specific job. * The legacy system used CoilAllocation.sql with JobNum + DBNAME params. * This queries PartLot/PartBin data filtered by job number. */ import { execQuery, getPortalDbName } from '@/lib/epicor'; import type { AvailableCoilItem } from '@/types/requests'; type EpicorCoilRow = { PartNum: string; LotNum: string | null; CoilNum: string | null; OnHandQty: number; Plant: string | null; Warehouse: string | null; }; /** * Get available coils for allocation to a specific job. * * This is a best-effort query — the legacy CoilAllocation.sql may not be available * as a view in the current Epicor database. If the query fails, we return an empty * array gracefully. */ export async function getAvailableCoils( custId: string, dbName: string, jobNumber: string ): Promise { try { // Try the portal coil allocation view/query // Legacy used: SELECT ... FROM CoilAllocation WHERE JobNum = @JobNum AND DBNAME = @DBNAME const query = ` SELECT PartNum, LotNum, CoilNum, OnHandQty, Plant, WarehouseCode AS Warehouse FROM portal_CoilAllocation WHERE JobNum = @JobNum ORDER BY PartNum, LotNum, CoilNum `; const rows = await execQuery(query, { JobNum: jobNumber, }); return rows.map((row) => ({ part_num: row.PartNum?.trim() ?? '', lot_num: row.LotNum?.trim() || null, coil_number: row.CoilNum?.trim() || null, on_hand_qty: Number(row.OnHandQty ?? 0), plant: row.Plant?.trim() || null, warehouse: row.Warehouse?.trim() || null, })); } catch (error) { // The coil allocation view may not exist yet — fail gracefully console.warn( '[available-coils] Failed to query coil allocation data. ' + 'The portal_CoilAllocation view may need to be created in Epicor.', error instanceof Error ? error.message : error ); return []; } }