Reorganiza gestão de usuários e remove dados mock

This commit is contained in:
Esdras Renan 2025-10-18 01:15:15 -03:00
parent 630110bf3a
commit dded6d1927
20 changed files with 1863 additions and 1368 deletions

View file

@ -1,4 +1,3 @@
import { randomBytes } from "@noble/hashes/utils"
import type { Id } from "./_generated/dataModel"
import { mutation } from "./_generated/server"
@ -59,17 +58,6 @@ export const seedDemo = mutation({
}
// Ensure users
function slugify(value: string) {
return value
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.replace(/[^\w\s-]/g, "")
.trim()
.replace(/\s+/g, "-")
.replace(/-+/g, "-")
.toLowerCase();
}
function defaultAvatar(name: string, email: string, role: string) {
const normalizedRole = role.toUpperCase();
if (normalizedRole === "MANAGER") {
@ -78,54 +66,6 @@ export const seedDemo = mutation({
const first = name.split(" ")[0] ?? email;
return `https://avatar.vercel.sh/${encodeURIComponent(first)}`;
}
async function ensureCompany(def: {
name: string;
slug?: string;
cnpj?: string;
domain?: string;
phone?: string;
description?: string;
address?: string;
provisioningCode?: string;
}): Promise<Id<"companies">> {
const slug = def.slug ?? slugify(def.name);
const existing = await ctx.db
.query("companies")
.withIndex("by_tenant_slug", (q) => q.eq("tenantId", tenantId).eq("slug", slug))
.first();
const now = Date.now();
const payload = {
tenantId,
name: def.name,
slug,
provisioningCode: def.provisioningCode ?? existing?.provisioningCode ?? generateCode(),
cnpj: def.cnpj ?? undefined,
domain: def.domain ?? undefined,
phone: def.phone ?? undefined,
description: def.description ?? undefined,
address: def.address ?? undefined,
createdAt: now,
updatedAt: now,
};
if (existing) {
const updates: Record<string, unknown> = {};
if (existing.name !== payload.name) updates.name = payload.name;
if (existing.cnpj !== payload.cnpj) updates.cnpj = payload.cnpj;
if (existing.domain !== payload.domain) updates.domain = payload.domain;
if (existing.phone !== payload.phone) updates.phone = payload.phone;
if (existing.description !== payload.description) updates.description = payload.description;
if (existing.address !== payload.address) updates.address = payload.address;
if (existing.provisioningCode !== payload.provisioningCode) updates.provisioningCode = payload.provisioningCode;
if (Object.keys(updates).length > 0) {
updates.updatedAt = now;
await ctx.db.patch(existing._id, updates);
}
return existing._id;
}
return await ctx.db.insert("companies", payload);
}
async function ensureUser(params: {
name: string;
email: string;
@ -161,42 +101,6 @@ export const seedDemo = mutation({
});
}
const companiesSeed: Array<{
name: string;
slug: string;
cnpj?: string;
domain?: string;
phone?: string;
description?: string;
address?: string;
provisioningCode?: string;
}> = [
{
name: "Atlas Engenharia Digital",
slug: "atlas-engenharia",
cnpj: "12.345.678/0001-90",
domain: "atlasengenharia.com.br",
phone: "+55 11 4002-8922",
description: "Transformação digital para empresas de engenharia e construção.",
address: "Av. Paulista, 1234 - Bela Vista, São Paulo/SP",
},
{
name: "Omni Saúde Integrada",
slug: "omni-saude",
cnpj: "45.678.912/0001-05",
domain: "omnisaude.com.br",
phone: "+55 31 3555-7788",
description: "Rede de clínicas com serviços de telemedicina e prontuário eletrônico.",
address: "Rua da Bahia, 845 - Centro, Belo Horizonte/MG",
},
];
const companyIds = new Map<string, Id<"companies">>();
for (const company of companiesSeed) {
const id = await ensureCompany(company);
companyIds.set(company.slug, id);
}
const adminId = await ensureUser({ name: "Administrador", email: "admin@sistema.dev", role: "ADMIN" });
const staffRoster = [
{ name: "Gabriel Oliveira", email: "gabriel.oliveira@rever.com.br" },
@ -209,62 +113,9 @@ export const seedDemo = mutation({
{ name: "Weslei Magalhães", email: "weslei@rever.com.br" },
];
const staffIds = await Promise.all(
await Promise.all(
staffRoster.map((staff) => ensureUser({ name: staff.name, email: staff.email, role: "AGENT" })),
);
const defaultAssigneeId = staffIds[0] ?? adminId;
const atlasCompanyId = companyIds.get("atlas-engenharia");
const omniCompanyId = companyIds.get("omni-saude");
if (!atlasCompanyId || !omniCompanyId) {
throw new Error("Empresas padrão não foram inicializadas");
}
const atlasManagerId = await ensureUser({
name: "Mariana Andrade",
email: "mariana.andrade@atlasengenharia.com.br",
role: "MANAGER",
companyId: atlasCompanyId,
});
const joaoAtlasId = await ensureUser({
name: "João Pedro Ramos",
email: "joao.ramos@atlasengenharia.com.br",
role: "MANAGER",
companyId: atlasCompanyId,
});
await ensureUser({
name: "Aline Rezende",
email: "aline.rezende@atlasengenharia.com.br",
role: "MANAGER",
companyId: atlasCompanyId,
});
const omniManagerId = await ensureUser({
name: "Fernanda Lima",
email: "fernanda.lima@omnisaude.com.br",
role: "MANAGER",
companyId: omniCompanyId,
});
const ricardoOmniId = await ensureUser({
name: "Ricardo Matos",
email: "ricardo.matos@omnisaude.com.br",
role: "MANAGER",
companyId: omniCompanyId,
});
await ensureUser({
name: "Luciana Prado",
email: "luciana.prado@omnisaude.com.br",
role: "MANAGER",
companyId: omniCompanyId,
});
const clienteDemoId = await ensureUser({
name: "Cliente Demo",
email: "cliente.demo@sistema.dev",
role: "MANAGER",
companyId: omniCompanyId,
});
const templateDefinitions = [
{
@ -301,103 +152,6 @@ export const seedDemo = mutation({
});
}
// Seed a couple of tickets
const now = Date.now();
const newestRef = await ctx.db
.query("tickets")
.withIndex("by_tenant_reference", (q) => q.eq("tenantId", tenantId))
.order("desc")
.take(1);
let ref = newestRef[0]?.reference ?? 41000;
const queue1 = queueChamados._id;
const queue2 = queueLaboratorio._id;
const t1 = await ctx.db.insert("tickets", {
tenantId,
reference: ++ref,
subject: "Erro 500 ao acessar portal do cliente",
summary: "Clientes relatam erro intermitente no portal web",
status: "AWAITING_ATTENDANCE",
priority: "URGENT",
channel: "EMAIL",
queueId: queue1,
requesterId: joaoAtlasId,
assigneeId: defaultAssigneeId,
companyId: atlasCompanyId,
createdAt: now - 1000 * 60 * 60 * 5,
updatedAt: now - 1000 * 60 * 10,
tags: ["portal", "cliente"],
});
await ctx.db.insert("ticketEvents", {
ticketId: t1,
type: "CREATED",
createdAt: now - 1000 * 60 * 60 * 5,
payload: {},
});
await ctx.db.insert("ticketEvents", {
ticketId: t1,
type: "MANAGER_NOTIFIED",
createdAt: now - 1000 * 60 * 60 * 4,
payload: { managerUserId: atlasManagerId },
});
const t2 = await ctx.db.insert("tickets", {
tenantId,
reference: ++ref,
subject: "Integração ERP parada",
summary: "Webhook do ERP retornando timeout",
status: "PENDING",
priority: "HIGH",
channel: "WHATSAPP",
queueId: queue2,
requesterId: ricardoOmniId,
assigneeId: defaultAssigneeId,
companyId: omniCompanyId,
createdAt: now - 1000 * 60 * 60 * 8,
updatedAt: now - 1000 * 60 * 30,
tags: ["Integração", "erp"],
});
await ctx.db.insert("ticketEvents", {
ticketId: t2,
type: "CREATED",
createdAt: now - 1000 * 60 * 60 * 8,
payload: {},
});
await ctx.db.insert("ticketEvents", {
ticketId: t2,
type: "MANAGER_NOTIFIED",
createdAt: now - 1000 * 60 * 60 * 7,
payload: { managerUserId: omniManagerId },
});
const t3 = await ctx.db.insert("tickets", {
tenantId,
reference: ++ref,
subject: "Visita técnica para instalação de roteadores",
summary: "Equipe Omni solicita agenda para instalação de novos pontos de rede",
status: "AWAITING_ATTENDANCE",
priority: "MEDIUM",
channel: "PHONE",
queueId: queueVisitas._id,
requesterId: clienteDemoId,
assigneeId: defaultAssigneeId,
companyId: omniCompanyId,
createdAt: now - 1000 * 60 * 60 * 3,
updatedAt: now - 1000 * 60 * 20,
tags: ["visita", "infraestrutura"],
});
await ctx.db.insert("ticketEvents", {
ticketId: t3,
type: "CREATED",
createdAt: now - 1000 * 60 * 60 * 3,
payload: {},
});
await ctx.db.insert("ticketEvents", {
ticketId: t3,
type: "VISIT_SCHEDULED",
createdAt: now - 1000 * 60 * 15,
payload: { scheduledFor: now + 1000 * 60 * 60 * 24 },
});
// No demo tickets are seeded; rely on real data from the database.
},
});
const generateCode = () => Array.from(randomBytes(32), (b) => b.toString(16).padStart(2, "0")).join("")