Implementação da API de micro hábitos

TLDR: Passo-a-passo de implementação do módulo de micro hábitos em 8 fases, uma por endpoint, começando pela infraestrutura base (models + migrations + admin).

Estado: as fases 4 e 7 (endpoints 3 e 6) ficaram pendentes neste plano; o contrato final da API está em reference/habits/habits_api.md.

Visão geral

Implementar o módulo completo de micro hábitos seguindo os padrões do projeto Django/DRF existente. O sistema permite criar hábitos com diferentes frequências (diária, semanal, mensal) e gerenciar suas execuções.

Endpoints alvo:

  1. GET /api/v1/habits/executions/{date} — listar execuções do dia
  2. GET /api/v1/habits — listagem de hábitos cadastrados
  3. PUT /api/v1/habits/executions/{execution_id} — atualizar execução de um hábito
  4. POST /api/v1/habits — cadastrar hábito
  5. PUT /api/v1/habits/{habit_id} — atualizar hábito
  6. GET /api/v1/habits/{habit_id}/executions — histórico de execuções de um hábito

```mermaid graph TB User[User] –> Habit[Habit Model] Habit –> Execution[HabitExecution Model]

HabitViewSet --> HabitSerializer
ExecutionViewSet --> ExecutionSerializer

HabitViewSet --> HabitService
ExecutionViewSet --> ExecutionService

HabitService --> GenerateExecutions[Geração de Execuções]
GenerateExecutions --> Execution ```

Estrutura do app:

apps/habits/ ├── models/ # habit.py, execution.py ├── serializers/ # habit.py, execution.py ├── views.py # HabitViewSet, ExecutionViewSet ├── urls.py # rotas da API ├── services.py # lógica de negócio ├── tasks.py # tasks Celery (geração de execuções) └── migrations/

Fases

Fase 1 — Infraestrutura base

Todos os endpoints dependem disto.

  1. Criar o app habits e a estrutura de diretórios
  2. Adicionar o app em INSTALLED_APPS
  3. Implementar os models Habit e HabitExecution
  4. Criar e executar as migrations
  5. Registrar os models no admin

apps/habits/models/habit.py — herda de BaseModel (já tem created_at, updated_at, deleted_at): - Campos: user (FK), name, category (choices), frequency (daily/weekly/monthly), status (active/finished), start_date, end_date, finished_at, hours (JSONField — array de HH:MM), weekly_days (JSONField — mon/tue/…), monthly_day (1-31) - Métodos: frequency_label (property, label PT-BR) e save() sobrescrito para setar finished_at quando status='finished'

apps/habits/models/execution.py — herda de BaseModel: - Campos: habit (FK), scheduled_date, scheduled_time, status (pending/completed/skipped/not-completed), executed_at - Meta: unique_together ['habit', 'scheduled_date', 'scheduled_time']; índices em scheduled_date e status

Fase 2 — Endpoint 1: listar execuções do dia

GET /api/v1/habits/executions/{date}

  1. ExecutionSerializer para listagem (com habit_id, habit_name, habit_category)
  2. ExecutionService.get_executions_by_date(user, date)
  3. ExecutionViewSet.list_by_date()

Fase 3 — Endpoint 2: listagem de hábitos cadastrados

GET /api/v1/habits

  1. HabitSerializer para listagem (com frequency_label e todos os campos)
  2. HabitViewSet.list()

Fase 4 — Endpoint 3: atualizar execução de um hábito

PUT /api/v1/habits/executions/{execution_id} — pendente

  1. ExecutionUpdateSerializer em apps/habits/serializers/execution.py — apenas o campo status, validando completed ou skipped
  2. ExecutionService.update_execution_status(execution_id, status, user) — validar que a execução pertence ao usuário, atualizar o status e setar executed_at
  3. ExecutionViewSet.update_status() em apps/habits/views.py — PUT que recebe execution_id na URL, valida autenticação, chama o service e retorna o ExecutionSerializer atualizado
  4. Adicionar a rota em apps/habits/urls.py

Fase 5 — Endpoint 4: cadastrar hábito

POST /api/v1/habits

  1. HabitSerializer para criação com validações: weekly_days obrigatório se frequency='weekly', monthly_day obrigatório se frequency='monthly', hours não pode ser vazio, end_date >= start_date
  2. HabitService.generate_executions(habit, start_date=None, end_date=None) — gera execuções conforme a frequência (diário: todos os dias entre start_date e end_date ou hoje + 30 dias; semanal: só nos dias da semana especificados; mensal: só no dia do mês). Usa bulk_create
  3. HabitViewSet.create() e perform_create()

Fase 6 — Endpoint 5: atualizar hábito

PUT /api/v1/habits/{habit_id}

  1. HabitSerializer para atualização (todos os campos opcionais, validações condicionais)
  2. Lógica para regerar execuções futuras quando frequency/hours/weekly_days/monthly_day/end_date mudarem
  3. HabitViewSet.update() e perform_update()

Fase 7 — Endpoint 6: histórico de execuções de um hábito

GET /api/v1/habits/{habit_id}/executions — pendente

  1. ExecutionListSerializer — campos id, scheduled_date, scheduled_time, status, executed_at, day_of_week (nome do dia em PT-BR)
  2. ExecutionService.get_executions_by_habit(habit_id, user, filters, pagination) — validar que o hábito pertence ao usuário, filtrar por status quando fornecido, ordenar por scheduled_date desc, scheduled_time desc
  3. ExecutionViewSet.list_by_habit() — query params page, per_page, status; paginação LimitOffsetPagination; resposta {habit_id, habit_name, total, page, per_page, executions: [...]}
  4. Adicionar a rota em apps/habits/urls.py

Fase 8 — Configuração final

  1. Criar urls.py com os 6 endpoints e registrar as rotas em routes/api.py
  2. Testes básicos
  3. Documentação

Regras de negócio embutidas

Criação de hábito - Se start_date não informada, usa a data atual - Se end_date não informada, o hábito é indefinido (null) - Gera execuções automaticamente ao criar (próximos 30 dias ou até end_date)

Atualização de hábito - Se mudar frequency, hours, weekly_days, monthly_day ou end_date, regera as execuções futuras - Se status mudar para finished, seta finished_at e cancela as execuções futuras

Execuções - Status inicial: pending - Ao atualizar para completed ou skipped, seta executed_at - Execuções passadas não podem ser alteradas

Filtros - O endpoint de histórico suporta filtro por status via query param - Paginação padrão: LimitOffsetPagination (20 itens)

Verificação

  • Criação de hábito
  • Geração de execuções por frequência (diária, semanal, mensal)
  • Atualização de status de execução
  • Filtros e paginação no histórico

Observações

  • Usar select_related para evitar N+1 queries
  • Execuções são geradas de forma eager (antecipada) por padrão
  • Se houver muitos hábitos, considerar task assíncrona para a geração de execuções