Symmetrical doc links for create / update doclink fields
This commit is contained in:
parent
5e8de4c1da
commit
74e81d673a
@ -471,6 +471,10 @@ class CustomFieldInstanceSerializer(serializers.ModelSerializer):
|
||||
# This key must exist, as it is validated
|
||||
data_store_name = type_to_data_store_name_map[custom_field.data_type]
|
||||
|
||||
if custom_field.data_type == CustomField.FieldDataType.DOCUMENTLINK:
|
||||
# prior to update so we can look for any docs that are going to be removed
|
||||
self.reflect_doclinks(document, custom_field, validated_data["value"])
|
||||
|
||||
# Actually update or create the instance, providing the value
|
||||
# to fill in the correct attribute based on the type
|
||||
instance, _ = CustomFieldInstance.objects.update_or_create(
|
||||
@ -494,6 +498,61 @@ class CustomFieldInstanceSerializer(serializers.ModelSerializer):
|
||||
URLValidator()(data["value"])
|
||||
return data
|
||||
|
||||
def reflect_doclinks(
|
||||
self,
|
||||
document: Document,
|
||||
field: CustomField,
|
||||
target_doc_ids: list[int],
|
||||
):
|
||||
"""
|
||||
Add or remove 'symmetrical' links to `document` on all `target_doc_ids`
|
||||
"""
|
||||
# Check if any documents are going to be removed from the current list of links and remove the symmetrical links
|
||||
current_field_instance = CustomFieldInstance.objects.filter(
|
||||
field=field,
|
||||
document=document,
|
||||
).first()
|
||||
if current_field_instance is not None:
|
||||
for doc_id in current_field_instance.value:
|
||||
if doc_id not in target_doc_ids:
|
||||
self.remove_doclink(document, field, doc_id)
|
||||
|
||||
for target_doc_id in target_doc_ids:
|
||||
target_doc_field_instance = CustomFieldInstance.objects.filter(
|
||||
field=field,
|
||||
document_id=target_doc_id,
|
||||
).first()
|
||||
if target_doc_field_instance is not None:
|
||||
if document.id not in target_doc_field_instance.value:
|
||||
target_doc_field_instance.value_document_ids.append(document.id)
|
||||
target_doc_field_instance.save()
|
||||
else:
|
||||
CustomFieldInstance.objects.update_or_create(
|
||||
document_id=target_doc_id,
|
||||
field=field,
|
||||
defaults={"value_document_ids": [document.id]},
|
||||
)
|
||||
|
||||
def remove_doclink(
|
||||
self,
|
||||
document: Document,
|
||||
field: CustomField,
|
||||
target_doc_id: int,
|
||||
):
|
||||
"""
|
||||
Removes a 'symmetrical' link to `document` from the target document's existing custom field instance
|
||||
"""
|
||||
target_doc_field_instance = CustomFieldInstance.objects.filter(
|
||||
document_id=target_doc_id,
|
||||
field=field,
|
||||
).first()
|
||||
if (
|
||||
target_doc_field_instance is not None
|
||||
and document.id in target_doc_field_instance.value
|
||||
):
|
||||
target_doc_field_instance.value.remove(document.id)
|
||||
target_doc_field_instance.save()
|
||||
|
||||
class Meta:
|
||||
model = CustomFieldInstance
|
||||
fields = [
|
||||
|
@ -70,6 +70,12 @@ class TestCustomField(DirectoriesMixin, APITestCase):
|
||||
checksum="123",
|
||||
mime_type="application/pdf",
|
||||
)
|
||||
doc2 = Document.objects.create(
|
||||
title="WOW2",
|
||||
content="the content2",
|
||||
checksum="1234",
|
||||
mime_type="application/pdf",
|
||||
)
|
||||
custom_field_string = CustomField.objects.create(
|
||||
name="Test Custom Field String",
|
||||
data_type=CustomField.FieldDataType.STRING,
|
||||
@ -139,7 +145,7 @@ class TestCustomField(DirectoriesMixin, APITestCase):
|
||||
},
|
||||
{
|
||||
"field": custom_field_documentlink.id,
|
||||
"value": [1, 2, 3],
|
||||
"value": [doc2.id],
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -160,7 +166,7 @@ class TestCustomField(DirectoriesMixin, APITestCase):
|
||||
{"field": custom_field_url.id, "value": "https://example.com"},
|
||||
{"field": custom_field_float.id, "value": 12.3456},
|
||||
{"field": custom_field_monetary.id, "value": 11.10},
|
||||
{"field": custom_field_documentlink.id, "value": [1, 2, 3]},
|
||||
{"field": custom_field_documentlink.id, "value": [doc2.id]},
|
||||
],
|
||||
)
|
||||
|
||||
@ -393,3 +399,80 @@ class TestCustomField(DirectoriesMixin, APITestCase):
|
||||
|
||||
self.assertEqual(CustomFieldInstance.objects.count(), 0)
|
||||
self.assertEqual(len(doc.custom_fields.all()), 0)
|
||||
|
||||
def test_bidirectional_doclink_fields(self):
|
||||
"""
|
||||
GIVEN:
|
||||
- Existing document
|
||||
WHEN:
|
||||
- Doc links are added or removed
|
||||
THEN:
|
||||
- Symmetrical link is created or removed as expected
|
||||
"""
|
||||
doc1 = Document.objects.create(
|
||||
title="WOW1",
|
||||
content="1",
|
||||
checksum="1",
|
||||
mime_type="application/pdf",
|
||||
)
|
||||
doc2 = Document.objects.create(
|
||||
title="WOW2",
|
||||
content="the content2",
|
||||
checksum="2",
|
||||
mime_type="application/pdf",
|
||||
)
|
||||
doc3 = Document.objects.create(
|
||||
title="WOW3",
|
||||
content="the content3",
|
||||
checksum="3",
|
||||
mime_type="application/pdf",
|
||||
)
|
||||
doc4 = Document.objects.create(
|
||||
title="WOW4",
|
||||
content="the content4",
|
||||
checksum="4",
|
||||
mime_type="application/pdf",
|
||||
)
|
||||
custom_field_doclink = CustomField.objects.create(
|
||||
name="Test Custom Field Doc Link",
|
||||
data_type=CustomField.FieldDataType.DOCUMENTLINK,
|
||||
)
|
||||
|
||||
# Add links, creates bi-directional
|
||||
resp = self.client.patch(
|
||||
f"/api/documents/{doc1.id}/",
|
||||
data={
|
||||
"custom_fields": [
|
||||
{
|
||||
"field": custom_field_doclink.id,
|
||||
"value": [2, 3, 4],
|
||||
},
|
||||
],
|
||||
},
|
||||
format="json",
|
||||
)
|
||||
|
||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(CustomFieldInstance.objects.count(), 4)
|
||||
self.assertEqual(doc2.custom_fields.first().value, [1])
|
||||
self.assertEqual(doc3.custom_fields.first().value, [1])
|
||||
self.assertEqual(doc4.custom_fields.first().value, [1])
|
||||
|
||||
# Remove one of the links, removed on other doc
|
||||
resp = self.client.patch(
|
||||
f"/api/documents/{doc1.id}/",
|
||||
data={
|
||||
"custom_fields": [
|
||||
{
|
||||
"field": custom_field_doclink.id,
|
||||
"value": [2, 3],
|
||||
},
|
||||
],
|
||||
},
|
||||
format="json",
|
||||
)
|
||||
|
||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(doc2.custom_fields.first().value, [1])
|
||||
self.assertEqual(doc3.custom_fields.first().value, [1])
|
||||
self.assertEqual(doc4.custom_fields.first().value, [])
|
||||
|
Loading…
x
Reference in New Issue
Block a user