Skip to content

Commit

Permalink
Hierarchy | in bulk import not creating parent version
Browse files Browse the repository at this point in the history
  • Loading branch information
snyaggarwal committed Jun 16, 2021
1 parent 2103f7e commit 8d4a197
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 12 deletions.
1 change: 1 addition & 0 deletions core/common/constants.py
Expand Up @@ -71,3 +71,4 @@
PASSWORD_RESET_MAIL_SUBJECT = "Password Reset E-mail"
LATEST = 'latest'
VERSION_HEADER = 'X-OCL-API-VERSION'
CREATE_PARENT_VERSION_QUERY_PARAM = 'createParentVersion'
4 changes: 2 additions & 2 deletions core/common/tasks.py
Expand Up @@ -299,7 +299,7 @@ def update_validation_schema(instance_type, instance_id, target_schema):
ignore_result=True, autoretry_for=(Exception, WorkerLostError, ), retry_kwargs={'max_retries': 2, 'countdown': 2},
acks_late=True, reject_on_worker_lost=True
)
def process_hierarchy_for_new_concept(concept_id, initial_version_id, parent_concept_uris):
def process_hierarchy_for_new_concept(concept_id, initial_version_id, parent_concept_uris, create_parent_version=True):
from core.concepts.models import Concept
concept = Concept.objects.filter(id=concept_id).first()

Expand All @@ -309,7 +309,7 @@ def process_hierarchy_for_new_concept(concept_id, initial_version_id, parent_con

parent_concepts = Concept.objects.filter(uri__in=parent_concept_uris)
concept._parent_concepts = parent_concepts # pylint: disable=protected-access
concept.set_parent_concepts_from_uris(create_parent_version=True)
concept.set_parent_concepts_from_uris(create_parent_version=create_parent_version)

if initial_version:
initial_version._parent_concepts = parent_concepts # pylint: disable=protected-access
Expand Down
8 changes: 5 additions & 3 deletions core/concepts/models.py
Expand Up @@ -529,7 +529,7 @@ def is_existing_in_parent(self):
return self.parent.concepts_set.filter(mnemonic__exact=self.mnemonic).exists()

@classmethod
def persist_new(cls, data, user=None, create_initial_version=True):
def persist_new(cls, data, user=None, create_initial_version=True, create_parent_version=True):
names = [
name if isinstance(name, LocalizedText) else LocalizedText.build(
name
Expand Down Expand Up @@ -575,9 +575,11 @@ def persist_new(cls, data, user=None, create_initial_version=True):
concept.update_mappings()
if parent_concept_uris:
if get(settings, 'TEST_MODE', False):
process_hierarchy_for_new_concept(concept.id, get(initial_version, 'id'), parent_concept_uris)
process_hierarchy_for_new_concept(
concept.id, get(initial_version, 'id'), parent_concept_uris, create_parent_version)
else:
process_hierarchy_for_new_concept.delay(concept.id, get(initial_version, 'id'), parent_concept_uris)
process_hierarchy_for_new_concept.delay(
concept.id, get(initial_version, 'id'), parent_concept_uris, create_parent_version)
except ValidationError as ex:
concept.errors.update(ex.message_dict)
except IntegrityError as ex:
Expand Down
17 changes: 14 additions & 3 deletions core/concepts/serializers.py
Expand Up @@ -4,7 +4,8 @@
from rest_framework.serializers import ModelSerializer

from core.common.constants import INCLUDE_INVERSE_MAPPINGS_PARAM, INCLUDE_MAPPINGS_PARAM, INCLUDE_EXTRAS_PARAM, \
INCLUDE_PARENT_CONCEPTS, INCLUDE_CHILD_CONCEPTS, INCLUDE_SOURCE_VERSIONS, INCLUDE_COLLECTION_VERSIONS
INCLUDE_PARENT_CONCEPTS, INCLUDE_CHILD_CONCEPTS, INCLUDE_SOURCE_VERSIONS, INCLUDE_COLLECTION_VERSIONS, \
CREATE_PARENT_VERSION_QUERY_PARAM
from core.common.fields import EncodedDecodedCharField
from core.concepts.models import Concept, LocalizedText

Expand Down Expand Up @@ -215,6 +216,10 @@ def __init__(self, *args, **kwargs):
self.include_direct_mappings = self.query_params.get(INCLUDE_MAPPINGS_PARAM) in ['true', True]
self.include_parent_concepts = self.query_params.get(INCLUDE_PARENT_CONCEPTS) in ['true', True]
self.include_child_concepts = self.query_params.get(INCLUDE_CHILD_CONCEPTS) in ['true', True]
if CREATE_PARENT_VERSION_QUERY_PARAM in self.query_params:
self.create_parent_version = self.query_params.get(CREATE_PARENT_VERSION_QUERY_PARAM) in ['true', True]
else:
self.create_parent_version = True

try:
if not self.include_parent_concepts:
Expand Down Expand Up @@ -247,13 +252,19 @@ def get_mappings(self, obj):
return []

def create(self, validated_data):
concept = Concept.persist_new(data=validated_data, user=self.context.get('request').user)
concept = Concept.persist_new(
data=validated_data, user=self.context.get('request').user,
create_parent_version=self.create_parent_version
)
if concept.errors:
self._errors.update(concept.errors)
return concept

def update(self, instance, validated_data):
errors = Concept.create_new_version_for(instance, validated_data, self.context.get('request').user)
errors = Concept.create_new_version_for(
instance=instance, data=validated_data, user=self.context.get('request').user,
create_parent_version=self.create_parent_version
)
if errors:
self._errors.update(errors)
return instance
Expand Down
178 changes: 178 additions & 0 deletions core/concepts/tests/tests.py
Expand Up @@ -412,6 +412,184 @@ def test_hierarchy(self): # pylint: disable=too-many-statements
[]
)

def test_hierarchy_without_multiple_parent_versions(self): # pylint: disable=too-many-statements
# Av1
parent_concept = ConceptFactory(
names=[LocalizedTextFactory(locale='en', name='English', locale_preferred=True)])
self.assertEqual(parent_concept.versions.count(), 1)
self.assertEqual(list(parent_concept.get_latest_version().child_concept_urls), [])
source = parent_concept.parent

# Av1 -> Bv1
child_concept = Concept.persist_new(data={
**factory.build(dict, FACTORY_CLASS=ConceptFactory), 'mnemonic': 'c1', 'parent': source,
'names': [LocalizedTextFactory.build(locale='en', name='English', locale_preferred=True)],
'parent_concept_urls': [parent_concept.uri]
}, create_parent_version=False)

parent_concept_latest_version = parent_concept.get_latest_version()
self.assertEqual(child_concept.errors, {})
self.assertIsNotNone(child_concept.id)
self.assertEqual(parent_concept.versions.count(), 1)
self.assertEqual(child_concept.versions.count(), 1)
self.assertEqual(list(child_concept.parent_concept_urls), [parent_concept.uri])
self.assertEqual(list(child_concept.child_concept_urls), [])
self.assertEqual(list(parent_concept.child_concept_urls), [child_concept.uri])
self.assertEqual(list(parent_concept_latest_version.child_concept_urls), [child_concept.uri])

# Av1 -> Bv1 -> Cv1
child_child_concept = Concept.persist_new(data={
**factory.build(dict, FACTORY_CLASS=ConceptFactory), 'mnemonic': 'c2', 'parent': source,
'names': [LocalizedTextFactory.build(locale='en', name='English', locale_preferred=True)],
'parent_concept_urls': [child_concept.uri]
}, create_parent_version=False)

self.assertEqual(child_child_concept.errors, {})
self.assertIsNotNone(child_child_concept.id)
self.assertEqual(parent_concept.versions.count(), 1)
self.assertEqual(child_concept.versions.count(), 1)
self.assertEqual(child_child_concept.versions.count(), 1)
self.assertEqual(list(child_child_concept.parent_concept_urls), [child_concept.uri])
self.assertEqual(list(child_child_concept.get_latest_version().parent_concept_urls), [child_concept.uri])
self.assertEqual(list(child_child_concept.child_concept_urls), [])
self.assertEqual(list(child_concept.child_concept_urls), [child_child_concept.uri])
self.assertEqual(list(child_concept.parent_concept_urls), [parent_concept.uri])
self.assertEqual(list(child_concept.get_latest_version().child_concept_urls), [child_child_concept.uri])
self.assertEqual(list(child_concept.get_latest_version().parent_concept_urls), [parent_concept.uri])
self.assertEqual(list(parent_concept.child_concept_urls), [child_concept.uri])

# Av1 -> Bv1 -> Cv1 to Av1 -> Bv2,Cv2 and Bv1 -> Cv1
Concept.create_new_version_for(
instance=child_child_concept.clone(),
data=dict(
parent_concept_urls=[parent_concept.uri],
names=[dict(locale='en', name='English', locale_preferred=True)]
),
user=child_child_concept.created_by,
create_parent_version=False
)

self.assertEqual(parent_concept.versions.count(), 1)
self.assertEqual(child_concept.versions.count(), 2)
self.assertEqual(child_child_concept.versions.count(), 2)

child_child_latest_version = child_child_concept.get_latest_version()
self.assertEqual(list(child_child_concept.parent_concept_urls), [parent_concept.uri])
self.assertEqual(list(child_child_latest_version.parent_concept_urls), [parent_concept.uri])
self.assertEqual(list(child_child_latest_version.prev_version.parent_concept_urls), [child_concept.url])

parent_concept_latest_version = parent_concept.get_latest_version()
self.assertListEqual(
sorted(list(parent_concept.child_concept_urls)),
sorted([child_concept.uri, child_child_concept.uri])
)
self.assertEqual(
sorted(list(parent_concept_latest_version.child_concept_urls)),
sorted([child_concept.uri, child_child_concept.uri])
)

child_latest_version = child_concept.get_latest_version()
self.assertEqual(list(child_concept.child_concept_urls), [])
self.assertEqual(list(child_latest_version.child_concept_urls), [])
self.assertEqual(list(child_latest_version.prev_version.child_concept_urls), [child_child_concept.uri])

# Av1 -> Bv1 -> Cv1 to Av1 -> Bv2,Cv2 and Bv1 -> Cv1 to Av2 -> Bv2 -> Cv3 and Av1 -> Bv1, Cv2 and Bv1 -> Cv1
Concept.create_new_version_for(
instance=child_child_concept.clone(),
data=dict(
parent_concept_urls=[child_concept.uri],
names=[dict(locale='en', name='English', locale_preferred=True)]
),
user=child_child_concept.created_by,
create_parent_version=False
)

self.assertEqual(parent_concept.versions.count(), 2)
self.assertEqual(child_concept.versions.count(), 2)
self.assertEqual(child_child_concept.versions.count(), 3)

child_child_latest_version = child_child_concept.get_latest_version()
self.assertEqual(
list(child_child_concept.parent_concept_urls), [child_concept.uri])
self.assertEqual(
list(child_child_latest_version.parent_concept_urls), [child_concept.uri])
self.assertEqual(
list(child_child_latest_version.prev_version.parent_concept_urls), [parent_concept.url])
self.assertEqual(
list(child_child_latest_version.prev_version.prev_version.parent_concept_urls), [child_concept.url])

child_latest_version = child_concept.get_latest_version()
self.assertEqual(list(child_concept.child_concept_urls), [child_child_concept.uri])
self.assertEqual(list(child_latest_version.child_concept_urls), [child_child_concept.uri])
self.assertEqual(
list(child_latest_version.prev_version.child_concept_urls), [child_child_concept.uri]
)
parent_concept_latest_version = parent_concept.get_latest_version()
self.assertListEqual(
sorted(list(parent_concept.child_concept_urls)),
sorted([child_concept.uri])
)
self.assertEqual(
sorted(list(parent_concept_latest_version.child_concept_urls)),
sorted([child_concept.uri])
)
self.assertEqual(
sorted(list(parent_concept_latest_version.prev_version.child_concept_urls)),
sorted([child_concept.uri, child_child_concept.uri])
)

# Av1 -> Bv1 -> Cv1 to Av1 -> Bv2,Cv2 and Bv1 -> Cv1 to Av2 -> Bv2 -> Cv3 and Av1 -> Bv1, Cv2 and Bv1 -> Cv1 to
# Av2 -> Bv3 and Bv2 -> Cv3 and Av1 -> Bv1, Cv2 and Bv1 -> Cv1 and Cv4
Concept.create_new_version_for(
instance=child_child_concept.clone(),
data=dict(
parent_concept_urls=[],
names=[dict(locale='en', name='English', locale_preferred=True)]
),
user=child_child_concept.created_by,
create_parent_version=False
)

self.assertEqual(parent_concept.versions.count(), 2)
self.assertEqual(child_concept.versions.count(), 3)
self.assertEqual(child_child_concept.versions.count(), 4)

child_child_latest_version = child_child_concept.get_latest_version()
self.assertEqual(
list(child_child_concept.parent_concept_urls), [])
self.assertEqual(
list(child_child_latest_version.parent_concept_urls), [])
self.assertEqual(
list(child_child_latest_version.prev_version.parent_concept_urls), [child_concept.uri])
self.assertEqual(
list(child_child_latest_version.prev_version.prev_version.parent_concept_urls), [parent_concept.url])
self.assertEqual(
list(child_child_latest_version.prev_version.prev_version.prev_version.parent_concept_urls),
[child_concept.url]
)

child_latest_version = child_concept.get_latest_version()
self.assertEqual(list(child_concept.child_concept_urls), [])
self.assertEqual(list(child_latest_version.child_concept_urls), [])
self.assertEqual(list(child_latest_version.prev_version.child_concept_urls), [child_child_concept.uri])
self.assertEqual(
list(child_latest_version.prev_version.prev_version.child_concept_urls), [child_child_concept.uri]
)

parent_concept_latest_version = parent_concept.get_latest_version()
self.assertListEqual(
sorted(list(parent_concept.child_concept_urls)),
sorted([child_concept.uri])
)
self.assertEqual(
sorted(list(parent_concept_latest_version.child_concept_urls)),
sorted([child_concept.uri])
)
self.assertEqual(
sorted(list(parent_concept_latest_version.prev_version.child_concept_urls)),
sorted([child_concept.uri, child_child_concept.uri])
)

def test_clone(self):
es_locale = LocalizedTextFactory(locale='es', name='Not English')
en_locale = LocalizedTextFactory(locale='en', name='English')
Expand Down
10 changes: 6 additions & 4 deletions core/importers/models.py
Expand Up @@ -224,7 +224,7 @@ def parse(self):
if isinstance(supported_locales, str):
self.data['supported_locales'] = supported_locales.split(',')

self.data.pop('short_code')
self.data.pop('short_code', None)

def process(self):
source = Source(**self.data)
Expand Down Expand Up @@ -301,7 +301,7 @@ def parse(self):
if isinstance(supported_locales, str):
self.data['supported_locales'] = supported_locales.split(',')

self.data.pop('short_code')
self.data.pop('short_code', None)

def process(self):
coll = Collection(**self.data)
Expand Down Expand Up @@ -394,10 +394,12 @@ def clean(self):
def process(self):
if self.version:
instance = self.get_queryset().first().clone()
errors = Concept.create_new_version_for(instance, self.data, self.user)
errors = Concept.create_new_version_for(
instance=instance, data=self.data, user=self.user, create_parent_version=False
)
return errors or UPDATED

instance = Concept.persist_new(self.data, self.user)
instance = Concept.persist_new(data=self.data, user=self.user, create_parent_version=False)
if instance.id:
return CREATED
return instance.errors or FAILED
Expand Down

0 comments on commit 8d4a197

Please sign in to comment.