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
|
|
@ -150,6 +150,36 @@ export const lastForCompanyBySlug = query({
|
|||
},
|
||||
})
|
||||
|
||||
export const lastForCompaniesBySlugs = query({
|
||||
args: { tenantId: v.string(), slugs: v.array(v.string()) },
|
||||
handler: async (ctx, { tenantId, slugs }) => {
|
||||
const result: Record<string, { createdAt: number; usagePct: number; threshold: number } | null> = {}
|
||||
// Fetch all alerts once for the tenant
|
||||
const alerts = await ctx.db
|
||||
.query("alerts")
|
||||
.withIndex("by_tenant", (q) => q.eq("tenantId", tenantId))
|
||||
.collect()
|
||||
for (const slug of slugs) {
|
||||
const company = await ctx.db
|
||||
.query("companies")
|
||||
.withIndex("by_tenant_slug", (q) => q.eq("tenantId", tenantId).eq("slug", slug))
|
||||
.first()
|
||||
if (!company) {
|
||||
result[slug] = null
|
||||
continue
|
||||
}
|
||||
const matches = alerts.filter((a) => a.companyId === company._id)
|
||||
if (matches.length === 0) {
|
||||
result[slug] = null
|
||||
continue
|
||||
}
|
||||
const last = matches.sort((a, b) => b.createdAt - a.createdAt)[0]
|
||||
result[slug] = { createdAt: last.createdAt, usagePct: last.usagePct, threshold: last.threshold }
|
||||
}
|
||||
return result
|
||||
},
|
||||
})
|
||||
|
||||
export const tenantIds = query({
|
||||
args: {},
|
||||
handler: async (ctx) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue