feat: adiciona SLA por empresa e modal de exclusao de automacoes
Some checks failed
Some checks failed
## SLA por Empresa - Adiciona tabela companySlaSettings no schema - Cria convex/companySlas.ts com queries e mutations - Modifica resolveTicketSlaSnapshot para verificar SLA da empresa primeiro - Fallback: empresa > categoria > padrao ## Modal de Exclusao de Automacoes - Substitui confirm() nativo por Dialog gracioso - Segue padrao do delete-ticket-dialog 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
b3fcbcc682
commit
33f0cc2e13
4 changed files with 404 additions and 22 deletions
|
|
@ -272,25 +272,74 @@ async function resolveTicketSlaSnapshot(
|
|||
ctx: AnyCtx,
|
||||
tenantId: string,
|
||||
category: Doc<"ticketCategories"> | null,
|
||||
priority: string
|
||||
priority: string,
|
||||
companyId?: Id<"companies"> | null
|
||||
): Promise<TicketSlaSnapshot | null> {
|
||||
if (!category) {
|
||||
return null;
|
||||
}
|
||||
const normalizedPriority = priority.trim().toUpperCase();
|
||||
const rule =
|
||||
(await ctx.db
|
||||
.query("categorySlaSettings")
|
||||
.withIndex("by_tenant_category_priority", (q) =>
|
||||
q.eq("tenantId", tenantId).eq("categoryId", category._id).eq("priority", normalizedPriority)
|
||||
|
||||
// 1. Primeiro, tenta buscar SLA específico da empresa (se companyId foi informado)
|
||||
let rule: {
|
||||
responseTargetMinutes?: number;
|
||||
responseMode?: string;
|
||||
solutionTargetMinutes?: number;
|
||||
solutionMode?: string;
|
||||
alertThreshold?: number;
|
||||
pauseStatuses?: string[];
|
||||
} | null = null;
|
||||
|
||||
if (companyId) {
|
||||
// Tenta: empresa + categoria + prioridade
|
||||
rule = await ctx.db
|
||||
.query("companySlaSettings")
|
||||
.withIndex("by_tenant_company_category_priority", (q) =>
|
||||
q.eq("tenantId", tenantId).eq("companyId", companyId).eq("categoryId", category._id).eq("priority", normalizedPriority)
|
||||
)
|
||||
.first()) ??
|
||||
(await ctx.db
|
||||
.query("categorySlaSettings")
|
||||
.withIndex("by_tenant_category_priority", (q) =>
|
||||
q.eq("tenantId", tenantId).eq("categoryId", category._id).eq("priority", "DEFAULT")
|
||||
)
|
||||
.first());
|
||||
.first();
|
||||
|
||||
// Fallback: empresa + categoria + DEFAULT
|
||||
if (!rule) {
|
||||
rule = await ctx.db
|
||||
.query("companySlaSettings")
|
||||
.withIndex("by_tenant_company_category_priority", (q) =>
|
||||
q.eq("tenantId", tenantId).eq("companyId", companyId).eq("categoryId", category._id).eq("priority", "DEFAULT")
|
||||
)
|
||||
.first();
|
||||
}
|
||||
|
||||
// Fallback: empresa + todas categorias (categoryId null) + prioridade
|
||||
if (!rule) {
|
||||
const allCategoriesRules = await ctx.db
|
||||
.query("companySlaSettings")
|
||||
.withIndex("by_tenant_company", (q) => q.eq("tenantId", tenantId).eq("companyId", companyId))
|
||||
.filter((q) => q.eq(q.field("categoryId"), undefined))
|
||||
.take(10);
|
||||
|
||||
rule = allCategoriesRules.find((r) => r.priority === normalizedPriority) ??
|
||||
allCategoriesRules.find((r) => r.priority === "DEFAULT") ??
|
||||
null;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Se não encontrou SLA da empresa, usa SLA da categoria (comportamento padrão)
|
||||
if (!rule) {
|
||||
rule =
|
||||
(await ctx.db
|
||||
.query("categorySlaSettings")
|
||||
.withIndex("by_tenant_category_priority", (q) =>
|
||||
q.eq("tenantId", tenantId).eq("categoryId", category._id).eq("priority", normalizedPriority)
|
||||
)
|
||||
.first()) ??
|
||||
(await ctx.db
|
||||
.query("categorySlaSettings")
|
||||
.withIndex("by_tenant_category_priority", (q) =>
|
||||
q.eq("tenantId", tenantId).eq("categoryId", category._id).eq("priority", "DEFAULT")
|
||||
)
|
||||
.first());
|
||||
}
|
||||
|
||||
if (!rule) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -2325,7 +2374,7 @@ export const create = mutation({
|
|||
avatarUrl: requester.avatarUrl ?? undefined,
|
||||
teams: requester.teams ?? undefined,
|
||||
}
|
||||
const slaSnapshot = await resolveTicketSlaSnapshot(ctx, args.tenantId, category as Doc<"ticketCategories"> | null, args.priority)
|
||||
// Resolve a empresa primeiro para poder verificar SLA específico
|
||||
let companyDoc = requester.companyId ? (await ctx.db.get(requester.companyId)) : null
|
||||
if (!companyDoc && machineDoc?.companyId) {
|
||||
const candidateCompany = await ctx.db.get(machineDoc.companyId)
|
||||
|
|
@ -2337,6 +2386,8 @@ export const create = mutation({
|
|||
? { name: companyDoc.name, slug: companyDoc.slug, isAvulso: companyDoc.isAvulso ?? undefined }
|
||||
: undefined
|
||||
const resolvedCompanyId = companyDoc?._id ?? requester.companyId ?? undefined
|
||||
// Resolve SLA passando companyId para verificar regras específicas da empresa
|
||||
const slaSnapshot = await resolveTicketSlaSnapshot(ctx, args.tenantId, category as Doc<"ticketCategories"> | null, args.priority, resolvedCompanyId)
|
||||
|
||||
let checklist = manualChecklist
|
||||
for (const templateId of args.checklistTemplateIds ?? []) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue