From 0cde9e83107196e64b51ac76fd51b413e31d3306 Mon Sep 17 00:00:00 2001 From: "martin.schweitzer" Date: Wed, 15 Apr 2026 08:36:22 +0000 Subject: [PATCH] =?UTF-8?q?=E2=80=9Escripts/ultimo=5Fmeter=5Freadings=5Fre?= =?UTF-8?q?corder.py=E2=80=9C=20l=C3=B6schen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/ultimo_meter_readings_recorder.py | 969 ---------------------- 1 file changed, 969 deletions(-) delete mode 100644 scripts/ultimo_meter_readings_recorder.py diff --git a/scripts/ultimo_meter_readings_recorder.py b/scripts/ultimo_meter_readings_recorder.py deleted file mode 100644 index 7fa0d49..0000000 --- a/scripts/ultimo_meter_readings_recorder.py +++ /dev/null @@ -1,969 +0,0 @@ -import json -import httpx -import base64 -from datetime import datetime, date -from typing import List, Dict, Any, Optional - -def make_graphql_request(query: str, variables: dict = None) -> dict: - """Führt eine GraphQL-Anfrage aus mit Fehlerbehandlung""" - try: - response = httpx.post( - f"{EXTERNAL_BASE_URL}/graphql", - json={"query": query, "variables": variables or {}}, - headers=AUTH_HEADERS, - timeout=30 - ) - response.raise_for_status() - data = response.json() - - if "errors" in data: - error_msg = "; ".join([err.get("message", "Unbekannter Fehler") for err in data["errors"]]) - return {"error": f"GraphQL Fehler: {error_msg}"} - - return data.get("data", {}) - except httpx.TimeoutException: - return {"error": "Timeout bei der Anfrage"} - except httpx.HTTPStatusError as e: - return {"error": f"HTTP Fehler {e.response.status_code}: {e.response.text}"} - except Exception as e: - return {"error": f"Unerwarteter Fehler: {str(e)}"} - -def search_sensors(meter_search: str) -> List[Dict]: - """Sucht Sensoren basierend auf Zählernummer""" - query = """ - query SearchSensors($meterNumber: String!) { - sensorsForMeterNumber(meterNumber: $meterNumber) { - sensorId - sensorName - sensorNameExtern - descr - measureConcept { - id - name - descr - } - } - } - """ - - data = make_graphql_request(query, {"meterNumber": meter_search}) - if "error" in data: - return [] - - return data.get("sensorsForMeterNumber", []) - -def get_variable_units(sensor_id: str) -> List[Dict]: - """Holt verfügbare Variablen und Units für einen Sensor""" - query = """ - query GetVariableUnits($sensorId: ID!) { - availableVariableUnits(sensorId: $sensorId) { - variableUnitId - variableName - unitName - } - } - """ - - data = make_graphql_request(query, {"sensorId": sensor_id}) - if "error" in data: - return [] - - return data.get("availableVariableUnits", []) - -def get_last_observation(sensor_id: str, variable_name: str) -> Optional[Dict]: - """Holt den letzten Zählerstand für einen Sensor""" - query = """ - query GetLastObservation($sensorId: ID!, $variableName: String) { - lastObservation(sensorId: $sensorId, variableName: $variableName) { - id - moment - meterValue - } - } - """ - - data = make_graphql_request(query, {"sensorId": sensor_id, "variableName": variable_name}) - if "error" in data: - return None - - return data.get("lastObservation") - -def record_single_reading(sensor_id: str, moment: str, value: float, variable_name: str, variable_unit: str) -> Dict: - """Erfasst einen einzelnen Zählerstand""" - mutation = """ - mutation RecordSingleReading($input: MeterReadingInput!) { - recordMeterReading(input: $input) { - success - observation { - id - moment - value - meterValue - } - errors { - code - message - details - } - } - } - """ - - input_data = { - "sensorId": sensor_id, - "moment": moment, - "value": value, - "variableName": variable_name, - "variableUnit": variable_unit - } - - return make_graphql_request(mutation, {"input": input_data}) - -def record_ultimo_readings(sensor_id: str, variable_name: str, variable_unit: str, readings: List[Dict]) -> Dict: - """Erfasst mehrere Ultimo-Zählerstände""" - mutation = """ - mutation RecordUltimoReadings($input: UltimoReadingsInput!) { - recordUltimoReadings(input: $input) { - success - created { - id - moment - value - meterValue - } - errors { - code - message - details - } - } - } - """ - - input_data = { - "sensorId": sensor_id, - "variableName": variable_name, - "variableUnit": variable_unit, - "readings": readings - } - - return make_graphql_request(mutation, {"input": input_data}) - -def generate_month_list(start_year: int, start_month: int, end_year: int, end_month: int) -> List[str]: - """Generiert eine Liste von Monaten im Format YYYY-MM""" - months = [] - current_year = start_year - current_month = start_month - - while current_year < end_year or (current_year == end_year and current_month <= end_month): - months.append(f"{current_year:04d}-{current_month:02d}") - current_month += 1 - if current_month > 12: - current_month = 1 - current_year += 1 - - return months - -# Phase Detection -if "sensor_id" not in PARAMS: - # PHASE 1: Sensor Suche - meter_search = PARAMS.get("meter_search", "") - - if not meter_search: - result = { - "type": "error", - "message": "Kein Suchbegriff angegeben" - } - else: - sensors = search_sensors(meter_search) - - if not sensors: - result = { - "type": "html", - "content": f""" -
-
-

⚠️ Keine Sensoren gefunden

-

Für die Suche "{meter_search}" wurden keine Sensoren gefunden.

-
- -
-

💡 Suchtipps:

-
    -
  • Verwenden Sie Teilstrings (z.B. "NG9" statt "NG9_40006_0_12")
  • -
  • Probieren Sie verschiedene Suchbegriffe
  • -
  • Achten Sie auf die korrekte Schreibweise
  • -
-
- -

- ← Zurück zur Suche -

-
- """ - } - else: - # Erstelle Sensor-Dropdown-Optionen mit Zusatzinformationen - sensor_options = [] - for sensor in sensors: - clean_name = sensor["sensorName"].strip() - measure_concept = sensor["measureConcept"] - concept_name = measure_concept["name"].strip() if measure_concept["name"] else "Unbekannt" - concept_desc = measure_concept.get("descr", "") or "" - - label = f"{clean_name} ({concept_name}" - if concept_desc and concept_desc.strip(): - label += f" - {concept_desc.strip()}" - label += ")" - - sensor_options.append({ - "value": sensor["sensorId"], - "label": label - }) - - # Sortiere Optionen alphabetisch - sensor_options.sort(key=lambda x: x["label"]) - - result = { - "type": "form", - "form_definition": { - "title": "Sensor Auswahl und Zählerstand Eingabe", - "description": f"Gefundene Sensoren für Suche: '{meter_search}'", - "layout": "sections", - "sections": [ - { - "title": "Sensor Auswahl", - "icon": "sensors", - "field_names": ["sensor_id", "variable_selection"] - }, - { - "title": "Erfassungsart", - "icon": "input", - "field_names": ["input_method"] - }, - { - "title": "Einzelne Erfassung", - "icon": "schedule", - "field_names": ["single_datetime", "single_value"] - }, - { - "title": "Ultimo Batch-Erfassung", - "icon": "batch_prediction", - "field_names": ["batch_start_year", "batch_start_month", "batch_end_year", "batch_end_month", "batch_values"] - } - ], - "fields": [ - { - "name": "sensor_id", - "widget": "dropdown", - "label": "Sensor auswählen", - "options": sensor_options, - "validators": [ - {"type": "required", "error_text": "Bitte wählen Sie einen Sensor aus"} - ] - }, - { - "name": "variable_selection", - "widget": "text_field", - "label": "Variable wird automatisch geladen...", - "read_only": True, - "initial_value": "Wählen Sie zuerst einen Sensor aus", - "helper_text": "Die verfügbaren Variablen werden nach der Sensor-Auswahl angezeigt" - }, - { - "name": "input_method", - "widget": "segmented_control", - "label": "Erfassungsart", - "initial_value": "single", - "options": [ - {"value": "single", "label": "Einzeln"}, - {"value": "batch", "label": "Batch (Ultimo)"} - ], - "validators": [ - {"type": "required", "error_text": "Bitte wählen Sie eine Erfassungsart"} - ] - }, - { - "name": "single_datetime", - "widget": "date_time_picker", - "label": "Datum und Uhrzeit", - "date_config": { - "input_type": "both", - "format": "dd.MM.yyyy HH:mm" - }, - "conditional": { - "field_name": "input_method", - "operator": "equals", - "value": "single", - "action": "show" - }, - "validators": [ - {"type": "required", "error_text": "Bitte wählen Sie Datum und Uhrzeit"} - ] - }, - { - "name": "single_value", - "widget": "text_field", - "label": "Zählerstand", - "text_field_config": { - "keyboard_type": "number" - }, - "conditional": { - "field_name": "input_method", - "operator": "equals", - "value": "single", - "action": "show" - }, - "validators": [ - {"type": "required", "error_text": "Bitte geben Sie einen Zählerstand ein"}, - {"type": "numeric", "error_text": "Zählerstand muss eine Zahl sein"}, - {"type": "min", "value": 0, "error_text": "Zählerstand darf nicht negativ sein"} - ] - }, - { - "name": "batch_start_year", - "widget": "text_field", - "label": "Start Jahr (YYYY)", - "text_field_config": { - "keyboard_type": "number" - }, - "initial_value": "2024", - "conditional": { - "field_name": "input_method", - "operator": "equals", - "value": "batch", - "action": "show" - }, - "validators": [ - {"type": "required", "error_text": "Jahr ist erforderlich"}, - {"type": "integer", "error_text": "Jahr muss eine ganze Zahl sein"}, - {"type": "between", "value": 2020, "value2": 2030, "error_text": "Jahr muss zwischen 2020 und 2030 liegen"} - ] - }, - { - "name": "batch_start_month", - "widget": "dropdown", - "label": "Start Monat", - "initial_value": "1", - "conditional": { - "field_name": "input_method", - "operator": "equals", - "value": "batch", - "action": "show" - }, - "options": [ - {"value": "1", "label": "Januar"}, - {"value": "2", "label": "Februar"}, - {"value": "3", "label": "März"}, - {"value": "4", "label": "April"}, - {"value": "5", "label": "Mai"}, - {"value": "6", "label": "Juni"}, - {"value": "7", "label": "Juli"}, - {"value": "8", "label": "August"}, - {"value": "9", "label": "September"}, - {"value": "10", "label": "Oktober"}, - {"value": "11", "label": "November"}, - {"value": "12", "label": "Dezember"} - ], - "validators": [ - {"type": "required", "error_text": "Start Monat ist erforderlich"} - ] - }, - { - "name": "batch_end_year", - "widget": "text_field", - "label": "Ende Jahr (YYYY)", - "text_field_config": { - "keyboard_type": "number" - }, - "initial_value": "2024", - "conditional": { - "field_name": "input_method", - "operator": "equals", - "value": "batch", - "action": "show" - }, - "validators": [ - {"type": "required", "error_text": "Jahr ist erforderlich"}, - {"type": "integer", "error_text": "Jahr muss eine ganze Zahl sein"}, - {"type": "between", "value": 2020, "value2": 2030, "error_text": "Jahr muss zwischen 2020 und 2030 liegen"} - ] - }, - { - "name": "batch_end_month", - "widget": "dropdown", - "label": "Ende Monat", - "initial_value": "12", - "conditional": { - "field_name": "input_method", - "operator": "equals", - "value": "batch", - "action": "show" - }, - "options": [ - {"value": "1", "label": "Januar"}, - {"value": "2", "label": "Februar"}, - {"value": "3", "label": "März"}, - {"value": "4", "label": "April"}, - {"value": "5", "label": "Mai"}, - {"value": "6", "label": "Juni"}, - {"value": "7", "label": "Juli"}, - {"value": "8", "label": "August"}, - {"value": "9", "label": "September"}, - {"value": "10", "label": "Oktober"}, - {"value": "11", "label": "November"}, - {"value": "12", "label": "Dezember"} - ], - "validators": [ - {"type": "required", "error_text": "Ende Monat ist erforderlich"} - ] - }, - { - "name": "batch_values", - "widget": "text_field", - "label": "Zählerstände (Komma-getrennt)", - "hint_text": "z.B: 1000.5, 2000.2, 3000.8", - "text_field_config": { - "max_lines": 3 - }, - "conditional": { - "field_name": "input_method", - "operator": "equals", - "value": "batch", - "action": "show" - }, - "helper_text": "Geben Sie die Zählerstände in chronologischer Reihenfolge an, getrennt durch Kommas", - "validators": [ - {"type": "required", "error_text": "Bitte geben Sie die Zählerstände ein"} - ] - } - ], - "submit_label": "Nächster Schritt" - } - } - -else: - # PHASE 2: Variable Auswahl und Verarbeitung - sensor_id = PARAMS.get("sensor_id") - - if not sensor_id: - result = { - "type": "error", - "message": "Sensor ID fehlt" - } - else: - # Prüfe ob bereits variable_name vorhanden ist (Phase 3) - if "variable_name" in PARAMS: - # PHASE 3: Ausführung - variable_name = PARAMS.get("variable_name") - variable_unit = PARAMS.get("variable_unit") - input_method = PARAMS.get("input_method", "single") - - try: - if input_method == "single": - # Einzelne Erfassung - single_datetime = PARAMS.get("single_datetime") - single_value = float(PARAMS.get("single_value", 0)) - - # Konvertiere Datetime zu ISO Format - if isinstance(single_datetime, str): - # Parse verschiedene Datetime-Formate - try: - dt = datetime.fromisoformat(single_datetime.replace('Z', '+00:00')) - except: - dt = datetime.strptime(single_datetime, "%Y-%m-%dT%H:%M:%S") - else: - dt = single_datetime - - iso_datetime = dt.isoformat() - - # Führe Einzelerfassung aus - response = record_single_reading( - sensor_id, iso_datetime, single_value, variable_name, variable_unit - ) - - if "error" in response: - result = { - "type": "html", - "content": f""" -
-
-

❌ Fehler bei der Erfassung

-

{response['error']}

-
-
- """ - } - else: - record_result = response.get("recordMeterReading", {}) - if record_result.get("success"): - obs = record_result.get("observation", {}) - result = { - "type": "html", - "content": f""" -
-
-

✅ Zählerstand erfolgreich erfasst

-

Der Zählerstand wurde erfolgreich gespeichert.

-
- -
-

📊 Erfasste Daten:

- - - - - -
Observation ID:{obs.get('id', 'N/A')}
Zeitpunkt:{obs.get('moment', 'N/A')}
Zählerstand:{obs.get('meterValue', 'N/A')}
Berechneter Wert:{obs.get('value', 'N/A')}
-
-
- """ - } - else: - errors = record_result.get("errors", []) - error_html = "" - - result = { - "type": "html", - "content": f""" -
-
-

❌ Erfassung fehlgeschlagen

-

Die Erfassung konnte nicht durchgeführt werden:

- {error_html} -
-
- """ - } - - else: - # Batch-Erfassung - start_year = int(PARAMS.get("batch_start_year", 2024)) - start_month = int(PARAMS.get("batch_start_month", 1)) - end_year = int(PARAMS.get("batch_end_year", 2024)) - end_month = int(PARAMS.get("batch_end_month", 12)) - batch_values_str = PARAMS.get("batch_values", "") - - # Parse Batch-Werte - try: - values = [float(v.strip()) for v in batch_values_str.split(",") if v.strip()] - except ValueError: - result = { - "type": "error", - "message": "Ungültige Zahlenwerte in Batch-Eingabe. Verwenden Sie nur Zahlen getrennt durch Kommas." - } - else: - # Generiere Monatsliste - months = generate_month_list(start_year, start_month, end_year, end_month) - - if len(values) != len(months): - result = { - "type": "html", - "content": f""" -
-
-

⚠️ Anzahl Unstimmigkeit

-

Anzahl der Werte ({len(values)}) stimmt nicht mit der Anzahl der Monate ({len(months)}) überein.

-

Erwartete Monate: {', '.join(months)}

-
-
- """ - } - else: - # Erstelle Readings-Liste - readings = [] - for i, month in enumerate(months): - readings.append({ - "month": month, - "meterValue": values[i] - }) - - # Führe Batch-Erfassung aus - response = record_ultimo_readings( - sensor_id, variable_name, variable_unit, readings - ) - - if "error" in response: - result = { - "type": "html", - "content": f""" -
-
-

❌ Fehler bei der Batch-Erfassung

-

{response['error']}

-
-
- """ - } - else: - batch_result = response.get("recordUltimoReadings", {}) - created = batch_result.get("created", []) - errors = batch_result.get("errors", []) - success = batch_result.get("success", False) - - html_content = f""" -
- """ - - if success and created: - html_content += f""" -
-

✅ Batch-Erfassung erfolgreich

-

{len(created)} Zählerstände wurden erfolgreich erfasst.

-
- -
-

📊 Erfasste Readings:

- - - - - - - - - - - """ - - for i, obs in enumerate(created): - bg_color = "#f8f9fa" if i % 2 == 0 else "white" - html_content += f""" - - - - - - - """ - - html_content += """ - -
IDZeitpunktZählerstandWert
{obs.get('id', 'N/A')}{obs.get('moment', 'N/A')}{obs.get('meterValue', 'N/A')}{obs.get('value', 'N/A')}
-
- """ - - if errors: - html_content += f""" -
-

⚠️ Warnungen/Fehler:

-
    - """ - - for err in errors: - html_content += f"
  • {err.get('code', 'ERROR')}: {err.get('message', 'Unbekannter Fehler')}" - if err.get('details'): - html_content += f" (Details: {err.get('details')})" - html_content += "
  • " - - html_content += "
" - - if not success and not created: - html_content += f""" -
-

❌ Batch-Erfassung fehlgeschlagen

-

Die Erfassung konnte nicht durchgeführt werden.

-
- """ - - html_content += "
" - - result = { - "type": "html", - "content": html_content - } - - except Exception as e: - result = { - "type": "error", - "message": f"Fehler bei der Verarbeitung: {str(e)}" - } - - else: - # PHASE 2: Variable Auswahl - variable_units = get_variable_units(sensor_id) - - if not variable_units: - result = { - "type": "error", - "message": "Keine Variablen für diesen Sensor gefunden" - } - else: - # Erstelle Variable-Dropdown-Optionen - variable_options = [] - for vu in variable_units: - clean_var_name = vu["variableName"].strip() - clean_unit_name = vu["unitName"].strip() - label = f"{clean_var_name} ({clean_unit_name})" - - variable_options.append({ - "value": f"{clean_var_name}|{clean_unit_name}", - "label": label - }) - - # Sortiere Optionen alphabetisch - variable_options.sort(key=lambda x: x["label"]) - - # Hole letzten Zählerstand für Kontext - last_obs = None - if variable_options: - # Verwende erste Variable für Kontext - first_var = variable_options[0]["value"].split("|")[0] - last_obs = get_last_observation(sensor_id, first_var) - - context_info = "" - if last_obs: - context_info = f"Letzter bekannter Zählerstand: {last_obs.get('meterValue', 'N/A')} am {last_obs.get('moment', 'N/A')}" - else: - context_info = "Kein vorheriger Zählerstand gefunden" - - # Übertrage alle Parameter aus der ersten Phase - result = { - "type": "form", - "form_definition": { - "title": "Variable Auswahl und Zählerstand Eingabe", - "description": context_info, - "layout": "sections", - "sections": [ - { - "title": "Variable/Einheit", - "icon": "analytics", - "field_names": ["variable_selection"] - }, - { - "title": "Erfassungsart", - "icon": "input", - "field_names": ["input_method"] - }, - { - "title": "Einzelne Erfassung", - "icon": "schedule", - "field_names": ["single_datetime", "single_value"] - }, - { - "title": "Ultimo Batch-Erfassung", - "icon": "batch_prediction", - "field_names": ["batch_start_year", "batch_start_month", "batch_end_year", "batch_end_month", "batch_values"] - } - ], - "fields": [ - # Versteckte Felder für übertragene Parameter - { - "name": "sensor_id", - "widget": "text_field", - "label": "Sensor ID", - "initial_value": sensor_id, - "read_only": True, - "enabled": False - }, - { - "name": "variable_selection", - "widget": "dropdown", - "label": "Variable und Einheit auswählen", - "options": variable_options, - "validators": [ - {"type": "required", "error_text": "Bitte wählen Sie eine Variable aus"} - ] - }, - { - "name": "input_method", - "widget": "segmented_control", - "label": "Erfassungsart", - "initial_value": PARAMS.get("input_method", "single"), - "options": [ - {"value": "single", "label": "Einzeln"}, - {"value": "batch", "label": "Batch (Ultimo)"} - ], - "validators": [ - {"type": "required", "error_text": "Bitte wählen Sie eine Erfassungsart"} - ] - }, - { - "name": "single_datetime", - "widget": "date_time_picker", - "label": "Datum und Uhrzeit", - "initial_value": PARAMS.get("single_datetime", datetime.now().isoformat()), - "date_config": { - "input_type": "both", - "format": "dd.MM.yyyy HH:mm" - }, - "conditional": { - "field_name": "input_method", - "operator": "equals", - "value": "single", - "action": "show" - }, - "validators": [ - {"type": "required", "error_text": "Bitte wählen Sie Datum und Uhrzeit"} - ] - }, - { - "name": "single_value", - "widget": "text_field", - "label": "Zählerstand", - "initial_value": PARAMS.get("single_value", ""), - "text_field_config": { - "keyboard_type": "number" - }, - "conditional": { - "field_name": "input_method", - "operator": "equals", - "value": "single", - "action": "show" - }, - "validators": [ - {"type": "required", "error_text": "Bitte geben Sie einen Zählerstand ein"}, - {"type": "numeric", "error_text": "Zählerstand muss eine Zahl sein"}, - {"type": "min", "value": 0, "error_text": "Zählerstand darf nicht negativ sein"} - ] - }, - { - "name": "batch_start_year", - "widget": "text_field", - "label": "Start Jahr (YYYY)", - "initial_value": PARAMS.get("batch_start_year", "2024"), - "text_field_config": { - "keyboard_type": "number" - }, - "conditional": { - "field_name": "input_method", - "operator": "equals", - "value": "batch", - "action": "show" - }, - "validators": [ - {"type": "required", "error_text": "Jahr ist erforderlich"}, - {"type": "integer", "error_text": "Jahr muss eine ganze Zahl sein"}, - {"type": "between", "value": 2020, "value2": 2030, "error_text": "Jahr muss zwischen 2020 und 2030 liegen"} - ] - }, - { - "name": "batch_start_month", - "widget": "dropdown", - "label": "Start Monat", - "initial_value": PARAMS.get("batch_start_month", "1"), - "conditional": { - "field_name": "input_method", - "operator": "equals", - "value": "batch", - "action": "show" - }, - "options": [ - {"value": "1", "label": "Januar"}, - {"value": "2", "label": "Februar"}, - {"value": "3", "label": "März"}, - {"value": "4", "label": "April"}, - {"value": "5", "label": "Mai"}, - {"value": "6", "label": "Juni"}, - {"value": "7", "label": "Juli"}, - {"value": "8", "label": "August"}, - {"value": "9", "label": "September"}, - {"value": "10", "label": "Oktober"}, - {"value": "11", "label": "November"}, - {"value": "12", "label": "Dezember"} - ], - "validators": [ - {"type": "required", "error_text": "Start Monat ist erforderlich"} - ] - }, - { - "name": "batch_end_year", - "widget": "text_field", - "label": "Ende Jahr (YYYY)", - "initial_value": PARAMS.get("batch_end_year", "2024"), - "text_field_config": { - "keyboard_type": "number" - }, - "conditional": { - "field_name": "input_method", - "operator": "equals", - "value": "batch", - "action": "show" - }, - "validators": [ - {"type": "required", "error_text": "Jahr ist erforderlich"}, - {"type": "integer", "error_text": "Jahr muss eine ganze Zahl sein"}, - {"type": "between", "value": 2020, "value2": 2030, "error_text": "Jahr muss zwischen 2020 und 2030 liegen"} - ] - }, - { - "name": "batch_end_month", - "widget": "dropdown", - "label": "Ende Monat", - "initial_value": PARAMS.get("batch_end_month", "12"), - "conditional": { - "field_name": "input_method", - "operator": "equals", - "value": "batch", - "action": "show" - }, - "options": [ - {"value": "1", "label": "Januar"}, - {"value": "2", "label": "Februar"}, - {"value": "3", "label": "März"}, - {"value": "4", "label": "April"}, - {"value": "5", "label": "Mai"}, - {"value": "6", "label": "Juni"}, - {"value": "7", "label": "Juli"}, - {"value": "8", "label": "August"}, - {"value": "9", "label": "September"}, - {"value": "10", "label": "Oktober"}, - {"value": "11", "label": "November"}, - {"value": "12", "label": "Dezember"} - ], - "validators": [ - {"type": "required", "error_text": "Ende Monat ist erforderlich"} - ] - }, - { - "name": "batch_values", - "widget": "text_field", - "label": "Zählerstände (Komma-getrennt)", - "initial_value": PARAMS.get("batch_values", ""), - "hint_text": "z.B: 1000.5, 2000.2, 3000.8", - "text_field_config": { - "max_lines": 3 - }, - "conditional": { - "field_name": "input_method", - "operator": "equals", - "value": "batch", - "action": "show" - }, - "helper_text": "Geben Sie die Zählerstände in chronologischer Reihenfolge an, getrennt durch Kommas", - "validators": [ - {"type": "required", "error_text": "Bitte geben Sie die Zählerstände ein"} - ] - } - ], - "submit_label": "Zählerstände erfassen" - } - } - - # Erweitere das Form um die variable_name und variable_unit basierend auf variable_selection - if "variable_selection" in PARAMS: - var_selection = PARAMS["variable_selection"] - if "|" in var_selection: - var_name, var_unit = var_selection.split("|", 1) - # Füge versteckte Felder hinzu - result["form_definition"]["fields"].extend([ - { - "name": "variable_name", - "widget": "text_field", - "label": "Variable Name", - "initial_value": var_name, - "read_only": True, - "enabled": False - }, - { - "name": "variable_unit", - "widget": "text_field", - "label": "Variable Unit", - "initial_value": var_unit, - "read_only": True, - "enabled": False - } - ])