Skip to content

Módulo de Pacientes

Documentação técnica detalhada do módulo de pacientes.

Modelo de Dados

typescript
interface PatientDTO {
  id: string;                    // UUID
  organizationId: string;        // Tenant owner
  fullName: string;              // Nome completo
  cpf: string;                   // CPF único por organização
  birthDate: string;             // ISO 8601
  gender: 'MALE' | 'FEMALE' | 'OTHER' | 'NOT_INFORMED';
  phonePrimary: string;
  phoneSecondary?: string;
  email?: string;
  address?: {
    street: string;
    number: string;
    complement?: string;
    city: string;
    state: string;
    zip: string;
  };
  photoUrl?: string;
  bloodType?: string;
  allergies: string[];           // Ex: ["Penicilina", "Dipirona"]
  observations?: string;         // Criptografado (AES-256)
  tags: string[];                // Segmentação
  referralSource?: string;
  insuranceId?: string;          // ID do convênio
  responsibleId?: string;        // ID do responsável (menor de 18 anos)
  isActive: boolean;
  createdAt: string;
  updatedAt: string;
}

Regras de Negócio

Unicidade do CPF

  • O CPF deve ser único por organização
  • O mesmo CPF pode existir em organizações diferentes (tenants separados)
  • A detecção de duplicata ocorre em tempo real ao digitar o CPF
  • Ao detectar duplicata: retorna 409 Conflict com { existing_id: UUID }

Menor de Idade

Pacientes com menos de 18 anos devem ter um responsible_id vinculado:

  • O responsável deve ser um paciente adulto já cadastrado na mesma organização
  • A validação é aplicada na criação e na edição

Criptografia de Dados Sensíveis

O campo observations é criptografado com AES-256 antes de ser armazenado no banco. A descriptografia ocorre transparentemente na camada de infraestrutura ao consultar o registro.

Imutabilidade do CPF

O CPF não pode ser alterado após o cadastro — apenas no fluxo de merge de duplicatas, onde o CPF do cadastro principal é mantido.

Inativação (Não Exclusão)

Por conformidade com regulação clínica:

  • Pacientes nunca são excluídos fisicamente
  • A inativação define is_active: false
  • Dados históricos são mantidos integralmente
  • Novos agendamentos são bloqueados para pacientes inativos

Endpoints da API

MétodoEndpointPapel mínimoDescrição
GET/patientsReceptionistListar pacientes com paginação e busca
POST/patientsReceptionistCriar paciente
GET/patients/:idReceptionistDetalhe do paciente
PUT/patients/:idReceptionistAtualizar dados do paciente
POST/patients/:id/tagsReceptionistAdicionar/remover tags
POST/patients/mergeAdminMesclar dois cadastros
GET/patients/:id/appointmentsViewerHistórico de agendamentos
GET/patients/:id/exportAdminExportação LGPD (JSON completo)

Listagem com Paginação

http
GET /patients?q=maria&page=1&per_page=20&tag=vip

Response 200:
{
  "data": [PatientSummaryDTO],
  "meta": {
    "total": 150,
    "page": 1,
    "per_page": 20,
    "total_pages": 8
  }
}

Criação de Paciente

http
POST /patients
Content-Type: application/json

{
  "fullName": "Maria Aparecida Silva",
  "cpf": "123.456.789-09",
  "birthDate": "1985-03-15",
  "gender": "FEMALE",
  "phonePrimary": "(11) 99999-9999",
  "email": "maria@email.com",
  "bloodType": "A+",
  "allergies": ["Penicilina"],
  "tags": ["VIP", "Convênio"]
}

Response 201: PatientDTO
Response 409: { "error": "CPF_ALREADY_EXISTS", "existing_id": "uuid" }

Merge de Pacientes

http
POST /patients/merge
Content-Type: application/json

{
  "primary_id": "uuid-paciente-principal",
  "secondary_id": "uuid-paciente-duplicado"
}

Response 200: PatientDTO (paciente principal consolidado)

O merge consolida:

  • Todos os agendamentos do secundário → transferidos para o principal
  • Todos os registros de prontuário → transferidos para o principal
  • Todas as faturas → transferidas para o principal
  • O cadastro secundário é desativado com flag merged_into: primary_id

Índices do Banco de Dados

sql
-- Performance em buscas comuns
CREATE UNIQUE INDEX idx_patients_org_cpf ON patients(organization_id, cpf);
CREATE INDEX idx_patients_org_active ON patients(organization_id, is_active);
CREATE INDEX idx_patients_fullname_fts ON patients USING gin(to_tsvector('portuguese', full_name));

Exportação LGPD

O endpoint GET /patients/:id/export retorna um JSON completo com:

json
{
  "patient": { ... dados cadastrais ... },
  "appointments": [ ... histórico de atendimentos ... ],
  "medical_records": [ ... prontuários ... ],
  "invoices": [ ... faturas ... ],
  "audit_access_logs": [ ... quem acessou seus dados e quando ... ],
  "exported_at": "2026-05-19T10:00:00Z",
  "exported_by": "uuid-do-admin"
}

A exportação é registrada no audit log.

Desenvolvido com ❤️ pela equipe FastGivr.