From c00682787d29fb2547aa2fd27047af161c3acfea Mon Sep 17 00:00:00 2001 From: Andrea Casarin Date: Sat, 10 Oct 2026 14:38:34 +0200 Subject: [PATCH] fix(config): clarify phonebook source and independent SGA changes --- custom_components/vimar_intercom/options_flow.py | 12 +++++++++--- custom_components/vimar_intercom/strings.json | 2 +- .../vimar_intercom/translations/en.json | 2 +- .../vimar_intercom/translations/it.json | 2 +- tests/test_config_flow_steps.py | 15 +++++++++++++++ 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/custom_components/vimar_intercom/options_flow.py b/custom_components/vimar_intercom/options_flow.py index db986e5..00b9adb 100644 --- a/custom_components/vimar_intercom/options_flow.py +++ b/custom_components/vimar_intercom/options_flow.py @@ -334,6 +334,7 @@ def __init__(self, config_entry: config_entries.ConfigEntry) -> None: # PICG dichiarato dal citofono stesso (get_info.php?action=nickname). # Resta None quando la rubrica arriva da un file caricato a mano. self._picg_from_rest: str | None = None + self._phonebook_source = "rubrica.db" async def async_step_init( self, user_input: dict | None = None @@ -720,6 +721,7 @@ def _fetch() -> tuple[dict, str | None]: self._imported = result self._imported_gid = gid self._picg_from_rest = picg + self._phonebook_source = "Tab" return await self.async_step_import_confirm() return self.async_show_form( @@ -823,6 +825,7 @@ def _fetch() -> dict: self._imported = result self._imported_gid = gid self._picg_from_rest = None + self._phonebook_source = "Vimar cloud" return await self.async_step_import_confirm() return self.async_show_form( @@ -873,6 +876,8 @@ def _load() -> dict: else: self._imported = result self._imported_gid = gid + self._picg_from_rest = None + self._phonebook_source = "rubrica.db" return await self.async_step_import_confirm() return self.async_show_form( @@ -961,7 +966,7 @@ async def async_step_import_confirm( if sga and sga != current_sga: sga_info = ( f"{sga} — diverso da quello attualmente configurato ({current_sga}); " - "confermando verrà impostato come nuovo sga_target/picg_target." + "confermando verrà impostato come nuovo sga_target." ) elif sga: sga_info = f"{sga} — coincide con quello già in uso." @@ -980,11 +985,11 @@ async def async_step_import_confirm( picg_info = f"{self._picg_from_rest} — dichiarato dal citofono, coincide con quello già in uso." elif configured_picg: picg_info = ( - f"non richiesto (rubrica da file): resta quello già configurato ({configured_picg})." + f"non rilevato dalla fonte della rubrica: resta quello già configurato ({configured_picg})." ) else: picg_info = ( - f"non richiesto (rubrica da file) e non ancora configurato: verrà impostato " + f"non rilevato dalla fonte della rubrica e non ancora configurato: verrà impostato " f"uguale all'SGA ({new_picg})." ) @@ -1027,6 +1032,7 @@ async def async_step_import_confirm( "count": str(len(actuators)), "names": ", ".join(a["name"] for a in actuators) or "—", "gid": self._imported_gid, + "source": self._phonebook_source, "sga_info": sga_info, "picg_info": picg_info, "camera_info": camera_info, diff --git a/custom_components/vimar_intercom/strings.json b/custom_components/vimar_intercom/strings.json index a0dbc04..4df5ab5 100644 --- a/custom_components/vimar_intercom/strings.json +++ b/custom_components/vimar_intercom/strings.json @@ -167,7 +167,7 @@ }, "import_confirm": { "title": "Conferma importazione", - "description": "Trovati {count} attuatori per il GID {gid}: {names}.\n\nSGA (MAGIC_APT_INTERCOM) rilevato: {sga_info}\n\nPICG rilevato: {picg_info}\n\nTarga video (camera) rilevata: {camera_info}\n\nTarga che apre la porta rilevata: {door_info}\n\nConfermando, questa lista SOSTITUISCE gli attuatori attualmente configurati e, se rilevato, aggiorna sga_target/picg_target/camera_target/door_target. Per annullare, chiudi questa finestra senza confermare." + "description": "Fonte della rubrica: {source}.\n\nTrovati {count} attuatori per il GID {gid}: {names}.\n\nSGA (MAGIC_APT_INTERCOM) rilevato: {sga_info}\n\nPICG rilevato: {picg_info}\n\nTarga video (camera) rilevata: {camera_info}\n\nTarga che apre la porta rilevata: {door_info}\n\nConfermando, questa lista SOSTITUISCE gli attuatori attualmente configurati e, se rilevato, aggiorna sga_target/picg_target/camera_target/door_target. Per annullare, chiudi questa finestra senza confermare." }, "fetch_rubrica": { "title": "Scarica dal citofono", diff --git a/custom_components/vimar_intercom/translations/en.json b/custom_components/vimar_intercom/translations/en.json index 69341be..e2d2a30 100644 --- a/custom_components/vimar_intercom/translations/en.json +++ b/custom_components/vimar_intercom/translations/en.json @@ -167,7 +167,7 @@ }, "import_confirm": { "title": "Confirm import", - "description": "Found {count} actuators for GID {gid}: {names}.\n\nDetected SGA (MAGIC_APT_INTERCOM): {sga_info}\n\nPICG detected: {picg_info}\n\nVideo entrance panel (camera) detected: {camera_info}\n\nDoor panel detected: {door_info}\n\nConfirming REPLACES the currently configured actuators and, when detected, updates sga_target/picg_target/camera_target/door_target. To cancel, close this window without confirming." + "description": "Phonebook source: {source}.\n\nFound {count} actuators for GID {gid}: {names}.\n\nDetected SGA (MAGIC_APT_INTERCOM): {sga_info}\n\nPICG detected: {picg_info}\n\nVideo entrance panel (camera) detected: {camera_info}\n\nDoor panel detected: {door_info}\n\nConfirming REPLACES the currently configured actuators and, when detected, updates sga_target/picg_target/camera_target/door_target. To cancel, close this window without confirming." }, "fetch_rubrica": { "title": "Download from the intercom", diff --git a/custom_components/vimar_intercom/translations/it.json b/custom_components/vimar_intercom/translations/it.json index a0dbc04..4df5ab5 100644 --- a/custom_components/vimar_intercom/translations/it.json +++ b/custom_components/vimar_intercom/translations/it.json @@ -167,7 +167,7 @@ }, "import_confirm": { "title": "Conferma importazione", - "description": "Trovati {count} attuatori per il GID {gid}: {names}.\n\nSGA (MAGIC_APT_INTERCOM) rilevato: {sga_info}\n\nPICG rilevato: {picg_info}\n\nTarga video (camera) rilevata: {camera_info}\n\nTarga che apre la porta rilevata: {door_info}\n\nConfermando, questa lista SOSTITUISCE gli attuatori attualmente configurati e, se rilevato, aggiorna sga_target/picg_target/camera_target/door_target. Per annullare, chiudi questa finestra senza confermare." + "description": "Fonte della rubrica: {source}.\n\nTrovati {count} attuatori per il GID {gid}: {names}.\n\nSGA (MAGIC_APT_INTERCOM) rilevato: {sga_info}\n\nPICG rilevato: {picg_info}\n\nTarga video (camera) rilevata: {camera_info}\n\nTarga che apre la porta rilevata: {door_info}\n\nConfermando, questa lista SOSTITUISCE gli attuatori attualmente configurati e, se rilevato, aggiorna sga_target/picg_target/camera_target/door_target. Per annullare, chiudi questa finestra senza confermare." }, "fetch_rubrica": { "title": "Scarica dal citofono", diff --git a/tests/test_config_flow_steps.py b/tests/test_config_flow_steps.py index 5c09dbe..57a357a 100644 --- a/tests/test_config_flow_steps.py +++ b/tests/test_config_flow_steps.py @@ -498,6 +498,7 @@ def test_the_phonebook_from_the_intercom_leads_to_the_confirmation_with_its_picg assert result["step_id"] == "import_confirm" assert calls == [("download", "192.0.2.1", "60999", "rubrica"), ("parse", "101")] assert "61000" in result["description_placeholders"]["picg_info"] + assert result["description_placeholders"]["source"] == "Tab" def test_missing_nicknames_do_not_spoil_the_import(of, monkeypatch): @@ -584,6 +585,8 @@ def download(cdomain, cproxy, token, ver): hub = _Hub({"init_status": {"token": "tok"}, "rubrica_ver": "abc"}) result = asyncio.run(_cloud_flow(of, hub, data).async_step_fetch_rubrica_cloud({"rubrica_gid": "101"})) assert result["step_id"] == "import_confirm" and seen["cdomain"] == "plant.relay.example.test" + assert result["description_placeholders"]["source"] == "Vimar cloud" + assert "rubrica da file" not in result["description_placeholders"]["picg_info"] def test_missing_cloud_data_is_named(of): @@ -645,6 +648,7 @@ def parse(path, gid): result = asyncio.run(_options_flow(of).async_step_import_rubrica({"rubrica_file": "up1", "rubrica_gid": ""})) assert result["step_id"] == "import_confirm" assert seen == ["up1"] and parsed_paths == [("/tmp/uploads/up1.db", "101")] + assert result["description_placeholders"]["source"] == "rubrica.db" def test_an_unreadable_upload_is_refused(of, monkeypatch): @@ -760,3 +764,14 @@ def test_the_av_key_page_is_translated(of): assert set(page["data"]) == {"regenerate"}, name # hassfest refuses anything that looks like HTML, `` included. assert "<" not in json.dumps(page, ensure_ascii=False), name + + +def test_import_summary_keeps_sga_and_picg_changes_separate(of): + flow = _confirm_flow(of, {"actuators": ACTUATORS, "sga": "53011"}, + {"sga_target": "53010", "picg_target": "52011"}) + form = asyncio.run(flow.async_step_import_confirm()) + saved = asyncio.run(flow.async_step_import_confirm({})) + assert "sga_target/picg_target" not in form["description_placeholders"]["sga_info"] + assert "52011" in form["description_placeholders"]["picg_info"] + assert saved["data"]["sga_target"] == "53011" + assert saved["data"]["picg_target"] == "52011"