From 9fbf4201087d121c0296a12460bcdaf2704eae1d Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 8 Jul 2015 00:01:46 +0200 Subject: Add a file for maintenance mode. --- ishtar_common/templates/maintenance/maintenance-fr.html | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 ishtar_common/templates/maintenance/maintenance-fr.html diff --git a/ishtar_common/templates/maintenance/maintenance-fr.html b/ishtar_common/templates/maintenance/maintenance-fr.html new file mode 100644 index 000000000..d950ad5ab --- /dev/null +++ b/ishtar_common/templates/maintenance/maintenance-fr.html @@ -0,0 +1,14 @@ + + + + + Ishtar + + + +

Ishtar est en maintenance.

+ + -- cgit v1.2.3 From 8a4ae5066af347c7cd9147b4b4f14b4439470b62 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 8 Jul 2015 00:05:58 +0200 Subject: Move maintenance to static dir (because it is in fact static) --- ishtar_common/static/maintenance/maintenance-fr.html | 14 ++++++++++++++ ishtar_common/templates/maintenance/maintenance-fr.html | 14 -------------- 2 files changed, 14 insertions(+), 14 deletions(-) create mode 100644 ishtar_common/static/maintenance/maintenance-fr.html delete mode 100644 ishtar_common/templates/maintenance/maintenance-fr.html diff --git a/ishtar_common/static/maintenance/maintenance-fr.html b/ishtar_common/static/maintenance/maintenance-fr.html new file mode 100644 index 000000000..d950ad5ab --- /dev/null +++ b/ishtar_common/static/maintenance/maintenance-fr.html @@ -0,0 +1,14 @@ + + + + + Ishtar + + + +

Ishtar est en maintenance.

+ + diff --git a/ishtar_common/templates/maintenance/maintenance-fr.html b/ishtar_common/templates/maintenance/maintenance-fr.html deleted file mode 100644 index d950ad5ab..000000000 --- a/ishtar_common/templates/maintenance/maintenance-fr.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Ishtar - - - -

Ishtar est en maintenance.

- - -- cgit v1.2.3 From 19397157a46284cd3d9b8bf0a80efcb42a4a6e87 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Wed, 8 Jul 2015 00:15:14 +0200 Subject: Maintenance mode pages --- .../static/maintenance/maintenance-fr.html | 23 ++++++++++++++----- ishtar_common/static/maintenance/maintenance.html | 26 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 6 deletions(-) create mode 100644 ishtar_common/static/maintenance/maintenance.html diff --git a/ishtar_common/static/maintenance/maintenance-fr.html b/ishtar_common/static/maintenance/maintenance-fr.html index d950ad5ab..de39ec54f 100644 --- a/ishtar_common/static/maintenance/maintenance-fr.html +++ b/ishtar_common/static/maintenance/maintenance-fr.html @@ -1,14 +1,25 @@ - - Ishtar - + Ishtar - maintenance + + -

Ishtar est en maintenance.

+

+
+

+ Ishtar connait en ce moment une maintenance programmée.
+ Veuillez essayer plus tard.
+
Restez sur cette page pour une vérification automatique régulière. Vous serez redirigé lorsque le système sera de nouveau disponible.
+

+ Désolé pour le dérangement. +

+ Réessayer maintenant +
+

+ + 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 @@ + + + + Ishtar - maintenance + + + + +

+
+

+ Ishtar is currently undergoing a scheduled maintenance.
+ Please try back in 30 min.
+
Stay in this page for auto check. You will be redirected as soon as the system restarts.
+

+ Sorry for the inconvenience +

+ retry now +
+ +

+ + + + -- cgit v1.2.3 From 959581f5e8e69b7784ce31ed1ba84f8909c6f183 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Thu, 9 Jul 2015 18:04:36 +0200 Subject: Parcels: simply manage parcel association on wizards --- archaeological_operations/wizards.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/archaeological_operations/wizards.py b/archaeological_operations/wizards.py index 1e4de70b7..b31e7b7f6 100644 --- a/archaeological_operations/wizards.py +++ b/archaeological_operations/wizards.py @@ -109,9 +109,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]) -- cgit v1.2.3 From b11698ddc6192505df28f73b4139df17789262d8 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Fri, 10 Jul 2015 20:16:12 +0200 Subject: Parcel management: copy non existing parcel from operation when associating a file --- archaeological_files/tests.py | 87 ++++++++++++++++++++++++++++--------- archaeological_operations/models.py | 35 +++++++-------- archaeological_operations/utils.py | 67 +++++++++++++++++----------- 3 files changed, 123 insertions(+), 66 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 +# Copyright (C) 2010-2015 Étienne Loks # 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 6e74f2c44..e76de8dd9 100644 --- a/archaeological_operations/models.py +++ b/archaeological_operations/models.py @@ -428,25 +428,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) @@ -467,6 +448,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): @@ -715,6 +710,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: @@ -737,6 +733,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) -- cgit v1.2.3