149 lines
4.5 KiB
TypeScript
149 lines
4.5 KiB
TypeScript
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
|
|
}
|