diff options
| -rw-r--r-- | archaeological_files/tests.py | 87 | ||||
| -rw-r--r-- | archaeological_operations/models.py | 35 | ||||
| -rw-r--r-- | archaeological_operations/utils.py | 67 | ||||
| -rw-r--r-- | archaeological_operations/wizards.py | 13 | ||||
| -rw-r--r-- | ishtar_common/static/maintenance/maintenance-fr.html | 25 | ||||
| -rw-r--r-- | ishtar_common/static/maintenance/maintenance.html | 26 | 
6 files changed, 185 insertions, 68 deletions
| diff --git a/archaeological_files/tests.py b/archaeological_files/tests.py index b30c39dc1..312c0402d 100644 --- a/archaeological_files/tests.py +++ b/archaeological_files/tests.py @@ -1,6 +1,6 @@  #!/usr/bin/env python  # -*- coding: utf-8 -*- -# Copyright (C) 2010-2013 Étienne Loks  <etienne.loks_AT_peacefrogsDOTnet> +# Copyright (C) 2010-2015 Étienne Loks  <etienne.loks_AT_peacefrogsDOTnet>  # This program is free software: you can redistribute it and/or modify  # it under the terms of the GNU Affero General Public License as @@ -20,26 +20,22 @@  """  Unit tests  """ -import json +import json, datetime  from django.conf import settings  from django.contrib.auth.models import User  from django.test import TestCase -from ishtar_common.models import PersonType -from archaeological_files import models, data_importer - -class FileTest(TestCase): -    fixtures = [settings.ROOT_PATH + \ -                '../fixtures/initial_data-auth-fr.json', -                settings.ROOT_PATH + \ -                '../ishtar_common/fixtures/initial_data-fr.json'] -    model = models.File +from ishtar_common.models import PersonType, Town +from archaeological_files import models +from archaeological_operations.models import Parcel, ParcelOwner +from archaeological_operations.tests import OperationInitTest +class FileInit(object):      def login_as_superuser(self):          self.client.login(username='username', password='tralala') -    def setUp(self): +    def create_file(self):          self.extra_models, self.model_list = {}, []          self.user, created = User.objects.get_or_create(username='username',                                                          is_superuser=True) @@ -70,11 +66,15 @@ class FileTest(TestCase):          self.item = self.model(**dct)          self.item.save() -    def tearDown(self): -        #self.item.delete() -        #for item in reversed(self.model_list): -        #    item.delete() -        pass +class FileTest(TestCase, FileInit): +    fixtures = [settings.ROOT_PATH + \ +                '../fixtures/initial_data-auth-fr.json', +                settings.ROOT_PATH + \ +                '../ishtar_common/fixtures/initial_data-fr.json'] +    model = models.File + +    def setUp(self): +        self.create_file()      def testAddAndGetHistorized(self):          """ @@ -176,7 +176,52 @@ class FileTest(TestCase):          self.assertTrue(data['records'] == 1)          self.assertEqual(data['rows'][0]['internal_reference'], initial_ref) -class ImporterTest(TestCase): -    def testFormaters(self): -        for formater in [data_importer.SurfaceFormater]: -            formater().test() +#class ImporterTest(TestCase): +#    def testFormaters(self): +#        from archaeological_files import data_importer +#        for formater in [data_importer.SurfaceFormater]: +#            formater().test() + +class FileOperationTest(TestCase, OperationInitTest, FileInit): +    model = models.File +    fixtures = [settings.ROOT_PATH + \ +                '../fixtures/initial_data-auth-fr.json', +                settings.ROOT_PATH + \ +                '../ishtar_common/fixtures/initial_data-fr.json', +                settings.ROOT_PATH + +                '../ishtar_common/fixtures/test_towns.json', +                settings.ROOT_PATH + +                '../ishtar_common/fixtures/initial_importtypes-fr.json', +                settings.ROOT_PATH + +                '../archaeological_files/fixtures/initial_data.json', +                settings.ROOT_PATH + +                '../archaeological_operations/fixtures/initial_data-fr.json'] + +    def setUp(self): +        self.create_file() +        self.orgas = self.create_orgas(self.user) +        self.operations = self.create_operation(self.user, self.orgas[0]) +        self.operation = self.operations[0] + +    def testFileAssociation(self): +        # parcel association +        default_town = Town.objects.all()[0] +        for p in range(0, 10): +            parcel = Parcel.objects.create(parcel_number=unicode(p), +                                     section='YY', +                                     town=default_town, +                                     operation=self.operation) +            if p == 1: +                ParcelOwner.objects.create( +                        owner=self.extra_models['person'], +                        parcel=parcel, start_date=datetime.date.today(), +                        end_date=datetime.date.today()) +        initial_nb = self.item.parcels.count() +        # no parcel on the file -> new parcels are copied from the +        # operation +        self.operation.associated_file = self.item +        self.operation.save() +        self.assertEqual(self.item.parcels.count(), initial_nb+10) +        # parcel owner well attached +        q = ParcelOwner.objects.filter(parcel__associated_file=self.item) +        self.assertEqual(q.count(), 1) diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py index 8f69dd2e0..f13ee4ca9 100644 --- a/archaeological_operations/models.py +++ b/archaeological_operations/models.py @@ -435,25 +435,6 @@ class Operation(BaseHistorizedItem, OwnPerms, ValueGetter, ShortMenuItem,          # put a default year if start_date is defined          if self.start_date and not self.year:              self.year = self.start_date.year -        # manage parcel association -        """ -        if FILES_AVAILABLE and self.associated_file: -            for parcel in self.associated_file.parcels.exclude( -                                        operation=self).all(): -                parcel.operation = self -                parcel.save() -            for parcel in self.parcels.exclude( -                            associated_file=self.associated_file).all(): -                parcel.associated_file = self.associated_file -                parcel.save() -            parcels = {} -            for parcel in self.parcels.all(): -                keys = (parcel.town, parcel.section, parcel.parcel_number) -                if keys in parcels.keys(): -                    parcel.merge(parcels[keys]) -                else: -                    parcels[keys] = parcel -        """          return super(Operation, self).save(*args, **kwargs)  m2m_changed.connect(cached_label_changed, sender=Operation.towns.through) @@ -474,6 +455,20 @@ def operation_post_save(sender, **kwargs):      cached_label_changed(sender, **kwargs)      if FILES_AVAILABLE and operation.associated_file:          operation.associated_file.update_short_menu_class() +    # manage parcel association +    if FILES_AVAILABLE and operation.associated_file: +        for parcel in operation.parcels.all(): +            keys = {'town':parcel.town, 'section':parcel.section, +                    'parcel_number':parcel.parcel_number} +            if not operation.associated_file.parcels.filter(**keys).count(): +                keys['address'] = parcel.address +                keys['year'] = parcel.year +                keys['associated_file'] = operation.associated_file +                new_p = Parcel.objects.create(**keys) +                for owning in parcel.owners.all(): +                    ParcelOwner.objects.create(owner=owning.owner, +                                    parcel=new_p, start_date=owning.start_date, +                                    end_date=owning.end_date)  post_save.connect(operation_post_save, sender=Operation)  class OperationByDepartment(models.Model): @@ -723,6 +718,7 @@ class Parcel(LightHistorizedItem):      def __unicode__(self):          return self.short_label +    """      def merge(self, parcel):          # cannot automatically merge          if self.address and parcel.address and self.address != parcel.address: @@ -745,6 +741,7 @@ class Parcel(LightHistorizedItem):                  cr.parcel = self                  cr.save()          parcel.delete() +    """      @classmethod      def grouped_parcels(cls, parcels): diff --git a/archaeological_operations/utils.py b/archaeological_operations/utils.py index dcae8a3a8..60b1585ef 100644 --- a/archaeological_operations/utils.py +++ b/archaeological_operations/utils.py @@ -35,7 +35,8 @@ from archaeological_files.models import PermitType, File, FileType  from archaeological_operations.models import Operation, OperationType, Period, \                              AdministrativeAct, ActType, OperationSource, Parcel -DEFAULT_PERSON = User.objects.order_by('pk').all()[0] +def get_default_person(): +    return User.objects.order_by('pk').all()[0]  def _get_parse_string(trunc_number=None):      def parse_string(value): @@ -56,25 +57,40 @@ def parse_multivalue(value):      return re.sub('([0-9])([a-z])', r'\1 \2', s1)  ope_types = {} -for k in settings.ISHTAR_OPE_TYPES.keys(): -    ot, created = OperationType.objects.get_or_create( +def _init_ope_types(): +    for k in settings.ISHTAR_OPE_TYPES.keys(): +        ot, created = OperationType.objects.get_or_create(                               txt_idx=settings.ISHTAR_OPE_TYPES[k][0],                               defaults={'label':settings.ISHTAR_OPE_TYPES[k][1],                                         'preventive':k[0]==u'préventive'}) -    ope_types[k] = ot +        ope_types[k] = ot  def parse_operationtype(value, preventive, owner):      value = (preventive.strip(), value.strip()) +    if not ope_types: +        _init_ope_types()      if value not in ope_types:          return None      return ope_types[value]  periods = {} -for k in settings.ISHTAR_PERIODS.keys(): -    periods[k] = Period.objects.get(txt_idx=settings.ISHTAR_PERIODS[k]) -periods_keys = periods.keys() -periods_keys.sort(key=len) -periods_keys.reverse() +periods_keys = [] +def _init_period(): +    for k in settings.ISHTAR_PERIODS.keys(): +        periods[k] = Period.objects.get(txt_idx=settings.ISHTAR_PERIODS[k]) +    periods_keys = periods.keys() +    periods_keys.sort(key=len) +    periods_keys.reverse() +    for k in settings.ISHTAR_PERIODS.keys(): +        period = Period.objects.get(txt_idx=settings.ISHTAR_PERIODS[k]) +        slug = slugify(period.label) +        period_names[slug] = period +        for k in REPLACED_PERIOD_DCT.keys(): +            if k in slug: +                period_names[slug.replace(k, REPLACED_PERIOD_DCT[k])] = period +    period_names_keys = period_names.keys() +    period_names_keys.sort(key=len) +    period_names_keys.reverse()  def parse_period(value):      value = parse_string(value) @@ -82,6 +98,8 @@ def parse_period(value):      while value.endswith('-'):          value = value[:-1]      value = value[3:] if value.startswith('EUR') else value +    if not periods: +        _init_period()      if not value:          return [periods[u'']]      period, old_val = [], u'' @@ -99,18 +117,11 @@ _REPLACED_PERIOD += [(y, x) for x, y in _REPLACED_PERIOD]  REPLACED_PERIOD_DCT = dict(_REPLACED_PERIOD)  period_names = {} -for k in settings.ISHTAR_PERIODS.keys(): -    period = Period.objects.get(txt_idx=settings.ISHTAR_PERIODS[k]) -    slug = slugify(period.label) -    period_names[slug] = period -    for k in REPLACED_PERIOD_DCT.keys(): -        if k in slug: -            period_names[slug.replace(k, REPLACED_PERIOD_DCT[k])] = period -period_names_keys = period_names.keys() -period_names_keys.sort(key=len) -period_names_keys.reverse() +period_names_keys = {}  def parse_period_name(value): +    if not period_names: +        _init_period()      value = parse_string(value)      if not value:          return [period_names[u'']] @@ -126,15 +137,19 @@ def parse_period_name(value):      return period  _CACHED_PERMIT_TYPES = {} -for k in settings.ISHTAR_PERMIT_TYPES: -    txt_idx, label = settings.ISHTAR_PERMIT_TYPES[k] -    permit_type, created = PermitType.objects.get_or_create(txt_idx=txt_idx, -                          defaults={'label':label, -                                    'available':True}) -    _CACHED_PERMIT_TYPES[k] = permit_type + +def _init_permit_type(): +    for k in settings.ISHTAR_PERMIT_TYPES: +        txt_idx, label = settings.ISHTAR_PERMIT_TYPES[k] +        permit_type, created = PermitType.objects.get_or_create(txt_idx=txt_idx, +                              defaults={'label':label, +                                        'available':True}) +        _CACHED_PERMIT_TYPES[k] = permit_type  def parse_permittype(value):      value = parse_string(value).lower() +    if not _CACHED_PERMIT_TYPES: +        _init_permit_type()      if value not in _CACHED_PERMIT_TYPES:          if not "" in _CACHED_PERMIT_TYPES:              return @@ -266,7 +281,7 @@ def parse_name_surname(value):      if q.count():          return q.all()[0]      else: -        defaults = {'history_modifier':DEFAULT_PERSON, +        defaults = {'history_modifier':get_default_user(),                      'title':''}          defaults.update(values)          p = Person.objects.create(**defaults) diff --git a/archaeological_operations/wizards.py b/archaeological_operations/wizards.py index 59eb1d554..c7c375a49 100644 --- a/archaeological_operations/wizards.py +++ b/archaeological_operations/wizards.py @@ -112,9 +112,18 @@ class OperationWizard(Wizard):      def get_available_parcels(self, file):          parcels = [] +        current_parcels = [] +        operation = self.get_current_object() +        for parcel in operation.parcels.all(): +            current_parcels.append((parcel.town, parcel.section, +                                    parcel.parcel_number)) +            parcels.append((parcel.pk, parcel.short_label))          try: -            parcels = [(parcel.pk, parcel.short_label) -                        for parcel in file.parcels.all()] +            for parcel in file.parcels.all(): +                if (parcel.town, parcel.section, parcel.parcel_number) \ +                   in current_parcels: +                    continue +                parcels.append((parcel.pk, parcel.short_label))          except (ValueError, ObjectDoesNotExist):              pass          return sorted(parcels, key=lambda x:x[1]) diff --git a/ishtar_common/static/maintenance/maintenance-fr.html b/ishtar_common/static/maintenance/maintenance-fr.html new file mode 100644 index 000000000..de39ec54f --- /dev/null +++ b/ishtar_common/static/maintenance/maintenance-fr.html @@ -0,0 +1,25 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" +    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr"> +<head> +    <title>Ishtar - maintenance</title> +    <meta http-equiv="refresh" content="60;url=/"> +    <meta charset="UTF-8"/> +</head> +<body> +<h3> +    <center> +        <a href="/"><img src="under-maintenance.gif"></a><br><br> +        Ishtar connait en ce moment une maintenance programmée.<br> +        Veuillez essayer plus tard.<br> +        <h5>Restez sur cette page pour une vérification automatique régulière. Vous serez redirigé lorsque le système sera de nouveau disponible.</h5> +        <br><br> +        Désolé pour le dérangement. +        <br><br> +        <a href="/">Réessayer maintenant</a> +    </center> +</h3> + +</body> +</html> + diff --git a/ishtar_common/static/maintenance/maintenance.html b/ishtar_common/static/maintenance/maintenance.html new file mode 100644 index 000000000..f50e1fdbf --- /dev/null +++ b/ishtar_common/static/maintenance/maintenance.html @@ -0,0 +1,26 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" +    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr"> +<head> +    <title>Ishtar - maintenance</title> +    <meta http-equiv="refresh" content="60;url=/"> +    <meta charset="UTF-8"/> +</head> +<body> +<h3> +    <center> +        <a href="/"><img src="under-maintenance.gif"></a><br><br> +        Ishtar is currently undergoing a scheduled maintenance.<br> +        Please try back in 30 min. <br> +        <h5>Stay in this page for auto check. You will be redirected as soon as the system restarts.</h5> +        <br><br> +        Sorry for the inconvenience +        <br><br> +        <a href="/">retry now</a> +    </center> + +</h3> + +</body> +</html> + | 
