Link de checkout no Trial

TLDR: adiciona o campo checkout_url ao Trial, obrigatório no cadastro do admin e exposto no objeto trial devolvido pelo sign-in e pelo perfil, para o app abrir o checkout do usuário em trial.

Status: proposed Created: 2026-08-19 Owner: @matheusscfr


Context

Hoje o Trial guarda duração, período, funcionalidades liberadas e limites de áudio, mas não guarda para onde mandar o usuário quando ele decide assinar. O link do checkout varia por trial (campanha, oferta, preço), então precisa ser configurável por registro e não fixo no app.

O objeto trial já é devolvido em POST /accounts/sign-in e GET /accounts/profile (R-015), e é o lugar natural para o app ler esse link e montar o botão de assinatura / paywall quando o trial acaba.

Objectives

  • Adicionar checkout_url ao modelo Trial, obrigatório no cadastro, preenchendo os trials já existentes na própria migração para não quebrar staging e produção.
  • Disponibilizar o campo no formulário do admin de Trial.
  • Expor checkout_url no objeto trial do sign-in e do perfil.
  • Preencher o campo no seed.
  • Atualizar a regra R-015 com o novo campo do contrato.

Non-goals

  • Não cria nem integra nenhum provedor de checkout — o campo é só um link cadastrado manualmente.
  • Não altera UserTrial, nem o fluxo de conversão (converted_at), nem o webhook de checkout aprovado.
  • Não adiciona o link em GET /accounts/ (AccountSerializer), que segue inalterado.
  • Não expõe o campo no endpoint público de registro de trial por campanha.

Changes

apps/trials/models/trial.py

  • Novo campo checkout_url = models.URLField(max_length=500, verbose_name="Link do checkout", help_text="..."), obrigatório (blank=False, sem null).

apps/trials/migrations/0007_trial_checkout_url.py

  • AddField com default="https://checkouts.ibft.app/2404/onion_externo/aff/370e61ef0113" (checkout externo padrão do produto) e preserve_default=False: os trials já existentes são preenchidos com esse link na migração e o campo segue obrigatório no formulário, sem default no modelo.

apps/trials/admin.py

  • Incluir checkout_url no fieldset “Informações” do TrialAdmin, logo após name.
  • TrialAdminForm usa fields = "__all__", então nada muda em apps/trials/forms.py.

apps/trials/serializers/user_trial_state.py

  • Novo checkout_url = serializers.SerializerMethodField() lendo obj.trial.checkout_url, seguindo o padrão dos demais campos derivados do trial.

apps/common/management/commands/seed.py

  • Preencher checkout_url nos trials criados em _seed_trials, com links distintos por trial (ex.: https://checkout.onion.local/trial-padrao-7-dias).

tests/trials/conftest.py

  • Fixture trial passa a criar o registro com checkout_url.

tests/trials/test_user_trial_state_serializer.py

  • Teste garantindo que o payload traz checkout_url com o valor do trial vinculado.

.project/docs/rules/trials/trial_state_in_auth_endpoints.md

  • Acrescentar checkout_url à lista de campos do objeto trial e uma constraint explicando que o link é por trial e é o destino de assinatura mostrado pelo app.

How to verify

  1. make migrate aplica a migração sem erro em base com trials já cadastrados.
  2. No admin (dash.* → Trials), o campo “Link do checkout” aparece no bloco Informações e o formulário rejeita o salvamento quando ele fica em branco.
  3. make test — suíte de trials e de contas verde, incluindo o novo teste do serializer.
  4. POST /accounts/sign-in com um usuário trial devolve trial.checkout_url igual ao link cadastrado no Trial vinculado.
  5. python manage.py seed cria os trials com o link preenchido.

Documentation

  • Atualizar .project/docs/rules/trials/trial_state_in_auth_endpoints.md (R-015) com o campo checkout_url.