feat: otimização de performance e ajustes finais
This commit is contained in:
@@ -0,0 +1,556 @@
|
||||
# 🔍 Análise Técnica Profunda - Módulo de Orçamento
|
||||
|
||||
**Data:** 2025-01-XX
|
||||
**Analista:** Auto (IA Assistant)
|
||||
**Módulo:** `sigefp-budget`
|
||||
**Implementado por:** Antigravity/Deepmind
|
||||
|
||||
---
|
||||
|
||||
## 📊 Resumo Executivo
|
||||
|
||||
### Status Geral: **85% Excelente | 15% Melhorias Necessárias**
|
||||
|
||||
O módulo de Orçamento implementado pelo Antigravity demonstra **arquitetura sólida** e **otimizações de performance** bem pensadas. No entanto, existem **2 problemas críticos** que **DEVEM ser corrigidos antes de produção** para garantir conformidade total com padrões GFP/SIGFIP e robustez operacional.
|
||||
|
||||
### ⚠️ Problemas Críticos Encontrados
|
||||
|
||||
1. **🔴 CRÍTICO:** `@Formula` de `totalCommitted` soma TODOS os tipos de movimento (COMMITMENT + LIQUIDATION + PAYMENT), quando deveria somar apenas COMMITMENT. Isso causa **cálculo incorreto de saldos disponíveis**.
|
||||
|
||||
2. **🔴 CRÍTICO:** Falta validação de sequência obrigatória: COMMITMENT → LIQUIDATION → PAYMENT. Permite criar LIQUIDATION sem COMMITMENT e PAYMENT sem LIQUIDATION, **quebrando conformidade GFP**.
|
||||
|
||||
### ✅ Pontos Fortes
|
||||
|
||||
- Otimizações de performance excelentes (@Formula, COUNT queries)
|
||||
- Validação de saldo insuficiente para COMMITMENT
|
||||
- Validação de ano fiscal fechado
|
||||
- Testes unitários implementados
|
||||
- Arquitetura de integração bem estruturada
|
||||
|
||||
---
|
||||
|
||||
## ✅ Pontos Fortes (Excelente Implementação)
|
||||
|
||||
### 1. **Otimização de Performance com @Formula** ⭐⭐⭐⭐⭐
|
||||
|
||||
**Implementação:**
|
||||
```java
|
||||
@org.hibernate.annotations.Formula("(SELECT COALESCE(SUM(be.amount), 0) FROM budget_entry be WHERE be.budget_line_id = id)")
|
||||
private BigDecimal totalAllocated;
|
||||
|
||||
@org.hibernate.annotations.Formula("(SELECT COALESCE(SUM(bex.amount), 0) FROM budget_execution bex WHERE bex.budget_line_id = id)")
|
||||
private BigDecimal totalCommitted;
|
||||
```
|
||||
|
||||
**Análise:**
|
||||
- ✅ **Excelente** uso de `@Formula` para evitar N+1 queries
|
||||
- ✅ Cálculo dinâmico no banco de dados
|
||||
- ✅ Reduz carga de memória (não carrega todas as entradas relacionadas)
|
||||
- ✅ Performance otimizada para listagens grandes
|
||||
|
||||
**Impacto:** Alto - Permite listar milhares de linhas orçamentárias sem problemas de performance.
|
||||
|
||||
---
|
||||
|
||||
### 2. **Validação de Fechamento com COUNT** ⭐⭐⭐⭐⭐
|
||||
|
||||
**Implementação:**
|
||||
```java
|
||||
long pendingCommitments = budgetExecutionRepository.countByFiscalYearIdAndMovementType(id, "COMMITMENT");
|
||||
if (pendingCommitments > 0) {
|
||||
throw new IllegalArgumentException("Não é possível fechar o ano fiscal: existem movimentos em aberto");
|
||||
}
|
||||
```
|
||||
|
||||
**Análise:**
|
||||
- ✅ **Excelente** uso de `COUNT` em vez de carregar lista completa
|
||||
- ✅ Previne OutOfMemoryError em anos fiscais com muitos registros
|
||||
- ✅ Validação eficiente e performática
|
||||
|
||||
**Impacto:** Crítico - Evita crashes do sistema ao fechar anos fiscais grandes.
|
||||
|
||||
---
|
||||
|
||||
### 3. **Validação de Saldo Insuficiente** ⭐⭐⭐⭐
|
||||
|
||||
**Implementação:**
|
||||
```java
|
||||
if ("COMMITMENT".equals(dto.getMovementType())) {
|
||||
BigDecimal totalAllocated = budgetAllocationRepository.calculateTotalAllocatedByBudgetLineId(budgetLine.getId());
|
||||
BigDecimal totalCommitted = budgetExecutionRepository.calculateTotalCommittedByBudgetLineId(budgetLine.getId());
|
||||
BigDecimal available = totalAllocated.subtract(totalCommitted);
|
||||
|
||||
if (dto.getAmount().compareTo(available) > 0) {
|
||||
throw new InsufficientBudgetException(...);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Análise:**
|
||||
- ✅ Validação rigorosa de saldo antes de criar COMMITMENT
|
||||
- ✅ Uso de exceção customizada (`InsufficientBudgetException`)
|
||||
- ✅ Mensagem clara com valores disponíveis vs. solicitados
|
||||
|
||||
**Impacto:** Alto - Garante integridade orçamentária.
|
||||
|
||||
---
|
||||
|
||||
### 4. **Validação de Ano Fiscal Fechado** ⭐⭐⭐⭐
|
||||
|
||||
**Implementação:**
|
||||
```java
|
||||
if ("CLOSED".equals(budgetLine.getFiscalYear().getStatus())) {
|
||||
throw new BusinessException("Não é possível registrar movimentos em um ano fiscal fechado",
|
||||
"FISCAL_YEAR_CLOSED", HttpStatus.CONFLICT);
|
||||
}
|
||||
```
|
||||
|
||||
**Análise:**
|
||||
- ✅ Bloqueia movimentações em anos fiscais fechados
|
||||
- ✅ Uso de exceção customizada com código de erro
|
||||
- ✅ HTTP status apropriado (409 CONFLICT)
|
||||
|
||||
**Impacto:** Alto - Garante integridade temporal.
|
||||
|
||||
---
|
||||
|
||||
### 5. **Testes Unitários Implementados** ⭐⭐⭐⭐
|
||||
|
||||
**Testes Encontrados:**
|
||||
- ✅ `BudgetLineServiceTest` - Valida uso de @Formula
|
||||
- ✅ `BudgetExecutionServiceTest` - Valida bloqueio de saldo insuficiente e ano fechado
|
||||
- ✅ `FiscalYearServiceTest` - Valida uso de COUNT query
|
||||
|
||||
**Análise:**
|
||||
- ✅ Cobertura dos cenários críticos
|
||||
- ✅ Uso de Mockito para isolamento
|
||||
- ✅ Testes bem estruturados e legíveis
|
||||
|
||||
**Impacto:** Médio - Garante que regras de negócio críticas funcionam.
|
||||
|
||||
---
|
||||
|
||||
### 6. **Arquitetura de Integração** ⭐⭐⭐⭐
|
||||
|
||||
**Implementação:**
|
||||
```java
|
||||
public void createCommitmentFromPayrollItem(UUID budgetLineId, Long periodId, BigDecimal amount, UUID referenceId)
|
||||
public void createPaymentFromTreasury(UUID budgetLineId, Long periodId, BigDecimal amount, UUID referenceId)
|
||||
public void createLiquidationFromPayrollItem(UUID budgetLineId, Long periodId, BigDecimal amount, UUID referenceId)
|
||||
```
|
||||
|
||||
**Análise:**
|
||||
- ✅ Serviço dedicado para integração (`BudgetIntegrationService`)
|
||||
- ✅ Exige `referenceId` para rastreabilidade
|
||||
- ✅ Separação clara de responsabilidades
|
||||
|
||||
**Impacto:** Alto - Facilita integração com outros módulos.
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Problemas Críticos Identificados
|
||||
|
||||
### 1. **🔴 CRÍTICO: Cálculo Incorreto de totalCommitted**
|
||||
|
||||
**Problema:**
|
||||
```java
|
||||
// BudgetLine.java - Linha 49
|
||||
@org.hibernate.annotations.Formula("(SELECT COALESCE(SUM(bex.amount), 0) FROM budget_execution bex WHERE bex.budget_line_id = id)")
|
||||
private BigDecimal totalCommitted;
|
||||
```
|
||||
|
||||
**Análise:**
|
||||
- ❌ **Soma TODOS os tipos de movimento** (COMMITMENT, LIQUIDATION, PAYMENT)
|
||||
- ❌ **Deveria somar apenas COMMITMENT** para calcular saldo disponível
|
||||
- ❌ **Causa cálculo incorreto** de `availableBalance = totalAllocated - totalCommitted`
|
||||
|
||||
**Impacto:** **CRÍTICO** - Saldos disponíveis estarão incorretos, permitindo compromissos além do disponível.
|
||||
|
||||
**Correção Necessária:**
|
||||
```java
|
||||
@org.hibernate.annotations.Formula("(SELECT COALESCE(SUM(bex.amount), 0) FROM budget_execution bex WHERE bex.budget_line_id = id AND bex.movement_type = 'COMMITMENT')")
|
||||
private BigDecimal totalCommitted;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. **🔴 CRÍTICO: Falta Validação de Sequência de Movimentos**
|
||||
|
||||
**Arquivo:** `sigefp-budget/src/main/java/br/gov/sigefp/budget/service/BudgetExecutionService.java`
|
||||
|
||||
**Problema:**
|
||||
- ❌ Não valida se existe COMMITMENT antes de criar LIQUIDATION
|
||||
- ❌ Não valida se existe LIQUIDATION antes de criar PAYMENT
|
||||
- ❌ Permite criar PAYMENT sem COMMITMENT/LIQUIDATION
|
||||
- ❌ Não valida se LIQUIDATION não excede COMMITMENT correspondente
|
||||
- ❌ Não valida se PAYMENT não excede LIQUIDATION correspondente
|
||||
|
||||
**Análise:**
|
||||
- Em sistemas GFP, a sequência **DEVE** ser: COMMITMENT → LIQUIDATION → PAYMENT
|
||||
- Criar PAYMENT sem COMMITMENT quebra a integridade contábil
|
||||
- Permite "pular" etapas do ciclo de execução
|
||||
- **Violação grave** de normas de execução orçamentária
|
||||
|
||||
**Cenário de Falha:**
|
||||
```
|
||||
1. Criar PAYMENT de 1.000 XOF sem COMMITMENT ❌ (deveria falhar)
|
||||
2. Criar LIQUIDATION de 1.000 XOF sem COMMITMENT ❌ (deveria falhar)
|
||||
3. Criar PAYMENT de 2.000 XOF quando LIQUIDATION é 1.000 ❌ (deveria falhar)
|
||||
```
|
||||
|
||||
**Impacto:** **CRÍTICO** - Quebra conformidade com normas de execução orçamentária e permite inconsistências contábeis.
|
||||
|
||||
**Correção Necessária:**
|
||||
Ver arquivo `CORRECOES_CRITICAS_ORCAMENTO.md` para código completo.
|
||||
|
||||
---
|
||||
|
||||
### 3. **🟡 MÉDIO: Tratamento de Exceções Inconsistente**
|
||||
|
||||
**Problema 1: BudgetEntryService**
|
||||
```java
|
||||
.orElseThrow(() -> new IllegalArgumentException("Linha orçamentária não encontrada: " + dto.getBudgetLineId()));
|
||||
```
|
||||
|
||||
**Problema 2: BudgetEntryController**
|
||||
```java
|
||||
catch (IllegalArgumentException e) {
|
||||
return ResponseEntity.badRequest().build(); // ❌ Sem mensagem de erro
|
||||
}
|
||||
```
|
||||
|
||||
**Análise:**
|
||||
- ❌ Uso de `IllegalArgumentException` genérico em vez de exceções customizadas
|
||||
- ❌ Controller não retorna mensagem de erro ao cliente
|
||||
- ❌ Dificulta debugging e tratamento de erros no frontend
|
||||
|
||||
**Impacto:** Médio - Degrada experiência do usuário e debugging.
|
||||
|
||||
**Correção Necessária:**
|
||||
```java
|
||||
// Service
|
||||
.orElseThrow(() -> new ResourceNotFoundException("Linha orçamentária não encontrada: " + dto.getBudgetLineId()));
|
||||
|
||||
// Controller
|
||||
catch (ResourceNotFoundException e) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
||||
.body(new ErrorResponse("RESOURCE_NOT_FOUND", e.getMessage()));
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. **🟡 MÉDIO: BudgetIntegrationService com RuntimeException**
|
||||
|
||||
**Problema:**
|
||||
```java
|
||||
catch (Exception e) {
|
||||
log.error("Erro ao criar execução orçamentária (COMMITMENT): {}", e.getMessage());
|
||||
throw new RuntimeException("Erro ao criar execução orçamentária: " + e.getMessage(), e);
|
||||
}
|
||||
```
|
||||
|
||||
**Análise:**
|
||||
- ❌ Uso de `RuntimeException` genérico
|
||||
- ❌ Perde informações específicas do erro original
|
||||
- ❌ Dificulta tratamento adequado no frontend
|
||||
|
||||
**Impacto:** Médio - Dificulta tratamento de erros específicos.
|
||||
|
||||
**Correção Necessária:**
|
||||
```java
|
||||
catch (InsufficientBudgetException e) {
|
||||
log.error("Saldo insuficiente ao criar execução orçamentária", e);
|
||||
throw e; // Re-throw exceção específica
|
||||
}
|
||||
catch (BusinessException e) {
|
||||
log.error("Erro de negócio ao criar execução orçamentária", e);
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("Erro inesperado ao criar execução orçamentária", e);
|
||||
throw new BusinessException("Erro ao criar execução orçamentária", "EXECUTION_ERROR", HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5. **🟢 BAIXO: Validação de Valores Negativos (Já Implementada no DTO)**
|
||||
|
||||
**Status:** ✅ **Já implementado no DTO**
|
||||
|
||||
**Análise:**
|
||||
- ✅ `CreateBudgetEntryDTO` tem `@DecimalMin(value = "0.01")` (linha 22)
|
||||
- ✅ `BudgetExecutionDTO` tem `@Positive` (linha 37)
|
||||
- ✅ Validação ocorre automaticamente via Bean Validation
|
||||
|
||||
**Impacto:** Nenhum - Já está correto.
|
||||
|
||||
**Nota:** Não é necessário adicionar validação adicional no Service.
|
||||
|
||||
---
|
||||
|
||||
### 6. **🟡 MÉDIO: Falta Validação de Datas**
|
||||
|
||||
**Arquivo:** `sigefp-budget/src/main/java/br/gov/sigefp/budget/service/BudgetEntryService.java`
|
||||
|
||||
**Problema:**
|
||||
- ❌ `BudgetEntry.transactionDate` não é validado contra `FiscalYear.startDate` e `endDate`
|
||||
- ❌ Permite criar entradas com datas fora do exercício fiscal
|
||||
- ❌ Pode criar inconsistências temporais
|
||||
|
||||
**Análise:**
|
||||
- Transações devem estar dentro do período do exercício fiscal
|
||||
- Validação importante para integridade temporal
|
||||
- Em alguns casos, pode ser aceitável (ex: ajustes retroativos), mas deve ser controlado
|
||||
|
||||
**Impacto:** Médio - Pode causar inconsistências temporais.
|
||||
|
||||
**Correção Necessária:**
|
||||
```java
|
||||
// Adicionar após linha 33 (após buscar budgetLine)
|
||||
if (dto.getTransactionDate().isBefore(budgetLine.getFiscalYear().getStartDate()) ||
|
||||
dto.getTransactionDate().isAfter(budgetLine.getFiscalYear().getEndDate())) {
|
||||
throw new BusinessException(
|
||||
String.format("Data da transação (%s) deve estar dentro do exercício fiscal (%s a %s)",
|
||||
dto.getTransactionDate(),
|
||||
budgetLine.getFiscalYear().getStartDate(),
|
||||
budgetLine.getFiscalYear().getEndDate()),
|
||||
"INVALID_TRANSACTION_DATE", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 7. **🟢 BAIXO: Falta Validação de Imutabilidade**
|
||||
|
||||
**Problema:**
|
||||
- ❌ Não há validação para impedir edição/exclusão de `BudgetEntry` após criação
|
||||
- ❌ Não há validação para impedir edição/exclusão de `BudgetExecution` se houver movimentos posteriores
|
||||
|
||||
**Análise:**
|
||||
- Em sistemas GFP, transações históricas devem ser imutáveis
|
||||
- Edições devem criar novas transações de ajuste
|
||||
|
||||
**Impacto:** Baixo - Pode ser aceitável se houver controle de auditoria.
|
||||
|
||||
**Recomendação:**
|
||||
- Considerar adicionar validação de imutabilidade
|
||||
- Ou documentar que edições são permitidas apenas para correções
|
||||
|
||||
---
|
||||
|
||||
### 8. **🔴 CRÍTICO: Falta Validação de LIQUIDATION (Parte do Problema #2)**
|
||||
|
||||
**Status:** Incluído no Problema Crítico #2 (Validação de Sequência)
|
||||
|
||||
**Nota:** Esta validação deve ser implementada junto com a validação de sequência.
|
||||
|
||||
---
|
||||
|
||||
### 9. **🔴 CRÍTICO: Falta Validação de PAYMENT (Parte do Problema #2)**
|
||||
|
||||
**Status:** Incluído no Problema Crítico #2 (Validação de Sequência)
|
||||
|
||||
**Nota:** Esta validação deve ser implementada junto com a validação de sequência.
|
||||
|
||||
---
|
||||
|
||||
### 10. **🟢 BAIXO: Falta Segurança (Anotações de Autorização)**
|
||||
|
||||
**Problema:**
|
||||
- ❌ Nenhum controller tem `@PreAuthorize` ou `@Secured`
|
||||
- ❌ Qualquer usuário autenticado pode criar/modificar orçamento
|
||||
|
||||
**Análise:**
|
||||
- Operações de orçamento devem ter controle de acesso rigoroso
|
||||
- Apenas usuários com permissões específicas devem poder criar entradas orçamentárias
|
||||
|
||||
**Impacto:** Alto - Risco de segurança e conformidade.
|
||||
|
||||
**Correção Necessária:**
|
||||
```java
|
||||
@PreAuthorize("hasAuthority('BUDGET_CREATE')")
|
||||
@PostMapping
|
||||
public ResponseEntity<BudgetEntryDTO> create(...)
|
||||
|
||||
@PreAuthorize("hasAuthority('BUDGET_APPROVE')")
|
||||
@PostMapping("/{id}/approve")
|
||||
public ResponseEntity<BudgetEntryDTO> approve(...)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Checklist de Problemas
|
||||
|
||||
### 🔴 Críticos (Devem ser corrigidos IMEDIATAMENTE - Antes de Produção)
|
||||
- [ ] **P1:** Corrigir `@Formula` de `totalCommitted` para filtrar apenas COMMITMENT
|
||||
- [ ] **P2:** Implementar validação de sequência obrigatória COMMITMENT → LIQUIDATION → PAYMENT
|
||||
- [ ] **P3:** Adicionar validação de LIQUIDATION não exceder COMMITMENT correspondente
|
||||
- [ ] **P4:** Adicionar validação de PAYMENT não exceder LIQUIDATION correspondente
|
||||
- [ ] **P5:** Adicionar validação de TRANSFER_OUT/CANCELLATION não exceder saldo disponível
|
||||
|
||||
### 🟡 Médios (Devem ser corrigidos em breve)
|
||||
- [ ] **P6:** Substituir `IllegalArgumentException` por exceções customizadas
|
||||
- [ ] **P7:** Melhorar tratamento de erros nos controllers (retornar mensagens)
|
||||
- [ ] **P8:** Substituir `RuntimeException` em `BudgetIntegrationService`
|
||||
- [ ] **P9:** Adicionar validação de datas dentro do exercício fiscal
|
||||
|
||||
### 🟢 Baixos (Melhorias recomendadas)
|
||||
- [ ] **P10:** Considerar validação de imutabilidade de transações
|
||||
- [ ] **P11:** Adicionar anotações de segurança (`@PreAuthorize`)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Recomendações Prioritárias
|
||||
|
||||
### Prioridade 1 (Urgente - Esta Semana)
|
||||
1. **Corrigir cálculo de totalCommitted** - Impacta todos os cálculos de saldo
|
||||
2. **Implementar validação de sequência** - Crítico para conformidade GFP
|
||||
|
||||
### Prioridade 2 (Importante - Próximas 2 Semanas)
|
||||
3. **Melhorar tratamento de exceções** - Melhora experiência do usuário
|
||||
4. **Adicionar validações de valores e datas** - Previne erros de dados
|
||||
|
||||
### Prioridade 3 (Melhorias - Próximo Mês)
|
||||
5. **Adicionar segurança** - Importante para produção
|
||||
6. **Considerar imutabilidade** - Depende de requisitos de negócio
|
||||
|
||||
---
|
||||
|
||||
## 📊 Métricas de Qualidade
|
||||
|
||||
| Aspecto | Nota | Comentário |
|
||||
|---------|------|------------|
|
||||
| **Arquitetura** | ⭐⭐⭐⭐⭐ | Excelente estrutura e separação de responsabilidades |
|
||||
| **Performance** | ⭐⭐⭐⭐⭐ | Otimizações excelentes com @Formula e COUNT |
|
||||
| **Validações de Negócio** | ⭐⭐⭐ | Boas, mas faltam validações críticas de sequência |
|
||||
| **Tratamento de Erros** | ⭐⭐⭐ | Funcional, mas pode melhorar com exceções customizadas |
|
||||
| **Testes** | ⭐⭐⭐⭐ | Boa cobertura dos cenários críticos |
|
||||
| **Segurança** | ⭐⭐ | Falta controle de acesso |
|
||||
| **Conformidade GFP** | ⭐⭐⭐ | Boa base, mas precisa de validações adicionais |
|
||||
| **Integridade de Dados** | ⭐⭐⭐ | Boa, mas cálculo de totalCommitted incorreto |
|
||||
|
||||
**Nota Geral: 3.5/5.0** (Bom, mas com problemas críticos que devem ser corrigidos)
|
||||
|
||||
**⚠️ ATENÇÃO:** Os problemas críticos (P1 e P2) **DEVEM ser corrigidos antes de produção**, pois afetam diretamente a integridade orçamentária e conformidade com normas GFP.
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Código de Correção Sugerido
|
||||
|
||||
### Correção 1: totalCommitted (CRÍTICO)
|
||||
|
||||
```java
|
||||
// BudgetLine.java
|
||||
@org.hibernate.annotations.Formula("(SELECT COALESCE(SUM(bex.amount), 0) FROM budget_execution bex WHERE bex.budget_line_id = id AND bex.movement_type = 'COMMITMENT')")
|
||||
private BigDecimal totalCommitted;
|
||||
```
|
||||
|
||||
### Correção 2: Validação de Sequência (CRÍTICO)
|
||||
|
||||
```java
|
||||
// BudgetExecutionService.java - Adicionar após validação de COMMITMENT
|
||||
|
||||
if ("LIQUIDATION".equals(dto.getMovementType())) {
|
||||
// Validar se existe COMMITMENT correspondente
|
||||
if (dto.getReferenceId() == null) {
|
||||
throw new BusinessException("ReferenceId é obrigatório para LIQUIDATION",
|
||||
"MISSING_REFERENCE_ID", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
BigDecimal totalCommitted = budgetExecutionRepository
|
||||
.calculateTotalCommittedByReferenceId(dto.getReferenceId());
|
||||
BigDecimal totalLiquidated = budgetExecutionRepository
|
||||
.calculateTotalLiquidatedByReferenceId(dto.getReferenceId());
|
||||
|
||||
if (totalCommitted.compareTo(BigDecimal.ZERO) == 0) {
|
||||
throw new BusinessException("Não existe COMMITMENT correspondente para liquidar",
|
||||
"NO_COMMITMENT", HttpStatus.CONFLICT);
|
||||
}
|
||||
|
||||
BigDecimal availableToLiquidate = totalCommitted.subtract(totalLiquidated);
|
||||
if (dto.getAmount().compareTo(availableToLiquidate) > 0) {
|
||||
throw new BusinessException(
|
||||
String.format("Liquidação não pode exceder empenho. Disponível: %s, Solicitado: %s",
|
||||
availableToLiquidate, dto.getAmount()),
|
||||
"INSUFFICIENT_COMMITMENT", HttpStatus.CONFLICT);
|
||||
}
|
||||
}
|
||||
|
||||
if ("PAYMENT".equals(dto.getMovementType())) {
|
||||
// Validar se existe LIQUIDATION correspondente
|
||||
if (dto.getReferenceId() == null) {
|
||||
throw new BusinessException("ReferenceId é obrigatório para PAYMENT",
|
||||
"MISSING_REFERENCE_ID", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
BigDecimal totalLiquidated = budgetExecutionRepository
|
||||
.calculateTotalLiquidatedByReferenceId(dto.getReferenceId());
|
||||
BigDecimal totalPaid = budgetExecutionRepository
|
||||
.calculateTotalPaidByReferenceId(dto.getReferenceId());
|
||||
|
||||
if (totalLiquidated.compareTo(BigDecimal.ZERO) == 0) {
|
||||
throw new BusinessException("Não existe LIQUIDATION correspondente para pagar",
|
||||
"NO_LIQUIDATION", HttpStatus.CONFLICT);
|
||||
}
|
||||
|
||||
BigDecimal availableToPay = totalLiquidated.subtract(totalPaid);
|
||||
if (dto.getAmount().compareTo(availableToPay) > 0) {
|
||||
throw new BusinessException(
|
||||
String.format("Pagamento não pode exceder liquidação. Disponível: %s, Solicitado: %s",
|
||||
availableToPay, dto.getAmount()),
|
||||
"INSUFFICIENT_LIQUIDATION", HttpStatus.CONFLICT);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Correção 3: Melhorar Tratamento de Exceções
|
||||
|
||||
```java
|
||||
// BudgetEntryService.java
|
||||
import br.gov.sigefp.common.exception.ResourceNotFoundException;
|
||||
|
||||
public BudgetEntryDTO create(CreateBudgetEntryDTO dto) {
|
||||
BudgetLine budgetLine = budgetLineRepository.findById(dto.getBudgetLineId())
|
||||
.orElseThrow(() -> new ResourceNotFoundException(
|
||||
"Linha orçamentária não encontrada: " + dto.getBudgetLineId()));
|
||||
// ...
|
||||
}
|
||||
|
||||
// BudgetEntryController.java
|
||||
@PostMapping
|
||||
public ResponseEntity<BudgetEntryDTO> create(@Valid @RequestBody CreateBudgetEntryDTO dto) {
|
||||
try {
|
||||
BudgetEntryDTO created = budgetEntryService.create(dto);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(created);
|
||||
} catch (ResourceNotFoundException e) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
||||
.build();
|
||||
} catch (BusinessException e) {
|
||||
return ResponseEntity.status(e.getHttpStatus())
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
log.error("Erro inesperado ao criar entrada orçamentária", e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Conclusão
|
||||
|
||||
O módulo de Orçamento implementado pelo Antigravity demonstra **excelente arquitetura** e **otimizações de performance** bem pensadas. Os pontos fortes superam os problemas, mas os **problemas críticos identificados** (cálculo incorreto de totalCommitted e falta de validação de sequência) devem ser corrigidos **imediatamente** antes de produção.
|
||||
|
||||
**Recomendação Final:**
|
||||
- ✅ **Aprovar arquitetura** - Excelente base
|
||||
- ⚠️ **Corrigir problemas críticos** antes de produção
|
||||
- 📈 **Implementar melhorias médias** nas próximas iterações
|
||||
|
||||
---
|
||||
|
||||
**Documento gerado em:** 2025-01-XX
|
||||
**Versão:** 1.0
|
||||
|
||||
Reference in New Issue
Block a user