#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ JSON Schema definitions for configuration file validation. """ from typing import Any, Dict, List # JSON Schema for header_config.json HEADER_CONFIG_SCHEMA = { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Header Configuration", "description": "Configuration for static header fields in PADneXt XML", "type": "object", "properties": { "nachrichtentyp_version": { "type": "string", "description": "Version of the message type", "default": "1.0" }, "rechnungsersteller_name": { "type": "string", "description": "Name of the billing entity" }, "rechnungsersteller_kundennr": { "type": "string", "description": "Customer number of billing entity" }, "rechnungsersteller_strasse": { "type": "string", "description": "Street address of billing entity" }, "rechnungsersteller_plz": { "type": "string", "description": "Postal code of billing entity", "pattern": "^[0-9]{5}$" }, "rechnungsersteller_ort": { "type": "string", "description": "City of billing entity" }, "rechnungsersteller_iknr": { "type": "string", "description": "IK number of billing entity (optional)" }, "leistungserbringer_id": { "type": "string", "description": "ID of the service provider" }, "leistungserbringer_titel": { "type": "string", "description": "Title of service provider (optional)" }, "leistungserbringer_vorname": { "type": "string", "description": "First name of service provider" }, "leistungserbringer_name": { "type": "string", "description": "Last name of service provider" }, "empfaenger_anrede": { "type": "string", "description": "Salutation for recipient" }, "empfaenger_vorname": { "type": "string", "description": "First name of recipient" }, "empfaenger_name": { "type": "string", "description": "Last name of recipient" }, "empfaenger_strasse": { "type": "string", "description": "Street address of recipient" }, "empfaenger_plz": { "type": "string", "description": "Postal code of recipient" }, "empfaenger_ort": { "type": "string", "description": "City of recipient" }, "empfaenger_gebdatum": { "type": "string", "description": "Birth date of recipient", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, "behandelter_anrede": { "type": "string", "description": "Salutation for patient" }, "behandelter_vorname": { "type": "string", "description": "First name of patient" }, "behandelter_name": { "type": "string", "description": "Last name of patient" }, "behandelter_gebdatum": { "type": "string", "description": "Birth date of patient", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, "behandelter_geschlecht": { "type": "string", "description": "Gender of patient", "enum": ["m", "w", "u"] }, "versicherter_anrede": { "type": "string", "description": "Salutation for insured person" }, "versicherter_vorname": { "type": "string", "description": "First name of insured person" }, "versicherter_name": { "type": "string", "description": "Last name of insured person" }, "versicherter_gebdatum": { "type": "string", "description": "Birth date of insured person", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, "versicherter_geschlecht": { "type": "string", "description": "Gender of insured person", "enum": ["m", "w", "u"] }, "behandlungsart": { "type": "string", "description": "Type of treatment", "pattern": "^[0-5]$" }, "vertragsart": { "type": "string", "description": "Type of contract", "pattern": "^[0-9]{1,3}$" }, "aktenzeichen": { "type": "string", "description": "File reference (optional)" }, "diagnose_text": { "type": "string", "description": "Diagnosis text" }, "diagnose_datum": { "type": "string", "description": "Diagnosis date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, "eabgabe": { "type": "string", "description": "Electronic submission (optional)" }, "aisaktenzeichen": { "type": "string", "description": "AIS file reference (optional)" }, "aisendbetrag": { "type": "string", "description": "AIS total amount (optional)" } }, "additionalProperties": True # Allow additional fields for flexibility } # JSON Schema for placeholder_config.json PLACEHOLDER_CONFIG_SCHEMA = { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Placeholder Configuration", "description": "Fallback values for missing required fields", "type": "object", "properties": { "rechnungsersteller": { "type": "object", "properties": { "name": {"type": "string"}, "plz": {"type": "string", "pattern": "^[0-9]{5}$"}, "ort": {"type": "string"}, "strasse": {"type": "string"} }, "required": ["name", "plz", "ort", "strasse"] }, "leistungserbringer": { "type": "object", "properties": { "vorname": {"type": "string"}, "name": {"type": "string"}, "titel": {"type": ["string", "null"]} }, "required": ["vorname", "name"] }, "empfaenger": { "type": "object", "properties": { "anrede": {"type": "string"}, "vorname": {"type": "string"}, "name": {"type": "string"}, "plz": {"type": "string"}, "ort": {"type": "string"}, "strasse": {"type": "string"}, "gebdatum": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"}, "geschlecht": {"type": "string", "enum": ["m", "w", "u"]} }, "required": ["anrede", "vorname", "name", "plz", "ort", "strasse", "gebdatum"] }, "behandelter": { "type": "object", "properties": { "anrede": {"type": ["string", "null"]}, "vorname": {"type": "string"}, "name": {"type": "string"}, "gebdatum": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"}, "geschlecht": {"type": "string", "enum": ["m", "w", "u"]} }, "required": ["vorname", "name", "gebdatum", "geschlecht"] }, "versicherter": { "type": "object", "properties": { "anrede": {"type": "string"}, "vorname": {"type": "string"}, "name": {"type": "string"}, "gebdatum": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"}, "geschlecht": {"type": "string", "enum": ["m", "w", "u"]} }, "required": ["anrede", "vorname", "name", "gebdatum", "geschlecht"] }, "rechnung": { "type": "object", "properties": { "eabgabe": {"type": ["string", "null"]}, "aisaktenzeichen": {"type": ["string", "null"]}, "aisendbetrag": {"type": ["string", "null"]} } }, "abrechnungsfall": { "type": "object", "properties": { "behandlungsart": {"type": "string", "pattern": "^[0-5]$"}, "vertragsart": {"type": "string", "pattern": "^[0-9]{1,3}$"} }, "required": ["behandlungsart", "vertragsart"] }, "zeitraum": { "type": "object", "properties": { "startdatum": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"}, "endedatum": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"} }, "required": ["startdatum", "endedatum"] }, "goziffer": { "type": "object", "properties": { "go": {"type": "string", "enum": ["GOAE", "UVGOAE", "EBM", "GOZ"]}, "ziffer": {"type": "string", "maxLength": 8, "minLength": 1}, "datum": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"} }, "required": ["go", "ziffer", "datum"] }, "diagnose": { "type": "object", "properties": { "datum": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"} }, "required": ["datum"] } }, "required": ["rechnungsersteller", "leistungserbringer", "goziffer"], "additionalProperties": True } # JSON Schema for mapping_config.json MAPPING_CONFIG_SCHEMA = { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Mapping Configuration", "description": "Mapping rules from FHIR resources to PAD positions", "type": "object", "properties": { "resources": { "type": "object", "description": "Resource type to position mappings", "additionalProperties": { "type": "object", "properties": { "target": { "type": "string", "description": "Target PAD element type", "enum": ["goziffer"] }, "fields": { "type": "object", "description": "Field mappings", "additionalProperties": { "type": "object", "properties": { "source": { "type": "string", "description": "Source field path in FHIR resource" }, "default": { "type": "string", "description": "Default value if source is missing" }, "required": { "type": "boolean", "description": "Whether this field is required" }, "placeholder": { "type": "string", "description": "Placeholder value for required fields" }, "translate": { "type": "object", "description": "Code translation rules", "properties": { "source_system_field": {"type": "string"}, "source_code_field": {"type": "string"} } } } } } }, "required": ["target", "fields"] } } }, "required": ["resources"] } def validate_config(config: Dict[str, Any], schema: Dict[str, Any], config_name: str) -> List[str]: """ Validate configuration against JSON schema. Args: config: The configuration dict to validate schema: The JSON schema to validate against config_name: Name of the config for error messages Returns: List of validation warnings (non-fatal issues) Raises: ValueError: If validation fails with errors Example: >>> config = {"rechnungsersteller": {...}} >>> warnings = validate_config(config, PLACEHOLDER_CONFIG_SCHEMA, "placeholder_config") """ warnings = [] try: import jsonschema except ImportError: warnings.append(f"jsonschema not available - skipping {config_name} validation") warnings.append("Install with: pip install jsonschema") return warnings try: jsonschema.validate(config, schema) except jsonschema.ValidationError as e: # Collect detailed error information error_path = " -> ".join(str(p) for p in e.path) if e.path else "root" error_msg = f"Validation error in {config_name} at {error_path}: {e.message}" raise ValueError(error_msg) from e except jsonschema.SchemaError as e: raise ValueError(f"Invalid schema for {config_name}: {e.message}") from e return warnings def validate_header_config(config: Dict[str, Any]) -> List[str]: """Validate header configuration.""" return validate_config(config, HEADER_CONFIG_SCHEMA, "header_config") def validate_placeholder_config(config: Dict[str, Any]) -> List[str]: """Validate placeholder configuration.""" return validate_config(config, PLACEHOLDER_CONFIG_SCHEMA, "placeholder_config") def validate_mapping_config(config: Dict[str, Any]) -> List[str]: """Validate mapping configuration.""" return validate_config(config, MAPPING_CONFIG_SCHEMA, "mapping_config")