Endpoint de consistência por intervalo
TLDR: Adicionar
GET /v1/habits/consistencyque retorna dias completos e porcentagem de consistência de um usuário num intervalo de datas.
Contexto
O frontend precisa mostrar, por semana (ou qualquer intervalo), quantos dias o usuário completou todos os hábitos e qual foi sua consistência geral no período. O campo consistency existente no HabitSerializer é por hábito individualmente; este endpoint é por usuário no intervalo.
Caso de uso principal: o frontend pede a semana inteira (01–07) mesmo estando no dia 02. O cálculo considera apenas execuções já decididas (não-pending), então no dia 02 com o dia 01 completo, a consistência é 100%.
Objetivos
- Criar
GET /v1/habits/consistency?start_date=YYYY-MM-DD&end_date=YYYY-MM-DD - Retornar
completed_days,consistency(%),total_days,evaluated_until,expected_executions,completed_executions - Ignorar execuções futuras e
pendingdo dia atual no cálculo de consistência - Validar o intervalo (start <= end, máximo 366 dias)
Fora de escopo
— (não registrado na spec original)
Mudanças
apps/habits/services.py
Adicionar ExecutionService.get_consistency_in_range(user, start_date, end_date):
- evaluated_until = min(end_date, today)
- decided = execuções com scheduled_date <= evaluated_until, excluindo (scheduled_date=today AND status='pending')
- consistency = round(completed / expected * 100, 1) — 0.0 se expected = 0
- completed_days = dias em que total == done AND pending == 0
- total_days = (end_date - start_date).days + 1 (usa o intervalo planejado original)
apps/habits/serializers/consistency.py (novo)
ConsistencyRangeQuerySerializer:
- Campos: start_date, end_date (DateField)
- Validações: start <= end, intervalo <= 366 dias, end_date pode ser futuro
apps/habits/views.py
Adicionar ConsistencyRangeView(APIView):
- Valida os params com ConsistencyRangeQuerySerializer
- Chama ExecutionService.get_consistency_in_range
- Sem cache (o valor muda ao longo do dia conforme as execuções são completadas)
apps/habits/urls.py
python
path("consistency", ConsistencyRangeView.as_view(), name="consistency-range"),
Inserir antes de executions/<str:date> para evitar conflito de matching.
apps/habits/tests/test_consistency_range.py (novo)
Testes Triple-A cobrindo:
- Semana em execução: dia 01 completo, dia 02 todo pending → consistency=100, completed_days=1, total_days=7
- Semana em execução com o dia atual parcial (alguns decididos, 1 pending restante)
- Intervalo totalmente no futuro → consistency=0.0, sem divisão por zero
- Happy path com mix de dias no passado
- Hábito semanal (weekly_days) — só os dias esperados entram
- Intervalo de 1 dia
- Validação: start > end → 400
- Validação: intervalo > 366 dias → 400
- Isolamento por usuário
apps/common/management/commands/seed.py
Atualizar para criar execuções de uma semana com mix de completed/pending/not-completed, permitindo teste manual via make seed.
Como verificar
make seed+GET /v1/habits/consistency?start_date=...&end_date=...retorna resposta válida- Semana em execução (hoje no meio da semana): somente dias passados com tudo completo contribuem para 100%
python manage.py test apps.habits.tests.test_consistency_range— todos passam
Documentação
- reference/habits/habits_api.md — adicionar a nova rota