diff options
Diffstat (limited to 'archaeological_finds/models_finds.py')
-rw-r--r-- | archaeological_finds/models_finds.py | 262 |
1 files changed, 247 insertions, 15 deletions
diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py index 8f0270236..e99b43bc7 100644 --- a/archaeological_finds/models_finds.py +++ b/archaeological_finds/models_finds.py @@ -22,6 +22,7 @@ import datetime from django.conf import settings from django.contrib.gis.db import models from django.core.urlresolvers import reverse +from django.db import connection, transaction from django.db.models import Max, Q from django.db.models.signals import m2m_changed, post_save, post_delete from django.utils.translation import ugettext_lazy as _, ugettext @@ -126,6 +127,26 @@ post_save.connect(post_save_cache, sender=ObjectType) post_delete.connect(post_save_cache, sender=ObjectType) +class BFBulkView(object): + CREATE_SQL = """ + CREATE VIEW basefind_cached_bulk_update + AS ( + SELECT bf.id AS id, ope.code_patriarche AS main_ope_code, + ope.year AS year, + ope.operation_code AS ope_code, + cr.label AS cr_label, + bf.index AS index + FROM archaeological_finds_basefind bf + INNER JOIN archaeological_context_records_contextrecord cr + ON cr.id = bf.context_record_id + INNER JOIN archaeological_operations_operation ope + ON ope.id = cr.operation_id + );""" + DELETE_SQL = """ + DROP VIEW basefind_cached_bulk_update; + """ + + class BaseFind(BaseHistorizedItem, OwnPerms): label = models.TextField(_(u"Free ID")) external_id = models.TextField(_(u"External ID"), blank=True, null=True) @@ -199,34 +220,45 @@ class BaseFind(BaseHistorizedItem, OwnPerms): return q.aggregate(Max('index'))['index__max'] return 0 - def complete_id(self): - # OPE|MAT.CODE|UE|FIND_index + def _ope_code(self): if not self.context_record.operation: - return - # find = self.get_last_find() + return '' ope = self.context_record.operation - c_id = [unicode(ope.code_patriarche) if ope.code_patriarche else - (unicode(ope.year) + "-" + unicode(ope.operation_code))] + c_id = [] + if ope.code_patriarche: + c_id.append(settings.ISHTAR_OPE_PREFIX + + unicode(ope.code_patriarche)) + elif ope.year and ope.operation_code: + c_id.append( + settings.ISHTAR_DEF_OPE_PREFIX + + unicode(ope.year or '') + u"-" + + unicode(ope.operation_code or '')) + else: + c_id.append('') + return settings.JOINT.join(c_id) + + def complete_id(self): + # OPE|MAT.CODE|UE|FIND_index + c_id = [self._ope_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)) + + c_id.append((u'{:0' + str(settings.ISHTAR_FINDS_INDEX_ZERO_LEN) + '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)) + c_id = [self._ope_code()] + c_id.append((u'{:0' + str(settings.ISHTAR_FINDS_INDEX_ZERO_LEN) + 'd}' + ).format(self.index)) return settings.JOINT.join(c_id) def full_label(self): @@ -290,6 +322,104 @@ class BaseFind(BaseHistorizedItem, OwnPerms): self.save() return returned + @classmethod + def cached_label_bulk_update(cls, operation_id=None, parcel_id=None): + if operation_id: + filters = """ + INNER JOIN archaeological_context_records_contextrecord acr + ON acr.operation_id = %s AND acr.id = mybf.context_record_id + """ + args = [int(operation_id)] + kwargs = {'operation_id': operation_id} + elif parcel_id: + filters = """ + INNER JOIN archaeological_context_records_contextrecord acr + ON acr.parcel_id = %s AND acr.id = mybf.context_record_id + """ + args = [int(parcel_id)] + kwargs = {'parcel_id': parcel_id} + else: + return + + sql = """ + UPDATE "archaeological_finds_basefind" AS bf + SET cache_short_id = + CASE basefind_cached_bulk_update.main_ope_code + WHEN NULL THEN + CASE basefind_cached_bulk_update.year + IS NOT NULL + AND basefind_cached_bulk_update.ope_code + IS NOT NULL + WHEN TRUE THEN + '{ope_prefix}' || + basefind_cached_bulk_update.year || + '-' || + basefind_cached_bulk_update.ope_code + ELSE '' + END + ELSE + '{main_ope_prefix}' || + basefind_cached_bulk_update.main_ope_code + END + || '{join}' || + to_char(basefind_cached_bulk_update.index, 'fm{zeros}'), + + cache_complete_id = + CASE basefind_cached_bulk_update.main_ope_code + WHEN NULL THEN + CASE basefind_cached_bulk_update.year + IS NOT NULL + AND basefind_cached_bulk_update.ope_code + IS NOT NULL + WHEN TRUE THEN + '{ope_prefix}' || + basefind_cached_bulk_update.year || + '-' || + basefind_cached_bulk_update.ope_code + ELSE '' + END + ELSE + '{main_ope_prefix}' || + basefind_cached_bulk_update.main_ope_code + END + || '{join}' || + + COALESCE( + (SELECT string_agg(code, '-') FROM + (SELECT DISTINCT mt.code AS code FROM + archaeological_finds_find_material_types fmt + INNER JOIN archaeological_finds_find f + ON f.id=fmt.find_id AND f.downstream_treatment_id IS NULL + INNER JOIN find_first_base_find fbf + ON fbf.find_id = f.id AND + basefind_cached_bulk_update.id = fbf.basefind_id + INNER JOIN archaeological_finds_materialtype mt + ON mt.id = fmt.materialtype_id ORDER BY mt.code) + as ag), + '-') + + || '{join}' || + basefind_cached_bulk_update.cr_label + || '{join}' || + to_char(basefind_cached_bulk_update.index, 'fm{zeros}') + + FROM basefind_cached_bulk_update + WHERE bf.id = basefind_cached_bulk_update.id + AND bf.id IN ( + SELECT mybf.id FROM archaeological_finds_basefind mybf + {filters} + ); + """.format(main_ope_prefix=settings.ISHTAR_OPE_PREFIX, + ope_prefix=settings.ISHTAR_DEF_OPE_PREFIX, + join=settings.JOINT, filters=filters, + zeros=settings.ISHTAR_FINDS_INDEX_ZERO_LEN * "0") + # with connection.cursor() as c: # django 1.8 + c = connection.cursor() + c.execute(sql, args) + transaction.commit_unless_managed() + cls._meta.get_field_by_name( + 'find')[0].model.cached_label_bulk_update(**kwargs) + post_save.connect(post_save_point, sender=BaseFind) @@ -307,6 +437,42 @@ class FindBasket(Basket): related_name='basket') +class FirstBaseFindView(object): + CREATE_SQL = """ + CREATE VIEW find_first_base_find + AS ( + SELECT find_id, min(basefind_id) as basefind_id + FROM archaeological_finds_find_base_finds GROUP BY find_id + );""" + DELETE_SQL = """ + DROP VIEW find_first_base_find; + """ + + +class FBulkView(object): + CREATE_SQL = """ + CREATE VIEW find_cached_bulk_update + AS ( + SELECT f.id AS id, ope.code_patriarche AS main_ope_code, + ope.year AS year, + ope.operation_code AS ope_code, + f.label AS label, + f.index AS index + FROM archaeological_finds_find f + INNER JOIN find_first_base_find fbf + ON fbf.find_id = f.id + INNER JOIN archaeological_finds_basefind bf + ON fbf.basefind_id = bf.id + INNER JOIN archaeological_context_records_contextrecord cr + ON cr.id = bf.context_record_id + INNER JOIN archaeological_operations_operation ope + ON ope.id = cr.operation_id + );""" + DELETE_SQL = """ + DROP VIEW find_cached_bulk_update; + """ + + class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem): CHECK_DICT = dict(CHECK_CHOICES) SHOW_URL = 'show-find' @@ -707,6 +873,72 @@ class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem): def _generate_cached_label(self): return unicode(self) + @classmethod + def cached_label_bulk_update(cls, operation_id=None, parcel_id=None): + if operation_id: + filters = """ + INNER JOIN find_first_base_find myfbf + ON myfbf.find_id = myf.id + INNER JOIN archaeological_finds_basefind mybf + ON myfbf.basefind_id = mybf.id + INNER JOIN archaeological_context_records_contextrecord acr + ON acr.operation_id = %s AND acr.id = mybf.context_record_id + """ + args = [int(operation_id)] + elif parcel_id: + filters = """ + INNER JOIN find_first_base_find myfbf + ON myfbf.find_id = myf.id + INNER JOIN archaeological_finds_basefind mybf + ON myfbf.basefind_id = mybf.id + INNER JOIN archaeological_context_records_contextrecord acr + ON acr.parcel_id = %s AND acr.id = mybf.context_record_id + """ + args = [int(parcel_id)] + else: + return + + sql = """ + UPDATE "archaeological_finds_find" AS f + SET cached_label = + CASE find_cached_bulk_update.main_ope_code + WHEN NULL THEN + CASE find_cached_bulk_update.year + IS NOT NULL + AND find_cached_bulk_update.ope_code + IS NOT NULL + WHEN TRUE THEN + '{ope_prefix}' || + find_cached_bulk_update.year || + '-' || + find_cached_bulk_update.ope_code + ELSE '' + END + ELSE + '{main_ope_prefix}' || + find_cached_bulk_update.main_ope_code + END + || '-' || + to_char(find_cached_bulk_update.index, 'fm{zeros}') + || '{join}' || + find_cached_bulk_update.label + + + FROM find_cached_bulk_update + WHERE f.id = find_cached_bulk_update.id + AND f.id IN ( + SELECT myf.id FROM archaeological_finds_find myf + {filters} + ); + """.format(main_ope_prefix=settings.ISHTAR_OPE_PREFIX, + ope_prefix=settings.ISHTAR_DEF_OPE_PREFIX, + join=settings.JOINT, filters=filters, + zeros=settings.ISHTAR_FINDS_INDEX_ZERO_LEN * "0") + # with connection.cursor() as c: # django 1.8 + c = connection.cursor() + c.execute(sql, args) + transaction.commit_unless_managed() + def save(self, *args, **kwargs): super(Find, self).save(*args, **kwargs) |