87 lines
2.4 KiB
TypeScript
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,
|
|
}
|
|
},
|
|
})
|