Initial SeConectai briefing system
This commit is contained in:
@@ -0,0 +1 @@
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,149 @@
|
||||
CREATE TYPE "Papel" AS ENUM ('CLIENTE', 'ADMIN');
|
||||
CREATE TYPE "TipoPessoa" AS ENUM ('PF', 'PJ');
|
||||
CREATE TYPE "TipoPergunta" AS ENUM ('TEXTAREA', 'RADIO', 'CHECKBOX', 'ANEXO');
|
||||
CREATE TYPE "StatusBriefing" AS ENUM ('RASCUNHO', 'ENVIADO', 'EM_ANALISE', 'CONCLUIDO');
|
||||
|
||||
CREATE TABLE "users" (
|
||||
"id" TEXT NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"senhaHash" TEXT NOT NULL,
|
||||
"papel" "Papel" NOT NULL DEFAULT 'CLIENTE',
|
||||
"criadoEm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"atualizadoEm" TIMESTAMP(3) NOT NULL,
|
||||
CONSTRAINT "users_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "clientes" (
|
||||
"id" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"nomeCompleto" TEXT NOT NULL,
|
||||
"cpfCifrado" TEXT NOT NULL,
|
||||
"cpfHash" TEXT NOT NULL,
|
||||
"whatsapp" TEXT NOT NULL,
|
||||
"tipo" "TipoPessoa" NOT NULL DEFAULT 'PF',
|
||||
"razaoSocial" TEXT,
|
||||
"cnpj" TEXT,
|
||||
"cep" TEXT,
|
||||
"logradouro" TEXT,
|
||||
"numero" TEXT,
|
||||
"complemento" TEXT,
|
||||
"bairro" TEXT,
|
||||
"cidade" TEXT,
|
||||
"uf" TEXT,
|
||||
"lgpdAceiteEm" TIMESTAMP(3) NOT NULL,
|
||||
"criadoEm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"atualizadoEm" TIMESTAMP(3) NOT NULL,
|
||||
CONSTRAINT "clientes_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "secoes" (
|
||||
"id" TEXT NOT NULL,
|
||||
"ordem" INTEGER NOT NULL,
|
||||
"titulo" TEXT NOT NULL,
|
||||
"descricao" TEXT,
|
||||
"ativo" BOOLEAN NOT NULL DEFAULT true,
|
||||
"criadoEm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"atualizadoEm" TIMESTAMP(3) NOT NULL,
|
||||
CONSTRAINT "secoes_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "perguntas" (
|
||||
"id" TEXT NOT NULL,
|
||||
"secaoId" TEXT NOT NULL,
|
||||
"ordem" INTEGER NOT NULL,
|
||||
"rotulo" TEXT NOT NULL,
|
||||
"dica" TEXT,
|
||||
"tipo" "TipoPergunta" NOT NULL,
|
||||
"opcoes" JSONB NOT NULL,
|
||||
"obrigatoria" BOOLEAN NOT NULL DEFAULT false,
|
||||
"permiteComplemento" BOOLEAN NOT NULL DEFAULT false,
|
||||
"ativo" BOOLEAN NOT NULL DEFAULT true,
|
||||
"criadoEm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"atualizadoEm" TIMESTAMP(3) NOT NULL,
|
||||
CONSTRAINT "perguntas_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "ajudas" (
|
||||
"id" TEXT NOT NULL,
|
||||
"perguntaId" TEXT NOT NULL,
|
||||
"oQueResponder" TEXT NOT NULL,
|
||||
"porQuePerguntamos" TEXT NOT NULL,
|
||||
"miniExemplo" TEXT NOT NULL,
|
||||
"criadoEm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"atualizadoEm" TIMESTAMP(3) NOT NULL,
|
||||
CONSTRAINT "ajudas_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "briefings" (
|
||||
"id" TEXT NOT NULL,
|
||||
"clienteId" TEXT NOT NULL,
|
||||
"titulo" TEXT NOT NULL,
|
||||
"status" "StatusBriefing" NOT NULL DEFAULT 'RASCUNHO',
|
||||
"confirmadoEm" TIMESTAMP(3),
|
||||
"enviadoEm" TIMESTAMP(3),
|
||||
"criadoEm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"atualizadoEm" TIMESTAMP(3) NOT NULL,
|
||||
CONSTRAINT "briefings_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "respostas" (
|
||||
"id" TEXT NOT NULL,
|
||||
"briefingId" TEXT NOT NULL,
|
||||
"perguntaId" TEXT NOT NULL,
|
||||
"texto" TEXT,
|
||||
"complemento" TEXT,
|
||||
"selecionadas" JSONB,
|
||||
"criadoEm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"atualizadoEm" TIMESTAMP(3) NOT NULL,
|
||||
CONSTRAINT "respostas_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "anexos" (
|
||||
"id" TEXT NOT NULL,
|
||||
"briefingId" TEXT NOT NULL,
|
||||
"perguntaId" TEXT NOT NULL,
|
||||
"nomeOriginal" TEXT NOT NULL,
|
||||
"caminho" TEXT NOT NULL,
|
||||
"mime" TEXT NOT NULL,
|
||||
"tamanho" INTEGER NOT NULL,
|
||||
"criadoEm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT "anexos_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "password_reset_tokens" (
|
||||
"id" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"tokenHash" TEXT NOT NULL,
|
||||
"expiraEm" TIMESTAMP(3) NOT NULL,
|
||||
"usadoEm" TIMESTAMP(3),
|
||||
"criadoEm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT "password_reset_tokens_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "users_email_key" ON "users"("email");
|
||||
CREATE UNIQUE INDEX "clientes_userId_key" ON "clientes"("userId");
|
||||
CREATE UNIQUE INDEX "clientes_cpfHash_key" ON "clientes"("cpfHash");
|
||||
CREATE INDEX "clientes_tipo_idx" ON "clientes"("tipo");
|
||||
CREATE UNIQUE INDEX "secoes_ordem_key" ON "secoes"("ordem");
|
||||
CREATE INDEX "perguntas_tipo_idx" ON "perguntas"("tipo");
|
||||
CREATE UNIQUE INDEX "perguntas_secaoId_ordem_key" ON "perguntas"("secaoId", "ordem");
|
||||
CREATE UNIQUE INDEX "ajudas_perguntaId_key" ON "ajudas"("perguntaId");
|
||||
CREATE INDEX "briefings_clienteId_idx" ON "briefings"("clienteId");
|
||||
CREATE INDEX "briefings_status_idx" ON "briefings"("status");
|
||||
CREATE INDEX "respostas_perguntaId_idx" ON "respostas"("perguntaId");
|
||||
CREATE UNIQUE INDEX "respostas_briefingId_perguntaId_key" ON "respostas"("briefingId", "perguntaId");
|
||||
CREATE INDEX "anexos_briefingId_idx" ON "anexos"("briefingId");
|
||||
CREATE INDEX "anexos_perguntaId_idx" ON "anexos"("perguntaId");
|
||||
CREATE UNIQUE INDEX "password_reset_tokens_tokenHash_key" ON "password_reset_tokens"("tokenHash");
|
||||
CREATE INDEX "password_reset_tokens_userId_idx" ON "password_reset_tokens"("userId");
|
||||
CREATE INDEX "password_reset_tokens_expiraEm_idx" ON "password_reset_tokens"("expiraEm");
|
||||
|
||||
ALTER TABLE "clientes" ADD CONSTRAINT "clientes_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "perguntas" ADD CONSTRAINT "perguntas_secaoId_fkey" FOREIGN KEY ("secaoId") REFERENCES "secoes"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "ajudas" ADD CONSTRAINT "ajudas_perguntaId_fkey" FOREIGN KEY ("perguntaId") REFERENCES "perguntas"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "briefings" ADD CONSTRAINT "briefings_clienteId_fkey" FOREIGN KEY ("clienteId") REFERENCES "clientes"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "respostas" ADD CONSTRAINT "respostas_briefingId_fkey" FOREIGN KEY ("briefingId") REFERENCES "briefings"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
ALTER TABLE "respostas" ADD CONSTRAINT "respostas_perguntaId_fkey" FOREIGN KEY ("perguntaId") REFERENCES "perguntas"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "anexos" ADD CONSTRAINT "anexos_briefingId_fkey" FOREIGN KEY ("briefingId") REFERENCES "briefings"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
ALTER TABLE "anexos" ADD CONSTRAINT "anexos_perguntaId_fkey" FOREIGN KEY ("perguntaId") REFERENCES "perguntas"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "password_reset_tokens" ADD CONSTRAINT "password_reset_tokens_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,10 @@
|
||||
CREATE TABLE "configuracoes" (
|
||||
"id" TEXT NOT NULL,
|
||||
"chave" TEXT NOT NULL,
|
||||
"valor" JSONB NOT NULL,
|
||||
"criadoEm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"atualizadoEm" TIMESTAMP(3) NOT NULL,
|
||||
CONSTRAINT "configuracoes_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "configuracoes_chave_key" ON "configuracoes"("chave");
|
||||
@@ -0,0 +1,27 @@
|
||||
CREATE TABLE "auditorias_acesso" (
|
||||
"id" TEXT NOT NULL,
|
||||
"adminId" TEXT NOT NULL,
|
||||
"clienteId" TEXT NOT NULL,
|
||||
"acao" TEXT NOT NULL,
|
||||
"criadoEm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT "auditorias_acesso_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "notas_internas" (
|
||||
"id" TEXT NOT NULL,
|
||||
"briefingId" TEXT NOT NULL,
|
||||
"adminId" TEXT NOT NULL,
|
||||
"texto" TEXT NOT NULL,
|
||||
"criadoEm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT "notas_internas_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE INDEX "auditorias_acesso_adminId_idx" ON "auditorias_acesso"("adminId");
|
||||
CREATE INDEX "auditorias_acesso_clienteId_idx" ON "auditorias_acesso"("clienteId");
|
||||
CREATE INDEX "notas_internas_briefingId_idx" ON "notas_internas"("briefingId");
|
||||
CREATE INDEX "notas_internas_adminId_idx" ON "notas_internas"("adminId");
|
||||
|
||||
ALTER TABLE "auditorias_acesso" ADD CONSTRAINT "auditorias_acesso_adminId_fkey" FOREIGN KEY ("adminId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "auditorias_acesso" ADD CONSTRAINT "auditorias_acesso_clienteId_fkey" FOREIGN KEY ("clienteId") REFERENCES "clientes"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "notas_internas" ADD CONSTRAINT "notas_internas_briefingId_fkey" FOREIGN KEY ("briefingId") REFERENCES "briefings"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
ALTER TABLE "notas_internas" ADD CONSTRAINT "notas_internas_adminId_fkey" FOREIGN KEY ("adminId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,22 @@
|
||||
CREATE TYPE "CanalNotificacao" AS ENUM ('EMAIL', 'WHATSAPP');
|
||||
CREATE TYPE "StatusNotificacao" AS ENUM ('PENDENTE', 'ENVIADO', 'ERRO');
|
||||
|
||||
CREATE TABLE "envios_notificacao" (
|
||||
"id" TEXT NOT NULL,
|
||||
"briefingId" TEXT NOT NULL,
|
||||
"canal" "CanalNotificacao" NOT NULL,
|
||||
"destino" TEXT NOT NULL,
|
||||
"assunto" TEXT,
|
||||
"status" "StatusNotificacao" NOT NULL DEFAULT 'PENDENTE',
|
||||
"erro" TEXT,
|
||||
"tentativas" INTEGER NOT NULL DEFAULT 0,
|
||||
"criadoEm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"atualizadoEm" TIMESTAMP(3) NOT NULL,
|
||||
"enviadoEm" TIMESTAMP(3),
|
||||
CONSTRAINT "envios_notificacao_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE INDEX "envios_notificacao_briefingId_idx" ON "envios_notificacao"("briefingId");
|
||||
CREATE INDEX "envios_notificacao_status_idx" ON "envios_notificacao"("status");
|
||||
|
||||
ALTER TABLE "envios_notificacao" ADD CONSTRAINT "envios_notificacao_briefingId_fkey" FOREIGN KEY ("briefingId") REFERENCES "briefings"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,16 @@
|
||||
CREATE TYPE "StatusSolicitacaoExclusao" AS ENUM ('PENDENTE', 'PROCESSADA', 'CANCELADA');
|
||||
|
||||
CREATE TABLE "solicitacoes_exclusao" (
|
||||
"id" TEXT NOT NULL,
|
||||
"clienteId" TEXT NOT NULL,
|
||||
"motivo" TEXT,
|
||||
"status" "StatusSolicitacaoExclusao" NOT NULL DEFAULT 'PENDENTE',
|
||||
"criadoEm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"processadoEm" TIMESTAMP(3),
|
||||
CONSTRAINT "solicitacoes_exclusao_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE INDEX "solicitacoes_exclusao_clienteId_idx" ON "solicitacoes_exclusao"("clienteId");
|
||||
CREATE INDEX "solicitacoes_exclusao_status_idx" ON "solicitacoes_exclusao"("status");
|
||||
|
||||
ALTER TABLE "solicitacoes_exclusao" ADD CONSTRAINT "solicitacoes_exclusao_clienteId_fkey" FOREIGN KEY ("clienteId") REFERENCES "clientes"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,282 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
enum Papel {
|
||||
CLIENTE
|
||||
ADMIN
|
||||
}
|
||||
|
||||
enum TipoPessoa {
|
||||
PF
|
||||
PJ
|
||||
}
|
||||
|
||||
enum TipoPergunta {
|
||||
TEXTAREA
|
||||
RADIO
|
||||
CHECKBOX
|
||||
ANEXO
|
||||
}
|
||||
|
||||
enum StatusBriefing {
|
||||
RASCUNHO
|
||||
ENVIADO
|
||||
EM_ANALISE
|
||||
CONCLUIDO
|
||||
}
|
||||
|
||||
enum CanalNotificacao {
|
||||
EMAIL
|
||||
WHATSAPP
|
||||
}
|
||||
|
||||
enum StatusNotificacao {
|
||||
PENDENTE
|
||||
ENVIADO
|
||||
ERRO
|
||||
}
|
||||
|
||||
enum StatusSolicitacaoExclusao {
|
||||
PENDENTE
|
||||
PROCESSADA
|
||||
CANCELADA
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
email String @unique
|
||||
senhaHash String
|
||||
papel Papel @default(CLIENTE)
|
||||
criadoEm DateTime @default(now())
|
||||
atualizadoEm DateTime @updatedAt
|
||||
cliente Cliente?
|
||||
passwordResetTokens PasswordResetToken[]
|
||||
auditorias AuditoriaAcesso[]
|
||||
notasInternas NotaInterna[]
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
model Cliente {
|
||||
id String @id @default(cuid())
|
||||
userId String @unique
|
||||
nomeCompleto String
|
||||
cpfCifrado String
|
||||
cpfHash String @unique
|
||||
whatsapp String
|
||||
tipo TipoPessoa @default(PF)
|
||||
razaoSocial String?
|
||||
cnpj String?
|
||||
cep String?
|
||||
logradouro String?
|
||||
numero String?
|
||||
complemento String?
|
||||
bairro String?
|
||||
cidade String?
|
||||
uf String?
|
||||
lgpdAceiteEm DateTime
|
||||
criadoEm DateTime @default(now())
|
||||
atualizadoEm DateTime @updatedAt
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
briefings Briefing[]
|
||||
auditorias AuditoriaAcesso[]
|
||||
solicitacoesExclusao SolicitacaoExclusao[]
|
||||
|
||||
@@index([tipo])
|
||||
@@map("clientes")
|
||||
}
|
||||
|
||||
model Secao {
|
||||
id String @id @default(cuid())
|
||||
ordem Int
|
||||
titulo String
|
||||
descricao String?
|
||||
ativo Boolean @default(true)
|
||||
criadoEm DateTime @default(now())
|
||||
atualizadoEm DateTime @updatedAt
|
||||
perguntas Pergunta[]
|
||||
|
||||
@@unique([ordem])
|
||||
@@map("secoes")
|
||||
}
|
||||
|
||||
model Pergunta {
|
||||
id String @id @default(cuid())
|
||||
secaoId String
|
||||
ordem Int
|
||||
rotulo String
|
||||
dica String?
|
||||
tipo TipoPergunta
|
||||
opcoes Json
|
||||
obrigatoria Boolean @default(false)
|
||||
permiteComplemento Boolean @default(false)
|
||||
ativo Boolean @default(true)
|
||||
criadoEm DateTime @default(now())
|
||||
atualizadoEm DateTime @updatedAt
|
||||
secao Secao @relation(fields: [secaoId], references: [id])
|
||||
ajuda Ajuda?
|
||||
respostas Resposta[]
|
||||
anexos Anexo[]
|
||||
|
||||
@@unique([secaoId, ordem])
|
||||
@@index([tipo])
|
||||
@@map("perguntas")
|
||||
}
|
||||
|
||||
model Ajuda {
|
||||
id String @id @default(cuid())
|
||||
perguntaId String @unique
|
||||
oQueResponder String
|
||||
porQuePerguntamos String
|
||||
miniExemplo String
|
||||
criadoEm DateTime @default(now())
|
||||
atualizadoEm DateTime @updatedAt
|
||||
pergunta Pergunta @relation(fields: [perguntaId], references: [id])
|
||||
|
||||
@@map("ajudas")
|
||||
}
|
||||
|
||||
model Briefing {
|
||||
id String @id @default(cuid())
|
||||
clienteId String
|
||||
titulo String
|
||||
status StatusBriefing @default(RASCUNHO)
|
||||
confirmadoEm DateTime?
|
||||
enviadoEm DateTime?
|
||||
criadoEm DateTime @default(now())
|
||||
atualizadoEm DateTime @updatedAt
|
||||
cliente Cliente @relation(fields: [clienteId], references: [id])
|
||||
respostas Resposta[]
|
||||
anexos Anexo[]
|
||||
notasInternas NotaInterna[]
|
||||
notificacoes EnvioNotificacao[]
|
||||
|
||||
@@index([clienteId])
|
||||
@@index([status])
|
||||
@@map("briefings")
|
||||
}
|
||||
|
||||
model Resposta {
|
||||
id String @id @default(cuid())
|
||||
briefingId String
|
||||
perguntaId String
|
||||
texto String?
|
||||
complemento String?
|
||||
selecionadas Json?
|
||||
criadoEm DateTime @default(now())
|
||||
atualizadoEm DateTime @updatedAt
|
||||
briefing Briefing @relation(fields: [briefingId], references: [id], onDelete: Cascade)
|
||||
pergunta Pergunta @relation(fields: [perguntaId], references: [id])
|
||||
|
||||
@@unique([briefingId, perguntaId])
|
||||
@@index([perguntaId])
|
||||
@@map("respostas")
|
||||
}
|
||||
|
||||
model Anexo {
|
||||
id String @id @default(cuid())
|
||||
briefingId String
|
||||
perguntaId String
|
||||
nomeOriginal String
|
||||
caminho String
|
||||
mime String
|
||||
tamanho Int
|
||||
criadoEm DateTime @default(now())
|
||||
briefing Briefing @relation(fields: [briefingId], references: [id], onDelete: Cascade)
|
||||
pergunta Pergunta @relation(fields: [perguntaId], references: [id])
|
||||
|
||||
@@index([briefingId])
|
||||
@@index([perguntaId])
|
||||
@@map("anexos")
|
||||
}
|
||||
|
||||
model PasswordResetToken {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
tokenHash String @unique
|
||||
expiraEm DateTime
|
||||
usadoEm DateTime?
|
||||
criadoEm DateTime @default(now())
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
|
||||
@@index([userId])
|
||||
@@index([expiraEm])
|
||||
@@map("password_reset_tokens")
|
||||
}
|
||||
|
||||
model Configuracao {
|
||||
id String @id @default(cuid())
|
||||
chave String @unique
|
||||
valor Json
|
||||
criadoEm DateTime @default(now())
|
||||
atualizadoEm DateTime @updatedAt
|
||||
|
||||
@@map("configuracoes")
|
||||
}
|
||||
|
||||
model AuditoriaAcesso {
|
||||
id String @id @default(cuid())
|
||||
adminId String
|
||||
clienteId String
|
||||
acao String
|
||||
criadoEm DateTime @default(now())
|
||||
admin User @relation(fields: [adminId], references: [id])
|
||||
cliente Cliente @relation(fields: [clienteId], references: [id])
|
||||
|
||||
@@index([adminId])
|
||||
@@index([clienteId])
|
||||
@@map("auditorias_acesso")
|
||||
}
|
||||
|
||||
model NotaInterna {
|
||||
id String @id @default(cuid())
|
||||
briefingId String
|
||||
adminId String
|
||||
texto String
|
||||
criadoEm DateTime @default(now())
|
||||
briefing Briefing @relation(fields: [briefingId], references: [id], onDelete: Cascade)
|
||||
admin User @relation(fields: [adminId], references: [id])
|
||||
|
||||
@@index([briefingId])
|
||||
@@index([adminId])
|
||||
@@map("notas_internas")
|
||||
}
|
||||
|
||||
model EnvioNotificacao {
|
||||
id String @id @default(cuid())
|
||||
briefingId String
|
||||
canal CanalNotificacao
|
||||
destino String
|
||||
assunto String?
|
||||
status StatusNotificacao @default(PENDENTE)
|
||||
erro String?
|
||||
tentativas Int @default(0)
|
||||
criadoEm DateTime @default(now())
|
||||
atualizadoEm DateTime @updatedAt
|
||||
enviadoEm DateTime?
|
||||
briefing Briefing @relation(fields: [briefingId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([briefingId])
|
||||
@@index([status])
|
||||
@@map("envios_notificacao")
|
||||
}
|
||||
|
||||
model SolicitacaoExclusao {
|
||||
id String @id @default(cuid())
|
||||
clienteId String
|
||||
motivo String?
|
||||
status StatusSolicitacaoExclusao @default(PENDENTE)
|
||||
criadoEm DateTime @default(now())
|
||||
processadoEm DateTime?
|
||||
cliente Cliente @relation(fields: [clienteId], references: [id])
|
||||
|
||||
@@index([clienteId])
|
||||
@@index([status])
|
||||
@@map("solicitacoes_exclusao")
|
||||
}
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
import { PrismaClient, TipoPergunta } from "@prisma/client";
|
||||
import argon2 from "argon2";
|
||||
import briefingSeed from "./briefing-seed.json";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
type SeedPergunta = {
|
||||
ordem: number;
|
||||
rotulo: string;
|
||||
dica?: string;
|
||||
tipo: keyof typeof TipoPergunta;
|
||||
opcoes: string[];
|
||||
permiteComplemento?: boolean;
|
||||
obrigatoria?: boolean;
|
||||
ajuda: {
|
||||
oQueResponder: string;
|
||||
porQuePerguntamos: string;
|
||||
miniExemplo: string;
|
||||
};
|
||||
};
|
||||
|
||||
type SeedSecao = {
|
||||
ordem: number;
|
||||
titulo: string;
|
||||
descricao?: string;
|
||||
perguntas: SeedPergunta[];
|
||||
};
|
||||
|
||||
async function seedConfiguracoes() {
|
||||
const meta = briefingSeed.meta;
|
||||
|
||||
await prisma.configuracao.upsert({
|
||||
where: { chave: "comoPreencher" },
|
||||
update: { valor: meta.comoPreencher },
|
||||
create: { chave: "comoPreencher", valor: meta.comoPreencher }
|
||||
});
|
||||
|
||||
await prisma.configuracao.upsert({
|
||||
where: { chave: "avisoSenhas" },
|
||||
update: { valor: meta.avisoSenhas },
|
||||
create: { chave: "avisoSenhas", valor: meta.avisoSenhas }
|
||||
});
|
||||
|
||||
await prisma.configuracao.upsert({
|
||||
where: { chave: "confirmacaoCliente" },
|
||||
update: { valor: meta.confirmacaoCliente },
|
||||
create: { chave: "confirmacaoCliente", valor: meta.confirmacaoCliente }
|
||||
});
|
||||
}
|
||||
|
||||
async function seedBriefing() {
|
||||
for (const secaoSeed of briefingSeed.secoes as SeedSecao[]) {
|
||||
const secao = await prisma.secao.upsert({
|
||||
where: { ordem: secaoSeed.ordem },
|
||||
update: {
|
||||
titulo: secaoSeed.titulo,
|
||||
descricao: secaoSeed.descricao ?? null,
|
||||
ativo: true
|
||||
},
|
||||
create: {
|
||||
ordem: secaoSeed.ordem,
|
||||
titulo: secaoSeed.titulo,
|
||||
descricao: secaoSeed.descricao ?? null,
|
||||
ativo: true
|
||||
}
|
||||
});
|
||||
|
||||
for (const perguntaSeed of secaoSeed.perguntas) {
|
||||
const pergunta = await prisma.pergunta.upsert({
|
||||
where: {
|
||||
secaoId_ordem: {
|
||||
secaoId: secao.id,
|
||||
ordem: perguntaSeed.ordem
|
||||
}
|
||||
},
|
||||
update: {
|
||||
rotulo: perguntaSeed.rotulo,
|
||||
dica: perguntaSeed.dica ?? null,
|
||||
tipo: perguntaSeed.tipo,
|
||||
opcoes: perguntaSeed.opcoes,
|
||||
obrigatoria: perguntaSeed.obrigatoria ?? false,
|
||||
permiteComplemento: perguntaSeed.permiteComplemento ?? false,
|
||||
ativo: true
|
||||
},
|
||||
create: {
|
||||
secaoId: secao.id,
|
||||
ordem: perguntaSeed.ordem,
|
||||
rotulo: perguntaSeed.rotulo,
|
||||
dica: perguntaSeed.dica ?? null,
|
||||
tipo: perguntaSeed.tipo,
|
||||
opcoes: perguntaSeed.opcoes,
|
||||
obrigatoria: perguntaSeed.obrigatoria ?? false,
|
||||
permiteComplemento: perguntaSeed.permiteComplemento ?? false,
|
||||
ativo: true
|
||||
}
|
||||
});
|
||||
|
||||
await prisma.ajuda.upsert({
|
||||
where: { perguntaId: pergunta.id },
|
||||
update: {
|
||||
oQueResponder: perguntaSeed.ajuda.oQueResponder,
|
||||
porQuePerguntamos: perguntaSeed.ajuda.porQuePerguntamos,
|
||||
miniExemplo: perguntaSeed.ajuda.miniExemplo
|
||||
},
|
||||
create: {
|
||||
perguntaId: pergunta.id,
|
||||
oQueResponder: perguntaSeed.ajuda.oQueResponder,
|
||||
porQuePerguntamos: perguntaSeed.ajuda.porQuePerguntamos,
|
||||
miniExemplo: perguntaSeed.ajuda.miniExemplo
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function seedAdmin() {
|
||||
const email = process.env.ADMIN_EMAIL?.trim().toLowerCase();
|
||||
const password = process.env.ADMIN_INITIAL_PASSWORD;
|
||||
|
||||
if (!email || !password) {
|
||||
return;
|
||||
}
|
||||
|
||||
const existingAdmin = await prisma.user.findUnique({
|
||||
where: { email }
|
||||
});
|
||||
|
||||
if (existingAdmin) {
|
||||
return;
|
||||
}
|
||||
|
||||
await prisma.user.create({
|
||||
data: {
|
||||
email,
|
||||
senhaHash: await argon2.hash(password),
|
||||
papel: "ADMIN"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
await seedConfiguracoes();
|
||||
await seedBriefing();
|
||||
await seedAdmin();
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((error) => {
|
||||
process.stderr.write(`Seed falhou: ${error instanceof Error ? error.message : "erro desconhecido"}\n`);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
Reference in New Issue
Block a user