diff options
| 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 | 
| commit | 4ba08d6d622a05bd22b442369f33ee9dca3e67af (patch) | |
| tree | 2c2c143a4adbf21b5fac1e4521688a0a2bd9fba2 | |
| parent | ce6b5a65849210f8f5ce6de94821ef2d4e784b88 (diff) | |
| download | Ishtar-4ba08d6d622a05bd22b442369f33ee9dca3e67af.tar.bz2 Ishtar-4ba08d6d622a05bd22b442369f33ee9dca3e67af.zip | |
Serializations: operations, sites, parcels
| -rw-r--r-- | archaeological_operations/models.py | 43 | ||||
| -rw-r--r-- | archaeological_operations/serializers.py | 17 | ||||
| -rw-r--r-- | archaeological_operations/tests.py | 44 | ||||
| -rw-r--r-- | ishtar_common/tests.py | 42 | 
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( | 
