Pular para o conteúdo principal

Coleta de KPIs

Resumo

Sistema de coleta de indicadores hospitalares (KPIs) com formulários diários (10h e 16h), mensais, semestrais e específicos por área (Centro Cirúrgico, Unidade de Internação). Os dados são armazenados em um banco MySQL separado (kpi).

Fontes de evidência

  • theme/functions/kpis/forms.php — lógica de permissões, conexão DB, listagem de coletas pendentes
  • theme/functions/wp/ajax.php:823-911 — endpoints REST API para leitura de KPIs
  • theme/templates/exportacao-kpis.php — template de exportação
  • wp-config.php:81-88 — constantes DB_KPI_*
  • mysql-init/init.sql — criação do database

Regras de negócio

Tipos de coleta (formulários)

SlugFrequênciaDescriçãoStatus
diario-10hDiáriaColeta às 10h (urgência/emergência)Ativa
diario-16hDiáriaColeta às 16h (urgência/emergência)Ativa
mensal-geralMensalColeta mensal consolidada — unifica indicadores que estavam distribuídos nas coletas mensais anterioresAtiva
mensalMensalIndicadores mensais geraisHistórico
mensal-centro-cirurgicoMensalIndicadores do Centro CirúrgicoHistórico
mensal-unidade-internacaoMensalIndicadores da Unidade de InternaçãoHistórico
semestralSemestralIndicadores semestraisHistórico
indicador-diario-centro-cirurgicoDiáriaIndicador diário do Centro CirúrgicoHistórico
kpi-listListagem de KPIs

Evidência: forms.php:33-44 — lista de form_name aceitos em is_kpi_form_action().

Status atual das coletas

Ao longo da evolução do sistema, as coletas mensais foram consolidadas:

  • Coletas ativas (aceitam novos registros): diario-10h, diario-16h e mensal-geral.
  • Coletas históricas (somente leitura): mensal, mensal-centro-cirurgico, mensal-unidade-internacao, semestral e indicador-diario-centro-cirurgico permanecem no código exclusivamente para permitir a visualização dos dados já coletados pelos hospitais quando essas coletas estavam em atividade. Não aceitam novos registros.
  • Sobre a mensal-geral: esta coleta passou a centralizar campos de indicadores que anteriormente estavam distribuídos nas coletas mensal, mensal-centro-cirurgico e mensal-unidade-internacao, consolidando a coleta mensal em um único formulário.

Data de início das coletas

Cada hospital (BP Group) define quando suas coletas começam via group meta:

  • hospital_kpi_day — dia
  • hospital_kpi_month — mês
  • hospital_kpi_year — ano

O sistema gera uma lista de datas desde o início até hoje. Coletas já preenchidas são excluídas.

Evidência: forms.php:217-232 — leitura dos metadados e cálculo das datas.

Bloqueio de período atual

  • Mensal: O mês corrente é bloqueado (só preenche meses anteriores).
  • Semestral: O semestre corrente é bloqueado.
  • Diário: Sem bloqueio — preenche o dia atual.

Evidência: forms.php:247-256 — verificação $date->format("Ym") == $now->format('Ym').

CSRF Token

Todo submit de formulário KPI exige csrf_token não vazio via POST.

Evidência: forms.php:30-31isset($_POST['csrf_token']) e !empty($_POST['csrf_token']).

Permissões

Quem pode ENVIAR coletas (can_post_kpi)

CondiçãoResultado
Roles globais: administrador_site, administrator✅ Pode postar
hospital_group_admin() do grupo✅ Pode postar
group_user_is_kpi() do grupo✅ Pode postar
Admin do grupo BP (groups_is_user_admin)✅ Pode postar
group_user_is_admusers() (admin de usuários do grupo)❌ Não pode postar
Não é membro do grupo❌ Não pode postar

Evidência: forms.php:46-75.

Quem pode VISUALIZAR KPIs (can_read_kpi)

CondiçãoResultado
Roles globais: administrator, ministerio_da_saude, administrador_site✅ Pode ler
hospital_group_admin() do grupo✅ Pode ler
Membro do grupo com role interna admusers_users (group_user_is_admusers)✅ Pode ler
group_user_is_kpi() ou group_user_is_read_kpi()✅ Pode ler
Admin do grupo BP✅ Pode ler
Não é membro do grupo❌ Não pode ler

Evidência: forms.php:89-117.

Postar KPI fora do contexto de grupo (can_post_kpi_outside_group)

Usuários com roles globais (administrador_site, administrator) podem postar fora do contexto de grupo. Para os demais, o sistema verifica se o usuário tem ao menos um grupo em que seja hospital_group_admin(), admin BP do grupo ou group_user_is_kpi().

Evidência: forms.php:120-148.

Quem pode EXPORTAR KPIs (verify_export_kpi)

CondiçãoResultado
Roles globais: administrador_site, administrator, ministerio_da_saude✅ Pode exportar
Super admin (is_super_admin)✅ Pode exportar
hospital_group_admin() no contexto atual✅ Pode exportar
group_user_is_kpi() ou group_user_is_read_kpi()✅ Pode exportar
Admin do grupo BP (groups_is_user_admin)✅ Pode exportar
Não membro do grupo atual❌ Não pode exportar

Evidência: theme/functions/kpis/forms_action.php:241-260.

Banco de dados

Conexão

Banco separado kpi via função kpi_db():

  1. Tenta usar constantes DB_KPI_HOST, DB_KPI_USER, DB_KPI_PASS, DB_KPI_DB_NAME.
  2. Fallback: lê configuração do ACF Options (configurations.environments).

Evidência: forms.php:180-212.

Tabelas

tipo_coleta

Catálogo dos tipos de formulário de coleta.

ColunaTipoDescrição
id_tipo_coletaint unsigned PKIdentificador do tipo
nomevarchar(45)Nome legível
slugvarchar(45)Slug usado no código para identificar o formulário (ex: diario-10h, mensal-geral)

coleta

Registro de cada submissão de formulário por hospital e período.

ColunaTipoDescrição
id_coletaint unsigned PKIdentificador da coleta
id_tipo_coletaint unsignedFK → tipo_coleta.id_tipo_coleta
wp_bp_id_hospitalintID do BuddyPress Group do hospital
wp_bp_id_usuariointID do usuário WordPress que submeteu
dt_coleta_iniciotimestampInício do período referente à coleta
dt_coleta_terminotimestampTérmino do período referente à coleta
dt_criacaotimestampData de criação do registro
dt_atualizacaotimestampData da última atualização
is_diagnostico_inicialtinyint(1)Flag: coleta de diagnóstico inicial (0/1)
is_diagnostico_finaltinyint(1)Flag: coleta de diagnóstico final (0/1)
ciclovarchar(255)Identificador do ciclo ao qual a coleta pertence
dt_liberacao_temporariadatetimeData de liberação temporária de edição (nullable)

indicador

Catálogo dos indicadores disponíveis para coleta, com metadados de apresentação.

ColunaTipoDescrição
id_indicadorint unsigned PKIdentificador do indicador
chave_indicadorvarchar(255)Chave única usada como FK em dados_coleta
titulotextTítulo de exibição
descricaotextDescrição do indicador
formulatextFórmula de cálculo
periodicidadevarchar(45)Frequência (diária, mensal, semestral)
unidadetextUnidade de medida
sentido_melhoriavarchar(100)Direção de melhoria (ex: menor, maior)
exportacaovarchar(10)Flag de uso na exportação
titulo_exportacaotextTítulo alternativo para exportação

dados_coleta

Valores individuais de cada indicador para uma coleta. Relação EAV (Entity-Attribute-Value).

ColunaTipoDescrição
id_dados_coletaint unsigned PKIdentificador do dado
id_coletaint unsignedFK → coleta.id_coleta
chave_indicadorvarchar(255)FK → indicador.chave_indicador
valortextValor submetido para o indicador

sala_de_comando

Tabela desnormalizada de visão consolidada, usada para relatórios e exportações. Agrega dados de coletas diárias e mensais em formato pronto para consumo.

ColunaTipoDescrição
idint unsigned PKIdentificador
id_coletaint unsignedReferência à coleta de origem (nullable)
Hospitalvarchar(255)Nome do hospital
SIGLA_HOSPITALvarchar(50)Sigla do hospital
HOSPITAL_RESUMIDOvarchar(50)Nome resumido
CNESvarchar(20)Código CNES do hospital
MUNICIPIO_IBGE_CODIGOvarchar(50)Código IBGE do município
Datavarchar(35)Data de referência
Horavarchar(30)Hora da coleta
Tipovarchar(20)Tipo da coleta
Status_Mesvarchar(25)Status do mês
CICLOvarchar(20)Ciclo
Data_Fechamento / Data_Fechamento_EnviovarcharDatas de fechamento
Considerarvarchar(25)Flag de inclusão nos relatórios
NEDOCSvarchar(127)Valor NEDOCS
IND_AIND_Gvarchar(127)Valores dos indicadores por posição

Diagrama ER

erDiagram
tipo_coleta {
int id_tipo_coleta PK
varchar nome
varchar slug
}
coleta {
int id_coleta PK
int id_tipo_coleta FK
int wp_bp_id_hospital
int wp_bp_id_usuario
timestamp dt_coleta_inicio
timestamp dt_coleta_termino
tinyint is_diagnostico_inicial
tinyint is_diagnostico_final
varchar ciclo
datetime dt_liberacao_temporaria
}
indicador {
int id_indicador PK
varchar chave_indicador
text titulo
text formula
varchar periodicidade
varchar sentido_melhoria
}
dados_coleta {
int id_dados_coleta PK
int id_coleta FK
varchar chave_indicador FK
text valor
}
sala_de_comando {
int id PK
int id_coleta
varchar Hospital
varchar CNES
varchar Data
varchar Tipo
varchar NEDOCS
}

tipo_coleta ||--o{ coleta : "id_tipo_coleta"
coleta ||--o{ dados_coleta : "id_coleta"
indicador ||--o{ dados_coleta : "chave_indicador"
coleta ||--o{ sala_de_comando : "id_coleta"

REST API (leitura)

Todos os endpoints de leitura de KPIs estão sob /wp-json/lean/v1/ e requerem can_read_kpi.

Exemplos: /lean/v1/nedocs, /lean/v1/kpi/giro_tmp_fator, /lean/v1/kpi/nps.

Evidência: theme/functions/wp/ajax.php:823-911register_rest_route('lean/v1', ...).

Fluxo de Coleta de KPIs

sequenceDiagram
participant U as Usuário KPI
participant WP as WordPress
participant KDB as Banco KPI

U->>WP: Acessa formulário de coleta
WP->>WP: Verifica can_post_kpi()
alt Sem permissão
WP-->>U: Acesso negado
end
WP->>KDB: get_kpi_items() — coletas pendentes
KDB-->>WP: Lista de datas sem coleta
WP-->>U: Formulário com datas pendentes

U->>WP: Submete formulário POST + csrf_token
WP->>WP: is_kpi_form_action() valida form_name e csrf_token
WP->>KDB: INSERT INTO coleta
WP->>KDB: INSERT INTO dados_coleta por chave_indicador
KDB-->>WP: OK
WP-->>U: Coleta registrada

Edição de coletas

Regra padrão de edição

Uma coleta pode ser editada pela função canEditKPI(), que combina duas verificações em ordem:

  1. Liberação temporária (verifyKPITemporaryRelease): se o campo dt_liberacao_temporaria da coleta está preenchido e ainda não venceu, a coleta pode ser editada até essa data/hora.
  2. Janela padrão (verifyKPIByDate): caso não haja liberação temporária ativa, a coleta pode ser editada até o dia 11 do mês seguinte ao período da coleta.

Evidência: theme/functions/kpis/helpers.phpcanEditKPI(), verifyKPIByDate(), verifyKPITemporaryRelease().

Liberação temporária de edição

Administradores do grupo (is_site_admin) podem liberar coletas já fora da janela padrão para edição, definindo uma data/hora limite via modal na tela de gestão de coletas.

Quem pode usar: administrator, administrador_site ou hospital_group_admin() do grupo.

Como funciona:

  1. Admin seleciona uma ou mais coletas na listagem.
  2. Escolhe a ação "Liberar Edição" e confirma a data/hora limite no modal.
  3. O sistema chama kpi_mass_temporarily_release_collections(), que grava dt_liberacao_temporaria em cada coleta via temporarilyReleaseCollection().
  4. A partir desse momento, canEditKPI() consulta verifyKPITemporaryRelease() e retorna a data limite enquanto ela não vencer.
  5. Após o vencimento, a coleta volta a ser somente leitura.

Evidência: helpers.phpkpi_mass_temporarily_release_collections(), temporarilyReleaseCollection() | edit-kpi.php — modal #modal-liberar-edicao, $_REQUEST['liberar_temporariamente'].

Fluxo de liberação temporária

sequenceDiagram
participant A as Admin do Grupo
participant UI as Tela de Gestão KPI
participant WP as WordPress
participant KDB as Banco KPI

A->>UI: Seleciona coleta(s) e escolhe "Liberar Edição"
UI->>A: Exibe modal com campo data/hora limite
A->>UI: Confirma data limite
UI->>WP: POST liberar_temporariamente[] + datahora_limite
WP->>WP: is_site_admin() verifica permissão
WP->>KDB: UPDATE coleta SET dt_liberacao_temporaria = ? WHERE id_coleta IN (...)
KDB-->>WP: OK
WP-->>UI: N coleta(s) liberada(s) até DD/MM/AAAA HH:mm

Note over A,KDB: Usuário KPI edita a coleta dentro do prazo
A->>WP: Acessa editar coleta
WP->>KDB: SELECT dt_liberacao_temporaria FROM coleta
KDB-->>WP: dt_liberacao_temporaria
WP->>WP: canEditKPI() → verifyKPITemporaryRelease()
alt Dentro do prazo
WP-->>A: Formulário de edição liberado
else Prazo vencido
WP-->>A: Coleta bloqueada
end

Exclusão em massa

Administradores do grupo também podem excluir coletas em massa. A operação é irreversível e exclui tanto a coleta quanto todos os dados_coleta associados.

Evidência: helpers.phpkpi_mass_delete_collections() | edit-kpi.phpacao_massa = deletar.

Pendências

  • Schema SQL do banco KPI não está versionado no repositório — manter dump atualizado em mysql-init/.
  • Falta documentação dos chave_indicador por tipo de coleta (quais indicadores da tabela indicador pertencem a cada formulário).
  • Tabela sala_de_comando populada por processo externo/manual — fluxo de atualização não documentado.