feat: review my team page with importance
This commit is contained in:
@@ -32,6 +32,7 @@ export class TeamReviewService {
|
||||
s.id as skill_id,
|
||||
s.name as skill_name,
|
||||
s.icon,
|
||||
s.importance,
|
||||
sc.name as category
|
||||
FROM skill_categories sc
|
||||
JOIN skills s ON s.category_id = sc.id
|
||||
@@ -54,6 +55,7 @@ export class TeamReviewService {
|
||||
u.email,
|
||||
s.id as skill_id,
|
||||
s.name as skill_name,
|
||||
s.importance,
|
||||
sc.name as category,
|
||||
se.level,
|
||||
se.can_mentor,
|
||||
@@ -97,6 +99,7 @@ export class TeamReviewService {
|
||||
skillId: row.skill_id,
|
||||
skillName: row.skill_name,
|
||||
category: row.category,
|
||||
importance: row.importance || "standard",
|
||||
level: row.level as SkillLevel,
|
||||
canMentor: row.can_mentor || false,
|
||||
wantsToLearn: row.wants_to_learn || false,
|
||||
@@ -140,22 +143,28 @@ export class TeamReviewService {
|
||||
const coverage =
|
||||
totalTeamMembers > 0 ? (teamMembers / totalTeamMembers) * 100 : 0;
|
||||
|
||||
// Déterminer le niveau de risque en fonction de l'importance
|
||||
const risk =
|
||||
skill.importance === "incontournable" && experts === 0
|
||||
? "high"
|
||||
: skill.importance === "majeure" && experts === 0 && mentors === 0
|
||||
? "high"
|
||||
: experts === 0 && mentors === 0
|
||||
? "medium"
|
||||
: "low";
|
||||
|
||||
return {
|
||||
skillId: skill.skill_id,
|
||||
skillName: skill.skill_name,
|
||||
category: skill.category,
|
||||
icon: skill.icon,
|
||||
importance: skill.importance || "standard",
|
||||
team_members: teamMembers,
|
||||
experts,
|
||||
mentors,
|
||||
learners,
|
||||
coverage,
|
||||
risk:
|
||||
experts === 0 && mentors === 0
|
||||
? "high"
|
||||
: experts === 0 || mentors === 0
|
||||
? "medium"
|
||||
: "low",
|
||||
risk,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -172,6 +181,10 @@ export class TeamReviewService {
|
||||
mentors: 0,
|
||||
learners: 0,
|
||||
coverage: 0,
|
||||
criticalSkillsCoverage: {
|
||||
incontournable: 0,
|
||||
majeure: 0,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -186,6 +199,17 @@ export class TeamReviewService {
|
||||
categoryStats.experts += skillGap.experts;
|
||||
categoryStats.mentors += skillGap.mentors;
|
||||
categoryStats.learners += skillGap.learners;
|
||||
|
||||
// Calculer la couverture des compétences critiques
|
||||
if (
|
||||
skillGap.importance === "incontournable" &&
|
||||
skillGap.coverage > 50
|
||||
) {
|
||||
categoryStats.criticalSkillsCoverage.incontournable++;
|
||||
}
|
||||
if (skillGap.importance === "majeure" && skillGap.coverage > 50) {
|
||||
categoryStats.criticalSkillsCoverage.majeure++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,6 +232,28 @@ export class TeamReviewService {
|
||||
);
|
||||
|
||||
// 8. Calculer les statistiques globales
|
||||
const criticalSkillsCoverage = {
|
||||
incontournable:
|
||||
(skillGaps
|
||||
.filter((gap) => gap.importance === "incontournable")
|
||||
.reduce((acc, gap) => acc + (gap.coverage > 50 ? 1 : 0), 0) /
|
||||
Math.max(
|
||||
1,
|
||||
skillGaps.filter((gap) => gap.importance === "incontournable")
|
||||
.length
|
||||
)) *
|
||||
100,
|
||||
majeure:
|
||||
(skillGaps
|
||||
.filter((gap) => gap.importance === "majeure")
|
||||
.reduce((acc, gap) => acc + (gap.coverage > 50 ? 1 : 0), 0) /
|
||||
Math.max(
|
||||
1,
|
||||
skillGaps.filter((gap) => gap.importance === "majeure").length
|
||||
)) *
|
||||
100,
|
||||
};
|
||||
|
||||
const stats = {
|
||||
totalMembers: membersMap.size,
|
||||
totalSkills: skillGaps.length,
|
||||
@@ -221,6 +267,7 @@ export class TeamReviewService {
|
||||
0
|
||||
),
|
||||
learningNeeds: skillGaps.filter((gap) => gap.risk === "high").length,
|
||||
criticalSkillsCoverage,
|
||||
};
|
||||
|
||||
await client.query("COMMIT");
|
||||
@@ -249,25 +296,43 @@ export class TeamReviewService {
|
||||
): string[] {
|
||||
const recommendations: string[] = [];
|
||||
|
||||
// Analyser les gaps critiques
|
||||
const criticalGaps = skillGaps.filter((gap) => gap.risk === "high");
|
||||
if (criticalGaps.length > 0) {
|
||||
// Analyser les gaps critiques par importance
|
||||
const uncoveredIncontournables = skillGaps.filter(
|
||||
(gap) => gap.importance === "incontournable" && gap.coverage < 50
|
||||
);
|
||||
if (uncoveredIncontournables.length > 0) {
|
||||
recommendations.push(
|
||||
`Attention : ${
|
||||
criticalGaps.length
|
||||
} compétences critiques sans expert ni mentor : ${criticalGaps
|
||||
`⚠️ ${
|
||||
uncoveredIncontournables.length
|
||||
} compétences incontournables faiblement couvertes : ${uncoveredIncontournables
|
||||
.map((gap) => gap.skillName)
|
||||
.join(", ")}`
|
||||
);
|
||||
}
|
||||
|
||||
// Analyser les opportunités de mentorat
|
||||
const mentorshipNeeds = skillGaps.filter(
|
||||
(gap) => gap.learners > 0 && gap.mentors > 0
|
||||
).length;
|
||||
if (mentorshipNeeds > 0) {
|
||||
const uncoveredMajeures = skillGaps.filter(
|
||||
(gap) => gap.importance === "majeure" && gap.coverage < 30
|
||||
);
|
||||
if (uncoveredMajeures.length > 0) {
|
||||
recommendations.push(
|
||||
`${mentorshipNeeds} opportunités de mentorat identifiées`
|
||||
`⚠️ ${
|
||||
uncoveredMajeures.length
|
||||
} compétences majeures faiblement couvertes : ${uncoveredMajeures
|
||||
.map((gap) => gap.skillName)
|
||||
.join(", ")}`
|
||||
);
|
||||
}
|
||||
|
||||
// Analyser les opportunités de mentorat pour les compétences importantes
|
||||
const criticalMentorshipNeeds = skillGaps.filter(
|
||||
(gap) =>
|
||||
gap.learners > 0 &&
|
||||
gap.mentors > 0 &&
|
||||
(gap.importance === "incontournable" || gap.importance === "majeure")
|
||||
).length;
|
||||
if (criticalMentorshipNeeds > 0) {
|
||||
recommendations.push(
|
||||
`${criticalMentorshipNeeds} opportunités de mentorat sur des compétences critiques identifiées`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -283,13 +348,19 @@ export class TeamReviewService {
|
||||
);
|
||||
}
|
||||
|
||||
// Identifier les experts isolés
|
||||
const isolatedExperts = members.filter(
|
||||
(member) => member.expertSkills > 0 && member.mentorSkills === 0
|
||||
// Identifier les experts isolés sur des compétences importantes
|
||||
const isolatedExperts = members.filter((member) =>
|
||||
member.skills.some(
|
||||
(skill) =>
|
||||
skill.level === "expert" &&
|
||||
!skill.canMentor &&
|
||||
(skill.importance === "incontournable" ||
|
||||
skill.importance === "majeure")
|
||||
)
|
||||
);
|
||||
if (isolatedExperts.length > 0) {
|
||||
recommendations.push(
|
||||
`${isolatedExperts.length} experts pourraient devenir mentors`
|
||||
`${isolatedExperts.length} experts en compétences critiques pourraient devenir mentors`
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user