feat: dispositivos e ajustes de csat e relatórios
This commit is contained in:
parent
25d2a9b062
commit
e0ef66555d
86 changed files with 5811 additions and 992 deletions
149
convex/ticketFormSettings.ts
Normal file
149
convex/ticketFormSettings.ts
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
import { mutation, query } from "./_generated/server"
|
||||
import type { MutationCtx, QueryCtx } from "./_generated/server"
|
||||
import { ConvexError, v } from "convex/values"
|
||||
import type { Id } from "./_generated/dataModel"
|
||||
|
||||
import { requireAdmin } from "./rbac"
|
||||
|
||||
const KNOWN_TEMPLATES = new Set(["admissao", "desligamento"])
|
||||
const VALID_SCOPES = new Set(["tenant", "company", "user"])
|
||||
|
||||
function normalizeTemplate(input: string) {
|
||||
const normalized = input.trim().toLowerCase()
|
||||
if (!KNOWN_TEMPLATES.has(normalized)) {
|
||||
throw new ConvexError("Template desconhecido")
|
||||
}
|
||||
return normalized
|
||||
}
|
||||
|
||||
function normalizeScope(input: string) {
|
||||
const normalized = input.trim().toLowerCase()
|
||||
if (!VALID_SCOPES.has(normalized)) {
|
||||
throw new ConvexError("Escopo inválido")
|
||||
}
|
||||
return normalized
|
||||
}
|
||||
|
||||
export const list = query({
|
||||
args: {
|
||||
tenantId: v.string(),
|
||||
viewerId: v.id("users"),
|
||||
template: v.optional(v.string()),
|
||||
},
|
||||
handler: async (ctx, { tenantId, viewerId, template }) => {
|
||||
await requireAdmin(ctx, viewerId, tenantId)
|
||||
const normalizedTemplate = template ? normalizeTemplate(template) : null
|
||||
const settings = await ctx.db
|
||||
.query("ticketFormSettings")
|
||||
.withIndex("by_tenant", (q) => q.eq("tenantId", tenantId))
|
||||
.collect()
|
||||
return settings
|
||||
.filter((setting) => !normalizedTemplate || setting.template === normalizedTemplate)
|
||||
.map((setting) => ({
|
||||
id: setting._id,
|
||||
template: setting.template,
|
||||
scope: setting.scope,
|
||||
companyId: setting.companyId ?? null,
|
||||
userId: setting.userId ?? null,
|
||||
enabled: setting.enabled,
|
||||
createdAt: setting.createdAt,
|
||||
updatedAt: setting.updatedAt,
|
||||
actorId: setting.actorId ?? null,
|
||||
}))
|
||||
},
|
||||
})
|
||||
|
||||
export const upsert = mutation({
|
||||
args: {
|
||||
tenantId: v.string(),
|
||||
actorId: v.id("users"),
|
||||
template: v.string(),
|
||||
scope: v.string(),
|
||||
companyId: v.optional(v.id("companies")),
|
||||
userId: v.optional(v.id("users")),
|
||||
enabled: v.boolean(),
|
||||
},
|
||||
handler: async (ctx, { tenantId, actorId, template, scope, companyId, userId, enabled }) => {
|
||||
await requireAdmin(ctx, actorId, tenantId)
|
||||
const normalizedTemplate = normalizeTemplate(template)
|
||||
const normalizedScope = normalizeScope(scope)
|
||||
|
||||
if (normalizedScope === "company" && !companyId) {
|
||||
throw new ConvexError("Informe a empresa para configurar o template")
|
||||
}
|
||||
if (normalizedScope === "user" && !userId) {
|
||||
throw new ConvexError("Informe o usuário para configurar o template")
|
||||
}
|
||||
if (normalizedScope === "tenant") {
|
||||
if (companyId || userId) {
|
||||
throw new ConvexError("Escopo global não aceita empresa ou usuário")
|
||||
}
|
||||
}
|
||||
|
||||
const existing = await findExisting(ctx, tenantId, normalizedTemplate, normalizedScope, companyId, userId)
|
||||
const now = Date.now()
|
||||
if (existing) {
|
||||
await ctx.db.patch(existing._id, {
|
||||
enabled,
|
||||
updatedAt: now,
|
||||
actorId,
|
||||
})
|
||||
return existing._id
|
||||
}
|
||||
|
||||
const id = await ctx.db.insert("ticketFormSettings", {
|
||||
tenantId,
|
||||
template: normalizedTemplate,
|
||||
scope: normalizedScope,
|
||||
companyId: normalizedScope === "company" ? (companyId as Id<"companies">) : undefined,
|
||||
userId: normalizedScope === "user" ? (userId as Id<"users">) : undefined,
|
||||
enabled,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
actorId,
|
||||
})
|
||||
return id
|
||||
},
|
||||
})
|
||||
|
||||
export const remove = mutation({
|
||||
args: {
|
||||
tenantId: v.string(),
|
||||
actorId: v.id("users"),
|
||||
settingId: v.id("ticketFormSettings"),
|
||||
},
|
||||
handler: async (ctx, { tenantId, actorId, settingId }) => {
|
||||
await requireAdmin(ctx, actorId, tenantId)
|
||||
const setting = await ctx.db.get(settingId)
|
||||
if (!setting || setting.tenantId !== tenantId) {
|
||||
throw new ConvexError("Configuração não encontrada")
|
||||
}
|
||||
await ctx.db.delete(settingId)
|
||||
return { ok: true }
|
||||
},
|
||||
})
|
||||
|
||||
async function findExisting(
|
||||
ctx: MutationCtx | QueryCtx,
|
||||
tenantId: string,
|
||||
template: string,
|
||||
scope: string,
|
||||
companyId?: Id<"companies">,
|
||||
userId?: Id<"users">,
|
||||
) {
|
||||
const candidates = await ctx.db
|
||||
.query("ticketFormSettings")
|
||||
.withIndex("by_tenant_template_scope", (q) => q.eq("tenantId", tenantId).eq("template", template).eq("scope", scope))
|
||||
.collect()
|
||||
|
||||
return candidates.find((setting) => {
|
||||
if (scope === "tenant") return true
|
||||
if (scope === "company") {
|
||||
return setting.companyId && companyId && String(setting.companyId) === String(companyId)
|
||||
}
|
||||
if (scope === "user") {
|
||||
return setting.userId && userId && String(setting.userId) === String(userId)
|
||||
}
|
||||
return false
|
||||
}) ?? null
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue