sistema-de-chamados/convex/ticketChecklist.ts
esdrasrenan 88a9ef454e feat: checklists em tickets + automações
- Adiciona checklist no ticket (itens obrigatórios/opcionais) e bloqueia encerramento com pendências\n- Cria templates de checklist (globais/por empresa) + tela em /settings/checklists\n- Nova ação de automação: aplicar template de checklist\n- Corrige crash do Select (value vazio), warnings de Dialog e dimensionamento de charts\n- Ajusta SMTP (STARTTLS) e melhora teste de integração
2025-12-13 20:51:47 -03:00

71 lines
2 KiB
TypeScript

import type { Id } from "./_generated/dataModel"
export type TicketChecklistItem = {
id: string
text: string
done: boolean
required?: boolean
templateId?: Id<"ticketChecklistTemplates">
templateItemId?: string
createdAt?: number
createdBy?: Id<"users">
doneAt?: number
doneBy?: Id<"users">
}
export type TicketChecklistTemplateLike = {
_id: Id<"ticketChecklistTemplates">
items: Array<{ id: string; text: string; required?: boolean }>
}
export function normalizeChecklistText(input: string) {
return input.replace(/\r\n/g, "\n").trim()
}
export function checklistBlocksResolution(checklist: TicketChecklistItem[] | null | undefined) {
return (checklist ?? []).some((item) => (item.required ?? true) && item.done !== true)
}
export function applyChecklistTemplateToItems(
existing: TicketChecklistItem[],
template: TicketChecklistTemplateLike,
options: {
now: number
actorId?: Id<"users">
generateId?: () => string
}
) {
const generateId = options.generateId ?? (() => crypto.randomUUID())
const now = options.now
const next = Array.isArray(existing) ? [...existing] : []
const existingKeys = new Set<string>()
for (const item of next) {
if (!item.templateId || !item.templateItemId) continue
existingKeys.add(`${String(item.templateId)}:${item.templateItemId}`)
}
let added = 0
for (const tplItem of template.items ?? []) {
const templateItemId = String(tplItem.id ?? "").trim()
const text = normalizeChecklistText(String(tplItem.text ?? ""))
if (!templateItemId || !text) continue
const key = `${String(template._id)}:${templateItemId}`
if (existingKeys.has(key)) continue
existingKeys.add(key)
next.push({
id: generateId(),
text,
done: false,
required: typeof tplItem.required === "boolean" ? tplItem.required : true,
templateId: template._id,
templateItemId,
createdAt: now,
createdBy: options.actorId,
})
added += 1
}
return { checklist: next, added }
}