first commit
This commit is contained in:
@@ -0,0 +1,438 @@
|
||||
// SeConectai Vendas — Prisma schema
|
||||
// Traduzido 1:1 a partir de `Etapas/seconectai-vendas-schema.sql` (fonte de verdade).
|
||||
// Constructos que o Prisma DSL não expressa nativamente (views, índices parciais,
|
||||
// CHECK constraints e as policies de RLS) são criados por uma migration manual
|
||||
// em `prisma/migrations/<timestamp>_rls_views_constraints/migration.sql`.
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// ENUMS
|
||||
// ============================================================
|
||||
|
||||
enum tenant_status {
|
||||
trial
|
||||
ativo
|
||||
inadimplente
|
||||
suspenso
|
||||
cancelado
|
||||
}
|
||||
|
||||
enum cobranca_status {
|
||||
pendente
|
||||
pago
|
||||
atrasado
|
||||
cancelado
|
||||
}
|
||||
|
||||
enum user_role {
|
||||
tenant_admin
|
||||
vendedor
|
||||
financeiro
|
||||
visualizador
|
||||
}
|
||||
|
||||
enum item_tipo {
|
||||
produto
|
||||
servico
|
||||
}
|
||||
|
||||
enum venda_status {
|
||||
orcamento
|
||||
confirmada
|
||||
cancelada
|
||||
concluida
|
||||
}
|
||||
|
||||
enum parcela_status {
|
||||
pendente
|
||||
pago
|
||||
atrasado
|
||||
cancelado
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 1. NÍVEL MASTER
|
||||
// ============================================================
|
||||
|
||||
model master_admins {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
nome String @db.VarChar(150)
|
||||
email String @unique @db.VarChar(150)
|
||||
senha_hash String
|
||||
ativo Boolean @default(true)
|
||||
mfa_secret String?
|
||||
ultimo_login DateTime? @db.Timestamptz(6)
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
atualizado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
tenants_criados tenants[]
|
||||
}
|
||||
|
||||
model evolution_api_config {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
nome String @db.VarChar(100)
|
||||
base_url String @db.VarChar(255)
|
||||
api_key_cripto String
|
||||
versao String @default("2.3") @db.VarChar(20)
|
||||
ativo Boolean @default(true)
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
instancias tenant_whatsapp_instances[]
|
||||
}
|
||||
|
||||
model master_email_config {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
smtp_host String @db.VarChar(150)
|
||||
smtp_porta Int
|
||||
smtp_usuario String @db.VarChar(150)
|
||||
smtp_senha_cripto String
|
||||
email_remetente String @db.VarChar(150)
|
||||
ativo Boolean @default(true)
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
}
|
||||
|
||||
model planos {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
nome String @db.VarChar(100)
|
||||
descricao String?
|
||||
valor_mensal Decimal @db.Decimal(10, 2)
|
||||
limite_customers Int?
|
||||
limite_usuarios Int?
|
||||
limite_instancias_whatsapp Int @default(1)
|
||||
ativo Boolean @default(true)
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
tenants tenants[]
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 2. TENANTS
|
||||
// ============================================================
|
||||
|
||||
model tenants {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
razao_social String @db.VarChar(200)
|
||||
nome_fantasia String? @db.VarChar(200)
|
||||
documento String? @db.VarChar(20)
|
||||
email_contato String @db.VarChar(150)
|
||||
telefone String? @db.VarChar(20)
|
||||
logo_url String?
|
||||
cor_primaria String? @db.VarChar(7)
|
||||
plano_id String? @db.Uuid
|
||||
status tenant_status @default(trial)
|
||||
dia_vencimento_mensalidade Int @default(10) @db.SmallInt
|
||||
trial_expira_em DateTime? @db.Timestamptz(6)
|
||||
criado_por String? @db.Uuid
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
atualizado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
plano planos? @relation(fields: [plano_id], references: [id])
|
||||
criador master_admins? @relation(fields: [criado_por], references: [id])
|
||||
|
||||
faturas tenant_faturas[]
|
||||
usuarios tenant_users[]
|
||||
whatsapp_instances tenant_whatsapp_instances[]
|
||||
email_config tenant_email_config?
|
||||
alert_templates alert_templates[]
|
||||
alert_logs alert_logs[]
|
||||
customers customers[]
|
||||
produtos products_services[]
|
||||
vendas sales[]
|
||||
audit_logs audit_logs[]
|
||||
|
||||
@@index([status], map: "idx_tenants_status")
|
||||
}
|
||||
|
||||
model tenant_faturas {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
tenant_id String @db.Uuid
|
||||
referencia String @db.VarChar(7)
|
||||
valor Decimal @db.Decimal(10, 2)
|
||||
vencimento DateTime @db.Date
|
||||
pago_em DateTime? @db.Timestamptz(6)
|
||||
status cobranca_status @default(pendente)
|
||||
alerta_enviado_em DateTime? @db.Timestamptz(6)
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
tenant tenants @relation(fields: [tenant_id], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([tenant_id, referencia])
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 3. USUÁRIOS E AUTENTICAÇÃO
|
||||
// ============================================================
|
||||
|
||||
model tenant_users {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
tenant_id String @db.Uuid
|
||||
nome String @db.VarChar(150)
|
||||
email String @db.VarChar(150)
|
||||
senha_hash String
|
||||
role user_role @default(vendedor)
|
||||
ativo Boolean @default(true)
|
||||
mfa_secret String?
|
||||
ultimo_login DateTime? @db.Timestamptz(6)
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
tenant tenants @relation(fields: [tenant_id], references: [id], onDelete: Cascade)
|
||||
|
||||
vendas sales[]
|
||||
|
||||
@@unique([tenant_id, email])
|
||||
@@index([tenant_id], map: "idx_tenant_users_tenant")
|
||||
}
|
||||
|
||||
model auth_refresh_tokens {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
usuario_tipo String @db.VarChar(20)
|
||||
usuario_id String @db.Uuid
|
||||
token_hash String
|
||||
expira_em DateTime @db.Timestamptz(6)
|
||||
revogado Boolean @default(false)
|
||||
ip_origem String? @db.Inet
|
||||
user_agent String?
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
@@index([usuario_tipo, usuario_id], map: "idx_refresh_tokens_usuario")
|
||||
}
|
||||
|
||||
model password_reset_tokens {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
usuario_tipo String @db.VarChar(20)
|
||||
usuario_id String @db.Uuid
|
||||
token_hash String
|
||||
expira_em DateTime @db.Timestamptz(6)
|
||||
usado Boolean @default(false)
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
}
|
||||
|
||||
model login_attempts {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
email String @db.VarChar(150)
|
||||
usuario_tipo String @db.VarChar(20)
|
||||
sucesso Boolean
|
||||
ip_origem String? @db.Inet
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
@@index([email, criado_em], map: "idx_login_attempts_email_data")
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 4. INTEGRAÇÕES POR TENANT
|
||||
// ============================================================
|
||||
|
||||
model tenant_whatsapp_instances {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
tenant_id String @db.Uuid
|
||||
evolution_config_id String? @db.Uuid
|
||||
instance_name String @unique @db.VarChar(100)
|
||||
numero_conectado String? @db.VarChar(20)
|
||||
status String @default("desconectado") @db.VarChar(30)
|
||||
qr_code_gerado_em DateTime? @db.Timestamptz(6)
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
tenant tenants @relation(fields: [tenant_id], references: [id], onDelete: Cascade)
|
||||
evolution_config evolution_api_config? @relation(fields: [evolution_config_id], references: [id])
|
||||
}
|
||||
|
||||
model tenant_email_config {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
tenant_id String @unique @db.Uuid
|
||||
smtp_host String? @db.VarChar(150)
|
||||
smtp_porta Int?
|
||||
smtp_usuario String? @db.VarChar(150)
|
||||
smtp_senha_cripto String?
|
||||
email_remetente String? @db.VarChar(150)
|
||||
usar_config_padrao Boolean @default(true)
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
tenant tenants @relation(fields: [tenant_id], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
||||
model alert_templates {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
tenant_id String? @db.Uuid
|
||||
tipo String @db.VarChar(50)
|
||||
canal String @db.VarChar(20)
|
||||
assunto String? @db.VarChar(200)
|
||||
corpo String
|
||||
ativo Boolean @default(true)
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
tenant tenants? @relation(fields: [tenant_id], references: [id], onDelete: Cascade)
|
||||
|
||||
alert_logs alert_logs[]
|
||||
}
|
||||
|
||||
model alert_logs {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
tenant_id String? @db.Uuid
|
||||
destinatario_tipo String @db.VarChar(20)
|
||||
destinatario_id String @db.Uuid
|
||||
canal String @db.VarChar(20)
|
||||
template_id String? @db.Uuid
|
||||
conteudo_enviado String?
|
||||
status String @default("enviado") @db.VarChar(20)
|
||||
erro String?
|
||||
enviado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
tenant tenants? @relation(fields: [tenant_id], references: [id], onDelete: Cascade)
|
||||
template alert_templates? @relation(fields: [template_id], references: [id])
|
||||
|
||||
@@index([tenant_id, enviado_em], map: "idx_alert_logs_tenant")
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 5. CLIENTES DO TENANT ("customers")
|
||||
// ============================================================
|
||||
|
||||
model customers {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
tenant_id String @db.Uuid
|
||||
razao_social String @db.VarChar(200)
|
||||
nome_fantasia String? @db.VarChar(200)
|
||||
documento String? @db.VarChar(20)
|
||||
email String? @db.VarChar(150)
|
||||
telefone_whatsapp String? @db.VarChar(20)
|
||||
endereco String?
|
||||
cidade String? @db.VarChar(100)
|
||||
uf String? @db.Char(2)
|
||||
observacoes String?
|
||||
ativo Boolean @default(true)
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
atualizado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
tenant tenants @relation(fields: [tenant_id], references: [id], onDelete: Cascade)
|
||||
contatos customer_contacts[]
|
||||
vendas sales[]
|
||||
|
||||
@@index([tenant_id], map: "idx_customers_tenant")
|
||||
}
|
||||
|
||||
model customer_contacts {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
customer_id String @db.Uuid
|
||||
nome String @db.VarChar(150)
|
||||
cargo String? @db.VarChar(100)
|
||||
email String? @db.VarChar(150)
|
||||
telefone_whatsapp String? @db.VarChar(20)
|
||||
principal Boolean @default(false)
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
customer customers @relation(fields: [customer_id], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 6. PRODUTOS E SERVIÇOS DO TENANT
|
||||
// ============================================================
|
||||
|
||||
model products_services {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
tenant_id String @db.Uuid
|
||||
tipo item_tipo
|
||||
nome String @db.VarChar(200)
|
||||
descricao String?
|
||||
sku String? @db.VarChar(50)
|
||||
valor_venda Decimal @db.Decimal(12, 2)
|
||||
valor_custo Decimal? @db.Decimal(12, 2)
|
||||
unidade String @default("un") @db.VarChar(20)
|
||||
recorrente Boolean @default(false)
|
||||
ativo Boolean @default(true)
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
atualizado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
tenant tenants @relation(fields: [tenant_id], references: [id], onDelete: Cascade)
|
||||
|
||||
itens_venda sale_items[]
|
||||
|
||||
@@unique([tenant_id, sku])
|
||||
@@index([tenant_id], map: "idx_products_tenant")
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 7. VENDAS
|
||||
// ============================================================
|
||||
|
||||
model sales {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
tenant_id String @db.Uuid
|
||||
customer_id String @db.Uuid
|
||||
vendedor_id String? @db.Uuid
|
||||
numero_venda Int @default(autoincrement())
|
||||
status venda_status @default(confirmada)
|
||||
valor_total Decimal @default(0) @db.Decimal(12, 2)
|
||||
desconto Decimal @default(0) @db.Decimal(12, 2)
|
||||
observacoes String?
|
||||
data_venda DateTime @default(now()) @db.Date
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
atualizado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
tenant tenants @relation(fields: [tenant_id], references: [id], onDelete: Cascade)
|
||||
customer customers @relation(fields: [customer_id], references: [id])
|
||||
vendedor tenant_users? @relation(fields: [vendedor_id], references: [id])
|
||||
|
||||
itens sale_items[]
|
||||
parcelas sale_payments[]
|
||||
|
||||
@@index([tenant_id, data_venda], map: "idx_sales_tenant_data")
|
||||
@@index([customer_id], map: "idx_sales_customer")
|
||||
}
|
||||
|
||||
model sale_items {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
sale_id String @db.Uuid
|
||||
product_service_id String @db.Uuid
|
||||
quantidade Decimal @default(1) @db.Decimal(10, 2)
|
||||
valor_unitario Decimal @db.Decimal(12, 2)
|
||||
valor_total Decimal @db.Decimal(12, 2)
|
||||
|
||||
sale sales @relation(fields: [sale_id], references: [id], onDelete: Cascade)
|
||||
produto products_services @relation(fields: [product_service_id], references: [id])
|
||||
|
||||
@@index([sale_id], map: "idx_sale_items_sale")
|
||||
}
|
||||
|
||||
model sale_payments {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
sale_id String @db.Uuid
|
||||
numero_parcela Int @default(1) @db.SmallInt
|
||||
valor Decimal @db.Decimal(12, 2)
|
||||
vencimento DateTime @db.Date
|
||||
pago_em DateTime? @db.Timestamptz(6)
|
||||
forma_pagamento String? @db.VarChar(30)
|
||||
status parcela_status @default(pendente)
|
||||
alerta_enviado_em DateTime? @db.Timestamptz(6)
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
sale sales @relation(fields: [sale_id], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 8. AUDITORIA GERAL
|
||||
// ============================================================
|
||||
|
||||
model audit_logs {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
tenant_id String? @db.Uuid
|
||||
usuario_tipo String @db.VarChar(20)
|
||||
usuario_id String? @db.Uuid
|
||||
acao String @db.VarChar(100)
|
||||
entidade String? @db.VarChar(50)
|
||||
entidade_id String? @db.Uuid
|
||||
detalhes Json?
|
||||
ip_origem String? @db.Inet
|
||||
criado_em DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
tenant tenants? @relation(fields: [tenant_id], references: [id], onDelete: SetNull)
|
||||
|
||||
@@index([tenant_id, criado_em], map: "idx_audit_tenant_data")
|
||||
}
|
||||
Reference in New Issue
Block a user