Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Entity justification #116

Merged
merged 29 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ba0e575
Add entity reason to backend.
mo-fu Jun 6, 2024
e02e2df
Add toggle for showing most recent entity reason in UI.
mo-fu Jun 6, 2024
50c9b2b
Refactor comments to be transferable for entity reason history.
mo-fu Jun 6, 2024
79cddc0
Add backend methods for retrieving and posting entity reasons.
mo-fu Jun 10, 2024
479fd5d
Add UI components for showing reason history and adding new resons.
mo-fu Jun 10, 2024
a4ae433
Rename Entity Reason to Justification.
mo-fu Jun 12, 2024
c835f7b
Fix offset bug for editing tags when justification is shown.
mo-fu Jun 12, 2024
85d64e6
Add entity justification to download.
mo-fu Jun 13, 2024
86e2116
Add duplicate check for entity justifications.
mo-fu Jun 13, 2024
f114508
Adapt tests to changes in contribution stepper
mo-fu Jun 14, 2024
41238d6
Add logic for already existing justification to UI.
mo-fu Jun 14, 2024
85430ec
Add justification to setting entity duplicate.
mo-fu Jun 19, 2024
51b828a
Add handling of justification to ingestion and column assignment.
mo-fu Jun 19, 2024
9d8669f
Expose contribution justification to API
mo-fu Jun 20, 2024
9cea38e
Add justification handling to entity matching.
mo-fu Jun 26, 2024
3f2df77
Add check for justification to entity match queue processing.
mo-fu Jun 26, 2024
8c99b71
Add django plugin for pylint to dev dependencies.
mo-fu Jun 26, 2024
35afc35
Add preview of justifications.
mo-fu Jun 27, 2024
0f8ffc3
Add justification to contribution entity chunks API endpoint.
mo-fu Jun 27, 2024
1fc9a66
Add justification to check for column assignment.
mo-fu Jun 27, 2024
73c95ae
Catch missing values during justification ingestion.
mo-fu Jun 27, 2024
3ee81a0
Fix bug in justification handling during entity match step.
mo-fu Jun 28, 2024
98074c6
Copy justifications during duplicate removal.
mo-fu Jun 28, 2024
233f116
Copy justifications for merging entities.
mo-fu Jun 28, 2024
5ca7018
Add timezone to all dates and timestamps.
mo-fu Jun 28, 2024
45953b8
Refacor some remaining occurences of Remote class to interface variant.
mo-fu Jul 2, 2024
da3d63d
Keep justification for all entities, even when duplicate is assigned.
mo-fu Jul 2, 2024
48e92d4
Always update justification of contribution.
mo-fu Jul 2, 2024
0ddb0a4
Improve and fix workflow for adding justifications.
mo-fu Jul 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
[MASTER]
ignore=manage.py
ignore-paths=vran/migrations
load-plugins=pylint_django
django-settings-module=tests.settings
3 changes: 2 additions & 1 deletion django_project/settings/settings_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.1/ref/settings/
"""

# pylint: disable=duplicate-code

from os import environ
Expand Down Expand Up @@ -85,7 +86,7 @@ def get_file_secret(secret_name):
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
# "django.contrib.postgres",
"django.contrib.postgres",
"corsheaders",
"django_rq",
"vran",
Expand Down
36 changes: 35 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ requests = "^2.28.1"
python-dotenv = "^0.21.0"
pytest-redis = "^3.0.2"
pip = "^24.0"
pylint-django = "^2.5.5"

[build-system]
requires = ["poetry-core"]
Expand Down
24 changes: 23 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from tests.tag import common as ct
from tests.user import common as cu
from tests.user.api.integration.requests import post_login, post_register
from vran.entity.models_django import Entity
from vran.entity.models_django import Entity, EntityJustification
from vran.management.display_txt.util import DISPLAY_TXT_ORDER_CONFIG_KEY
from vran.management.models_django import ConfigValue
from vran.tag.models_django import TagDefinition, TagDefinitionHistory
Expand Down Expand Up @@ -66,6 +66,28 @@ def entity2(user1):
return entity


@pytest.fixture()
def justification0(user):
EntityJustification.add(
ce.id_justification_0,
ce.id_persistent_test_0,
ce.justification_0,
ce.time_justification_0,
user,
)


@pytest.fixture()
def justification1(user1):
EntityJustification.add(
ce.id_justification_1,
ce.id_persistent_test_1,
ce.justification_1,
ce.time_justification_1,
user1,
)


@pytest.fixture()
def tag_def(user):
return TagDefinitionHistory.objects.create( # pylint: disable=no-member
Expand Down
6 changes: 4 additions & 2 deletions tests/contribution/api/integration/common.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# pylint: disable=missing-module-docstring, missing-function-docstring,redefined-outer-name,invalid-name,disable=unused-argument
from datetime import datetime
from datetime import datetime, timezone

import tests.contribution.common as c
import tests.user.common as cu
Expand All @@ -25,6 +25,7 @@
"error_msg": None,
"error_details": None,
"empty_values": "null,nan,na",
"justification_txt": None,
}

contribution_test_upload1 = {
Expand All @@ -36,6 +37,7 @@
"error_msg": None,
"error_details": None,
"empty_values": "null,nan,na",
"justification_txt": None,
}

tag_def_test0 = {
Expand All @@ -55,4 +57,4 @@
}

id_tag_merge_request_persistent = "ab6a456e-4560-458b-9f8d-864bdcccc904"
time_edit_tag_merge_request = datetime(2020, 2, 3)
time_edit_tag_merge_request = datetime(2020, 2, 3, tzinfo=timezone.utc)
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,5 @@ def test_get_with_error(auth_server, contribution_error):
"error_details": contribution_error.error_trace,
"match_tag_definition_list": [],
"empty_values": "null,nan,na",
"justification_txt": None,
}
11 changes: 11 additions & 0 deletions tests/contribution/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ def contribution_tag_def_assigned(contribution_user, tag_def):
)


@pytest.fixture
def contribution_tag_def_assigned_justification(contribution_user, tag_def):
return TagDefinitionContribution.objects.create( # pylint:disable=no-member
name=c.name_definition_test0,
id_persistent=c.id_persistent_tag_def_test0,
contribution_candidate=contribution_user,
index_in_file=9000,
id_existing_persistent="justification",
)


@pytest.fixture
def contribution_tag_def_assigned_display_txt(contribution_user, tag_def):
return TagDefinitionContribution.objects.create( # pylint:disable=no-member
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def test_get_chunk(auth_server, contribution_candidate, entities):
"display_txt": c.display_txt_test_entity_duplicate,
"display_txt_details": "Display Text",
"disabled": False,
"justification_txt": None,
}
]
},
Expand Down
113 changes: 107 additions & 6 deletions tests/contribution/entity/api/integration/put_duplicate_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,24 @@
import tests.contribution.entity.common as c
import tests.entity.common as ce
from vran.contribution.entity.models_django import EntityDuplicate
from vran.contribution.models_django import ContributionCandidate
from vran.entity.models_django import EntityJustification

justification = "justification for entity"


def test_no_cookies(auth_server):
live_server, _ = auth_server
rsp = r.put_duplicate(
live_server.url, "contribution_id", "id_origin", "id_destination", []
live_server.url, "contribution_id", "id_origin", "id_destination", cookies=None
)
assert rsp.status_code == 401


def test_no_candidate(auth_server):
live_server, cookies = auth_server
rsp = r.put_duplicate(
live_server.url, str(uuid4()), "id_origin", "id_destination", cookies
live_server.url, str(uuid4()), "id_origin", "id_destination", cookies=cookies
)
assert rsp.status_code == 404

Expand All @@ -30,7 +34,7 @@ def test_unknown_entities(auth_server, contribution_candidate):
contribution_candidate.id_persistent,
"id_origin",
"id_destination",
cookies,
cookies=cookies,
)
assert rsp.status_code == 404
assert rsp.json() == {"msg": "One of the entities does not exist."}
Expand All @@ -43,30 +47,127 @@ def test_put_duplicate(auth_server, contribution_candidate, entities):
contribution_candidate.id_persistent,
c.id_persistent_entity_duplicate_test,
ce.id_persistent_test_0,
cookies,
cookies=cookies,
)
assert rsp.status_code == 200
duplicate = EntityDuplicate.objects.all().get() # pylint: disable=no-member
assert duplicate.id_origin_persistent == c.id_persistent_entity_duplicate_test
assert duplicate.id_destination_persistent == ce.id_persistent_test_0


def test_put_none_no_justification(auth_server, contribution_candidate, entities):
live_server, cookies = auth_server
rsp = r.put_duplicate(
live_server.url,
contribution_candidate.id_persistent,
c.id_persistent_entity_duplicate_test,
None,
cookies=cookies,
)
assert rsp.status_code == 400
assert len(EntityDuplicate.objects.all()) == 0 # pylint: disable=no-member


def test_put_none_with_justification(auth_server, contribution_candidate, entities):
live_server, cookies = auth_server
rsp = r.put_duplicate(
live_server.url,
contribution_candidate.id_persistent,
c.id_persistent_entity_duplicate_test,
None,
justification=justification,
cookies=cookies,
)
assert rsp.status_code == 200
assert len(EntityDuplicate.objects.all()) == 0 # pylint: disable=no-member
justification_db = EntityJustification.for_id_entity_persistent_unordered(
c.id_persistent_entity_duplicate_test
).get()
assert justification_db.text == justification


def test_keep_justification(auth_server, contribution_candidate, entities):
live_server, cookies = auth_server
rsp = r.put_duplicate(
live_server.url,
contribution_candidate.id_persistent,
c.id_persistent_entity_duplicate_test,
None,
justification=justification,
keep_justification_for_all=True,
cookies=cookies,
)
assert rsp.status_code == 200
assert len(EntityDuplicate.objects.all()) == 0 # pylint: disable=no-member
justification_db = EntityJustification.for_id_entity_persistent_unordered(
c.id_persistent_entity_duplicate_test
).get()
assert justification_db.text == justification
contribution = ContributionCandidate.by_id_persistent(
contribution_candidate.id_persistent, contribution_candidate.created_by
).get()
assert contribution.justification == justification


def test_uses_contribution_justification(auth_server, contribution_candidate, entities):
contribution_candidate.justification = justification
contribution_candidate.save()
live_server, cookies = auth_server
rsp = r.put_duplicate(
live_server.url,
contribution_candidate.id_persistent,
c.id_persistent_entity_duplicate_test,
None,
cookies=cookies,
)
assert rsp.status_code == 200
assert len(EntityDuplicate.objects.all()) == 0 # pylint: disable=no-member
justification_db = EntityJustification.for_id_entity_persistent_unordered(
c.id_persistent_entity_duplicate_test
).get()
assert justification_db.text == justification


def test_uses_entity_justification(auth_server, contribution_candidate, entities):
EntityJustification.add(
"72ae157a-75f8-46a6-a143-6548ea4ea91b",
c.id_persistent_entity_duplicate_test,
justification,
c.time_edit_deduplication,
contribution_candidate.created_by,
)
live_server, cookies = auth_server
rsp = r.put_duplicate(
live_server.url,
contribution_candidate.id_persistent,
c.id_persistent_entity_duplicate_test,
None,
cookies=cookies,
)
assert rsp.status_code == 200
assert len(EntityDuplicate.objects.all()) == 0 # pylint: disable=no-member
justification_db = EntityJustification.for_id_entity_persistent_unordered(
c.id_persistent_entity_duplicate_test
).get()
assert justification_db.text == justification


def test_put_duplicate_removes_old(auth_server, contribution_candidate, entities):
live_server, cookies = auth_server
rsp = r.put_duplicate(
live_server.url,
contribution_candidate.id_persistent,
c.id_persistent_entity_duplicate_test,
ce.id_persistent_test_0,
cookies,
cookies=cookies,
)
assert rsp.status_code == 200
rsp = r.put_duplicate(
live_server.url,
contribution_candidate.id_persistent,
c.id_persistent_entity_duplicate_test,
ce.id_persistent_test_1,
cookies,
cookies=cookies,
)
assert rsp.status_code == 200
duplicate = EntityDuplicate.objects.all().get() # pylint: disable=no-member
Expand Down
12 changes: 9 additions & 3 deletions tests/contribution/entity/api/requests.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# pylint: disable=missing-module-docstring, missing-function-docstring,redefined-outer-name,invalid-name
# pylint: disable=missing-module-docstring, missing-function-docstring,redefined-outer-name,invalid-name,too-many-arguments
import requests


Expand Down Expand Up @@ -36,6 +36,8 @@ def put_duplicate(
id_contribution_candidate_persistent,
id_entity_origin_persistent,
id_entity_destination_persistent,
justification=None,
keep_justification_for_all=None,
cookies=None,
):
return requests.put(
Expand All @@ -44,7 +46,11 @@ def put_duplicate(
f"/vran/api/contributions/{id_contribution_candidate_persistent}"
f"/entities/{id_entity_origin_persistent}/duplicate"
),
json={"id_entity_destination_persistent": id_entity_destination_persistent},
json={
"id_entity_destination_persistent": id_entity_destination_persistent,
"justification_txt": justification,
"keep_justification_for_all": keep_justification_for_all,
},
cookies=cookies,
timeout=9,
timeout=90,
)
6 changes: 3 additions & 3 deletions tests/contribution/entity/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
id_tag_instance_match_destination = "2ce8231e-5a58-4f43-8ef4-89efca0a6b97"
id_tag_instance_match_origin = "db0079c1-4cbf-43e8-ad19-e5dee0ae7405"
id_tag_merge_request_persistent = "af01c5cb-33b9-4b05-ade5-6d821a2d3075"
time_edit_tag_instance_match_origin = datetime(2022, 1, 1)
time_edit_tag_instance_match_destination = datetime(2021, 12, 3)
time_edit_tag_merge_request = datetime(2022, 1, 2)
time_edit_tag_instance_match_origin = datetime(2022, 1, 1, tzinfo=timezone.utc)
time_edit_tag_instance_match_destination = datetime(2021, 12, 3, tzinfo=timezone.utc)
time_edit_tag_merge_request = datetime(2022, 1, 2, tzinfo=timezone.utc)
Loading
Loading