Bahn: aisupport, Analyse-O2C-C2S, awesome-bahn-mcp-servers, beam-mcp,
Confluence_Bot, db-planet-mcp-server, O2C-Harness, project-audit,
Projekt-KIQ-HP, teamlandkarte-mcp
Dhive: Jury-Voting
Privat: CV, NoteGraph (NOTE: NoteGraph needs complete redo after consolidation)
Shared: AI-Orchestrator, OrgMyLife, power_skills_and_more
Shared/references: symphony (read-only)
Bahn repos remain available as independent remotes - this monorepo
pulls them in via subtree, the originals are untouched.
122 lines
2.9 KiB
Python
122 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from datetime import date, datetime
|
|
from typing import Optional
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Task:
|
|
"""Published task loaded from the database."""
|
|
|
|
id: str
|
|
name: Optional[str]
|
|
title: str
|
|
description: str
|
|
start_date: Optional[date]
|
|
end_date: Optional[date]
|
|
created_date: datetime
|
|
skills: list[str] = field(default_factory=list)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Capacity:
|
|
"""A person's available capacity entry from the database."""
|
|
|
|
id: int
|
|
owner_name: str
|
|
role_name: Optional[str]
|
|
role_level: Optional[str]
|
|
begin_date: Optional[date]
|
|
end_date: Optional[date]
|
|
competences: list[str] = field(default_factory=list)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Requirements:
|
|
"""Structured matching requirements."""
|
|
|
|
role_name: Optional[str]
|
|
competences: list[str]
|
|
date_start: Optional[date] = None
|
|
date_end: Optional[date] = None
|
|
description: Optional[str] = None
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class RankedRole:
|
|
"""A role candidate extracted from a description.
|
|
|
|
Attributes:
|
|
rank: 1-based rank.
|
|
role: Role name.
|
|
rationale: Short explanation for why this role matches.
|
|
"""
|
|
|
|
rank: int
|
|
role: str
|
|
rationale: str
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ScoredCapacity:
|
|
"""A `Capacity` plus matching scores and diagnostic lists."""
|
|
|
|
capacity: Capacity
|
|
competence_score: float
|
|
role_score: float
|
|
overall_score: float
|
|
category: str
|
|
matched_competences: list[str] = field(default_factory=list)
|
|
missing_competences: list[str] = field(default_factory=list)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class TeamCompetence:
|
|
"""Eine Team-Kompetenz mit aufgelöstem Namen und Top-Markierung."""
|
|
|
|
name: str
|
|
top_competency: bool
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class TeamReference:
|
|
"""Eine Team-Referenz mit aufgelöstem Partner-Namen und Projekttext.
|
|
|
|
`partner_name` ist leer, wenn `partner_id` `NULL` ist oder der LEFT JOIN
|
|
auf `teamlandkarte_v_partners_latest` keinen Treffer liefert. `projects`
|
|
ist bereits getrimmt und nie leer (Whitespace-only-Werte werden im
|
|
DBClient ausgefiltert).
|
|
"""
|
|
|
|
partner_name: str
|
|
projects: str
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Team:
|
|
"""Aggregiertes Team-Stammdatum aus dem Data Lake."""
|
|
|
|
team_id: str
|
|
ouid: str
|
|
team_name: str
|
|
focus_name: str
|
|
about_us: str
|
|
offerings: str
|
|
interests: str
|
|
competences: list[TeamCompetence] = field(default_factory=list)
|
|
references: list[TeamReference] = field(default_factory=list)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ScoredTeam:
|
|
"""A `Team` plus matching scores and diagnostic lists (score mode only)."""
|
|
|
|
team: Team
|
|
competence_score: float
|
|
role_score: float
|
|
overall_score: float
|
|
category: str
|
|
matched_competences: list[str] = field(default_factory=list)
|
|
missing_competences: list[str] = field(default_factory=list)
|