diff options
Diffstat (limited to 'archaeological_operations/models.py')
-rw-r--r-- | archaeological_operations/models.py | 144 |
1 files changed, 93 insertions, 51 deletions
diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py index c4fd0d96e..54ed96cec 100644 --- a/archaeological_operations/models.py +++ b/archaeological_operations/models.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Copyright (C) 2012-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> +# Copyright (C) 2012-2017 É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 @@ -24,6 +24,7 @@ from django.conf import settings from django.contrib.gis.db import models from django.core.cache import cache from django.core.urlresolvers import reverse +from django.db import IntegrityError, transaction from django.db.models import Q, Count, Sum, Max, Avg from django.db.models.signals import post_save, m2m_changed, post_delete from django.forms import ValidationError @@ -37,7 +38,7 @@ from ishtar_common.models import GeneralType, BaseHistorizedItem, \ SourceType, Person, Organization, Town, Dashboard, IshtarUser, ValueGetter,\ DocumentTemplate, ShortMenuItem, DashboardFormItem, GeneralRelationType,\ GeneralRecordRelations, post_delete_record_relation, OperationType, \ - get_external_id, ImageModel, post_save_cache + ImageModel, post_save_cache class RemainType(GeneralType): @@ -86,24 +87,24 @@ class ArchaeologicalSite(BaseHistorizedItem): name = models.CharField(_(u"Name"), max_length=200, null=True, blank=True) periods = models.ManyToManyField(Period, verbose_name=_(u"Periods"), - blank=True, null=True) + blank=True) remains = models.ManyToManyField("RemainType", verbose_name=_(u'Remains'), - blank=True, null=True) + blank=True) class Meta: verbose_name = _(u"Archaeological site") verbose_name_plural = _(u"Archaeological sites") permissions = ( ("view_archaeologicalsite", - ugettext(u"Can view all Archaeological sites")), + u"Can view all Archaeological sites"), ("view_own_archaeologicalsite", - ugettext(u"Can view own Archaeological site")), + u"Can view own Archaeological site"), ("add_own_archaeologicalsite", - ugettext(u"Can add own Archaeological site")), + u"Can add own Archaeological site"), ("change_own_archaeologicalsite", - ugettext(u"Can change own Archaeological site")), + u"Can change own Archaeological site"), ("delete_own_archaeologicalsite", - ugettext(u"Can delete own Archaeological site")), + u"Can delete own Archaeological site"), ) def __unicode__(self): @@ -179,7 +180,6 @@ class Operation(ClosedItem, BaseHistorizedItem, ImageModel, OwnPerms, SHOW_URL = 'show-operation' TABLE_COLS = ['year', 'towns', 'common_name', 'operation_type', 'start_date', 'excavation_end_date', 'remains'] - IMAGE_PREFIX = 'operations/' SLUG = 'operation' # search parameters @@ -270,7 +270,7 @@ class Operation(ClosedItem, BaseHistorizedItem, ImageModel, OwnPerms, on_delete=models.SET_NULL, related_name='operation_responsability') collaborators = models.ManyToManyField( - Person, blank=True, null=True, verbose_name=_(u"Collaborators"), + Person, blank=True, verbose_name=_(u"Collaborators"), related_name='operation_collaborator' ) year = models.IntegerField(_(u"Year"), null=True, blank=True) @@ -284,13 +284,13 @@ class Operation(ClosedItem, BaseHistorizedItem, ImageModel, OwnPerms, verbose_name=_(u"Operation type")) surface = models.IntegerField(_(u"Surface (m2)"), blank=True, null=True) remains = models.ManyToManyField("RemainType", verbose_name=_(u'Remains'), - null=True, blank=True) + blank=True) towns = models.ManyToManyField(Town, verbose_name=_(u"Towns"), related_name='operations') cost = models.IntegerField(_(u"Cost (euros)"), blank=True, null=True) # preventive periods = models.ManyToManyField(Period, verbose_name=_(u"Periods"), - null=True, blank=True) + blank=True) # preventive scheduled_man_days = models.IntegerField(_(u"Scheduled man-days"), blank=True, null=True) @@ -343,7 +343,7 @@ class Operation(ClosedItem, BaseHistorizedItem, ImageModel, OwnPerms, null=True, blank=True) archaeological_sites = models.ManyToManyField( ArchaeologicalSite, verbose_name=_(u"Archaeological sites"), - null=True, blank=True) + blank=True, related_name='operations') virtual_operation = models.BooleanField( _(u"Virtual operation"), default=False, help_text=_( @@ -372,12 +372,12 @@ class Operation(ClosedItem, BaseHistorizedItem, ImageModel, OwnPerms, verbose_name = _(u"Operation") verbose_name_plural = _(u"Operations") permissions = ( - ("view_operation", ugettext(u"Can view all Operations")), - ("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")), - ("close_operation", ugettext(u"Can close Operation")), + ("view_operation", u"Can view all Operations"), + ("view_own_operation", u"Can view own Operation"), + ("add_own_operation", u"Can add own Operation"), + ("change_own_operation", u"Can change own Operation"), + ("delete_own_operation", u"Can delete own Operation"), + ("close_operation", u"Can close Operation"), ) ordering = ('cached_label',) @@ -479,6 +479,10 @@ class Operation(ClosedItem, BaseHistorizedItem, ImageModel, OwnPerms, self.context_record.model.cached_label_bulk_update(operation_id=self.pk) return True + def _get_base_image_path(self): + return u"operation/{}/{}".format( + self.year, self.reference) + def get_town_label(self): lbl = unicode(_('Intercommunal')) if self.towns.count() == 1: @@ -573,12 +577,12 @@ class Operation(ClosedItem, BaseHistorizedItem, ImageModel, OwnPerms, return round(float(self.cost) / self.surface, 2) @classmethod - def get_query_owns(cls, user): + def get_query_owns(cls, ishtaruser): return ( - Q(in_charge=user.ishtaruser.person) | - Q(scientist=user.ishtaruser.person) | - Q(collaborators__pk=user.ishtaruser.person.pk) | - Q(history_creator=user)) & Q(end_date__isnull=True) + Q(in_charge=ishtaruser.person) | + Q(scientist=ishtaruser.person) | + Q(collaborators__pk=ishtaruser.person.pk) | + Q(history_creator=ishtaruser.user_ptr)) & Q(end_date__isnull=True) def is_active(self): return not bool(self.end_date) @@ -812,13 +816,19 @@ def operation_post_save(sender, **kwargs): # manage parcel association for parcel in operation.parcels.all(): parcel.copy_to_file() + + # external id update + for parcel in operation.parcels.all(): + parcel.update_external_id(save=True) + + for cr in operation.context_record.all(): + cr.update_external_id(save=True) + + post_save.connect(operation_post_save, sender=Operation) class RelationType(GeneralRelationType): - inverse_relation = models.ForeignKey( - 'RelationType', verbose_name=_(u"Inverse relation"), blank=True, - null=True) class Meta: verbose_name = _(u"Operation relation type") @@ -839,6 +849,7 @@ class RecordRelations(GeneralRecordRelations, models.Model): verbose_name_plural = _(u"Operation record relations") ordering = ('left_record', 'relation_type') + post_delete.connect(post_delete_record_relation, sender=RecordRelations) @@ -846,6 +857,22 @@ class OperationByDepartment(models.Model): """ Database view for dashboard """ + CREATE_SQL = """ + CREATE VIEW operation_department (id, department_id, operation_id) as + select town."id", town."departement_id", + operation_towns."operation_id" + from ishtar_common_town town + inner join archaeological_operations_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(); + """ + DELETE_SQL = """ + DROP VIEW operation_department; + """ + operation = models.ForeignKey(Operation, verbose_name=_(u"Operation")) department = models.ForeignKey(Department, verbose_name=_(u"Department"), blank=True, null=True) @@ -908,14 +935,16 @@ class OperationSource(Source): @property def code(self): + if not self.index: + return u"{}-".format(self.operation.code_patriarche or '') return u"{}-{:04d}".format(self.operation.code_patriarche or '', self.index) @classmethod - def get_query_owns(cls, user): - return (Q(operation__in_charge=user.ishtaruser.person) | - Q(operation__scientist=user.ishtaruser.person) | - Q(operation__collaborators__pk=user.ishtaruser.person.pk)) \ + def get_query_owns(cls, ishtaruser): + return (Q(operation__in_charge=ishtaruser.person) | + Q(operation__scientist=ishtaruser.person) | + Q(operation__collaborators__pk=ishtaruser.person.pk)) \ & Q(operation__end_date__isnull=True) @@ -929,7 +958,7 @@ class ActType(GeneralType): choices=TYPE) code = models.CharField(_(u"Code"), max_length=10, blank=True, null=True) associated_template = models.ManyToManyField( - DocumentTemplate, blank=True, null=True, + DocumentTemplate, blank=True, verbose_name=_(u"Associated template"), related_name='acttypes') indexed = models.BooleanField(_(u"Indexed"), default=False) @@ -1064,15 +1093,15 @@ class AdministrativeAct(BaseHistorizedItem, OwnPerms, ValueGetter): verbose_name_plural = _(u"Administrative acts") permissions = ( ("view_administrativeact", - ugettext(u"Can view all Administrative acts")), + u"Can view all Administrative acts"), ("view_own_administrativeact", - ugettext(u"Can view own Administrative act")), + u"Can view own Administrative act"), ("add_own_administrativeact", - ugettext(u"Can add own Administrative act")), + u"Can add own Administrative act"), ("change_own_administrativeact", - ugettext(u"Can change own Administrative act")), + u"Can change own Administrative act"), ("delete_own_administrativeact", - ugettext(u"Can delete own Administrative act")), + u"Can delete own Administrative act"), ) def __unicode__(self): @@ -1228,6 +1257,8 @@ def strip_zero(value): class Parcel(LightHistorizedItem): + EXTERNAL_ID_KEY = 'parcel_external_id' + associated_file = models.ForeignKey( 'archaeological_files.File', related_name='parcels', verbose_name=_(u"File"), @@ -1408,13 +1439,6 @@ def parcel_post_save(sender, **kwargs): parcel.delete() return - if not parcel.external_id or parcel.auto_external_id: - external_id = get_external_id('parcel_external_id', parcel) - if external_id != parcel.external_id: - updated = True - parcel._updated_id = True - parcel.auto_external_id = True - parcel.external_id = external_id if updated: parcel.save() return @@ -1429,12 +1453,22 @@ def parcel_post_save(sender, **kwargs): parcel_id=parcel.id) if parcel.operation and parcel.operation.pk and \ - parcel.town not in list(parcel.operation.towns.all()): - parcel.operation.towns.add(parcel.town) + parcel.town not in list(parcel.operation.towns.all()): + try: + # multiple save can cause multiple add + with transaction.atomic(): + parcel.operation.towns.add(parcel.town) + except IntegrityError: + pass if parcel.associated_file and \ - parcel.associated_file.pk and \ - parcel.town not in list(parcel.associated_file.towns.all()): - parcel.associated_file.towns.add(parcel.town) + parcel.associated_file.pk and \ + parcel.town not in list(parcel.associated_file.towns.all()): + try: + # multiple save can cause multiple add + with transaction.atomic(): + parcel.associated_file.towns.add(parcel.town) + except IntegrityError: + pass if parcel.operation and parcel.associated_file: # parcels are copied between files and operations parcel.copy_to_operation() @@ -1455,7 +1489,15 @@ class ParcelOwner(LightHistorizedItem): verbose_name_plural = _(u"Parcel owners") def __unicode__(self): - return self.owner + settings.JOINT + self.parcel + return "{}{}{}".format(self.owner, settings.JOINT, self.parcel) + + @property + def operation(self): + return self.parcel.operation + + @property + def associated_file(self): + return self.parcel.associated_file class OperationDashboard: |