- Visão Geral
- Tecnologias Utilizadas
- Arquitetura Geral
- Modelagem de Domínio
- Regras de Negócio Implementadas
- Dashboard Administrativo
- Seeds e Cenários de Teste
- API e Swagger
- Testes
- Como Rodar o Projeto
- Considerações Finais
- 🎯 Resumo Executivo — Apresentação rápida (5 min)
- 📊 Diagramas Técnicos — Arquitetura, ER, estados, fluxos
- ✅ Walkthrough de Validação — Checklist completo de requisitos
- 🏗️ Decisões Técnicas — Justificativas arquiteturais
Este projeto implementa um sistema completo de gestão de biblioteca desenvolvido como resposta a um desafio técnico. O objetivo é demonstrar a capacidade de construir uma solução de software estruturada, testável e escalável, aplicando boas práticas de engenharia de software em stack moderna.
O sistema permite:
- Gerenciamento de clientes da biblioteca (membros) com validação rigorosa de CPF
- Catálogo de livros com controle granular de disponibilidade por exemplar físico
- Fluxo completo de reservas e empréstimos
- Identificação automática de atrasos e cálculo de multas progressivas
- Dashboard administrativo com métricas em tempo real
- Autenticação baseada em JWT com controle de acesso por perfil (roles)
A solução atende integralmente ao escopo solicitado, com melhorias estruturais para garantir consistência de dados, separação de responsabilidades e facilidade de manutenção.
- NestJS — Framework escolhido pela arquitetura modular baseada em injeção de dependências, facilitando testes e manutenção. Segue padrões estabelecidos (decorators, guards, interceptors) que tornam o código previsível e escalável.
- Prisma ORM — Provê tipagem end-to-end do banco de dados para o TypeScript, migrations versionadas, e relacionamentos declarativos. Elimina classes de bugs relacionados a inconsistência de schema.
- MariaDB / MySQL — Banco relacional robusto, com suporte a transações ACID, essencial para garantir integridade em operações críticas (reservas, empréstimos, pagamentos).
- JWT (Passport) — Autenticação stateless via JSON Web Tokens, com estratégia de roles (ADMIN / USER) para controle fino de permissões.
- Swagger / OpenAPI — Documentação automática da API gerada a partir dos decorators NestJS, facilitando integração e testes.
- Angular (Standalone) — Framework declarativo e fortemente tipado, ideal para aplicações corporativas. Uso de componentes standalone elimina módulos desnecessários e simplifica a estrutura.
- Angular Material — Biblioteca de componentes UI que garante consistência visual, acessibilidade e responsividade sem necessidade de CSS customizado excessivo.
- Docker Compose — Ambiente de desenvolvimento reprodutível (MySQL + Adminer).
- Jest — Framework de testes com threshold mínimo de 80% de cobertura no backend.
- ESLint + Prettier — Garantia de padrão de código consistente.
A solução segue uma arquitetura em camadas, com separação clara entre apresentação, lógica de negócio e persistência:
┌─────────────────────────────────────────────────┐
│ Frontend (Angular + Material) │
│ apps/web (porta 4200) │
│ - Standalone components │
│ - Guards client-side para proteção de rotas │
│ - Interceptor HTTP para injeção de JWT │
└─────────────────┬───────────────────────────────┘
│
│ HTTP REST + JWT
│
┌─────────────────▼───────────────────────────────┐
│ Backend (NestJS + Guards) │
│ apps/api (porta 3000) │
│ - Controllers (validação de entrada) │
│ - Services (regras de negócio) │
│ - Repositories (Prisma abstraído) │
│ - Guards (JwtAuthGuard, RolesGuard) │
│ - Swagger em /docs │
└─────────────────┬───────────────────────────────┘
│
│ Prisma ORM
│
┌─────────────────▼───────────────────────────────┐
│ Banco de Dados (MariaDB/MySQL) │
│ - 15+ tabelas relacionais │
│ - Constraints de integridade │
│ - Índices estratégicos │
└─────────────────────────────────────────────────┘
Para facilitar a compreensão da arquitetura e fluxos de dados, consulte:
📊 Diagramas Completos — Inclui:
- Diagrama de Arquitetura (Frontend → API → DB)
- Diagrama Entidade-Relacionamento (ER) completo
- Diagramas de Estados (Reservation, Loan, Fine)
- Sequências de Fluxo de Negócio
- Frontend: apresentação, validação básica de UX, gerenciamento de estado local (não usa Redux/NgRx para evitar complexidade desnecessária).
- Backend: toda a lógica de negócio, validações críticas (CPF, disponibilidade, cálculo de multas), geração de tokens JWT.
- Banco de Dados: integridade referencial, constraints de unicidade (CPF, email, ISBN), índices para performance em queries comuns.
- Requisições HTTP via
HttpClientdo Angular. - Autenticação via header
Authorization: Bearer <token>. - Respostas padronizadas com
{ items, meta }para paginação.
A modelagem do banco de dados reflete uma separação explícita entre conceitos de autenticação e domínio de negócio, evitando acoplamento entre "quem acessa o sistema" e "quem é cliente da biblioteca".
User (1) ──── (0..1) Member
- User: representa uma identidade de acesso ao sistema (email, senha, role). Armazena credenciais e permissões (ADMIN, USER).
- Member: representa um cliente da biblioteca (nome, CPF, telefone, multas, empréstimos). É a entidade de domínio central.
Justificativa:
Separar autenticação de domínio permite que:
- Um cliente da biblioteca exista sem usuário de acesso (cadastrado presencialmente).
- Um usuário ADMIN gerencie o sistema sem ser cliente.
- Regras de negócio (multas, bloqueios) fiquem desacopladas de autenticação.
Essa separação é uma prática comum em sistemas corporativos que distinguem "identidade" de "entidade de negócio".
| Entidade | Responsabilidade | Ponto-Chave |
|---|---|---|
| User | Autenticação e autorização | Email único, hash bcrypt, role |
| Member | Cliente da biblioteca | CPF validado e único, status (ACTIVE/BLOCKED), configurações de multa personalizáveis |
| Book | Livro do catálogo | Metadados (título, ISBN, autores), status agregado (AVAILABLE/RESERVED) |
| BookCopy | Exemplar físico | Barcode único, localização, status individual (AVAILABLE/ON_LOAN/RESERVED/LOST/DAMAGED) |
| Reservation | Reserva de livro | Status versionado (ACTIVE → READY_FOR_PICKUP → FULFILLED), expiração automática |
| Loan | Empréstimo ativo | Data de vencimento, status (ACTIVE/OVERDUE/CLOSED), itens associados |
| LoanItem | Item específico emprestado | Associa um BookCopy a um Loan, permite renovação (renewCount), rastreamento de devolução |
| Fine | Multa aplicada | Tipo (OVERDUE/LOST/DAMAGED), valor em centavos, status de pagamento (OPEN/PARTIALLY_PAID/PAID) |
| Payment | Pagamento realizado | Associado a uma ou mais multas via PaymentFine, método (CASH/PIX/CARD) |
Member ────┬──── Reservation (n)
├──── Loan (n)
├──── Fine (n)
└──── Payment (n)
Book ──────┬──── BookCopy (1:n)
└──── Reservation (n)
BookCopy ──┬──── LoanItem (n)
└──── Reservation (opcional, quando reserva específica)
Loan ──────┬──── LoanItem (n)
└──── Fine (n)
Modelagem de exemplares separados (Book vs BookCopy):
Permite que a biblioteca tenha múltiplas cópias físicas do mesmo livro, cada uma com estado independente. Um livro pode estar "disponível" no catálogo enquanto todos os exemplares estão emprestados — o sistema sabe disso porque agrega o status dos
BookCopy.
Todas as regras de negócio vivem exclusivamente no backend. O frontend apenas consome e exibe informações.
- CPF validado com algoritmo de dígitos verificadores.
- Constraint de unicidade no banco (
cpf UNIQUE). - Mensagens de erro claras ao tentar cadastrar CPF duplicado ou inválido.
- Status do Book: agregação derivada dos
BookCopy. - Status do BookCopy: atualizado em tempo real ao criar/cancelar reserva ou empréstimo.
- Lógica:
AVAILABLE: nenhum empréstimo/reserva ativo.RESERVED: reserva ativa aguardando retirada.ON_LOAN: emprestado para membro.LOST/DAMAGED/MAINTENANCE: fora de circulação.
- Reserva criada com
dueDate(prazo para retirada). - Sistema identifica reservas expiradas (
expiresAt < now). - Status de reserva:
ACTIVE: aguardando disponibilidade.READY_FOR_PICKUP: cópia disponível para retirada.FULFILLED: convertida em empréstimo.EXPIRED: prazo de retirada vencido.CANCELLED: cancelada pelo usuário ou administrador.
- Empréstimo criado com
dueAt(data de devolução). - Query
GET /reservations?overdue=trueretorna empréstimos comdueAt < now. - Status
OVERDUEaplicado automaticamente.
Fórmula implementada:
multa_centavos = FINE_FIXED_CENTS × (1 + dias_atraso × (FINE_DAILY_PERCENT / 100))
Exemplo:
FINE_FIXED_CENTS = 500(R$ 5,00)FINE_DAILY_PERCENT = 10(10% ao dia)- Atraso de 3 dias:
500 × (1 + 3 × 0.1) = 500 × 1.3 = 650 centavos(R$ 6,50)
Características:
- Multa fixa + percentual progressivo (não linear).
- Armazenada em centavos para evitar problemas de arredondamento.
- Status de multa rastreado:
OPEN→PARTIALLY_PAID→PAID.
- ADMIN: acesso total (CRUD de livros, clientes, reservas; dashboard; importação de catálogo).
- USER: acesso restrito (visualizar catálogo, criar próprias reservas, área
/me). - Guards aplicados via decorators:
@UseGuards(JwtAuthGuard, RolesGuard)+@Roles('ADMIN').
O sistema inclui um dashboard com métricas de negócio, acessível apenas para usuários com role ADMIN.
Retorna:
{
"overview": {
"totalBooks": 150,
"totalMembers": 87,
"activeMembers": 82,
"blockedMembers": 5
},
"circulation": {
"activeReservations": 12,
"activeLoans": 34,
"overdueLoans": 5,
"totalFines": 15,
"openFines": 8
},
"nextActions": [
{
"type": "overdue_loan",
"memberId": "...",
"memberName": "João Silva",
"dueDate": "2026-01-20T12:00:00Z",
"daysOverdue": 5
}
]
}- Contadores em tempo real: livros, clientes ativos, reservas ativas, multas pendentes.
- Próximas ações: lista de empréstimos atrasados, reservas próximas do vencimento.
- Métricas de gestão: total de multas aplicadas, taxa de bloqueio de clientes.
Justificativa:
Mesmo não sendo exigido explicitamente pelo desafio, o dashboard facilita a validação visual das regras de negócio e demonstra preocupação com a usabilidade do sistema para o operador final.
Dashboard com métricas em tempo real: estatísticas gerais, empréstimos ativos/atrasados, reservas e ações pendentes.
Para facilitar a avaliação do sistema, foram implementados seeds avançados que simulam cenários reais de operação de uma biblioteca.
catalog.seed.ts: popula catálogo de livros, autores, categorias, exemplares físicos.circulation.seed.ts: cria membros, reservas em diferentes estados, empréstimos ativos/atrasados/concluídos, multas pagas e pendentes.
- Dezenas de usuários com status variados (ACTIVE, SUSPENDED, BLOCKED).
- Reservas em diferentes estados:
ACTIVE,READY_FOR_PICKUP,FULFILLED,EXPIRED. - Empréstimos completos: ciclo desde reserva → empréstimo → devolução.
- Multas diversificadas: multas pagas integralmente, parcialmente pagas, e pendentes.
- Livros com múltiplos exemplares: demonstra controle de disponibilidade por cópia.
cd apps/api
npm run prisma:seedValor para avaliação:
Os seeds permitem testar o sistema imediatamente após o setup, sem necessidade de criar dados manualmente. Facilitam testes exploratórios e validação visual de regras de negócio.
O sistema conta com interface completa para gestão de biblioteca. Veja as principais telas:
Catálogo público com busca, filtros e visualização de disponibilidade.
Formulário de cadastro com validação de CPF em tempo real.
Área do usuário autenticado visualizando suas reservas ativas.
Painel administrativo para gerenciamento de todas as reservas do sistema.
A API REST está totalmente documentada via Swagger/OpenAPI, acessível em desenvolvimento em:
http://localhost:3000/docs
POST /auth/login— Login (retorna JWT)- Body:
{ email, password } - Response:
{ access_token: "jwt-token" }
- Body:
GET /auth/me— Dados do usuário logado- Headers:
Authorization: Bearer <token> - Response:
{ id, email, role }
- Headers:
POST /clients— Cadastro de cliente (validação de CPF)- Body:
{ name, cpf, email? }
- Body:
GET /clients— Listagem com paginação e busca- Query:
?q=Maria&sort=name&order=asc
- Query:
GET /clients/:id— Detalhes do clientePATCH /clients/:id— Atualização de dadosDELETE /clients/:id— Remoção
POST /books— Cadastro de livro (ADMIN)- Body:
{ title, authors[], isbn?, coverUrl?, type?, status? }
- Body:
GET /books— Listagem paginada com filtros- Query:
?q=Clean Code&author=Robert&status=AVAILABLE
- Query:
GET /books/:id— Detalhes do livroPATCH /books/:id— AtualizaçãoDELETE /books/:id— Remoção
GET /public/books— Catálogo sem autenticação- Suporta mesmos filtros de
/books
- Suporta mesmos filtros de
GET /public/books/facets— Facetas para filtros (autores, anos, tipos)POST /public/books/:id/reserve— Reservar do catálogo (requer JWT)GET /public/config— Configurações públicas do sistemaGET /public/members/check-cpf— Verificar disponibilidade de CPF- Query:
?cpf=529.982.247-25
- Query:
POST /public/members/register— Cadastro público de novo membro- Body:
{ name, email, cpf, password }
- Body:
POST /reservations— Criar reserva- Body:
{ memberId, bookId, dueDate }
- Body:
GET /reservations— Listar reservas (com filtros)- Query:
?status=ACTIVE&overdue=true&memberId=xxx
- Query:
GET /reservations/overdue— Apenas atrasadasPATCH /reservations/:id/return— Devolver livro
GET /me/reservations— Minhas reservas- Query:
?status=ACTIVE&sort=reservedAt
- Query:
GET /me/loans— Meus empréstimos- Query:
?overdue=true&status=ACTIVE
- Query:
POST /me/reservations/:id/checkout— Finalizar reserva (criar empréstimo)POST /me/reservations/:id/cancel— Cancelar reserva
GET /admin/stats— Dashboard de métricas (ADMIN)- Response:
{ overview, circulation, nextActions }
- Response:
POST /admin/books/import— Importar de OpenLibrary/Google Books (ADMIN)- Body:
{ query?, isbn?, limit? }
- Body:
Total: 30+ endpoints REST documentados
{
"items": [...],
"meta": {
"page": 1,
"pageSize": 10,
"total": 87,
"pageCount": 9
}
}A estratégia de testes prioriza cobertura de regras de negócio críticas e fluxos de integração.
- Services: validação de CPF, cálculo de multas, lógica de disponibilidade.
- Isolamento: mocks de Prisma para garantir testes rápidos e determinísticos.
- Fluxos completos: criar cliente → reservar livro → emprestar → devolver → calcular multa.
- Banco de dados de teste: SQLite em memória ou container Docker efêmero.
Configuração no package.json:
"coverageThreshold": {
"global": {
"branches": 80,
"functions": 80,
"lines": 80,
"statements": 80
}
}Execução:
npm run test:cov- Testes unitários de componentes: validação de formulários, exibição correta de dados.
- Testes de guards e interceptors: garantir proteção de rotas e injeção de JWT.
- Node.js 18+ e npm
- Docker e Docker Compose
- PowerShell 5.1 (Windows) ou bash (Linux/Mac)
git clone <url-do-repositorio>
cd Biblioteca_apidocker compose up -d- MySQL:
localhost:3306, usuárioapp, senhaapp, databasebiblioteca - Adminer: http://localhost:8081 (gerenciamento visual do banco)
cd apps/api
npm installCriar .env (se não existir):
DATABASE_URL="mysql://app:app@localhost:3306/biblioteca"
SHADOW_DATABASE_URL="mysql://root:root@localhost:3306/prisma_shadow"
JWT_SECRET="seu-secret-aqui"
FINE_FIXED_CENTS=500
FINE_DAILY_PERCENT=10Aplicar migrations e popular banco:
npx prisma migrate dev
npx prisma generate
npm run prisma:seedSubir servidor:
npm run start:devAPI estará em: http://localhost:3000
Swagger: http://localhost:3000/docs
cd apps/web
npm install
npm run dev:webFrontend estará em: http://localhost:4200
Após rodar os seeds, use o usuário administrador:
- Email:
admin@biblioteca.local - Senha:
admin
Esta solução atende integralmente todos os requisitos especificados no desafio técnico:
✅ CRUD de clientes com validação rigorosa de CPF único
✅ CRUD de livros com controle correto de disponibilidade
✅ Sistema de reservas de livros por clientes
✅ Identificação de reservas em atraso
✅ Cálculo de multa fixa + percentual progressivo por dia de atraso
✅ Autenticação JWT com roles (ADMIN/USER)
✅ Testes unitários e de integração com cobertura mínima de 80% no backend
- Separação User/Member: evita acoplamento entre autenticação e domínio, permitindo evolução independente (ex: autenticação OAuth2, clientes sem usuário).
- Book vs BookCopy: reflete corretamente a realidade de uma biblioteca (múltiplos exemplares, estados individuais).
- Regras no backend: o frontend é "burro" — toda validação crítica ocorre no servidor, garantindo segurança e consistência.
- Prisma ORM: tipagem end-to-end elimina bugs de schema mismatch, migrations versionadas facilitam evolução do banco.
- Dashboard administrativo: não era obrigatório, mas demonstra preocupação com usabilidade e validação de negócio.
- Seeds avançados: facilita avaliação imediata do sistema, simula cenários reais.
- Arquitetura modular (NestJS): novos módulos (ex: notificações, relatórios) podem ser adicionados sem afetar código existente.
- Testes com alta cobertura: reduz risco de regressão ao evoluir features.
- Migrations versionadas: deploy em produção sem downtime, rollback seguro.
- Separação de responsabilidades: frontend e backend podem evoluir independentemente (ex: trocar Angular por React sem impacto no backend).
Se este fosse um projeto real em produção, as próximas evoluções incluiriam:
- Notificações por email/SMS para atrasos e multas
- Integração com gateway de pagamento (Stripe, PagSeguro)
- Logs estruturados (Winston, Pino) para auditoria
- Deploy containerizado (Kubernetes, AWS ECS)
- Rate limiting e throttling para proteção contra abuso
- Internacionalização (i18n) para suporte a múltiplos idiomas
Desenvolvido com foco em clareza, consistência e facilidade de manutenção. Pronto para avaliação técnica.
