Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Credfranco – Controle de Empréstimos

Aplicação Full Stack para controle de empréstimos pessoais, construída como teste técnico.

O sistema permite:

  • Cadastrar clientes
  • Simular empréstimos com juros compostos
  • Aprovar empréstimos com regras de negócio
  • Gerar e persistir parcelas automaticamente
  • Autenticar via Laravel Sanctum (token)
  • Visualizar um dashboard com estatísticas e gráfico
  • Bloquear novos empréstimos para clientes com parcelas em atraso
  • Consultar um serviço externo de score de crédito (mock em rota Next.js)

Stack utilizada

Backend

  • PHP 8.4+ (desenvolvido e testado em ambiente local com PHP 8.2.12, totalmente compatível com 8.4+)
  • Laravel 11
  • Laravel Sanctum (API + token)
  • MySQL 8 (via Docker)
  • Composer

Frontend

  • Next.js 16 (App Router)
  • TypeScript
  • Tailwind CSS
  • Recharts (gráfico do dashboard)

Infra

  • Docker + docker-compose (somente para o banco de dados)
  • MySQL rodando na porta 3307 (a 3306 já está ocupada por outra instância)

Estrutura de pastas

/backend   → API Laravel
/frontend  → Frontend Next.js (App Router)
/docker-compose.yml → banco MySQL

Passo a passo para rodar o projeto

1. Pré-requisitos

Você precisa ter instalado na sua máquina:

  • Git
  • Docker e Docker Compose
  • PHP 8.2+
  • Composer
  • Node.js 20+ e npm (ou yarn/pnpm)

2. Clonar o repositório

git clone https://github.com/seu-usuario/credfranco.git
cd credfranco

(Substitua seu-usuario pelo usuário correto do GitHub.)


3. Subir o banco de dados com Docker

O projeto já vem com um docker-compose.yml configurado para o MySQL na porta 3307:

services:
  db:
    image: mysql:8.0
    container_name: credfranco_db
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: credfranco
      MYSQL_USER: creduser
      MYSQL_PASSWORD: credpass
      MYSQL_ROOT_PASSWORD: root
    ports:
      - "3307:3306"
    volumes:
      - db_data:/var/lib/mysql

volumes:
  db_data:

Para subir o banco:

docker-compose up -d

Verifique se o container está rodando:

docker ps

Banco disponível em:

  • Host: 127.0.0.1
  • Porta: 3307
  • Banco: credfranco
  • Usuário: creduser
  • Senha: credpass

4. Configurar e rodar o Backend (Laravel)

No diretório do projeto, entre na pasta backend:

cd backend

4.1. Copiar o arquivo de ambiente

cp .env.example .env

4.2. Ajustar variáveis de conexão com o banco

Edite o .env para bater com o docker-compose:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3307
DB_DATABASE=credfranco
DB_USERNAME=creduser
DB_PASSWORD=credpass

4.3. Instalar as dependências do Laravel

composer install

4.4. Gerar a chave da aplicação

php artisan key:generate

4.5. Executar as migrations

php artisan migrate

Isso criará, entre outras, as tabelas:

  • users
  • clients
  • loans
  • installments
  • personal_access_tokens

Caso prefira, você também pode criar o usuário manualmente via php artisan tinker.

4.6. Usuário padrão para login

Utilize as credenciais definidas nos seeds (ou criadas manualmente). Exemplo:

  • E-mail: admin@credfranco.test
  • Senha: secret123

4.7. Subir o servidor local do Laravel

php artisan serve

Por padrão, a API ficará disponível em:

  • http://127.0.0.1:8000
  • Endpoints da API em http://127.0.0.1:8000/api/...

5. Configurar e rodar o Frontend (Next.js)

Em outro terminal, volte para a raiz do projeto e entre na pasta frontend:

cd ../frontend

5.1. Criar o arquivo de variáveis de ambiente do frontend

cp .env.example .env.local

5.2. Configurar a URL da API

NEXT_PUBLIC_API_URL=http://127.0.0.1:8000/api

5.3. Instalar as dependências do frontend

npm install
# ou
yarn
# ou
pnpm install

5.4. Subir o servidor de desenvolvimento do Next.js

npm run dev
# ou
yarn dev

Por padrão, o frontend ficará disponível em:

  • http://localhost:3000

Deixe os dois servidores rodando ao mesmo tempo:

  • Backend: php artisan serve
  • Frontend: npm run dev

6. Fluxos principais do sistema

Login

  1. Acesse http://localhost:3000.
  2. Informe e-mail e senha do usuário criado (ex.: admin@credfranco.test / secret123).
  3. O frontend obtém um token da API e passa a enviar esse token no header Authorization.

Cadastro de clientes

  • Tela para registro dos dados básicos do cliente, que serão utilizados nas simulações e contratos de empréstimo.
  • Campos principais: nome, CPF, data de nascimento, renda mensal, telefone.
  • Funcionalidades: listagem paginada, busca por nome/CPF, máscaras de CPF e telefone.

Simulação de empréstimos

  • Formulário com: valor solicitado, taxa de juros mensal (%), quantidade de parcelas (6–36).
  • O backend calcula:
    • valor da parcela (juros compostos)
    • valor total do empréstimo
    • data da primeira parcela (D+30)
    • lista de parcelas com data de vencimento e valor.

Aprovação de empréstimos

Na aprovação, o backend aplica as regras de negócio:

  • Renda mensal ≥ 4× o valor da parcela
  • CPF válido
  • Consulta a serviço externo (mockado) de score (0–1000)
  • Score mínimo para aprovação: 600
  • Bloqueio caso o cliente possua parcelas em atraso (vencimento + 5 dias)

Se aprovado:

  • O empréstimo é salvo em loans
  • As parcelas são salvas em installments
  • Status do empréstimo: approved

Dashboard

  • Total emprestado
  • Ticket médio
  • Quantidade de empréstimos ativos
  • Gráfico com evolução dos valores emprestados (Recharts)

Decisões de arquitetura

Separação Backend / Frontend

  • Projeto dividido em dois módulos independentes (/backend e /frontend).
  • Comunicação via API REST em JSON, facilitando eventual troca de frontend (ex.: app mobile).

API e autenticação

  • API REST construída em Laravel 11, usando controllers organizados por contexto (clientes, empréstimos).
  • Autenticação via Laravel Sanctum, utilizando tokens pessoais.
  • Rotas protegidas exigem header Authorization: Bearer {token}.

Modelagem de domínio

  • Entidades principais:
    • Client: dados cadastrais do cliente.
    • Loan: contrato de empréstimo, com valor principal, taxa, quantidade de parcelas, score externo, status, etc.
    • Installment: parcelas geradas a partir do empréstimo, com número, valor, data de vencimento e status.
  • Relacionamentos:
    • Client 1:N Loan
    • Loan 1:N Installment

Regras de negócio de aprovação

  • A simulação e a aprovação são separadas:
    • Simulação não persiste dados, apenas calcula valores.
    • Aprovação valida as regras e persiste empréstimo + parcelas dentro de uma DB::transaction().
  • As regras (renda mínima, CPF, parcelas em atraso, score) estão centralizadas no fluxo de aprovação para facilitar manutenção.

Integração com score externo (mock)

  • Em vez de chamar diretamente um terceiro real, o frontend utiliza uma rota Next.js que simula um serviço externo de score.
  • Essa rota retorna um score aleatório/determinístico de 0 a 1000.
  • O backend consome esse score na aprovação, como se fosse um serviço externo real.

Eventos de domínio

  • Ao aprovar um empréstimo, é disparado o evento LoanCreated.
  • Um listener (LogLoanCreated) registra no laravel.log um resumo do empréstimo criado.
  • Isso permite adicionar comportamentos assíncronos (ex.: disparar e-mail, enviar mensagem para fila) sem acoplar a lógica diretamente ao controller.

Testes automatizados

  • Foram adicionados testes de Feature para garantir o comportamento das principais regras de negócio.
  • Exemplos:
    • Bloqueio de aprovação quando o cliente possui parcelas em atraso.
    • Simulação de empréstimo para cliente existente.
  • Execução dos testes:
cd backend
php artisan test

Exemplos de requisições (API)

Abaixo alguns exemplos em curl para facilitar a validação da API.

1. Login

curl -X POST http://127.0.0.1:8000/api/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "admin@credfranco.test",
    "password": "secret123"
  }'

Resposta (exemplo):

{
  "user": {
    "id": 1,
    "name": "Admin",
    "email": "admin@credfranco.test"
  },
  "token": "1|abcdef..."
}

Guarde o token para usar nas próximas requisições.


2. Listar clientes

curl -X GET http://127.0.0.1:8000/api/clients \
  -H "Accept: application/json" \
  -H "Authorization: Bearer 1|abcdef..."

3. Criar cliente

curl -X POST http://127.0.0.1:8000/api/clients \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer 1|abcdef..." \
  -d '{
    "name": "João Silva",
    "cpf": "12345678909",
    "birth_date": "1990-01-01",
    "monthly_income": 5000,
    "phone": "11999999999"
  }'

Resposta (exemplo):

{
  "id": 1,
  "name": "João Silva",
  "cpf": "12345678909",
  "monthly_income": 5000,
  "phone": "11999999999",
  "created_at": "2025-12-05T14:13:41.000000Z"
}

4. Simular empréstimo

curl -X POST http://127.0.0.1:8000/api/loans/simulate \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer 1|abcdef..." \
  -d '{
    "client_id": 1,
    "principal_amount": 5632.00,
    "installments_count": 12,
    "interest_rate_monthly": 2.5
  }'

Resposta (exemplo):

{
  "principal_amount": 5632.0,
  "interest_rate_monthly": 2.5,
  "installments_count": 12,
  "monthly_installment": 493.29,
  "total_amount": 5919.48,
  "first_due_date": "2025-01-05",
  "installments": [
    {
      "number": 1,
      "due_date": "2025-01-05",
      "amount": 493.29
    }
    // ... demais parcelas
  ]
}

5. Aprovar empréstimo

curl -X POST http://127.0.0.1:8000/api/loans/approve \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer 1|abcdef..." \
  -d '{
    "client_id": 1,
    "principal_amount": 5632.00,
    "installments_count": 12,
    "interest_rate_monthly": 2.5
  }'

Resposta de sucesso (exemplo):

{
  "loan": {
    "id": 35,
    "client_id": 1,
    "principal_amount": 5632.0,
    "interest_rate_monthly": 2.5,
    "installments_count": 12,
    "monthly_installment": 493.29,
    "total_amount": 5919.48,
    "status": "approved",
    "external_score": 750,
    "approved_at": "2025-12-05T14:13:41.000000Z",
    "installments": [
      {
        "number": 1,
        "due_date": "2025-01-05",
        "amount": 493.29,
        "status": "pending"
      }
      // ... demais parcelas
    ]
  },
  "external_score": 750
}

6. Exemplos de erros de regra de negócio

Renda insuficiente:

{
  "error": "Renda insuficiente para aprovação",
  "client_monthly_income": 2500,
  "required_minimum": 3899.48
}

Parcelas em atraso:

{
  "error": "Cliente possui parcelas em atraso",
  "late_installments": [
    {
      "id": 123,
      "due_date": "2025-02-01",
      "days_late": 14
    }
  ]
}

Score abaixo do mínimo:

{
  "error": "Score abaixo do mínimo para aprovação",
  "score": 524
}

Possíveis melhorias futuras

  • Implementar autenticação com roles (admin/operador)
  • Histórico de alterações nos empréstimos
  • Exportação de dados (CSV/Excel) de clientes e contratos
  • Integração real com serviço externo de score de crédito
  • Envio de e-mails para clientes (aprovação, vencimento próximo, atraso)
  • Jobs/fila para geração de parcelas e/ou consulta de score

Qualquer dúvida sobre configuração ou fluxo da aplicação, consulte este README ou abra uma issue no repositório.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages