Projeto: Global Solution FIAP 2025
Instituição: FIAP - Faculdade de Informática e Administração Paulista
Curso: Análise e Desenvolvimento de Sistemas
| RM | Nome |
|---|---|
| RM556152 | Daniel da Silva Barros |
| RM558253 | Luccas de Alencar Rufino |
| RM5550063 | Raul Clauson |
Sistema backend em .NET 8 que gerencia currículos de candidatos, integrando-se com uma API Python de IA para análise inteligente de ocupações e extração de skills.
graph TB
A["Frontend<br/>HTML/CSS/JS<br/>LiveServer"] -->|HTTP| B["ASP.NET Core 8<br/>API REST<br/>porta 5000"]
B --> C["PdfTextExtractor<br/>Extrai texto"]
C --> D["PDF Upload"]
B --> E["ResumeService<br/>Orquestrador"]
E --> F["Python API<br/>Flask<br/>porta 5001"]
F --> G["SkillExtractionService<br/>BERT + Regex"]
F --> H["OccupationInferenceService<br/>CBO Dataset"]
B --> I["UserService<br/>Gestão de Users"]
B --> J["JobService<br/>Busca Adzuna"]
I --> K["Oracle Database<br/>on-premises<br/>oracle.fiap.com.br"]
B -->|JSON| A
F -->|JSON| B
style B fill:#512BD4,color:#fff
style A fill:#4CAF50,color:#fff
style F fill:#4CAF50,color:#fff
style K fill:#FF6F00,color:#fff
Instale:
cd c:/Users/seu_usuario/Desktop/entregas-gs
git clone <url_repositorio>
cd dotnet-gs2-2025
Crie arquivo .env na raiz do projeto com as credenciais:
# ============================================
# ADZUNA API
# ============================================
ADZUNA_APP_ID=
ADZUNA_APP_KEY=
# ============================================
# HUGGING FACE
# ============================================
HUGGINGFACE__TOKEN=
# ============================================
# ORACLE DATABASE (On-Premises)
# ============================================
ORACLE_USER_ID=
ORACLE_PASSWORD=
ORACLE_DATA_SOURCE=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=oracle.fiap.com.br)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=orcl)))
dotnet restore
dotnet build
dotnet run
Esperado:
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5000
A API estará disponível em http://localhost:5000
http://localhost:5000/api/v1/users)POST /users
Content-Type: application/json
{
"name": "João Silva",
"email": "joao@example.com",
"password": "senha_segura_123",
"phone": "11999999999"
}
Resposta: 201 Created
{
"id": 1,
"name": "João Silva",
"email": "joao@example.com",
"phone": "11999999999",
"createdAt": "2025-11-20T18:30:00Z",
"updatedAt": "2025-11-20T18:30:00Z"
}
GET /users
Resposta: 200 OK
[
{
"id": 1,
"name": "João Silva",
"email": "joao@example.com",
"phone": "11999999999"
}
]
GET /users/{id}
PUT /users/{id}
Content-Type: application/json
{
"name": "João Silva Santos",
"email": "novo@example.com",
"phone": "11988888888"
}
DELETE /users/{id}
/resumes)POST /resumes/analyze
Content-Type: multipart/form-data
[Form Data]
file: <arquivo PDF>
Resposta: 200 OK
{
"status": "success",
"resumeType": "technical",
"primaryOccupation": {
"titulo": "Desenvolvedor Python",
"codigo": "317105",
"score": 0.92,
"confidence": "high"
},
"skills": [
{
"skillName": "programação python",
"originalSkill": "Python",
"score": 0.95,
"confidence": "high"
}
],
"totalSkillsFound": 12,
"successfulMatches": 10,
"processingTime": 2.345
}
POST /resumes/skills
Content-Type: multipart/form-data
[Form Data]
file: <arquivo PDF>
Resposta: 200 OK
{
"skills": ["Python", "Django", "PostgreSQL", "Docker", "AWS"],
"totalSkills": 5,
"textLength": 1250,
"metadata": {
"fileName": "curriculo.pdf",
"fileSizeBytes": 45000
}
}
POST /resumes/infer-primary-occupation
Content-Type: application/json
{
"resumeText": "Trabalho como desenvolvedor full-stack há 5 anos..."
}
Resposta: 200 OK
{
"status": "success",
"primaryOccupation": {
"titulo": "Desenvolvedor Full Stack",
"codigo": "317115",
"score": 0.88,
"confidence": "high"
},
"processingTime": 0.567
}
POST /resumes/match-profile
Content-Type: application/json
{
"candidateSkills": ["Python", "Django", "PostgreSQL"],
"jobRequirements": ["Python", "Django", "AWS", "Docker"]
}
Resposta: 200 OK
{
"matchScore": 0.75,
"matchPercentage": "75%",
"level": "BOM - Candidato bem qualificado",
"matchedSkills": ["Python", "Django"],
"matchedCount": 2,
"missingSkills": ["AWS", "Docker"],
"missingCount": 2,
"analysis": {
"strengths": "Possui 2 das 4 skills requeridas",
"gaps": "Faltam 2 skills",
"recommendation": "Forte candidato"
}
}
/jobs)POST /jobs/search
Content-Type: application/json
{
"occupation": "Desenvolvedor Python",
"location": "São Paulo",
"page": 1
}
Resposta: 200 OK
{
"jobs": [
{
"id": "123456",
"title": "Desenvolvedor Python Senior",
"company": "Tech Company",
"location": "São Paulo, SP",
"salary": "R$ 8.000 - R$ 12.000",
"description": "Procuramos desenvolvedor Python com experiência...",
"link": "https://www.adzuna.com.br/job/123456"
}
],
"totalResults": 45,
"page": 1,
"pageSize": 10
}
/health)GET /health
Resposta: 200 OK
{
"status": "Healthy",
"checks": {
"oracle-database": {
"status": "Healthy",
"description": "Oracle Database connection is healthy"
}
},
"timestamp": "2025-11-20T18:30:00Z"
}
A API Python deve estar rodando em http://localhost:5001
# Terminal 1: Python
cd ia-gs2-2025/api
chmod +x *.sh
./install.sh
python run.py
# Terminal 2: .NET
cd dotnet-gs2-2025
dotnet restore
dotnet build
dotnet run
sequenceDiagram
participant User as Usuário
participant Frontend as Frontend<br/>HTML/CSS/JS
participant DotNet as API .NET<br/>ASP.NET Core
participant Python as API Python<br/>Flask
participant CBO as Dataset CBO
User->>Frontend: 1. Seleciona PDF
Frontend->>DotNet: 2. POST /resumes/analyze
DotNet->>DotNet: 3. Extrai texto PDF
DotNet->>Python: 4. POST /analyze-resume
Python->>CBO: 5. Busca ocupação
Python->>CBO: 6. Busca skills
Python-->>DotNet: 7. Retorna resultado
DotNet->>DotNet: 8. Formata resposta
DotNet-->>Frontend: 9. JSON com ocupação + skills
Frontend-->>User: 10. Exibe na tela
O serviço já está configurado em ResumeService.cs:
// HTTP Client com timeout de 180s
client.BaseAddress = new Uri("http://localhost:5001");
client.Timeout = TimeSpan.FromSeconds(180);
// Chamar endpoint Python
var response = await _httpClient.PostAsync(
"/api/v1/analyze-resume",
content
);
dotnet-gs2-2025/frontend/index.html| Tecnologia | Versão | Uso |
|---|---|---|
| .NET | 8.0 | Framework principal |
| ASP.NET Core | 8.0 | Web API |
| Entity Framework Core | 8.0 | ORM |
| Oracle.EntityFrameworkCore | 8.23 | Driver Oracle |
| Serilog | Latest | Logging |
| DotNetEnv | Latest | Carregamento .env |
| OpenTelemetry | Latest | Tracing |
| HealthChecks | Latest | Health Check |
| HttpClient | Built-in | Chamadas HTTP |
dotnet-gs2-2025/
├── Controllers/
│ ├── HealthController.cs
│ ├── V1/
│ │ ├── ResumesController.cs ⭐ Upload + Análise
│ │ ├── UsersController.cs 👤 Gestão usuários
│ │ └── JobsController.cs 🔍 Busca vagas
│ └── V2/
│ └── UsersController.cs (versioning)
├── Services/
│ ├── ResumeService.cs ⭐ Orquestrador
│ ├── HuggingFaceService.cs 🤖 Chamadas Python
│ ├── PdfTextExtractor.cs 📄 Extração PDF
│ ├── UserService.cs
│ ├── AdzunaService.cs 🔍 Integração vagas
│ └── JobSuggestionService.cs
├── Models/
│ ├── User.cs 👤 Nome, Email, Telefone, Senha
│ ├── HuggingFaceEntity.cs
│ ├── ResumeExtraction.cs
│ └── DTOs/
├── Repositories/
│ ├── IUserRepository.cs
│ └── UserRepository.cs
├── Data/
│ ├── ApplicationDbContext.cs
│ └── Migrations/
├── Configuration/
│ └── HuggingFaceOptions.cs
├── frontend/
│ ├── index.html 🌐 Interface
│ ├── script.js 📱 Lógica
│ └── style.css 🎨 Estilos
├── Properties/
│ └── launchSettings.json ⚙️ Portas (5000)
├── logs/ 📋 Logs da aplicação
├── .env 🔐 Variáveis ambiente
├── .env.example 📋 Exemplo .env
├── appsettings.json 📋 Configurações
├── appsettings.Development.json 📋 Config desenvolvimento
├── Program.cs ⚙️ Startup
└── dotnet-gs2-2025.csproj 📦 Projeto
{
"ConnectionStrings": {
"OracleConnection": ""
},
"Adzuna": {
"AppId": "",
"AppKey": ""
},
"HuggingFace": {
"SkillsModel": "gpt2",
"LocationsModel": "dslim/bert-base-NER",
"Token": "",
"MinScore": 0.9,
"PythonSkillsApiUrl": "http://localhost:5001/api/v1/skills"
},
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.AspNetCore": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "logs/api-.log",
"rollingInterval": "Day",
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {Level:u3}] {Message:lj}{NewLine}{Exception}"
}
}
]
},
"AllowedHosts": "*"
}
As credenciais são carregadas do arquivo .env na raiz do projeto:
Abra no navegador: http://localhost:5000
Swagger UI mostrará todos os endpoints documentados
Abra no navegador: http://127.0.0.1:5500/dotnet-gs2-2025/frontend/
No site é só fazer o upload do curriculo em pdf
✅ Solução:
1. Verifique as credenciais no .env
2. Teste conexão: ping oracle.fiap.com.br
3. Verifique porta 1521 aberta
✅ Solução: Verifique se Python está rodando em localhost:5001
python run.py
✅ Solução: CORS está habilitado para qualquer origem
Se persistir, verifique launchSettings.json
✅ Solução: Reinstale .NET 8 SDK
https://dotnet.microsoft.com/download/dotnet/8.0
✅ Solução: Altere em launchSettings.json
"applicationUrl": "http://localhost:5002"
| Operação | Tempo |
|---|---|
| Upload + Análise | 2-4s |
| Extração skills | 1-2s |
| Busca ocupação | 0.5-1s |
| Busca vagas Adzuna | 1-2s |
| Health Check | <100ms |
.env criado com credenciais corretasdotnet restore executado com sucessodotnet build compilado com sucesso (0 errors)dotnet run iniciadoPrecisa de ajuda?
logs/ folder/health para status dos serviçosappsettings.json e .envC#
90.2%
JavaScript
6.2%
CSS
2.2%
HTML
1.4%
Projeto: Global Solution FIAP 2025
Instituição: FIAP - Faculdade de Informática e Administração Paulista
Curso: Análise e Desenvolvimento de Sistemas
| RM | Nome |
|---|---|
| RM556152 | Daniel da Silva Barros |
| RM558253 | Luccas de Alencar Rufino |
| RM5550063 | Raul Clauson |
Sistema backend em .NET 8 que gerencia currículos de candidatos, integrando-se com uma API Python de IA para análise inteligente de ocupações e extração de skills.
graph TB
A["Frontend<br/>HTML/CSS/JS<br/>LiveServer"] -->|HTTP| B["ASP.NET Core 8<br/>API REST<br/>porta 5000"]
B --> C["PdfTextExtractor<br/>Extrai texto"]
C --> D["PDF Upload"]
B --> E["ResumeService<br/>Orquestrador"]
E --> F["Python API<br/>Flask<br/>porta 5001"]
F --> G["SkillExtractionService<br/>BERT + Regex"]
F --> H["OccupationInferenceService<br/>CBO Dataset"]
B --> I["UserService<br/>Gestão de Users"]
B --> J["JobService<br/>Busca Adzuna"]
I --> K["Oracle Database<br/>on-premises<br/>oracle.fiap.com.br"]
B -->|JSON| A
F -->|JSON| B
style B fill:#512BD4,color:#fff
style A fill:#4CAF50,color:#fff
style F fill:#4CAF50,color:#fff
style K fill:#FF6F00,color:#fff
Instale:
cd c:/Users/seu_usuario/Desktop/entregas-gs
git clone <url_repositorio>
cd dotnet-gs2-2025
Crie arquivo .env na raiz do projeto com as credenciais:
# ============================================
# ADZUNA API
# ============================================
ADZUNA_APP_ID=
ADZUNA_APP_KEY=
# ============================================
# HUGGING FACE
# ============================================
HUGGINGFACE__TOKEN=
# ============================================
# ORACLE DATABASE (On-Premises)
# ============================================
ORACLE_USER_ID=
ORACLE_PASSWORD=
ORACLE_DATA_SOURCE=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=oracle.fiap.com.br)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=orcl)))
dotnet restore
dotnet build
dotnet run
Esperado:
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5000
A API estará disponível em http://localhost:5000
http://localhost:5000/api/v1/users)POST /users
Content-Type: application/json
{
"name": "João Silva",
"email": "joao@example.com",
"password": "senha_segura_123",
"phone": "11999999999"
}
Resposta: 201 Created
{
"id": 1,
"name": "João Silva",
"email": "joao@example.com",
"phone": "11999999999",
"createdAt": "2025-11-20T18:30:00Z",
"updatedAt": "2025-11-20T18:30:00Z"
}
GET /users
Resposta: 200 OK
[
{
"id": 1,
"name": "João Silva",
"email": "joao@example.com",
"phone": "11999999999"
}
]
GET /users/{id}
PUT /users/{id}
Content-Type: application/json
{
"name": "João Silva Santos",
"email": "novo@example.com",
"phone": "11988888888"
}
DELETE /users/{id}
/resumes)POST /resumes/analyze
Content-Type: multipart/form-data
[Form Data]
file: <arquivo PDF>
Resposta: 200 OK
{
"status": "success",
"resumeType": "technical",
"primaryOccupation": {
"titulo": "Desenvolvedor Python",
"codigo": "317105",
"score": 0.92,
"confidence": "high"
},
"skills": [
{
"skillName": "programação python",
"originalSkill": "Python",
"score": 0.95,
"confidence": "high"
}
],
"totalSkillsFound": 12,
"successfulMatches": 10,
"processingTime": 2.345
}
POST /resumes/skills
Content-Type: multipart/form-data
[Form Data]
file: <arquivo PDF>
Resposta: 200 OK
{
"skills": ["Python", "Django", "PostgreSQL", "Docker", "AWS"],
"totalSkills": 5,
"textLength": 1250,
"metadata": {
"fileName": "curriculo.pdf",
"fileSizeBytes": 45000
}
}
POST /resumes/infer-primary-occupation
Content-Type: application/json
{
"resumeText": "Trabalho como desenvolvedor full-stack há 5 anos..."
}
Resposta: 200 OK
{
"status": "success",
"primaryOccupation": {
"titulo": "Desenvolvedor Full Stack",
"codigo": "317115",
"score": 0.88,
"confidence": "high"
},
"processingTime": 0.567
}
POST /resumes/match-profile
Content-Type: application/json
{
"candidateSkills": ["Python", "Django", "PostgreSQL"],
"jobRequirements": ["Python", "Django", "AWS", "Docker"]
}
Resposta: 200 OK
{
"matchScore": 0.75,
"matchPercentage": "75%",
"level": "BOM - Candidato bem qualificado",
"matchedSkills": ["Python", "Django"],
"matchedCount": 2,
"missingSkills": ["AWS", "Docker"],
"missingCount": 2,
"analysis": {
"strengths": "Possui 2 das 4 skills requeridas",
"gaps": "Faltam 2 skills",
"recommendation": "Forte candidato"
}
}
/jobs)POST /jobs/search
Content-Type: application/json
{
"occupation": "Desenvolvedor Python",
"location": "São Paulo",
"page": 1
}
Resposta: 200 OK
{
"jobs": [
{
"id": "123456",
"title": "Desenvolvedor Python Senior",
"company": "Tech Company",
"location": "São Paulo, SP",
"salary": "R$ 8.000 - R$ 12.000",
"description": "Procuramos desenvolvedor Python com experiência...",
"link": "https://www.adzuna.com.br/job/123456"
}
],
"totalResults": 45,
"page": 1,
"pageSize": 10
}
/health)GET /health
Resposta: 200 OK
{
"status": "Healthy",
"checks": {
"oracle-database": {
"status": "Healthy",
"description": "Oracle Database connection is healthy"
}
},
"timestamp": "2025-11-20T18:30:00Z"
}
A API Python deve estar rodando em http://localhost:5001
# Terminal 1: Python
cd ia-gs2-2025/api
chmod +x *.sh
./install.sh
python run.py
# Terminal 2: .NET
cd dotnet-gs2-2025
dotnet restore
dotnet build
dotnet run
sequenceDiagram
participant User as Usuário
participant Frontend as Frontend<br/>HTML/CSS/JS
participant DotNet as API .NET<br/>ASP.NET Core
participant Python as API Python<br/>Flask
participant CBO as Dataset CBO
User->>Frontend: 1. Seleciona PDF
Frontend->>DotNet: 2. POST /resumes/analyze
DotNet->>DotNet: 3. Extrai texto PDF
DotNet->>Python: 4. POST /analyze-resume
Python->>CBO: 5. Busca ocupação
Python->>CBO: 6. Busca skills
Python-->>DotNet: 7. Retorna resultado
DotNet->>DotNet: 8. Formata resposta
DotNet-->>Frontend: 9. JSON com ocupação + skills
Frontend-->>User: 10. Exibe na tela
O serviço já está configurado em ResumeService.cs:
// HTTP Client com timeout de 180s
client.BaseAddress = new Uri("http://localhost:5001");
client.Timeout = TimeSpan.FromSeconds(180);
// Chamar endpoint Python
var response = await _httpClient.PostAsync(
"/api/v1/analyze-resume",
content
);
dotnet-gs2-2025/frontend/index.html| Tecnologia | Versão | Uso |
|---|---|---|
| .NET | 8.0 | Framework principal |
| ASP.NET Core | 8.0 | Web API |
| Entity Framework Core | 8.0 | ORM |
| Oracle.EntityFrameworkCore | 8.23 | Driver Oracle |
| Serilog | Latest | Logging |
| DotNetEnv | Latest | Carregamento .env |
| OpenTelemetry | Latest | Tracing |
| HealthChecks | Latest | Health Check |
| HttpClient | Built-in | Chamadas HTTP |
dotnet-gs2-2025/
├── Controllers/
│ ├── HealthController.cs
│ ├── V1/
│ │ ├── ResumesController.cs ⭐ Upload + Análise
│ │ ├── UsersController.cs 👤 Gestão usuários
│ │ └── JobsController.cs 🔍 Busca vagas
│ └── V2/
│ └── UsersController.cs (versioning)
├── Services/
│ ├── ResumeService.cs ⭐ Orquestrador
│ ├── HuggingFaceService.cs 🤖 Chamadas Python
│ ├── PdfTextExtractor.cs 📄 Extração PDF
│ ├── UserService.cs
│ ├── AdzunaService.cs 🔍 Integração vagas
│ └── JobSuggestionService.cs
├── Models/
│ ├── User.cs 👤 Nome, Email, Telefone, Senha
│ ├── HuggingFaceEntity.cs
│ ├── ResumeExtraction.cs
│ └── DTOs/
├── Repositories/
│ ├── IUserRepository.cs
│ └── UserRepository.cs
├── Data/
│ ├── ApplicationDbContext.cs
│ └── Migrations/
├── Configuration/
│ └── HuggingFaceOptions.cs
├── frontend/
│ ├── index.html 🌐 Interface
│ ├── script.js 📱 Lógica
│ └── style.css 🎨 Estilos
├── Properties/
│ └── launchSettings.json ⚙️ Portas (5000)
├── logs/ 📋 Logs da aplicação
├── .env 🔐 Variáveis ambiente
├── .env.example 📋 Exemplo .env
├── appsettings.json 📋 Configurações
├── appsettings.Development.json 📋 Config desenvolvimento
├── Program.cs ⚙️ Startup
└── dotnet-gs2-2025.csproj 📦 Projeto
{
"ConnectionStrings": {
"OracleConnection": ""
},
"Adzuna": {
"AppId": "",
"AppKey": ""
},
"HuggingFace": {
"SkillsModel": "gpt2",
"LocationsModel": "dslim/bert-base-NER",
"Token": "",
"MinScore": 0.9,
"PythonSkillsApiUrl": "http://localhost:5001/api/v1/skills"
},
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.AspNetCore": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "logs/api-.log",
"rollingInterval": "Day",
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {Level:u3}] {Message:lj}{NewLine}{Exception}"
}
}
]
},
"AllowedHosts": "*"
}
As credenciais são carregadas do arquivo .env na raiz do projeto:
Abra no navegador: http://localhost:5000
Swagger UI mostrará todos os endpoints documentados
Abra no navegador: http://127.0.0.1:5500/dotnet-gs2-2025/frontend/
No site é só fazer o upload do curriculo em pdf
✅ Solução:
1. Verifique as credenciais no .env
2. Teste conexão: ping oracle.fiap.com.br
3. Verifique porta 1521 aberta
✅ Solução: Verifique se Python está rodando em localhost:5001
python run.py
✅ Solução: CORS está habilitado para qualquer origem
Se persistir, verifique launchSettings.json
✅ Solução: Reinstale .NET 8 SDK
https://dotnet.microsoft.com/download/dotnet/8.0
✅ Solução: Altere em launchSettings.json
"applicationUrl": "http://localhost:5002"
| Operação | Tempo |
|---|---|
| Upload + Análise | 2-4s |
| Extração skills | 1-2s |
| Busca ocupação | 0.5-1s |
| Busca vagas Adzuna | 1-2s |
| Health Check | <100ms |
.env criado com credenciais corretasdotnet restore executado com sucessodotnet build compilado com sucesso (0 errors)dotnet run iniciadoPrecisa de ajuda?
logs/ folder/health para status dos serviçosappsettings.json e .envC#
90.2%
JavaScript
6.2%
CSS
2.2%
HTML
1.4%