Skip to content

Commit 2d3874c

Browse files
committed
OpenConceptLab/ocl_issues#2406 | fixing valditor for FSN check
1 parent fd3dbcf commit 2d3874c

2 files changed

Lines changed: 58 additions & 6 deletions

File tree

core/concepts/custom_validators.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
LOCALES_SEARCH_INDEX_TERM, INDEX_TERM, FULLY_SPECIFIED, SHORT,
1515
OPENMRS_CONCEPT_EXTERNAL_ID_ERROR, OPENMRS_EXTERNAL_ID_LENGTH, OPENMRS_NAME_EXTERNAL_ID_ERROR,
1616
OPENMRS_DESCRIPTION_EXTERNAL_ID_ERROR)
17+
from core.concepts.models import ConceptName
1718
from core.concepts.validators import BaseConceptValidator, message_with_name_details
1819

1920

@@ -76,7 +77,7 @@ def preferred_name_should_be_unique_for_source_and_locale(self, concept):
7677
concept=concept,
7778
attribute='locale_preferred',
7879
error_message=OPENMRS_PREFERRED_NAME_UNIQUE_PER_SOURCE_LOCALE,
79-
filters={'names__locale_preferred': True}
80+
filters={'locale_preferred': True}
8081
)
8182

8283
def fully_specified_name_should_be_unique_for_source_and_locale(self, concept):
@@ -103,14 +104,20 @@ def no_other_record_has_same_name(self, name, versioned_object_id, filters=None)
103104
if not filters:
104105
filters = {}
105106

106-
return not self.repo.concepts_set.exclude(
107-
versioned_object_id=versioned_object_id
107+
# Query the localized text row directly so all name constraints apply to the same related record.
108+
return not ConceptName.objects.exclude(
109+
concept__versioned_object_id=versioned_object_id
108110
).exclude(
109-
names__type__in=(*LOCALES_SHORT, *LOCALES_SEARCH_INDEX_TERM, '', None)
111+
type__in=(*LOCALES_SHORT, *LOCALES_SEARCH_INDEX_TERM, '', None)
110112
).exclude(
111-
names__type__isnull=True
113+
type__isnull=True
112114
).filter(
113-
is_active=True, retired=False, is_latest_version=True, names__locale=name.locale, names__name=name.name,
115+
concept__parent=self.repo,
116+
concept__is_active=True,
117+
concept__retired=False,
118+
concept__is_latest_version=True,
119+
locale=name.locale,
120+
name=name.name,
114121
**filters
115122
).exists()
116123

core/concepts/tests/tests.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1800,6 +1800,51 @@ def test_concepts_should_have_unique_fully_specified_name_per_locale(self):
18001800
}
18011801
)
18021802

1803+
def test_duplicate_fully_specified_name_per_source_should_fail_even_with_unrelated_null_typed_name(self):
1804+
"""Regression for #2406: duplicate FSNs must still be caught when another concept also has NULL-typed names."""
1805+
source = OrganizationSourceFactory(custom_validation_schema=OPENMRS_VALIDATION_SCHEMA, version=HEAD)
1806+
1807+
concept1 = Concept.persist_new(
1808+
{
1809+
'mnemonic': 'cerebral-malaria-existing',
1810+
'version': HEAD,
1811+
'parent': source,
1812+
'concept_class': 'Diagnosis',
1813+
'datatype': 'None',
1814+
'names': [
1815+
ConceptNameFactory.build(
1816+
name='Cerebral malaria', locale='en', locale_preferred=True, type='Fully Specified'
1817+
),
1818+
ConceptNameFactory.build(
1819+
name='Unrelated synonym with NULL type', locale='en', locale_preferred=False, type=None
1820+
),
1821+
]
1822+
}
1823+
)
1824+
concept2 = Concept.persist_new(
1825+
{
1826+
'mnemonic': 'cerebral-malaria-duplicate',
1827+
'version': HEAD,
1828+
'parent': source,
1829+
'concept_class': 'Diagnosis',
1830+
'datatype': 'None',
1831+
'names': [
1832+
ConceptNameFactory.build(
1833+
name='Cerebral malaria', locale='en', locale_preferred=True, type='Fully Specified'
1834+
),
1835+
]
1836+
}
1837+
)
1838+
1839+
self.assertEqual(concept1.errors, {})
1840+
self.assertEqual(
1841+
concept2.errors,
1842+
{
1843+
'names': [OPENMRS_FULLY_SPECIFIED_NAME_UNIQUE_PER_SOURCE_LOCALE +
1844+
': Cerebral malaria (locale: en, preferred: yes)']
1845+
}
1846+
)
1847+
18031848
def test_at_least_one_fully_specified_name_per_concept_negative(self):
18041849
source = OrganizationSourceFactory(custom_validation_schema=OPENMRS_VALIDATION_SCHEMA, version=HEAD)
18051850

0 commit comments

Comments
 (0)