# Time Tracking - Billed Via Hub Order ID

## Oversigt

Implementeret tracking af hvilken Hub ordre (og dermed e-conomic ordre) hver tidsregistrering er blevet faktureret gennem.

## Database Ændringer

### Migration: `060_add_billed_via_thehub_id.sql`

Tilføjet nyt felt til `tmodule_times` tabellen:

```sql
ALTER TABLE tmodule_times ADD COLUMN billed_via_thehub_id INTEGER;
ALTER TABLE tmodule_times 
    ADD CONSTRAINT tmodule_times_billed_via_thehub_id_fkey 
    FOREIGN KEY (billed_via_thehub_id) 
    REFERENCES tmodule_orders(id) 
    ON DELETE SET NULL;
CREATE INDEX idx_tmodule_times_billed_via_thehub_id ON tmodule_times(billed_via_thehub_id);
```

**Felt beskrivelse:**
- `billed_via_thehub_id`: Hub ordre ID som tidsregistreringen er faktureret gennem
- Foreign key til `tmodule_orders.id` 
- Via Hub ordren kan man finde `economic_order_number` som er ordrenummeret i e-conomic

## Kode Ændringer

### 1. `app/timetracking/backend/models.py`

Tilføjet felt til `TModuleTime` Pydantic model:

```python
billed_via_thehub_id: Optional[int] = Field(None, description="Hub order ID this time was billed through")
is_travel: bool = False  # Også tilføjet manglende felt
```

### 2. `app/timetracking/backend/economic_export.py`

Opdateret `export_order_to_economic()` til at sætte `billed_via_thehub_id` når ordren eksporteres:

```python
# Marker time entries som billed og opdater billed_via_thehub_id
execute_update(
    """UPDATE tmodule_times
       SET status = 'billed',
           billed_via_thehub_id = %s
       WHERE id IN (
           SELECT UNNEST(time_entry_ids) 
           FROM tmodule_order_lines 
           WHERE order_id = %s
       )""",
    (request.order_id, request.order_id)
)
```

**Vigtig note:** vTiger opdateres også via `update_timelog_billed()` som sætter `billed_via_thehub_id` i vTiger's Timelog records.

### 3. `app/timetracking/backend/order_service.py`

**FJERNET** for tidlig status opdatering:

```python
# BEFORE: Time entries blev sat til 'billed' når Hub ordre blev oprettet
# AFTER: Time entries forbliver 'approved' indtil e-conomic eksporten er succesfuld
```

Nu opdateres `status='billed'` og `billed_via_thehub_id` KUN i `economic_export.py` efter succesfuld eksport.

### 4. `app/timetracking/backend/vtiger_sync.py`

**BESKYTTELSE MOD OVERSKRIVNING:** Tidsregistreringer med `billed_via_thehub_id` opdateres IKKE ved sync:

```python
# Update only if NOT yet approved AND NOT yet billed
result = execute_update(
    """UPDATE tmodule_times 
       SET description = %s, original_hours = %s, worked_date = %s,
           user_name = %s, billable = %s, vtiger_data = %s::jsonb, 
           sync_hash = %s, last_synced_at = CURRENT_TIMESTAMP
       WHERE vtiger_id = %s 
       AND status = 'pending' 
       AND billed_via_thehub_id IS NULL""",
    ...
)
```

Dette sikrer at allerede fakturerede tidsregistreringer forbliver låst og ikke overskrevet af vTiger sync.

## Workflow

### Før ændringerne:
1. Godkendte tider → `status='approved'`
2. **Opret ordre** i Hub → `status='billed'` ⚠️ (for tidligt!)
3. Eksporter til e-conomic → `economic_order_number` sættes på Hub ordre

### Efter ændringerne:
1. Godkendte tider → `status='approved'`
2. **Opret ordre** i Hub → tider forbliver `status='approved'`
3. **Eksporter til e-conomic** → `status='billed'` + `billed_via_thehub_id` sættes
4. vTiger opdateres også med `billed_via_thehub_id`

## Data Relations

```
tmodule_times.billed_via_thehub_id 
  ↓ (foreign key)
tmodule_orders.id
  → tmodule_orders.economic_order_number (e-conomic ordre nummer)
  → tmodule_orders.economic_draft_id (e-conomic kladde ID)
```

## Queries

### Find alle tidsregistreringer for en e-conomic ordre:

```sql
SELECT t.*, o.economic_order_number
FROM tmodule_times t
JOIN tmodule_orders o ON t.billed_via_thehub_id = o.id
WHERE o.economic_order_number = '12345';
```

### Find tider der er faktureret via en specifik Hub ordre:

```sql
SELECT * FROM tmodule_times 
WHERE billed_via_thehub_id = 123;
```

### Find tider der IKKE er faktureret endnu:

```sql
SELECT * FROM tmodule_times 
WHERE status = 'approved' 
AND billed_via_thehub_id IS NULL;
```

## vTiger Integration

vTiger's `Timelog` records opdateres også via `app/timetracking/backend/vtiger_sync.py`:

```python
async def update_timelog_billed(self, vtiger_ids: List[str], hub_order_id: int):
    payload = {
        "elementType": "Timelog",
        "element": {
            "id": vtiger_id,
            "billed_via_thehub_id": str(hub_order_id),
            "cf_timelog_invoiced": "1"
        }
    }
```

**Note:** `cf_timelog_invoiced` (IS BILLED) feltet i vTiger kan vi IKKE ændre fra Hub (vTiger begrænsning), men vi opdaterer vores eget `billed_via_thehub_id` felt.

## Testing

Migrationen er kørt og verificeret:
```bash
docker exec bmc-hub-postgres psql -U bmc_hub -d bmc_hub -c "\d tmodule_times"
# Viser: billed_via_thehub_id | integer med foreign key
```

## Deployment

1. Migration er kørt på dev (060_add_billed_via_thehub_id.sql)
2. Kode ændringer deployed i samme commit
3. Eksisterende tidsregistreringer har `billed_via_thehub_id = NULL`
4. Fremtidige eksporter vil populere feltet korrekt

## Relaterede Filer

- `migrations/060_add_billed_via_thehub_id.sql`
- `app/timetracking/backend/models.py`
- `app/timetracking/backend/economic_export.py`
- `app/timetracking/backend/order_service.py`
- `app/timetracking/backend/vtiger_sync.py`
