Checklist Sistemico
Módulo de inspeção sistemica de equipamentos eletrônicos instalados nos veículos. Diferente do checklist veicular comum, opera sobre itens rastreadores/dispositivos IoT com estados binários lidos diretamente do backend. Exclusivo Android na versão atual.
/ui/sistemic/) é independente do Checklist Veicular (/ui/checklist/). Usa os mesmos endpoints /v1/checklist mas com filtro origin=sistemic implícito e modelo de dados diferente.
Fluxo de Navegação
FragmentSistemicList — nav_sistemic_list
Lista todos os checklists sistemicos com chips de filtro por status. Suporta retry automático com backoff exponencial para HTTP 429 (via SistemicHttpUtils.kt).
FragmentSistemicSchedule — nav_sistemic_schedule
Agendamento de novos checklists sistemicos. Permite selecionar veículo e data/hora de execução.
FragmentCadSistemic — nav_sistemic_cad
Visualização e execução do checklist. Exibe contagem regressiva ao vivo, métricas de progresso, filtros por estado dos itens e botão de ação contextual (Iniciar / Finalizar).
Máquina de Estado do Checklist
| Status | Label | Cor | Ação disponível |
|---|---|---|---|
| P | Pendente | Orange | Iniciar (requer perm 423) |
| I | Iniciado | Azul | Finalizar (qualquer usuário autenticado) |
| F | Finalizado | Verde | Somente leitura |
| C | Cancelado | Vermelho | Somente leitura |
Estados dos Itens
| state | Label | Tone | Descrição |
|---|---|---|---|
"" (vazio) | Aguardando leitura | warning / orange | Item ainda não avaliado — conta como pending nas métricas |
"0" | Com Problema | danger / red | Falha genérica detectada |
"1" | Não Instalado | warning / orange | Dispositivo não encontrado no veículo |
"2" | Com Problema | danger / red | Falha com tipo específico (stateType) |
"3" | OK | success / green | Item verificado e aprovado |
"4" | Análise Humana | info / azul | Requer revisão manual por inspetor |
"5" | Não Verificado | neutral / cinza | Fora do escopo desta inspeção |
"9" | Não Aplicado | info | Item não se aplica ao veículo |
Tipos de problema para state = "2"
| stateType | Label |
|---|---|
"0" | Ausência de Alerta |
"1" | Alerta Contínuo |
"2" | Falha Comunicação |
"3" | Não Atua |
Lógica de Contagem Regressiva
Visível apenas para status P e I. O prazo (deadline) é calculado assim:
// Status P — prazo para iniciar
deadline = scheduleDatetime + 86400 // +24 horas
// Status I — prazo para concluir
deadline = startDatetime + 2400 // +40 minutos
?: scheduleDatetime + 86400 // fallback se startDatetime == null
O timer atualiza a cada segundo no UI thread via Handler(Looper.getMainLooper()). Quando remaining < 0 o contador exibe tempo expirado e o label muda para EXPIRADO.
Métricas de Progresso
Calculadas em computeMetrics() em SistemicModels.kt:
data class SistemicChecklistMetrics(
val total: Int,
val ok: Int, // state == "3"
val problem: Int, // state in ["0", "2"]
val notInstalled: Int, // state == "1"
val notVerified: Int, // state == "5"
val notApplied: Int, // state == "9"
val pending: Int, // state == "" (vazio)
)
val done = ok + problem + notInstalled + notVerified + notApplied
val pct = if (total > 0) done * 100 / total else 0
state == "" (vazio) contam como pending e não entram no numerador done. O progresso só avança quando o item recebe qualquer estado explícito.
Permissões
| Código | Ação protegida |
|---|---|
423 | Iniciar checklist sistemico (botão "Iniciar" visível apenas com esta permissão) |
// Leitura em SharedPreferences "DATA", chave "perms_user"
val permissionsJson = dataPrefs.getString("perms_user", "[]") ?: "[]"
hasPerm423 = permissionsJson.contains("423")
Filtros e Busca nos Itens
O SistemicItemAdapter.filter() aceita dois parâmetros combinados:
| Chip | stateFilter | States mapeados |
|---|---|---|
| OK | "ok" | "3" |
| Pendente | "pending" | "" (vazio) |
| Problema | "problem" | "0", "2" |
| Análise | "analysis" | "4" |
| (nenhum) | null | Todos |
A busca textual (etSearchItem) filtra pelo campo item.name com ignoreCase = true e é combinada com o filtro de chip em tempo real via TextWatcher.
Modelos de Dados
data class SistemicChecklist(
val id: String,
val plate: String, // placa do veículo
val status: String, // "P" | "I" | "F" | "C"
val statusLabel: String,
val origin: String,
val nameDoer: String, // executor
val nameApplicant: String, // solicitante
val scheduleDatetime: Long?, // Unix epoch (segundos)
val startDatetime: Long?,
val endDatetime: Long?,
val registrationDatetime: Long?,
val canStart: Boolean,
val resultChecklist: List<SistemicChecklistItem>,
)
data class SistemicChecklistItem(
val id: String,
val name: String,
val state: String, // "" | "0".."9"
val stateLabel: String,
val stateTone: String, // "success" | "danger" | "warning" | "neutral" | "info"
val stateType: String, // relevante apenas quando state == "2"
val stateTypeLabel: String,
val statusOn: Long?, // Unix epoch (segundos)
val statusOff: Long?,
val acessorio: Boolean?,
val datetime: Long?, // última verificação
)
Date(epochSeconds * 1000).
Endpoints
/v1/checklist
origin quando necessário. ViewModel aplica retry com backoff exponencial (1s → 2s → 4s, máx 30s) para HTTP 429./v1/checklist/{id}
fetchChecklistById(id, token) em SistemicCadViewModel. Retorna o SistemicChecklist completo com resultChecklist preenchido./v1/checklist/{id}/start
AlertDialog de confirmação antes de chamar viewModel.startChecklist(id, token)./v1/checklist/{id}/finalize
fetchChecklistById.Retry e Rate Limiting
A classe SistemicHttpUtils.kt implementa retry com backoff exponencial para absorver respostas HTTP 429 do backend:
// Sequência de delays: 1s → 2s → 4s → ... // Máximo: 30 segundos de espera acumulada // Máximo de tentativas: configurável no ViewModel
SistemicHttpUtils — não implemente retry manual nos ViewModels.
Expand/Collapse de Itens
Cada item do RecyclerView é expansível. O estado é mantido em expandedIds: MutableSet<String> no adapter. Ao expandir, exibe:
- Status On — momento em que o dispositivo ficou ativo
- Status Off — momento em que o dispositivo ficou inativo
- Resultado —
stateLabelcom pill colorido - Detalhe —
stateTypeLabel(relevante para state = "2")