# `Isox.Camt054`
[🔗](https://github.com/RicardoSantos-99/isox/blob/v0.2.0/lib/isox/camt054.ex#L1)

Detalhe de um lançamento da Conta PI: a contrapartida contábil de cada
pagamento liquidado.

Versões 1.15 e 1.16 coexistindo. É a maior mensagem do catálogo, e
repete os dados de pagador e recebedor da `Isox.Pacs008` com metadados
contábeis por cima. Chega de dois jeitos: como resposta a uma
`Isox.Camt060` que pediu `camt.054`, ou espontaneamente, quando o SPI
avisa um lançamento.

O mesmo pagamento gera dois lançamentos, um em cada Conta PI, com
`cdt_dbt_ind` oposto: o valor sai como `DBIT` do lado do pagador e entra
como `CRDT` do lado do recebedor.

## O que a struct cobre

O caminho comum de um lançamento de liquidação, mais `RtrInf` quando é
devolução. Ficam de fora `Tax` e `RmtInf.Strd`, ramos raros que seguem
acessíveis pelo codec genérico, mesma decisão da `Isox.Pacs008`.

## Dois pontos que o schema real desmente da intuição

`RltdAgts` é obrigatório como contêiner, mas `DbtrAgt` e `CdtrAgt`
dentro dele são opcionais cada um por si. É diferente da pacs.008, onde
os dois agentes são sempre obrigatórios.

`addtl_tx_inf` não é texto livre, apesar de a tag se chamar
`AdditionalTransactionInformation`. O tipo XSD é `Priority2Code` e só
aceita `"HIGH"` ou `"NORM"`: é a prioridade da transação original,
reaproveitando o mesmo tipo ISO do `InstrPrty` da pacs.008. O nome do
campo segue o da tag, mas o conteúdo é esse.

## Lote

`Ntfctn` é ilimitado no schema. O caminho comum é um lançamento por
notificação, mas `encode/3` aceita uma mensagem ou uma lista, e
`decode/1` devolve uma struct ou uma lista. `Ntry` continua sendo no
máximo 1, isso não muda.

# `t`

```elixir
@type t() :: %Isox.Camt054{
  accptnc_dt_tm: term(),
  acct_ispb: term(),
  addtl_ntfctn_inf: term(),
  addtl_ntry_inf: term(),
  addtl_tx_inf: term(),
  bktxcd_domn_cd: term(),
  bktxcd_fmly_cd: term(),
  bktxcd_sub_fmly_cd: term(),
  bookg_dt: term(),
  cdt_dbt_ind: term(),
  cdtr_acct_id: term(),
  cdtr_acct_issr: term(),
  cdtr_acct_proxy: term(),
  cdtr_acct_type: term(),
  cdtr_agt_ispb: term(),
  cdtr_cpf_cnpj: term(),
  clr_sys_ref: term(),
  created_at: term(),
  dbtr_acct_id: term(),
  dbtr_acct_issr: term(),
  dbtr_acct_type: term(),
  dbtr_agt_ispb: term(),
  dbtr_cpf_cnpj: term(),
  dbtr_name: term(),
  end_to_end_id: term(),
  initg_pty_id: term(),
  instr_id: term(),
  lcl_instrm: term(),
  msg_id: term(),
  msg_nm_id: term(),
  ntfctn_id: term(),
  prtry_ref: term(),
  purp_cd: term(),
  rmt_inf: term(),
  rtr_rsn_addtl_inf: term(),
  rtr_rsn_cd: term(),
  sts_cd: term(),
  tx_id: term(),
  val_dt: term(),
  value: term()
}
```

# `version`

```elixir
@type version() :: :v1_15 | :v1_16
```

# `decode`

```elixir
@spec decode(binary()) :: {:ok, t() | [t(), ...], version()} | {:error, term()}
```

Decodifica um XML de camt.054 de volta para a struct, ou
para uma lista de structs quando a
mensagem traz mais de um `Ntfctn` (lote), para uma lista de structs.

# `encode`

```elixir
@spec encode(t() | [t(), ...], Isox.AppHdr.t(), version()) ::
  {:ok, binary()} | {:error, String.t()}
```

Monta o XML (envelope completo, `AppHdr` + `Document`) para a versão
dada. Aceita 1 mensagem ou uma lista de mensagens (lote: vira vários
`Ntfctn` na mesma `Document`).

`msg_id`/`created_at` são de `GrpHdr` (uma vez por mensagem XML). Em
lote, têm que ser iguais em todos os itens da lista.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
