Datas do Trial sem horário no admin
TLDR:
start_dateeend_datedoTrialpassam a ser sempre gravados à meia-noite (horário local) e o admin exibe apenas um campo de data para eles, sem mudar o tipo da coluna (continuaDateTimeField).
Contexto
Trial.start_date e Trial.end_date são DateTimeField. No admin, o widget padrão de DateTimeField (AdminSplitDateTime) mostra um campo de data e um de hora separados, mas o horário nunca teve relevância de negócio para o período do trial — só a data de início e fim importa. Isso permitia cadastrar horários arbitrários (ex.: início às 14h) e exibia um campo de hora sem uso real na tela de edição.
Trocar o tipo da coluna para DateField implicaria migração e poderia afetar comparações existentes com timezone.now() (ex.: apps/trials/services/user_trial.py), então a decisão foi manter DateTimeField e normalizar o valor para sempre ser meia-noite.
Objetivos
- Sempre que um
Trialfor salvo,start_dateeend_datesão normalizados para00:00:00no timezone local (America/Sao_Paulo), independentemente da hora informada. - O formulário do admin (
TrialAdminForm) exibe só um campo de data parastart_date/end_date, sem o campo de hora do widget padrão. - A validação de
end_dateposterior astart_datecontinua funcionando corretamente após a normalização (evitar falso positivo/negativo por causa da hora original).
Fora de escopo
- Não altera o tipo da coluna no banco (continua
DateTimeField, sem migração). - Não altera
UserTrial.started_at/expires_at(já são somente leitura no admin, conforme R-018 emuser_trial_dates_immutable_in_admin.md) nem seu formato de exibição. - Não altera a exibição das colunas
start_date/end_datena listagem (list_display) do admin, nem o dashboard de estatísticas (TrialDashboardMixin). - Não altera nenhum serializer ou endpoint de API.
Mudanças
apps/trials/models/trial.py
- Adiciona
Trial._to_midnight(value): converte um datetime para o horário local (timezone.localtime) e zera hora/minuto/segundo/microssegundo. Trial.clean()normalizastart_date/end_datepara meia-noite antes de validarend_date > start_date.Trial.save()normalizastart_date/end_datepara meia-noite antes de chamarsuper().save(), garantindo o comportamento mesmo fora do fluxo do admin (ex.: shell, script).
apps/trials/forms.py
TrialAdminFormdeclarastart_date/end_datecomoforms.DateField(widget=AdminDateWidget), substituindo o widget padrão de data+hora.- Adiciona
clean_start_date/clean_end_date, convertendo a data escolhida em um datetime timezone-aware à meia-noite local antes de popular a instância do model.
Como verificar
make test(oupytest tests/trials) — suíte de trials passa, incluindo a validação deend_date > start_date.- No admin (
dash.*/admin/trials/trial/), abrir um Trial para edição: os campos “Início” e “Fim” mostram apenas um seletor de data, sem campo de hora. - Criar/editar um Trial informando datas no formulário e confirmar no banco (ou no shell) que
start_date/end_dateficam com hora00:00:00-03:00. - Criar um
Trialdiretamente viaTrial.objects.create(...)com um datetime com hora diferente de meia-noite e confirmar que é normalizado ao salvar.
Documentação
Nenhuma mudança de documentação necessária — não há regra de negócio documentada em .project/docs/rules/trials/ sobre o formato de start_date/end_date do Trial para atualizar.