quest-vorteq/src/services/available-coils.ts

71 lines
2 KiB
TypeScript
Raw Normal View History

/**
* 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<AvailableCoilItem[]> {
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<EpicorCoilRow[]>(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 [];
}
}