reports(SLA): aplica filtro de período (7d/30d/90d) no Convex e inclui período no filename do CSV; admin(alerts): filtros no servidor; alerts: batch de últimos alertas por slugs; filtros persistentes de empresa (localStorage) em relatórios; prisma: Company.contractedHoursPerMonth; smtp: suporte a múltiplos destinatários e timeout opcional
This commit is contained in:
parent
a23b429e4d
commit
384d4411b6
13 changed files with 133 additions and 38 deletions
|
|
@ -21,17 +21,11 @@ export async function GET(request: Request) {
|
|||
const slugs = slugsParam.split(",").map((s) => s.trim()).filter(Boolean)
|
||||
|
||||
const tenantId = session.user.tenantId ?? "tenant-atlas"
|
||||
const result: Record<string, { createdAt: number; usagePct: number; threshold: number } | null> = {}
|
||||
for (const slug of slugs) {
|
||||
try {
|
||||
const last = (await client.query(api.alerts.lastForCompanyBySlug, { tenantId, slug })) as
|
||||
| { createdAt: number; usagePct: number; threshold: number }
|
||||
| null
|
||||
result[slug] = last
|
||||
} catch {
|
||||
result[slug] = null
|
||||
}
|
||||
try {
|
||||
const result = (await client.query(api.alerts.lastForCompaniesBySlugs, { tenantId, slugs })) as Record<string, { createdAt: number; usagePct: number; threshold: number } | null>
|
||||
return NextResponse.json({ items: result })
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch last alerts by slugs", error)
|
||||
return NextResponse.json({ items: {} })
|
||||
}
|
||||
|
||||
return NextResponse.json({ items: result })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ export async function GET(request: Request) {
|
|||
|
||||
const rows: Array<Array<unknown>> = []
|
||||
rows.push(["Relatório", "SLA e produtividade"])
|
||||
rows.push(["Período", range ?? "—"])
|
||||
rows.push(["Período", report.rangeDays ? `Últimos ${report.rangeDays} dias` : (range ?? "90d")])
|
||||
if (companyId) rows.push(["EmpresaId", companyId])
|
||||
rows.push([])
|
||||
|
||||
|
|
@ -89,10 +89,14 @@ export async function GET(request: Request) {
|
|||
}
|
||||
|
||||
const csv = rowsToCsv(rows)
|
||||
const daysLabel = (() => {
|
||||
const raw = (range ?? "90d").replace("d", "")
|
||||
return /^(7|30|90)$/.test(raw) ? `${raw}d` : "all"
|
||||
})()
|
||||
return new NextResponse(csv, {
|
||||
headers: {
|
||||
"Content-Type": "text/csv; charset=UTF-8",
|
||||
"Content-Disposition": `attachment; filename="sla-${tenantId}.csv"`,
|
||||
"Content-Disposition": `attachment; filename="sla-${tenantId}-${daysLabel}.csv"`,
|
||||
"Cache-Control": "no-store",
|
||||
},
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue