summaryrefslogtreecommitdiff
path: root/archaeological_finds/models.py
diff options
context:
space:
mode:
Diffstat (limited to 'archaeological_finds/models.py')
-rw-r--r--archaeological_finds/models.py175
1 files changed, 169 insertions, 6 deletions
diff --git a/archaeological_finds/models.py b/archaeological_finds/models.py
index 7d4eadbf6..d1f194727 100644
--- a/archaeological_finds/models.py
+++ b/archaeological_finds/models.py
@@ -23,11 +23,12 @@ from django.conf import settings
from django.contrib.gis.db import models
from django.core.urlresolvers import reverse
from django.db.models import Max, Q
+from django.db.models.signals import m2m_changed
from django.utils.translation import ugettext_lazy as _, ugettext
from ishtar_common.models import GeneralType, ImageModel, BaseHistorizedItem, \
ShortMenuItem, LightHistorizedItem, HistoricalRecords, OwnPerms, Source, \
- Person, Basket
+ Person, Basket, get_external_id
from archaeological_operations.models import AdministrativeAct
from archaeological_context_records.models import ContextRecord, Dating
@@ -69,7 +70,14 @@ class PreservationType(GeneralType):
class IntegrityType(GeneralType):
class Meta:
verbose_name = _(u"Integrity type")
- verbose_name_plural = _(u"Integrity type")
+ verbose_name_plural = _(u"Integrity types")
+ ordering = ('label',)
+
+
+class RemarkabilityType(GeneralType):
+ class Meta:
+ verbose_name = _(u"Remarkability type")
+ verbose_name_plural = _(u"Remarkability types")
ordering = ('label',)
@@ -103,8 +111,9 @@ IS_ISOLATED_CHOICES = (
class BaseFind(BaseHistorizedItem, OwnPerms):
IS_ISOLATED_DICT = dict(IS_ISOLATED_CHOICES)
label = models.TextField(_(u"Free ID"))
- external_id = models.CharField(_(u"External ID"), blank=True, null=True,
- max_length=120)
+ external_id = models.TextField(_(u"External ID"), blank=True, null=True)
+ auto_external_id = models.BooleanField(
+ _(u"External ID is set automatically"), default=False)
description = models.TextField(_(u"Description"), blank=True, null=True)
comment = models.TextField(_(u"Comment"), blank=True, null=True)
topographic_localisation = models.CharField(
@@ -235,6 +244,20 @@ class BaseFind(BaseHistorizedItem, OwnPerms):
fields['find'] = field.related.model
return fields
+ def save(self, *args, **kwargs):
+ returned = super(BaseFind, self).save(*args, **kwargs)
+
+ updated = False
+ if not self.external_id or self.auto_external_id:
+ external_id = get_external_id('base_find_external_id', self)
+ if external_id != self.external_id:
+ updated = True
+ self.auto_external_id = True
+ self.external_id = external_id
+ if updated:
+ self.save()
+ return returned
+
WEIGHT_UNIT = (('g', _(u"g")),
('kg', _(u"kg")),)
@@ -287,8 +310,9 @@ class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem):
ATTRS_EQUIV = {'get_first_base_find': 'base_finds'}
base_finds = models.ManyToManyField(BaseFind, verbose_name=_(u"Base find"),
related_name='find')
- external_id = models.CharField(_(u"External ID"), blank=True, null=True,
- max_length=120)
+ external_id = models.TextField(_(u"External ID"), blank=True, null=True)
+ auto_external_id = models.BooleanField(
+ _(u"External ID is set automatically"), default=False)
order = models.IntegerField(_(u"Order"), default=1)
label = models.TextField(_(u"Free ID"))
description = models.TextField(_(u"Description"), blank=True, null=True)
@@ -325,6 +349,9 @@ class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem):
ObjectType, verbose_name=_(u"Object types"), related_name='find')
integrities = models.ManyToManyField(
IntegrityType, verbose_name=_(u"Integrity"), related_name='find')
+ remarkabilities = models.ManyToManyField(
+ RemarkabilityType, verbose_name=_(u"Remarkability"),
+ related_name='find')
length = models.FloatField(_(u"Length (cm)"), blank=True, null=True)
width = models.FloatField(_(u"Width (cm)"), blank=True, null=True)
height = models.FloatField(_(u"Height (cm)"), blank=True, null=True)
@@ -341,6 +368,8 @@ class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem):
choices=CHECK_CHOICES)
check_date = models.DateField(_(u"Check date"),
default=datetime.date.today)
+ estimated_value = models.FloatField(_(u"Estimated value"), blank=True,
+ null=True)
history = HistoricalRecords()
BASKET_MODEL = FindBasket
@@ -554,6 +583,18 @@ class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem):
def save(self, *args, **kwargs):
super(Find, self).save(*args, **kwargs)
+
+ updated = False
+ if not self.external_id or self.auto_external_id:
+ external_id = get_external_id('find_external_id', self)
+ if external_id != self.external_id:
+ updated = True
+ self.auto_external_id = True
+ self.external_id = external_id
+ if updated:
+ self.save()
+ return
+
q = self.base_finds
if not self.index and q.count():
operation = q.filter(
@@ -600,9 +641,22 @@ class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem):
# idx and idx['material_index__max'] + 1 or 1
+def base_find_find_changed(sender, **kwargs):
+ obj = kwargs.get('instance', None)
+ if not obj:
+ return
+ # recalculate complete id and external id
+ obj.save()
+
+m2m_changed.connect(base_find_find_changed, sender=Find.base_finds.through)
+
+
class FindSource(Source):
SHOW_URL = 'show-findsource'
MODIFY_URL = 'find_source_modify'
+ TABLE_COLS = ['find__base_finds__context_record__operation',
+ 'find__base_finds__context_record', 'find'] + \
+ Source.TABLE_COLS
class Meta:
verbose_name = _(u"Find documentation")
@@ -704,6 +758,115 @@ class Treatment(BaseHistorizedItem, OwnPerms):
basket.items.add(new)
+class AbsFindTreatments(object):
+ find = models.ForeignKey(Find, verbose_name=_(u"Find"),
+ related_name='treatments')
+ treatment = models.ForeignKey(Treatment, verbose_name=_(u"Treatment"),
+ primary_key=True)
+ # primary_key is set to prevent django to ask for an id column
+ # treatment is not a primary key
+ treatment_nb = models.IntegerField(_(u"Order"))
+ TABLE_COLS = ['treatment__treatment_type',
+ 'treatment__start_date', 'treatment__end_date',
+ 'treatment__location', 'treatment__person',
+ 'treatment_nb']
+
+ class Meta:
+ abstract = True
+
+ def __unicode__(self):
+ return u"{} - {} [{}]".format(
+ self.find, self.treatment, self.treatment_nb)
+
+
+class FindDownstreamTreatments(AbsFindTreatments):
+ """
+ CREATE VIEW find_downtreatments_tree AS
+ WITH RECURSIVE rel_tree AS (
+ SELECT id AS find_id, upstream_treatment_id, downstream_treatment_id,
+ 1 AS level,
+ array[upstream_treatment_id] AS path_info
+ FROM archaeological_finds_find
+ WHERE upstream_treatment_id is null
+ UNION ALL
+ SELECT c.id AS find_id, c.upstream_treatment_id,
+ c.downstream_treatment_id,
+ p.level + 1, p.path_info||c.upstream_treatment_id
+ FROM archaeological_finds_find c
+ JOIN rel_tree p
+ ON c.upstream_treatment_id = p.downstream_treatment_id
+ )
+ SELECT DISTINCT find_id, path_info, level
+ FROM rel_tree ORDER BY find_id;
+
+ CREATE VIEW find_downtreatments AS
+ SELECT DISTINCT find_id,
+ path_info[nb] AS treatment_id, level - nb + 1 AS treatment_nb
+ FROM (SELECT *, generate_subscripts(path_info, 1) AS nb
+ FROM find_downtreatments_tree) y
+ WHERE path_info[nb] is not NULL
+ ORDER BY find_id, treatment_id;
+ """
+
+ class Meta:
+ managed = False
+ db_table = 'find_downtreatments'
+ unique_together = ('find', 'treatment')
+
+
+class FindUpstreamTreatments(AbsFindTreatments):
+ """
+ CREATE VIEW find_uptreatments_tree AS
+ WITH RECURSIVE rel_tree AS (
+ SELECT id AS find_id, downstream_treatment_id, upstream_treatment_id,
+ 1 AS level,
+ array[downstream_treatment_id] AS path_info
+ FROM archaeological_finds_find
+ WHERE downstream_treatment_id is null
+ UNION ALL
+ SELECT c.id AS find_id, c.downstream_treatment_id,
+ c.upstream_treatment_id,
+ p.level + 1, p.path_info||c.downstream_treatment_id
+ FROM archaeological_finds_find c
+ JOIN rel_tree p
+ ON c.downstream_treatment_id = p.upstream_treatment_id
+ )
+ SELECT DISTINCT find_id, path_info, level
+ FROM rel_tree ORDER BY find_id;
+
+ CREATE VIEW find_uptreatments AS
+ SELECT DISTINCT find_id,
+ path_info[nb] AS treatment_id, level - nb + 1 AS treatment_nb
+ FROM (SELECT *, generate_subscripts(path_info, 1) AS nb
+ FROM find_uptreatments_tree) y
+ WHERE path_info[nb] is not NULL
+ ORDER BY find_id, treatment_id;
+ """
+
+ class Meta:
+ managed = False
+ db_table = 'find_uptreatments'
+ unique_together = ('find', 'treatment')
+
+
+class FindTreatments(AbsFindTreatments):
+ """
+ CREATE VIEW find_treatments AS
+ SELECT find_id, treatment_id, treatment_nb, TRUE as upstream
+ FROM find_uptreatments
+ UNION
+ SELECT find_id, treatment_id, treatment_nb, FALSE as upstream
+ FROM find_downtreatments
+ ORDER BY find_id, treatment_id, upstream;
+ """
+ upstream = models.BooleanField(_(u"Is upstream"))
+
+ class Meta:
+ managed = False
+ db_table = 'find_treatments'
+ unique_together = ('find', 'treatment')
+
+
class TreatmentSource(Source):
class Meta:
verbose_name = _(u"Treatment documentation")