fix: normalize official agricultural crop groups
GeoIntel CI / docs-smoke (push) Canceled after 0s
GeoIntel CI / contract-smoke (push) Canceled after 0s

This commit is contained in:
Codex
2026-07-15 15:53:10 +02:00
parent 7f1064ff1e
commit 312400759f
4 changed files with 39 additions and 1 deletions
+2
View File
@@ -20,6 +20,8 @@
- Added a scope-specific 18-edition temporal series while explicitly disabling - Added a scope-specific 18-edition temporal series while explicitly disabling
parcel-level lineage and excluding the provisional current campaign. parcel-level lineage and excluding the provisional current campaign.
- Added focused source, clipping, metric, pagination, packaging and UI tests. - Added focused source, clipping, metric, pagination, packaging and UI tests.
- Added compatibility for the official comma-separated grain and horticulture
group labels after live source validation exposed their exact wording.
## Sprint 204 Governed BWK and Natura 2000 for Mol (2026-07-15) ## Sprint 204 Governed BWK and Natura 2000 for Mol (2026-07-15)
+21 -1
View File
@@ -101,8 +101,25 @@ SEMANTIC_COUNT_LABELS = {
"agriculture": "Landbouwgebruikspercelen", "agriculture": "Landbouwgebruikspercelen",
} }
# Sprint 205 initially normalized two official comma-separated ALZ group labels
# mechanically. Keep those persisted values queryable while new artifacts use
# the explicit controlled keys.
SELECTION_FILTER_VALUE_ALIASES: dict[tuple[str, str], tuple[str, ...]] = {
("main_crop_group_key", "grains_seeds_legumes"): ("granen,_zaden_en_peulvruchten",),
("main_crop_group_key", "horticulture"): ("groenten,_kruiden_en_sierplanten",),
}
class VectorFeatureService: class VectorFeatureService:
@staticmethod
def _expanded_selection_filter_values(filter_property: str, filter_values: list[Any]) -> list[str]:
expanded: list[str] = []
for value in filter_values:
normalized = str(value)
expanded.append(normalized)
expanded.extend(SELECTION_FILTER_VALUE_ALIASES.get((filter_property, normalized), ()))
return list(dict.fromkeys(expanded))
@staticmethod @staticmethod
def _dataset_theme(dataset: Dataset) -> str | None: def _dataset_theme(dataset: Dataset) -> str | None:
source_metadata = dataset.source_metadata if isinstance(dataset.source_metadata, dict) else {} source_metadata = dataset.source_metadata if isinstance(dataset.source_metadata, dict) else {}
@@ -453,7 +470,10 @@ class VectorFeatureService:
details={"dataset_id": str(dataset.id), "filter_property": filter_property}, details={"dataset_id": str(dataset.id), "filter_property": filter_property},
status_code=500, status_code=500,
) )
normalized_filter_values = [str(value) for value in filter_values] normalized_filter_values = VectorFeatureService._expanded_selection_filter_values(
filter_property,
filter_values,
)
metric_filter += ( metric_filter += (
VectorFeature.properties_json.op("->>")(filter_property).in_(normalized_filter_values), VectorFeature.properties_json.op("->>")(filter_property).in_(normalized_filter_values),
) )
@@ -150,6 +150,20 @@ def test_crop_code_list_preserves_year_specific_titles_and_reports_conflicts() -
assert result["code_title_conflicts"] == {"201": ["Korrelmais", "Mais"]} assert result["code_title_conflicts"] == {"201": ["Korrelmais", "Mais"]}
assert "maincropgroup_title" in result["historical_comparison_rule"] assert "maincropgroup_title" in result["historical_comparison_rule"]
assert module.normalized_group_title("Maïs") == "maize" assert module.normalized_group_title("Maïs") == "maize"
assert module.normalized_group_title("Granen, zaden en peulvruchten") == "grains_seeds_legumes"
assert module.normalized_group_title("Groenten, kruiden en sierplanten") == "horticulture"
def test_persisted_first_import_group_keys_remain_query_compatible() -> None:
assert VectorFeatureService._expanded_selection_filter_values(
"main_crop_group_key",
["grains_seeds_legumes", "horticulture"],
) == [
"grains_seeds_legumes",
"granen,_zaden_en_peulvruchten",
"horticulture",
"groenten,_kruiden_en_sierplanten",
]
def test_features_are_exactly_clipped_in_lambert72_and_keep_source_fields() -> None: def test_features_are_exactly_clipped_in_lambert72_and_keep_source_fields() -> None:
@@ -94,8 +94,10 @@ GROUP_ALIASES = {
"grasland": "grassland", "grasland": "grassland",
"mais": "maize", "mais": "maize",
"granen/zaden/peulvruchten": "grains_seeds_legumes", "granen/zaden/peulvruchten": "grains_seeds_legumes",
"granen, zaden en peulvruchten": "grains_seeds_legumes",
"aardappelen": "potatoes", "aardappelen": "potatoes",
"groenten/kruiden/sierplanten": "horticulture", "groenten/kruiden/sierplanten": "horticulture",
"groenten, kruiden en sierplanten": "horticulture",
"suikerbieten": "sugar_beets", "suikerbieten": "sugar_beets",
"voedergewassen": "fodder_crops", "voedergewassen": "fodder_crops",
"fruit en noten": "fruit_nuts", "fruit en noten": "fruit_nuts",