diff options
Diffstat (limited to 'archaeological_finds/models.py')
| -rw-r--r-- | archaeological_finds/models.py | 175 |
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") |
