summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2019-09-03 18:10:25 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2019-09-03 18:10:25 +0200
commit4ba08d6d622a05bd22b442369f33ee9dca3e67af (patch)
tree2c2c143a4adbf21b5fac1e4521688a0a2bd9fba2
parentce6b5a65849210f8f5ce6de94821ef2d4e784b88 (diff)
downloadIshtar-4ba08d6d622a05bd22b442369f33ee9dca3e67af.tar.bz2
Ishtar-4ba08d6d622a05bd22b442369f33ee9dca3e67af.zip
Serializations: operations, sites, parcels
-rw-r--r--archaeological_operations/models.py43
-rw-r--r--archaeological_operations/serializers.py17
-rw-r--r--archaeological_operations/tests.py44
-rw-r--r--ishtar_common/tests.py42
4 files changed, 102 insertions, 44 deletions
diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py
index f971981c0..c1f03368b 100644
--- a/archaeological_operations/models.py
+++ b/archaeological_operations/models.py
@@ -229,7 +229,7 @@ class ArchaeologicalSite(DocumentItem, BaseHistorizedItem, QRCodeItem,
),
'top_operation': SearchAltName(
pgettext_lazy("key for text search", "top-operation"),
- 'top_operation__cached_label__icontains'
+ 'top_operations__cached_label__icontains'
),
'drassm_number': SearchAltName(
pgettext_lazy("key for text search", "numero-drassm"),
@@ -254,7 +254,7 @@ class ArchaeologicalSite(DocumentItem, BaseHistorizedItem, QRCodeItem,
'cached_remains']
DOWN_MODEL_UPDATE = ["context_records"]
- # objects = SiteManager()
+ objects = SiteManager()
reference = models.CharField(_("Reference"), max_length=200, unique=True)
name = models.CharField(_("Name"), max_length=200,
@@ -266,9 +266,6 @@ class ArchaeologicalSite(DocumentItem, BaseHistorizedItem, QRCodeItem,
towns = models.ManyToManyField(Town, verbose_name=_("Towns"),
related_name='sites', blank=True)
comment = models.TextField(_("Comment"), null=True, blank=True)
- top_operation = models.ForeignKey("Operation", blank=True, null=True,
- verbose_name=_("Top operation"),
- on_delete=models.SET_NULL)
locality_ngi = models.TextField(
_("National Geographic Institute locality"),
null=True, blank=True
@@ -342,6 +339,12 @@ class ArchaeologicalSite(DocumentItem, BaseHistorizedItem, QRCodeItem,
def short_class_name(self):
return _("SITE")
+ @property
+ def top_operation(self):
+ if self.top_operations.count():
+ return self.top_operations.all()[0]
+ return
+
def public_representation(self):
dct = super(ArchaeologicalSite, self).public_representation()
dct.update({
@@ -379,16 +382,16 @@ class ArchaeologicalSite(DocumentItem, BaseHistorizedItem, QRCodeItem,
'operations__context_record__base_finds__find__container__location__',
Warehouse._get_query_owns_dicts(ishtaruser)
) | cls._construct_query_own(
- 'top_operation__context_record__base_finds__find__container__responsible__',
+ 'top_operations__context_record__base_finds__find__container__responsible__',
Warehouse._get_query_owns_dicts(ishtaruser)
) | cls._construct_query_own(
- 'top_operation__context_record__base_finds__find__container__location__',
+ 'top_operations__context_record__base_finds__find__container__location__',
Warehouse._get_query_owns_dicts(ishtaruser)
) | cls._construct_query_own(
'operations__', Operation._get_query_owns_dicts(ishtaruser,
no_rel=True)
) | cls._construct_query_own(
- 'top_operation__', Operation._get_query_owns_dicts(ishtaruser)
+ 'top_operations__', Operation._get_query_owns_dicts(ishtaruser)
) | cls._construct_query_own('', [
{'history_creator': ishtaruser.user_ptr}
])
@@ -429,8 +432,8 @@ class ArchaeologicalSite(DocumentItem, BaseHistorizedItem, QRCodeItem,
def _generate_cached_periods(self):
return " & ".join([str(period) for period in self.periods.all()]) or "-"
- # def natural_key(self):
- # return (self.reference, )
+ def natural_key(self):
+ return (self.reference, )
@property
def external_id(self):
@@ -466,7 +469,7 @@ class ArchaeologicalSite(DocumentItem, BaseHistorizedItem, QRCodeItem,
This cluster operation can be used to attach context records
which are only attached to the site.
"""
- if not self.top_operation:
+ if not self.top_operations.count():
if not create:
return
operation_type, created = OperationType.objects.get_or_create(
@@ -479,20 +482,22 @@ class ArchaeologicalSite(DocumentItem, BaseHistorizedItem, QRCodeItem,
if self.towns.count():
name += u' - ' + ", ".join([town.name
for town in self.towns.all()])
- self.top_operation = Operation.objects.create(
+ operation = Operation.objects.create(
operation_type=operation_type,
common_name=name,
virtual_operation=True
)
- self.skip_history_when_saving = True
- self.save()
+ operation.top_sites.add(self)
+ top_operation = self.top_operations.all()[0]
current_operations = dict(
[(ope.pk, ope)
- for ope in self.operations.exclude(pk=self.top_operation.pk).all()
+ for ope in self.operations.exclude(
+ pk=top_operation.pk
+ ).all()
]
)
q = RecordRelations.objects.filter(
- left_record=self.top_operation,
+ left_record=top_operation,
relation_type__txt_idx='has_got'
)
for relation in q.all():
@@ -503,7 +508,7 @@ class ArchaeologicalSite(DocumentItem, BaseHistorizedItem, QRCodeItem,
rel_type = RelationType.get_cache('has_got')
for missing in current_operations:
RecordRelations.objects.create(
- left_record=self.top_operation,
+ left_record=top_operation,
right_record=current_operations[missing],
relation_type=rel_type
)
@@ -998,6 +1003,10 @@ class Operation(ClosedItem, DocumentItem, BaseHistorizedItem, QRCodeItem,
archaeological_sites = models.ManyToManyField(
ArchaeologicalSite, verbose_name=_("Archaeological sites"),
blank=True, related_name='operations')
+ top_sites = models.ManyToManyField(
+ ArchaeologicalSite,
+ verbose_name=_("Sites for which this operation is top operation"),
+ related_name="top_operations", blank=True)
virtual_operation = models.BooleanField(
_("Virtual operation"),
default=False, help_text=_(
diff --git a/archaeological_operations/serializers.py b/archaeological_operations/serializers.py
new file mode 100644
index 000000000..7d4d9033d
--- /dev/null
+++ b/archaeological_operations/serializers.py
@@ -0,0 +1,17 @@
+from ishtar_common.serializers import generic_get_results, archive_serialization
+from archaeological_operations import models
+
+
+OPERATION_MODEL_LIST = [
+ models.ArchaeologicalSite, models.Operation, models.Parcel,
+ models.ParcelOwner
+]
+
+
+def operation_serialization(archive=False, return_empty_types=False,
+ archive_name=None):
+ result = generic_get_results(OPERATION_MODEL_LIST, "operations")
+ full_archive = archive_serialization(
+ result, archive_dir="operations", archive=archive,
+ return_empty_types=return_empty_types, archive_name=archive_name)
+ return full_archive
diff --git a/archaeological_operations/tests.py b/archaeological_operations/tests.py
index 647f0f86e..d0726fbdc 100644
--- a/archaeological_operations/tests.py
+++ b/archaeological_operations/tests.py
@@ -38,7 +38,7 @@ from django.utils.translation import ugettext_lazy as _, pgettext, pgettext_lazy
from . import models
from ishtar_common.views import document_deletion_steps
-from archaeological_operations import views
+from archaeological_operations import views, serializers
from ishtar_common.models import OrganizationType, Organization, ItemKey, \
ImporterType, IshtarUser, TargetKey, ImporterModel, IshtarSiteProfile, \
@@ -54,7 +54,7 @@ from ishtar_common import forms_common
from ishtar_common.tests import WizardTest, WizardTestFormData as FormData, \
create_superuser, create_user, TestCase, OPERATION_FIXTURES, \
AutocompleteTestBase, AcItem, OPERATION_TOWNS_FIXTURES, FILE_FIXTURES, \
- FILE_TOWNS_FIXTURES
+ COMMON_FIXTURES, GenericSerializationTest, WAREHOUSE_FIXTURES
class FileInit(object):
@@ -743,6 +743,35 @@ class ImportStepByStepTest(ImportTest, TestCase):
self.assertIn(error, response.content.decode('utf-8'))
+class SerializationTest(GenericSerializationTest, TestCase):
+ fixtures = COMMON_FIXTURES + WAREHOUSE_FIXTURES
+
+ def setUp(self):
+ self.username, self.password, self.user = create_superuser()
+ operation = create_operation(self.user,
+ values={"code_patriarche": "66666"})
+ site = models.ArchaeologicalSite.objects.create(
+ reference="ref-site"
+ )
+ operation.top_sites.add(site)
+ default = {"town": Town.objects.create(numero_insee="66666"),
+ "section": 'A', 'parcel_number': '1', "operation": operation}
+ parcel = models.Parcel.objects.create(**default)
+ models.ParcelOwner.objects.create(
+ parcel=parcel, owner=Person.objects.create(),
+ start_date=datetime.date.today(), end_date=datetime.date.today())
+
+ def test_serialization(self):
+ self.generic_serialization_test(serializers.operation_serialization)
+
+ def test_conf_restore(self):
+ current_number, zip_filename = self.generic_restore_test_genzip(
+ serializers.OPERATION_MODEL_LIST,
+ serializers.operation_serialization)
+ self.generic_restore_test(zip_filename, current_number,
+ serializers.OPERATION_MODEL_LIST)
+
+
class ParcelTest(ImportTest, TestCase):
fixtures = OPERATION_TOWNS_FIXTURES
@@ -1029,13 +1058,14 @@ class OperationInitTest(object):
self.create_towns()
return self.towns[0]
- def create_parcel(self, data={}):
+ def create_parcel(self, data=None):
default = {'town': self.get_default_town(),
'section': 'A', 'parcel_number': '1'}
if not hasattr(self, 'operations'):
self.create_operation()
default['operation'] = self.operations[0]
- default.update(data)
+ if data:
+ default.update(data)
if not getattr(self, 'parcels', None):
self.parcels = []
self.parcels.append(models.Parcel.objects.create(**default))
@@ -2721,7 +2751,7 @@ class SiteTest(TestCase, OperationInitTest):
codename='view_own_operation'))
self.orgas = self.create_orgas(self.user)
- def test_create_or_update_top_operation(self):
+ def test_create_or_update_top_operations(self):
operation_0 = self.create_operation(self.user, self.orgas[0])[0]
operation_1 = self.create_operation(self.alt_user, self.orgas[0])[1]
site = models.ArchaeologicalSite.objects.create(
@@ -2731,12 +2761,12 @@ class SiteTest(TestCase, OperationInitTest):
q = models.ArchaeologicalSite.objects.filter(reference='ref-site')
site = q.all()[0]
# creation not forced - no creation
- self.assertIsNone(site.top_operation)
+ self.assertEqual(site.top_operations.count(), 0)
site.create_or_update_top_operation(create=True)
site = q.all()[0]
# a default operation has been created
- self.assertIsNotNone(site.top_operation)
+ self.assertEqual(site.top_operations.count(), 1)
self.assertTrue(site.top_operation.virtual_operation)
self.assertEqual(site.top_operation.right_relations.count(), 0)
diff --git a/ishtar_common/tests.py b/ishtar_common/tests.py
index 99840ddaa..7bb3ce098 100644
--- a/ishtar_common/tests.py
+++ b/ishtar_common/tests.py
@@ -598,9 +598,7 @@ class CacheTest(TestCase):
self.assertIn(b'href="/operation_modification/', response.content)
-class SerializationTest(TestCase):
- fixtures = COMMON_FIXTURES + WAREHOUSE_FIXTURES
-
+class GenericSerializationTest:
def generic_serialization_test(self, serialize):
json_result = serialize()
for key in json_result.keys():
@@ -618,6 +616,27 @@ class SerializationTest(TestCase):
"expected".format(module.__name__, model_name,
serialization_count, current_count))
+ def generic_restore_test_genzip(self, model_list, serialization):
+ current_number = {}
+ for model in model_list:
+ current_number[model.__name__] = model.objects.count()
+ zip_filename = serialization(archive=True)
+ return current_number, zip_filename
+
+ def generic_restore_test(self, zip_filename, current_number, model_list):
+ restore_serialized(zip_filename, delete_existing=True)
+ for model in model_list:
+ previous_nb = current_number[model.__name__]
+ current_nb = model.objects.count()
+ self.assertEqual(
+ previous_nb, current_nb,
+ msg="Restore for model {} failed. Initial: {}, restored: "
+ "{}.".format(model.__name__, previous_nb, current_nb))
+
+
+class SerializationTest(GenericSerializationTest, TestCase):
+ fixtures = COMMON_FIXTURES + WAREHOUSE_FIXTURES
+
def test_type_serialization(self):
self.generic_serialization_test(type_serialization)
@@ -758,23 +777,6 @@ class SerializationTest(TestCase):
self.assertTrue(OperationRT.objects.filter(
inverse_relation__isnull=False).count())
- def generic_restore_test_genzip(self, model_list, serialization):
- current_number = {}
- for model in model_list:
- current_number[model.__name__] = model.objects.count()
- zip_filename = serialization(archive=True)
- return current_number, zip_filename
-
- def generic_restore_test(self, zip_filename, current_number, model_list):
- restore_serialized(zip_filename, delete_existing=True)
- for model in model_list:
- previous_nb = current_number[model.__name__]
- current_nb = model.objects.count()
- self.assertEqual(
- previous_nb, current_nb,
- msg="Restore for model {} failed. Initial: {}, restored: "
- "{}.".format(model.__name__, previous_nb, current_nb))
-
def test_conf_restore(self):
values = self.create_default_conf()
current_number, zip_filename = self.generic_restore_test_genzip(