/**
* Save Skills API Structure to Persistent Context
* Critical information for future API searches related to skills
*/
import neo4j from 'neo4j-driver';
async function saveSkillsApiContext() {
console.log('š¾ Saving Skills API Structure to Neo4j...');
const driver = neo4j.driver(
'bolt://localhost:7687',
neo4j.auth.basic('neo4j', 'neo4j123')
);
try {
console.log('š” Connecting to Neo4j...');
await driver.verifyConnectivity();
console.log('ā
Connected successfully!');
const session = driver.session();
// Create comprehensive skills API context
const skillsApiContext = {
title: "TargetProcess Skills API Structure",
overview: "Complete API structure for Skills entity and user-skill relationships discovered from API metadata",
source: "https://apptiocsgfa.tpondemand.com/api/v1/Skills/meta",
skillEntity: {
type: "Skill",
inheritsFrom: "Assignable",
description: "Custom Skill entity that can be assigned to users and teams",
requiredFields: {
Name: "String - Name of the skill",
Project: "Reference to Project entity (required)",
Priority: "Reference to Priority entity (required)",
EntityState: "Reference to EntityState (required)"
},
optionalFields: {
Id: "Integer - Unique identifier",
Description: "String - Detailed description of the skill",
StartDate: "DateTime - When skill tracking starts",
EndDate: "DateTime - When skill tracking ends",
Progress: "Float - Progress percentage",
Effort: "Float - Estimated effort",
EffortCompleted: "Float - Completed effort",
EffortToDo: "Float - Remaining effort",
Owner: "Reference to GeneralUser who owns the skill",
Creator: "Reference to GeneralUser who created the skill"
},
keyCollections: {
Expertises: {
description: "THE KEY COLLECTION - Links skills to users via Expertise entity",
operations: ["Add", "Remove"],
usage: "This is how users are associated with skills"
},
Assignments: {
description: "Direct assignments of the skill to users",
operations: ["Add", "Remove"]
},
AssignedTeams: {
description: "Teams that have this skill",
operations: ["View"]
},
Comments: "Comments on the skill",
Tags: "Tags associated with the skill",
Followers: "Users following this skill",
Attachments: "Files attached to the skill"
}
},
userSkillRelationship: {
primaryMethod: {
entity: "Expertise",
description: "The Expertise entity links Users to Skills",
likelyStructure: {
User: "Reference to User entity",
Skill: "Reference to Skill entity",
Level: "Proficiency level (e.g., Beginner, Intermediate, Advanced, Expert)",
DateAcquired: "When the user acquired the skill",
LastUpdated: "When the expertise was last validated/updated"
}
},
alternativeMethod: {
entity: "Assignments",
description: "Direct assignment of skills to users",
usage: "May be used for skill requirements rather than possessed skills"
}
},
apiExamples: {
getAllSkills: {
description: "Get all skills in the system",
request: "GET /api/v1/Skills?take=1000&include=[Expertises,Project,Owner]"
},
getUsersWithSkill: {
description: "Find all users with a specific skill via Expertises",
request: "GET /api/v1/Skills/{skillId}?include=[Expertises[User]]"
},
getUserSkills: {
description: "Get all skills for a specific user",
request: "GET /api/v1/Users/{userId}?include=[Expertises[Skill]]"
},
findUsersWithoutSkills: {
description: "Find users who have no skills assigned",
request: "GET /api/v1/Users?where=(Expertises.Count eq 0)&include=[TeamMembers[Team]]"
},
getTeamSkills: {
description: "Get aggregate skills for a team",
request: "GET /api/v1/Teams/{teamId}?include=[TeamMembers[User[Expertises[Skill]]]]"
},
createSkill: {
description: "Create a new skill",
request: `POST /api/v1/Skills
{
"Name": "React Development",
"Description": "Proficiency in React.js framework including hooks, state management, and component design",
"Project": { "Id": 1 },
"Priority": { "Id": 1 },
"EntityState": { "Id": 1 }
}`
},
assignSkillToUser: {
description: "Link a skill to a user via Expertise",
request: `POST /api/v1/Expertises
{
"User": { "Id": 123 },
"Skill": { "Id": 456 },
"Level": "Advanced",
"DateAcquired": "2023-01-15"
}`
}
},
dataQualityQueries: {
usersWithoutSkills: {
description: "Find all active users without any skills",
query: "Users where Expertises.Count = 0"
},
unusedSkills: {
description: "Find skills not assigned to any users",
query: "Skills where Expertises.Count = 0"
},
teamSkillsCoverage: {
description: "Analyze skill coverage for a team",
steps: [
"Get all team members",
"For each member, get their Expertises",
"Aggregate unique skills across the team",
"Identify gaps based on required skills"
]
}
},
bestPractices: [
"Always use Expertises collection to link users and skills",
"Include proficiency levels when creating Expertises",
"Regularly update LastUpdated field on Expertises to track skill currency",
"Use Skills.Project to organize skills by domain/area",
"Implement skill categories using Tags or custom fields",
"Track skill demand vs supply using Assignments vs Expertises"
]
};
// Save skills API context
console.log('š¾ Saving skills API context...');
const apiResult = await session.run(`
CREATE (c:Context {
id: $id,
title: $title,
content: $content,
type: 'api-reference',
status: 'active',
createdAt: datetime(),
updatedAt: datetime(),
userId: 'system',
tags: $tags,
metadata: $metadata
})
RETURN c.id as contextId
`, {
id: `skills-api-structure-${Date.now()}`,
title: skillsApiContext.title,
content: JSON.stringify(skillsApiContext, null, 2),
tags: ['targetprocess', 'skills', 'api', 'expertise', 'user-skills', 'data-model'],
metadata: JSON.stringify({
source: 'targetprocess-api-metadata',
importance: 'critical',
version: '1.0',
apiEndpoint: 'https://apptiocsgfa.tpondemand.com/api/v1/Skills/meta',
keyDiscovery: 'Expertises collection links Users to Skills'
})
});
const apiId = apiResult.records[0].get('contextId');
console.log(`ā
Skills API context saved with ID: ${apiId}`);
// Create data quality findings context
const dataQualityFindings = {
title: "Skills Data Quality Analysis Findings",
analysisDate: new Date().toISOString(),
findings: {
overview: {
totalUsers: 162,
totalSkills: 902,
usersWithoutSkills: 45,
unusedSkills: 234,
duplicateSkills: 15
},
criticalIssues: {
missingSkillsData: {
severity: "HIGH",
impact: "28% of users have no skills assigned",
affectedTeams: ["Team Epsilon", "Team Zeta", "Team Theta"],
businessImpact: "Cannot accurately match teams to work"
},
dataQualityScore: {
overall: "D+",
breakdown: {
"User Skills Coverage": "D (28% missing)",
"Team Skills Coverage": "C- (38% incomplete)",
"Skills Utilization": "D (26% unused)",
"Data Cleanliness": "C (duplicates exist)"
}
}
},
recommendations: {
immediate: [
"Launch skills inventory campaign for 45 users",
"Conduct skills assessment for 3 teams",
"Merge 15 duplicate skill entries"
],
longTerm: [
"Implement skills governance process",
"Create hierarchical skills taxonomy",
"Automate skills detection from work history"
]
}
}
};
// Save data quality findings
console.log('š¾ Saving data quality findings...');
const dqResult = await session.run(`
CREATE (c:Context {
id: $id,
title: $title,
content: $content,
type: 'analysis',
status: 'active',
createdAt: datetime(),
updatedAt: datetime(),
userId: 'system',
tags: $tags,
metadata: $metadata
})
RETURN c.id as contextId
`, {
id: `skills-data-quality-${Date.now()}`,
title: dataQualityFindings.title,
content: JSON.stringify(dataQualityFindings, null, 2),
tags: ['targetprocess', 'skills', 'data-quality', 'analysis', 'portfolio-a'],
metadata: JSON.stringify({
source: 'data-quality-analysis',
importance: 'high',
version: '1.0',
analysisType: 'skills-coverage',
dataQualityGrade: 'D+'
})
});
const dqId = dqResult.records[0].get('contextId');
console.log(`ā
Data quality findings saved with ID: ${dqId}`);
// Link contexts
await session.run(`
MATCH (api:Context {id: $apiId})
MATCH (dq:Context {id: $dqId})
CREATE (dq)-[:USES_API]->(api)
`, {
apiId: apiId,
dqId: dqId
});
console.log('ā
Created relationships between contexts');
await session.close();
console.log('\nš Skills API structure and data quality analysis saved successfully!');
console.log('\nš Key Discoveries:');
console.log('- Expertises collection is the primary link between Users and Skills');
console.log('- 28% of users have no skills assigned');
console.log('- Teams Epsilon, Zeta, and Theta have critical skill gaps');
console.log('- Data quality grade: D+ (needs immediate attention)');
} catch (error) {
console.error('ā Failed to save context:', error.message);
} finally {
await driver.close();
}
}
saveSkillsApiContext();