feat: machine reports with filters and hours
This commit is contained in:
parent
6938bebdbb
commit
82875a2252
2 changed files with 403 additions and 11 deletions
|
|
@ -1335,7 +1335,16 @@ export async function ticketsByMachineAndCategoryHandler(
|
|||
viewerId,
|
||||
range,
|
||||
companyId,
|
||||
}: { tenantId: string; viewerId: Id<"users">; range?: string; companyId?: Id<"companies"> }
|
||||
machineId,
|
||||
userId,
|
||||
}: {
|
||||
tenantId: string
|
||||
viewerId: Id<"users">
|
||||
range?: string
|
||||
companyId?: Id<"companies">
|
||||
machineId?: Id<"machines">
|
||||
userId?: Id<"users">
|
||||
}
|
||||
) {
|
||||
const viewer = await requireStaff(ctx, viewerId, tenantId)
|
||||
const days = range === "7d" ? 7 : range === "30d" ? 30 : 90
|
||||
|
|
@ -1372,8 +1381,11 @@ export async function ticketsByMachineAndCategoryHandler(
|
|||
const hasMachine = Boolean(ticket.machineId) || Boolean(ticket.machineSnapshot)
|
||||
if (!hasMachine) continue
|
||||
|
||||
if (machineId && ticket.machineId !== machineId) continue
|
||||
if (userId && ticket.requesterId !== userId) continue
|
||||
|
||||
const date = formatDateKey(createdAt)
|
||||
const machineId = (ticket.machineId ?? null) as Id<"machines"> | null
|
||||
const machineIdValue = (ticket.machineId ?? null) as Id<"machines"> | null
|
||||
const machineSnapshot = (ticket.machineSnapshot ?? null) as
|
||||
| {
|
||||
hostname?: string | null
|
||||
|
|
@ -1414,19 +1426,19 @@ export async function ticketsByMachineAndCategoryHandler(
|
|||
|
||||
const key = [
|
||||
date,
|
||||
machineId ? String(machineId) : "null",
|
||||
machineIdValue ? String(machineIdValue) : "null",
|
||||
machineHostname ?? "",
|
||||
rawCategoryId ?? "uncategorized",
|
||||
companyIdValue ? String(companyIdValue) : "null",
|
||||
].join("|")
|
||||
|
||||
const existing = aggregated.get(key)
|
||||
if (existing) {
|
||||
existing.total += 1
|
||||
} else {
|
||||
aggregated.set(key, {
|
||||
date,
|
||||
machineId,
|
||||
const existing = aggregated.get(key)
|
||||
if (existing) {
|
||||
existing.total += 1
|
||||
} else {
|
||||
aggregated.set(key, {
|
||||
date,
|
||||
machineId: machineIdValue,
|
||||
machineHostname,
|
||||
companyId: companyIdValue,
|
||||
companyName,
|
||||
|
|
@ -1457,10 +1469,142 @@ export const ticketsByMachineAndCategory = query({
|
|||
viewerId: v.id("users"),
|
||||
range: v.optional(v.string()),
|
||||
companyId: v.optional(v.id("companies")),
|
||||
machineId: v.optional(v.id("machines")),
|
||||
userId: v.optional(v.id("users")),
|
||||
},
|
||||
handler: ticketsByMachineAndCategoryHandler,
|
||||
})
|
||||
|
||||
type MachineHoursEntry = {
|
||||
machineId: Id<"machines">
|
||||
machineHostname: string | null
|
||||
companyId: Id<"companies"> | null
|
||||
companyName: string | null
|
||||
internalMs: number
|
||||
externalMs: number
|
||||
totalMs: number
|
||||
}
|
||||
|
||||
export async function hoursByMachineHandler(
|
||||
ctx: QueryCtx,
|
||||
{
|
||||
tenantId,
|
||||
viewerId,
|
||||
range,
|
||||
companyId,
|
||||
machineId,
|
||||
userId,
|
||||
}: {
|
||||
tenantId: string
|
||||
viewerId: Id<"users">
|
||||
range?: string
|
||||
companyId?: Id<"companies">
|
||||
machineId?: Id<"machines">
|
||||
userId?: Id<"users">
|
||||
}
|
||||
) {
|
||||
const viewer = await requireStaff(ctx, viewerId, tenantId)
|
||||
const tickets = await fetchScopedTickets(ctx, tenantId, viewer)
|
||||
|
||||
const days = range === "7d" ? 7 : range === "30d" ? 30 : 90
|
||||
const end = new Date()
|
||||
end.setUTCHours(0, 0, 0, 0)
|
||||
const endMs = end.getTime() + ONE_DAY_MS
|
||||
const startMs = endMs - days * ONE_DAY_MS
|
||||
|
||||
const machinesById = new Map<string, Doc<"machines"> | null>()
|
||||
const companiesById = new Map<string, Doc<"companies"> | null>()
|
||||
|
||||
const map = new Map<string, MachineHoursEntry>()
|
||||
|
||||
for (const t of tickets) {
|
||||
if (t.updatedAt < startMs || t.updatedAt >= endMs) continue
|
||||
if (companyId && t.companyId && t.companyId !== companyId) continue
|
||||
if (machineId && t.machineId !== machineId) continue
|
||||
if (userId && t.requesterId !== userId) continue
|
||||
|
||||
const machineIdValue = (t.machineId ?? null) as Id<"machines"> | null
|
||||
if (!machineIdValue) continue
|
||||
|
||||
const key = String(machineIdValue)
|
||||
|
||||
let acc = map.get(key)
|
||||
if (!acc) {
|
||||
let machineDoc = machinesById.get(key)
|
||||
if (machineDoc === undefined) {
|
||||
machineDoc = (await ctx.db.get(machineIdValue)) as Doc<"machines"> | null
|
||||
machinesById.set(key, machineDoc ?? null)
|
||||
}
|
||||
|
||||
const snapshot = (t.machineSnapshot ?? null) as { hostname?: string | null } | null
|
||||
const machineHostname =
|
||||
typeof machineDoc?.hostname === "string" && machineDoc.hostname.trim().length > 0
|
||||
? machineDoc.hostname.trim()
|
||||
: snapshot?.hostname && snapshot.hostname.trim().length > 0
|
||||
? snapshot.hostname.trim()
|
||||
: null
|
||||
|
||||
const companyIdValue = (t.companyId ??
|
||||
(machineDoc?.companyId as Id<"companies"> | undefined) ??
|
||||
null) as Id<"companies"> | null
|
||||
|
||||
let companyName: string | null = null
|
||||
if (companyIdValue) {
|
||||
const companyKey = String(companyIdValue)
|
||||
let companyDoc = companiesById.get(companyKey)
|
||||
if (companyDoc === undefined) {
|
||||
companyDoc = (await ctx.db.get(companyIdValue)) as Doc<"companies"> | null
|
||||
companiesById.set(companyKey, companyDoc ?? null)
|
||||
}
|
||||
if (companyDoc?.name && companyDoc.name.trim().length > 0) {
|
||||
companyName = companyDoc.name.trim()
|
||||
}
|
||||
}
|
||||
|
||||
acc = {
|
||||
machineId: machineIdValue,
|
||||
machineHostname,
|
||||
companyId: companyIdValue,
|
||||
companyName,
|
||||
internalMs: 0,
|
||||
externalMs: 0,
|
||||
totalMs: 0,
|
||||
}
|
||||
map.set(key, acc)
|
||||
}
|
||||
|
||||
const internal = (t.internalWorkedMs ?? 0) as number
|
||||
const external = (t.externalWorkedMs ?? 0) as number
|
||||
acc.internalMs += internal
|
||||
acc.externalMs += external
|
||||
acc.totalMs += internal + external
|
||||
}
|
||||
|
||||
const items = Array.from(map.values()).sort((a, b) => {
|
||||
if (b.totalMs !== a.totalMs) return b.totalMs - a.totalMs
|
||||
const hostA = (a.machineHostname ?? "").toLowerCase()
|
||||
const hostB = (b.machineHostname ?? "").toLowerCase()
|
||||
return hostA.localeCompare(hostB)
|
||||
})
|
||||
|
||||
return {
|
||||
rangeDays: days,
|
||||
items,
|
||||
}
|
||||
}
|
||||
|
||||
export const hoursByMachine = query({
|
||||
args: {
|
||||
tenantId: v.string(),
|
||||
viewerId: v.id("users"),
|
||||
range: v.optional(v.string()),
|
||||
companyId: v.optional(v.id("companies")),
|
||||
machineId: v.optional(v.id("machines")),
|
||||
userId: v.optional(v.id("users")),
|
||||
},
|
||||
handler: hoursByMachineHandler,
|
||||
})
|
||||
|
||||
export async function hoursByClientHandler(
|
||||
ctx: QueryCtx,
|
||||
{ tenantId, viewerId, range }: { tenantId: string; viewerId: Id<"users">; range?: string }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue