Campos personalizados no checkout

TLDR: permitir que o admin defina campos extras por checkout — tamanho de camisa, cor, número do sapato — em texto livre ou opções pré-definidas, e guardar a resposta do comprador junto do pagamento.

Contexto

Alguns produtos precisam coletar informação que não faz parte do cadastro padrão do comprador. Hoje não há onde colocar esse dado no checkout, e o time acaba tratando isso fora do sistema.

Objetivos

  • No admin de um checkout, o administrador pode criar campos customizados.
  • O administrador escolhe entre campo aberto e opções pré-definidas.
  • O administrador marca o campo como múltipla escolha ou escolha única (padrão).
  • O administrador agrupa campos por nome — ex.: “Tamanhos de Camisa” — para facilitar a seleção.

Fora de escopo

— (não registrado na spec original)

Mudanças

Modelos

Checkout ganha has_many :custom_fields.

CustomField

Campo Nome Descrição
checkout_id ID do checkout Referência para o Checkout
title Nome exibido ao cliente O texto que aparece no label
value Valor agregado Ex.: 50, casa, short
options_group_title (Opcional) Grupo de opções Nome do grupo de opções usado. Ex.: Tamanho de Camisa, Número de sapato

CustomFieldOption

Campo Nome Descrição
group_title (Opcional) Nome do grupo Agrupador de opções, ex.: Tamanho de Camisa
slug (Opcional) Nome do grupo parametrizado Gerado automaticamente no create, para agrupar facilmente e ser usado na API
title Nome exibido ao cliente Ex.: P, M ou G
value Valor agregado Ex.: P, M ou G

PaymentCustomFieldAnswer

Campo Nome Descrição
custom_field Referência para o Custom Field Referência para o Custom Field
payment Referência para o Pagamento Referência para o Pagamento
answer Resposta A resposta do comprador

Nota da spec original: poderia existir uma tabela polimórfica aqui, sem prefixar por pagamento, mas não há utilidade para isso no momento.

Controller e API

  • O endpoint /checkout/:id retorna o campo custom_fields, para a UI montar o formulário.
  • Ao montar o serializer do checkout, é preciso trazer as options do checkout com base no group_title escolhido — isso não é trivial (a intenção é evitar mais uma tabela).
  • O POST da UI deve respeitar os strong params. Os campos são enviados no array custom_fields.
  • Para campos de resposta fixa (não aberta) com group_title envolvido, validar se o valor enviado bate com o value das options. Possivelmente um model customizado para isso, como já é feito em PaymentDetails.

json { "custom_field_answers": [ { "custom_field_id": 56, "answer": "Resposta de campo aberto" }, { "custom_field_id": 56, "answer": "M" } ] }

ActiveAdmin

Para não criar uma tabela só para o grupo de opções, a exibição dos grupos no admin pode ser uma consulta GROUP BY sobre o group_title das options.

Roadmap

  • [x] Modelo CustomField
  • [x] Modelo PaymentCustomFieldAnswer
  • [x] Modelo CustomFieldOption
  • [x] Mudanças de checkout no ActiveAdmin
  • [x] API/controller — retorno das options no checkout
  • [x] API/controller — POST das respostas
  • [x] API/controller — validação (única, múltipla, etc.)
  • [x] Exibir os campos personalizados nos detalhes do pagamento
  • [x] Permitir alterações nos detalhes do pagamento
  • [ ] IBFT Web — mudanças de UI

Como verificar

— (não registrado na spec original)

Sugestão a partir do estado atual do código: criar um checkout com campos abertos e com grupo de opções, submeter uma compra pela API e conferir os PaymentCustomFieldAnswer gravados e exibidos nos detalhes do pagamento.

Documentação

Implementação: app/models/custom_field.rb, app/models/custom_field_option.rb, app/models/payment_custom_field_answer.rb.