sistema-de-chamados/convex/companies.ts

87 lines
2.4 KiB
TypeScript

import { ConvexError, v } from "convex/values";
import { mutation, query } from "./_generated/server";
import { requireStaff } from "./rbac";
function normalizeSlug(input?: string | null): string | undefined {
if (!input) return undefined
const trimmed = input.trim()
if (!trimmed) return undefined
const ascii = trimmed
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.replace(/[\u2013\u2014]/g, "-")
const sanitized = ascii.replace(/[^\w\s-]/g, "").replace(/[_\s]+/g, "-")
const collapsed = sanitized.replace(/-+/g, "-").toLowerCase()
const normalized = collapsed.replace(/^-+|-+$/g, "")
return normalized || undefined
}
export const list = query({
args: { tenantId: v.string(), viewerId: v.id("users") },
handler: async (ctx, { tenantId, viewerId }) => {
await requireStaff(ctx, viewerId, tenantId)
const companies = await ctx.db
.query("companies")
.withIndex("by_tenant", (q) => q.eq("tenantId", tenantId))
.collect()
return companies.map((c) => ({ id: c._id, name: c.name, slug: c.slug }))
},
})
export const ensureProvisioned = mutation({
args: {
tenantId: v.string(),
slug: v.string(),
name: v.string(),
provisioningCode: v.string(),
},
handler: async (ctx, { tenantId, slug, name, provisioningCode }) => {
const normalizedSlug = normalizeSlug(slug)
if (!normalizedSlug) {
throw new ConvexError("Slug inválido")
}
const trimmedName = name.trim()
if (!trimmedName) {
throw new ConvexError("Nome inválido")
}
const existing = await ctx.db
.query("companies")
.withIndex("by_tenant_slug", (q) => q.eq("tenantId", tenantId).eq("slug", normalizedSlug))
.unique()
if (existing) {
if (existing.provisioningCode !== provisioningCode) {
await ctx.db.patch(existing._id, { provisioningCode })
}
return {
id: existing._id,
slug: existing.slug,
name: existing.name,
}
}
const now = Date.now()
const id = await ctx.db.insert("companies", {
tenantId,
name: trimmedName,
slug: normalizedSlug,
provisioningCode,
isAvulso: false,
contractedHoursPerMonth: undefined,
cnpj: undefined,
domain: undefined,
phone: undefined,
description: undefined,
address: undefined,
createdAt: now,
updatedAt: now,
})
return {
id,
slug: normalizedSlug,
name: trimmedName,
}
},
})