Custeio de Mão de Obra na OS
:::info Decisão tomada (04/08/2026) — ver ADR-009
Valor/hora default no cargo + override opcional por colaborador; rate carregado;
cadastro gateado por CostCenter (endpoint dedicado). Fase 1 = cadastro (em
implementação); Fase 2 = materialização (horas líquidas × rate); terceirizada fica no
backlog.
:::
Pra quê essa proposta existe
Queremos saber quanto custa de verdade cada manutenção — pra medir custo por veículo, decidir troca de frota, etc. O custo de uma ordem de serviço tem duas partes:
Custo da OS = Peças + Mão de obra
As peças já são reais (o custo é materializado da solicitação de peça). Mas a mão de obra hoje é um número chutado — um valor fixo de seed gravado no banco, que não veio de lugar nenhum. Resultado: todo custo e relatório que envolve mão de obra está errado.
Esta proposta é sobre tornar o custo de mão de obra real.
O problema, num exemplo
A OS #1234 trocou a embreagem de um caminhão. O João trabalhou 3 horas nisso. Hoje a tela mostra "Mão de obra: R$ 200" — mas esse R$ 200 é fixo, não veio de nada. O certo seria: 3 horas × o quanto custa a hora do João.
A conta é simples — e falta só UM número
Custo de MO = horas trabalhadas × valor da hora
- ✅ As horas a gente já tem. O sistema registra a duração real de cada serviço, por
colaborador (
ServiceExecutionLog.actualDurationHours) — são as horas-homem, a mesma base que a análise de produtividade já consome. Não precisa criar apontamento novo. - ❓ O valor da hora é o que falta. É a única coisa que precisamos definir.
Ou seja: a proposta inteira se resume a uma pergunta — de onde vem o valor da hora?
De onde vem o valor da hora?
Só há duas opções que fazem sentido pra nós:
| Opção | O que é | A favor | Contra |
|---|---|---|---|
| Por colaborador | Cada pessoa tem o seu R$/hora | Mais exato | Trabalhoso (um por pessoa); o custo por OS quase revela o salário de cada um |
| Por cargo | Um R$/hora por função (mecânico, mecânico sênior, ajudante…) | Pouco cadastro; não expõe salário individual | Menos exato (todos do mesmo cargo custam igual) |
:::note Por que só essas duas Existem outros modelos no mercado (taxa única da oficina; valor por tipo de serviço), mas eles servem pra cobrar cliente, não pra medir custo de frota própria. Ficam de fora. Detalhe nas referências. :::
Como o mercado faz (o resumo que importa)
Olhei UpKeep, Fiix, Fleetio, Samsara e Limble. Tirando o jargão, o padrão é o mesmo:
- Põem o R$/hora no cadastro (na pessoa ou na função) e multiplicam pelas horas — é exatamente a nossa conta.
- Só o admin vê o R$/hora e o custo — porque esse número quase revela salário.
- Ferramentas que faturam cliente separam "custo" de "preço de venda". Não é o nosso caso — frota própria só quer saber o custo, não cobrar de ninguém. Isso simplifica tudo.
Recomendação
Valor da hora por cargo, com exceção opcional por colaborador.
- Base no cargo: poucos valores pra manter e não expõe o salário de ninguém.
- Exceção por pessoa: se um mecânico foge da curva, dá pra cadastrar um valor só dele, que tem prioridade sobre o do cargo.
- Valor "cheio": o número cadastrado já deve incluir encargos (salário + FGTS, INSS, etc.). Só o salário bruto subestima o custo real em ~20–40%.
- Privacidade: mostrar R$/hora e custo de MO só pra quem tem permissão de custo.
- Congelar na OS: ao lançar, gravar o valor usado naquela OS — um reajuste futuro não deve reescrever o custo de uma OS antiga.
Escopo: própria agora, terceirizada depois
Esta proposta cobre oficina própria. Mas o app pode gerenciar também oficinas terceirizadas (a contratante usa oficinas de fora). A peça é igual (é da contratante); a mão de obra muda:
| Própria | Terceirizada | |
|---|---|---|
| Quem faz | Seu colaborador | Mecânico de fora (não é seu funcionário) |
| Como custa | horas-homem líquidas × R$/hora interno | O que a terceirizada cobra de você |
| Regra do valor | Seu custo/cargo | Tabela/orçamento deles — não a sua hora |
| Campo | labourCost | externalCost |
Decisão: fazer só a própria agora; terceirizada é Fase 2. Por quê:
- Cada empresa cobra terceirizada de um jeito (preço fechado, tabela por serviço, nota fiscal, orçamento aprovado). Construir agora é chutar a abstração — boa abstração vem de 2–3 casos reais. O argumento "várias empresas do ramo" reforça esperar, não antecipar.
- MO própria é o 80% que todo cliente precisa. A estrutura de terceirizada (cadastro de oficina + tabela de preço + aprovação de orçamento) é grande e atrasaria o valor imediato.
Costura barata (não fecha porta): o campo externalCost já existe na OS — serve pra
lançar a fatura da terceirizada como número manual, sem estrutura nova. Quando um cliente
real pedir, a Fase 2 acrescenta o ramo externo sem reescrever o custo próprio.
:::tip O "valor por serviço" tem lugar aqui A ideia de uma tabela de preço por serviço (tempário) faz sentido pra terceirizada — é como se orça e se confere a fatura dela. Fica registrada pra Fase 2 (ver Backlog & Ideias). :::
Nota técnica (pro backend)
:::warning As horas de hoje são BRUTAS (incluem pausas)
actualDurationHours é calculado como fim − início (em change-assigments-status.ts e
service-execution-logger.listener.ts). Isso inclui almoço, espera de peça e fim de turno.
Usar esse número no custo superfatura (ex.: 9h de relógio pra 7h trabalhadas → +28%).
:::
- O tempo líquido (só o trabalhado) é calculável das transições de estado
(
ServiceExecutionEmployeeTransitionmarca as pausas compauseReasone duração). O custo deve usar o líquido. - Já existe o campo
ServiceExecutionLog.costreservado — é onde o custo (horas líquidas × R$/hora) deve ser gravado. Não precisa criar estrutura nova. - Dívida técnica adjacente (registrar; não bloqueia): duas tabelas de transição quase iguais
(execução vs colaborador);
statusduplicado; cálculo de duração repetido em 2 lugares; colunas legadasservice_assignment_id.
Decisão tomada (produto)
- Valor da hora por cargo (default) + override por colaborador quando fugir da curva. ✅
- O valor cadastrado já é o custo cheio (salário + encargos). ✅
- Cadastro gateado por
CostCenter(endpoint dedicado). ✅
Registrado no ADR-009. Fase 1 (cadastro) em implementação; a Fase 2 materializa o custo na OS a partir de horas líquidas × valor da hora, com o valor congelado na linha.
Referências
- Fleetio — Work Order Line Items · Markup
- Samsara — Work Orders for Maintenance
- UpKeep — Technician Hourly Rates · Calculate Time & Cost
- Fiix — Track labor and parts costs
- Limble — Labor Categories
- Custo "cheio" (loaded rate) — SmartBarrel · QuickBooks