Auditoría del beneficio de alimentación en campo

Auditoría
R
Quarto
Beneficios
Un año de recargas de alimentación cruzado con el diario de campo y el registro de personal. Cuánto se pagó fuera de la regla, dónde y por qué.

Caso ficticio. Fiorena Redes Elétricas S.A., sus bases, personas y registros no existen. Los datos se generaron desde cero con un script en R, con reglas de beneficio inventadas y defectos de tamaño conocido. El método es real.

Descargar el informe (PDF) · Descargar los casos a revisar (CSV)

Los comentarios del código R están en portugués, el idioma original del caso.

La pregunta

La contraloría de Fiorena vio que el valor pagado en alimentación por día de cuadrilla en campo subió de R$ 219 en el primer semestre de 2025 a R$ 239 en el segundo, un 9,5% más, sin reajuste de valores ni cambios en el tipo de servicio. La pregunta era simple: ¿cuánto de eso es gasto legítimo y cuánto se pagó fuera de la regla?

Dos líneas mes a mes. El valor pagado sube de unos 205 reales en enero a cerca de 250 reales en diciembre, con un salto en agosto. La línea sin lo indebido sube menos y queda por debajo de la otra desde agosto.

Valor pagado en alimentación por día de cuadrilla en campo, mes a mes, en 2025. La línea punteada es el mismo valor sin lo que la auditoría clasificó como indebido. La marca en agosto es el cambio del sistema de recargas.

Dos líneas mes a mes. El valor pagado sube de unos 205 reales en enero a cerca de 250 reales en diciembre, con un salto en agosto. La línea sin lo indebido sube menos y queda por debajo de la otra desde agosto.

Valor pagado en alimentación por día de cuadrilla en campo, mes a mes, en 2025. La línea punteada es el mismo valor sin lo que la auditoría clasificó como indebido. La marca en agosto es el cambio del sistema de recargas.

La caída de julio tiene una causa en los datos: julio y enero son los meses con más personas de vacaciones (en julio, 81 electricistas por día hábil, frente a 37 en la mediana del año), y cada cuadrilla salió a campo con 3,5 personas, frente a 3,8 en la mediana. El valor por persona en campo no bajó: se mantuvo entre R$ 58 y R$ 60 de enero a julio.

Cada electricista recibe en la tarjeta de alimentación una recarga por día en campo. La recarga la registra la base, la aprueba el supervisor y se paga sin cruce automático con el diario de campo ni con el registro de vacaciones y ausencias. Nadie había mirado juntos los 12 meses de registros.

La auditoría respondió tres preguntas, en este orden:

  1. ¿Cuánto se pagó fuera de una regla objetiva (duplicidad, por encima del tope, persona que no estaba trabajando)?
  2. ¿Cuánto se pagó sin respaldo: sin registro de la cuadrilla en campo ese día, o con una justificación que no explica nada?
  3. ¿Dónde se concentra, y por qué?

La regla y los datos

La regla del beneficio:

  • Almuerzo de R$ 52 por día en campo.
  • Cena de R$ 44, solo cuando el diario de campo registra pernocte de la cuadrilla.
  • Extra de hasta R$ 24, solo con una de las justificaciones de la lista: “desplazamiento de más de 300 km” o “jornada extendida en más de 2 horas”.
  • Tope de R$ 120 por persona por día, sumando todo, y como máximo una recarga de cada tipo por día.
  • Solo para quien está activo, fuera de vacaciones y ausencias, y en una cuadrilla que estuvo en campo ese día.

Se auditaron 155.909 recargas de 2025, por un total de R$ 7,63 millones, pagadas a 649 personas de 8 bases, cruzadas con 33.254 registros de cuadrillas en campo en el diario, con el registro de personal y con las vacaciones y ausencias de RR. HH.

Método

Cada recarga pasa por las mismas verificaciones y termina en una de cuatro conclusiones. La auditoría separa lo que es un error objetivo, que se puede recuperar, de lo que solo merece una segunda mirada de la base; no saca conclusiones sobre la intención de nadie.

  1. Preparar. Usar el día trabajado, y no la fecha en que se registró la recarga, y vincular cada recarga con el registro de personal, las ausencias y la cuadrilla de la persona ese día.
  2. Revisar las reglas objetivas. Duplicidad, persona fuera de servicio, cena sin pernocte, extra sin justificación y suma del día por encima del tope. En el tope, solo el excedente cuenta como indebido.
  3. Revisar el respaldo. ¿La cuadrilla estaba en campo ese día? ¿La justificación del extra es válida, vaga o falta? Un diccionario de términos acepta errores de tipeo, para que “deslocamneto acima de 300km” (con error, en portugués) cuente como válida.
  4. Comparar con lo esperado. Para cada base y mes, el valor por día en campo se compara con el de las otras bases en el mismo mes. Queda fuera del rango esperado el grupo que se aleja mucho más de lo que las bases suelen alejarse entre sí (el criterio de Tukey, en el código).
  5. Puntuar el riesgo. Un punto por cada señal: regla violada, sin respaldo de campo, justificación vaga o ausente, base y mes por encima del rango.
  6. Concluir. Cada recarga recibe una de las cuatro conclusiones de abajo.
Conclusión Cuándo Qué hacer
Indebido Violó una regla objetiva Revertir o recuperar, según la política de la empresa y con apoyo de RR. HH. y del área legal
Revisar Ninguna regla violada, pero sin respaldo de campo o con dos señales o más La base confirma o corrige en un plazo de 15 días
Atención Una sola señal, sin regla violada Entra en la muestra del mes siguiente
Conforme Ninguna señal Nada que hacer

Indebido

Cuándo: Violó una regla objetiva

Qué hacer: Revertir o recuperar, según la política de la empresa y con apoyo de RR. HH. y del área legal

Revisar

Cuándo: Ninguna regla violada, pero sin respaldo de campo o con dos señales o más

Qué hacer: La base confirma o corrige en un plazo de 15 días

Atención

Cuándo: Una sola señal, sin regla violada

Qué hacer: Entra en la muestra del mes siguiente

Conforme

Cuándo: Ninguna señal

Qué hacer: Nada que hacer

Ver el código R de la etapa 1: preparar
# O que vale é o dia de referência (o dia trabalhado), e não a data em que a
# recarga foi lançada. Cada recarga é ligada ao cadastro, às ausências e à
# equipe da pessoa naquele dia no diário de campo.
recargas <- read_csv("dados/recargas.csv.gz", show_col_types = FALSE, na = "",
                     col_types = cols(justificativa = "c"))
diario <- read_csv("dados/diario_campo.csv", show_col_types = FALSE)
cadastro <- read_csv("dados/cadastro.csv", show_col_types = FALSE, na = "")
ausencias <- read_csv("dados/ausencias.csv", show_col_types = FALSE)

base_auditoria <- recargas |>
  mutate(dia = dia_referencia) |>
  left_join(cadastro |> select(matricula, equipe, admissao, desligamento), "matricula") |>
  left_join(ausencias |> select(matricula, tipo_ausencia = tipo, inicio, fim),
            join_by(matricula, between(dia, inicio, fim))) |>
  left_join(diario |> transmute(equipe, dia = data, em_campo = TRUE, pernoite = pernoite == "sim"),
            c("equipe", "dia")) |>
  mutate(em_campo = coalesce(em_campo, FALSE))
Ver el código R de la etapa 2: reglas objetivas
# Regras objetivas: cada violação pode ser cobrada. No teto, só o excedente
# conta como indevido; ele é calculado depois de tirar o que já é indevido por
# outra regra, para não contar o mesmo real duas vezes.
normalizar <- function(x) {
  x <- tolower(iconv(coalesce(x, ""), to = "ASCII//TRANSLIT"))
  x <- gsub("([0-9])\\s*km", "\\1 km", x)
  x <- gsub("([0-9])\\s*h\\b", "\\1 horas", x)
  trimws(gsub("[^a-z0-9 ]", " ", gsub("\\s+", " ", x)))
}
# Dicionário com tolerância a erro de digitação: a justificativa vale se
# estiver a até 15% de distância (em letras) de uma das frases da regra.
classificar_justificativa <- function(x) {
  n <- normalizar(x)
  validas <- normalizar(JUSTIFICATIVAS_VALIDAS)
  dist <- adist(n, validas, partial = FALSE) / outer(nchar(n), nchar(validas), pmax)
  case_when(n == "" ~ "ausente",
            apply(dist, 1, min) <= 0.15 ~ "válida",
            TRUE ~ "vaga")
}

# Cada texto diferente é classificado uma vez só.
textos <- unique(coalesce(base_auditoria$justificativa[base_auditoria$tipo == "Extra"], ""))
classes <- classificar_justificativa(textos)

auditada <- base_auditoria |>
  mutate(justificativa_classe = if_else(tipo == "Extra", classes[match(coalesce(justificativa, ""), textos)], NA)) |>
  arrange(matricula, dia, tipo, data_recarga, id) |>
  group_by(matricula, dia, tipo) |>
  mutate(duplicidade = row_number() > 1) |>
  ungroup() |>
  mutate(
    fora_do_trabalho = dia < admissao | (!is.na(desligamento) & dia > desligamento) | !is.na(tipo_ausencia),
    jantar_sem_pernoite = tipo == "Jantar" & !coalesce(pernoite, FALSE),
    extra_sem_justificativa = tipo == "Extra" & justificativa_classe == "ausente",
    motivo_regra = case_when(duplicidade ~ "Duplicidade",
                             fora_do_trabalho ~ "Pessoa fora do trabalho",
                             jantar_sem_pernoite ~ "Jantar sem pernoite",
                             extra_sem_justificativa ~ "Extra sem justificativa"),
    valor_indevido = if_else(is.na(motivo_regra), 0, valor)
  )

# Teto diário: soma do que não é indevido por outra regra; o excedente sai
# primeiro do extra, depois do jantar.
ordem_corte <- c("Extra" = 1, "Jantar" = 2, "Almoço" = 3)
auditada <- auditada |>
  mutate(restante = valor - valor_indevido, corte = ordem_corte[tipo]) |>
  group_by(matricula, dia) |>
  mutate(excedente_dia = pmax(sum(restante) - TETO, 0)) |>
  arrange(corte, .by_group = TRUE) |>
  mutate(antes = cumsum(restante) - restante,
         acima_do_teto = pmin(restante, pmax(excedente_dia - antes, 0))) |>
  ungroup() |>
  mutate(valor_indevido = valor_indevido + acima_do_teto,
         motivo_regra = if_else(is.na(motivo_regra) & acima_do_teto > 0, "Acima do teto", motivo_regra),
         regra = !is.na(motivo_regra)) |>
  select(-restante, -corte, -excedente_dia, -antes)
Ver el código R de la etapa 3: respaldo
# A equipe estava em campo naquele dia? A justificativa do extra é válida,
# vaga ou ausente?
auditada <- auditada |>
  mutate(sem_lastro = !em_campo,
         justificativa_fraca = tipo == "Extra" & justificativa_classe %in% c("vaga", "ausente"))
Ver el código R de la etapa 4: rango esperado
# Valor pago por dia de equipe em campo, por base e mês. Como o nível geral
# muda de um mês para outro (mais pernoites no segundo semestre), cada base é
# comparada com a mediana das bases no mesmo mês; a faixa esperada desse
# índice vem do critério de Tukey sobre todos os grupos com pelo menos 15 dias
# de equipe em campo. Como a auditoria procura pagamento a mais, só ficar
# acima da faixa conta como sinal de risco; abaixo dela, o grupo só é anotado.
dias_campo <- diario |>
  mutate(mes = format(data, "%Y-%m")) |>
  count(base, mes, name = "dias_equipe")
base_mes <- auditada |>
  mutate(mes = format(dia, "%Y-%m")) |>
  group_by(base, mes) |>
  summarise(valor = sum(valor), .groups = "drop") |>
  left_join(dias_campo, c("base", "mes")) |>
  mutate(valor_dia = valor / dias_equipe) |>
  group_by(mes) |>
  mutate(mediana_mes = median(valor_dia), indice = valor_dia / mediana_mes) |>
  ungroup()
validos <- base_mes |> filter(dias_equipe >= 15)
q <- quantile(validos$indice, c(0.25, 0.75))
faixa <- c(q[[1]] - 1.5 * diff(q), q[[2]] + 1.5 * diff(q))
base_mes <- base_mes |>
  mutate(faixa_min = faixa[1] * mediana_mes, faixa_max = faixa[2] * mediana_mes,
         abaixo_da_faixa = dias_equipe >= 15 & indice < faixa[1],
         fora_da_faixa = dias_equipe >= 15 & indice > faixa[2])
auditada <- auditada |>
  mutate(mes = format(dia, "%Y-%m")) |>
  left_join(base_mes |> select(base, mes, fora_da_faixa), c("base", "mes")) |>
  mutate(fora_da_faixa = coalesce(fora_da_faixa, FALSE))
Ver el código R de la etapa 5: puntaje de riesgo
# Um ponto para cada sinal, de 0 a 4.
auditada <- auditada |>
  mutate(score = regra + sem_lastro + justificativa_fraca + fora_da_faixa,
         score_sem_regra = score - regra)
Ver el código R de la etapa 6: conclusión
# Indevido: violou uma regra objetiva. Revisar: sem regra violada, mas sem
# lastro de campo ou com score de 2 ou mais. Atenção: score 1. Regular: 0.
# Numa recarga que passou do teto só em parte, o excedente é Indevido e o
# resto recebe a conclusão que teria sem essa regra.
concluir <- function(sem_lastro, score) {
  case_when(sem_lastro | score >= 2 ~ "Revisar", score == 1 ~ "Atenção", TRUE ~ "Regular")
}
auditada <- auditada |>
  mutate(conclusao = if_else(regra, "Indevido", concluir(sem_lastro, score)),
         conclusao_resto = concluir(sem_lastro, score_sem_regra),
         valor_resto = valor - valor_indevido)
NIVEIS <- c("Indevido", "Revisar", "Atenção", "Regular")

Resultado

Del valor pagado en el año, R$ 305 mil (4,0%) fueron indebidos, y otros R$ 235 mil (3,1%) necesitan confirmación de la base.

Una barra horizontal con el valor del año. Indebido, Revisar y Atención ocupan juntos poco más de una décima parte de la barra; el resto es Conforme.

El valor pagado en 2025, dividido en las cuatro conclusiones de la auditoría.

Una barra horizontal con el valor del año. Indebido, Revisar y Atención ocupan juntos poco más de una décima parte de la barra; el resto es Conforme.

El valor pagado en 2025, dividido en las cuatro conclusiones de la auditoría.
  • Indebido es lo que violó una regla objetiva y se puede recuperar.
  • Revisar está formado casi todo por recargas sin respaldo de campo: R$ 234 mil en 4.500 recargas registradas en días en que la cuadrilla no aparece en el diario. Puede ser una falla del diario, y no de la recarga; por eso la base confirma antes de cualquier recuperación.
  • Atención no es una acusación. De las 8.686 recargas en Atención, 7.925 están ahí solo porque la base y el mes quedaron por encima del rango esperado; la recarga en sí cumple la regla. Entre ellas hay 1.072 registros que solo parecían error (registrados uno o dos días después, pernocte anotado con atraso, justificación con error de tipeo). Las otras 872 tienen una justificación vaga, como “ajuste” o “conforme combinado” (según lo acordado).

Lo indebido por tipo de defecto

Barras horizontales de mayor a menor. Duplicidad, en azul, es el mayor defecto, seguido de cena sin pernocte, persona fuera de servicio, por encima del tope y extra sin justificación.

Valor indebido en 2025 por tipo de defecto. En el tope, solo el excedente por encima del límite diario.

Barras horizontales de mayor a menor. Duplicidad, en azul, es el mayor defecto, seguido de cena sin pernocte, persona fuera de servicio, por encima del tope y extra sin justificación.

Valor indebido en 2025 por tipo de defecto. En el tope, solo el excedente por encima del límite diario.

Qué explica el salto del segundo semestre

El valor por día en campo subió R$ 20,86. De ese aumento, R$ 10,21 (49%) vinieron de pagos indebidos. Otros R$ 8,51 (41%) vinieron de más cenas legítimas, porque los pernoctes pasaron del 11,5% al 16,8% de los días en campo. El resto, R$ 2,14, acompaña a los pernoctes, en los extras.

Dónde y por qué

  • El cambio de sistema en agosto creó duplicidades. Hasta julio suman R$ 6 mil; de agosto a diciembre, R$ 112 mil. El sistema nuevo acepta dos recargas del mismo tipo para la misma persona el mismo día.
  • El registro de personal llega con atraso. El 100% de las recargas pagadas a personas de vacaciones cayeron en los cinco primeros días del período: la base se entera de las vacaciones después de que empezaron.
  • Dos bases pagan cena sin pernocte. La Base 3 y la Base 6 concentran el 100% de las cenas sin pernocte, y son las únicas con meses por encima del rango esperado: 3 meses en la primera y 3 en la segunda.

Ocho gráficos pequeños, uno por base. En seis bases la línea queda dentro del rango gris todo el año. En las bases 3 y 6, en azul, la línea pasa por encima del rango en tres meses cada una.

Valor pagado por día de cuadrilla en campo, por base y mes, frente al rango esperado (área gris). Los puntos azules son los meses por encima del rango.

Ocho gráficos pequeños, uno por base. En seis bases la línea queda dentro del rango gris todo el año. En las bases 3 y 6, en azul, la línea pasa por encima del rango en tres meses cada una.

Valor pagado por día de cuadrilla en campo, por base y mes, frente al rango esperado (área gris). Los puntos azules son los meses por encima del rango.

Casos a revisar

La lista completa tiene 12.033 recargas clasificadas como Indebido o Revisar, ordenadas por conclusión, riesgo y valor, y se puede descargar al inicio de la página. Abajo, primero las 5 personas con mayor valor indebido (solo la parte indebida de cada recarga) y después las 5 con mayor valor a revisar.

Conclusión Matrícula Base Período Recargas Valor Motivo
Indebido F6561 Base 3 06/01/2025 a 17/12/2025 40 R$ 1.692 Cena sin pernocte
Indebido F5109 Base 3 24/02/2025 a 11/12/2025 40 R$ 1.684 Cena sin pernocte
Indebido F5730 Base 6 27/03/2025 a 31/12/2025 37 R$ 1.616 Cena sin pernocte
Indebido F4119 Base 6 22/04/2025 a 26/12/2025 37 R$ 1.580 Cena sin pernocte
Indebido F5573 Base 3 23/01/2025 a 29/12/2025 37 R$ 1.568 Cena sin pernocte
Revisar F3012 Base 2 13/01/2025 a 29/12/2025 18 R$ 936 Sin respaldo de campo
Revisar F8211 Base 6 23/01/2025 a 31/12/2025 18 R$ 936 Sin respaldo de campo
Revisar F1355 Base 6 08/01/2025 a 23/12/2025 18 R$ 872 Sin respaldo de campo
Revisar F6862 Base 6 15/01/2025 a 16/12/2025 17 R$ 852 Sin respaldo de campo
Revisar F1035 Base 2 27/01/2025 a 29/12/2025 16 R$ 832 Sin respaldo de campo

Indebido

Matrícula: F6561

Base: Base 3

Período: 06/01/2025 a 17/12/2025

Recargas: 40

Valor: R$ 1.692

Motivo: Cena sin pernocte

Indebido

Matrícula: F5109

Base: Base 3

Período: 24/02/2025 a 11/12/2025

Recargas: 40

Valor: R$ 1.684

Motivo: Cena sin pernocte

Indebido

Matrícula: F5730

Base: Base 6

Período: 27/03/2025 a 31/12/2025

Recargas: 37

Valor: R$ 1.616

Motivo: Cena sin pernocte

Indebido

Matrícula: F4119

Base: Base 6

Período: 22/04/2025 a 26/12/2025

Recargas: 37

Valor: R$ 1.580

Motivo: Cena sin pernocte

Indebido

Matrícula: F5573

Base: Base 3

Período: 23/01/2025 a 29/12/2025

Recargas: 37

Valor: R$ 1.568

Motivo: Cena sin pernocte

Revisar

Matrícula: F3012

Base: Base 2

Período: 13/01/2025 a 29/12/2025

Recargas: 18

Valor: R$ 936

Motivo: Sin respaldo de campo

Revisar

Matrícula: F8211

Base: Base 6

Período: 23/01/2025 a 31/12/2025

Recargas: 18

Valor: R$ 936

Motivo: Sin respaldo de campo

Revisar

Matrícula: F1355

Base: Base 6

Período: 08/01/2025 a 23/12/2025

Recargas: 18

Valor: R$ 872

Motivo: Sin respaldo de campo

Revisar

Matrícula: F6862

Base: Base 6

Período: 15/01/2025 a 16/12/2025

Recargas: 17

Valor: R$ 852

Motivo: Sin respaldo de campo

Revisar

Matrícula: F1035

Base: Base 2

Período: 27/01/2025 a 29/12/2025

Recargas: 16

Valor: R$ 832

Motivo: Sin respaldo de campo

Cómo saber que la auditoría acertó

Como los datos de este caso se generaron con un script, fue posible comparar la auditoría con lo que el generador plantó: encontró los 12.905 defectos plantados, sin excepción, y ninguno de los 19.885 registros que solo parecían error terminó como Indebido o Revisar. La auditoría no lee la clave de respuestas; un script aparte compara las dos cosas al final. Con datos reales no existe una clave de respuestas, y esa verificación se hace con la base: una muestra de casos de cada conclusión se revisa con quienes conocen el proceso antes de cerrar el informe.

Recomendaciones

Cada hallazgo se convierte en una corrección del proceso, para que el problema no vuelva al año siguiente.

Hallazgo Corrección recomendada Responsable
Duplicidad después del cambio de sistema Bloqueo en el sistema de una recarga por tipo, persona y día TI y proveedor de la tarjeta
Registro de personal con atraso Lista diaria de vacaciones, ausencias y desvinculaciones enviada al sistema de recargas RR. HH.
Cena sin pernocte Cena habilitada solo cuando el diario registra pernocte Operaciones y supervisores de las bases
Por encima del tope Tope diario aplicado por el propio sistema TI
Justificación vaga Justificación elegida de una lista cerrada, no escrita a mano Contraloría
Valores ya pagados como indebidos Reversión o recuperación según la política de la empresa RR. HH., con apoyo del área legal

Duplicidad después del cambio de sistema

Corrección recomendada: Bloqueo en el sistema de una recarga por tipo, persona y día

Responsable: TI y proveedor de la tarjeta

Registro de personal con atraso

Corrección recomendada: Lista diaria de vacaciones, ausencias y desvinculaciones enviada al sistema de recargas

Responsable: RR. HH.

Cena sin pernocte

Corrección recomendada: Cena habilitada solo cuando el diario registra pernocte

Responsable: Operaciones y supervisores de las bases

Por encima del tope

Corrección recomendada: Tope diario aplicado por el propio sistema

Responsable: TI

Justificación vaga

Corrección recomendada: Justificación elegida de una lista cerrada, no escrita a mano

Responsable: Contraloría

Valores ya pagados como indebidos

Corrección recomendada: Reversión o recuperación según la política de la empresa

Responsable: RR. HH., con apoyo del área legal

La auditoría también deja tres indicadores para seguir todos los meses:

  • Tasa de recargas indebidas: valor indebido ÷ valor pagado, con meta por debajo del 0,5%.
  • Cobertura de respaldo: recargas con cuadrilla registrada en campo ÷ total de recargas, con meta por encima del 99%.
  • Valor por día en campo: por base, frente al rango esperado.

Lo que demuestra el caso

  • Cruzar bases que nadie cruzaba. El error no estaba en ninguna base por sí sola, sino en la falta de verificación entre la tarjeta, el diario de campo y RR. HH.
  • Separar el error objetivo de la sospecha. Solo lo que viola una regla va a recuperación; el resto va a la base para que lo confirme, sin acusar a nadie.
  • Un número que explica el problema. El salto del segundo semestre se dividió entre lo indebido y lo legítimo, en lugar de convertirse en una orden genérica de recorte de gastos.
  • Un informe que se vuelve a ejecutar. El código queda en la empresa, y el mismo informe se ejecuta el año siguiente con los datos nuevos.

¿Tu empresa paga algún beneficio, reembolso o adicional sin cruzarlo con otra base?

Cuéntame cómo funciona hoy y te digo qué se puede verificar.

Escríbeme