summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ishtar_common/migrations/0212_auto_20210222_1718.py (renamed from ishtar_common/migrations/0212_auto_20210222_1334.py)7
-rw-r--r--ishtar_common/models.py9
-rw-r--r--ishtar_common/models_common.py36
-rw-r--r--ishtar_common/tests.py82
4 files changed, 110 insertions, 24 deletions
diff --git a/ishtar_common/migrations/0212_auto_20210222_1334.py b/ishtar_common/migrations/0212_auto_20210222_1718.py
index 703b58f2b..5cd506a10 100644
--- a/ishtar_common/migrations/0212_auto_20210222_1334.py
+++ b/ishtar_common/migrations/0212_auto_20210222_1718.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Generated by Django 1.11.27 on 2021-02-22 13:34
+# Generated by Django 1.11.27 on 2021-02-22 17:18
from __future__ import unicode_literals
from django.db import migrations, models
@@ -20,6 +20,11 @@ class Migration(migrations.Migration):
),
migrations.AddField(
model_name='ishtarsiteprofile',
+ name='clean_redundant_document_association',
+ field=models.BooleanField(default=False, help_text='For instance, remove operation association of a document also associated to a find of this operation. Only manage association of operations, context records and finds.', verbose_name='Document - Remove redundant association'),
+ ),
+ migrations.AddField(
+ model_name='ishtarsiteprofile',
name='delete_image_zip_on_archive',
field=models.BooleanField(default=False, verbose_name='Import - Delete image/document zip on archive'),
),
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 0a2f4bb6f..55fb1566c 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -60,7 +60,7 @@ from django.core.files.base import ContentFile
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.urlresolvers import reverse
from django.db.models import Q, Max, Count
-from django.db.models.signals import post_save, post_delete
+from django.db.models.signals import post_save, post_delete, m2m_changed
from django.db.utils import DatabaseError
from django.template import Context, Template
from django.template.defaultfilters import slugify
@@ -740,6 +740,13 @@ class IshtarSiteProfile(models.Model, Cached):
delete_image_zip_on_archive = models.BooleanField(
_("Import - Delete image/document zip on archive"), default=False
)
+ clean_redundant_document_association = models.BooleanField(
+ _("Document - Remove redundant association"), default=False,
+ help_text=_("For instance, remove operation association of a "
+ "document also associated to a find of this operation. "
+ "Only manage association of operations, context records "
+ "and finds.")
+ )
config = models.CharField(
_("Alternate configuration"), max_length=200,
choices=ALTERNATE_CONFIGS_CHOICES,
diff --git a/ishtar_common/models_common.py b/ishtar_common/models_common.py
index 2d8966066..17e643631 100644
--- a/ishtar_common/models_common.py
+++ b/ishtar_common/models_common.py
@@ -2369,6 +2369,40 @@ class DocumentItem:
return actions
+def clean_duplicate_association(document, related_item, action):
+ profile = get_current_profile()
+ if not profile.clean_redundant_document_association or action != "post_add":
+ return
+ class_name = related_item.__class__.__name__
+ if class_name not in ("Find", "ContextRecord", "Operation"):
+ return
+ if class_name == "Find":
+ for cr in document.context_records.filter(
+ base_finds__find__pk=related_item.pk).all():
+ document.context_records.remove(cr)
+ for ope in document.operations.filter(
+ context_record__base_finds__find__pk=related_item.pk).all():
+ document.operations.remove(ope)
+ return
+ if class_name == "ContextRecord":
+ for ope in document.operations.filter(
+ context_record__pk=related_item.pk).all():
+ document.operations.remove(ope)
+ if document.finds.filter(
+ base_finds__context_record=related_item.pk).count():
+ document.context_records.remove(related_item)
+ return
+ if class_name == "Operation":
+ if document.context_records.filter(
+ operation=related_item.pk).count():
+ document.operations.remove(related_item)
+ return
+ if document.finds.filter(
+ base_finds__context_record__operation=related_item.pk).count():
+ document.operations.remove(related_item)
+ return
+
+
def document_attached_changed(sender, **kwargs):
# associate a default main image
instance = kwargs.get("instance", None)
@@ -2388,6 +2422,8 @@ def document_attached_changed(sender, **kwargs):
return
for item in items:
+ clean_duplicate_association(instance, item,
+ kwargs.get("action", None))
for doc in item.documents.all():
doc.regenerate_all_ids()
q = item.documents.filter(
diff --git a/ishtar_common/tests.py b/ishtar_common/tests.py
index 71e599d59..72836fa45 100644
--- a/ishtar_common/tests.py
+++ b/ishtar_common/tests.py
@@ -2757,7 +2757,7 @@ class PersonQATest(TestCase):
class DocumentTest(TestCase):
- def test_custom_index(self):
+ def setUp(self):
Operation = apps.get_model("archaeological_operations", "Operation")
ContextRecord = apps.get_model("archaeological_context_records",
"ContextRecord")
@@ -2766,25 +2766,27 @@ class DocumentTest(TestCase):
Find = apps.get_model("archaeological_finds", "Find")
operation_type, __ = models.OperationType.objects.get_or_create(
txt_idx="arch_diagnostic", label="Diagnostic")
- ope1 = Operation.objects.create(
+ self.ope1 = Operation.objects.create(
code_patriarche="001",
operation_type_id=operation_type.pk)
- ope2 = Operation.objects.create(
+ self.ope2 = Operation.objects.create(
code_patriarche="002",
operation_type_id=operation_type.pk)
su, __ = Unit.objects.get_or_create(
txt_idx='stratigraphic-unit', label="Stratigraphic unit", order=1)
- cr1 = ContextRecord.objects.create(operation=ope1, unit=su)
- cr2 = ContextRecord.objects.create(operation=ope2, unit=su)
- bf1 = BaseFind.objects.create(context_record=cr1)
- bf2 = BaseFind.objects.create(context_record=cr2)
- find1 = Find.objects.create()
- find1.base_finds.add(bf1)
- find2 = Find.objects.create()
- find2.base_finds.add(bf2)
- st1 = models.SourceType.objects.create(label="Report", code="REP")
- st2 = models.SourceType.objects.create(label="Illustration", code="ILL")
+ self.cr1 = ContextRecord.objects.create(operation=self.ope1, unit=su)
+ self.cr2 = ContextRecord.objects.create(operation=self.ope2, unit=su)
+ bf1 = BaseFind.objects.create(context_record=self.cr1)
+ bf2 = BaseFind.objects.create(context_record=self.cr2)
+ self.find1 = Find.objects.create()
+ self.find1.base_finds.add(bf1)
+ self.find2 = Find.objects.create()
+ self.find2.base_finds.add(bf2)
+ self.st1 = models.SourceType.objects.create(label="Report", code="REP")
+ self.st2 = models.SourceType.objects.create(label="Illustration",
+ code="ILL")
+ def test_custom_index(self):
profile, created = models.IshtarSiteProfile.objects.get_or_create(
slug='default', active=True)
profile.document_complete_identifier = \
@@ -2792,25 +2794,25 @@ class DocumentTest(TestCase):
profile.document_custom_index = "operation"
profile.save()
- doc = models.Document.objects.create(source_type=st1,
+ doc = models.Document.objects.create(source_type=self.st1,
title="Operation report")
- doc.operations.add(ope1)
+ doc.operations.add(self.ope1)
doc = models.Document.objects.get(pk=doc.pk)
self.assertEqual(doc.complete_identifier, "001-REP-1")
- doc2 = models.Document.objects.create(source_type=st2,
+ doc2 = models.Document.objects.create(source_type=self.st2,
title="Illustration CR")
- doc2.context_records.add(cr1)
+ doc2.context_records.add(self.cr1)
doc2 = models.Document.objects.get(pk=doc2.pk)
self.assertEqual(doc2.complete_identifier, "001-ILL-2")
- doc3 = models.Document.objects.create(source_type=st1,
+ doc3 = models.Document.objects.create(source_type=self.st1,
title="Operation report 2")
- doc3.operations.add(ope2)
+ doc3.operations.add(self.ope2)
doc3 = models.Document.objects.get(pk=doc3.pk)
self.assertEqual(doc3.complete_identifier, "002-REP-1")
- doc3.operations.add(ope1)
+ doc3.operations.add(self.ope1)
doc3.custom_index = None
doc3.save()
doc3 = models.Document.objects.get(pk=doc3.pk)
@@ -2823,20 +2825,56 @@ class DocumentTest(TestCase):
"{{ \"%03d\" % (custom_index|int)}}{% else %}no-code{% endif %}"
profile.save()
- doc3.operations.remove(ope1)
+ doc3.operations.remove(self.ope1)
doc3.custom_index = None
doc3.complete_identifier = ""
doc3.save()
doc3 = models.Document.objects.get(pk=doc3.pk)
self.assertEqual(doc3.complete_identifier, '002-REP-001')
- doc3.operations.remove(ope2)
+ doc3.operations.remove(self.ope2)
doc3.custom_index = None
doc3.complete_identifier = ""
doc3.save()
doc3 = models.Document.objects.get(pk=doc3.pk)
self.assertEqual(doc3.complete_identifier, 'no-code')
+ def test_clean_duplicate_association(self):
+ doc = models.Document.objects.create(source_type=self.st1,
+ title="Operation report")
+ doc.operations.add(self.ope1)
+ doc.context_records.add(self.cr1)
+ doc = models.Document.objects.get(pk=doc.pk)
+ self.assertEqual(doc.operations.count(), 1)
+
+ doc.context_records.remove(self.cr1)
+ profile = models.get_current_profile()
+ profile.clean_redundant_document_association = True
+ profile.save()
+
+ doc = models.Document.objects.get(pk=doc.pk)
+ doc.context_records.add(self.cr1)
+
+ doc = models.Document.objects.get(pk=doc.pk)
+ self.assertEqual(doc.context_records.count(), 1)
+ self.assertEqual(doc.operations.count(), 0)
+
+ doc.context_records.remove(self.cr1)
+ doc.operations.add(self.ope1)
+ doc.context_records.add(self.cr2)
+ self.assertEqual(doc.operations.count(), 1) # different ope keep it
+ self.assertEqual(doc.context_records.count(), 1)
+
+ # adding a find - remove the operation
+ doc.finds.add(self.find1)
+ self.assertEqual(doc.finds.count(), 1)
+ self.assertEqual(doc.context_records.count(), 1)
+ self.assertEqual(doc.operations.count(), 0)
+
+ # adding an operation is undo
+ doc.operations.add(self.ope1)
+ self.assertEqual(doc.operations.count(), 0)
+
class JinjaFilterTest(TestCase):
def test_splitpart(self):