<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jefferson Rodrigues</title>
    <description>The latest articles on DEV Community by Jefferson Rodrigues (@jeffersonrodrigues92).</description>
    <link>https://dev.to/jeffersonrodrigues92</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2863155%2F148cef97-f844-414e-a730-f22152f6c398.png</url>
      <title>DEV Community: Jefferson Rodrigues</title>
      <link>https://dev.to/jeffersonrodrigues92</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jeffersonrodrigues92"/>
    <language>en</language>
    <item>
      <title>Saga pattern</title>
      <dc:creator>Jefferson Rodrigues</dc:creator>
      <pubDate>Thu, 18 Sep 2025 10:58:43 +0000</pubDate>
      <link>https://dev.to/jeffersonrodrigues92/saga-pattern-4ca6</link>
      <guid>https://dev.to/jeffersonrodrigues92/saga-pattern-4ca6</guid>
      <description></description>
    </item>
    <item>
      <title>Midaz Terraform Foundation: AWS, GCP e Azure</title>
      <dc:creator>Jefferson Rodrigues</dc:creator>
      <pubDate>Thu, 05 Jun 2025 14:40:15 +0000</pubDate>
      <link>https://dev.to/jeffersonrodrigues92/midaz-terraform-foundation-aws-gcp-e-azure-4e81</link>
      <guid>https://dev.to/jeffersonrodrigues92/midaz-terraform-foundation-aws-gcp-e-azure-4e81</guid>
      <description>&lt;p&gt;Provisionar uma infraestrutura sólida, segura e escalável é um passo essencial para rodar aplicações financeiras com alto grau de exigência — como o Midaz, o core bancário open source desenvolvido pela Lerian Studio.&lt;/p&gt;

&lt;p&gt;Pensando nisso, a Lerian desenvolveu o Midaz Terraform Foundation, que oferece uma coleção de templates Terraform para criar a fundação necessária para operar o Midaz com eficiência, seguindo boas práticas e com suporte às três principais nuvens do mercado: AWS, Google Cloud Platform (GCP) e Microsoft Azure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🎯 Foco na fundação: redes, DNS, bancos e Kubernetes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O repositório entrega módulos organizados por provedor e por componente, cobrindo todos os elementos essenciais para executar uma aplicação moderna em cloud:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;examples/&lt;br&gt;
├── aws/     → VPC, Route53, RDS, Valkey, EKS&lt;br&gt;
├── gcp/     → VPC, Cloud DNS, Cloud SQL, Valkey, GKE&lt;br&gt;
└── azure/   → Network, DNS, Database, Redis, AKS&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A estrutura respeita a ordem lógica de provisionamento:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rede&lt;/li&gt;
&lt;li&gt;DNS&lt;/li&gt;
&lt;li&gt;Banco de dados&lt;/li&gt;
&lt;li&gt;Cache (Valkey/Redis)&lt;/li&gt;
&lt;li&gt;Cluster Kubernetes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;✅ Boas práticas incorporadas&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Todos os templates seguem recomendações dos próprios provedores, utilizando módulos oficiais sempre que possível, aplicando versionamento e bloqueio de estado, e separando claramente código e configuração.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔐 Segurança embutida&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Autenticação via CLI com suporte a MFA, SSO e rotação de credenciais&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Armazenamento remoto de estado com criptografia;&lt;/li&gt;
&lt;li&gt;Compatibilidade com o princípio do menor privilégio;&lt;/li&gt;
&lt;li&gt;Recomendações de uso com clusters privados e controle de acesso via RBAC;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🧩 Modularidade e reuso&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Templates reutilizáveis por componente&lt;/li&gt;
&lt;li&gt;Separação por ambiente via arquivos .tfvars&lt;/li&gt;
&lt;li&gt;Estrutura compatível com automação em pipelines de CI/CD, como GitLab, GitHub Actions, Jenkins e outras ferramentas&lt;/li&gt;
&lt;li&gt;Facilita a adoção de práticas GitOps e integração com gerenciadores de segredos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;☁️ Suporte nativo a múltiplos provedores&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O Midaz Terraform Foundation é compatível com AWS, GCP e Azure, permitindo que a infraestrutura seja criada no provedor que melhor se adapta à estratégia da organização — seja por razões técnicas, comerciais ou regulatórias.&lt;br&gt;
Essa flexibilidade é ideal para:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Equipes que trabalham com múltiplos ambientes distribuídos em diferentes clouds;&lt;/li&gt;
&lt;li&gt;Organizações que desejam evitar lock-in;&lt;/li&gt;
&lt;li&gt;Produtos que precisam ser implantados em diferentes regiões ou clientes com requisitos distintos;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🛡️ Preparado para ambientes críticos&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Projetado com foco em aplicações sensíveis como o Midaz, o Terraform Foundation é adequado para empresas que operam sob requisitos rigorosos de segurança, auditoria e conformidade.&lt;/p&gt;

&lt;p&gt;Entre os destaques:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prontidão para ambientes produtivos&lt;/li&gt;
&lt;li&gt;Controle de versionamento e histórico de mudanças&lt;/li&gt;
&lt;li&gt;Base segura para implantar o Midaz via Helm em clusters Kubernetes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🚀 Resumo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O Midaz Terraform Foundation oferece uma fundação de infraestrutura open source, robusta, segura e escalável — pronta para ser adotada por times que desejam acelerar a implantação do Midaz ou estruturar seus ambientes em nuvem com consistência, reutilização e governança.&lt;/p&gt;

&lt;p&gt;Com suporte para AWS, GCP e Azure, os templates entregam flexibilidade, padronização e aderência às boas práticas de mercado, tudo em um único repositório acessível à comunidade.&lt;/p&gt;

&lt;p&gt;🔗 Repositório: &lt;a href="https://github.com/LerianStudio/midaz-terraform-foundation" rel="noopener noreferrer"&gt;Midaz Terraform Foundation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>corebanking</category>
      <category>terraform</category>
      <category>devops</category>
      <category>infrastructureascode</category>
    </item>
    <item>
      <title>Construindo SDKs: Lições da Lerian com o Midaz, o primeiro ledger open source da América Latina.</title>
      <dc:creator>Jefferson Rodrigues</dc:creator>
      <pubDate>Wed, 28 May 2025 18:24:32 +0000</pubDate>
      <link>https://dev.to/lerian/construindo-sdks-licoes-da-lerian-com-o-midaz-o-primeiro-ledger-open-source-da-america-latina-1kid</link>
      <guid>https://dev.to/lerian/construindo-sdks-licoes-da-lerian-com-o-midaz-o-primeiro-ledger-open-source-da-america-latina-1kid</guid>
      <description>&lt;p&gt;Hoje quero compartilhar um pouco dos bastidores do desenvolvimento das nossas SDKs oficiais para o Midaz, nosso ledger open source para sistemas financeiros e, por que, para nós, SDK não é um simples wrapper e sim um produto que expressa nosso foco junto com a comunidade de desenvolvedores.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O que está por trás do Midaz?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No coração do Midaz existe um ledger open source com double-entry contábil, multi-moeda e preparado para fluxos complexos de transações financeiras. &lt;/p&gt;

&lt;p&gt;Mas sabemos que expor apenas APIs REST não resolve o maior desafio: a barreira de entrada para quem está construindo fintechs e sistemas financeiros robustos, ou seja, a dificuldade que muitas vezes o time tech do nosso cliente encontra ao integrar novas ferramentas. Por exemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Documentação confusa e com ausência de informações relevantes;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;API’s inconsistentes;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ausência de exemplos reais de aplicabilidade;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Falta de ferramentas para lidar com retries, performance e resiliência.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;SDK: mais que um wrapper, uma extensão da arquitetura&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Quando decidimos construir as SDKs do Midaz em TypeScript e Go, partimos de alguns questionamentos internos: Como tornar a vida do desenvolvedor mais fácil, sem abrir mão da robustez financeira?&lt;/p&gt;

&lt;p&gt;Como evitar que erros bobos (payload mal formatado, conta errada e afins) virem problemas reais em produção? Como suportar o nosso cliente a ter uma implantação fluida e eficiente?&lt;/p&gt;

&lt;p&gt;Como criar um kit que realmente ajuda a escalar a operação do cliente e não só a conectar pontas?&lt;/p&gt;

&lt;p&gt;A resposta foi desenhar SDKs como uma ferramentas de verdade e com algumas premissas básicas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Validação no cliente: não faz sentido mandar ao backend algo que já sabemos que vai falhar;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retry inteligente: em sistemas financeiros, falhas transitórias são normais e por isso há a necessidade de antever esse movimento com backoff exponencial, jitter, categorização de erros e afins;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Paginação e concorrência controlada: processar grandes volumes de dados não é um caso de uso opcional quando falamos de mercado financeiro e de partidas contábeis dobradas;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Performance e observabilidade: pooling de JSON, modularidade de logs e tracing com OpenTelemetry;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Exemplos práticos: a documentação só é considerada completa quando temos casos de uso práticos para o usuário entender a aplicabilidade do que estamos construindo. &lt;/p&gt;

&lt;p&gt;No SDK de GoLang, por exemplo, optamos por um padrão de opções funcionais para configuração. Já no SDK de TypeScript, aproveitamos o ecossistema para entregar tipagem forte e integração fluida com ferramentas modernas de frontend e backend.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open source como filosofia da Lerian&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Lançar SDKs como parte de um projeto open source nos traz responsabilidades extras porque temos que manter a coerência, garantir a estabilidade e documentar de forma que as pessoas da comunidade possam contribuir.&lt;/p&gt;

&lt;p&gt;Por isso, acreditamos que SDKs bem desenhados não são “nice to have” e sim são o coração do nosso pilar de Developer Experience e também para um pilar para o futuro financeiro open source que estamos ajudando a construir.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusão&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Os SDKs do Midaz nasceram de um princípio simples: foco na agilidade dos entregáveis aos nossos clientes e compromisso com a confiabilidade.&lt;br&gt;
Queremos que qualquer pessoa que precise integrar com um core banking tenha em mãos ferramentas que façam sentido, funcionem e sejam transparentes.&lt;br&gt;
Se quiser ver o que estamos criando (ou contribuir!):&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/LerianStudio/midaz" rel="noopener noreferrer"&gt;Midaz no GitHub&lt;/a&gt;&lt;br&gt;
 🔗 &lt;a href="https://github.com/LerianStudio/midaz-sdk-typescript" rel="noopener noreferrer"&gt;SDK TypeScript&lt;/a&gt;&lt;br&gt;
 🔗 &lt;a href="https://github.com/LerianStudio/midaz-sdk-golang" rel="noopener noreferrer"&gt;SDK Go&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedbacks e pull requests são sempre bem-vindos.&lt;/p&gt;

&lt;p&gt;Vamos construir o futuro financeiro juntos?&lt;/p&gt;

&lt;p&gt;Jeff Rodrigues / CTO @ Lerian&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Plugins made-to-scale: uma visão sobre cache, filas e resiliência.</title>
      <dc:creator>Jefferson Rodrigues</dc:creator>
      <pubDate>Mon, 19 May 2025 20:08:49 +0000</pubDate>
      <link>https://dev.to/lerian/plugins-made-to-scale-uma-visao-sobre-cache-filas-e-resiliencia-2o7c</link>
      <guid>https://dev.to/lerian/plugins-made-to-scale-uma-visao-sobre-cache-filas-e-resiliencia-2o7c</guid>
      <description>&lt;p&gt;Quando falamos de infraestrutura financeira, resiliência não é um diferencial e sim um requisito. E na Lerian, cada plugin construído é pensado para garantir estabilidade mesmo em ambientes hostis: redes instáveis, dependências externas, falhas parciais e tráfego intenso.&lt;/p&gt;

&lt;p&gt;Neste artigo, exploramos como cache, filas e boas práticas de resiliência são combinadas na arquitetura dos nossos plugins para criar soluções robustas, auditáveis e performáticas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Cache: Performance sem comprometer a consistência.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Muitos plugins operam com dados de leitura frequente e alteração rara como, por exemplo, pacotes de tarifas e gerenciamento de tokens e lock de transações. Para esses casos, adotamos cache local e distribuído: &lt;/p&gt;

&lt;p&gt;Valkey é usado para armazenar estruturas intermediárias e reduzir chamadas ao backend;&lt;/p&gt;

&lt;p&gt;TTLs inteligentes ajudam a equilibrar escala  e eficiência;&lt;br&gt;
Embora não utilizemos eventos de pub/sub em todos os plugins, o cache é atualizado individualmente por cada serviço, conforme a lógica de funcionamento definida para cada um deles.&lt;/p&gt;

&lt;p&gt;Essa camada reduz a latência de chamadas, alivia a pressão sobre o core e melhora a experiência do consumidor da API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Filas: desacoplamento, resiliência e reatividade com integridade.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Plugins que se comunicam com serviços externos ou operam de forma assíncrona utilizam filas como mecanismo de segurança e desacoplamento. É o caso do Smart Templates e do próprio ledger, Midaz, que empregam filas para garantir que, em caso de erro, nenhuma informação se perca e a operação possa ser reprocessada com consistência.&lt;/p&gt;

&lt;p&gt;Adotamos o RabbitMQ como broker padrão, tanto para persistência assíncrona de saldo quanto para orquestrar eventos como a criação de contas de asset.&lt;/p&gt;

&lt;p&gt;Essa arquitetura atual, com mecanismo de retry, permite reatividade sem comprometer a integridade: se uma dependência estiver indisponível, a mensagem é retida e processada posteriormente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Resiliência: Não é sobre evitar falhas, mas sobre suportá-las.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nossos plugins seguem padrões de projeto defensivos:&lt;br&gt;
Idempotência nativa: eventos são processados uma única vez, mesmo que reenviados;&lt;/p&gt;

&lt;p&gt;Utilizamos a fila como mecanismo de retry, uma prática que garante resiliência operacional  para evitar overload;&lt;/p&gt;

&lt;p&gt;Observabilidade integrada com OpenTelemetry para tracing, métricas e logs estruturados.&lt;/p&gt;

&lt;p&gt;Para garantir segurança e controle de acesso, cada plugin que se integra ao ledger pode utilizar uma credencial própria para se autenticar no Midaz. Com isso, conseguimos definir permissões específicas por plugin, evitando o uso de uma credencial única e reduzindo o risco de acessos indevidos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Plugins como produtos de infraestrutura&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cada plugin é tratado como um componente core, com o mesmo rigor técnico aplicado ao próprio Midaz. Afinal, eles não ficam na borda: executam lógica crítica como cálculo de tarifas, câmbio, validação de acesso, entre outras funções sensíveis.&lt;/p&gt;

&lt;p&gt;Cache, filas e resiliência não são acessórios. São fundamentos arquiteturais que garantem performance, consistência e estabilidade,  mesmo diante de falhas externas ou cenários de alta complexidade.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quer explorar o que estamos construindo?&lt;/strong&gt;&lt;br&gt;
 🔗 github.com/lerianstudio&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Garantindo confiabilidade do calculo valores monetários</title>
      <dc:creator>Jefferson Rodrigues</dc:creator>
      <pubDate>Tue, 18 Mar 2025 18:54:24 +0000</pubDate>
      <link>https://dev.to/lerian/garantindo-confiabilidade-do-calculo-valores-monetarios-fme</link>
      <guid>https://dev.to/lerian/garantindo-confiabilidade-do-calculo-valores-monetarios-fme</guid>
      <description>&lt;p&gt;Continuando a nossa &lt;a href="https://dev.to/jeffersonrodrigues92/series/30606"&gt;saga de entender como são realizadas as transações financeiras&lt;/a&gt;, hoje vamos explorar um aspecto crítico no desenvolvimento de sistemas financeiros: como garantir a precisão nos cálculos de valores monetários.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entendendo o que é precisão arbitrária
&lt;/h2&gt;

&lt;p&gt;Um dos conceitos importantes quando falamos de transações financeiras é a precisão arbitrária, que permite que os cálculos matemáticos sejam realizados com exatidão absoluta, sem limitações de tamanho ou escala. Isso é especialmente crucial em sistemas financeiros, onde até mesmo pequenos erros de arredondamento podem resultar em discrepâncias significativas ao longo do tempo.&lt;/p&gt;

&lt;h2&gt;
  
  
  O problema da precisão
&lt;/h2&gt;

&lt;p&gt;Em Go, se usarmos &lt;code&gt;float64&lt;/code&gt; para somar valores monetários, podemos obter resultados imprecisos devido à forma como números de ponto flutuante são representados na memória.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kr"&gt;package&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fmt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;a&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;
    &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;
    &lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 0.30000000000000004 ❌ (Erro de precisão)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Por que esse erro acontece?
&lt;/h3&gt;

&lt;p&gt;Números de ponto flutuante (&lt;code&gt;float64&lt;/code&gt;) são representados internamente usando o &lt;strong&gt;padrão IEEE 754&lt;/strong&gt;, que usa uma aproximação binária para armazenar valores decimais. No entanto, números como &lt;code&gt;0.1&lt;/code&gt; e &lt;code&gt;0.2&lt;/code&gt; não têm uma representação exata em binário, resultando em pequenas imprecisões ao somar.&lt;/p&gt;

&lt;p&gt;Isso pode ser um grande problema em aplicações financeiras, pois pequenos erros podem se acumular ao longo de muitas transações.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solução: Usando &lt;code&gt;math/big&lt;/code&gt; para Precisão Arbitrária
&lt;/h3&gt;

&lt;p&gt;Em Go, a biblioteca &lt;code&gt;math/big&lt;/code&gt; oferece o tipo &lt;code&gt;big.Float&lt;/code&gt;, que permite cálculos com precisão arbitrária:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kr"&gt;package&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fmt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;math/big&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;a&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NewFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NewFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Float&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nc"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;f&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// "0.3" ✅ (Precisão exata)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui, &lt;code&gt;big.NewFloat(0.1)&lt;/code&gt; armazena o número com precisão arbitrária, evitando erros de arredondamento.&lt;/p&gt;

&lt;h2&gt;
  
  
  Armazenando centavos como inteiros
&lt;/h2&gt;

&lt;p&gt;No nosso caso, &lt;a href="https://github.com/LerianStudio/midaz/blob/main/components/transaction/internal/adapters/postgres/operation/operation.go" rel="noopener noreferrer"&gt;dentro do Midaz&lt;/a&gt;, armazenamos todos os valores monetários como uma estrutura que combina um valor inteiro (Amount) e uma escala (Scale).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Amount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;int64&lt;/span&gt; &lt;span class="s"&gt;`json:"amount" example:"1500"`&lt;/span&gt;
    &lt;span class="n"&gt;Scale&lt;/span&gt;  &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;int64&lt;/span&gt; &lt;span class="s"&gt;`json:"scale" example:"2"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No código acima, o Amount representa o valor monetário multiplicado pela escala (10^n), e o Scale define o número de casas decimais. Por exemplo, para representar R$ 15,00, teríamos &lt;code&gt;Amount = 1500&lt;/code&gt; e &lt;code&gt;Scale = 2&lt;/code&gt;. Esta estrutura nos permite trabalhar com valores monetários de forma precisa e flexível, adaptando-se a diferentes moedas e requisitos de precisão.&lt;/p&gt;

&lt;p&gt;Esta abordagem é particularmente interessante para valores cuja precisão varia, como é o caso do Bitcoin, em que é necessário trabalhar com até 8 casas decimais. Para entender mais sobre o &lt;code&gt;Amount&lt;/code&gt; e &lt;code&gt;Scale&lt;/code&gt;, recomendo &lt;a href="https://docs.lerian.studio/docs/amount-and-scale" rel="noopener noreferrer"&gt;a leitura da nossa documentação&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;E você, já teve que lidar com cálculos monetários com esse nível de precisão? Como foi sua experiência? Compartilhe suas experiências nos comentários abaixo!&lt;/p&gt;

</description>
      <category>go</category>
      <category>braziliandevs</category>
      <category>midaz</category>
      <category>programming</category>
    </item>
    <item>
      <title>Ledgers Open Source: Transformando Conceitos em Vantagem Competitiva</title>
      <dc:creator>Jefferson Rodrigues</dc:creator>
      <pubDate>Mon, 10 Mar 2025 14:00:32 +0000</pubDate>
      <link>https://dev.to/lerian/ledgers-open-source-transformando-conceitos-em-vantagem-competitiva-3g8k</link>
      <guid>https://dev.to/lerian/ledgers-open-source-transformando-conceitos-em-vantagem-competitiva-3g8k</guid>
      <description>&lt;p&gt;Se você está mergulhando no mundo dos sistemas financeiros, provavelmente já se deparou com o termo "ledger". Mas o que realmente é um ledger e por que a abordagem open source que a Lerian está tendo está revolucionando este cenário?&lt;/p&gt;

&lt;p&gt;Em sua essência, um ledger é um sistema de registro que mantém o histórico de transações de forma auditável. Quando combinamos isso com open source, criamos algo verdadeiramente poderoso.&lt;/p&gt;

&lt;p&gt;O valor do open source neste contexto vai muito além do código aberto. Estamos falando de:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔍 Transparência total: Cada linha de código pode ser auditada&lt;/li&gt;
&lt;li&gt;🛡️ Segurança fortalecida: A comunidade atua como guardiã constante&lt;/li&gt;
&lt;li&gt;🚀 Inovação acelerada: Contribuições podem vir de qualquer lugar&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Estas características não são apenas &lt;em&gt;buzzwords&lt;/em&gt; — são vantagens competitivas reais que podem impulsionar projetos e empresas a novos patamares.&lt;/p&gt;

&lt;p&gt;Ao explorar ledgers open source, como o &lt;a href="https://github.com/LerianStudio/midaz" rel="noopener noreferrer"&gt;repositório do Midaz&lt;/a&gt;, você se conecta a um mundo de possibilidades profissionais e técnicas. Por exemplo:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Você tem a oportunidade de contribuir com sistemas que estão redefinindo o futuro das transações financeiras&lt;/li&gt;
&lt;li&gt;Pode aprender com implementações reais de &lt;a href="https://dev.to/lerian/race-conditions-e-locks-garantindo-a-integridade-das-transacoes-financeiras-24b3"&gt;como uma transação financeira funciona&lt;/a&gt; e &lt;a href="https://dev.to/lerian/double-entry-o-que-e-quando-usar-e-como-fazer-2594"&gt;modelos double-entry&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://discord.lerian.studio" rel="noopener noreferrer"&gt;Fazer parte de uma comunidade&lt;/a&gt; que está ativamente moldando o futuro dos sistemas financeiros&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>midaz</category>
      <category>opensource</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>What is Double Entry and how to use it on a financial operation</title>
      <dc:creator>Jefferson Rodrigues</dc:creator>
      <pubDate>Wed, 05 Mar 2025 12:06:00 +0000</pubDate>
      <link>https://dev.to/lerian/what-is-double-entry-and-how-to-use-it-on-a-financial-operation-1ae5</link>
      <guid>https://dev.to/lerian/what-is-double-entry-and-how-to-use-it-on-a-financial-operation-1ae5</guid>
      <description>&lt;p&gt;Those who are starting to work in the financial sector may encounter the term "double-entry," which is a fundamental concept for managing financial transactions and records. In this post, I want to explain in detail how this concept works, when it should be used, and its importance in maintaining the integrity of financial transactions.&lt;/p&gt;

&lt;p&gt;The best way to explain what double-entry is with an example. So, consider that you make a transfer of R$ 1,000 to pay a bill; this transfer process actually performs two operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first operation is a 1,000$ debit from your account;&lt;/li&gt;
&lt;li&gt;The second operation is a 1,000$ credit to the destination account.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is essential that, for the transaction to be successfully completed, both operations are recorded correctly. If one of the operations fails, the entire process needs to be reversed to maintain account integrity. This concept is known as double entry and is fundamental to ensuring the integrity of financial transactions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3uv1qiunnqyu8raf96r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3uv1qiunnqyu8raf96r.png" alt="Image description" width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Importance in the Financial Sector
&lt;/h2&gt;

&lt;p&gt;The double entry system is crucial in the financial sector for several reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Accounting accuracy:&lt;/strong&gt; Ensures that all financial transactions are recorded accurately, reducing errors and discrepancies in accounts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplified auditing:&lt;/strong&gt; Makes it easy to track transaction history and identify potential irregularities or fraud.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regulatory compliance:&lt;/strong&gt; Meets legal and regulatory requirements of the financial sector, which demand accurate and transparent records.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bank reconciliation:&lt;/strong&gt; Simplifies the reconciliation process, enabling efficient comparison between internal records and bank statements.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Applications Beyond Financial Systems
&lt;/h2&gt;

&lt;p&gt;The double entry system, although traditionally associated with financial systems, can also be applied in other contexts, such as inventory management and logistics where it's necessary to record the inflow and outflow of products.&lt;/p&gt;

&lt;p&gt;In all these cases, the fundamental principle of double entry — where each transaction affects two different records — helps maintain data integrity and traceability.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to Develop
&lt;/h1&gt;

&lt;p&gt;Let's create a simple implementation example of the double entry system in Go. In this example, we'll simulate a bank transfer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Account&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;      &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Balance&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Transaction&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;        &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;FromID&lt;/span&gt;    &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;ToID&lt;/span&gt;      &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Amount&lt;/span&gt;    &lt;span class="kt"&gt;float64&lt;/span&gt;
    &lt;span class="n"&gt;Timestamp&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Debit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Insufficient balance."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Credit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// First entry: debit from the source account.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Debit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Second entry: credit to the destination account.&lt;/span&gt;
    &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Credit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Creating example accounts&lt;/span&gt;
    &lt;span class="n"&gt;accountA&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="s"&gt;"conta_a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1000.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;accountB&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="s"&gt;"conta_b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;500.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Before the transfer:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Account A: %.2f&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Account B: %.2f&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;accountA&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accountB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Performing a transfer.&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accountA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accountB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;300.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"After the transfer:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Account A: %.2f&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Account B: %.2f&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;accountA&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accountB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we implemented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;code&gt;Account&lt;/code&gt; structure to represent accounts with ID and balance&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;Transaction&lt;/code&gt; structure to record transaction details&lt;/li&gt;
&lt;li&gt;Methods &lt;code&gt;Debit&lt;/code&gt; and &lt;code&gt;Credit&lt;/code&gt; to perform account operations&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;Transfer&lt;/code&gt; function that implements the double entry concept, ensuring both operations are performed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When executed, this code demonstrates a transfer of $300.00 from account A to account B, showing the balances before and after the operation. If there is any error during the process (such as insufficient funds), the transaction is not completed.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Said Operations
&lt;/h3&gt;

&lt;p&gt;In the example we saw earlier, we created two fundamental operations that make up a transaction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A debit operation (Debit) that removes the value from the source account&lt;/li&gt;
&lt;li&gt;A credit operation (Credit) that adds the value to the destination account&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These operations are the basic units of a financial transaction and must always occur in pairs to maintain the double-entry principle. Each operation is atomic, meaning it either happens completely or doesn't happen at all, with no intermediate states.&lt;/p&gt;

&lt;p&gt;In the code, we implemented these operations as separate methods of the Account structure, but they are always called together through the Transfer function to ensure the double-entry principle is respected.&lt;/p&gt;

&lt;h3&gt;
  
  
  Encapsulation and Security
&lt;/h3&gt;

&lt;p&gt;To ensure that the balance can only be modified through the transaction function, we can use encapsulation and make the Balance field private in the Account structure. See how we can modify the previous code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Account&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;      &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;  &lt;span class="c"&gt;// Note the lowercase 'b' making the field private.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Getter method to access the balance.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetBalance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Debit and credit methods now work with the private field.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;debit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"saldo insuficiente"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;credit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this implementation, the balance field can only be modified through the package's own methods, ensuring that all balance changes go through the double entry system.&lt;/p&gt;

&lt;p&gt;Of course, there are other important considerations when implementing a double entry system, such as ensuring transaction atomicity using a transactional database and implementing detailed logs of all operations for auditing purposes. These practices help maintain system integrity and traceability.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Code in Production
&lt;/h1&gt;

&lt;p&gt;As a practical example of a tool that implements the double entry system, we have &lt;a href="https://github.com/LerianStudio/midaz" rel="noopener noreferrer"&gt;Midaz, an open source ledger maintained by Lerian&lt;/a&gt; that uses this technique to ensure the integrity of financial transactions.&lt;/p&gt;

&lt;p&gt;Unlike virtually all Brazilian financial systems which are closed, Midaz allows us to openly examine and discuss the use of double entry and study how this practice works in a production environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  How an Operation is Created
&lt;/h3&gt;

&lt;p&gt;Let's examine how Midaz creates an individual operation within a transaction. Within the creation of a transaction, the &lt;code&gt;CreateOperation&lt;/code&gt; method is called, which receives the transaction details and the accounts involved. Here's the commented code for creating an operation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;UseCase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;CreateOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;transactionID&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;dsl&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;goldModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;validate&lt;/span&gt; &lt;span class="n"&gt;goldModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Responses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Operation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c"&gt;// Declare a list to store the created operations.&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;operations&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Operation&lt;/span&gt;

    &lt;span class="c"&gt;// Create a fromTo list containing the source and destination accounts involved in the transaction.&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fromTo&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;goldModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromTo&lt;/span&gt;
    &lt;span class="n"&gt;fromTo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fromTo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dsl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Send&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Source&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;From&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c"&gt;// Add origin accounts.&lt;/span&gt;
    &lt;span class="n"&gt;fromTo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fromTo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dsl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Send&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Distribute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;To&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c"&gt;// Add destination accounts.&lt;/span&gt;

    &lt;span class="c"&gt;// Iterate over all the accounts involved in the transaction.&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Check if the account is in the fromTo list.&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;fromTo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="c"&gt;// Check if the current account is involved in the transaction, either by ID or alias.&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;fromTo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;fromTo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Alias&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

                &lt;span class="c"&gt;// Set the account's current balance.&lt;/span&gt;
                &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;Available&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Available&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;OnHold&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnHold&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Scale&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="c"&gt;// Validate the operation and calculate the transaction values.&lt;/span&gt;
                &lt;span class="n"&gt;amt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;er&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;goldModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ValidateFromToOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fromTo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;er&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error creating operation: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;er&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="c"&gt;// Convert the transaction values to float64 and set the decimal scale.&lt;/span&gt;
                &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Scale&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="c"&gt;// Set the account balance after the operation.&lt;/span&gt;
                &lt;span class="n"&gt;ba&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Available&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;boh&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnHold&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;bs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="n"&gt;balanceAfter&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;Available&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ba&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;OnHold&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;boh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Scale&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="c"&gt;// Select whether the operation will be a debit or a credit.&lt;/span&gt;
                &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;typeOperation&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;fromTo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsFrom&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;typeOperation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEBIT&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;typeOperation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CREDIT&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="c"&gt;// Create a new operation with the processed data.&lt;/span&gt;
                &lt;span class="n"&gt;save&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Operation&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;              &lt;span class="n"&gt;pkg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GenerateUUIDv7&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                    &lt;span class="n"&gt;TransactionID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;transactionID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;            &lt;span class="n"&gt;typeOperation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;AssetCode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="n"&gt;dsl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Send&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Asset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;          &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;         &lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;BalanceAfter&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;balanceAfter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;AccountID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;AccountAlias&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Alias&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="o"&gt;...&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="c"&gt;// Save the operation to the database.&lt;/span&gt;
                &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;er&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;uc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OperationRepo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;er&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error creating operation: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;er&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="c"&gt;// Add the created operation to the list of operations.&lt;/span&gt;
                &lt;span class="n"&gt;operations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;operations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="c"&gt;// Exit the loop to avoid multiple inclusions of the same account.&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Sends the list of created operations through the result channel&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;operations&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make it easier to read, I removed loggers and tracers and some other details, but you can analyze the complete code on GitHub &lt;a href="https://github.com/LerianStudio/midaz/blob/main/components/transaction/internal/adapters/http/in/transaction.go" rel="noopener noreferrer"&gt;for creating a transaction&lt;/a&gt; and the operation. Leave a comment if you would like an article breaking down and explaining how the code for a complete financial transaction is done.&lt;/p&gt;

</description>
      <category>midaz</category>
      <category>go</category>
      <category>opensource</category>
      <category>backend</category>
    </item>
    <item>
      <title>Race Conditions e Locks: Garantindo a Integridade das Transações Financeiras</title>
      <dc:creator>Jefferson Rodrigues</dc:creator>
      <pubDate>Tue, 25 Feb 2025 16:29:15 +0000</pubDate>
      <link>https://dev.to/lerian/race-conditions-e-locks-garantindo-a-integridade-das-transacoes-financeiras-24b3</link>
      <guid>https://dev.to/lerian/race-conditions-e-locks-garantindo-a-integridade-das-transacoes-financeiras-24b3</guid>
      <description>&lt;p&gt;Assim como &lt;a href="https://dev.to/lerian/double-entry-o-que-e-quando-usar-e-como-fazer-2594"&gt;falei sobre Double-Entry recentemente&lt;/a&gt;, hoje quero falar sobre um outro pilar fundamental na construção de um sistema financeiro confiável, o Race Condition.&lt;/p&gt;

&lt;p&gt;Race conditions acontecem quando dois ou mais processos tentam acessar e modificar o mesmo recurso simultaneamente, podendo levar a resultados inconsistentes ou comportamentos inesperados no sistema.&lt;/p&gt;

&lt;p&gt;Por exemplo, quando dois usuários tentam atualizar o mesmo registro em um banco de dados ao mesmo tempo, o resultado final pode não refletir corretamente as alterações de ambos os processos. Essa situação é particularmente crítica em sistemas que lidam com dados sensíveis ou transações financeiras na modalidade débito.&lt;/p&gt;

&lt;p&gt;Imagine uma conta com saldo de R$ 100, onde duas operações de débito chegam exatamente no mesmo segundo — acontece e muito! — uma de R$ 50 e outra de R$ 80. No total deveria debitar da conta R$ 130, porém como só há R$ 100, ficaria R$ 30 negativos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3jgkdyesndyr6ezwv2a3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3jgkdyesndyr6ezwv2a3.png" alt="Image description" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Essa situação pode causar sérios problemas de consistência de dados e prejuízos financeiros gigantes, já que o sistema pode processar ambas as transações sem a devida validação do saldo disponível. &lt;/p&gt;

&lt;h2&gt;
  
  
  Possíveis soluções
&lt;/h2&gt;

&lt;p&gt;Existem várias abordagens para prevenir race conditions em sistemas financeiros, como por exemplo implementar o conceito de serialização de transações, onde as operações são processadas em uma ordem específica e controlada.&lt;/p&gt;

&lt;p&gt;Além disso, a utilização de controle de concorrência otimista (OCCs - Optimistic Concurrency Control) pode ser uma alternativa viável, especialmente em sistemas com baixa probabilidade de conflitos. Em suma, ela permite que múltiplas transações ocorram simultaneamente, verificando apenas no momento da confirmação (commit) se houve algum conflito. Se um conflito for detectado, a transação é revertida e pode ser tentada novamente. Esta abordagem é especialmente eficiente em ambientes onde os conflitos são raros, pois evita o overhead de bloqueios constantes.&lt;/p&gt;

&lt;p&gt;Outra solução eficaz e amplamente difundida é a utilização de locks, ou semáforos, que garantem acesso exclusivo aos recursos compartilhados durante uma transação. &lt;/p&gt;

&lt;h1&gt;
  
  
  Funcionamento dos Locks
&lt;/h1&gt;

&lt;p&gt;Locks são mecanismos de sincronização que impedem que múltiplos processos acessem simultaneamente um recurso compartilhado. Em um sistema financeiro, quando uma transação precisa modificar o saldo de uma conta, ela primeiro adquire um lock exclusivo sobre aquele registro, garantindo que nenhuma outra transação possa alterá-lo ao mesmo tempo. Somente após a conclusão da primeira transação e a liberação do lock, outras operações podem acessar e modificar o mesmo recurso.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementando locks com Redis
&lt;/h2&gt;

&lt;p&gt;O &lt;a href="https://redis.io/docs/latest/develop/use/patterns/distributed-locks/" rel="noopener noreferrer"&gt;Redis é uma excelente opção para implementar locks distribuídos&lt;/a&gt; devido à sua natureza atômica e alta performance. Um exemplo simples de implementação seria utilizar o comando SETNX (SET if Not eXists) para criar um lock:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;acquireLock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lockKey&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;acquired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetNX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lockKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unix&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;acquired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este código cria um lock atômico que expira automaticamente após um determinado período, evitando deadlocks caso o processo que adquiriu o lock falhe antes de liberá-lo.&lt;/p&gt;

&lt;p&gt;É crucial garantir sua liberação após a conclusão da operação, mesmo em caso de erros. Isso pode ser feito utilizando um bloco try-finally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;performOperation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;lockKey&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"account:123:lock"&lt;/span&gt;
    &lt;span class="n"&gt;acquired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;acquireLock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lockKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;acquired&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Del&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lockKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c"&gt;// Execute operation&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta abordagem garante que o lock será sempre liberado, permitindo que outras operações prossigam normalmente.&lt;/p&gt;

&lt;p&gt;Voltando ao nosso exemplo anterior da conta com 100 reais e duas transações simultâneas, a implementação de locks garantiria que apenas uma transação fosse processada por vez. Assim, se a primeira transação de 50 reais adquirisse o lock, ela seria processada completamente antes que a segunda transação de 80 reais pudesse acessar o saldo, evitando o problema de consistência. &lt;/p&gt;

&lt;p&gt;Neste cenário, a primeira transação seria bem-sucedida (reduzindo o saldo para 50 reais) e a segunda seria rejeitada por saldo insuficiente, mantendo a integridade dos dados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diferença entre Pessimistic e Optimistic Lock?
&lt;/h2&gt;

&lt;p&gt;Enquanto o lock pessimista, ou &lt;strong&gt;Pessimistic Lock&lt;/strong&gt;, realiza o lock do registro tanto para ESCRITA quanto para LEITURA, impedindo qualquer acesso ao recurso até que o processamento seja concluído. O &lt;strong&gt;Optimistic Lock&lt;/strong&gt;, ou lock otimista, realiza o lock do registro apenas para ESCRITA, mantendo a leitura liberada. Utiliza versionamento como mecanismo de validação no momento da escrita.&lt;/p&gt;

&lt;h3&gt;
  
  
  Qual o melhor modelo de lock para transações financeiras
&lt;/h3&gt;

&lt;p&gt;Para transações financeiras, o &lt;strong&gt;Pessimistic Lock&lt;/strong&gt; é geralmente considerado mais adequado devido às suas características de segurança mais rigorosas. Isso se deve a alguns fatores importantes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consistência garantida: Ao bloquear tanto leitura quanto escrita, garante-se que nenhuma operação seja realizada com dados potencialmente desatualizados&lt;/li&gt;
&lt;li&gt;Prevenção de conflitos: Elimina a possibilidade de conflitos antes que ocorram, em vez de detectá-los posteriormente&lt;/li&gt;
&lt;li&gt;Segurança em transações críticas: Em operações financeiras, onde a precisão é crucial, é preferível ter um controle mais rigoroso mesmo que isso implique em uma pequena redução de performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No entanto, é importante notar que o Pessimistic Lock pode impactar a performance do sistema devido ao maior tempo de bloqueio dos recursos. Por isso, sua implementação deve ser cuidadosamente planejada, considerando aspectos como timeout do lock e estratégias de deadlock prevention.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qual débito acontece primeiro?
&lt;/h2&gt;

&lt;p&gt;A ordem de processamento das transações em um sistema distribuído geralmente é determinada por vários fatores, incluindo o timestamp da transação, a latência da rede e a implementação específica do mecanismo de locks. &lt;/p&gt;

&lt;p&gt;Na prática, a primeira transação que conseguir adquirir o lock será processada primeiro, seguindo um princípio de "primeiro a chegar, primeiro a ser servido" (FCFS - First Come, First Served). No entanto, é importante notar que em sistemas distribuídos, nem sempre é possível garantir uma ordem totalmente determinística devido a fatores como diferenças de clock entre servidores.&lt;/p&gt;

&lt;h1&gt;
  
  
  O código em produção
&lt;/h1&gt;

&lt;p&gt;Como exemplo prático temos o &lt;a href="https://github.com/LerianStudio/midaz" rel="noopener noreferrer"&gt;Midaz, um ledger open source mantido pela Lerian&lt;/a&gt; que utiliza essa pessimist lock para garantir a integridade das transações financeiras, isso nos permite visualizar o código produtivo de como é feito esse lock que segue o mesmo princípio acima.&lt;/p&gt;

&lt;h2&gt;
  
  
  Realizando o lock do saldo
&lt;/h2&gt;

&lt;p&gt;Vimos anteriormente como operações financeiras são criadas, o processo do lock acontece uma etapa antes até mesmo da criação da transação, na validação das contas que chama o método &lt;code&gt;LockBalanceVersion&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;UseCase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;LockBalanceVersion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;organizationID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;ledgerID&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Cria um mapa de contas (usando ID ou Alias como chave) para facilitar a busca durante o processamento.&lt;/span&gt;
    &lt;span class="n"&gt;accountsMap&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;accountsMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;  &lt;span class="c"&gt;// Adiciona a conta com ID como chave&lt;/span&gt;
        &lt;span class="n"&gt;accountsMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Alias&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;  &lt;span class="c"&gt;// Adiciona a conta com Alias como chave&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Itera sobre todas as chaves para tentar bloquear a versão do saldo.&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Verifica se a chave corresponde a uma conta existente no mapa.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;accountsMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c"&gt;// Cria uma chave interna para bloquear a versão do saldo da conta no Redis.&lt;/span&gt;
            &lt;span class="n"&gt;internalKey&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;pkg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LockVersionInternalKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;organizationID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ledgerID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FormatInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

            &lt;span class="c"&gt;// Tenta configurar o bloqueio no Redis (SetNX) e define um tempo de expiração.&lt;/span&gt;
            &lt;span class="n"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;uc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RedisRepo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetNX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;internalKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TimeSetLockBalance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c"&gt;// Caso ocorra um erro, registra no telemetry e retorna o erro.&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="c"&gt;// Incrementa o contador de tentativas de bloqueio no Redis.&lt;/span&gt;
            &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;uc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RedisRepo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Incr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;internalKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c"&gt;// Se o número de tentativas exceder o limite, libera o bloqueio e retorna erro.&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RedisTimesRetry&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RedisRepo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Del&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;internalKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;// Libera o bloqueio&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="c"&gt;// Se ocorrer erro ao liberar o bloqueio, loga o erro.&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pkg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ValidateBusinessError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;constant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrLockVersionAccountBalance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"LockBalanceVersion"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="c"&gt;// Se o bloqueio não foi adquirido, espera um tempo e tenta novamente.&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;isSuccess&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;constant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LockRetry&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Retorna false, indicando que não conseguiu bloquear, sem erros.&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Removendo os locks
&lt;/h2&gt;

&lt;p&gt;Após o processamento das transações, é chamado o método &lt;code&gt;AllKeysUnlocked&lt;/code&gt; para liberar todas as keys e permitir que outras operações possam ser executadas. O Midaz implementa um sistema de liberação de locks utilizando goroutines para processar múltiplas chaves simultaneamente, melhorando a performance do sistema. Veja como isso é feito no código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;UseCase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;AllKeysUnlocked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;organizationID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ledgerID&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Cria um WaitGroup para sincronizar as goroutines.&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;

    &lt;span class="c"&gt;// Canal para receber os resultados das goroutines de verificação de bloqueios.&lt;/span&gt;
    &lt;span class="n"&gt;resultChan&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c"&gt;// Itera sobre todas as chaves fornecidas para verificar o status de bloqueio de cada uma.&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Cria uma chave interna para verificar o bloqueio no Redis.&lt;/span&gt;
        &lt;span class="n"&gt;internalKey&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;pkg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LockInternalKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;organizationID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ledgerID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c"&gt;// Incrementa o contador do WaitGroup para acompanhar a goroutine.&lt;/span&gt;
        &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c"&gt;// Inicia uma goroutine para verificar e liberar o bloqueio da chave.&lt;/span&gt;
        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;uc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;checkAndReleaseLock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;internalKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resultChan&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Espera todas as goroutines finalizarem.&lt;/span&gt;
    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Fecha o canal de resultados.&lt;/span&gt;
    &lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resultChan&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para facilitar a leitura, removi loggers e tracers e alguns outros detalhes, mas você pode analisar na íntegra o código no GitHub &lt;a href="https://github.com/LerianStudio/midaz/blob/main/components/transaction/internal/adapters/http/in/transaction.go" rel="noopener noreferrer"&gt;da criação de uma transação&lt;/a&gt; e dos &lt;a href="https://github.com/LerianStudio/midaz/blob/acc57a3fc91ebbe4d4a7492bbd4bd49d23945e78/components/transaction/internal/services/command/create-lock-race-condition.go" rel="noopener noreferrer"&gt;comandos de lock do race condition&lt;/a&gt;. Coloque nos comentários caso queria um artigo destrinchando e explicando como é feito o código de uma transação financeira por completo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;A implementação correta de mecanismos de controle de concorrência é crucial para garantir a integridade e confiabilidade das transações financeiras, esta é uma das vantagens de se utilizar um ledger para lidar com transações, pois ele já possui mecanismos nativos de controle de concorrência e locks integrados. &lt;/p&gt;

&lt;p&gt;Isso significa que ao utilizar um ledger, você não precisa se preocupar em implementar esses controles manualmente, pois a própria arquitetura do sistema garante a integridade das transações. Uma das ferramentas que implementa estes conceitos é o &lt;a href="https://github.com/LerianStudio/midaz" rel="noopener noreferrer"&gt;Midaz, um ledger open source mantido pela Lerian&lt;/a&gt;, que você pode explorar o código e utilizar em seus projetos ou na sua empresa.&lt;/p&gt;

&lt;p&gt;Você já enfrentou desafios de race conditions em seus projetos? Compartilhe suas experiências nos comentários e não se esqueça de compartilhar este artigo com outros desenvolvedores que possam se beneficiar deste conhecimento!&lt;/p&gt;

</description>
      <category>midaz</category>
      <category>opensource</category>
      <category>braziliandevs</category>
      <category>go</category>
    </item>
    <item>
      <title>Double Entry: o que é, quando usar e como fazer</title>
      <dc:creator>Jefferson Rodrigues</dc:creator>
      <pubDate>Tue, 18 Feb 2025 17:19:12 +0000</pubDate>
      <link>https://dev.to/lerian/double-entry-o-que-e-quando-usar-e-como-fazer-2594</link>
      <guid>https://dev.to/lerian/double-entry-o-que-e-quando-usar-e-como-fazer-2594</guid>
      <description>&lt;p&gt;Quem está começando a trabalhar no setor financeiro pode se deparar com esse termo "double-entry", que é um conceito fundamental para o gerenciamento de transações e registros financeiros. Neste post, quero explicar em detalhes como esse conceito funciona, quando ele deve ser utilizado e sua importância para manter a integridade das transações financeiras.&lt;/p&gt;

&lt;p&gt;A melhor maneira de explicar o que é um double-entry é com um exemplo. Então, considere que você faça uma transferência Pix de R$ 1.000 para pagar uma conta; esse processo de transferência, na verdade, realiza duas operações:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A primeira operação é a de débito de R$ 1.000 na sua conta;&lt;/li&gt;
&lt;li&gt;A segunda operação é a de crédito de R$ 1.000 na conta destino.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;É imprescindível que, para a transação seja efetuada com sucesso, ambas as operações sejam registradas corretamente. Se uma das operações falhar, todo o processo precisa ser revertido para manter a integridade da conta. Esse conceito é conhecido como double entry (entrada dupla) e é fundamental para garantir a integridade das transações financeiras.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F07m77r69vt2odlv26zzu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F07m77r69vt2odlv26zzu.png" alt="Image description" width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Importância no Setor Financeiro
&lt;/h2&gt;

&lt;p&gt;O sistema de double entry é crucial no setor financeiro por diversos motivos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Precisão contábil:&lt;/strong&gt; Garante que todas as transações financeiras sejam registradas com exatidão, reduzindo erros e discrepâncias nas contas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auditoria facilitada:&lt;/strong&gt; Permite rastrear facilmente o histórico de transações e identificar possíveis irregularidades ou fraudes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conformidade regulatória:&lt;/strong&gt; Atende aos requisitos legais e regulatórios do setor financeiro, que exigem registros precisos e transparentes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reconciliação bancária:&lt;/strong&gt; Simplifica o processo de reconciliação, permitindo a comparação eficiente entre registros internos e extratos bancários.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Aplicações além dos sistemas financeiros
&lt;/h2&gt;

&lt;p&gt;O sistema de double entry, embora tradicionalmente associado a sistemas financeiros, pode ser aplicado em outros contextos também, como em gestão de inventário e logística em que é preciso registrar a entrada e saída de produtos.&lt;/p&gt;

&lt;p&gt;Em todos esses casos, o princípio fundamental do double entry — onde cada transação afeta dois registros diferentes — ajuda a manter a integridade e rastreabilidade dos dados.&lt;/p&gt;

&lt;h1&gt;
  
  
  Como desenvolver
&lt;/h1&gt;

&lt;p&gt;Vamos criar um exemplo simples de implementação do sistema double entry em Go. Neste exemplo, vamos simular uma transferência bancária:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Account&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;      &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Balance&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Transaction&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;        &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;FromID&lt;/span&gt;    &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;ToID&lt;/span&gt;      &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Amount&lt;/span&gt;    &lt;span class="kt"&gt;float64&lt;/span&gt;
    &lt;span class="n"&gt;Timestamp&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Debit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"saldo insuficiente"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Credit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Primeira entrada: débito da conta origem&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Debit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Segunda entrada: crédito na conta destino&lt;/span&gt;
    &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Credit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Criando contas de exemplo&lt;/span&gt;
    &lt;span class="n"&gt;accountA&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="s"&gt;"conta_a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1000.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;accountB&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="s"&gt;"conta_b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;500.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Antes da transferência:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Conta A: R$%.2f&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Conta B: R$%.2f&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;accountA&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accountB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Realizando uma transferência&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accountA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accountB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;300.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Erro na transferência: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Após a transferência:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Conta A: R$%.2f&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Conta B: R$%.2f&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;accountA&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accountB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste exemplo, implementamos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uma estrutura &lt;code&gt;Account&lt;/code&gt; para representar contas com ID e saldo&lt;/li&gt;
&lt;li&gt;Uma estrutura &lt;code&gt;Transaction&lt;/code&gt; para registrar os detalhes das transações&lt;/li&gt;
&lt;li&gt;Métodos &lt;code&gt;Debit&lt;/code&gt; e &lt;code&gt;Credit&lt;/code&gt; para realizar as operações nas contas&lt;/li&gt;
&lt;li&gt;Uma função &lt;code&gt;Transfer&lt;/code&gt; que implementa o conceito de double entry, garantindo que ambas as operações sejam realizadas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Quando executado, este código demonstra uma transferência de R$ 300,00 da conta A para a conta B, mostrando os saldos antes e depois da operação. Se houver qualquer erro durante o processo (como saldo insuficiente), a transação não é completada.&lt;/p&gt;

&lt;h3&gt;
  
  
  As ditas operações
&lt;/h3&gt;

&lt;p&gt;No exemplo que vimos anteriormente, criamos duas operações fundamentais que compõem uma transação:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uma operação de débito (Debit) que remove o valor da conta de origem&lt;/li&gt;
&lt;li&gt;Uma operação de crédito (Credit) que adiciona o valor na conta de destino&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Essas operações são as unidades básicas de uma transação financeira e devem sempre ocorrer em pares para manter o princípio do double-entry. Cada operação é atômica, ou seja, ou ela acontece por completo ou não acontece, não existindo estados intermediários.&lt;/p&gt;

&lt;p&gt;No código, implementamos essas operações como métodos separados da estrutura Account, mas elas são sempre chamadas juntas através da função Transfer para garantir que o princípio do double-entry seja respeitado.&lt;/p&gt;

&lt;h3&gt;
  
  
  Encapsulamento e Segurança
&lt;/h3&gt;

&lt;p&gt;Para garantir que o saldo só possa ser alterado através da função de transação, podemos utilizar encapsulamento e tornar o campo Balance privado na estrutura Account. Veja como podemos modificar o código anterior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Account&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;      &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;  &lt;span class="c"&gt;// Note o 'b' minúsculo tornando o campo privado&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Método getter para acessar o saldo&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetBalance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Métodos de débito e crédito agora trabalham com o campo privado&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;debit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"saldo insuficiente"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;credit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com essa implementação, o campo balance só pode ser modificado através dos métodos do próprio pacote, garantindo que todas as alterações de saldo passem pelo sistema de double entry.&lt;/p&gt;

&lt;p&gt;Claro, há outras considerações importantes ao implementar um sistema de double entry, como garantir a atomicidade das transações usando um banco de dados transacional e implementar logs detalhados de todas as operações para fins de auditoria. Essas práticas ajudam a manter a integridade e rastreabilidade do sistema.&lt;/p&gt;

&lt;h1&gt;
  
  
  O código em produção
&lt;/h1&gt;

&lt;p&gt;Como exemplo prático de uma ferramenta que implementa o sistema de double entry, temos o &lt;a href="https://github.com/LerianStudio/midaz" rel="noopener noreferrer"&gt;Midaz, um ledger open source mantido pela Lerian&lt;/a&gt; que utiliza essa técnica para garantir a integridade das transações financeiras.&lt;/p&gt;

&lt;p&gt;Ao contrário de basicamente todos os sistemas financeiros brasileiros que são fechados, o Midaz nos permite examinar e discutir abertamente o uso de double entry e estudar como essa prática funciona em um ambiente de produção.&lt;/p&gt;

&lt;h3&gt;
  
  
  Como é criada uma operação
&lt;/h3&gt;

&lt;p&gt;Vamos examinar como o Midaz cria uma operação individual dentro de uma transação. Dentro da criação de uma transação, é chamado o método &lt;code&gt;CreateOperation&lt;/code&gt; que recebe os detalhes da transação e as contas envolvidas. Segue o código da criação de uma operação, comentado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;UseCase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;CreateOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;transactionID&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;dsl&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;goldModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;validate&lt;/span&gt; &lt;span class="n"&gt;goldModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Responses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Operation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c"&gt;// Declara uma lista para armazenar as operações criadas&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;operations&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Operation&lt;/span&gt;

    &lt;span class="c"&gt;// Cria uma lista `fromTo` contendo as contas de origem e destino envolvidas na transação&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fromTo&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;goldModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromTo&lt;/span&gt;
    &lt;span class="n"&gt;fromTo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fromTo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dsl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Send&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Source&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;From&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c"&gt;// Adiciona contas de origem&lt;/span&gt;
    &lt;span class="n"&gt;fromTo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fromTo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dsl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Send&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Distribute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;To&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c"&gt;// Adiciona contas de destino&lt;/span&gt;

    &lt;span class="c"&gt;// Percorre todas as contas envolvidas na transação&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Verifica se a conta está na lista `fromTo`&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;fromTo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="c"&gt;// Verifica se a conta atual está envolvida na transação, seja pelo ID ou pelo alias.&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;fromTo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;fromTo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Alias&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

                &lt;span class="c"&gt;// Define o saldo atual da conta&lt;/span&gt;
                &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;Available&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Available&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;OnHold&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnHold&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Scale&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="c"&gt;// Valida a operação e calcula os valores da transação&lt;/span&gt;
                &lt;span class="n"&gt;amt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;er&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;goldModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ValidateFromToOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fromTo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;er&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error creating operation: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;er&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="c"&gt;// Converte os valores da transação para float64 e a escala de casas decimais&lt;/span&gt;
                &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Scale&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="c"&gt;// Define o saldo da conta após a operação&lt;/span&gt;
                &lt;span class="n"&gt;ba&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Available&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;boh&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnHold&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;bs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="n"&gt;balanceAfter&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;Available&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ba&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;OnHold&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;boh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Scale&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="c"&gt;// Determina se a operação será um débito ou crédito&lt;/span&gt;
                &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;typeOperation&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;fromTo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsFrom&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;typeOperation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEBIT&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;typeOperation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CREDIT&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="c"&gt;// Cria uma nova operação com os dados processados&lt;/span&gt;
                &lt;span class="n"&gt;save&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Operation&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;              &lt;span class="n"&gt;pkg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GenerateUUIDv7&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                    &lt;span class="n"&gt;TransactionID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;transactionID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;            &lt;span class="n"&gt;typeOperation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;AssetCode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="n"&gt;dsl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Send&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Asset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;          &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Balance&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;         &lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;BalanceAfter&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;balanceAfter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;AccountID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;AccountAlias&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Alias&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="o"&gt;...&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="c"&gt;// Salva a operação no banco de dados&lt;/span&gt;
                &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;er&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;uc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OperationRepo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;er&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error creating operation: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;er&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="c"&gt;// Adiciona a operação criada à lista de operações&lt;/span&gt;
                &lt;span class="n"&gt;operations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;operations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="c"&gt;// Sai do loop para evitar múltiplas inclusões da mesma conta&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Envia a lista de operações criadas pelo canal `result`&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;operations&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para facilitar a leitura, removi loggers e tracers e alguns outros detalhes, mas você pode analisar na íntegra o código no GitHub &lt;a href="https://github.com/LerianStudio/midaz/blob/main/components/transaction/internal/adapters/http/in/transaction.go" rel="noopener noreferrer"&gt;da criação de uma transação&lt;/a&gt; e da operação. Coloque nos comentários caso queira um artigo destrinchando e explicando como é feito o código de uma transação financeira por completo.&lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>go</category>
      <category>midaz</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
