From 4f125cee8f2191f4410d333eea951e47317270d0 Mon Sep 17 00:00:00 2001 From: David Vogt Date: Tue, 4 Apr 2023 11:21:17 +0200 Subject: [PATCH] fix(scopes): update subscope's full names when scope changes This will ensure that the sub scope's full_name will be correct even after a parent's scope was renamed. --- emeis/core/models.py | 6 ++++++ emeis/core/tests/snapshots/snap_test_api.py | 2 ++ emeis/core/tests/test_models.py | 20 +++++++++++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/emeis/core/models.py b/emeis/core/models.py index c800ad7..10e4ca6 100644 --- a/emeis/core/models.py +++ b/emeis/core/models.py @@ -219,6 +219,12 @@ def set_full_name(instance, sender, **kwargs): instance.full_name.clear() instance.full_name[forced_lang] = full_name + # Force update of all children (recursively) + for child in instance.children.all(): + # save() triggers the set_full_name signal handler, which will + # recurse all the way down, updating the full_name + child.save() + class Role(SlugModel): name = LocalizedCharField(_("role name"), blank=False, null=False, required=False) diff --git a/emeis/core/tests/snapshots/snap_test_api.py b/emeis/core/tests/snapshots/snap_test_api.py index 485ea4d..c69bebc 100644 --- a/emeis/core/tests/snapshots/snap_test_api.py +++ b/emeis/core/tests/snapshots/snap_test_api.py @@ -155,6 +155,7 @@ snapshots["test_api_create[ScopeViewSet] 1"] = { "queries": [ 'SELECT MAX("emeis_core_scope"."tree_id") AS "tree_id__max" FROM "emeis_core_scope"', + 'SELECT "emeis_core_scope"."created_at", "emeis_core_scope"."modified_at", "emeis_core_scope"."created_by_user_id", "emeis_core_scope"."metainfo", "emeis_core_scope"."id", "emeis_core_scope"."name", "emeis_core_scope"."full_name", "emeis_core_scope"."description", "emeis_core_scope"."parent_id", "emeis_core_scope"."is_active", "emeis_core_scope"."lft", "emeis_core_scope"."rght", "emeis_core_scope"."tree_id", "emeis_core_scope"."level" FROM "emeis_core_scope" WHERE "emeis_core_scope"."parent_id" = \'f561aaf6-ef0b-f14d-4208-bb46a4ccb3ad\'::uuid ORDER BY "emeis_core_scope"."tree_id" ASC, "emeis_core_scope"."lft" ASC', """INSERT INTO "emeis_core_scope" ("created_at", "modified_at", "created_by_user_id", "metainfo", "id", "name", "full_name", "description", "parent_id", "is_active", "lft", "rght", "tree_id", "level") VALUES (\'2017-05-21T00:00:00+00:00\'::timestamptz, \'2017-05-21T00:00:00+00:00\'::timestamptz, \'9336ebf2-5087-d91c-818e-e6e9ec29f8c1\'::uuid, \'{}\', \'f561aaf6-ef0b-f14d-4208-bb46a4ccb3ad\'::uuid, hstore(ARRAY[\'en\',\'de\',\'fr\'], ARRAY[\'Pamela Horton\',\'\',\'\']), hstore(ARRAY[\'en\',\'de\',\'fr\'], ARRAY[\'Pamela Horton\',\'Pamela Horton\',\'Pamela Horton\']), hstore(ARRAY[\'en\',\'de\',\'fr\'], ARRAY[\'Effort meet relationship far. Option program interesting station. First where during teach country talk across. Argue move appear catch toward help wind. Material minute ago get.','','']), NULL, true, 1, 2, 1, 0)""", ], @@ -1544,6 +1545,7 @@ "queries": [ 'SELECT "emeis_core_scope"."created_at", "emeis_core_scope"."modified_at", "emeis_core_scope"."created_by_user_id", "emeis_core_scope"."metainfo", "emeis_core_scope"."id", "emeis_core_scope"."name", "emeis_core_scope"."full_name", "emeis_core_scope"."description", "emeis_core_scope"."parent_id", "emeis_core_scope"."is_active", "emeis_core_scope"."lft", "emeis_core_scope"."rght", "emeis_core_scope"."tree_id", "emeis_core_scope"."level" FROM "emeis_core_scope" WHERE "emeis_core_scope"."id" = \'9dd4e461-268c-8034-f5c8-564e155c67a6\'::uuid LIMIT 21', 'SELECT "emeis_core_acl"."created_at", "emeis_core_acl"."modified_at", "emeis_core_acl"."created_by_user_id", "emeis_core_acl"."metainfo", "emeis_core_acl"."id", "emeis_core_acl"."user_id", "emeis_core_acl"."scope_id", "emeis_core_acl"."role_id", "emeis_core_user"."password", "emeis_core_user"."last_login", "emeis_core_user"."created_at", "emeis_core_user"."modified_at", "emeis_core_user"."created_by_user_id", "emeis_core_user"."metainfo", "emeis_core_user"."id", "emeis_core_user"."username", "emeis_core_user"."first_name", "emeis_core_user"."last_name", "emeis_core_user"."email", "emeis_core_user"."phone", "emeis_core_user"."language", "emeis_core_user"."address", "emeis_core_user"."city", "emeis_core_user"."zip", "emeis_core_user"."is_active", "emeis_core_user"."date_joined", "emeis_core_scope"."created_at", "emeis_core_scope"."modified_at", "emeis_core_scope"."created_by_user_id", "emeis_core_scope"."metainfo", "emeis_core_scope"."id", "emeis_core_scope"."name", "emeis_core_scope"."full_name", "emeis_core_scope"."description", "emeis_core_scope"."parent_id", "emeis_core_scope"."is_active", "emeis_core_scope"."lft", "emeis_core_scope"."rght", "emeis_core_scope"."tree_id", "emeis_core_scope"."level", "emeis_core_role"."created_at", "emeis_core_role"."modified_at", "emeis_core_role"."created_by_user_id", "emeis_core_role"."metainfo", "emeis_core_role"."slug", "emeis_core_role"."name", "emeis_core_role"."description" FROM "emeis_core_acl" INNER JOIN "emeis_core_scope" ON ("emeis_core_acl"."scope_id" = "emeis_core_scope"."id") INNER JOIN "emeis_core_user" ON ("emeis_core_acl"."user_id" = "emeis_core_user"."id") INNER JOIN "emeis_core_role" ON ("emeis_core_acl"."role_id" = "emeis_core_role"."slug") WHERE "emeis_core_acl"."scope_id" IN (\'9dd4e461-268c-8034-f5c8-564e155c67a6\'::uuid)', + 'SELECT "emeis_core_scope"."created_at", "emeis_core_scope"."modified_at", "emeis_core_scope"."created_by_user_id", "emeis_core_scope"."metainfo", "emeis_core_scope"."id", "emeis_core_scope"."name", "emeis_core_scope"."full_name", "emeis_core_scope"."description", "emeis_core_scope"."parent_id", "emeis_core_scope"."is_active", "emeis_core_scope"."lft", "emeis_core_scope"."rght", "emeis_core_scope"."tree_id", "emeis_core_scope"."level" FROM "emeis_core_scope" WHERE "emeis_core_scope"."parent_id" = \'9dd4e461-268c-8034-f5c8-564e155c67a6\'::uuid ORDER BY "emeis_core_scope"."tree_id" ASC, "emeis_core_scope"."lft" ASC', """UPDATE "emeis_core_scope" SET "created_at" = \'2017-05-21T00:00:00+00:00\'::timestamptz, "modified_at" = \'2017-05-21T00:00:00+00:00\'::timestamptz, "created_by_user_id" = NULL, "metainfo" = \'{}\', "name" = hstore(ARRAY[\'en\',\'de\',\'fr\'], ARRAY[\'Pamela Horton\',\'\',\'\']), "full_name" = hstore(ARRAY[\'en\',\'de\',\'fr\'], ARRAY[\'Pamela Horton\',\'Pamela Horton\',\'Pamela Horton\']), "description" = hstore(ARRAY[\'en\',\'de\',\'fr\'], ARRAY[\'Effort meet relationship far. Option program interesting station. First where during teach country talk across. Argue move appear catch toward help wind. Material minute ago get.\',\'\',\'\']), "parent_id" = NULL, "is_active" = true WHERE "emeis_core_scope"."id" = \'9dd4e461-268c-8034-f5c8-564e155c67a6\'::uuid""", ], diff --git a/emeis/core/tests/test_models.py b/emeis/core/tests/test_models.py index 729732e..8a70147 100644 --- a/emeis/core/tests/test_models.py +++ b/emeis/core/tests/test_models.py @@ -113,7 +113,6 @@ def test_scope_hierarchical_name_fallbacks( @pytest.mark.parametrize("language", ["de", "fr"]) def test_scope_fullname_when_forced_language(db, language, scope_factory, settings): - settings.LANGUAGE_CODE = "de" settings.LANGUAGES = [("de", "de"), ("fr", "fr")] settings.EMEIS_FORCE_MODEL_LOCALE = {"scope": "de"} @@ -129,3 +128,22 @@ def test_scope_fullname_when_forced_language(db, language, scope_factory, settin grandchild.save() assert grandchild.full_name.de == "DE ROOT » DE CHILD » DE GRANDCHILD" assert grandchild.full_name.fr == "" + + +def test_update_full_name_of_child(db, scope_factory): + root = scope_factory(parent=None, name="r") + child = scope_factory(parent=root, name="c") + grandchild = scope_factory(parent=child, name="g") + + # full name should be r -> c -> g + assert str(grandchild.full_name) == "r » c » g" + + sibling = scope_factory(parent=root, name="s") + + # move parent of grandchild - this should trigger an + # update on the grandchild's full name + child.parent = sibling + child.save() + + grandchild.refresh_from_db() + assert str(grandchild.full_name) == "r » s » c » g"