# Profit.co OKR/KPI API Integration

## Base Connector

**Source**: `prototype/src/talentverse/nodes/connectors/profit.py`
**Base URL**: `https://api.profit.co`
**Auth**: API Key + Access Key (query parameters)

### Environment Variables

```env
PROFIT_API_KEY=
PROFIT_API_ACCESS_KEY=
```

### Fetch All Objectives

```python
url = "https://api.profit.co/app/dao/v6/objective"
params = {
    "a": "getAll",
    "apiKey": self.api_key,
    "accessKey": self.api_access_key
}

async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=30)) as session:
    async with session.get(url, params=params) as response:
        if response.status == 200:
            data = await response.json()
            objectives = data.get('data', [])
```

### OKR Data Processing

```python
def _process_okr_response(self, employee_id, api_data):
    objectives = []
    for obj_data in api_data.get('objectives', []):
        key_results = []
        for kr in obj_data.get('key_results', []):
            key_results.append({
                'id': kr.get('id', ''),
                'title': kr.get('title', ''),
                'progress': kr.get('progress_percentage', 0),
                'target_value': kr.get('target_value', ''),
                'current_value': kr.get('current_value', ''),
                'status': kr.get('status', 'in_progress')
            })
        objective = {
            'id': obj_data.get('id', ''),
            'title': obj_data.get('title', ''),
            'progress': obj_data.get('progress_percentage', 0),
            'achievement_rate': obj_data.get('achievement_rate', 0),
            'key_results': key_results,
            'status': obj_data.get('status', 'active'),
        }
        objectives.append(objective)
    return {
        'employee_id': employee_id,
        'type': 'okr',
        'objectives': objectives,
        'overall_achievement': total_achievement / objective_count if objective_count > 0 else 0,
    }
```

### KPI Score Calculation (0-5 Scale)

```python
def _process_kpi_response(self, employee_id, api_data):
    for metric_data in api_data.get('metrics', []):
        current_value = metric_data.get('current_value', 0)
        target_value = metric_data.get('target_value', 0)

        if target_value > 0:
            achievement_pct = min((current_value / target_value) * 100, 200)
        else:
            achievement_pct = 0

        # Convert to 0-5 scale
        if achievement_pct >= 100: score = 5.0
        elif achievement_pct >= 80: score = 4.0 + (achievement_pct - 80) / 20
        elif achievement_pct >= 60: score = 3.0 + (achievement_pct - 60) / 20
        elif achievement_pct >= 40: score = 2.0 + (achievement_pct - 40) / 20
        elif achievement_pct >= 20: score = 1.0 + (achievement_pct - 20) / 20
        else: score = achievement_pct / 20
```

---

## Production Connector

**Source**: `prototype/src/talentverse/nodes/connectors/profit_production.py`
**Base URL**: `https://api.profit.co/app/dao/v6`
**Returns**: 652+ objectives with nested key results

### API Response Field Mapping

```python
def _parse_objective(self, obj):
    return {
        'id': obj.get('objectiveId'),
        'name': obj.get('objectiveName', '').strip(),
        'status': obj.get('objectiveStatusName'),
        'progress': obj.get('progress', 0),
        'actual_progress': obj.get('actualProgress', obj.get('progress', 0)),
        'confidence': obj.get('confidencePercentage', 0),
        'period': obj.get('periodName'),
        'period_code': obj.get('periodCode'),
        'quarter': obj.get('qt'),
        'start_date': obj.get('targetStartDate'),
        'end_date': obj.get('targetEndDate'),
        'created_by': obj.get('createdByName'),
        'key_results_count': obj.get('nks', 0),
        'key_results': self._parse_key_results(obj.get('keyResults', [])),
        'average_score': obj.get('avgSc'),
        'custom_attributes': obj.get('customAttributes', [])
    }

def _parse_key_results(self, key_results):
    parsed = []
    for kr in key_results:
        parsed.append({
            'id': kr.get('keyResultId'),
            'name': kr.get('keyResultName', '').strip(),
            'type': kr.get('keyResultTypeName'),
            'status': kr.get('keyResultStatusName'),
            'value': kr.get('value', 0),
            'start_value': kr.get('keyResultStartValue', 0),
            'end_value': kr.get('keyResultEndValue', 100),
            'achievement_score': kr.get('achievementScore', 0),
            'confidence': kr.get('confidencePercentage', 0),
            'commitment_level': kr.get('commitmentLevelName'),
            'owner_id': kr.get('ownerId'),
            'employee_id': kr.get('employeeId')
        })
    return parsed
```

### Convenience Methods

```python
# Employee-specific OKRs
result = await connector.get_employee_okrs(employee_email="john@company.com")

# Department-level OKRs
result = await connector.get_department_okrs(department="Technology")

# Quarter-specific OKRs
result = await connector.get_quarterly_okrs(quarter="Q1-2025")
```

### Department Rollup Metrics

```python
def _calculate_department_rollup(self, objectives):
    by_period = {}
    for obj in objectives:
        period = obj.get('period', 'Unknown')
        by_period.setdefault(period, []).append(obj)

    rollup = {}
    for period, period_objs in by_period.items():
        rollup[period] = {
            'objective_count': len(period_objs),
            'average_progress': sum(o.get('progress', 0) for o in period_objs) / len(period_objs),
            'average_confidence': sum(o.get('confidence', 0) for o in period_objs) / len(period_objs),
            'status_distribution': self._get_status_distribution(period_objs),
            'total_key_results': sum(len(o.get('key_results', [])) for o in period_objs)
        }
    return rollup
```
