Skip to content

Módulo de Timesheet & Time Tracking ​

O módulo de Timesheet é um sistema de controle de horas e ponto headless completo. Ele permite que um workspace opere registro de ponto (com geolocalização), jornadas de trabalho, ausências, fluxo de aprovação de dias e períodos, apontamento por projeto com valor-hora e um kanban integrado — tudo isolado por instância.

Cada workspace pode ter várias instâncias do Timesheet (uma por empresa ou unidade), com configurações, profissionais, clientes, projetos e apontamentos totalmente independentes.

Por que utilizar este módulo? ​

  • Isolamento Total: Os dados são isolados por instância do Timesheet (timesheet_id é o eixo de isolamento) — um profissional de uma instância não enxerga dados de outra.
  • Dois Públicos, Duas APIs: O dono da conta provisiona e configura a instância; gestores e profissionais operam o ponto e os apontamentos com autenticação própria do módulo.
  • Regras na Aplicação: Toda a inteligência (consolidação de dias, cálculo de valor-hora, trava de períodos fechados, máquinas de estado) vive na aplicação — o banco guarda apenas os dados, sem functions, triggers ou views.
  • Auditoria Nativa: Batidas de ponto nunca sofrem UPDATE; correções de apontamento geram revisões com antes/depois, autor e motivo.

As Duas Áreas do Módulo ​

ÁreaPrefixo das rotasPúblicoGuard
Gestão da instância/user/timesheetsDono da conta (módulo user)user
Operação/v1/timesheetGestores e profissionaistimesheetUser
  • A gestão da instância cria e configura as instâncias (fuso, moeda, geolocalização obrigatória, dia de virada do período) e segue a autenticação da plataforma.
  • A área de operação concentra todo o restante: equipe, estrutura organizacional, jornadas, ponto, apontamentos, períodos, métricas, chamados internos, kanban e exportações.

Autenticação e Contexto ​

Identificação da Instância ​

Todas as requisições para os endpoints /v1/timesheet/** devem incluir o identificador da instância:

HeaderTipoObrigatórioDescrição
X-Timesheet-IdUUIDSimO tokenHeader da instância, obtido no painel administrativo do workspace.

Como funciona o X-Timesheet-Id

O middleware resolve a instância pelo tokenHeader e valida se o domínio (ou IP) de origem está na lista de domínios autorizados do workspace, conforme a configuração allowBy (domain ou ip) de cada domínio vinculado. Requisições sem o header, com instância inexistente ou com origem não autorizada recebem 401 Unauthorized. Instâncias inativas (ou cujo workspace está inativo) recebem 503 Service Unavailable.

bash
curl -X GET "https://api.us.basis.tavares.in/v1/timesheet/me/days" \
  -H "X-Timesheet-Id: 123e4567-e89b-12d3-a456-426614174000" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"

Tokens de Acesso ​

O login da operação é feito em POST /v1/timesheet/users/login com email + password do profissional e retorna um token Bearer com validade de 30 dias. O logout invalida o token imediatamente.

HeaderValorDescrição
AuthorizationBearer <token>Token obtido no login do profissional (guard timesheetUser).

Profissionais sem senha cadastrada (quem só bate ponto num tablet, por exemplo) não conseguem autenticar — o cadastro de email e password é opcional.


Controle de Acesso (Gestor vs Profissional) ​

O módulo tem um RBAC simples, baseado na flag isManager do profissional:

PapelEscopo
Gestor (isManager: true)Acesso total à instância: gerencia equipe, estrutura, jornadas, tarifas, clientes, projetos, feriados; aprova dias, ausências e períodos; enxerga dados de todos os profissionais.
Profissional (isManager: false)Bate o próprio ponto, cria os próprios apontamentos e ausências, consulta apenas os próprios dias, períodos, chamados e exportações (endpoints /me/** ou escopo automático).

Regras adicionais:

  • Ações restritas a gestor falham com 403 FORBIDDEN para profissionais.
  • Profissionais que tentam acessar recursos de terceiros recebem 404 Not Found (o recurso é filtrado pelo próprio ID).
  • O kanban tem um RBAC próprio por quadro (owner/editor/viewer), detalhado em Kanban.

Billing e Limites de Plano ​

Todas as rotas do módulo passam por limite de plano (usageLimit) e contabilização de uso horário (workspaceHourlyUsage). Quando o plano não permite a operação, a API responde 402 Payment Required com um dos seguintes códigos:

CodeSignificado
PENDING_INVOICESExistem faturas pendentes no workspace.
PLAN_REQUIREDO workspace não possui um plano ativo para o módulo.
USAGE_LIMIT_EXCEEDEDO limite de uso do plano foi atingido.

Convenções da API ​

  • Paginação: parâmetros page/perPage (máx. 100). Os endpoints /v1/timesheet/** respondem no formato { "meta": { "currentPage", "perPage" }, "data": [...] }; a área do dono (/user/timesheets) usa o paginador completo da plataforma, com total, lastPage, firstPage e URLs de navegação no meta.
  • Listas para dropdown: endpoints GET .../list retornam [{ "value", "label" }], com search opcional.
  • Soft delete: registros removidos não aparecem em nenhuma consulta.
  • Erros de validação: 422 Unprocessable Entity com errors: [{ "message", "rule", "field" }] (mensagens em pt/en via i18n).
  • Datas: sempre em ISO 8601; filtros de período e campos de dia usam YYYY-MM-DD; instantes (startedAt, punchedAt) usam ISO 8601 completo. Horários de jornada (startsAt/endsAt) são enviados como HH:mm e retornados como HH:mm:ss.
  • Durações e valores: tempos são sempre em minutos inteiros (expectedMinutes, workedMinutes...). Campos decimais — valores monetários (hourlyCost, billingAmount...), coordenadas e posições do kanban — são serializados como string na resposta (ex.: "billingRate": "160.0000", "position": "1000.0000000000"); métricas calculadas (workedHours, totalBillable...) vêm como número.
  • IDs: retornados como números, sem assumir tamanho (as tabelas usam bigint).
  • Rate limit: 3000 req/min para o módulo (global); as rotas de gestão da instância (/user/timesheets) seguem o throttle do módulo user (100 req/min).

Códigos de Erro de Negócio ​

Erros de regra de negócio retornam status 4xx com um code identificador no corpo da resposta. Os principais:

CodeStatusSignificado
FORBIDDEN403Profissional sem permissão de gestor para a ação.
OPEN_ENTRY_EXISTS422Já existe um apontamento em aberto para o profissional.
NO_OPEN_ENTRY422Tentativa de bater saída sem apontamento aberto.
MAX_INTERVALS_REACHED422Limite diário de intervalos (maxIntervalsPerDay) atingido.
INVALID_PUNCH_INTERVAL422Saída anterior à entrada ou registro com mais de 24h.
GEOLOCATION_REQUIRED422A instância exige geolocalização e a batida veio sem coordenadas.
OUTSIDE_GEOFENCE422Batida fora do raio de qualquer local autorizado.
ENTRY_OVERLAP422O apontamento se sobrepõe a outro existente.
MANUAL_ENTRY_NOT_ALLOWED422A instância não permite apontamentos manuais (isAllowsManualEntry: false).
DAY_LOCKED422O dia não está em um status editável (aprovado/bloqueado; para profissional, qualquer status diferente de open).
PERIOD_CLOSED422A data pertence a um período já fechado.
PERIOD_OVERLAP422Já existe um período sobreposto para o profissional.
RATE_OVERLAP422Vigência de tarifa sobreposta para o mesmo profissional.
SCHEDULE_OVERLAP422Vigência de jornada sobreposta para o mesmo profissional.
INVALID_STAGE_MOVE422Transição de status inválida (dia, período, ausência ou chamado).
WIP_LIMIT_REACHED422Limite de WIP da coluna do kanban atingido.
COLUMN_HAS_CARDS422A coluna possui cards e não pode ser removida.
LAST_OWNER422O quadro precisa ter ao menos um proprietário.
NOT_BOARD_MEMBER403Profissional não é membro do quadro privado.
EXPORT_EXPIRED422O arquivo da exportação expirou (24h após a geração).

Próximos Passos ​