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 pendentestheme/functions/wp/ajax.php:823-911— endpoints REST API para leitura de KPIstheme/templates/exportacao-kpis.php— template de exportaçãowp-config.php:81-88— constantes DB_KPI_*mysql-init/init.sql— criação do database
Regras de negócio
Tipos de coleta (formulários)
| Slug | Frequência | Descrição | Status |
|---|---|---|---|
diario-10h | Diária | Coleta às 10h (urgência/emergência) | Ativa |
diario-16h | Diária | Coleta às 16h (urgência/emergência) | Ativa |
mensal-geral | Mensal | Coleta mensal consolidada — unifica indicadores que estavam distribuídos nas coletas mensais anteriores | Ativa |
mensal | Mensal | Indicadores mensais gerais | Histórico |
mensal-centro-cirurgico | Mensal | Indicadores do Centro Cirúrgico | Histórico |
mensal-unidade-internacao | Mensal | Indicadores da Unidade de Internação | Histórico |
semestral | Semestral | Indicadores semestrais | Histórico |
indicador-diario-centro-cirurgico | Diária | Indicador diário do Centro Cirúrgico | Histórico |
kpi-list | — | Listagem 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-16hemensal-geral. - Coletas históricas (somente leitura):
mensal,mensal-centro-cirurgico,mensal-unidade-internacao,semestraleindicador-diario-centro-cirurgicopermanecem 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 coletasmensal,mensal-centro-cirurgicoemensal-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— diahospital_kpi_month— mêshospital_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-31 — isset($_POST['csrf_token']) e !empty($_POST['csrf_token']).
Permissões
Quem pode ENVIAR coletas (can_post_kpi)
| Condição | Resultado |
|---|---|
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ção | Resultado |
|---|---|
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ção | Resultado |
|---|---|
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():
- Tenta usar constantes
DB_KPI_HOST,DB_KPI_USER,DB_KPI_PASS,DB_KPI_DB_NAME. - 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.
| Coluna | Tipo | Descrição |
|---|---|---|
id_tipo_coleta | int unsigned PK | Identificador do tipo |
nome | varchar(45) | Nome legível |
slug | varchar(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.
| Coluna | Tipo | Descrição |
|---|---|---|
id_coleta | int unsigned PK | Identificador da coleta |
id_tipo_coleta | int unsigned | FK → tipo_coleta.id_tipo_coleta |
wp_bp_id_hospital | int | ID do BuddyPress Group do hospital |
wp_bp_id_usuario | int | ID do usuário WordPress que submeteu |
dt_coleta_inicio | timestamp | Início do período referente à coleta |
dt_coleta_termino | timestamp | Término do período referente à coleta |
dt_criacao | timestamp | Data de criação do registro |
dt_atualizacao | timestamp | Data da última atualização |
is_diagnostico_inicial | tinyint(1) | Flag: coleta de diagnóstico inicial (0/1) |
is_diagnostico_final | tinyint(1) | Flag: coleta de diagnóstico final (0/1) |
ciclo | varchar(255) | Identificador do ciclo ao qual a coleta pertence |
dt_liberacao_temporaria | datetime | Data de liberação temporária de edição (nullable) |
indicador
Catálogo dos indicadores disponíveis para coleta, com metadados de apresentação.
| Coluna | Tipo | Descrição |
|---|---|---|
id_indicador | int unsigned PK | Identificador do indicador |
chave_indicador | varchar(255) | Chave única usada como FK em dados_coleta |
titulo | text | Título de exibição |
descricao | text | Descrição do indicador |
formula | text | Fórmula de cálculo |
periodicidade | varchar(45) | Frequência (diária, mensal, semestral) |
unidade | text | Unidade de medida |
sentido_melhoria | varchar(100) | Direção de melhoria (ex: menor, maior) |
exportacao | varchar(10) | Flag de uso na exportação |
titulo_exportacao | text | Título alternativo para exportação |
dados_coleta
Valores individuais de cada indicador para uma coleta. Relação EAV (Entity-Attribute-Value).
| Coluna | Tipo | Descrição |
|---|---|---|
id_dados_coleta | int unsigned PK | Identificador do dado |
id_coleta | int unsigned | FK → coleta.id_coleta |
chave_indicador | varchar(255) | FK → indicador.chave_indicador |
valor | text | Valor 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.
| Coluna | Tipo | Descrição |
|---|---|---|
id | int unsigned PK | Identificador |
id_coleta | int unsigned | Referência à coleta de origem (nullable) |
Hospital | varchar(255) | Nome do hospital |
SIGLA_HOSPITAL | varchar(50) | Sigla do hospital |
HOSPITAL_RESUMIDO | varchar(50) | Nome resumido |
CNES | varchar(20) | Código CNES do hospital |
MUNICIPIO_IBGE_CODIGO | varchar(50) | Código IBGE do município |
Data | varchar(35) | Data de referência |
Hora | varchar(30) | Hora da coleta |
Tipo | varchar(20) | Tipo da coleta |
Status_Mes | varchar(25) | Status do mês |
CICLO | varchar(20) | Ciclo |
Data_Fechamento / Data_Fechamento_Envio | varchar | Datas de fechamento |
Considerar | varchar(25) | Flag de inclusão nos relatórios |
NEDOCS | varchar(127) | Valor NEDOCS |
IND_A … IND_G | varchar(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-911 — register_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:
- Liberação temporária (
verifyKPITemporaryRelease): se o campodt_liberacao_temporariada coleta está preenchido e ainda não venceu, a coleta pode ser editada até essa data/hora. - 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.php — canEditKPI(), 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:
- Admin seleciona uma ou mais coletas na listagem.
- Escolhe a ação "Liberar Edição" e confirma a data/hora limite no modal.
- O sistema chama
kpi_mass_temporarily_release_collections(), que gravadt_liberacao_temporariaem cada coleta viatemporarilyReleaseCollection(). - A partir desse momento,
canEditKPI()consultaverifyKPITemporaryRelease()e retorna a data limite enquanto ela não vencer. - Após o vencimento, a coleta volta a ser somente leitura.
Evidência: helpers.php — kpi_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.php — kpi_mass_delete_collections() | edit-kpi.php — acao_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_indicadorpor tipo de coleta (quais indicadores da tabelaindicadorpertencem a cada formulário). - Tabela
sala_de_comandopopulada por processo externo/manual — fluxo de atualização não documentado.