47 lines
2.5 KiB
TypeScript
47 lines
2.5 KiB
TypeScript
import type { FastifyInstance } from "fastify";
|
|
import { eq, and } from "drizzle-orm";
|
|
import { assets as assetsTable, integrationMappings as mappingsTable, unifiProductCatalog as catalogTable } from "@sankofa/schema";
|
|
|
|
export async function reportsRoutes(app: FastifyInstance) {
|
|
const db = app.db;
|
|
|
|
app.get<{ Querystring: { org_id?: string; site_id?: string } }>("/bom", async (req, reply) => {
|
|
const orgId = (req.query as { org_id?: string }).org_id ?? app.orgId(req);
|
|
const siteId = (req.query as { site_id?: string }).site_id;
|
|
const assetList = siteId
|
|
? await db.select().from(assetsTable).where(and(eq(assetsTable.orgId, orgId), eq(assetsTable.siteId, siteId)))
|
|
: await db.select().from(assetsTable).where(eq(assetsTable.orgId, orgId));
|
|
const mappings = await db.select().from(mappingsTable).where(eq(mappingsTable.orgId, orgId));
|
|
const catalog = await db.select().from(catalogTable);
|
|
const items = assetList.map((a) => {
|
|
const mapping = mappings.find((m) => m.assetId === a.id && m.provider === "unifi");
|
|
const catalogEntry = mapping ? catalog.find((c) => c.sku === mapping.externalId || c.modelName === mapping.externalId) : null;
|
|
return {
|
|
assetId: a.assetId,
|
|
category: a.category,
|
|
siteId: a.siteId,
|
|
catalogSku: catalogEntry?.sku,
|
|
generation: catalogEntry?.generation,
|
|
supportHorizon: catalogEntry?.supportHorizon,
|
|
};
|
|
});
|
|
return reply.send({ orgId, siteId: siteId ?? null, items });
|
|
});
|
|
|
|
app.get<{ Querystring: { org_id?: string; horizon_months?: string } }>("/support-risk", async (req, reply) => {
|
|
const orgId = (req.query as { org_id?: string }).org_id ?? app.orgId(req);
|
|
const horizonMonths = Math.min(24, Math.max(1, parseInt((req.query as { horizon_months?: string }).horizon_months ?? "12", 10) || 12));
|
|
const catalog = await db.select().from(catalogTable);
|
|
const mappings = await db.select().from(mappingsTable).where(and(eq(mappingsTable.orgId, orgId), eq(mappingsTable.provider, "unifi")));
|
|
const cutoff = new Date();
|
|
cutoff.setMonth(cutoff.getMonth() + horizonMonths);
|
|
const atRisk = catalog.filter((c) => {
|
|
if (!c.eolDate) return false;
|
|
const eol = new Date(c.eolDate);
|
|
return eol <= cutoff;
|
|
});
|
|
const bySku = atRisk.map((c) => ({ sku: c.sku, modelName: c.modelName, generation: c.generation, eolDate: c.eolDate, supportHorizon: c.supportHorizon }));
|
|
return reply.send({ orgId, horizonMonths, atRisk: bySku, deviceCount: mappings.length });
|
|
});
|
|
}
|