439 lines
16 KiB
Plaintext
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")
|
|
}
|