summaryrefslogtreecommitdiff
path: root/archaeological_operations/models.py
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@peacefrogs.net>2012-10-19 22:10:20 +0200
committerÉtienne Loks <etienne.loks@peacefrogs.net>2012-10-19 22:10:20 +0200
commit666747d6371a908e6fe1968e2e802e3065d610c5 (patch)
tree3fa5ef50970a84f5499b6a2ad8629ab3623ef2b5 /archaeological_operations/models.py
parentf30dc48d37e90a3bab3d5264bd16c628eb9568ab (diff)
downloadIshtar-666747d6371a908e6fe1968e2e802e3065d610c5.tar.bz2
Ishtar-666747d6371a908e6fe1968e2e802e3065d610c5.zip
Djangoization - Major refactoring (step 2) models reorganization in django apps
Diffstat (limited to 'archaeological_operations/models.py')
-rw-r--r--archaeological_operations/models.py300
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])