Hábitos default no onboarding
TLDR: Permitir que admins cadastrem hábitos pré-configurados por período do dia, exibidos no onboarding para usuários sem hábitos.
Contexto
Usuários novos chegam numa tela vazia, sem hábitos. Para reduzir a fricção no onboarding, o app exibirá sugestões de hábitos pré-configurados. O admin cadastra os templates no Django Admin e o app os consome para criar os hábitos do usuário em uma única chamada.
Objetivos
- Admins podem criar, editar e ativar/desativar
DefaultHabitpelo Django Admin - Cada
DefaultHabittem três conjuntos independentes de horários: manhã, tarde e noite - O app lista os defaults disponíveis via API
- O app cria os hábitos selecionados em uma única chamada, passando o período escolhido pelo usuário
Fora de escopo
— (não registrado na spec original)
Mudanças
Novo model: apps/habits/models/default_habit.py
DefaultHabit
├── name CharField(255)
├── category CharField — mesmos choices de Habit
├── frequency CharField — daily | weekly | monthly
├── hours_morning JSONField — ex: ['07:00', '10:00']
├── hours_afternoon JSONField — ex: ['14:00', '17:00']
├── hours_night JSONField — ex: ['20:00', '22:00']
├── weekly_days JSONField(null) — para frequency=weekly
├── monthly_day IntegerField(null) — para frequency=monthly
├── is_active BooleanField(default=True)
├── order IntegerField(default=0)
└── timestamps (created_at, updated_at)
Arquivos a criar/modificar
| Arquivo | Ação |
|---|---|
apps/habits/models/default_habit.py |
criar model |
apps/habits/models/__init__.py |
exportar DefaultHabit |
apps/habits/admin.py |
registrar DefaultHabitAdmin |
apps/habits/serializers/default_habit.py |
criar serializers |
apps/habits/serializers/__init__.py |
exportar novos serializers |
apps/habits/views.py |
adicionar DefaultHabitViewSet e CreateHabitsFromDefaultView |
apps/habits/urls.py |
registrar rotas |
apps/habits/services.py |
adicionar DefaultHabitService.create_from_defaults() |
apps/habits/tests/unit/test_default_habit_service.py |
testes do service |
apps/habits/tests/integration/test_default_habit_api.py |
testes da API |
apps/habits/migrations/ |
migration gerada |
Endpoints
GET /habits/defaults/ — lista DefaultHabits ativos
POST /habits/default/ — cria hábitos do usuário a partir dos defaults selecionados
GET /habits/defaults/ — resposta:
json
[
{
"id": 1,
"name": "Beber água",
"category": "health",
"frequency": "daily",
"hours_morning": ["07:00", "10:00", "14:00", "19:00"],
"hours_afternoon": ["10:00", "14:00", "17:00", "19:00"],
"hours_night": ["18:00", "20:00", "22:00"],
"order": 1
}
]
POST /habits/default/ — payload:
json
{
"time_of_day": "morning",
"default_habit_ids": [1, 3]
}
O backend busca cada DefaultHabit, usa o array de horários do time_of_day informado e chama o HabitService existente para criar o hábito e gerar as execuções. Retorna os hábitos criados.
Admin: DefaultHabitAdmin
list_display: name, category, frequency, is_active, order- Filtros: category, frequency, is_active
- Fieldsets:
- Info: name, category, frequency, is_active, order
- Horários por período: hours_morning, hours_afternoon, hours_night
- Recorrência: weekly_days, monthly_day
Passos de execução
- Model — criar
apps/habits/models/default_habit.py, exportar em__init__.py, gerar e aplicar a migration - Admin — adicionar
DefaultHabitAdmin; validar no Django Admin a criação com os três arrays de horários - Serializers —
DefaultHabitSerializer(GET) eCreateHabitsFromDefaultSerializer(POST, validatime_of_dayedefault_habit_ids) - Service —
DefaultHabitService.create_from_defaults(user, time_of_day, default_habit_ids): busca só osis_active=True, seleciona o array de horários do período, chama oHabitServicee retorna os hábitos criados - Views —
DefaultHabitViewSet(sólist, ordenado pororder) eCreateHabitsFromDefaultView - URLs — registrar as duas rotas
- Testes unitários —
test_default_habit_service.py: manhã/tarde/noite usam o array correto, inativos são ignorados, criação múltipla - Testes de integração —
test_default_habit_api.py: lista só ativos, ordenação pororder, POST cria com horários corretos,time_of_dayinválido retorna 400 - Factory e seed —
DefaultHabitFactory;apps/habits/fixtures/default_habits.jsoncom 4-5 hábitos representativos, idempotente viaget_or_createporname - Documentação — documentar a regra de negócio dos hábitos default e indexá-la
Como verificar
- Admin: criar um
DefaultHabitcom horários distintos por período GET /habits/defaults/→ retorna o default criado com os três arrays de horáriosPOST /habits/default/comtime_of_day=morninge o ID do default → cria o hábito com os horários de manhãPOST /habits/default/comtime_of_day=night→ mesmo default, hábito criado com horários de noite- Checar que as
HabitExecutionforam geradas corretamente para os horários make seedexecuta sem erro
Documentação
- reference/habits/default_habits.md — regra de negócio dos hábitos default