Skip to content

Commit

Permalink
Merge pull request #279 from JaviFdez7/develop
Browse files Browse the repository at this point in the history
Update Docs Reference
  • Loading branch information
IsmaelHerrera2000 authored Apr 1, 2024
2 parents 4aa0e84 + b77fe37 commit a4c4802
Show file tree
Hide file tree
Showing 8 changed files with 774 additions and 631 deletions.
1 change: 1 addition & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[submodule "docs"]
path = docs
url = https://github.com/Francisco-David/ITTalent-Wiki
branch = main
311 changes: 159 additions & 152 deletions api/v1/modules/team-creator/services/TeamCreatorService.ts
Original file line number Diff line number Diff line change
@@ -1,169 +1,176 @@
import { AnalysisModel,AnalysisDocument } from "../../analysis/models/analysis.model";
import {ProfessionalExperience} from "../../professional-experience/models/professional-experience"
import {Candidate,CandidateDocument} from "../../user/models/user"
import { ProfileRequested,SkillRequested,FilteredCandidates,ProfileMap,TeamCreatorDocument,TeamCreator } from "../models/TeamCreatorModel";
import mongoose from 'mongoose';


import { AnalysisModel, AnalysisDocument } from '../../analysis/models/analysis.model'
import { ProfessionalExperience } from '../../professional-experience/models/professional-experience'
import { Candidate, CandidateDocument } from '../../user/models/user'
import {
ProfileRequested,
SkillRequested,
FilteredCandidates,
ProfileMap,
TeamCreatorDocument,
TeamCreator,
} from '../models/TeamCreatorModel'
import mongoose from 'mongoose'

function processSkillsRequested(profiles: ProfileRequested[]): SkillRequested {
const languagesSet = new Set<string>();
const technologiesSet = new Set<string>();
let minYearsOfExperience = profiles.length > 0 ? profiles[0].yearsOfExperience : 0;
const fieldsSet = new Set<string>();
profiles.forEach(profile => {
profile.languages.forEach(language => languagesSet.add(language));
profile.technologies.forEach(technology => technologiesSet.add(technology));
if (profile.yearsOfExperience < minYearsOfExperience) {
minYearsOfExperience = profile.yearsOfExperience;
}
fieldsSet.add(profile.field);
});


return {
languages: Array.from(languagesSet),
technologies: Array.from(technologiesSet),
yearsOfExperience: minYearsOfExperience,
field: Array.from(fieldsSet)
};
const languagesSet = new Set<string>()
const technologiesSet = new Set<string>()
let minYearsOfExperience = profiles.length > 0 ? profiles[0].yearsOfExperience : 0
const fieldsSet = new Set<string>()
profiles.forEach((profile) => {
profile.languages.forEach((language) => languagesSet.add(language))
profile.technologies.forEach((technology) => technologiesSet.add(technology))
if (profile.yearsOfExperience < minYearsOfExperience) {
minYearsOfExperience = profile.yearsOfExperience
}
fieldsSet.add(profile.field)
})

return {
languages: Array.from(languagesSet),
technologies: Array.from(technologiesSet),
yearsOfExperience: minYearsOfExperience,
field: Array.from(fieldsSet),
}
}
async function filterCandidates(skillsRequested: SkillRequested): Promise<FilteredCandidates[]> {

const candidates = await Candidate.find()
.populate('analysisId')
.populate('profesionalExperiences')
.exec() as unknown as CandidateDocument[];

const qualifiedCandidates: FilteredCandidates[] = [];

candidates.forEach(candidate => {
const hasMatchingSkill = candidate.analysisId.globalTopLanguages.some(lang => skillsRequested.languages.includes(lang.language)) || candidate.analysisId.globalTechnologies.some(tech => skillsRequested.technologies.includes(tech));

let totalExperienceYears = 0;
let matchesField = false;

candidate.profesionalExperiences.forEach(exp => {
const startDate = new Date(exp.startDate);
const endDate = exp.endDate ? new Date(exp.endDate) : new Date();
const years = endDate.getFullYear() - startDate.getFullYear();
const monthDiff = endDate.getMonth() - startDate.getMonth();
if (years > 0 || monthDiff > 0) {
totalExperienceYears += years + monthDiff / 12;
}

if (skillsRequested.field.includes(exp.professionalArea)) {
matchesField = true;
}
});

if (hasMatchingSkill || (matchesField && totalExperienceYears >= skillsRequested.yearsOfExperience)) {
const filteredLanguages = candidate.analysisId.globalTopLanguages
.map(lang => lang.language)
.filter(lang => skillsRequested.languages.includes(lang));

const filteredTechnologies = candidate.analysisId.globalTechnologies
.filter(tech => skillsRequested.technologies.includes(tech));

qualifiedCandidates.push({
github_username: candidate.githubUser,
languages: filteredLanguages,
technologies: filteredTechnologies,
yearsOfExperience: totalExperienceYears,
field: skillsRequested.field
});
}
});
return qualifiedCandidates;
const candidates = (await Candidate.find()
.populate('analysisId')
.populate('profesionalExperiences')
.exec()) as unknown as CandidateDocument[]

const qualifiedCandidates: FilteredCandidates[] = []

candidates.forEach((candidate) => {
console.log(candidate.analysisId.globalTopLanguages)
const hasMatchingSkill =
candidate.analysisId.globalTopLanguages.some((lang) =>
skillsRequested.languages.includes(lang.language)
) ||
candidate.analysisId.globalTechnologies.some((tech) =>
skillsRequested.technologies.includes(tech)
)

let totalExperienceYears = 0
let matchesField = false

candidate.profesionalExperiences.forEach((exp) => {
const startDate = new Date(exp.startDate)
const endDate = exp.endDate ? new Date(exp.endDate) : new Date()
const years = endDate.getFullYear() - startDate.getFullYear()
const monthDiff = endDate.getMonth() - startDate.getMonth()
if (years > 0 || monthDiff > 0) {
totalExperienceYears += years + monthDiff / 12
}

if (skillsRequested.field.includes(exp.professionalArea)) {
matchesField = true
}
})

if (
hasMatchingSkill ||
(matchesField && totalExperienceYears >= skillsRequested.yearsOfExperience)
) {
const filteredLanguages = candidate.analysisId.globalTopLanguages
.map((lang) => lang.language)
.filter((lang) => skillsRequested.languages.includes(lang))

const filteredTechnologies = candidate.analysisId.globalTechnologies.filter((tech) =>
skillsRequested.technologies.includes(tech)
)

qualifiedCandidates.push({
github_username: candidate.githubUser,
languages: filteredLanguages,
technologies: filteredTechnologies,
yearsOfExperience: totalExperienceYears,
field: skillsRequested.field,
})
}
})
return qualifiedCandidates
}

function selectBestCandidates(filteredCandidates: FilteredCandidates[], profilesRequested: ProfileRequested[]): Map<ProfileRequested, FilteredCandidates[]> {
const bestCandidatesPerProfile = new Map<ProfileRequested, FilteredCandidates[]>();

for (const profile of profilesRequested) {
let maxScore = 0;
const candidatesScores: Map<FilteredCandidates, number> = new Map();

for (const candidate of filteredCandidates) {
let score = 0;
candidate.languages.forEach(lang => {
if (profile.languages.includes(lang)) score++;
});
candidate.technologies.forEach(tech => {
if (profile.technologies.includes(tech)) score++;
});
if (candidate.yearsOfExperience >= profile.yearsOfExperience) score++;
if (candidate.field.includes(profile.field)) score++;
candidatesScores.set(candidate, score);
}
const sortedCandidates = Array.from(candidatesScores.entries())
.sort((a, b) => b[1] - a[1])
.slice(0, 3)
.map(entry => entry[0]);

bestCandidatesPerProfile.set(profile, sortedCandidates);
}


return bestCandidatesPerProfile;
function selectBestCandidates(
filteredCandidates: FilteredCandidates[],
profilesRequested: ProfileRequested[]
): Map<ProfileRequested, FilteredCandidates[]> {
const bestCandidatesPerProfile = new Map<ProfileRequested, FilteredCandidates[]>()

for (const profile of profilesRequested) {
let maxScore = 0
const candidatesScores: Map<FilteredCandidates, number> = new Map()

for (const candidate of filteredCandidates) {
let score = 0
candidate.languages.forEach((lang) => {
if (profile.languages.includes(lang)) score++
})
candidate.technologies.forEach((tech) => {
if (profile.technologies.includes(tech)) score++
})
if (candidate.yearsOfExperience >= profile.yearsOfExperience) score++
if (candidate.field.includes(profile.field)) score++
candidatesScores.set(candidate, score)
}
const sortedCandidates = Array.from(candidatesScores.entries())
.sort((a, b) => b[1] - a[1])
.slice(0, 3)
.map((entry) => entry[0])

bestCandidatesPerProfile.set(profile, sortedCandidates)
}

return bestCandidatesPerProfile
}
async function saveTeamCreator(userId: string, profilesMap: ProfileMap): Promise<void> {
const profiles = Array.from(profilesMap).map(([profileRequested, recommendedCandidates]) => ({
profileRequested,
recommendedCandidates
}));


const teamCreator = new TeamCreator({
userId,
profiles
});

await teamCreator.save();
}
export const createTeamCreator: any = async (data: ProfileRequested[],userId: string) => {

const skills: SkillRequested = processSkillsRequested(data);
const filteredcandidates: FilteredCandidates[] = await filterCandidates(skills);
const selectCandidates: ProfileMap = selectBestCandidates(filteredcandidates,data);
await saveTeamCreator(userId,selectCandidates);
const profiles = Array.from(profilesMap).map(([profileRequested, recommendedCandidates]) => ({
profileRequested,
recommendedCandidates,
}))

const teamCreator = new TeamCreator({
userId,
profiles,
})

};
await teamCreator.save()
}
export const createTeamCreator: any = async (data: ProfileRequested[], userId: string) => {
const skills: SkillRequested = processSkillsRequested(data)
const filteredcandidates: FilteredCandidates[] = await filterCandidates(skills)
const selectCandidates: ProfileMap = selectBestCandidates(filteredcandidates, data)
await saveTeamCreator(userId, selectCandidates)
}
export const getAllTeamCreatorOfRepresentative: any = async (id: any) => {

try {
const result = await TeamCreator.find({ userId: id }).exec();
return result;
} catch (err) {
console.error(err);
}
};

try {
const result = await TeamCreator.find({ userId: id }).exec()
return result
} catch (err) {
console.error(err)
}
}

export const deleteTeamCreator: any = async (id: any) => {

try {
const result = await TeamCreator.findByIdAndDelete(id);
} catch (err) {
console.error(err);
}
};
try {
const result = await TeamCreator.findByIdAndDelete(id)
} catch (err) {
console.error(err)
}
}

export const getTeamCreatorById: any = async (id: any) => {

try {
const result = await TeamCreator.findById(id);
return result;
} catch (err) {
console.error(err);
}
};

try {
const result = await TeamCreator.findById(id)
return result
} catch (err) {
console.error(err)
}
}

export default {
getAllTeamCreatorOfRepresentative,
createTeamCreator,
deleteTeamCreator,
getTeamCreatorById
};
getAllTeamCreatorOfRepresentative,
createTeamCreator,
deleteTeamCreator,
getTeamCreatorById,
}
11 changes: 11 additions & 0 deletions api/v1/modules/user/middlewares/UserMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,17 @@ export const checkCreateCandidate: any = async (
ApiResponse.sendError(res, [{ title: 'Bad Request', detail: message }], 400)
return
}
const response = await fetch(`https://api.github.com/users/${data.githubUser ?? ''}`)

if (response.status === 404) {
ApiResponse.sendError(res, [
{
title: 'Internal Server Error',
detail: 'GitHub username does not exist.',
},
])
return
}

// Comprobar si el candidato ya existe
const existingUsername = await User.findOne({ username: data.username })
Expand Down
8 changes: 4 additions & 4 deletions api/v1/modules/user/services/UserService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ export const getProfessionalExperiencesByUserId: any = async (userId: any) => {
export const createUser: any = async (data: any, role: string) => {
try {
const Model = getModelForRole(role)
if (role === 'Candidate') {
const analysis = await createAnalysis(data?.githubUser, data?.githubToken)
data.analysisId = analysis._id
}
const user = new Model(data)
await user.save()
return user
Expand All @@ -33,10 +37,6 @@ export const createUser: any = async (data: any, role: string) => {
export const updateUser: any = async (id: any, data: any, role: string) => {
try {
const Model = getModelForRole(role) as typeof User
if (role === 'Candidate') {
const analysis = await createAnalysis(data?.githubUser, data?.githubToken)
data.analysisId = analysis._id
}
const { password, profilePicture, ...editableDetails } = data
const updatedUser = await Model.findByIdAndUpdate(id, editableDetails, { new: true })
return updatedUser
Expand Down
Loading

0 comments on commit a4c4802

Please sign in to comment.