Files
SeConectai_Vendas/prisma/schema.prisma
T
2026-08-14 17:35:24 -03:00

439 lines
16 KiB
Plaintext

// 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")
}