Ir para o conteúdo

Backend - Modelos de Dados

Este documento descreve todos os modelos de dados do sistema Billings Ease, incluindo campos, relacionamentos, constraints e exemplos de uso.

Índice

  1. Modelos de Usuário e Autenticação
  2. Modelos do Método Billings
  3. Modelos de Perfis
  4. Modelos de Comunicação
  5. Modelos Financeiros
  6. Modelos de Configuração
  7. Tipos Auxiliares

Atualização importante

O domínio de cursos foi expandido e refatorado (bundles, recomendações, reviews, materiais de aula, revenue split e contrato monetário em centavos).

Ver documentação dedicada:


Modelos de Usuário e Autenticação

User

Modelo principal de usuário do sistema. Representa todos os tipos de usuários (client, professional, admin).

Localização: internal/models/user.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
CreatedAt time.Time Data de criação Automático
UpdatedAt time.Time Data de atualização Automático
DeletedAt gorm.DeletedAt Soft delete Index
Username *string Nome de usuário (opcional) Index, pode ser NULL
Email string Email (usado para login) Unique, Not Null
Password string Hash da senha (bcrypt) Not Null, não retornado em JSON
Name string Nome completo Not Null
UserType UserType Tipo de usuário Not Null
IsActive bool Se está ativo Default: true
EmailVerified bool Se email foi verificado Default: false
EmailVerifiedAt *time.Time Data de verificação Opcional

Tipos de Usuário (UserType): - client - Cliente (paciente) - professional - Profissional de saúde - admin - Administrador

Relacionamentos: - Accounts - Contas financeiras (1:N) - Subscriptions - Assinaturas (1:N) - Cycles - Ciclos menstruais (1:N) - Observations - Observações diárias (1:N) - SyncLogs - Logs de sincronização (1:N)

Exemplo de uso:

user := models.User{
    Email:     "user@example.com",
    Password:  hashedPassword,
    Name:      "Maria Silva",
    UserType:  models.UserTypeClient,
    IsActive:  true,
}

UserAuthProvider

Representa uma identidade externa (OAuth) associada a um usuário. Permite que um usuário tenha múltiplas identidades externas (Google, Apple, etc.).

Localização: internal/models/user_auth_provider.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
UserID uint Referência ao usuário Not Null, Index
Provider AuthProvider Provedor OAuth Not Null, Index
ProviderUserID string ID do usuário no provedor Not Null
Email *string Email (apenas informativo) Opcional

Provedores Suportados (AuthProvider): - google - Google OAuth - apple - Apple Sign In

Relacionamentos: - User - Usuário associado (N:1)

Nota Importante: O ProviderUserID é o identificador único do provedor (sub do token OIDC) e é usado para autenticação. O email é apenas informativo e nunca deve ser usado como identidade.

EmailVerification

Token de verificação de email para novos usuários.

Localização: internal/models/email_verification.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
Token string Token único Unique, Not Null
UserID uint Usuário a verificar Not Null, Index
ExpiresAt time.Time Data de expiração Not Null
Used bool Se foi usado Default: false
UsedAt *time.Time Data de uso Opcional
LastResendAt *time.Time Último reenvio Index

Relacionamentos: - User - Usuário associado (N:1)

PasswordReset

Token para recuperação de senha.

Localização: internal/models/password_reset.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
Token string Token único Unique, Not Null
UserID uint Usuário Not Null, Index
ExpiresAt time.Time Data de expiração Not Null
Used bool Se foi usado Default: false
UsedAt *time.Time Data de uso Opcional

Relacionamentos: - User - Usuário associado (N:1)


Modelos do Método Billings

Cycle

Representa um ciclo menstrual completo, desde o primeiro dia de sangramento até o dia anterior ao próximo sangramento.

Localização: internal/models/cycle.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
UserID uint Usuária dona do ciclo Not Null, Index
StartDate Date Primeiro dia de sangramento Not Null
EndDate *Date Último dia do ciclo Opcional
Length int Duração em dias Calculado
IsActive bool Se está ativo Default: true
LastSyncedAt *time.Time Última sincronização Opcional
SyncID string ID para sincronização mobile Index

Regras de Negócio: - Apenas um ciclo ativo por usuária - Ciclo começa no primeiro dia de sangramento - Ciclo termina quando novo sangramento é registrado

Relacionamentos: - User - Usuária dona do ciclo (N:1) - Observations - Observações do ciclo (1:N)

Exemplo:

cycle := models.Cycle{
    UserID:    1,
    StartDate: models.NewDate(time.Now()),
    IsActive:  true,
}

Observation

Registro diário dos sinais de fertilidade. Apenas uma observação por dia por usuária.

Localização: internal/models/observation.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
UserID uint Usuária Not Null, Index
CycleID *uint Ciclo associado Index, Opcional
Date Date Data da observação Not Null
Type ObservationType Tipo de observação Not Null
Description string Descrição Opcional
Sensation string Sensação física Opcional
Temperature *float64 Temperatura basal Opcional
Notes string Notas pessoais Opcional
ProfessionalNotes string Notas do profissional Opcional
MoodChanges bool Mudanças de humor Default: false
Cramps bool Cólicas Default: false
BreastPain bool Dor nos seios Default: false
HadIntercourse bool Teve relação sexual Default: false
IsFirstDayOfMenstruation bool Primeiro dia da menstruação Default: false
MucusType string Tipo de muco Opcional
SymbolID *uint Símbolo escolhido Index, Opcional
AppearanceID *uint Aparência observada Index, Opcional
LastSyncedAt *time.Time Última sincronização Opcional
SyncID string ID para sincronização Index

Tipos de Observação (ObservationType): - dry - Seca - sticky - Pegajosa - creamy - Cremosa - watery - Aquosa - egg_white - Clara de ovo - bleeding - Sangramento

Relacionamentos: - User - Usuária (N:1) - Cycle - Ciclo associado (N:1, opcional) - Symbol - Símbolo escolhido (N:1, opcional) - Appearance - Aparência observada (N:1, opcional)

Regras: - Apenas uma observação por dia por usuária - Deve existir ciclo ativo (exceto em casos especiais)

Symbol

Símbolo do Método Billings. Representa diferentes estados do muco cervical.

Localização: internal/models/symbol.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
Name string Nome único do símbolo Unique, Not Null
Description string Descrição Opcional
ImagePath string Caminho da imagem Not Null
RelationImagePath *string Imagem para relação sexual Opcional

Exemplos de Símbolos: - seca - Período seco - fertilidade - Período fértil - fertilidade apice - Ápice de fertilidade - fluxo - Fluxo - sangramento sem mancha - Sangramento - sangramento com mancha - Sangramento com mancha

Relacionamentos: - Observations - Observações que usam este símbolo (1:N, via Observation.SymbolID)

Nota: A tabela no banco é nomeada symbol (singular).

Sensation

Sensação física percebida no muco cervical.

Localização: internal/models/sensation.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
Name string Nome único Unique, Not Null
DisplayName string Nome para exibição Not Null
Description string Descrição detalhada Opcional
IsActive bool Se está ativa Default: true
Order int Ordem de exibição Default: 0

Exemplos: - seca - Seca - pegajosa - Pegajosa - úmida - Úmida - lubrificante - Lubrificante

Appearance

Aparência visual do muco cervical.

Localização: internal/models/appearance.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
Name string Nome único Unique, Not Null
DisplayName string Nome para exibição Not Null
Description string Descrição Opcional
IsActive bool Se está ativa Default: true
Order int Ordem de exibição Default: 0

Exemplos: - ausente - Ausente - clara - Clara - opaca - Opaca - espessa - Espessa - transparente - Transparente

DayBasedRule

Regra baseada em dias do ciclo que define quais símbolos são permitidos ou restritos em determinados períodos.

Localização: internal/models/day_based_rule.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
Name string Nome da regra Not Null
Description string Descrição Opcional
MinDay int Dia mínimo (inclusive) Not Null
MaxDay int Dia máximo (inclusive) Not Null
AllowedSymbolIDs UIntArray IDs de símbolos permitidos JSONB
RestrictedSymbolIDs UIntArray IDs de símbolos restritos JSONB
IsActive bool Se está ativa Default: true
Order int Ordem de aplicação Default: 0

Exemplo:

rule := models.DayBasedRule{
    Name:            "Primeiros 15 dias",
    MinDay:          1,
    MaxDay:          15,
    AllowedSymbolIDs: models.UIntArray{1, 2, 3}, // IDs de símbolos permitidos
    IsActive:        true,
}

CycleComment

Comentário de um profissional sobre um ciclo de uma paciente.

Localização: internal/models/cycle_comment.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
CycleID uint Ciclo comentado Not Null, Index
ProfessionalID uint Profissional que comentou Not Null, Index
Content string Conteúdo do comentário Not Null

Relacionamentos: - Cycle - Ciclo comentado (N:1) - Professional - Profissional que comentou (N:1)

Regras: - Apenas profissionais podem comentar - Profissional deve estar vinculado à paciente do ciclo


Modelos de Perfis

ClientProfile

Perfil detalhado de cliente (paciente). Relacionamento 1:1 com User.

Localização: internal/models/client_profile.go

Campos:

Informações Pessoais: - FullName - Nome completo - Phone - Telefone - CellPhone - Celular - BirthDate - Data de nascimento - ProfilePhotoKey - Chave da foto no R2 - ProfilePhotoURL - URL completa (calculada, não salva) - CPF - CPF - Address - Endereço

Informações de Saúde Menstrual: - FirstMenstruationDate - Data da menarca - AverageCycleLength - Duração média do ciclo (dias) - AveragePeriodLength - Duração média da menstruação (dias) - LastMenstruationDate - Última menstruação - HealthNotes - Observações sobre saúde menstrual

Informações Adicionais: - Objective - Objetivo (engravidar, espaçar, conhecimento) - IsBreastfeeding - Se está amamentando - FamilyPlanningHistory - Histórico de métodos (JSON) - WomanPattern - Padrão Básico de Infertilidade (PBI) - PBISensationID - ID da sensação do PBI - PBIAppearanceID - ID da aparência do PBI

Relacionamentos: - User - Usuário associado (1:1, via UserID)

Constraints: - UserID é único (garante 1:1)

ProfessionalProfile

Perfil detalhado de profissional. Relacionamento 1:1 com User.

Localização: internal/models/professional_profile.go

Campos:

Informações Básicas: - FullName - Nome completo - Phone - Telefone - CellPhone - Celular - Email - Email - BirthDate - Data de nascimento - ProfilePhotoKey - Chave da foto no R2 - ProfilePhotoURL - URL completa (calculada) - CPFOrCNPJ - CPF ou CNPJ

Informações Profissionais: - MethodType - Tipo de método que trabalha - Biography - Biografia ("Quem sou eu") - Rating - Média de avaliações (1-5) - RatingCount - Quantidade de avaliações

Documentos: - ProfessionalCertificateKey - Chave do certificado no R2 - ProfessionalCertificateURL - URL do certificado - DocumentType - Tipo de documento (CNH, RG, CPF) - DocumentKey - Chave do documento no R2 - DocumentURL - URL do documento

Status de Aprovação: - Status - Status (pending, approved, rejected) - RejectionReason - Motivo da reprovação - ApprovedBy - ID do admin que aprovou - ApprovedAt - Data de aprovação

Status Possíveis (ProfileStatus): - pending - Aguardando aprovação - approved - Aprovado - rejected - Rejeitado

Relacionamentos: - User - Usuário associado (1:1, via UserID)

Constraints: - UserID é único (garante 1:1)

ProfessionalPatient

Relacionamento entre profissional e paciente. N:1 (um profissional pode ter vários pacientes, mas um paciente só pode estar com um profissional).

Localização: internal/models/professional_patient.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
ProfessionalID uint ID do profissional Not Null, Index
PatientID uint ID do paciente Not Null, Unique Index
Status LinkStatus Status do vínculo Not Null, Default: pending

Status Possíveis (LinkStatus): - pending - Aguardando aprovação da orientadora - approved - Aprovado pela orientadora - rejected - Rejeitado pela orientadora

Relacionamentos: - Professional - Profissional (N:1) - Patient - Paciente (N:1)

Constraints: - PatientID é único (garante que um paciente só pode estar com um profissional)


Modelos de Comunicação

Message

Mensagem entre usuários (cliente ↔ profissional).

Localização: internal/models/message.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
SenderID uint Remetente Not Null, Index
ReceiverID uint Destinatário Not Null, Index
Content string Conteúdo da mensagem Not Null
AttachmentURL string URL de anexo Opcional
IsRead bool Se foi lida Default: false
ReadAt *time.Time Data de leitura Opcional

Relacionamentos: - Sender - Remetente (N:1) - Receiver - Destinatário (N:1)

Regras: - Cliente só pode enviar para profissional vinculado - Profissional só pode enviar para pacientes vinculados - Admin pode enviar para qualquer um

Appointment

Agendamento entre profissional e paciente.

Localização: internal/models/appointment.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
ProfessionalID uint Profissional Not Null, Index
PatientID uint Paciente Not Null, Index
ScheduledAt time.Time Data/hora agendada Not Null
Duration int Duração em minutos Default: 60
Status AppointmentStatus Status do agendamento Default: pending_confirmation
VideoCallURL string URL da videochamada Opcional
MeetingID string ID da reunião Opcional
Notes string Notas Opcional
RejectionReason string Motivo da rejeição Opcional

Status Possíveis (AppointmentStatus): - pending_confirmation - Aguardando confirmação - scheduled - Agendado - completed - Concluído - cancelled - Cancelado - rejected - Rejeitado

Relacionamentos: - Professional - Profissional (N:1) - Patient - Paciente (N:1)

Notification

Notificação do sistema para usuários.

Localização: internal/models/notification.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
UserID uint Usuário destinatário Not Null, Index
Type NotificationType Tipo de notificação Not Null
Title string Título Not Null
Message string Mensagem Not Null
IsRead bool Se foi lida Default: false
ReadAt *time.Time Data de leitura Opcional
Metadata NotificationMetadata Metadados (JSONB) Opcional
ReferenceType string Tipo de referência Opcional
ReferenceID *uint ID da referência Opcional

Tipos de Notificação (NotificationType): - message - Nova mensagem - appointment - Agendamento - task - Tarefa - reminder - Lembrete - system - Sistema

Metadata: O campo Metadata é um JSONB que pode armazenar dados adicionais específicos do tipo de notificação.

Relacionamentos: - User - Usuário destinatário (N:1)


Modelos Financeiros

Plan

Plano de assinatura disponível.

Localização: internal/models/plan.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
Name string Nome do plano Not Null
Description string Descrição Opcional
Status PlanStatus Status do plano Default: active
CanUseApp bool Pode usar app Default: false
CanUseWeb bool Pode usar web Default: false
CanAccessReports bool Pode acessar relatórios Default: false
CanAccessAPI bool Pode acessar API Default: false
PriceMonthly float64 Preço mensal Not Null
PriceSixMonths float64 Preço semestral Not Null
PriceYearly float64 Preço anual Not Null

Status Possíveis (PlanStatus): - active - Ativo - inactive - Inativo

Relacionamentos: - Subscriptions - Assinaturas deste plano (1:N)

Subscription

Assinatura de um usuário a um plano.

Localização: internal/models/subscription.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
UserID uint Usuário Not Null, Index
PlanID *uint Plano associado Index, Opcional
Name string Nome da assinatura Not Null
Description string Descrição Opcional
Amount float64 Valor Not Null
Status SubscriptionStatus Status Default: active
StartDate Date Data de início Not Null
EndDate *Date Data de término Opcional
BillingCycle string Ciclo de cobrança Opcional
PaymentGatewayID string ID no gateway Opcional

Status Possíveis (SubscriptionStatus): - active - Ativa - inactive - Inativa - cancelled - Cancelada

Relacionamentos: - User - Usuário (N:1) - Plan - Plano associado (N:1, opcional)

Ciclos de Cobrança: - monthly - Mensal - six_months - Semestral - yearly - Anual

Payment

Pagamento de uma assinatura ou transação.

Localização: internal/models/payment.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
UserID uint Usuário Not Null, Index
SubscriptionID *uint Assinatura associada Index, Opcional
Amount float64 Valor Not Null
Status PaymentStatus Status Default: pending
PaymentDate *Date Data do pagamento Opcional
GatewayProvider string Provedor do gateway Opcional
GatewayID string ID no gateway Index, Opcional
GatewayResponse string Resposta do gateway Opcional

Status Possíveis (PaymentStatus): - pending - Pendente - completed - Concluído - failed - Falhou - cancelled - Cancelado

Relacionamentos: - User - Usuário (N:1) - Subscription - Assinatura associada (N:1, opcional)

Account

Conta financeira genérica (não relacionada a assinaturas).

Localização: internal/models/account.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
UserID uint Usuário Not Null, Index
Name string Nome da conta Not Null
Description string Descrição Opcional
Amount float64 Valor Not Null
DueDate Date Data de vencimento Not Null
IsPaid bool Se foi pago Default: false
LastSyncedAt *time.Time Última sincronização Opcional
SyncID string ID para sincronização Index

Relacionamentos: - User - Usuário (N:1)

ProfessionalBankAccount

Conta bancária de um profissional para recebimento de pagamentos.

Localização: internal/models/professional_bank_account.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
ProfessionalID uint Profissional Not Null, Unique Index
BankName string Nome do banco Not Null
AccountType AccountType Tipo de conta Not Null
Agency string Agência Not Null
AccountNumber string Número da conta Not Null
CPFOrCNPJ string CPF ou CNPJ Not Null

Tipos de Conta (AccountType): - checking - Conta Corrente - savings - Conta Poupança

Relacionamentos: - Professional - Profissional (1:1, via ProfessionalID)

Constraints: - ProfessionalID é único (garante uma conta por profissional)


Modelos de Configuração

Settings

Configurações globais do sistema.

Localização: internal/models/settings.go

Campos: - Apenas campos padrão (ID, CreatedAt, UpdatedAt, DeletedAt)

Nota: Este modelo é uma estrutura base para configurações futuras. A tabela no banco é nomeada settings.

WorkSchedule

Horário de trabalho de um profissional.

Localização: internal/models/work_schedule.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
ProfessionalID uint Profissional Not Null, Unique Index
DaysOfWeek string Dias da semana (JSON array) Opcional
StartTime string Horário de início (HH:MM) Not Null
EndTime string Horário de fim (HH:MM) Not Null
AppointmentDuration int Duração da consulta (minutos) Default: 60
LunchStartTime string Início do almoço (HH:MM) Opcional
LunchEndTime string Fim do almoço (HH:MM) Opcional

Relacionamentos: - Professional - Profissional (1:1, via ProfessionalID)

Constraints: - ProfessionalID é único (garante um horário por profissional)

Formato de DaysOfWeek: JSON array de números: [1,2,3,4,5] (0=Domingo, 1=Segunda, ..., 6=Sábado)

AvailabilitySlot

Slot de disponibilidade específico de um profissional.

Localização: internal/models/availability.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
ProfessionalID uint Profissional Not Null, Index
Date Date Data do slot Not Null
StartTime string Horário de início (HH:MM) Not Null
EndTime string Horário de fim (HH:MM) Not Null
IsAvailable bool Se está disponível Default: true

Relacionamentos: - Professional - Profissional (N:1)

Uso: Usado para definir horários específicos disponíveis além do horário de trabalho padrão.

Course

Curso educativo disponível na plataforma.

Localização: internal/models/course.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
Title string Título Not Null
Description string Descrição Opcional
VideoURL string URL do vídeo Not Null
ThumbnailURL string URL da thumbnail Opcional
Duration int Duração em minutos Opcional
Order int Ordem de exibição Default: 0

SyncLog

Log de sincronização entre mobile e backend.

Localização: internal/models/sync.go

Campos:

Campo Tipo Descrição Constraints
ID uint Identificador único Primary Key
UserID uint Usuário Not Null, Index
DeviceID string ID do dispositivo Not Null, Index
SyncType string Tipo (push, pull) Opcional
Status string Status (success, error) Opcional
RecordsCount int Quantidade de registros Opcional
Error string Erro (se houver) Opcional
SyncedAt time.Time Data da sincronização Not Null

Relacionamentos: - User - Usuário (N:1)


Tipos Auxiliares

Date

Tipo personalizado para representar datas civis (sem hora/timezone). Armazena apenas a data (YYYY-MM-DD).

Localização: internal/models/date.go

Características: - Serializa para JSON como string "YYYY-MM-DD" - Normaliza para UTC à meia-noite - Implementa driver.Valuer e sql.Scanner para GORM - Implementa json.Marshaler e json.Unmarshaler

Métodos: - NewDate(t time.Time) Date - Cria Date a partir de time.Time - NewDateFromString(s string) (Date, error) - Cria Date a partir de string - String() string - Retorna "YYYY-MM-DD" - IsZero() bool - Verifica se é zero

Uso:

date := models.NewDate(time.Now())
dateStr := date.String() // "2024-01-15"

UIntArray

Tipo personalizado para arrays de uint armazenados como JSONB.

Localização: internal/models/uint_array.go

Características: - Armazena arrays de uint como JSONB no PostgreSQL - Implementa driver.Valuer e sql.Scanner - Implementa json.Unmarshaler

Uso:

ids := models.UIntArray{1, 2, 3, 4, 5}
// Serializa para JSONB: [1,2,3,4,5]


Relacionamentos Principais

Diagrama de Relacionamentos

erDiagram
    User ||--o{ Cycle : "tem"
    User ||--o| ClientProfile : "tem"
    User ||--o| ProfessionalProfile : "tem"
    User ||--o{ Observation : "faz"
    User ||--o{ Subscription : "tem"
    User ||--o{ Message : "envia/recebe"
    User ||--o{ Appointment : "agenda"
    User ||--o{ Notification : "recebe"

    Cycle ||--o{ Observation : "contém"
    Cycle ||--o{ CycleComment : "tem"

    ProfessionalProfile ||--o{ ProfessionalPatient : "atende"
    ProfessionalProfile ||--|| WorkSchedule : "tem"
    ProfessionalProfile ||--|| ProfessionalBankAccount : "tem"

    Plan ||--o{ Subscription : "gera"
    Subscription ||--o{ Payment : "tem"

    Symbol ||--o{ Observation : "usado_em"
    Appearance ||--o{ Observation : "usado_em"

    DayBasedRule ||--o{ Symbol : "permite"

Soft Deletes

A maioria dos modelos implementa soft deletes através do campo DeletedAt do tipo gorm.DeletedAt. Isso significa que:

  • Registros não são fisicamente deletados
  • GORM automaticamente filtra registros deletados nas queries normais
  • Use Unscoped() para incluir registros deletados:
    db.Unscoped().Find(&users) // Inclui deletados
    

Sincronização Mobile

Vários modelos incluem campos para sincronização com mobile:

  • SyncID - Identificador único do dispositivo mobile
  • LastSyncedAt - Última data de sincronização

Modelos com suporte a sincronização: - Cycle - Observation - Account


Referências