# KPI EUR Conversion - Developer Guide

## Purpose
This feature fills (or rebuilds) EUR-denominated KPI values in `kpis.data` using ECB FX rates stored in `exchange_rates`.

It is implemented by:

- Command: `app/Console/Commands/TkoConvertKpisToEuroCommand.php` (`tko:convert-kpis-euro`)
- Service: `app/Services/KpiEuroConversionService.php`

## Scope (what rows are processed)

Only KPIs matching:

- `report_type = ACTUAL`
- `report_period IN (LTM, M)`

Key mapping:

- **LTM**: `SALES → SALES_EURO`, `EBITDA → EBITDA_EURO`, `EBIT → EBIT_EURO`
- **M**: `EV → EV_EURO`, `RISKEV → RISKEV_EURO`

## Currency resolution

For each KPI row, currency is resolved in this order:

1. `kpis.data['Currency']` (if set and non-empty)
2. `kpis.currency` (if set and non-empty)
3. `companies.data['Currency']` (via `Kpi->company` relation)

If no currency is found, the row is skipped and counted as `skipped_no_currency`.

## FX lookup logic (important)

Exchange rates are expected as:

- `exchange_rates.cur1 = EUR`
- `exchange_rates.cur2 = <LOCAL_CURRENCY>`
- `exchange_rates.source = ECB`
- `exchange_rates.rate = units of cur2 per 1 EUR`

For a KPI `report_date`, the service searches for a rate on that date, and if missing, looks back up to **7 days** (including the same day). If no rate is found in that lookback window, the row is skipped and counted as `skipped_no_rate`.

Conversion formula:

- \( EUR = \frac{LOCAL}{rate} \)

If currency is already `EUR`, the value is copied as-is.

## Required dynamic fields

All target `*_EURO` keys must exist in `dynamic_fields` for model `App\Models\Kpi`.

The service validates this upfront and throws if any are missing:

- `SALES_EURO`
- `EBITDA_EURO`
- `EBIT_EURO`
- `EV_EURO`
- `RISKEV_EURO`

## Modes

The command selects mode via `--rebuild`:

- **Default (fill missing)**: only writes `*_EURO` keys that are not already present on the KPI row.
- **Rebuild (`--rebuild`)**: removes all configured `*_EURO` keys first, then recalculates.
  - If currency/rate is unavailable, the keys remain removed for that row.

## Command usage

```bash
php artisan tko:convert-kpis-euro [--rebuild] [--company=<uuid>] [--progress]
```

Options:

- `--rebuild`: remove all target `*_EURO` keys then recalculate.
- `--company=<uuid>`: restrict processing to a single company UUID.
- `--progress`: show a progress bar (also shown automatically in verbose mode).

## Output + logs

Console output prints a summary:

- `duration_seconds`, `rows_scanned`, `rows_updated`, `fields_written`
- `skipped_no_currency`, `skipped_no_rate`, `field_skipped_no_source`
- `fields_written_by_key` breakdown

Job logs are written to:

- `storage/logs/job_logs.log`
  - Start: `lnc:convert-kpis-to-euro started`
  - End: `lnc:convert-kpis-to-euro finished`
  - Failure: `lnc:convert-kpis-to-euro failed`

## Recommended operational flow

1. Ensure FX rates are present:
   - Run `php artisan lnc:sync-ecb-exchange-rates` (see `dev_guide/exchange_rates_developer.md`)
2. Run EUR conversion in fill-missing mode regularly.
3. Use `--rebuild` after changing mapping/dynamic fields or fixing historical FX gaps.

