Este projeto é um serviço escalável de validação de contratos financeiros com processamento assíncrono de alto volume, desenvolvido como parte de um desafio técnico para o Agibank.
O sistema utiliza a Arquitetura Hexagonal (Ports & Adapters) para isolar a lógica de negócio (Domain) de detalhes de infraestrutura.
- JDK 21
- Docker
- Maven
- Clone o repositório.
git clone https://github.com/MarleneMoraes/contract-validation-service- Na raiz do projeto, suba a infraestrutura (Kafka + PostgreSQL) via Docker:
docker-compose up -d --build- Execute a aplicação via Maven:
./mvnw clean spring-boot:runOBS: caso esteja em um terminal Power Shell, digitar:
.\mvnw clean spring-boot:run
- Em um terminal separado, injete um contrato para validação (conforme exemplo abaixo):
docker exec -i agibank-kafka kafka-console-producer --bootstrap-server agibank-kafka:9092 --topic contracts-input << EOF
{"contractId":"CNT-2026-X","clientId":"C99","productType":"LOAN","amount":15000.0,"currency":"BRL","termMonths":36,"startDate":"2026-02-01","customerAge":25,"clientRiskTier":"B","collateralProvided":true,"attributes":{"region":"South","employmentStatus":"EMPLOYED","annualIncome":60000.0}}
EOF- Acesse
http://localhost:8080/swagger-ui/index.htmle consulte o ID do contrato.
- Curl:
curl -X 'GET' \
'http://localhost:8080/api/contracts/CNT-2026-X' \
-H 'accept: */*'- Request URL:
http://localhost:8080/api/contracts/CNT-2026-X
Para auditar os contratos processados, utilize os seguintes cenários:
| Cenário | Endpoint | Status Esperado | Motivo |
|---|---|---|---|
| Sucesso | GET /api/contracts/CNT-2026-X |
200 OK |
Retorna lista com os 8 resultados das validações. |
| Não Encontrado | GET /api/contracts/CNT-2026-X |
404 Not Found |
O contrato ainda não foi processado ou o ID é inválido. |
| Falha de Regra | GET /api/contracts/CNT-2026-X |
200 OK |
Retorna a lista indicando quais campos (ex: idade, valor) falharam. |
O motor de validação executa 8 regras independentes simultaneamente, localizadas em src/main/java/com/agibank/contract/infraestructure/rules:
AmountValidator: Valor entre R$ 1.000 e R$ 5.000.000.CurrencyValidator: Validação se o código pertence às moedas suportadas pela aplicação (BRL, USD, EUR).TermMonthsValidator: Validação de prazo entre 12 e 360 meses.StartDateValidator: Validação de Data de início não ser no passado.CustomerAgeValidator: Validação se a Idade do cliente é entre 18 e 75 anos.RiskTierValidator: Validação de tier de risco válidos - A, B, C, D.CollateralValidator: Validação de Garantia obrigatória para valores maiores que R$ 1.000.000.ProductIncomeValidator: Validação dinâmica de renda anual mínima conforme o produto selecionado.
Após o processamento assíncrono, os resultados detalhados de cada uma das 8 regras podem ser consultados via API REST (Swagger).
-
Endpoint:
GET /api/contracts/{contractId} -
Exemplo de Resposta (Status 200 OK):
[
{
"id": 1,
"contractId": "CNT-2026-X",
"ruleName": "VALIDATION_AMOUNT",
"passed": true,
"message": "Valor válido: 15000.0",
"durationMs": 3,
"createdAt": "2026-01-26T09:29:40.947242"
},
{
"id": 2,
"contractId": "CNT-2026-X",
"ruleName": "VALIDATION_COLLATERAL",
"passed": true,
"message": "Garantia validada com sucesso para o valor de R$ 15000.0",
"durationMs": 3,
"createdAt": "2026-01-26T09:29:40.947263"
},
{
"id": 3,
"contractId": "CNT-2026-X",
"ruleName": "VALIDATION_CURRENCY",
"passed": true,
"message": "Moeda válida: BRL",
"durationMs": 1,
"createdAt": "2026-01-26T09:29:40.947269"
},
{
"id": 4,
"contractId": "CNT-2026-X",
"ruleName": "VALIDATION_CUSTOMER_AGE",
"passed": true,
"message": "Idade do cliente válida: 25",
"durationMs": 0,
"createdAt": "2026-01-26T09:29:40.947273"
},
{
"id": 5,
"contractId": "CNT-2026-X",
"ruleName": "VALIDATION_PRODUCT_INCOME",
"passed": true,
"message": "Renda anual compatível com produto:60000.0",
"durationMs": 1,
"createdAt": "2026-01-26T09:29:40.947277"
},
{
"id": 6,
"contractId": "CNT-2026-X",
"ruleName": "VALIDATION_RISK_TIER",
"passed": true,
"message": "Tier de risco aceitável: B",
"durationMs": 0,
"createdAt": "2026-01-26T09:29:40.947281"
},
{
"id": 7,
"contractId": "CNT-2026-X",
"ruleName": "VALIDATION_START_DATE",
"passed": true,
"message": "Data de início válida: 2026-02-01",
"durationMs": 0,
"createdAt": "2026-01-26T09:29:40.947285"
},
{
"id": 8,
"contractId": "CNT-2026-X",
"ruleName": "VALIDATION_TERM_MONTHS",
"passed": true,
"message": "Prazo válido: 36",
"durationMs": 0,
"createdAt": "2026-01-26T09:29:40.947288"
}
]A aplicação expõe métricas via Micrometer/Actuator.
- Endpoint de Listagem:
GET /actuator/metrics - Endpoint de Detalhe:
GET /actuator/metrics/{nome_da_metrica}
Principais métricas de negócio (disponíveis após o primeiro processamento):
contract_validation_total: Total de mensagens processadas.contract_validation_approved: Total de contratos aprovados.contract_validation_rejected: Total de contratos rejeitados.- Health Checks: Disponíveis em
/actuator/healthe/actuator/readiness.
- Unitários:
mvn test(Validação das 8 regras de domínio). - Integração:
mvn test(Testcontainers para Kafka e Postgres).
