Skip to content

callegariodev/bip-test-integrado

Repository files navigation

Bip Teste Integrado

Backend

Resumo rápido: este README explica todas as decisões técnicas do backend, por que optei por elas e como rodar o projeto localmente (com Docker). Também explica as adaptações feitas para simular um EJB sem exigir um servidor de aplicação (WildFly), o que facilita avaliação e execução do código pelo avaliador.


1. Visão geral do projeto

  • Implementação do backend em Spring Boot (API REST) + um componente chamado BeneficioEjbService que mantém o nome e responsabilidades de um EJB, mas é integradamente gerenciado pelo Spring para facilitar execução local e em CI/CD.
  • Banco de dados: PostgreSQL (esquema e seed providos em src/main/resources/db/ e executados no startup do container do Postgres).
  • Documentação: OpenAPI / Swagger via springdoc.
  • Validações: jakarta.validation nas requisições.
  • DTOs: feitos com record (concisos e imutáveis).
  • Exceptions: exceções customizadas para regras de negócio e um GlobalExceptionHandler para mapear para respostas HTTP apropriadas.

2 - Arquitetura em Camadas

  • O projeto segue uma arquitetura em camadas, com separação clara entre API (Controller), camada de aplicação (Service) e domínio.
  • O domínio foi isolado em um módulo separado (ejb-module), contendo entidades e regras de negócio, evitando acoplamento com Spring ou HTTP.

3. Por que o nome BeneficioEjbService e o que é simulado

O exercício original usava anotações EJB (@Stateless) e um módulo ejb-module. Para não obrigar o avaliador a subir um servidor WildFly (e evitar configuração extra no CI), optei por:

  • Manter o nome BeneficioEjbService (para preservar a intenção do desafio e facilitar revisão do código).
  • Para simular o comportamento de um EJB sem exigir um servidor de aplicação como wildfly, foi criado o EjbServiceConfig, que expõe o BeneficioEjbService como um @Bean, injetando o EntityManager gerenciado pelo Spring.

4. Design de domínio (inspirado em DDD)

  • Regras de criação/alteração estão dentro da entidade de domínio (Beneficio).
  • O domínio contém os métodos debit/credit/create/update para garantir invariantes (ex.: não permitir valor negativo).
  • Decisão: domínio centralizado no módulo EJB-simulado. Não criei um Repository Spring separado para evitar duas fontes de controle do BD (um único lugar gerenciando persistência evita inconsistências).

5. Concurrency / Locking

  • Usei optimistic locking via campo @Version na entidade Beneficio. Justificativa:

    • Menor impacto na performance (comparado a locks pesimistas).
    • Em cenários de alta concorrência, otimistic lock lança OptimisticLockException na segunda commit que conflitar — comportamento esperado.
  • Tratamento: o GlobalExceptionHandler captura OptimisticLockException (e a variante do Spring ObjectOptimisticLockingFailureException) e retorna HTTP 409 Conflict com uma mensagem amigável: Registro foi atualizado por outra operação. Tente novamente.


6. Validação e DTOs

  • Requisições validadas com @NotBlank, @Size, @NotNull, @Positive — erros coletados e retornados por um ErrorResponse (record com status, List<String> errors e timestamp).
  • Se o JSON enviado for inválido (erro de parsing), o GlobalExceptionHandler trata e retorna feedback apropriado em vez de 500 genérico.

7. Unique constraint e tratamento de violação de banco

  • A coluna nome tem UNIQUE no schema. Se um INSERT violar essa constraint, o Postgres lança uma ConstraintViolationException.
  • Estratégia: preferi capturar a exceção no GlobalExceptionHandler (detectar ConstraintViolationException / DataIntegrityViolationException) e transformar em um 400 Bad Request ou mensagem clara explicando que o nome já existe.
  • Alternativa não utilizada: criar checagem de unicidade no serviço (SELECT + throw) — porém isso tem race conditions se usado sozinho; por isso a constraint no DB + tratamento da exceção é mais robusto.

8. Testes

  • Unit / Domain tests: JUnit 5 + Mockito para mocks.

  • Cobertura:

    • Testes de domínio (ex.: BeneficioTest) cobrem regras de negócio.
    • Testes de serviço/EJB (mockando EntityManager) cobrem cenários de transferência, erro de saldo, exclusão, etc.
    • Não foram incluídos testes de integração com banco real por se tratar de um desafio focado em lógica de domínio e regras de negócio, mantendo os testes rápidos e determinísticos.

9. Docker / Execução local

  • Dockerfile e docker-compose.yml para subir API + Postgres sem precisar commitar .jar no repositório.
  • Docker build utiliza multi-stage: primeiro mvn -pl backend-module -am clean package -DskipTests, depois copia o target/*.jar para imagem leve (runtime)
  • docker-compose.yml expõe portas e injeta variáveis diretamente (não uso .env por decisão do desafio — as variáveis estão no compose para facilitar avaliação).

Comandos úteis:

# build + up (vai construir a api e subir postgres)
docker compose up --build

# build local do backend (se quiser só compilar)
mvn -pl backend-module -am clean package

10. Como testar rapidamente

  1. docker compose up --build
  2. Acesse http://localhost:3000/swagger-ui/index.html#/ para ver endpoints.
  3. Teste os endpoints de CRUD e POST /beneficios/transferencias.

Frontend


1. Visão geral do frontend

  • Frontend desenvolvido em Angular 20.
  • Utilização de Standalone Components, sem uso de NgModules.
  • Interface construída com Angular Material, priorizando consistência visual, acessibilidade e boa UX.
  • Comunicação com backend via HttpClient.
  • Tratamento centralizado de erros retornados pela API.
  • Aplicação alinhada às regras de negócio do backend, como soft delete e validações de transferência.

2. Stack e dependências principais

  • Angular 20
  • Angular Router
  • Angular Forms (Reactive Forms)
  • Angular Material
  • RxJS
  • TypeScript 5.9

Dependências principais:

@angular/core @angular/router @angular/forms @angular/material rxjs


3. Arquitetura e organização de pastas

O frontend segue uma organização clara por responsabilidade, separando core, models, services, páginas e componentes compartilhados.

Estrutura real do projeto:

src
 ├── app
 │   ├── core
 │   │   ├── interceptors
 │   │   │   └── error.interceptor.ts
 │   │   ├── models
 │   │   │   └── beneficio.model.ts
 │   │   └── services
 │   │       └── beneficio.service.ts
 │   │
 │   ├── pages
 │   │   ├── beneficio
 │   │   │   ├── beneficio-list
 │   │   │   │   ├── beneficio-list.component.ts
 │   │   │   │   ├── beneficio-list.component.html
 │   │   │   │   └── beneficio-list.component.scss
 │   │   │   └── beneficio-form-dialog
 │   │   │       ├── beneficio-form-dialog.component.ts
 │   │   │       ├── beneficio-form-dialog.component.html
 │   │   │       └── beneficio-form-dialog.component.scss
 │   │   │
 │   │   └── transferencia
 │   │       ├── transferencia.component.ts
 │   │       ├── transferencia.component.html
 │   │       └── transferencia.component.scss
 │   │
 │   └── shared
 │       └── components
 │           └── navbar
 │               ├── navbar.component.ts
 │               ├── navbar.component.html
 │               └── navbar.component.scss
 │
 └── environments
     ├── environment.ts
     └── environment.prod.ts

4. Integração com o backend

  • A URL base da API é centralizada no environment:

http://localhost:3000/api/v1/beneficios


5. Modelos

Os modelos do frontend espelham os contratos do backend, garantindo tipagem forte e clareza.

Principais modelos:

  • Beneficio
  • BeneficioCreateRequest
  • BeneficioUpdateRequest
  • TransferRequest
  • ApiErrorResponse

6. Tela principal — Benefícios

A tela principal exibe um grid com todos os benefícios cadastrados.

Características:

  • Listagem de benefícios ativos e inativos
  • Exibição de:
    • Nome
    • Descrição
    • Saldo (formatado em Real Brasileiro - R$)
    • Status (Ativo / Inativo)
  • Benefícios inativos são exibidos com destaque visual

Ações disponíveis por item:

  • Editar
    • Abre um dialog de edição
    • Permite alterar nome e descrição
    • O saldo não pode ser alterado após a criação
  • Inativar (Soft Delete)
    • Não remove o registro do banco
    • Apenas altera o status para inativo
  • Transferir
    • Disponível apenas para benefícios ativos

7. Dialog de criação / edição de benefício

  • Implementado com Angular Material Dialog
  • Utiliza Reactive Forms
  • Validações no frontend alinhadas com o backend
  • UX moderna e clara

No modo edição:

  • Nome e descrição são editáveis
  • Saldo é exibido como somente leitura
  • Status pode ser alterado entre ativo e inativo

8. Tela de transferência

  • Rota dedicada: /transferencia
  • Permite selecionar:
    • Benefício de origem
    • Benefício de destino
    • Valor da transferência

Regras aplicadas:

  • Benefícios inativos não podem ser selecionados
  • Origem e destino não podem ser iguais
  • Valor deve ser maior que zero

9. Tratamento de erros

  • Tratamento centralizado via HttpInterceptor
  • O frontend espera erros no formato:
{
  "status": 400,
  "timestamp": "2024-01-01T12:00:00Z",
  "errors": [
    "Mensagem de erro"
  ]
}
  • As mensagens são exibidas usando Angular Material Snackbar
  • Caso o erro não esteja no formato esperado, é exibida uma mensagem genérica ao usuário

10. UX e decisões importantes

  • Não exibir ações que o usuário não pode executar
  • Evitar exclusões físicas (soft delete)
  • Feedback visual claro para erros e ações bem-sucedidas
  • Interface moderna sem overengineering

11. Como rodar o frontend localmente

Pré-requisitos:

  • Node.js compatível com Angular 20
  • Angular CLI 20+

Comandos:

npm install npm start

Aplicação disponível em:

http://localhost:4200


12. Considerações finais

O frontend foi desenvolvido com foco em:

  • Clareza de código
  • Alinhamento total com o backend
  • Boa experiência do usuário
  • Facilidade de avaliação técnica

A aplicação está pronta para uso real e evolução futura.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors