{"id":30092749,"url":"https://github.com/wallanpsantos/ms-wallet-service","last_synced_at":"2026-04-29T16:07:31.839Z","repository":{"id":307929906,"uuid":"1030044277","full_name":"wallanpsantos/ms-wallet-service","owner":"wallanpsantos","description":"Serviço de carteira digital que permite aos usuários gerenciar fundos através de operações básicas como criação de carteira, depósitos, saques e transferências. Projetado com foco em consistência de dados, rastreabilidade e resiliência utilizando padrões como Clean Architecture e Outbox Pattern.","archived":false,"fork":false,"pushed_at":"2025-08-17T23:27:39.000Z","size":221,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-18T00:19:53.230Z","etag":null,"topics":["cleanarchitecture","docker-compose","kafka","multimodule","resilience4j","rest-api","rest-assured","spring-boot"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wallanpsantos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-08-01T02:15:34.000Z","updated_at":"2025-08-17T23:27:42.000Z","dependencies_parsed_at":"2025-08-18T00:14:25.830Z","dependency_job_id":"6429ae47-7d97-48c7-9ed8-f1c7c866e439","html_url":"https://github.com/wallanpsantos/ms-wallet-service","commit_stats":null,"previous_names":["wallanpsantos/ms-wallet-service"],"tags_count":1,"template":true,"template_full_name":null,"purl":"pkg:github/wallanpsantos/ms-wallet-service","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wallanpsantos%2Fms-wallet-service","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wallanpsantos%2Fms-wallet-service/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wallanpsantos%2Fms-wallet-service/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wallanpsantos%2Fms-wallet-service/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wallanpsantos","download_url":"https://codeload.github.com/wallanpsantos/ms-wallet-service/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wallanpsantos%2Fms-wallet-service/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279012638,"owners_count":26085158,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-12T02:00:06.719Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cleanarchitecture","docker-compose","kafka","multimodule","resilience4j","rest-api","rest-assured","spring-boot"],"created_at":"2025-08-09T08:04:03.504Z","updated_at":"2025-10-12T19:12:45.649Z","avatar_url":"https://github.com/wallanpsantos.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Wallet Service - Documentação Técnica\n\n## 📋 Visão Geral\n\nO **Wallet Service** é um serviço de carteira digital que permite aos usuários gerenciar fundos através de operações básicas como criação de carteira, depósitos, saques e transferências. O sistema foi projetado com foco em **consistência de dados**, **rastreabilidade** e **resiliência** utilizando padrões como Clean Architecture e Outbox Pattern.\n\n### Funcionalidades Principais\n\n- ✅ **Criação de Carteira** - Permite criar carteiras para usuários\n- ✅ **Consulta de Saldo** - Recupera saldo atual e histórico\n- ✅ **Depósito de Fundos** - Adiciona fundos à carteira\n- ✅ **Saque de Fundos** - Remove fundos da carteira\n- ✅ **Transferência** - Move fundos entre carteiras de usuários\n- ✅ **Auditoria Completa** - Rastreamento de todas as operações via eventos\n\n---\n\n## 🏗️ Decisões de Arquitetura\n\n### Exemplo da Arquitetura do projeto - Clean Architecture Multi-Module Simplificada\n\nMais a frente na documentação terá uma melhor visão sobre a arquitetura real.\n\n![Baseline Design for Project Architecture - Clean Architecture Multi-Module Simplified.jpg](doc/others/Baseline%20Design%20for%20Project%20Architecture%20-%20Clean%20Architecture%20Multi-Module%20Simplified.jpg)\n### Clean Architecture Multi-Módulo\n\n**Por que Clean Architecture?**\n- **Separação de Responsabilidades:** Cada camada tem uma responsabilidade específica\n- **Independência de Framework:** Core isolado de dependências externas\n- **Testabilidade:** Facilita criação de testes unitários e de integração\n- **Manutenibilidade:** Mudanças em uma camada não impactam outras\n\n**Estrutura dos Módulos:**\n\n```\nwallet-service/\n├── wallet-core/          # Regras de negócio puras (domain, use cases, ports)\n├── wallet-dataprovider/  # Implementação de adapters (MongoDB, Kafka)\n├── wallet-entrypoint/    # Controllers REST e DTOs\n└── wallet-config/        # Configurações centralizadas e aplicação principal\n```\n\n### MongoDB como Banco de Dados\n\n**Por que MongoDB?**\n- ✅ **Flexibilidade de Schema:** Permite evolução dos modelos sem migrations complexas\n- ✅ **Transações ACID:** Suporte nativo a transações (essencial para transferências)\n- ✅ **Performance:** Excelente performance para reads e writes\n- ✅ **Escalabilidade Horizontal:** Facilita crescimento futuro\n- ✅ **Indexes Flexíveis:** Otimização de consultas por userId, timestamp, etc.\n\n### Apache Kafka para Eventos\n\n**Por que Kafka (ou Redpanda)?**\n- ✅ **Auditoria Completa:** Histórico imutável de todas as operações\n- ✅ **Processamento Assíncrono:** Permite funcionalidades como notificações sem impactar performance\n- ✅ **Escalabilidade:** Suporta alto volume de transações\n- ✅ **Resiliência:** Replicação e persistência de mensagens\n- ✅ **Integração:** Facilita integração com outros serviços\n\n**Observação:** O projeto suporta tanto Apache Kafka quanto Redpanda para desenvolvimento.\n\n### Outbox Pattern\n\n**Por que Outbox Pattern?**\n- ✅ **Consistência Eventual:** Garante que eventos sejam publicados mesmo se Kafka estiver indisponível\n- ✅ **Transação Única:** Dados e eventos salvos na mesma transação de banco\n- ✅ **Retry Automático:** Reprocessamento automático de eventos falhados\n- ✅ **Durabilidade:** Eventos não são perdidos em caso de falha\n\n**Implementação:**\n- `OutboxEventPublisher`: Salva eventos na collection `outbox_events`\n- `OutboxEventProcessor`: Scheduler que processa eventos pendentes\n- `KafkaEventPublisher`: Publicação direta no Kafka (fallback)\n\n---\n\n# 🌊 Fluxos por Endpoint - Wallet Service\n\n## 1. 📝 Criar Carteira - `POST /api/v1/wallets`\n\n```mermaid\ngraph TD\n   A[Cliente] --\u003e B[WalletController.createWallet]\n   B --\u003e C{Validação Request}\n   C --\u003e|Erro| D[ValidationException 400]\n   C --\u003e|OK| E[CreateWalletUseCase]\n\n   E --\u003e F[WalletRepository.findByUserId]\n   F --\u003e G{Usuário já tem carteira?}\n   G --\u003e|Sim| H[IllegalArgumentException 400]\n   G --\u003e|Não| I[Criar Wallet com saldo ZERO]\n\n   I --\u003e J[WalletRepository.save]\n   J --\u003e K[MongoDB wallets]\n   K --\u003e L[EventPublisher - WALLET_CREATED]\n   L --\u003e M[OutboxEventPublisher]\n   M --\u003e N[MongoDB outbox_events]\n\n   N --\u003e O[Kafka Async]\n   J --\u003e P[WalletResponse 201]\n   P --\u003e Q[Cliente]\n\n   classDef success fill:#c8e6c9,stroke:#4caf50\n   classDef error fill:#ffcdd2,stroke:#f44336\n   classDef process fill:#e3f2fd,stroke:#2196f3\n   classDef storage fill:#fff3e0,stroke:#ff9800\n\n   class P,Q success\n   class D,H error\n   class B,E,I,L,M process\n   class K,N,O storage\n```\n\n\n---\n\n## 2. 👤 Consultar Carteira - `GET /api/v1/wallets/{userId}`\n\n```mermaid\ngraph TD\n    A[Cliente] --\u003e B[WalletController.getWallet]\n    B --\u003e C{userId válido?}\n    C --\u003e|Não| D[ValidationException 400]\n    C --\u003e|Sim| E[GetWalletUseCase]\n    \n    E --\u003e F[WalletRepository.findByUserId]\n    F --\u003e G[MongoDB wallets]\n    G --\u003e H{Carteira encontrada?}\n    \n    H --\u003e|Não| I[IllegalArgumentException 400]\n    H --\u003e|Sim| J[WalletResponseMapper]\n    J --\u003e K[WalletResponse 200]\n    K --\u003e L[Cliente]\n    \n    classDef success fill:#c8e6c9,stroke:#4caf50\n    classDef error fill:#ffcdd2,stroke:#f44336\n    classDef process fill:#e3f2fd,stroke:#2196f3\n    classDef storage fill:#fff3e0,stroke:#ff9800\n    \n    class K,L success\n    class D,I error\n    class B,E,J process\n    class G storage\n```\n\n---\n\n## 3. 💰 Depósito - `POST /api/v1/wallets/{userId}/deposit`\n\n```mermaid\ngraph TD\n    A[Cliente] --\u003e B[WalletController.deposit]\n    B --\u003e C{Validação DepositRequest}\n    C --\u003e|Erro| D[ValidationException 400]\n    C --\u003e|OK| E[Money.of - validação valor negativo]\n    E --\u003e F[DepositUseCase]\n    \n    F --\u003e G[WalletRepository.findByUserId]\n    G --\u003e H{Carteira existe?}\n    H --\u003e|Não| I[IllegalArgumentException 400]\n    \n    H --\u003e|Sim| J[Wallet.deposit]\n    J --\u003e K{Moeda compatível?}\n    K --\u003e|Não| L[IllegalArgumentException 400]\n    K --\u003e|Sim| M[Atualizar saldo]\n    \n    M --\u003e N[WalletRepository.save]\n    N --\u003e O[WalletTransaction DEPOSIT]\n    O --\u003e P[saveTransaction]\n    P --\u003e Q[MongoDB wallets + transactions]\n    \n    Q --\u003e R[EventPublisher FUNDS_DEPOSITED]\n    R --\u003e S[OutboxEventPublisher]\n    S --\u003e T[Kafka Async]\n    \n    O --\u003e U[TransactionResponse 200]\n    U --\u003e V[Cliente]\n    \n    classDef success fill:#c8e6c9,stroke:#4caf50\n    classDef error fill:#ffcdd2,stroke:#f44336\n    classDef process fill:#e3f2fd,stroke:#2196f3\n    classDef storage fill:#fff3e0,stroke:#ff9800\n    classDef business fill:#f3e5f5,stroke:#9c27b0\n    \n    class U,V success\n    class D,I,L error\n    class B,F,E,R,S process\n    class Q,T storage\n    class J,M,O business\n```\n\n---\n\n## 4. 💸 Saque - `POST /api/v1/wallets/{userId}/withdraw`\n\n```mermaid\ngraph TD\n    A[Cliente] --\u003e B[WalletController.withdraw]\n    B --\u003e C{Validação WithdrawRequest}\n    C --\u003e|Erro| D[ValidationException 400]\n    C --\u003e|OK| E[WithdrawUseCase]\n    \n    E --\u003e F[WalletRepository.findByUserId]\n    F --\u003e G{Carteira existe?}\n    G --\u003e|Não| H[IllegalArgumentException 400]\n    \n    G --\u003e|Sim| I[Wallet.withdraw]\n    I --\u003e J{Saldo suficiente?}\n    J --\u003e|Não| K[IllegalArgumentException 400]\n    J --\u003e|Sim| L[Deduzir saldo]\n    \n    L --\u003e M[WalletRepository.save]\n    M --\u003e N[WalletTransaction WITHDRAW]\n    N --\u003e O[saveTransaction]\n    O --\u003e P[MongoDB wallets + transactions]\n    \n    P --\u003e Q[EventPublisher FUNDS_WITHDRAWN]\n    Q --\u003e R[OutboxEventPublisher]\n    R --\u003e S[Kafka Async]\n    \n    N --\u003e T[TransactionResponse 200]\n    T --\u003e U[Cliente]\n    \n    classDef success fill:#c8e6c9,stroke:#4caf50\n    classDef error fill:#ffcdd2,stroke:#f44336\n    classDef process fill:#e3f2fd,stroke:#2196f3\n    classDef storage fill:#fff3e0,stroke:#ff9800\n    classDef business fill:#f3e5f5,stroke:#9c27b0\n    \n    class T,U success\n    class D,H,K error\n    class B,E,Q,R process\n    class P,S storage\n    class I,L,N business\n```\n\n---\n\n## 5. 🔄 Transferência - `POST /api/v1/wallets/transfer`\n\n```mermaid\ngraph TD\n    A[Cliente] --\u003e B[WalletController.transfer]\n    B --\u003e C{Validação TransferRequest}\n    C --\u003e|Erro| D[ValidationException 400]\n    C --\u003e|OK| E[TransferUseCase]\n    \n    E --\u003e F{fromUserId == toUserId?}\n    F --\u003e|Sim| G[IllegalArgumentException 400]\n    F --\u003e|Não| H[Buscar carteiras origem/destino]\n    \n    H --\u003e I{Ambas existem?}\n    I --\u003e|Não| J[IllegalArgumentException 400]\n    I --\u003e|Sim| K{Moedas compatíveis?}\n    K --\u003e|Não| L[IllegalArgumentException 400]\n    \n    K --\u003e|Sim| M[MongoDB Transaction BEGIN]\n    M --\u003e N[sourceWallet.withdraw]\n    N --\u003e O{Saldo suficiente?}\n    O --\u003e|Não| P[Rollback + Exception 400]\n    \n    O --\u003e|Sim| Q[targetWallet.deposit]\n    Q --\u003e R[Save ambas carteiras]\n    R --\u003e S[Criar 2 WalletTransactions]\n    S --\u003e T[TRANSFER_OUT + TRANSFER_IN]\n    \n    T --\u003e U[EventPublisher FUNDS_TRANSFERRED]\n    U --\u003e V[MongoDB Transaction COMMIT]\n    V --\u003e W[OutboxEventPublisher]\n    W --\u003e X[Kafka Async]\n    \n    S --\u003e Y[List TransactionResponse 200]\n    Y --\u003e Z[Cliente]\n    \n    classDef success fill:#c8e6c9,stroke:#4caf50\n    classDef error fill:#ffcdd2,stroke:#f44336\n    classDef process fill:#e3f2fd,stroke:#2196f3\n    classDef storage fill:#fff3e0,stroke:#ff9800\n    classDef business fill:#f3e5f5,stroke:#9c27b0\n    classDef transaction fill:#fff9c4,stroke:#f57f17\n    \n    class Y,Z success\n    class D,G,J,L,P error\n    class B,E,H,U,W process\n    class V,X storage\n    class N,Q,S,T business\n    class M,V transaction\n```\n\n---\n\n## 6. 💰 Consultar Saldo Atual - `GET /api/v1/wallets/{userId}/balance`\n\n```mermaid\ngraph TD\n    A[Cliente] --\u003e B[WalletController.getCurrentBalance]\n    B --\u003e C[GetBalanceUseCase]\n    C --\u003e D[WalletRepository.findByUserId]\n    D --\u003e E[MongoDB wallets]\n    \n    E --\u003e F{Carteira encontrada?}\n    F --\u003e|Não| G[IllegalArgumentException 400]\n    F --\u003e|Sim| H[wallet.getBalance]\n    \n    H --\u003e I[BalanceResponseMapper]\n    I --\u003e J[BalanceResponse 200]\n    J --\u003e K[Cliente]\n    \n    classDef success fill:#c8e6c9,stroke:#4caf50\n    classDef error fill:#ffcdd2,stroke:#f44336\n    classDef process fill:#e3f2fd,stroke:#2196f3\n    classDef storage fill:#fff3e0,stroke:#ff9800\n    \n    class J,K success\n    class G error\n    class B,C,I process\n    class E storage\n```\n\n---\n\n## 7. 📊 Consultar Saldo Histórico - `GET /api/v1/wallets/{userId}/balance/historical?date=X`\n\n```mermaid\ngraph TD\n    A[Cliente] --\u003e B[WalletController.getHistoricalBalance]\n    B --\u003e C{Validação data}\n    C --\u003e|Inválida| D[ValidationException 400]\n    C --\u003e|Válida| E[GetBalanceUseCase.getHistoricalBalance]\n    \n    E --\u003e F[WalletRepository.findByUserId]\n    F --\u003e G{Carteira existe?}\n    G --\u003e|Não| H[IllegalArgumentException 400]\n    \n    G --\u003e|Sim| I[findTransactionsByWalletIdUntilTimestamp]\n    I --\u003e J[MongoDB wallet_transactions]\n    J --\u003e K[Query: timestamp \u003c= date ORDER BY timestamp]\n    \n    K --\u003e L{Transações encontradas?}\n    L --\u003e|Não| M[createZeroBalance]\n    L --\u003e|Sim| N[Última transação.balanceAfter]\n    \n    M --\u003e O[BalanceResponseMapper]\n    N --\u003e O\n    O --\u003e P[BalanceResponse 200]\n    P --\u003e Q[Cliente]\n    \n    classDef success fill:#c8e6c9,stroke:#4caf50\n    classDef error fill:#ffcdd2,stroke:#f44336\n    classDef process fill:#e3f2fd,stroke:#2196f3\n    classDef storage fill:#fff3e0,stroke:#ff9800\n    classDef business fill:#f3e5f5,stroke:#9c27b0\n    \n    class P,Q success\n    class D,H error\n    class B,E,O process\n    class J storage\n    class K,M,N business\n```\n\n---\n\n## 🎯 **Legenda dos Fluxos:**\n\n- 🟢 **Verde**: Respostas de sucesso\n- 🔴 **Vermelho**: Erros e exceções\n- 🔵 **Azul**: Processamento e controllers\n- 🟠 **Laranja**: Persistência (MongoDB/Kafka)\n- 🟣 **Roxo**: Regras de negócio importantes\n- 🟡 **Amarelo**: Transações (apenas no Transfer)\n\n## 📝 **Pontos Importantes:**\n\n1. **Validações em Camadas**: Bean Validation + Domain Validation\n2. **Event Sourcing**: Todos os fluxos com alteração geram eventos\n3. **Transactional Outbox**: Consistência eventual garantida\n4. **ACID na Transferência**: Única operação com transação explícita\n5. **Histórico Eficiente**: Query otimizada por timestamp\n---\n\n## ⚙️ Configuração e Execução\n\n### Pré-requisitos\n\n```bash\n# Ferramentas necessárias\n- Java 21+\n- Maven 3.9+\n- Docker \u0026 Docker Compose\n- Git\n```\n\n### Configuração do Ambiente\n\n1. **Clone o repositório:**\n```bash\ngit clone \u003crepository-url\u003e\ncd wallet-service\n```\n\n2. **Configure as variáveis de ambiente:**\n```bash\n# Crie o arquivo .env na raiz do projeto\ncp .env.example .env  # Se existir\n# Ou configure manualmente:\nMONGO_USER=admin\nMONGO_PASS=admin123\nMONGO_DB=wallet_db\nMONGO_PORT=27017\nKAFKA_PORT=9092\n```\n\n3. **Inicie as dependências:**\n```bash\n# Para desenvolvimento com Redpanda (mais leve)\ndocker-compose -f docker-compose.yml up -d\n\n# Ou com Kafka tradicional (se disponível)\ndocker-compose up -d\n```\n\n4. **Aguarde inicialização completa:**\n```bash\n# Verificar saúde dos serviços\ndocker-compose -f docker-compose.yml ps\ndocker-compose -f docker-compose.yml logs -f\n```\n\n### Compilação e Execução\n\n```bash\n# Compilar o projeto multi-módulo\n./mvnw clean compile\n\n# Executar testes\n./mvnw test\n\n# Executar a aplicação (módulo principal é wallet-config)\n./mvnw spring-boot:run -pl wallet-config\n\n# Ou executar com profile Docker\n./mvnw spring-boot:run -pl wallet-config -Dspring.profiles.active=docker\n```\n\n### Verificação da Saúde\n\n```bash\n# Verificar se aplicação subiu\ncurl http://localhost:8080/actuator/health\n\n# Verificar conectividade MongoDB\ndocker exec -it wallet-mongodb-dev mongosh --eval \"db.runCommand('ping')\"\n\n# Verificar Redpanda\ndocker exec -it wallet-redpanda-dev rpk cluster health\n\n# Verificar tópicos\ndocker exec -it wallet-redpanda-dev rpk topic list\n```\n\n---\n\n## 🧪 Testando as APIs\n\n### 1. Criar Carteira\n\n```bash\ncurl --location --request POST 'http://localhost:8080/api/v1/wallets' \\\n--header 'Content-Type: application/json' \\\n--data '{\n    \"userId\": \"688c2e05c0514a144d4teste\",\n    \"currency\": \"BRL\"\n}'\n\n# Resposta esperada:\n#{\n#    \"id\": \"688c334d57bd95d223b9af9c\",\n#    \"userId\": \"688c2e05c0514a144d4bd13c\",\n#    \"balance\": 0,\n#    \"currency\": \"BRL\",\n#    \"createdAt\": \"2025-08-01T00:23:57.6203075\"\n#}\n```\n\n### 2. Depositar Fundos\n\n```bash\ncurl --location --request POST 'http://localhost:8080/api/v1/wallets/688c2e05c0514a144d4bd13c/deposit' \\\n--header 'Content-Type: application/json' \\\n--data '{\n    \"amount\": 200.50,\n    \"currency\": \"BRL\"\n}'\n\n# Resposta: TransactionResponse com detalhes da transação\n#{\n#    \"id\": \"c942674d-06af-4d71-aa98-3a63ef9faaa1\",\n#    \"walletId\": \"688c334d57bd95d223b9af9c\",\n#    \"type\": \"DEPOSIT\",\n#    \"amount\": 200.5,\n#    \"currency\": \"BRL\",\n#    \"balanceAfter\": 200.5,\n#    \"timestamp\": \"2025-08-01T00:24:33.3230074\",\n#    \"correlationId\": \"deea4840-6aae-4d2a-a530-1a0476260954\"\n#}\n```\n\n### 3. Consultar Carteira\n\n```bash\ncurl --location --request GET 'http://localhost:8080/api/v1/wallets/688c2e05c0514a144d4bd13c/balance'\n\n# Retorna WalletResponse com saldo atual\n#{\n#    \"userId\": \"688c2e05c0514a144d4bd13c\",\n#    \"balance\": 200.5,\n#    \"currency\": \"BRL\",\n#    \"timestamp\": \"2025-08-01T00:24:52.2017933\"\n#}\n```\n\n### 4. Consultar Saldo Atual\n\n```bash\ncurl --location --request POST 'http://localhost:8080/api/v1/wallets' \\\n--header 'Content-Type: application/json' \\\n--data '{\n    \"userId\": \"000022e05c0514a144d400002\",\n    \"currency\": \"BRL\"\n}'\n\n# Retorna BalanceResponse com saldo e timestamp\n#{\n#    \"id\": \"688c339457bd95d223b9af9d\",\n#    \"userId\": \"000022e05c0514a144d400002\",\n#    \"balance\": 0,\n#    \"currency\": \"BRL\",\n#    \"createdAt\": \"2025-08-01T00:25:08.1199087\"\n#}\n```\n\n### 5. Transferir Fundos\n\n```bash\n# Primeiro criar segunda carteira\ncurl --location --request POST 'http://localhost:8080/api/v1/wallets' \\\n--header 'Content-Type: application/json' \\\n--data '{\n    \"userId\": \"000022e05c0514a144d400002\",\n    \"currency\": \"BRL\"\n}'\n\n# Retorno segunda carteira\n#{\n#    \"id\": \"688c339457bd95d223b9af9d\",\n#    \"userId\": \"000022e05c0514a144d400002\",\n#    \"balance\": 0,\n#    \"currency\": \"BRL\",\n#    \"createdAt\": \"2025-08-01T00:25:08.1199087\"\n#}\n\n\n# Depois transferir\ncurl --location --request POST 'http://localhost:8080/api/v1/wallets/transfer' \\\n--header 'Content-Type: application/json' \\\n--data '{\n    \"fromUserId\": \"688c2e05c0514a144d4bd13c\", \n    \"toUserId\": \"000022e05c0514a144d400002\",\n    \"amount\": 50.00,\n    \"currency\": \"BRL\"\n}'\n\n# Retorna lista com 2 TransactionResponse (OUT e IN)\n#[\n#    {\n#        \"id\": \"a75ed55b-904e-46e2-883f-b0e313741c61\",\n#        \"walletId\": \"688c334d57bd95d223b9af9c\",\n#        \"type\": \"TRANSFER_OUT\",\n#        \"amount\": 50,\n#        \"currency\": \"BRL\",\n#        \"balanceAfter\": 150.5,\n#        \"timestamp\": \"2025-08-01T00:25:30.9426638\",\n#        \"correlationId\": \"c422b3ab-2204-4a61-a688-2c668917e160\"\n#    },\n#    {\n#        \"id\": \"b2e1655a-6afd-47b8-9a89-601b05d1334e\",\n#        \"walletId\": \"688c339457bd95d223b9af9d\",\n#        \"type\": \"TRANSFER_IN\",\n#        \"amount\": 50,\n#        \"currency\": \"BRL\",\n#        \"balanceAfter\": 50,\n#        \"timestamp\": \"2025-08-01T00:25:30.9461698\",\n#        \"correlationId\": \"c422b3ab-2204-4a61-a688-2c668917e160\"\n#    }\n#]\n```\n\n### 6. Consultar Saldo Histórico\n\n```bash\ncurl --location --request GET 'http://localhost:8080/api/v1/wallets/688c2e05c0514a144d4bd13c/balance/historical?date=2025-08-01'\n\n# Retorna saldo no final do dia especificado para carteira 688c2e05c0514a144d4bd13c\n#[\n#    {\n#        \"userId\": \"688c2e05c0514a144d4bd13c\",\n#        \"balance\": 150.5,\n#        \"currency\": \"BRL\",\n#        \"timestamp\": \"2025-08-01T00:26:46.2724831\"\n#    }\n#]\n```\n\n---\n\n## 🔍 Monitoramento e Observabilidade\n\n### Logs Estruturados\n\nA aplicação gera logs estruturados com diferentes níveis:\n\n```json\n{\n  \"timestamp\": \"2024-01-01T10:00:00.000\",\n  \"level\": \"INFO\", \n  \"logger\": \"com.br.walletcore.usecase.TransferUseCase\",\n  \"message\": \"Processing transfer from: user123 to: user456, amount: 25.00\",\n  \"correlationId\": \"abc-123-def\"\n}\n```\n\n### Eventos Kafka\n\nTodos os eventos são publicados no tópico `wallet-events`:\n\n```json\n{\n   \"eventId\": \"53aea7a2-f59a-420b-8a7a-20dbea06dad8\",\n   \"eventType\": \"WALLET_CREATED\",\n   \"aggregateId\": \"688c31564e4543aca62c18d0\",\n   \"payload\": {\n      \"currency\": \"BRL\",\n      \"timestamp\": \"2025-08-01T00:15:34.679578700\",\n      \"userId\": \"688c2e05c0514a144d4bd13c\",\n      \"walletId\": \"688c31564e4543aca62c18d0\"\n   },\n   \"createdAt\": \"2025-08-01T00:15:34.727141200\",\n   \"correlationId\": \"correlation-id-value\"\n}\n```\n\n### Ferramentas de Monitoramento Disponíveis\n\n**Redpanda Console:** http://localhost:8090\n- Visualização de tópicos e mensagens\n- Monitoramento de consumers\n- Métricas de performance\n\n**Mongo Express:** http://localhost:8081\n- Interface web para MongoDB\n- Visualização de collections\n- Execução de queries\n\n**Actuator Endpoints:**\n- `/actuator/health` - Status da aplicação\n- `/actuator/metrics` - Métricas da aplicação\n- `/actuator/info` - Informações da build\n\n### Verificando Processamento de Eventos\n\n```bash\n# Verificar eventos na Outbox\ndocker exec -it wallet-mongodb-dev mongosh wallet_db \\\n  --eval \"db.outbox_events.find().limit(5).pretty()\"\n\n# Verificar mensagens no Redpanda\ndocker exec -it wallet-redpanda-dev rpk topic consume wallet-events --num 5\n\n# Verificar se scheduler está processando\ndocker-compose -f docker-compose.yml logs wallet-service | grep \"Processing outbox\"\n```\n\n---\n\n## 🚨 Tratamento de Erros\n\n### Cenários de Erro Comuns\n\n| Erro HTTP 400 | Causa | Validação |\n|---------------|-------|-----------|\n| `User already has a wallet` | Tentativa de criar carteira duplicada | `CreateWalletUseCase` |\n| `Wallet not found for user: X` | UserId não possui carteira | Todos os use cases |\n| `Insufficient funds` | Saldo insuficiente para saque/transferência | `Money.subtract()` |  \n| `Currency mismatch` | Moedas incompatíveis | `Money.validateSameCurrency()` |\n| `Amount must be positive` | Valor negativo ou zero | `Wallet.validateAmount()` |\n| `Cannot transfer to same user` | Transfer para mesmo usuário | `TransferUseCase` |\n\n### Resposta Padrão de Erro\n\n```json\n{\n  \"status\": \"Bad Request\",\n  \"statusCode\": 400,\n  \"title\": \"Business Rule Violation\",\n  \"message\": \"Insufficient funds\",\n  \"timestamp\": \"2024-01-01 10:00:00\",\n  \"details\": [\n    {\n      \"field\": \"businessRule\",\n      \"message\": \"Insufficient funds\"\n    }\n  ]\n}\n```\n\n### Resiliência do Sistema\n\n**Falha do Kafka/Redpanda:**\n- Eventos ficam na Outbox MongoDB\n- `OutboxEventProcessor` reprocessa automaticamente quando serviço volta\n- Aplicação continua funcionando normalmente\n- Configuração: `wallet.outbox.scheduler.enabled=true`\n\n**Falha do MongoDB:**\n- Aplicação falha (by design - não pode funcionar sem dados)\n- Health check indica status DOWN\n- Container restart automático via Docker\n\n**Falha no Consumer:**\n- Mensagens não confirmadas são reprocessadas\n- Acknowledgment manual: `ack-mode: manual_immediate`\n- Retry configurado no `OutboxEventProcessor`\n\n---\n\n## 📊 Performance e Escalabilidade\n\n### Configurações Importantes\n\n```yaml\n# Configurações no application.yml\nwallet:\n  outbox:\n    batch-size: 100        # Eventos processados por batch\n    scheduler:\n      fixed-delay: 5000    # Intervalo do scheduler (ms)\n      initial-delay: 10000 # Tempo inicial para Kafka subir\n    max-retries: 3         # Tentativas máximas por evento\n\nspring:\n  kafka:\n    consumer:\n      max-poll-records: 10 # Controle de batch size\n    producer:\n      batch-size: 16384    # Otimização de throughput\n      linger-ms: 5         # Latência vs throughput\n      compression-type: snappy # Compressão\n```\n\n### Índices MongoDB\n\nO script `init-mongo.js` cria índices otimizados:\n\n```javascript\n// Wallets\ndb.wallets.createIndex({\"userId\": 1}, {unique: true});\ndb.wallets.createIndex({\"createdAt\": 1});\ndb.wallets.createIndex({\"updatedAt\": 1});\n\n// Transactions\ndb.wallet_transactions.createIndex({\"walletId\": 1});\ndb.wallet_transactions.createIndex({\"timestamp\": 1});\ndb.wallet_transactions.createIndex({\"correlationId\": 1});\ndb.wallet_transactions.createIndex({\"walletId\": 1, \"timestamp\": 1});\n\n// Outbox Events\ndb.outbox_events.createIndex({\"processed\": 1});\ndb.outbox_events.createIndex({\"createdAt\": 1});\ndb.outbox_events.createIndex({\"aggregateId\": 1});\n```\n\n### Métricas para Monitorar\n\n- **Latência das APIs** (p95, p99) - via Actuator metrics\n- **Throughput de transações** (TPS) - logs de use cases\n- **Lag do Consumer** - Redpanda Console\n- **Tamanho da Outbox** (eventos pendentes) - query MongoDB\n- **Taxa de erro** nas operações - logs de erro\n- **Conexões MongoDB** (pool) - health checks\n\n---\n\n## 🔧 Troubleshooting\n\n### Problemas Comuns\n\n**Aplicação não inicia:**\n```bash\n# Verificar se dependências estão rodando\ndocker-compose -f docker-compose.yml ps\n\n# Verificar logs da aplicação\n./mvnw spring-boot:run -pl wallet-config | grep ERROR\n\n# Verificar conectividade MongoDB\ndocker exec -it wallet-mongodb-dev mongosh --eval \"db.runCommand('ping')\"\n\n# Verificar conectividade Redpanda\ndocker exec -it wallet-redpanda-dev rpk cluster health\n```\n\n**Eventos não processados:**\n```bash\n# Verificar se scheduler está habilitado\ngrep -r \"wallet.outbox.scheduler.enabled\" wallet-config/src/main/resources/\n\n# Verificar eventos pendentes na Outbox\ndocker exec -it wallet-mongodb-dev mongosh wallet_db \\\n  --eval \"db.outbox_events.find({processed: false}).count()\"\n\n# Verificar logs do scheduler\ndocker-compose -f docker-compose.yml logs | grep \"OutboxEventProcessor\"\n```\n\n**Consumer não processa mensagens:**\n```bash\n# Verificar consumer group no Redpanda\ndocker exec -it wallet-redpanda-dev rpk group list\n\n# Verificar lag do consumer\ndocker exec -it wallet-redpanda-dev rpk group describe wallet-audit-consumer\n\n# Verificar logs do consumer\ndocker-compose -f docker-compose.yml logs | grep \"WalletEventConsumer\"\n```\n\n**Erro de transação MongoDB:**\n```bash\n# Verificar se MongoDB está configurado para replica set\ndocker exec -it wallet-mongodb-dev mongosh \\\n  --eval \"rs.status()\" || echo \"Replica set not configured\"\n\n# Verificar configuração de transação\ngrep -r \"EnableTransactionManagement\" wallet-config/\n```\n\n---\n\n## 🐳 Docker e Containerização\n\n### Dockerfile Multi-stage\n\nO projeto usa um Dockerfile otimizado com duas etapas:\n\n1. **Builder Stage**: Compila a aplicação Maven\n2. **Runtime Stage**: Executa apenas o JAR com JRE\n\n**Características:**\n- Usa imagem `eclipse-temurin:21-jre-alpine` (menor footprint)\n- Usuário não-root para segurança\n- Health check integrado\n- Otimizações JVM para containers\n\n### Docker Compose Environments\n\n**docker-compose.dev.yml**: Ambiente de desenvolvimento\n- Redpanda (mais leve que Kafka)\n- MongoDB com inicialização automática\n- Redpanda Console (UI)\n- Mongo Express (UI)\n- Volumes persistentes para desenvolvimento\n\n**Principais Serviços:**\n- `redpanda`: Message broker compatível com Kafka\n- `mongodb`: Banco de dados principal\n- `redpanda-console`: Interface web para tópicos\n- `mongo-express`: Interface web para MongoDB\n\n### Configurações Docker\n\n```yaml\n# Exemplo de configuração para produção\nservices:\n  wallet-service:\n    build: .\n    environment:\n      SPRING_PROFILES_ACTIVE: docker\n      MONGO_URL: mongodb://mongodb:27017/wallet_db\n      KAFKA_BOOTSTRAP_SERVERS: redpanda:29092\n    depends_on:\n      - mongodb\n      - redpanda\n    healthcheck:\n      test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:8080/actuator/health\"]\n      interval: 30s\n      timeout: 10s\n      retries: 3\n```\n\n---\n\n## 🚀 Próximos Passos\n\n### Melhorias Implementadas\n\n1. **Outbox Pattern**: ✅ Implementado com scheduler automático\n2. **Clean Architecture**: ✅ Separação clara de responsabilidades em módulos\n3. **Transações ACID**: ✅ MongoDB com suporte completo a transações\n4. **Event Sourcing**: ✅ Histórico completo via transações e eventos\n5. **Health Checks**: ✅ Actuator com MongoDB e Kafka health\n6. **Containerização**: ✅ Docker multi-stage otimizado\n\n### Melhorias Futuras\n\n1. **Segurança:**\n   - Implementar autenticação JWT\n   - Rate limiting por usuário\n   - Validações de compliance (AML/KYC)\n   - Criptografia de dados sensíveis\n\n2. **Observabilidade:**\n   - Métricas com Micrometer/Prometheus\n   - Distributed tracing com Jaeger/Zipkin\n   - Dashboards com Grafana\n   - Alertas proativos\n\n3. **Performance:**\n   - Cache Redis para consultas frequentes\n   - Read replicas para MongoDB\n   - Particionamento inteligente no Kafka\n   - Connection pooling otimizado\n\n4. **Funcionalidades:**\n   - Suporte a múltiplas moedas com conversão\n   - Limites de transação configuráveis\n   - Análise de fraude em tempo real\n   - Notificações push/email\n   - API de relatórios e analytics\n\n5. **DevOps:**\n   - Pipeline CI/CD com GitHub Actions\n   - Testes de integração automatizados\n   - Deploy automático em Kubernetes\n   - Backup automatizado MongoDB\n\n### Considerações de Produção\n\n- **Backup:** Implementar estratégia de backup automatizado MongoDB\n- **Security:** HTTPS, WAF, validação rigorosa de entrada\n- **Monitoring:** APM (New Relic/Datadog), alertas por SLA\n- **Scalability:** Auto-scaling baseado em métricas de CPU/memória\n- **Disaster Recovery:** Replicação cross-region, RTO/RPO definidos\n\n---\n\n## 📚 Referências Técnicas\n\n### Estrutura de Módulos\n\n**wallet-core**: Lógica de domínio pura\n- `Money.java` - Value object para valores monetários com validações\n- `Wallet.java` - Entidade principal com regras de negócio (deposit/withdraw)\n- `WalletTransaction.java` - Histórico de transações\n- Use cases: `CreateWalletUseCase`, `TransferUseCase`, etc.\n\n**wallet-dataprovider**: Adapters de infraestrutura\n- MongoDB repositories e mappers\n- Kafka publishers e consumers\n- Outbox pattern implementation\n\n**wallet-entrypoint**: Interface REST\n- Controllers REST com validação\n- DTOs de request/response\n- Exception handlers globais\n\n**wallet-config**: Configuração e bootstrap\n- Configuração Spring Boot principal\n- Beans de configuração (Kafka, MongoDB, Use Cases)\n- Profiles para diferentes ambientes\n\n### Configurações Importantes\n\n- `application.yml` - Configuração para desenvolvimento local\n- `application-docker.yml` - Configuração para containers\n- `MongoConfig.java` - Configuração de transações MongoDB\n- `KafkaConfig.java` - Criação automática de tópicos\n- `UseCaseConfig.java` - Injeção de dependências dos use cases\n\n### Pontos de Atenção\n\n1. **Transações MongoDB**: Requer replica set mesmo em desenvolvimento\n2. **Outbox Scheduler**: Configuração de delay adequada para ambiente\n3. **Kafka/Redpanda**: Diferentes configurações de conexão\n4. **Mapeamento**: MapStruct para conversão entre layers\n5. **Validações**: Bean Validation nas DTOs de entrada\n\nEsta documentação reflete a implementação atual do projeto e serve como guia completo para desenvolvedores que precisam entender, executar ou contribuir com o sistema.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwallanpsantos%2Fms-wallet-service","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwallanpsantos%2Fms-wallet-service","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwallanpsantos%2Fms-wallet-service/lists"}