summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archaeological_context_records/forms.py16
-rw-r--r--archaeological_context_records/migrations/0038_auto_20190122_1550.py87
-rw-r--r--archaeological_context_records/models.py29
-rw-r--r--archaeological_finds/models_finds.py5
-rw-r--r--archaeological_operations/forms.py30
-rw-r--r--archaeological_operations/migrations/0046_auto_20190122_1550.py178
-rw-r--r--archaeological_operations/migrations/0047_point_to_point_2d.py27
-rw-r--r--archaeological_operations/migrations/0048_auto_20190122_1621.py36
-rw-r--r--archaeological_operations/models.py60
-rw-r--r--ishtar_common/migrations/0084_ishtarsiteprofile_use_town_for_geo.py20
-rw-r--r--ishtar_common/models.py2
-rw-r--r--ishtar_common/utils.py9
12 files changed, 487 insertions, 12 deletions
diff --git a/archaeological_context_records/forms.py b/archaeological_context_records/forms.py
index ae25e0abe..7566dcc71 100644
--- a/archaeological_context_records/forms.py
+++ b/archaeological_context_records/forms.py
@@ -33,7 +33,7 @@ from archaeological_context_records import models
from ishtar_common.forms import FinalForm, FormSet, \
reverse_lazy, get_form_selection, TableSelect, ManageOldType, CustomForm, \
- FieldType, CustomFormSearch, IshtarForm, HistorySelect
+ FieldType, CustomFormSearch, IshtarForm, FormHeader, HistorySelect
from ishtar_common.forms_common import get_town_field
from archaeological_operations.forms import OperationSelect, ParcelField, \
RecordRelationsForm as OpeRecordRelationsForm, RecordRelationsFormSetBase
@@ -135,6 +135,7 @@ class RecordFormSelection(CustomFormSearch):
class RecordFormGeneral(CustomForm, ManageOldType):
+ HEADERS = {}
form_label = _("General")
form_admin_name = _(u"Context record - 020 - General")
form_slug = "contextrecord-020-general"
@@ -182,6 +183,19 @@ class RecordFormGeneral(CustomForm, ManageOldType):
label=_(u"Location"), widget=forms.Textarea,
required=False, validators=[validators.MaxLengthValidator(200)])
+ HEADERS['x'] = FormHeader(_(u"Coordinates"))
+ x = forms.FloatField(label=_(u"X"), required=False)
+ estimated_error_x = forms.FloatField(label=_(u"Estimated error for X"),
+ required=False)
+ y = forms.FloatField(label=_(u"Y"), required=False)
+ estimated_error_y = forms.FloatField(label=_(u"Estimated error for Y"),
+ required=False)
+ z = forms.FloatField(label=_(u"Z"), required=False)
+ estimated_error_z = forms.FloatField(label=_(u"Estimated error for Z"),
+ required=False)
+ spatial_reference_system = forms.ChoiceField(
+ label=_(u"Spatial Reference System"), required=False, choices=[])
+
TYPES = [
FieldType('unit', models.Unit),
FieldType('excavation_technic', models.ExcavationTechnicType),
diff --git a/archaeological_context_records/migrations/0038_auto_20190122_1550.py b/archaeological_context_records/migrations/0038_auto_20190122_1550.py
new file mode 100644
index 000000000..c7777dfd8
--- /dev/null
+++ b/archaeological_context_records/migrations/0038_auto_20190122_1550.py
@@ -0,0 +1,87 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.10 on 2019-01-22 15:50
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('ishtar_common', '0084_ishtarsiteprofile_use_town_for_geo'),
+ ('archaeological_context_records', '0037_auto_20190118_1203'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='contextrecord',
+ name='estimated_error_x',
+ field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour X'),
+ ),
+ migrations.AddField(
+ model_name='contextrecord',
+ name='estimated_error_y',
+ field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour Y'),
+ ),
+ migrations.AddField(
+ model_name='contextrecord',
+ name='estimated_error_z',
+ field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour Z'),
+ ),
+ migrations.AddField(
+ model_name='contextrecord',
+ name='spatial_reference_system',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='ishtar_common.SpatialReferenceSystem', verbose_name='Syst\xe8me de r\xe9f\xe9rence spatiale'),
+ ),
+ migrations.AddField(
+ model_name='contextrecord',
+ name='x',
+ field=models.FloatField(blank=True, null=True, verbose_name='X'),
+ ),
+ migrations.AddField(
+ model_name='contextrecord',
+ name='y',
+ field=models.FloatField(blank=True, null=True, verbose_name='Y'),
+ ),
+ migrations.AddField(
+ model_name='contextrecord',
+ name='z',
+ field=models.FloatField(blank=True, null=True, verbose_name='Z'),
+ ),
+ migrations.AddField(
+ model_name='historicalcontextrecord',
+ name='estimated_error_x',
+ field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour X'),
+ ),
+ migrations.AddField(
+ model_name='historicalcontextrecord',
+ name='estimated_error_y',
+ field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour Y'),
+ ),
+ migrations.AddField(
+ model_name='historicalcontextrecord',
+ name='estimated_error_z',
+ field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour Z'),
+ ),
+ migrations.AddField(
+ model_name='historicalcontextrecord',
+ name='spatial_reference_system',
+ field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='ishtar_common.SpatialReferenceSystem'),
+ ),
+ migrations.AddField(
+ model_name='historicalcontextrecord',
+ name='x',
+ field=models.FloatField(blank=True, null=True, verbose_name='X'),
+ ),
+ migrations.AddField(
+ model_name='historicalcontextrecord',
+ name='y',
+ field=models.FloatField(blank=True, null=True, verbose_name='Y'),
+ ),
+ migrations.AddField(
+ model_name='historicalcontextrecord',
+ name='z',
+ field=models.FloatField(blank=True, null=True, verbose_name='Z'),
+ ),
+ ]
diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py
index cb6dbc635..89526076a 100644
--- a/archaeological_context_records/models.py
+++ b/archaeological_context_records/models.py
@@ -27,14 +27,15 @@ from django.utils.translation import ugettext_lazy as _, pgettext, \
activate, pgettext_lazy, deactivate
from django.utils.text import slugify
-from ishtar_common.utils import cached_label_changed, m2m_historization_changed
+from ishtar_common.utils import cached_label_changed, \
+ m2m_historization_changed, post_save_point
from ishtar_common.models import Document, GeneralType, \
BaseHistorizedItem, HistoricalRecords, OwnPerms, ShortMenuItem, \
GeneralRelationType, GeneralRecordRelations, post_delete_record_relation,\
post_save_cache, ValueGetter, BulkUpdatedItem, ExternalIdManager, \
RelationItem, Town, get_current_profile, document_attached_changed, \
- HistoryModel, SearchAltName
+ HistoryModel, SearchAltName, SpatialReferenceSystem
from archaeological_operations.models import Operation, Period, Parcel, \
ArchaeologicalSite
@@ -470,6 +471,18 @@ class ContextRecord(BulkUpdatedItem, BaseHistorizedItem,
verbose_name=_(u"Excavation technique"))
related_context_records = models.ManyToManyField(
'ContextRecord', through='RecordRelations', blank=True)
+ x = models.FloatField(_(u'X'), blank=True, null=True)
+ y = models.FloatField(_(u'Y'), blank=True, null=True)
+ z = models.FloatField(_(u'Z'), blank=True, null=True)
+ estimated_error_x = models.FloatField(_(u'Estimated error for X'),
+ blank=True, null=True)
+ estimated_error_y = models.FloatField(_(u'Estimated error for Y'),
+ blank=True, null=True)
+ estimated_error_z = models.FloatField(_(u'Estimated error for Z'),
+ blank=True, null=True)
+ spatial_reference_system = models.ForeignKey(
+ SpatialReferenceSystem, verbose_name=_(u"Spatial Reference System"),
+ blank=True, null=True)
point_2d = models.PointField(_(u"Point (2D)"), blank=True, null=True)
point = models.PointField(_(u"Point (3D)"), blank=True, null=True, dim=3)
multi_polygon = models.MultiPolygonField(_(u"Multi polygon"), blank=True,
@@ -510,6 +523,11 @@ class ContextRecord(BulkUpdatedItem, BaseHistorizedItem,
def __unicode__(self):
return self.short_label
+ def get_town_centroid(self):
+ if self.town:
+ return self.town.center
+ return self.operation.get_town_centroid()
+
@classmethod
def cached_label_bulk_update(cls, operation_id=None, parcel_id=None,
transaction_id=None):
@@ -732,7 +750,12 @@ class ContextRecord(BulkUpdatedItem, BaseHistorizedItem,
self.save()
-post_save.connect(cached_label_changed, sender=ContextRecord)
+def context_record_post_save(sender, **kwargs):
+ cached_label_changed(sender=sender, **kwargs)
+ post_save_point(sender=sender, **kwargs)
+
+
+post_save.connect(context_record_post_save, sender=ContextRecord)
m2m_changed.connect(document_attached_changed,
sender=ContextRecord.documents.through)
diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py
index 15b6451d6..fce9548ba 100644
--- a/archaeological_finds/models_finds.py
+++ b/archaeological_finds/models_finds.py
@@ -354,6 +354,11 @@ class BaseFind(BulkUpdatedItem, BaseHistorizedItem, OwnPerms):
return find
return
+ def get_town_centroid(self):
+ if self.context_record.town:
+ return self.context_record.town.get_town_centroid()
+ return self.context_record.operation.get_town_centroid()
+
def generate_index(self):
"""
Generate index based on operation or context record (based on
diff --git a/archaeological_operations/forms.py b/archaeological_operations/forms.py
index b093b383c..f964375c7 100644
--- a/archaeological_operations/forms.py
+++ b/archaeological_operations/forms.py
@@ -40,7 +40,7 @@ from bootstrap_datepicker.widgets import DateField
from ishtar_common import widgets
from ishtar_common.forms import FinalForm, FormSet, get_now, \
reverse_lazy, TableSelect, get_data_from_formset, \
- ManageOldType, IshtarForm, CustomForm, FieldType, HistorySelect
+ ManageOldType, IshtarForm, CustomForm, FieldType, FormHeader, HistorySelect
from ishtar_common.forms_common import TownFormSet, get_town_field, TownForm
from ishtar_common.models import valid_id, Person, Town, \
DocumentTemplate, Organization, get_current_profile, \
@@ -741,6 +741,7 @@ class DashboardForm(IshtarForm):
class OperationFormGeneral(CustomForm, ManageOldType):
+ HEADERS = {}
form_label = _(u"General")
form_admin_name = _(u"Operation - 010 - General")
form_slug = "operation-010-general"
@@ -856,6 +857,19 @@ class OperationFormGeneral(CustomForm, ManageOldType):
virtual_operation = forms.BooleanField(required=False,
label=_(u"Virtual operation"))
+ HEADERS['x'] = FormHeader(_(u"Coordinates"))
+ x = forms.FloatField(label=_(u"X"), required=False)
+ estimated_error_x = forms.FloatField(label=_(u"Estimated error for X"),
+ required=False)
+ y = forms.FloatField(label=_(u"Y"), required=False)
+ estimated_error_y = forms.FloatField(label=_(u"Estimated error for Y"),
+ required=False)
+ z = forms.FloatField(label=_(u"Z"), required=False)
+ estimated_error_z = forms.FloatField(label=_(u"Estimated error for Z"),
+ required=False)
+ spatial_reference_system = forms.ChoiceField(
+ label=_(u"Spatial Reference System"), required=False, choices=[])
+
FILE_FIELDS = [
'report_delivery_date',
'report_processing',
@@ -1154,6 +1168,7 @@ class PeriodForm(CustomForm, ManageOldType, forms.Form):
class ArchaeologicalSiteForm(ManageOldType):
+ HEADERS = {}
reference = forms.CharField(label=_(u"Reference"), max_length=200)
name = forms.CharField(label=_(u"Name"), max_length=200, required=False)
periods = forms.MultipleChoiceField(
@@ -1162,6 +1177,19 @@ class ArchaeologicalSiteForm(ManageOldType):
remains = forms.MultipleChoiceField(
label=_("Remains"), choices=[], widget=widgets.Select2Multiple,
required=False)
+ HEADERS['x'] = FormHeader(_(u"Coordinates"))
+ x = forms.FloatField(label=_(u"X"), required=False)
+ estimated_error_x = forms.FloatField(label=_(u"Estimated error for X"),
+ required=False)
+ y = forms.FloatField(label=_(u"Y"), required=False)
+ estimated_error_y = forms.FloatField(label=_(u"Estimated error for Y"),
+ required=False)
+ z = forms.FloatField(label=_(u"Z"), required=False)
+ estimated_error_z = forms.FloatField(label=_(u"Estimated error for Z"),
+ required=False)
+ spatial_reference_system = forms.ChoiceField(
+ label=_(u"Spatial Reference System"), required=False, choices=[])
+
TYPES = [
FieldType('periods', models.Period, True),
diff --git a/archaeological_operations/migrations/0046_auto_20190122_1550.py b/archaeological_operations/migrations/0046_auto_20190122_1550.py
new file mode 100644
index 000000000..4a352a970
--- /dev/null
+++ b/archaeological_operations/migrations/0046_auto_20190122_1550.py
@@ -0,0 +1,178 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.10 on 2019-01-22 15:50
+from __future__ import unicode_literals
+
+import django.contrib.gis.db.models.fields
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('ishtar_common', '0084_ishtarsiteprofile_use_town_for_geo'),
+ ('archaeological_operations', '0045_auto_20190118_1203'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='archaeologicalsite',
+ name='estimated_error_x',
+ field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour X'),
+ ),
+ migrations.AddField(
+ model_name='archaeologicalsite',
+ name='estimated_error_y',
+ field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour Y'),
+ ),
+ migrations.AddField(
+ model_name='archaeologicalsite',
+ name='estimated_error_z',
+ field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour Z'),
+ ),
+ migrations.AddField(
+ model_name='archaeologicalsite',
+ name='point_2d',
+ field=django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326, verbose_name='Point (2D)'),
+ ),
+ migrations.AddField(
+ model_name='archaeologicalsite',
+ name='spatial_reference_system',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='ishtar_common.SpatialReferenceSystem', verbose_name='Syst\xe8me de r\xe9f\xe9rence spatiale'),
+ ),
+ migrations.AddField(
+ model_name='archaeologicalsite',
+ name='x',
+ field=models.FloatField(blank=True, null=True, verbose_name='X'),
+ ),
+ migrations.AddField(
+ model_name='archaeologicalsite',
+ name='y',
+ field=models.FloatField(blank=True, null=True, verbose_name='Y'),
+ ),
+ migrations.AddField(
+ model_name='archaeologicalsite',
+ name='z',
+ field=models.FloatField(blank=True, null=True, verbose_name='Z'),
+ ),
+ migrations.AddField(
+ model_name='historicalarchaeologicalsite',
+ name='estimated_error_x',
+ field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour X'),
+ ),
+ migrations.AddField(
+ model_name='historicalarchaeologicalsite',
+ name='estimated_error_y',
+ field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour Y'),
+ ),
+ migrations.AddField(
+ model_name='historicalarchaeologicalsite',
+ name='estimated_error_z',
+ field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour Z'),
+ ),
+ migrations.AddField(
+ model_name='historicalarchaeologicalsite',
+ name='point_2d',
+ field=django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326, verbose_name='Point (2D)'),
+ ),
+ migrations.AddField(
+ model_name='historicalarchaeologicalsite',
+ name='spatial_reference_system',
+ field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='ishtar_common.SpatialReferenceSystem'),
+ ),
+ migrations.AddField(
+ model_name='historicalarchaeologicalsite',
+ name='x',
+ field=models.FloatField(blank=True, null=True, verbose_name='X'),
+ ),
+ migrations.AddField(
+ model_name='historicalarchaeologicalsite',
+ name='y',
+ field=models.FloatField(blank=True, null=True, verbose_name='Y'),
+ ),
+ migrations.AddField(
+ model_name='historicalarchaeologicalsite',
+ name='z',
+ field=models.FloatField(blank=True, null=True, verbose_name='Z'),
+ ),
+ migrations.AddField(
+ model_name='historicaloperation',
+ name='estimated_error_x',
+ field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour X'),
+ ),
+ migrations.AddField(
+ model_name='historicaloperation',
+ name='estimated_error_y',
+ field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour Y'),
+ ),
+ migrations.AddField(
+ model_name='historicaloperation',
+ name='estimated_error_z',
+ field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour Z'),
+ ),
+ migrations.AddField(
+ model_name='historicaloperation',
+ name='point_2d',
+ field=django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326, verbose_name='Point (2D)'),
+ ),
+ migrations.AddField(
+ model_name='historicaloperation',
+ name='spatial_reference_system',
+ field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='ishtar_common.SpatialReferenceSystem'),
+ ),
+ migrations.AddField(
+ model_name='historicaloperation',
+ name='x',
+ field=models.FloatField(blank=True, null=True, verbose_name='X'),
+ ),
+ migrations.AddField(
+ model_name='historicaloperation',
+ name='y',
+ field=models.FloatField(blank=True, null=True, verbose_name='Y'),
+ ),
+ migrations.AddField(
+ model_name='historicaloperation',
+ name='z',
+ field=models.FloatField(blank=True, null=True, verbose_name='Z'),
+ ),
+ migrations.AddField(
+ model_name='operation',
+ name='estimated_error_x',
+ field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour X'),
+ ),
+ migrations.AddField(
+ model_name='operation',
+ name='estimated_error_y',
+ field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour Y'),
+ ),
+ migrations.AddField(
+ model_name='operation',
+ name='estimated_error_z',
+ field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour Z'),
+ ),
+ migrations.AddField(
+ model_name='operation',
+ name='point_2d',
+ field=django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326, verbose_name='Point (2D)'),
+ ),
+ migrations.AddField(
+ model_name='operation',
+ name='spatial_reference_system',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='ishtar_common.SpatialReferenceSystem', verbose_name='Syst\xe8me de r\xe9f\xe9rence spatiale'),
+ ),
+ migrations.AddField(
+ model_name='operation',
+ name='x',
+ field=models.FloatField(blank=True, null=True, verbose_name='X'),
+ ),
+ migrations.AddField(
+ model_name='operation',
+ name='y',
+ field=models.FloatField(blank=True, null=True, verbose_name='Y'),
+ ),
+ migrations.AddField(
+ model_name='operation',
+ name='z',
+ field=models.FloatField(blank=True, null=True, verbose_name='Z'),
+ ),
+ ]
diff --git a/archaeological_operations/migrations/0047_point_to_point_2d.py b/archaeological_operations/migrations/0047_point_to_point_2d.py
new file mode 100644
index 000000000..7750fb88a
--- /dev/null
+++ b/archaeological_operations/migrations/0047_point_to_point_2d.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.10 on 2019-01-22 15:54
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+def point_to_point_2d(apps, schema_editor):
+ ArchaeologicalSite = apps.get_model(
+ 'archaeological_operations', 'ArchaeologicalSite')
+ Operation = apps.get_model('archaeological_operations', 'Operation')
+ for kls in [ArchaeologicalSite, Operation]:
+ for item in kls.objects.exclude(point__isnull=True).all():
+ item.point_2d = item.point
+ item.point = None
+ item.save()
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('archaeological_operations', '0046_auto_20190122_1550'),
+ ]
+
+ operations = [
+ migrations.RunPython(point_to_point_2d)
+ ]
diff --git a/archaeological_operations/migrations/0048_auto_20190122_1621.py b/archaeological_operations/migrations/0048_auto_20190122_1621.py
new file mode 100644
index 000000000..c7d2d8cb1
--- /dev/null
+++ b/archaeological_operations/migrations/0048_auto_20190122_1621.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.10 on 2019-01-22 16:21
+from __future__ import unicode_literals
+
+import django.contrib.gis.db.models.fields
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('archaeological_operations', '0047_point_to_point_2d'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='archaeologicalsite',
+ name='point',
+ field=django.contrib.gis.db.models.fields.PointField(blank=True, dim=3, null=True, srid=4326, verbose_name='Point'),
+ ),
+ migrations.AlterField(
+ model_name='historicalarchaeologicalsite',
+ name='point',
+ field=django.contrib.gis.db.models.fields.PointField(blank=True, dim=3, null=True, srid=4326, verbose_name='Point'),
+ ),
+ migrations.AlterField(
+ model_name='historicaloperation',
+ name='point',
+ field=django.contrib.gis.db.models.fields.PointField(blank=True, dim=3, null=True, srid=4326, verbose_name='Point'),
+ ),
+ migrations.AlterField(
+ model_name='operation',
+ name='point',
+ field=django.contrib.gis.db.models.fields.PointField(blank=True, dim=3, null=True, srid=4326, verbose_name='Point'),
+ ),
+ ]
diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py
index 7bb27ab6c..a8f1d4faf 100644
--- a/archaeological_operations/models.py
+++ b/archaeological_operations/models.py
@@ -22,6 +22,8 @@ from itertools import groupby
from django.conf import settings
from django.contrib.gis.db import models
+from django.contrib.gis.db.models.aggregates import Union
+from django.contrib.gis.db.models.functions import Centroid
from django.core.urlresolvers import reverse
from django.db import IntegrityError, transaction
from django.db.models import Q, Count, Sum, Max, Avg
@@ -36,9 +38,10 @@ from ishtar_common.models import BaseHistorizedItem, Dashboard, \
OperationType, Organization, OwnPerms, Person, PersonType, \
post_delete_record_relation, post_save_cache, RelationItem, \
ShortMenuItem, SourceType, Town, ValueGetter, get_current_profile, \
- document_attached_changed, HistoryModel, SearchAltName
+ document_attached_changed, HistoryModel, SearchAltName, \
+ SpatialReferenceSystem
from ishtar_common.utils import cached_label_changed, \
- force_cached_label_changed, mode, m2m_historization_changed
+ force_cached_label_changed, mode, m2m_historization_changed, post_save_point
class RemainType(GeneralType):
@@ -260,7 +263,20 @@ class ArchaeologicalSite(BaseHistorizedItem, OwnPerms, ValueGetter,
null=True, blank=True)
# gis
- point = models.PointField(_(u"Point"), blank=True, null=True)
+ x = models.FloatField(_(u'X'), blank=True, null=True)
+ y = models.FloatField(_(u'Y'), blank=True, null=True)
+ z = models.FloatField(_(u'Z'), blank=True, null=True)
+ estimated_error_x = models.FloatField(_(u'Estimated error for X'),
+ blank=True, null=True)
+ estimated_error_y = models.FloatField(_(u'Estimated error for Y'),
+ blank=True, null=True)
+ estimated_error_z = models.FloatField(_(u'Estimated error for Z'),
+ blank=True, null=True)
+ spatial_reference_system = models.ForeignKey(
+ SpatialReferenceSystem, verbose_name=_(u"Spatial Reference System"),
+ blank=True, null=True)
+ point = models.PointField(_(u"Point"), blank=True, null=True, dim=3)
+ point_2d = models.PointField(_(u"Point (2D)"), blank=True, null=True)
multi_polygon = models.MultiPolygonField(_(u"Multi polygon"), blank=True,
null=True)
@@ -369,6 +385,13 @@ class ArchaeologicalSite(BaseHistorizedItem, OwnPerms, ValueGetter,
def towns_label(self):
return u" - ".join(self.towns_codes())
+ def get_town_centroid(self):
+ q = self.towns.filter(center__isnull=False).annotate(
+ centroid=Centroid(Union('center'))).all()
+ if not q.count():
+ return None
+ return q.all()[0].centroid
+
def _get_base_image_path(self):
return u"{}/{}".format(self.SLUG, self.reference)
@@ -422,7 +445,12 @@ class ArchaeologicalSite(BaseHistorizedItem, OwnPerms, ValueGetter,
)
-post_save.connect(cached_label_changed, sender=ArchaeologicalSite)
+def site_post_save(sender, **kwargs):
+ cached_label_changed(sender=sender, **kwargs)
+ post_save_point(sender=sender, **kwargs)
+
+
+post_save.connect(site_post_save, sender=ArchaeologicalSite)
m2m_changed.connect(document_attached_changed,
sender=ArchaeologicalSite.documents.through)
@@ -898,7 +926,20 @@ class Operation(ClosedItem, BaseHistorizedItem, OwnPerms, ValueGetter,
blank=True, null=True)
# gis
- point = models.PointField(_(u"Point"), blank=True, null=True)
+ x = models.FloatField(_(u'X'), blank=True, null=True)
+ y = models.FloatField(_(u'Y'), blank=True, null=True)
+ z = models.FloatField(_(u'Z'), blank=True, null=True)
+ estimated_error_x = models.FloatField(_(u'Estimated error for X'),
+ blank=True, null=True)
+ estimated_error_y = models.FloatField(_(u'Estimated error for Y'),
+ blank=True, null=True)
+ estimated_error_z = models.FloatField(_(u'Estimated error for Z'),
+ blank=True, null=True)
+ spatial_reference_system = models.ForeignKey(
+ SpatialReferenceSystem, verbose_name=_(u"Spatial Reference System"),
+ blank=True, null=True)
+ point = models.PointField(_(u"Point"), blank=True, null=True, dim=3)
+ point_2d = models.PointField(_(u"Point (2D)"), blank=True, null=True)
multi_polygon = models.MultiPolygonField(_(u"Multi polygon"), blank=True,
null=True)
history = HistoricalRecords(bases=[HistoryModel])
@@ -1067,6 +1108,13 @@ class Operation(ClosedItem, BaseHistorizedItem, OwnPerms, ValueGetter,
def render_parcels(self):
return Parcel.render_parcels(list(self.parcels.all()))
+ def get_town_centroid(self):
+ q = self.towns.filter(center__isnull=False).annotate(
+ centroid=Centroid(Union('center'))).all()
+ if not q.count():
+ return None
+ return q.all()[0].centroid
+
def context_record_relations_q(self):
from archaeological_context_records.models \
import RecordRelations as CRRL
@@ -1416,6 +1464,8 @@ for attr in Operation.HISTORICAL_M2M:
def operation_post_save(sender, **kwargs):
if not kwargs['instance']:
return
+ post_save_point(sender=sender, **kwargs)
+
operation = kwargs['instance']
operation.skip_history_when_saving = True
if operation.fnap_financing and operation.cost:
diff --git a/ishtar_common/migrations/0084_ishtarsiteprofile_use_town_for_geo.py b/ishtar_common/migrations/0084_ishtarsiteprofile_use_town_for_geo.py
new file mode 100644
index 000000000..182187e8b
--- /dev/null
+++ b/ishtar_common/migrations/0084_ishtarsiteprofile_use_town_for_geo.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.10 on 2019-01-22 15:44
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('ishtar_common', '0083_document_index_external_id'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='ishtarsiteprofile',
+ name='use_town_for_geo',
+ field=models.BooleanField(default=True, verbose_name='Use town to locate when coordinates are missing'),
+ ),
+ ]
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 6a4a0930e..76e415368 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -2151,6 +2151,8 @@ class IshtarSiteProfile(models.Model, Cached):
preservation = models.BooleanField(_(u"Preservation module"),
default=False)
mapping = models.BooleanField(_(u"Mapping module"), default=False)
+ use_town_for_geo = models.BooleanField(
+ _(u"Use town to locate when coordinates are missing"), default=True)
underwater = models.BooleanField(_(u"Underwater module"), default=False)
parcel_mandatory = models.BooleanField(
_(u"Parcel are mandatory for context records"), default=True)
diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py
index 55e3a3a75..20957c43e 100644
--- a/ishtar_common/utils.py
+++ b/ishtar_common/utils.py
@@ -476,8 +476,11 @@ def post_save_point(sender, **kwargs):
if not kwargs.get('instance'):
return
instance = kwargs.get('instance')
- point = None
- point_2d = None
+ point = instance.point
+ point_2d = instance.point_2d
+ from ishtar_common.models import get_current_profile # not clean but utils
+ # must be loaded before models
+ profile = get_current_profile()
if instance.x and instance.y and \
instance.spatial_reference_system and \
instance.spatial_reference_system.auth_name == 'EPSG' and \
@@ -488,6 +491,8 @@ def post_save_point(sender, **kwargs):
point = convert_coordinates_to_point(
instance.x, instance.y, instance.z,
srid=instance.spatial_reference_system.srid)
+ elif profile.use_town_for_geo:
+ point_2d = instance.get_town_centroid()
if point_2d != instance.point_2d or point != instance.point:
instance.point = point
instance.point_2d = point_2d