Files
greeneclipse 8580c996c3 Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
2026-08-09 22:47:43 +02:00

76 lines
3.3 KiB
Markdown

# EPREL integration (v2)
Descrybe enriches processed products with EU **EPREL** (European Product Registry for Energy Labelling) data when a registration ID is present on the feed item.
## How it works
1. **Feed sync / mapping** stores product fields in `raw_products.mapped_data` / `raw_data`. Vendor XML often includes an empty or populated `<EPRELID/>` (also `eprel_id`, `eprelId`, …).
2. **Processing worker** runs the canonical steps:
`normalize``parse_specs``fill_fields`**`eprel`** → `ai_enhance` (optional).
When `EPREL_ENABLED=true`, the `eprel` step:
- Discovers an ID via `eprel.ExtractID(normalized, mapped, raw)` (same key variants as legacy: `EPRELID`, `eprel_id`, …).
- Calls the public EPREL HTTP API (`internal/eprel.Client` / `Fetcher` interface) with a hard timeout and bounded response body.
- Merges results into `processed_products.attributes` and `processed_attributes` as:
- Flat keys: `eprel_id`, `eprel_label` / `eprel_label_url`, `eprel_pdf` / `eprel_pdf_url`, `eprel_energy_class`, `eprel_energy_scale`
- Nested object: `eprel: { id, label, pdf?, energy_class?, energy_scale? }`
- Also records a compact `field_sources.eprel` / step log entry.
3. **Export XML/CSV** resolves those keys (and aliases like `energy_class`, `eprel_label_url`) through the export template `source` field. Map them in the export feed builder like any other attribute.
EPREL failures are **soft**: the product still completes; a truncated note may appear in `gpt_response.steps` for the `eprel` step. No API keys or Authorization headers are written to logs.
## Configuration
Set on the **worker** process (enrichment runs during `ProcessJob`):
| Variable | Default | Purpose |
|---|---|---|
| `EPREL_ENABLED` | `false` | Turn on enrichment |
| `EPREL_TIMEOUT` | `10s` | HTTP client timeout (`10s`, `500ms`, or integer seconds `10`) |
| `EPREL_BASE_URL` | `https://eprel.ec.europa.eu/api` | Override for tests/proxies |
| `EPREL_FICHE_LANGUAGE` | `EN` | Language for product fiche PDF |
| `EPREL_API_KEY` | _(empty)_ | Optional `X-API-KEY` if your deployment requires a whitelisted key — **never log** |
Example:
```bash
EPREL_ENABLED=true
EPREL_TIMEOUT=10s
EPREL_FICHE_LANGUAGE=EN
```
## Public API calls (per product)
For registration id `{id}`:
- Label URL (constructed): `{base}/product/{id}/labels?format=png`
- Fiche: `GET {base}/product/{id}/fiches?noRedirect=true&language={lang}` → PDF path
- Info: `GET {base}/product/{id}``energyClass`, `energyClassRange` / `energyScale`
## Export mapping examples
Template field sources that work out of the box:
- `eprel_id`
- `eprel_label` / `eprel_label_url`
- `eprel_pdf` / `eprel_pdf_url`
- `eprel_energy_class` / `energy_class`
- `eprel_energy_scale` / `energy_scale`
- `attr.eprel_id` (generic attribute path)
## Package layout
- `apps/api/internal/eprel``Fetcher` interface, HTTP `Client`, ID normalize/extract, `MergeInto`
- `apps/api/internal/processing` — Engine step `eprel` (`StepEPREL`) after fill_fields
- `apps/api/internal/feeds` — export source aliases for EPREL fields
- `apps/api/cmd/worker` — sets `Engine.EPREL` from config when enabled
Processing type aliases: `eprel` / `eprel_only` run normalize + eprel only.
## Tests
```bash
cd apps/api
go test ./internal/eprel/ ./internal/processing/ ./internal/feeds/ ./internal/config/
go build ./...
```