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")  | 
