Files
odoo-at-payroll/pv-agent/tests/test_kv_variant_map.py
T

76 lines
2.9 KiB
Python

"""Tests für die KV-Varianten-Map (Odoo library_variant_id ↔ KB kv-kvt-IDs)."""
import json
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
def load_map() -> dict:
return json.loads(
(ROOT / "tools" / "catalogs" / "kv_variant_map.json").read_text(encoding="utf-8")
)
def load_kb_catalog() -> dict:
return json.loads(
(ROOT / "tools" / "catalogs" / "kv_catalog.json").read_text(encoding="utf-8")
)
def test_map_structure_and_kb_id_integrity():
kb = load_kb_catalog()
kb_ids = {e["id"] for e in kb["entries"].values()}
variant_map = load_map()
variants = variant_map["variants"]
assert variants, "Mapping muss Varianten enthalten"
referenced = set()
for vid, variant in variants.items():
assert variant["variant_id"] == vid
assert variant["docs"], f"leere Variante: {vid}"
assert variant["confidence"] in ("matched", "low")
for doc in variant["docs"]:
assert {"kv_kvt_id", "slug", "doctype"} <= set(doc)
referenced.add(doc["kv_kvt_id"])
assert referenced <= kb_ids, "Mapping darf nur existierende KB-IDs führen"
# Unmatched-Einträge sind ebenfalls echte KB-IDs und decken den Rest ab
unmatched = variant_map["unmatched_kb_entries"]
assert set(unmatched) <= kb_ids
stats = variant_map["stats"]
assert stats["n_kb_entries_covered"] + stats["n_kb_entries_unmatched"] == (
stats["n_kb_entries_total"]
)
assert stats["n_variants"] == len(variants)
def test_odoo_seed_variants_are_covered():
"""Odoo-Seed-KVs (kv_seed.xml): SI-2203 Handwerk und Gewerbe,
SI-2748 Metallgewerbe müssen KV- und Tabellendokumente führen."""
variants = load_map()["variants"]
seeds = {vid: variants.get(vid) for vid in ("SI-2203_de", "SI-2748_de")}
assert seeds["SI-2203_de"] and seeds["SI-2203_de"]["confidence"] == "matched"
assert seeds["SI-2748_de"] and seeds["SI-2748_de"]["confidence"] == "matched"
slugs_2203 = {d["slug"] for d in seeds["SI-2203_de"]["docs"]}
slugs_2748 = {d["slug"] for d in seeds["SI-2748_de"]["docs"]}
assert "kollektivvertrag-gewerbe-handwerk-und-dienstleistung-2026" in slugs_2203
assert "gehaltsordnung-gewerbe-handwerk-dienstleistung-2026" in slugs_2203
assert "kollektivvertrag-abschluss-angestellte-metallgewerbe-2026" in slugs_2748
assert "lohnordnung-metallgewerbe-arbeiter-2026" in slugs_2748
def test_doc_pairs_keep_slug_and_id_correspondence():
kb = load_kb_catalog()
by_id = {e["id"]: e for e in kb["entries"].values()}
variant_map = load_map()
checked = 0
for variant in variant_map["variants"].values():
for doc in variant["docs"]:
entry = by_id[doc["kv_kvt_id"]]
url_slug = entry["url"].rstrip("/").rsplit("/", 1)[-1]
assert url_slug == doc["slug"], (
f"{doc['kv_kvt_id']}: {url_slug} != {doc['slug']}"
)
checked += 1
assert checked >= 400