R-012 — Campanha inválida ou expirada bloqueia cadastro de trial
TLDR:
POST /v1/trials/registerrejeita com 400 se o slug não corresponder a uma campanha comend_date >= hoje.
Given / When / Then
Dado que POST /v1/trials/register recebe um slug
Quando não existe nenhuma Campaign com esse slug e end_date >= hoje
Então a requisição falha com ValidationError {"slug": "Campanha não encontrada ou expirada."} e nenhum recurso é criado
Restrições
- A busca usa
end_date__gte=timezone.localdate()— campanhas comend_dateigual a hoje ainda são válidas - O campo
statusda Campaign não é verificado nesta regra; apenasend_datee a existência do registro
Teste vinculado
tests/trials/test_service.py — test_register_rejects_unknown_slug, test_register_rejects_expired_campaign
R-013 — Campanha sem trial vinculado bloqueia cadastro
TLDR: Se a campanha existe mas não tem
trial_id, o endpoint rejeita com 400.
Given / When / Then
Dado que a campanha identificada pelo slug existe e não está expirada
Quando campaign.trial_id é nulo
Então a requisição falha com ValidationError {"slug": "A campanha não possui um trial vinculado."} e nenhum recurso é criado
Restrições
- Campanhas sem trial vinculado são uma má configuração administrativa; o endpoint não cria trial em branco
- A validade do
Trialem si (datas, status) não é verificada — é responsabilidade do administrador manter a consistência
Teste vinculado
tests/trials/test_service.py — test_register_rejects_campaign_without_trial
R-014 — Conta existente ou trial anterior bloqueia sem revelar o motivo
TLDR: Se o email ou phone já existem como
Userou já foram usados em algumUserTrial, o endpoint retorna 201 e envia e-mail de rejeição — sem expor que o cadastro foi bloqueado.
Given / When / Then
Dado que os dados enviados passam pelas validações de campanha (R-012, R-013)
Quando existe um User com o mesmo email ou phone ou existe um UserTrial (incluindo soft-deleted via all_objects) com esse email ou phone
Então:
- Um e-mail de rejeição é enviado via task Celery send_trial_negative_response
- O endpoint retorna 201 sem criar nenhum recurso
- O corpo da resposta não distingue a causa do bloqueio (prevenção de enumeração de contas)
Restrições
UserTrial.all_objectsé usado para incluir registros com soft delete — um usuário que teve trial e depois foi deletado logicamente ainda é bloqueado- O retorno 201 é intencional: não deve ser alterado para 400, pois isso revelaria a existência da conta
Teste vinculado
tests/trials/test_service.py — test_register_sends_negative_response_when_user_exists, test_register_sends_negative_response_when_trial_already_used