Isox.Dictionary (Isox v0.2.0)

Copy Markdown View Source

O que cada campo de cada mensagem quer dizer.

Quem integra com o SPI passa boa parte do tempo com a planilha do catálogo aberta do lado do editor, só para descobrir que dbtr_acct_id é a conta do pagador e que purp_cd só aceita cinco valores. Este módulo traz essa informação para dentro do código.

iex> {:ok, entrada} = Isox.Dictionary.field(Isox.Pacs008, :dbtr_acct_id)
iex> entrada.name_br
"contaUsuarioPagador"

A mesma informação aparece de três formas, todas vindas da mesma fonte:

  • como dado, em fields/1 e field/2, para quem quer montar tela, validar ou gerar formulário;
  • como texto para ler no IEx, em explain/2;
  • como tabela na documentação de cada mensagem, montada em tempo de compilação por doc/1. A tabela que você vê em Isox.Pacs008 é esta aqui, renderizada.

Isso é de propósito: descrição que mora em dois lugares diverge, e a que diverge é sempre a que alguém vai ler.

De onde vêm as descrições

Dos documentos que o Banco Central publica para o SPI: o XSD de cada mensagem, a planilha do catálogo (que traz o nome brasileiro, a obrigatoriedade, o tamanho e a tabela de domínios de cada campo) e os manuais do Pix.

O texto das descrições é escrito aqui, não copiado de lá. O catálogo é a fonte normativa e continua sendo: em caso de divergência, quem manda é o documento oficial, e é para lá que name_br serve de chave de busca.

O que não está aqui

Só os campos que as structs do isox expõem. As structs cobrem o caminho comum de cada mensagem, não a árvore inteira do XSD, então ramos raros que a lib não modela também não aparecem no dicionário. Isox.Pacs008, por exemplo, não modela Tax nem RmtInf.Strd.

Summary

Functions

Os valores aceitos por um campo de domínio, com o significado de cada um.

O bloco de documentação de uma mensagem, em Markdown.

O campo explicado em texto corrido, para ler no IEx.

Um campo específico.

Todos os campos de uma mensagem, na ordem em que aparecem no XML.

Mensagens que o dicionário cobre.

Procura um termo em todos os campos de todas as mensagens.

Functions

codes(message, field)

@spec codes(module(), atom()) :: {:ok, %{optional(String.t()) => String.t()}} | :error

Os valores aceitos por um campo de domínio, com o significado de cada um.

iex> {:ok, codigos} = Isox.Dictionary.codes(Isox.Pacs008, :purp_cd)
iex> codigos["GSCB"]
"Pix Troco: compra com saque de dinheiro em espécie no mesmo pagamento."

Devolve :error para campo que não é de domínio (texto livre, valor, data) e para campo que não existe.

As tabelas de rejeição estão aqui, incluindo a do pacs.002, que é a mais consultada de quem integra com o SPI. São também as que mais mudam de uma versão do catálogo para outra: confira contra a versão que você está usando antes de tratar qualquer código como definitivo.

doc(message)

@spec doc(module()) :: String.t()

O bloco de documentação de uma mensagem, em Markdown.

Chamado em tempo de compilação pelo @moduledoc de cada mensagem, para a tabela de campos ser a mesma coisa que a API devolve.

explain(message, field)

@spec explain(module(), atom()) :: String.t()

O campo explicado em texto corrido, para ler no IEx.

Isox.Pacs008 |> Isox.Dictionary.explain(:dbtr_acct_id) |> IO.puts()

field(message, field)

@spec field(module(), atom()) :: {:ok, Isox.Dictionary.Entry.t()} | :error

Um campo específico.

iex> {:ok, entrada} = Isox.Dictionary.field(Isox.Pacs008, :purp_cd)
iex> entrada.name_br
"finalidadeDaTransacao"

iex> Isox.Dictionary.field(Isox.Pacs008, :nao_existe)
:error

fields(message)

@spec fields(module()) :: [Isox.Dictionary.Entry.t()]

Todos os campos de uma mensagem, na ordem em que aparecem no XML.

iex> Isox.Dictionary.fields(Isox.Pibr001) |> Enum.map(& &1.field)
[:msg_id, :created_at, :data]

messages()

@spec messages() :: [module()]

Mensagens que o dicionário cobre.

search(term)

@spec search(String.t()) :: [{module(), Isox.Dictionary.Entry.t()}]

Procura um termo em todos os campos de todas as mensagens.

Busca no nome do campo na struct, no nome brasileiro, no caminho XML e na descrição. Ignora acento e caixa, porque ninguém lembra se o catálogo escreveu "transacao" ou "transação".

iex> Isox.Dictionary.search("idFimAFim") |> Enum.any?(fn {m, e} ->
...>   m == Isox.Pacs008 and e.field == :end_to_end_id
...> end)
true