summaryrefslogtreecommitdiff
path: root/archaeological_finds/models.py
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2016-12-07 20:01:09 +0100
committerÉtienne Loks <etienne.loks@iggdrasil.net>2016-12-07 20:01:09 +0100
commit86c95b458869560d97ede77579262c86597c4453 (patch)
tree5377e0e17c0a0f0952d37997aee038803b6ca680 /archaeological_finds/models.py
parentfcf63a61bdcab906aad45c69eb95167850e2c40a (diff)
downloadIshtar-86c95b458869560d97ede77579262c86597c4453.tar.bz2
Ishtar-86c95b458869560d97ede77579262c86597c4453.zip
Manage treatment files
Diffstat (limited to 'archaeological_finds/models.py')
-rw-r--r--archaeological_finds/models.py1132
1 files changed, 15 insertions, 1117 deletions
diff --git a/archaeological_finds/models.py b/archaeological_finds/models.py
index 274e2d76f..40251bba0 100644
--- a/archaeological_finds/models.py
+++ b/archaeological_finds/models.py
@@ -1,1117 +1,15 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# Copyright (C) 2012-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-# See the file COPYING for details.
-
-import datetime
-
-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, post_save, post_delete, \
- pre_delete
-from django.template.defaultfilters import slugify
-from django.utils.translation import ugettext_lazy as _, ugettext
-
-from ishtar_common.utils import cached_label_changed
-
-from ishtar_common.models import GeneralType, ImageModel, BaseHistorizedItem, \
- ShortMenuItem, LightHistorizedItem, HistoricalRecords, OwnPerms, Source, \
- Organization, Person, Basket, get_external_id, post_save_cache
-
-from archaeological_operations.models import AdministrativeAct
-from archaeological_context_records.models import ContextRecord, Dating
-
-from ishtar_common.models import PRIVATE_FIELDS
-from archaeological_warehouse.models import Warehouse, Container
-
-
-class MaterialType(GeneralType):
- code = models.CharField(_(u"Code"), max_length=10, blank=True, null=True)
- recommendation = models.TextField(_(u"Recommendation"), blank=True,
- null=True)
- parent = models.ForeignKey("MaterialType", blank=True, null=True,
- verbose_name=_(u"Parent material"))
-
- class Meta:
- verbose_name = _(u"Material type")
- verbose_name_plural = _(u"Material types")
- ordering = ('label',)
-post_save.connect(post_save_cache, sender=MaterialType)
-post_delete.connect(post_save_cache, sender=MaterialType)
-
-
-class ConservatoryState(GeneralType):
- parent = models.ForeignKey("ConservatoryState", blank=True, null=True,
- verbose_name=_(u"Parent conservatory state"))
-
- class Meta:
- verbose_name = _(u"Conservatory state")
- verbose_name_plural = _(u"Conservatory states")
- ordering = ('label',)
-post_save.connect(post_save_cache, sender=ConservatoryState)
-post_delete.connect(post_save_cache, sender=ConservatoryState)
-
-
-class PreservationType(GeneralType):
- class Meta:
- verbose_name = _(u"Preservation type")
- verbose_name_plural = _(u"Preservation types")
- ordering = ('label',)
-post_save.connect(post_save_cache, sender=PreservationType)
-post_delete.connect(post_save_cache, sender=PreservationType)
-
-
-class IntegrityType(GeneralType):
- class Meta:
- verbose_name = _(u"Integrity / interest type")
- verbose_name_plural = _(u"Integrity / interest types")
- ordering = ('label',)
-post_save.connect(post_save_cache, sender=IntegrityType)
-post_delete.connect(post_save_cache, sender=IntegrityType)
-
-
-class RemarkabilityType(GeneralType):
- class Meta:
- verbose_name = _(u"Remarkability type")
- verbose_name_plural = _(u"Remarkability types")
- ordering = ('label',)
-post_save.connect(post_save_cache, sender=RemarkabilityType)
-post_delete.connect(post_save_cache, sender=RemarkabilityType)
-
-
-class ObjectType(GeneralType):
- parent = models.ForeignKey("ObjectType", blank=True, null=True,
- verbose_name=_(u"Parent"))
-
- class Meta:
- verbose_name = _(u"Object type")
- verbose_name_plural = _(u"Object types")
- ordering = ('parent__label', 'label',)
-
- def full_label(self):
- lbls = [self.label]
- item = self
- while item.parent:
- item = item.parent
- lbls.append(item.label)
- return u" > ".join(reversed(lbls))
-
- def __unicode__(self):
- return self.label
-post_save.connect(post_save_cache, sender=ObjectType)
-post_delete.connect(post_save_cache, sender=ObjectType)
-
-IS_ISOLATED_CHOICES = (
- ('U', _(u"Unknow")),
- ('O', _(u"Object")),
- ('B', _(u"Batch"))
-)
-
-
-class BaseFind(BaseHistorizedItem, OwnPerms):
- IS_ISOLATED_DICT = dict(IS_ISOLATED_CHOICES)
- label = models.TextField(_(u"Free ID"))
- 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(
- _(u"Topographic localisation"), blank=True, null=True, max_length=120)
- special_interest = models.CharField(_(u"Special interest"), blank=True,
- null=True, max_length=120)
- context_record = models.ForeignKey(
- ContextRecord, related_name='base_finds',
- verbose_name=_(u"Context Record"))
- discovery_date = models.DateField(_(u"Discovery date"),
- blank=True, null=True)
- batch = models.CharField(_(u"Batch/object"), max_length=1, default="U",
- choices=IS_ISOLATED_CHOICES)
- index = models.IntegerField(u"Index", default=0)
- material_index = models.IntegerField(_(u"Material index"), default=0)
- point = models.PointField(_(u"Point"), blank=True, null=True, dim=3)
- line = models.LineStringField(_(u"Line"), blank=True, null=True)
- polygon = models.PolygonField(_(u"Polygon"), blank=True, null=True)
- cache_short_id = models.TextField(
- _(u"Short ID"), blank=True, null=True,
- help_text=_(u"Cached value - do not edit"))
- cache_complete_id = models.TextField(
- _(u"Complete ID"), blank=True, null=True,
- help_text=_(u"Cached value - do not edit"))
- history = HistoricalRecords()
- RELATED_POST_PROCESS = ['find']
-
- class Meta:
- verbose_name = _(u"Base find")
- verbose_name_plural = _(u"Base finds")
- permissions = (
- ("view_basefind", ugettext(u"Can view all Base finds")),
- ("view_own_basefind", ugettext(u"Can view own Base find")),
- ("add_own_basefind", ugettext(u"Can add own Base find")),
- ("change_own_basefind", ugettext(u"Can change own Base find")),
- ("delete_own_basefind", ugettext(u"Can delete own Base find")),
- )
-
- def __unicode__(self):
- return self.label
-
- def get_last_find(self):
- # TODO: manage virtuals - property(last_find) ?
- finds = self.find.filter().order_by("-order").all()
- return finds and finds[0]
-
- @classmethod
- def get_max_index(cls, operation):
- q = BaseFind.objects\
- .filter(context_record__operation=operation)
- if q.count():
- return q.aggregate(Max('index'))['index__max']
- return 0
-
- def complete_id(self):
- # OPE|MAT.CODE|UE|FIND_index
- if not self.context_record.operation:
- return
- # find = self.get_last_find()
- ope = self.context_record.operation
- c_id = [unicode(ope.code_patriarche) if ope.code_patriarche else
- (unicode(ope.year) + "-" + unicode(ope.operation_code))]
- materials = set()
- for find in self.find.filter(downstream_treatment__isnull=True):
- for mat in find.material_types.all():
- if mat.code:
- materials.add(mat.code)
- c_id.append(u'-'.join(sorted(list(materials))))
- c_id.append(self.context_record.label)
- max_index = str(self.get_max_index(ope))
- c_id.append((u'{:0' + str(len(max_index)) + 'd}').format(self.index))
- return settings.JOINT.join(c_id)
-
- def short_id(self):
- # OPE|FIND_index
- if not self.context_record.operation:
- return
- ope = self.context_record.operation
- c_id = [(ope.code_patriarche and unicode(ope.code_patriarche)) or
- (unicode(ope.year) + "-" + unicode(ope.operation_code))]
- max_index = str(self.get_max_index(ope))
- c_id.append((u'{:0' + str(len(max_index)) + 'd}').format(self.index))
- return settings.JOINT.join(c_id)
-
- def full_label(self):
- return self._real_label() or self._temp_label() or u""
-
- def material_type_label(self):
- find = self.get_last_find()
- finds = [find and find.material_type.code or '']
- ope = self.context_record.operation
- finds += [unicode(ope.code_patriarche) or
- (unicode(ope.year) + "-" + unicode(ope.operation_code))]
- finds += [self.context_record.label, unicode(self.material_index)]
- return settings.JOINT.join(finds)
-
- def _real_label(self):
- if not self.context_record.parcel \
- or not self.context_record.operation \
- or not self.context_record.operation.code_patriarche:
- return
- find = self.get_last_find()
- lbl = find.label or self.label
- return settings.JOINT.join(
- [unicode(it) for it in (
- self.context_record.operation.code_patriarche,
- self.context_record.label, lbl) if it])
-
- def _temp_label(self):
- if not self.context_record.parcel:
- return
- find = self.get_last_find()
- lbl = find.label or self.label
- return settings.JOINT.join(
- [unicode(it) for it in (
- self.context_record.parcel.year, self.index,
- self.context_record.label, lbl) if it])
-
- @property
- def name(self):
- return self.label
-
- @classmethod
- def get_extra_fields(cls):
- fields = {}
- for field in Find._meta.many_to_many:
- if field.name == 'base_finds':
- 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._cached_label_checked = False
- self.save()
- return returned
-
-WEIGHT_UNIT = (('g', _(u"g")),
- ('kg', _(u"kg")),)
-
-CHECK_CHOICES = (('NC', _(u"Not checked")),
- ('CI', _(u"Checked but incorrect")),
- ('CC', _(u"Checked and correct")),
- )
-
-
-class FindBasket(Basket):
- items = models.ManyToManyField('Find', blank=True, null=True,
- related_name='basket')
-
-
-class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem):
- CHECK_DICT = dict(CHECK_CHOICES)
- SHOW_URL = 'show-find'
- SLUG = 'find'
- TABLE_COLS = ['label', 'material_types', 'datings__period',
- 'base_finds__context_record__parcel__town',
- 'base_finds__context_record__operation__year',
- 'base_finds__context_record__operation__operation_code',
- 'container__reference', 'container__location',
- 'base_finds__batch',
- 'base_finds__context_record__parcel__town',
- 'base_finds__context_record__parcel', ]
- if settings.COUNTRY == 'fr':
- TABLE_COLS.insert(
- 6, 'base_finds__context_record__operation__code_patriarche')
- TABLE_COLS_FOR_OPE = [
- 'base_finds__cache_short_id',
- 'base_finds__cache_complete_id',
- 'previous_id', 'label', 'material_types',
- 'datings__period__label', 'find_number', 'object_types',
- 'description',
- 'base_finds__context_record__parcel__town',
- 'base_finds__context_record__parcel', ]
- TABLE_COLS_FOR_OPE_LBL = {
- 'datings__period__label': _(u"Periods"),
- }
-
- EXTRA_FULL_FIELDS = [
- 'base_finds__cache_short_id', 'base_finds__cache_complete_id',
- 'base_finds__comment', 'base_finds__description',
- 'base_finds__topographic_localisation',
- 'base_finds__special_interest',
- 'base_finds__discovery_date']
- EXTRA_FULL_FIELDS_LABELS = {
- 'base_finds__cache_short_id': _(u"Base find - Short ID"),
- 'base_finds__cache_complete_id': _(u"Base find - Complete ID"),
- 'base_finds__comment': _(u"Base find - Comment"),
- 'base_finds__description': _(u"Base find - Description"),
- 'base_finds__topographic_localisation': _(u"Base find - "
- u"Topographic localisation"),
- 'base_finds__special_interest': _(u"Base find - Special interest"),
- 'base_finds__discovery_date': _(u"Base find - Discovery date"),
- }
- ATTRS_EQUIV = {'get_first_base_find': 'base_finds'}
-
- # search parameters
- REVERSED_BOOL_FIELDS = ['image__isnull']
- RELATION_TYPES_PREFIX = {
- 'ope_relation_types':
- 'base_finds__context_record__operation__'}
- RELATIVE_SESSION_NAMES = [
- ('contextrecord', 'base_finds__context_record__pk'),
- ('operation', 'base_finds__context_record__operation__pk'),
- ('file', 'base_finds__context_record__operation__associated_file__pk')
- ]
- BASE_REQUEST = {'downstream_treatment__isnull': True}
- EXTRA_REQUEST_KEYS = {
- 'base_finds__cache_short_id':
- 'base_finds__cache_short_id__icontains',
- 'base_finds__cache_complete_id':
- 'base_finds__cache_complete_id__icontains',
- 'label':
- 'label__icontains',
- 'base_finds__context_record':
- 'base_finds__context_record__pk',
- 'base_finds__context_record__parcel__town':
- 'base_finds__context_record__parcel__town',
- 'base_finds__context_record__operation__year':
- 'base_finds__context_record__operation__year__contains',
- 'base_finds__context_record__operation':
- 'base_finds__context_record__operation__pk',
- 'archaeological_sites':
- 'base_finds__context_record__operation__archaeological_sites__pk',
- 'base_finds__context_record__operation__code_patriarche':
- 'base_finds__context_record__operation__code_patriarche',
- 'datings__period': 'datings__period__pk',
- 'base_finds__find__description':
- 'base_finds__find__description__icontains',
- 'base_finds__batch': 'base_finds__batch',
- 'basket': 'basket',
- 'cached_label': 'cached_label__icontains',
- 'image': 'image__isnull'}
-
- # fields
- base_finds = models.ManyToManyField(BaseFind, verbose_name=_(u"Base find"),
- related_name='find')
- 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)
- material_types = models.ManyToManyField(
- MaterialType, verbose_name=_(u"Material types"), related_name='finds')
- conservatory_state = models.ForeignKey(
- ConservatoryState, verbose_name=_(u"Conservatory state"), blank=True,
- null=True)
- conservatory_comment = models.TextField(_(u"Conservatory comment"),
- blank=True, null=True)
- preservation_to_considers = models.ManyToManyField(
- PreservationType, verbose_name=_(u"Type of preservation to consider"),
- related_name='finds')
- volume = models.FloatField(_(u"Volume (l)"), blank=True, null=True)
- weight = models.FloatField(_(u"Weight (g)"), blank=True, null=True)
- weight_unit = models.CharField(_(u"Weight unit"), max_length=4,
- blank=True, null=True, choices=WEIGHT_UNIT)
- find_number = models.IntegerField(_("Find number"), blank=True, null=True)
- upstream_treatment = models.ForeignKey(
- "Treatment", blank=True, null=True,
- related_name='downstream',
- verbose_name=_("Upstream treatment"))
- downstream_treatment = models.ForeignKey(
- "Treatment", blank=True, null=True, related_name='upstream',
- verbose_name=_("Downstream treatment"))
- datings = models.ManyToManyField(Dating, verbose_name=_(u"Dating"),
- related_name='find')
- container = models.ForeignKey(
- Container, verbose_name=_(u"Container"), blank=True, null=True,
- related_name='finds')
- is_complete = models.NullBooleanField(_(u"Is complete?"), blank=True,
- null=True)
- object_types = models.ManyToManyField(
- ObjectType, verbose_name=_(u"Object types"), related_name='find')
- integrities = models.ManyToManyField(
- IntegrityType, verbose_name=_(u"Integrity / interest"),
- related_name='find')
- remarkabilities = models.ManyToManyField(
- RemarkabilityType, verbose_name=_(u"Remarkability"),
- related_name='find')
- min_number_of_individuals = models.IntegerField(
- _(u"Minimum number of individuals (MNI)"), blank=True, null=True)
- 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)
- diameter = models.FloatField(_(u"Diameter (cm)"), blank=True, null=True)
- thickness = models.FloatField(_(u"Thickness (cm)"), blank=True, null=True)
- topographic_reference_point = models.CharField(
- _(u"Point of topographic reference"), max_length=20,
- blank=True, null=True)
- dimensions_comment = models.TextField(_(u"Dimensions comment"),
- blank=True, null=True)
- mark = models.TextField(_(u"Mark"), blank=True, null=True)
- comment = models.TextField(_(u"Comment"), blank=True, null=True)
- dating_comment = models.TextField(_(u"Comment on dating"), blank=True,
- null=True)
- previous_id = models.TextField(_(u"Previous ID"), blank=True, null=True)
- index = models.IntegerField(u"Index", default=0)
- checked = models.CharField(_(u"Check"), max_length=2, default='NC',
- 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)
- cached_label = models.TextField(_(u"Cached name"), null=True, blank=True)
- history = HistoricalRecords()
- BASKET_MODEL = FindBasket
- IMAGE_PREFIX = 'finds/'
-
- class Meta:
- verbose_name = _(u"Find")
- verbose_name_plural = _(u"Finds")
- permissions = (
- ("view_find", ugettext(u"Can view all Finds")),
- ("view_own_find", ugettext(u"Can view own Find")),
- ("add_own_find", ugettext(u"Can add own Find")),
- ("change_own_find", ugettext(u"Can change own Find")),
- ("delete_own_find", ugettext(u"Can delete own Find")),
- )
- ordering = ('cached_label',)
-
- @property
- def short_class_name(self):
- return _(u"FIND")
-
- def __unicode__(self):
- lbl = settings.JOINT.join([
- getattr(self, attr)
- for attr in ('administrative_index', 'label')
- if getattr(self, attr)])
- return lbl
-
- @property
- def short_label(self):
- return self.reference
-
- @property
- def dating(self):
- return u" ; ".join([unicode(dating) for dating in self.datings.all()])
-
- @property
- def show_url(self):
- return reverse('show-find', args=[self.pk, ''])
-
- @property
- def name(self):
- return u" - ".join([base_find.name
- for base_find in self.base_finds.all()])
-
- @property
- def full_label(self):
- lbl = u" - ".join([
- getattr(self, attr)
- for attr in ('label', 'administrative_index')
- if getattr(self, attr)])
- base = u" - ".join([base_find.complete_id()
- for base_find in self.base_finds.all()])
- if base:
- lbl += u' ({})'.format(base)
- return lbl
-
- def get_first_base_find(self):
- q = self.base_finds
- if not q.count():
- return
- return q.order_by('-pk').all()[0]
-
- @property
- def reference(self):
- bf = self.get_first_base_find()
- if not bf:
- return "00"
- return bf.short_id()
-
- @property
- def administrative_index(self):
- bf = self.get_first_base_find()
- if not bf or not bf.context_record or not bf.context_record.operation:
- return ""
- return "{}-{}".format(
- bf.context_record.operation.get_reference(),
- self.index)
-
- def _get_treatments(self, model, rel='upstream'):
- treatments, findtreats = [], []
- for findtreat in model.objects.filter(
- find_id=self.pk).order_by(
- 'treatment_nb', 'treatment__start_date',
- 'treatment__end_date').distinct().all():
- if findtreat.pk in findtreats:
- continue
- findtreats.append(findtreat.pk)
- q = getattr(findtreat.treatment, rel).distinct().order_by(
- 'label')
- treatments.append((q.all(), findtreat.treatment))
- return treatments
-
- @property
- def weight_string(self):
- if not self.weight:
- return ""
- return "{} {}".format(self.weight, self.weight_unit or "")
-
- def upstream_treatments(self):
- return self._get_treatments(FindUpstreamTreatments, 'upstream')
-
- def downstream_treatments(self):
- return self._get_treatments(FindDownstreamTreatments, 'downstream')
-
- def all_treatments(self):
- return self.upstream_treatments() + self.downstream_treatments()
-
- def get_department(self):
- bf = self.get_first_base_find()
- if not bf:
- return "00"
- return bf.context_record.operation.get_department()
-
- def get_town_label(self):
- bf = self.get_first_base_find()
- if not bf:
- return "00"
- return bf.context_record.operation.get_town_label()
-
- @classmethod
- def get_periods(cls, slice='year', fltr={}):
- q = cls.objects
- if fltr:
- q = q.filter(**fltr)
- if slice == 'year':
- years = set()
- finds = q.filter(downstream_treatment__isnull=True)
- for find in finds:
- bi = find.base_finds.all()
- if not bi:
- continue
- bi = bi[0]
- if bi.context_record.operation.start_date:
- yr = bi.context_record.operation.start_date.year
- years.add(yr)
- return list(years)
-
- @classmethod
- def get_by_year(cls, year, fltr={}):
- q = cls.objects
- if fltr:
- q = q.filter(**fltr)
- return q.filter(
- downstream_treatment__isnull=True,
- base_finds__context_record__operation__start_date__year=year)
-
- @classmethod
- def get_operations(cls):
- operations = set()
- finds = cls.objects.filter(downstream_treatment__isnull=True)
- for find in finds:
- bi = find.base_finds.all()
- if not bi:
- continue
- bi = bi[0]
- pk = bi.context_record.operation.pk
- operations.add(pk)
- return list(operations)
-
- @classmethod
- def get_by_operation(cls, operation_id):
- return cls.objects.filter(
- downstream_treatment__isnull=True,
- base_finds__context_record__operation__pk=operation_id)
-
- @classmethod
- def get_total_number(cls, fltr={}):
- q = cls.objects
- if fltr:
- q = q.filter(**fltr)
- return q.filter(downstream_treatment__isnull=True).count()
-
- def duplicate(self, user):
- model = self.__class__
- # base fields
- table_cols = [field.name for field in model._meta.fields
- if field.name not in PRIVATE_FIELDS or
- field.name == 'order']
- dct = dict([(attr, getattr(self, attr)) for attr in
- table_cols])
- dct['order'] += 1
- dct['history_modifier'] = user
- new = self.__class__(**dct)
- new.save()
-
- # m2m fields
- m2m = [field.name for field in model._meta.many_to_many
- if field.name not in PRIVATE_FIELDS]
- for field in m2m:
- for val in getattr(self, field).all():
- getattr(new, field).add(val)
- return new
-
- @classmethod
- def get_query_owns(cls, user):
- return Q(base_finds__context_record__operation__scientist=user.
- ishtaruser.person) |\
- Q(base_finds__context_record__operation__in_charge=user.
- ishtaruser.person) |\
- Q(history_creator=user)
-
- @classmethod
- def get_owns(cls, user, menu_filtr=None, limit=None):
- replace_query = {}
- if menu_filtr:
- replace_query = {'base_finds__context_record': menu_filtr}
- owns = super(Find, cls).get_owns(
- user, replace_query=replace_query,
- limit=limit)
- return sorted(
- owns, key=lambda x: x.cached_label
- if hasattr(x, 'cached_label') else unicode(x))
-
- def _generate_cached_label(self):
- return unicode(self)
-
- def save(self, *args, **kwargs):
- super(Find, self).save(*args, **kwargs)
-
- updated = False
- self.skip_history_when_saving = True
- 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._cached_label_checked = False
- self.save()
- return
-
- q = self.base_finds
- if not self.index and q.count():
- operation = q.filter(
- context_record__operation__pk__isnull=False).order_by(
- '-context_record__operation__start_date')
- if operation.count():
- operation = operation.all()[0].context_record.operation
- q = Find.objects\
- .filter(base_finds__context_record__operation=operation)
- if self.pk:
- q = q.exclude(pk=self.pk)
- if q.count():
- self.index = q.aggregate(Max('index'))['index__max'] + 1
- else:
- self.index = 1
- self._cached_label_checked = False
- self.save()
- for base_find in self.base_finds.filter(
- context_record__operation__pk__isnull=False).all():
- modified = False
- if not base_find.index:
- modified = True
- base_find.index = BaseFind.get_max_index(
- base_find.context_record.operation) + 1
- short_id = base_find.short_id()
- if base_find.cache_short_id != short_id:
- base_find.cache_short_id = short_id
- modified = True
- complete_id = base_find.complete_id()
- if base_find.cache_complete_id != complete_id:
- base_find.cache_complete_id = complete_id
- modified = True
- if modified:
- base_find.skip_history_when_saving = True
- base_find._cached_label_checked = False
- base_find.save()
- # if not base_find.material_index:
- # idx = BaseFind.objects\
- # .filter(context_record=base_find.context_record,
- # find__material_types=self.material_type)\
- # .aggregate(Max('material_index'))
- # base_find.material_index = \
- # idx and idx['material_index__max'] + 1 or 1
-
-
-post_save.connect(cached_label_changed, sender=Find)
-
-
-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
-
- # search parameters
- BOOL_FIELDS = ['duplicate']
- RELATIVE_SESSION_NAMES = [
- ('find', 'find__pk'),
- ('contextrecord', 'find__base_finds__context_record__pk'),
- ('operation', 'find__base_finds__context_record__operation__pk'),
- ('file',
- 'find__base_finds__context_record__operation__associated_file__pk')
- ]
- EXTRA_REQUEST_KEYS = {
- 'title': 'title__icontains',
- 'description': 'description__icontains',
- 'comment': 'comment__icontains',
- 'additional_information': 'additional_information__icontains',
- 'person': 'authors__person__pk',
- 'find__base_finds__context_record__operation__year':
- 'find__base_finds__context_record__operation__year',
- 'find__base_finds__context_record__operation__operation_code':
- 'find__base_finds__context_record__operation__operation_code',
- 'find__base_finds__context_record__operation__code_patriarche':
- 'find__base_finds__context_record__operation__code_patriarche',
- 'find__datings__period': 'find__datings__period__pk',
- 'find__description': 'find__description__icontains',
- }
-
- class Meta:
- verbose_name = _(u"Find documentation")
- verbose_name_plural = _(u"Find documentations")
- find = models.ForeignKey(Find, verbose_name=_(u"Find"),
- related_name="source")
-
- @property
- def owner(self):
- return self.find
-
-
-class TreatmentType(GeneralType):
- virtual = models.BooleanField(_(u"Virtual"))
- upstream_is_many = models.BooleanField(
- _(u"Upstream is many"), default=False,
- help_text=_(
- u"Check this if for this treatment from many finds you'll get "
- u"one."))
- downstream_is_many = models.BooleanField(
- _(u"Downstream is many"), default=False,
- help_text=_(
- u"Check this if for this treatment from one find you'll get "
- u"many."))
-
- class Meta:
- verbose_name = _(u"Treatment type")
- verbose_name_plural = _(u"Treatment types")
- ordering = ('label',)
-post_save.connect(post_save_cache, sender=TreatmentType)
-post_delete.connect(post_save_cache, sender=TreatmentType)
-
-
-class Treatment(BaseHistorizedItem, ImageModel, OwnPerms):
- SHOW_URL = 'show-treatment'
- TABLE_COLS = ('year', 'index', 'treatment_types_lbl', 'label', 'person',
- 'start_date', 'downstream_cached_label',
- 'upstream_cached_label')
- REVERSED_BOOL_FIELDS = ['image__isnull']
- EXTRA_REQUEST_KEYS = {
- "label": 'label__icontains',
- "other_reference": 'other_reference__icontains',
- "treatment_types": "treatment_types__pk",
- "downstream_cached_label": "downstream__cached_label",
- "upstream_cached_label": "upstream__cached_label",
- 'image': 'image__isnull',
- }
- TABLE_COLS_LBL = {
- "downstream_cached_label": _(u"Downstream find"),
- "upstream_cached_label": _(u"Upstream find"),
- }
- IMAGE_PREFIX = 'treatment'
- label = models.CharField(_(u"Label"), blank=True, null=True,
- max_length=200)
- other_reference = models.CharField(_(u"Other ref."), blank=True, null=True,
- max_length=200)
- year = models.IntegerField(_(u"Year"), default=2016)
- index = models.IntegerField(_(u"Index"), default=1)
- treatment_types = models.ManyToManyField(
- TreatmentType, verbose_name=_(u"Treatment type"))
- location = models.ForeignKey(
- Warehouse, verbose_name=_(u"Location"), blank=True, null=True,
- help_text=_(
- u"Location where the treatment is done. Target warehouse for "
- u"a move."))
- person = models.ForeignKey(
- Person, verbose_name=_(u"Responsible"), blank=True, null=True,
- on_delete=models.SET_NULL, related_name='treatments')
- organization = models.ForeignKey(
- Organization, verbose_name=_(u"Organization"), blank=True, null=True,
- on_delete=models.SET_NULL, related_name='treatments')
- external_id = models.CharField(_(u"External ID"), blank=True, null=True,
- max_length=200)
- comment = models.TextField(_(u"Comment"), blank=True, null=True)
- description = models.TextField(_(u"Description"), blank=True, null=True)
- goal = models.TextField(_(u"Goal"), blank=True, null=True)
- start_date = models.DateField(_(u"Start date"), blank=True, null=True)
- end_date = models.DateField(_(u"End date"), blank=True, null=True)
- container = models.ForeignKey(Container, verbose_name=_(u"Container"),
- blank=True, null=True)
- target_is_basket = models.BooleanField(_(u"Target a basket"), default=False)
- history = HistoricalRecords()
-
- class Meta:
- verbose_name = _(u"Treatment")
- verbose_name_plural = _(u"Treatments")
- unique_together = ('year', 'index')
- permissions = (
- ("view_treatment", ugettext(u"Can view all Treatments")),
- ("view_own_treatment", ugettext(u"Can view own Treatment")),
- ("add_own_treatment", ugettext(u"Can add own Treatment")),
- ("change_own_treatment", ugettext(u"Can change own Treatment")),
- ("delete_own_treatment", ugettext(u"Can delete own Treatment")),
- )
-
- def __unicode__(self):
- lbl = unicode(self.treatment_types_lbl())
- if self.person:
- lbl += u" %s %s" % (_(u"by"), unicode(self.person))
- return lbl
-
- def treatment_types_lbl(self):
- """
- Treatment types label
- :return: string
- """
- return u" ; ".join([unicode(t) for t in self.treatment_types.all()])
-
- def pre_save(self):
- # is not new
- if self.pk is not None:
- return
- self.index = 1
- q = Treatment.objects.filter(year=self.year)
- if q.count():
- self.index = q.all().aggregate(Max('index'))['index__max'] + 1
-
- def save(self, *args, **kwargs):
- items, user, extra_args_for_new = [], None, []
- if "items" in kwargs:
- items = kwargs.pop('items')
- if "user" in kwargs:
- user = kwargs.pop('user')
- if "extra_args_for_new" in kwargs:
- extra_args_for_new = kwargs.pop('extra_args_for_new')
- self.pre_save()
- super(Treatment, self).save(*args, **kwargs)
- updated = []
- if hasattr(items, "items"):
- items = items.items.all()
- for item in items:
- new = item.duplicate(user)
- item.downstream_treatment = self
- item.save()
- new.upstream_treatment = self
- for k in extra_args_for_new:
- setattr(new, k, extra_args_for_new[k])
- new.save()
- updated.append(new.pk)
- # update baskets
- for basket in \
- FindBasket.objects.filter(items__pk=item.pk).all():
- basket.items.remove(item)
- basket.items.add(new)
- # manage containers
- for find in Find.objects.filter(upstream_treatment=self).all():
- if find.container != self.container:
- find.container = self.container
- if find.pk in updated:
- # don't record twice history
- find.skip_history_when_saving = True
- find.save()
-
- @property
- def associated_filename(self):
- return "-".join([
- str(slugify(getattr(self, attr)))
- for attr in ('year', 'index', 'label')])
-
-
-def pre_delete_treatment(sender, **kwargs):
- treatment = kwargs.get('instance')
- for find in Find.objects.filter(upstream_treatment=treatment).all():
- if find.downstream_treatment:
- # a new treatment have be done since the deleted treatment
- raise NotImplemented()
- find.delete()
- for find in Find.objects.filter(downstream_treatment=treatment).all():
- find.downstream_treatment = None
- find.save()
-
-post_delete.connect(pre_delete_treatment, sender=Treatment)
-
-
-class AbsFindTreatments(models.Model):
- find = models.ForeignKey(Find, verbose_name=_(u"Find"),
- related_name='%(class)s_related')
- 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__container',
- 'treatment__person', 'treatment_nb']
- EXTRA_FULL_FIELDS_LABELS = {
- 'treatment__treatment_type': _(u"Treatment type"),
- 'treatment__start_date': _(u"Start date"),
- 'treatment__end_date': _(u"End date"),
- 'treatment__location': _(u"Location"),
- 'treatment__container': _(u"Container"),
- 'treatment__person': _(u"Doer"),
- 'treatment__upstream': _(u"Related finds"),
- 'treatment__downstream': _(u"Related finds"),
- }
-
- class Meta:
- abstract = True
-
- def __unicode__(self):
- return u"{} - {} [{}]".format(
- self.find, self.treatment, self.treatment_nb)
-
-
-class FindUpstreamTreatments(AbsFindTreatments):
- """
- CREATE VIEW find_uptreatments_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_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;
-
- -- deactivate deletion
- CREATE RULE find_uptreatments_del AS ON DELETE TO find_uptreatments
- DO INSTEAD DELETE FROM archaeological_finds_find where id=NULL;
- """
- TABLE_COLS = ['treatment__treatment_type',
- 'treatment__upstream',
- 'treatment__start_date', 'treatment__end_date',
- 'treatment__location', 'treatment__container',
- 'treatment__person', 'treatment_nb']
-
- # search parameters
- EXTRA_REQUEST_KEYS = {'find_id': 'find_id'}
-
- class Meta:
- managed = False
- db_table = 'find_uptreatments'
- unique_together = ('find', 'treatment')
- ordering = ('find', '-treatment_nb')
-
-
-class FindDownstreamTreatments(AbsFindTreatments):
- """
- CREATE VIEW find_downtreatments_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_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;
-
- -- deactivate deletion
- CREATE RULE find_downtreatments_del AS ON DELETE TO find_downtreatments
- DO INSTEAD DELETE FROM archaeological_finds_find where id=NULL;
- """
- TABLE_COLS = ['treatment__treatment_type',
- 'treatment__downstream',
- 'treatment__start_date', 'treatment__end_date',
- 'treatment__location', 'treatment__container',
- 'treatment__person', 'treatment_nb']
-
- # search parameters
- EXTRA_REQUEST_KEYS = {'find_id': 'find_id'}
-
- class Meta:
- managed = False
- db_table = 'find_downtreatments'
- unique_together = ('find', 'treatment')
- ordering = ('find', '-treatment_nb')
-
-
-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;
-
- -- deactivate deletion
- CREATE RULE find_treatments_del AS ON DELETE TO find_treatments
- DO INSTEAD DELETE FROM archaeological_finds_find where id=NULL;
- """
- upstream = models.BooleanField(_(u"Is upstream"))
-
- class Meta:
- managed = False
- db_table = 'find_treatments'
- unique_together = ('find', 'treatment')
- ordering = ('find', 'upstream', '-treatment_nb')
-
-
-class TreatmentSource(Source):
- class Meta:
- verbose_name = _(u"Treatment documentation")
- verbose_name_plural = _(u"Treament documentations")
- treatment = models.ForeignKey(
- Treatment, verbose_name=_(u"Treatment"), related_name="source")
-
- @property
- def owner(self):
- return self.treatment
-
-
-class Property(LightHistorizedItem):
- find = models.ForeignKey(Find, verbose_name=_(u"Find"))
- administrative_act = models.ForeignKey(
- AdministrativeAct, verbose_name=_(u"Administrative act"))
- person = models.ForeignKey(Person, verbose_name=_(u"Person"),
- related_name='properties')
- start_date = models.DateField(_(u"Start date"))
- end_date = models.DateField(_(u"End date"))
-
- class Meta:
- verbose_name = _(u"Property")
- verbose_name_plural = _(u"Properties")
-
- def __unicode__(self):
- return self.person + settings.JOINT + self.find
+from archaeological_finds.models_finds import MaterialType, ConservatoryState,\
+ PreservationType, IntegrityType, RemarkabilityType, ObjectType, BaseFind, \
+ FindBasket, Find, FindSource, Property, IS_ISOLATED_CHOICES
+from archaeological_finds.models_treatments import TreatmentType, Treatment, \
+ AbsFindTreatments, FindUpstreamTreatments, FindDownstreamTreatments, \
+ FindTreatments, TreatmentSource, TreatmentFile, TreatmentFileType
+
+__all__ = ['MaterialType', 'ConservatoryState', 'PreservationType',
+ 'IntegrityType', 'RemarkabilityType', 'ObjectType',
+ 'BaseFind', 'FindBasket', 'Find', 'FindSource', 'Property',
+ 'IS_ISOLATED_CHOICES',
+ 'TreatmentType', 'Treatment', 'AbsFindTreatments',
+ 'FindUpstreamTreatments', 'FindDownstreamTreatments',
+ 'FindTreatments', 'TreatmentSource', 'TreatmentFile',
+ 'TreatmentFileType'] \ No newline at end of file