API REST para gerenciamento de contratos empresariais desenvolvida com ASP.NET Core 9.0, Entity Framework Core e MariaDB.
- Pré-requisitos
- Tecnologias Utilizadas
- Instalação
- Configuração do Banco de Dados
- Executando o Projeto
- Testando a API
- Endpoints da API
- Estrutura do Projeto
- Troubleshooting
Antes de começar, certifique-se de ter instalado em sua máquina:
| Software | Versão Mínima | Download |
|---|---|---|
| .NET SDK | 9.0 | Download |
| Docker Desktop | Latest | Download |
| Git (opcional) | 2.x | Download |
# Verificar .NET
dotnet --version
# Deve retornar: 9.0.x
# Verificar Docker
docker --version
# Deve retornar: Docker version 20.x ou superior
# Verificar Docker Compose
docker-compose --version
# Deve retornar: Docker Compose version 2.x ou superior- ASP.NET Core 9.0 - Framework web
- Entity Framework Core 9.0 - ORM
- MariaDB - Banco de dados relacional
- Pomelo.EntityFrameworkCore.MySql - Provider MySQL/MariaDB
- AutoMapper 13.0 - Mapeamento objeto-objeto
- Swashbuckle (Swagger) - Documentação da API
- Docker - Containerização
# Clone o repositório
git clone https://github.com/seu-usuario/ContratosAPI.git
# Entre na pasta do projeto
cd ContratosAPI- Baixe o arquivo
ContratosAPI.zip - Extraia o arquivo em uma pasta de sua preferência
- Abra o terminal/prompt de comando na pasta extraída
# Windows (PowerShell)
cd C:\caminho\para\ContratosAPI
# Linux/Mac
cd /caminho/para/ContratosAPIO projeto utiliza Docker para executar o banco de dados MariaDB.
# Certifique-se de estar na pasta do projeto
cd ContratosAPI
# Inicie o container do banco de dados
docker-compose up -dSaída esperada:
Creating network "contratosapi_default" with the default driver
Creating volume "contratosapi_mariadb_data" with default driver
Creating contratos_api ... done
docker psSaída esperada:
CONTAINER ID IMAGE COMMAND STATUS PORTS NAMES
xxxxxxxxxxxxx mariadb:latest "docker-entrypoint.s…" Up 30 seconds 0.0.0.0:3306->3306/tcp contratos_api
dotnet restore# Aplicar migrações (cria as tabelas no banco)
dotnet ef database updateSaída esperada:
Build started...
Build succeeded.
Applying migration '20251222184650_InitialCreate'.
Applying migration '20251222184934_Update'.
Applying migration '20251222222004_NewUpdate'.
Done.
Nota: Se o comando
dotnet efnão for reconhecido, instale a ferramenta:dotnet tool install --global dotnet-ef
# Execute a aplicação
dotnet runSaída esperada:
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5016
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
# Execute com auto-reload (recarrega quando arquivos são modificados)
dotnet watch runApós executar o projeto, acesse:
- Swagger UI: http://localhost:5016/swagger/index.html
- API Base URL: http://localhost:5016/api
- Abra o navegador e acesse: http://localhost:5016/swagger/index.html
- Você verá a interface do Swagger com todos os endpoints disponíveis
- Clique em qualquer endpoint para expandir
- Clique em "Try it out"
- Preencha os parâmetros necessários
- Clique em "Execute"
- Veja a resposta da API
Você também pode testar usando cURL no terminal:
# Listar todos os estados
curl http://localhost:5016/api/estadosGerencia os estados brasileiros (tabela de referência).
Descrição: Retorna todos os estados brasileiros.
Request:
curl -X GET http://localhost:5016/api/estadosResponse: 200 OK
[
{
"id": 1,
"sigla": "AC",
"nome": "Acre"
},
{
"id": 25,
"sigla": "SP",
"nome": "São Paulo"
}
]Descrição: Retorna um estado específico.
Request:
curl -X GET http://localhost:5016/api/estados/25Response: 200 OK
{
"id": 25,
"sigla": "SP",
"nome": "São Paulo"
}Gerencia os tipos de contrato (tabela de referência).
Descrição: Retorna todos os tipos de contrato.
Request:
curl -X GET http://localhost:5016/api/tiposcontratoResponse: 200 OK
[
{
"id": 1,
"nome": "Prestação de Serviços",
"descricao": "Contrato de prestação de serviços profissionais"
},
{
"id": 2,
"nome": "Consultoria",
"descricao": "Contrato de consultoria especializada"
}
]Gerencia os status possíveis de um contrato.
Descrição: Retorna todos os status de contrato.
Request:
curl -X GET http://localhost:5016/api/statuscontratosResponse: 200 OK
[
{
"id": 1,
"nome": "Ativo",
"descricao": "Contrato em vigor"
},
{
"id": 2,
"nome": "Suspenso",
"descricao": "Contrato temporariamente suspenso"
},
{
"id": 3,
"nome": "Encerrado",
"descricao": "Contrato finalizado"
}
]Gerencia os tipos de contraente (Empresa ou Funcionário).
Descrição: Retorna todos os tipos de contraente.
Request:
curl -X GET http://localhost:5016/api/tiposcontraenteResponse: 200 OK
[
{
"id": 1,
"nome": "Empresa",
"descricao": "Pessoa Jurídica"
},
{
"id": 2,
"nome": "Funcionário",
"descricao": "Pessoa Física"
}
]Gerencia empresas (Pessoas Jurídicas).
Descrição: Lista todas as empresas (paginado).
Parâmetros Query:
pageNumber(opcional): Número da página (padrão: 1)pageSize(opcional): Tamanho da página (padrão: 10, máx: 100)
Request:
curl -X GET "http://localhost:5016/api/empresas?pageNumber=1&pageSize=10"Response: 200 OK
[
{
"id": 1,
"razaoSocial": "Tech Solutions Ltda",
"nomeFantasia": "Tech Solutions",
"cnpj": "12345678901234",
"cidade": "São Paulo",
"estadoSigla": "SP",
"email": "contato@techsolutions.com",
"telefone": "+5511987654321"
}
]Response Headers:
X-Total-Count: 1
X-Page-Number: 1
X-Page-Size: 10
Descrição: Retorna uma empresa específica com detalhes completos.
Request:
curl -X GET http://localhost:5016/api/empresas/1Response: 200 OK
{
"id": 1,
"razaoSocial": "Tech Solutions Ltda",
"nomeFantasia": "Tech Solutions",
"cnpj": "12345678901234",
"logradouro": "Av. Paulista",
"numero": "1000",
"complemento": "Sala 501",
"setor": "Tecnologia",
"cidade": "São Paulo",
"estadoId": 25,
"estadoSigla": "SP",
"estadoNome": "São Paulo",
"email": "contato@techsolutions.com",
"telefone": "+5511987654321",
"telefoneAlternativo": "+5511912345678",
"website": "https://www.techsolutions.com",
"linkedIn": "tech-solutions",
"totalContratos": 5
}Descrição: Busca empresa por CNPJ.
Request:
curl -X GET http://localhost:5016/api/empresas/cnpj/12345678901234Response: 200 OK ou 404 Not Found
Descrição: Cria uma nova empresa.
Request:
curl -X POST http://localhost:5016/api/empresas \
-H "Content-Type: application/json" \
-d '{
"razaoSocial": "Tech Solutions Ltda",
"nomeFantasia": "Tech Solutions",
"cnpj": "12345678901234",
"logradouro": "Av. Paulista",
"numero": "1000",
"complemento": "Sala 501",
"setor": "Tecnologia",
"cidadeEstado": {
"cidade": "São Paulo",
"estadoId": 25
},
"contato": {
"email": "contato@techsolutions.com",
"telefone": "+5511987654321",
"telefoneAlternativo": "+5511912345678",
"website": "https://www.techsolutions.com",
"linkedIn": "tech-solutions"
}
}'Response: 201 Created
{
"id": 1,
"razaoSocial": "Tech Solutions Ltda",
"nomeFantasia": "Tech Solutions",
"cnpj": "12345678901234",
...
}Validações:
razaoSocial: Obrigatório, máx 200 caracteresnomeFantasia: Obrigatório, máx 200 caracterescnpj: Obrigatório, exatamente 14 dígitos numéricos, únicoemail: Obrigatório, formato válido de emailtelefone: Obrigatório, formato válidoestadoId: Obrigatório, deve existir na tabela Estados
Descrição: Atualiza uma empresa existente.
Request:
curl -X PUT http://localhost:5016/api/empresas/1 \
-H "Content-Type: application/json" \
-d '{
"razaoSocial": "Tech Solutions Ltda - Atualizada",
"nomeFantasia": "Tech Solutions",
"cnpj": "12345678901234",
"logradouro": "Av. Paulista",
"numero": "2000",
"complemento": "Sala 1001",
"setor": "Tecnologia da Informação",
"cidadeEstado": {
"cidade": "São Paulo",
"estadoId": 25
},
"contato": {
"email": "contato@techsolutions.com",
"telefone": "+5511987654321"
}
}'Response: 204 No Content
Descrição: Remove uma empresa.
Request:
curl -X DELETE http://localhost:5016/api/empresas/1Response: 204 No Content ou 409 Conflict (se houver contratos vinculados)
Response 409:
{
"error": "Empresa possui contratos vinculados",
"message": "Não é possível excluir uma empresa com contratos vinculados"
}Gerencia funcionários (Pessoas Físicas).
Descrição: Lista todos os funcionários (paginado).
Request:
curl -X GET "http://localhost:5016/api/funcionarios?pageNumber=1&pageSize=10"Response: 200 OK
[
{
"id": 1,
"nomeCompleto": "João Silva",
"cpf": "12345678901",
"idade": 30,
"funcao": "Desenvolvedor",
"cidade": "São Paulo",
"estadoSigla": "SP",
"email": "joao.silva@email.com",
"telefone": "+5511987654321"
}
]Descrição: Retorna um funcionário específico.
Request:
curl -X GET http://localhost:5016/api/funcionarios/1Response: 200 OK
{
"id": 1,
"nomeCompleto": "João Silva",
"dataNascimento": "1994-05-15T00:00:00",
"idade": 30,
"cpf": "12345678901",
"funcao": "Desenvolvedor Senior",
"cidade": "São Paulo",
"estadoId": 25,
"estadoSigla": "SP",
"estadoNome": "São Paulo",
"email": "joao.silva@email.com",
"telefone": "+5511987654321",
"telefoneAlternativo": null,
"website": null,
"linkedIn": "joao-silva",
"totalContratos": 3
}Descrição: Busca funcionário por CPF.
Request:
curl -X GET http://localhost:5016/api/funcionarios/cpf/12345678901Response: 200 OK ou 404 Not Found
Descrição: Cria um novo funcionário.
Request:
curl -X POST http://localhost:5016/api/funcionarios \
-H "Content-Type: application/json" \
-d '{
"nomeCompleto": "João Silva",
"dataNascimento": "1994-05-15",
"cpf": "12345678901",
"funcao": "Desenvolvedor Senior",
"cidadeEstado": {
"cidade": "São Paulo",
"estadoId": 25
},
"contato": {
"email": "joao.silva@email.com",
"telefone": "+5511987654321",
"linkedIn": "joao-silva"
}
}'Response: 201 Created
Validações:
nomeCompleto: Obrigatório, máx 200 caracteresdataNascimento: Obrigatório, idade mínima 14 anoscpf: Obrigatório, exatamente 11 dígitos numéricos, únicofuncao: Obrigatório, máx 200 caracteresemail: Obrigatório, formato válido
Descrição: Atualiza um funcionário existente.
Request:
curl -X PUT http://localhost:5016/api/funcionarios/1 \
-H "Content-Type: application/json" \
-d '{
"nomeCompleto": "João Silva Santos",
"dataNascimento": "1994-05-15",
"cpf": "12345678901",
"funcao": "Tech Lead",
"cidadeEstado": {
"cidade": "São Paulo",
"estadoId": 25
},
"contato": {
"email": "joao.silva@email.com",
"telefone": "+5511987654321"
}
}'Response: 204 No Content
Descrição: Remove um funcionário.
Request:
curl -X DELETE http://localhost:5016/api/funcionarios/1Response: 204 No Content ou 409 Conflict (se houver contratos vinculados)
Gerencia contratos entre empresas e contraentes (Empresa ou Funcionário).
Descrição: Lista todos os contratos (paginado e com filtros).
Parâmetros Query:
pageNumber(opcional): Número da página (padrão: 1)pageSize(opcional): Tamanho da página (padrão: 10)statusId(opcional): Filtrar por statustipoId(opcional): Filtrar por tipo de contrato
Request:
# Listar todos
curl -X GET http://localhost:5016/api/contratos
# Filtrar por status ativo
curl -X GET "http://localhost:5016/api/contratos?statusId=1"
# Filtrar por tipo e status
curl -X GET "http://localhost:5016/api/contratos?tipoId=1&statusId=1"Response: 200 OK
[
{
"id": 1,
"contratanteNome": "Tech Solutions Ltda",
"contraenteNome": "João Silva",
"tipoContratoNome": "Prestação de Serviços",
"statusContratoNome": "Ativo",
"precificacao": 5000.00,
"dataEmissao": "2024-01-15T00:00:00",
"estaVencido": false
}
]Descrição: Retorna um contrato específico com detalhes completos.
Request:
curl -X GET http://localhost:5016/api/contratos/1Response: 200 OK
{
"id": 1,
"contratanteId": 1,
"contratanteNome": "Tech Solutions Ltda",
"contratanteCNPJ": "12345678901234",
"contraenteId": 1,
"tipoContraenteId": 2,
"tipoContraenteNome": "Funcionário",
"contraenteNome": "João Silva",
"contraenteDocumento": "12345678901",
"tipoContratoId": 1,
"tipoContratoNome": "Prestação de Serviços",
"tipoContratoDescricao": "Contrato de prestação de serviços profissionais",
"statusContratoId": 1,
"statusContratoNome": "Ativo",
"statusContratoDescricao": "Contrato em vigor",
"precificacao": 5000.00,
"condicoesPagamento": "Mensal, até o dia 10",
"dataEmissao": "2024-01-15T00:00:00",
"validade": "2025-01-15T00:00:00",
"descricao": "Contrato de desenvolvimento de software",
"estaVencido": false,
"diasAtivo": 342
}Descrição: Cria um novo contrato.
Request:
curl -X POST http://localhost:5016/api/contratos \
-H "Content-Type: application/json" \
-d '{
"contratanteId": 1,
"contraenteId": 1,
"tipoContraenteId": 2,
"tipoContratoId": 1,
"statusContratoId": 1,
"precificacao": 5000.00,
"condicoesPagamento": "Mensal, até o dia 10",
"dataEmissao": "2024-01-15",
"validade": "2025-01-15",
"descricao": "Contrato de desenvolvimento de software"
}'Response: 201 Created
Validações:
contratanteId: Obrigatório, deve existir na tabela EmpresascontraenteId: Obrigatório, deve existir (Empresa ou Funcionário conforme tipo)tipoContraenteId: Obrigatório, 1=Empresa ou 2=FuncionáriotipoContratoId: Obrigatório, deve existir na tabela TiposContratostatusContratoId: Obrigatório, deve existir na tabela StatusContratosprecificacao: Obrigatório, maior que zerocondicoesPagamento: Obrigatório, máx 500 caracteresdataEmissao: Obrigatório
Exemplo com Contraente Empresa:
curl -X POST http://localhost:5016/api/contratos \
-H "Content-Type: application/json" \
-d '{
"contratanteId": 1,
"contraenteId": 2,
"tipoContraenteId": 1,
"tipoContratoId": 2,
"statusContratoId": 1,
"precificacao": 10000.00,
"condicoesPagamento": "Trimestral, até o último dia útil",
"dataEmissao": "2024-03-01",
"validade": "2025-03-01",
"descricao": "Contrato de consultoria empresarial"
}'Descrição: Atualiza um contrato existente.
Request:
curl -X PUT http://localhost:5016/api/contratos/1 \
-H "Content-Type: application/json" \
-d '{
"tipoContratoId": 1,
"statusContratoId": 2,
"precificacao": 6000.00,
"condicoesPagamento": "Mensal, até o dia 15",
"dataEmissao": "2024-01-15",
"validade": "2025-01-15",
"descricao": "Contrato de desenvolvimento de software - ATUALIZADO"
}'Response: 204 No Content
Nota: O contratante e contraente geralmente não são alterados após a criação do contrato.
Descrição: Remove um contrato.
Request:
curl -X DELETE http://localhost:5016/api/contratos/1Response: 204 No Content
ContratosAPI/
├── Controllers/ # Controllers da API
│ ├── ContratosController.cs
│ ├── EmpresasController.cs
│ ├── FuncionariosController.cs
│ ├── EstadosController.cs
│ ├── TipoContratoController.cs
│ ├── StatusContratoController.cs
│ └── TipoContraenteController.cs
├── DTOs/ # Data Transfer Objects
│ ├── Common/ # DTOs compartilhados
│ │ ├── CidadeEstadoDTO.cs
│ │ ├── ContatoDTO.cs
│ │ ├── EstadoDTO.cs
│ │ ├── TipoContratoDTO.cs
│ │ ├── StatusContratoDTO.cs
│ │ └── TipoContraenteDTO.cs
│ ├── Empresa/ # DTOs de Empresa
│ │ ├── EmpresaCreateDto.cs
│ │ ├── EmpresaListDto.cs
│ │ ├── EmpresaPutDto.cs
│ │ └── EmpresaResponseDto.cs
│ ├── Funcionario/ # DTOs de Funcionário
│ │ ├── FuncionarioCreateDto.cs
│ │ ├── FuncionarioListDto.cs
│ │ ├── FuncionarioPutDto.cs
│ │ └── FuncionarioResponseDto.cs
│ └── Contrato/ # DTOs de Contrato
│ ├── ContratoCreateDto.cs
│ ├── ContratoListDto.cs
│ ├── ContratoPutDto.cs
│ └── ContratoResponseDto.cs
├── Models/ # Entidades do domínio
│ ├── Empresa.cs
│ ├── Funcionario.cs
│ ├── Contrato.cs
│ ├── Estado.cs
│ ├── TipoContrato.cs
│ ├── StatusContrato.cs
│ ├── TipoContraente.cs
│ ├── CidadeEstado.cs # Owned Entity
│ └── Contato.cs # Owned Entity
├── Data/ # Contexto do banco
│ ├── ApplicationDbContext.cs
│ └── DbContextFactory.cs
├── Mappings/ # Configuração AutoMapper
│ └── AutoMapperProfile.cs
├── Middleware/ # Middlewares customizados
│ └── ErrorHandlingMiddleware.cs
├── Attributes/ # Atributos de validação
│ ├── ContraenteValidacao.cs
│ └── DataNascimentoValidacao.cs
├── Migrations/ # Migrations do EF Core
├── Properties/
│ └── launchSettings.json
├── appsettings.json # Configurações da aplicação
├── docker-compose.yml # Configuração Docker
├── Program.cs # Entry point
└── ContratosAPI.csproj # Arquivo do projeto
Solução:
- Instale o .NET SDK 9.0
- Reinicie o terminal
- Verifique:
dotnet --version
Solução:
- Instale o Docker Desktop
- Inicie o Docker Desktop
- Verifique:
docker --version
Solução:
# Parar o container conflitante
docker ps # Liste os containers
docker stop <container_id> # Pare o container que está usando a porta
# Ou altere a porta no docker-compose.yml:
ports:
- "3307:3306" # Mude 3306 para 3307Solução:
# 1. Verifique se o container está rodando
docker ps
# 2. Verifique os logs do container
docker logs contratos_api
# 3. Reinicie o container
docker-compose down
docker-compose up -d
# 4. Aguarde alguns segundos e tente novamenteSolução:
# Encontre o processo usando a porta
# Windows
netstat -ano | findstr :5016
taskkill /PID <PID> /F
# Linux/Mac
lsof -i :5016
kill -9 <PID>
# Ou altere a porta em Properties/launchSettings.jsonSolução:
# Limpe e restaure o projeto
dotnet clean
dotnet restore
dotnet buildSolução:
# Remova migrações existentes e recrie
rm -rf Migrations
dotnet ef migrations add InitialCreate
dotnet ef database updateSolução:
- Verifique se a aplicação está rodando:
dotnet run - Acesse:
http://localhost:5016/swagger/index.html(nãohttps) - Verifique se não há erros no console
Solução:
Verifique se o AutoMapperProfile está registrado no Program.cs:
builder.Services.AddAutoMapper(typeof(AutoMapperProfile));O banco de dados é populado automaticamente com dados de referência ao executar as migrations:
- 27 estados brasileiros (AC, AL, AM, AP, BA, CE, DF, ES, GO, MA, MG, MS, MT, PA, PB, PE, PI, PR, RJ, RN, RO, RR, RS, SC, SE, SP, TO)
- Prestação de Serviços
- Consultoria
- Parceria Comercial
- Desenvolvimento de Software
- Suporte Técnico
- Manutenção
- Ativo
- Suspenso
- Encerrado
- Empresa (Pessoa Jurídica)
- Funcionário (Pessoa Física)
Se você encontrar problemas ou tiver dúvidas:
- Verifique a seção Troubleshooting
- Consulte a documentação do Swagger:
http://localhost:5016/swagger - Abra uma issue no GitHub (se aplicável)
Este projeto é licenciado sob a MIT License.
- .NET SDK 9.0 instalado
- Docker Desktop instalado e rodando
- Projeto clonado ou extraído
- Container MariaDB iniciado (
docker-compose up -d) - Pacotes NuGet restaurados (
dotnet restore) - Migrations aplicadas (
dotnet ef database update) - Aplicação rodando (
dotnet run) - Swagger acessível em
http://localhost:5016/swagger - Endpoints testados com sucesso
Desenvolvido com ❤️ usando ASP.NET Core 9.0