diff options
Diffstat (limited to 'archaeological_operations/models.py')
| -rw-r--r-- | archaeological_operations/models.py | 300 | 
1 files changed, 300 insertions, 0 deletions
| diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py new file mode 100644 index 000000000..48baa57ba --- /dev/null +++ b/archaeological_operations/models.py @@ -0,0 +1,300 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2012 É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. + +from django.conf import settings +from django.contrib.gis.db import models +from django.db.models.signals import post_save +from django.utils.translation import ugettext_lazy as _, ugettext + +from ishtar_common.models import GeneralType, BaseHistorizedItem, \ +     HistoricalRecords, OwnPerms, Department, Source, Person, Organization, Town +FILES_AVAILABLE = 'archaeological_files' in settings.INSTALLED_APPS +if FILES_AVAILABLE: +    from archaeological_files.models import File + +class OperationType(GeneralType): +    class Meta: +        verbose_name = _(u"Operation type") +        verbose_name_plural = _(u"Operation types") + +    @classmethod +    def is_preventive(cls, ope_type_id, key=''): +        key = key or 'prev_excavation' +        try: +            preventive = OperationType.objects.get(txt_idx=key).pk +            return ope_type_id == preventive +        except ObjectDoesNotExist: +            return False + +class RemainType(GeneralType): +    class Meta: +        verbose_name = _(u"Remain type") +        verbose_name_plural = _(u"Remain types") + +class Period(GeneralType) : +    order = models.IntegerField(_(u"Order")) +    start_date = models.IntegerField(_(u"Start date")) +    end_date = models.IntegerField(_(u"End date")) +    parent = models.ForeignKey("Period", verbose_name=_(u"Parent period"), +                               blank=True, null=True) + +    class Meta: +        verbose_name = _(u"Type Period") +        verbose_name_plural = _(u"Types Period") + +    def __unicode__(self): +        return self.label + +class Operation(BaseHistorizedItem, OwnPerms): +    TABLE_COLS = ['year_index', 'operation_type', 'remains', 'towns', +                  'associated_file', 'start_date', 'excavation_end_date'] +    start_date = models.DateField(_(u"Start date"), null=True, blank=True) +    excavation_end_date = models.DateField(_(u"Excavation end date"), null=True, +                                           blank=True) +    end_date = models.DateField(_(u"Closing date"), null=True, blank=True) +    in_charge = models.ForeignKey(Person, related_name='+', null=True, +                                  blank=True, verbose_name=_(u"In charge")) +    year = models.IntegerField(_(u"Year")) +    operation_code = models.IntegerField(_(u"Operation code")) +    if FILES_AVAILABLE: +        associated_file = models.ForeignKey(File, related_name='operations', +                                 verbose_name=_(u"File"), blank=True, null=True) +    operation_type = models.ForeignKey(OperationType, related_name='+', +                                       verbose_name=_(u"Operation type")) +    surface = models.IntegerField(_(u"Surface (m²)"), blank=True, null=True) +    remains = models.ManyToManyField("RemainType", verbose_name=_(u'Remains')) +    towns = models.ManyToManyField(Town, verbose_name=_(u"Towns")) +    cost = models.IntegerField(_(u"Cost (€)"), blank=True, null=True) +    periods = models.ManyToManyField(Period, verbose_name=_(u"Periods")) +    scheduled_man_days = models.IntegerField(_(u"Scheduled man-days"), +                                             blank=True, null=True) +    optional_man_days = models.IntegerField(_(u"Optional man-days"), +                                             blank=True, null=True) +    effective_man_days = models.IntegerField(_(u"Effective man-days"), +                                             blank=True, null=True) +    if settings.COUNTRY == 'fr': +        code_patriarche = models.IntegerField(u"Code PATRIARCHE", null=True, +                                              blank=True) +        TABLE_COLS = ['code_patriarche'] + TABLE_COLS +        code_dracar = models.CharField(u"Code DRACAR", max_length=10, null=True, +                                       blank=True) +        fnap_financing = models.FloatField(u"Financement FNAP (%)", +                                             blank=True, null=True) +        fnap_cost = models.IntegerField(u"Financement FNAP (€)", +                                             blank=True, null=True) +        zoning_prescription = models.NullBooleanField( +                            _(u"Prescription on zoning"), blank=True, null=True) +        large_area_prescription = models.NullBooleanField( +                        _(u"Prescription on large area"), blank=True, null=True) +        geoarchaeological_context_prescription = models.NullBooleanField( +         _(u"Prescription on geoarchaeological context"), blank=True, null=True) +    operator_reference = models.CharField(_(u"Operator reference"), +                                    max_length=20, null=True, blank=True) +    common_name = models.CharField(_(u"Generic name"), max_length=120, null=True, +                                   blank=True) +    comment = models.TextField(_(u"Comment"), null=True, blank=True) +    history = HistoricalRecords() + +    class Meta: +        verbose_name = _(u"Operation") +        verbose_name_plural = _(u"Operations") +        permissions = ( +            ("view_own_operation", ugettext(u"Can view own Operation")), +            ("add_own_operation", ugettext(u"Can add own Operation")), +            ("change_own_operation", ugettext(u"Can change own Operation")), +            ("delete_own_operation", ugettext(u"Can delete own Operation")), +        ) + +    def __unicode__(self): +        items = [unicode(_('Intercommunal'))] +        if self.towns.count() == 1: +            items[0] = unicode(self.towns.all()[0]) +        items.append("-".join((unicode(self.year), +                               unicode(self.operation_code)))) +        return JOINT.join(items) + +    @classmethod +    def get_available_operation_code(cls, year=None): +        if not year: +            year = datetime.date.today().year +        max_val = cls.objects.filter(year=year).aggregate( +                            Max('operation_code'))["operation_code__max"] +        return (max_val + 1) if max_val else 1 + +    @classmethod +    def get_years(cls): +        return [res['year'] for res in list(cls.objects.values('year').annotate( +                                             Count("id")).order_by())] + +    @classmethod +    def get_by_year(cls, year): +        return cls.objects.filter(year=year) + +    @classmethod +    def get_total_number(cls): +        return cls.objects.count() + +    year_index_lbl = _(u"Operation code") +    @property +    def year_index(self): +        lbl = unicode(self.operation_code) +        lbl = u"%d-%s%s" % (self.year, (3-len(lbl))*"0", lbl) +        return lbl + +    def clean(self): +        objs = self.__class__.objects.filter(year=self.year, +                                             operation_code=self.operation_code) +        if self.pk: +            objs = objs.exclude(pk=self.pk) +        if objs.count(): +            raise ValidationError(_(u"This operation code already exists for " +                                    u"this year")) + +    def is_own(self, person): +        return False + +    @property +    def surface_ha(self): +        if self.surface: +            return self.surface/10000.0 + +    @property +    def cost_by_m2(self): +        if not self.surface or not self.cost: +            return +        return round(float(self.cost)/self.surface, 2) + +    @property +    def cost_by_m2(self): +        if not self.surface or not self.cost: +            return +        return round(float(self.cost)/self.surface, 2) + +    @classmethod +    def get_query_owns(cls, user): +        return Q(in_charge=user.person)|Q(history_modifier=user)\ +               & Q(end_date__isnull=True) + +    def is_active(self): +        return not bool(self.end_date) + +    def closing(self): +        if self.is_active(): +            return +        for item in self.history.all(): +            if not item.end_date: +                break +        return {'date':item.history_date, +                'user':IshtarUser.objects.get(pk=item.history_modifier_id)} + +def operation_post_save(sender, **kwargs): +    if not kwargs['instance']: +        return +    operation = kwargs['instance'] +    if operation.fnap_financing and operation.cost: +        fnap_cost = int(float(operation.cost)/100*operation.fnap_financing) +        if not operation.fnap_cost or operation.fnap_cost != fnap_cost: +            operation.fnap_cost = fnap_cost +            operation.save() +    elif operation.fnap_cost and operation.cost: +        fnap_percent = float(operation.fnap_cost)*100/operation.cost +        operation.fnap_financing = fnap_percent +        operation.save() +post_save.connect(operation_post_save, sender=Operation) + +class OperationByDepartment(models.Model): +    ''' +    Database view: don't forget to create it + +    create view operation_department (id, department_id, operation_id) as +        select town."id", town."departement_id", operation_towns."operation_id" +            from ishtar_base_town town +        inner join ishtar_base_operation_towns operation_towns on +            operation_towns."town_id"=town."id" order by town."departement_id"; +    CREATE RULE operation_department_delete +                            AS ON DELETE TO operation_department DO INSTEAD(); +    ''' +    operation = models.ForeignKey(Operation, verbose_name=_(u"Operation")) +    department = models.ForeignKey(Department, verbose_name=_(u"Department"), +                                   blank=True, null=True) +    class Meta: +        managed = False +        db_table = 'operation_department' + +class OperationSource(Source): +    class Meta: +        verbose_name = _(u"Operation documentation") +        verbose_name_plural = _(u"Operation documentations") +    operation = models.ForeignKey(Operation, verbose_name=_(u"Operation"), +                                  related_name="source") +    index = models.IntegerField(verbose_name=_(u"Index")) +    TABLE_COLS = ['operation.year', 'operation.operation_code'] + \ +                 Source.TABLE_COLS + +class ActType(GeneralType): +    TYPE = (('F', _(u'Archaelogical file')), +            ('O', _(u'Operation')), +            ) +    intented_to = models.CharField(_(u"Intended to"), max_length=1, +                                   choices=TYPE) +    class Meta: +        verbose_name = _(u"Act type") +        verbose_name_plural = _(u"Act types") + +class AdministrativeAct(BaseHistorizedItem, OwnPerms): +    TABLE_COLS = ['act_type', 'associated_file', 'operation', +                  'associated_file.towns', 'operation.towns'] +    TABLE_COLS_FILE = ['act_type', 'associated_file', 'associated_file.towns',] +    TABLE_COLS_OPE = ['act_type', 'operation', 'operation.towns'] +    act_type = models.ForeignKey(ActType, verbose_name=_(u"Act type")) +    in_charge = models.ForeignKey(Person, blank=True, null=True, +        related_name='+', verbose_name=_(u"Person in charge of the operation")) +    operator = models.ForeignKey(Organization, blank=True, null=True, +                    verbose_name=_(u"Archaeological preventive operator")) +    scientific = models.ForeignKey(Person, blank=True, null=True, +related_name='+', verbose_name=_(u"Person in charge of the scientific part")) +    signatory = models.ForeignKey(Person, blank=True, null=True, +                    related_name='+', verbose_name=_(u"Signatory")) +    operation = models.ForeignKey(Operation, blank=True, null=True, +                related_name='administrative_act', verbose_name=_(u"Operation")) +    if FILES_AVAILABLE: +        associated_file = models.ForeignKey(File, blank=True, null=True, +            related_name='administrative_act', +            verbose_name=_(u"Archaelogical file")) +    signature_date = models.DateField(_(u"Signature date"), blank=True, +                                      null=True) +    act_object = models.CharField(_(u"Object"), max_length=200) +    if settings.COUNTRY == 'fr': +        ref_sra = models.CharField(u"Référence SRA", max_length=15) +    history = HistoricalRecords() + +    class Meta: +        verbose_name = _(u"Administrative act") +        verbose_name_plural = _(u"Administrative acts") +        permissions = ( +("view_own_administrativeact", ugettext(u"Can view own Administrative act")), +("add_own_administrativeact", ugettext(u"Can add own Administrative act")), +("change_own_administrativeact", ugettext(u"Can change own Administrative act")), +("delete_own_administrativeact", ugettext(u"Can delete own Administrative act")), +        ) + +    def __unicode__(self): +        return JOINT.join([unicode(item) +          for item in [self.operation, self.associated_file, self.act_object] +          if item]) | 
