summaryrefslogtreecommitdiff
path: root/archaeological_finds/models_finds.py
diff options
context:
space:
mode:
Diffstat (limited to 'archaeological_finds/models_finds.py')
-rw-r--r--archaeological_finds/models_finds.py264
1 files changed, 247 insertions, 17 deletions
diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py
index 57f7a4f79..ae9903af5 100644
--- a/archaeological_finds/models_finds.py
+++ b/archaeological_finds/models_finds.py
@@ -29,6 +29,7 @@ from django.db.models import Max, Q, F
from django.db.models.signals import m2m_changed, post_save, post_delete, pre_delete
from django.core.exceptions import ObjectDoesNotExist
from django.urls import reverse, reverse_lazy
+from django.utils.formats import date_format
from ishtar_common.data_importer import post_importer_action, ImporterError
from ishtar_common.utils import (
@@ -65,6 +66,7 @@ from ishtar_common.models import (
Imported,
IshtarSiteProfile,
LightHistorizedItem,
+ QualifiedBiographicalNote,
main_item_pre_delete,
MainItem,
OrderedHierarchicalType,
@@ -124,9 +126,52 @@ post_save.connect(post_save_cache, sender=MaterialTypeQualityType)
post_delete.connect(post_save_cache, sender=MaterialTypeQualityType)
-class ConservatoryState(HierarchicalType):
- order = models.IntegerField(_("Order"), default=10)
+class IconographicPatternType(OrderedHierarchicalType):
+ class Meta:
+ verbose_name = _("Iconographic pattern type")
+ verbose_name_plural = _("Iconographic pattern types")
+ ordering = (
+ "order",
+ "label",
+ )
+ ADMIN_SECTION = _("Finds")
+
+
+post_save.connect(post_save_cache, sender=IconographicPatternType)
+post_delete.connect(post_save_cache, sender=IconographicPatternType)
+
+
+class WorkshopMovementStyleType(OrderedHierarchicalType):
+ class Meta:
+ verbose_name = _("Workshop, movement, style type")
+ verbose_name_plural = _("Workshop, movement, style types")
+ ordering = (
+ "order",
+ "label",
+ )
+ ADMIN_SECTION = _("Finds")
+
+
+post_save.connect(post_save_cache, sender=WorkshopMovementStyleType)
+post_delete.connect(post_save_cache, sender=WorkshopMovementStyleType)
+
+class ListedBuildingProtectionNature(OrderedHierarchicalType):
+ class Meta:
+ verbose_name = _("Listed building protection nature")
+ verbose_name_plural = _("Listed building protection nature")
+ ordering = (
+ "order",
+ "label",
+ )
+ ADMIN_SECTION = _("Finds")
+
+
+post_save.connect(post_save_cache, sender=ListedBuildingProtectionNature)
+post_delete.connect(post_save_cache, sender=ListedBuildingProtectionNature)
+
+
+class ConservatoryState(OrderedHierarchicalType):
class Meta:
verbose_name = _("Conservatory state type")
verbose_name_plural = _("Conservatory state types")
@@ -634,7 +679,8 @@ class BaseFind(
)
excavation_id = models.TextField(_("Excavation ID"), blank=True, default="")
description = models.TextField(_("Description"), blank=True, default="")
- comment = models.TextField(_("Comment on the circumstances of discovery"), blank=True, default="")
+ comment = models.TextField(_("Comment on the circumstances of discovery"), blank=True,
+ default="")
special_interest = models.CharField(
_("Special interest"), blank=True, default="", max_length=120
)
@@ -644,6 +690,8 @@ class BaseFind(
verbose_name=_("Context Record"),
on_delete=models.CASCADE,
)
+ context_record_comment = models.TextField(_("Details on context record"),
+ blank=True, default="")
discovery_date = models.DateField(
_("Discovery date (exact or beginning)"), blank=True, null=True
)
@@ -690,6 +738,7 @@ class BaseFind(
BASE_SEARCH_VECTORS = [
SearchVectorConfig("label", "raw"),
SearchVectorConfig("description", "local"),
+ SearchVectorConfig("context_record_comment", "local"),
SearchVectorConfig("comment", "local"),
SearchVectorConfig("cache_short_id", "raw"),
SearchVectorConfig("cache_complete_id", "raw"),
@@ -1296,6 +1345,7 @@ class Find(
"base_finds__context_record__parcel": _("Parcel"),
"base_finds__batch": _("Batch"),
"base_finds__comment": _("Base find - Comment"),
+ "base_finds__context_record_comment": _("Base find - Context record details"),
"base_finds__description": _("Base find - Description"),
"base_finds__topographic_localisation": _(
"Base find - " "Topographic localisation"
@@ -1319,6 +1369,7 @@ class Find(
"base_finds__cache_short_id",
"base_finds__cache_complete_id",
"base_finds__comment",
+ "base_finds__context_record_comment",
"base_finds__description",
"base_finds__topographic_localisation",
"base_finds__special_interest",
@@ -1348,6 +1399,8 @@ class Find(
("datings__period__label", _("Chronological period")),
("material_types__label", _("Material type")),
("object_types__label", _("Object type")),
+ ("iconographic_patterns__label", _("Iconographic patterns")),
+ ("workshop_movement_styles__label", _("Workshop, movement, style")),
("recommended_treatments__label", _("Recommended treatments")),
("conservatory_states__label", _("Conservatory states")),
("integrities__label", _("Integrity")),
@@ -1395,6 +1448,7 @@ class Find(
"museum_entry_date",
"museum_entry_date_end",
"museum_allocation_date",
+ "listed_building_date"
]
NUMBER_FIELDS = [
"base_finds__context_record__operation__year",
@@ -1440,6 +1494,8 @@ class Find(
"documents__image__isnull": "documents__image__isnull",
"container__location": "container__location__pk",
"container_ref__location": "container_ref__location__pk",
+ "base_finds__excavation_id": "base_finds__excavation_id",
+ "editors__person_id": "editors__person_id", # dynamic_table_documents
}
for table in (TABLE_COLS, TABLE_COLS_FOR_OPE):
for key in table:
@@ -1459,6 +1515,9 @@ class Find(
"label": SearchAltName(
pgettext_lazy("key for text search", "free-id"), "label__iexact"
),
+ "title": SearchAltName(
+ pgettext_lazy("key for text search", "title"), "title__iexact"
+ ),
"denomination": SearchAltName(
pgettext_lazy("key for text search", "denomination"), "denomination__iexact"
),
@@ -1517,6 +1576,10 @@ class Find(
pgettext_lazy("key for text search", "discovery-comment"),
"base_finds__comment__iexact",
),
+ "base_finds__context_record_comment": SearchAltName(
+ pgettext_lazy("key for text search", "context-record-comment"),
+ "base_finds__context_record_comment__iexact",
+ ),
"ope_relation_types": SearchAltName(
pgettext_lazy("key for text search", "operation-relation-type"),
"ope_relation_types",
@@ -1530,6 +1593,24 @@ class Find(
"material_types__label__iexact",
related_name="material_types",
),
+ "iconographic_patterns": SearchAltName(
+ pgettext_lazy("key for text search", "iconographic-patterns"),
+ "iconographic_patterns__label__iexact",
+ related_name="iconographic_patterns",
+ ),
+ "iconography_notes": SearchAltName(
+ pgettext_lazy("key for text search", "iconography-notes"),
+ "iconography_notes__iexact",
+ ),
+ "workshop_movement_styles": SearchAltName(
+ pgettext_lazy("key for text search", "workshop-movement-style"),
+ "workshop_movement_styles__label__iexact",
+ related_name="workshop_movement_styles",
+ ),
+ "actors": SearchAltName(
+ pgettext_lazy("key for text search", "actors"),
+ "actors__cached_label__iexact"
+ ),
"object_types": SearchAltName(
pgettext_lazy("key for text search", "object-type"),
"object_types__label__iexact",
@@ -1558,6 +1639,9 @@ class Find(
"description": SearchAltName(
pgettext_lazy("key for text search", "description"), "description__iexact"
),
+ "comparanda": SearchAltName(
+ pgettext_lazy("key for text search", "comparanda"), "comparanda__iexact"
+ ),
"base_finds__batch": SearchAltName(
pgettext_lazy("key for text search", "batch"),
"base_finds__batch__label__iexact",
@@ -1609,7 +1693,7 @@ class Find(
"previous_id": SearchAltName(
pgettext_lazy("key for text search", "previous-id"), "previous_id__iexact"
),
- #'collection':
+ # 'collection':
# SearchAltName(
# pgettext_lazy("key for text search", "collection"),
# 'collection__name__iexact'),
@@ -1623,8 +1707,17 @@ class Find(
"museum_id": SearchAltName(
pgettext_lazy("key for text search", "museum-id"), "museum_id__iexact"
),
+ "museum_id_prefix": SearchAltName(
+ pgettext_lazy("key for text search", "museum-id-prefix"),
+ "museum_id_prefix__iexact"
+ ),
+ "museum_id_suffix": SearchAltName(
+ pgettext_lazy("key for text search", "museum-id-suffix"),
+ "museum_id_suffix__iexact"
+ ),
"cache_complete_museum_id": SearchAltName(
- pgettext_lazy("key for text search", "complete-museum-id"), "cache_complete_museum_id__iexact"
+ pgettext_lazy("key for text search", "complete-museum-id"),
+ "cache_complete_museum_id__iexact"
),
"laboratory_id": SearchAltName(
pgettext_lazy("key for text search", "laboratory-id"),
@@ -1633,6 +1726,10 @@ class Find(
"mark": SearchAltName(
pgettext_lazy("key for text search", "mark"), "mark__iexact"
),
+ "mark_text": SearchAltName(
+ pgettext_lazy("key for text search", "marking-transcription"),
+ "mark_text__iexact"
+ ),
"base_finds__discovery_date": SearchAltName(
pgettext_lazy("key for text search", "discovery-date"),
"base_finds__discovery_date",
@@ -1688,6 +1785,10 @@ class Find(
pgettext_lazy("key for text search", "conservatory-comment"),
"conservatory_comment__iexact",
),
+ "conservatory_states_details": SearchAltName(
+ pgettext_lazy("key for text search", "conservatory-states-details"),
+ "conservatory_states_details__iexact",
+ ),
"length": SearchAltName(
pgettext_lazy("key for text search", "length"), "length"
),
@@ -1920,6 +2021,22 @@ class Find(
pgettext_lazy("key for text search", "museum-observed-quantity"),
"museum_observed_quantity"
),
+ "listed_building_id": SearchAltName(
+ pgettext_lazy("key for text search", "listed-building-id"),
+ "listed_building_id__iexact"
+ ),
+ "listed_building_protection_nature": SearchAltName(
+ pgettext_lazy("key for text search", "listed-building-protection-nature"),
+ "listed_building_protection_nature__label__iexact"
+ ),
+ "listed_building_date": SearchAltName(
+ pgettext_lazy("key for text search", "listed-building-date"),
+ "listed_building_date"
+ ),
+ "listed_building_notes": SearchAltName(
+ pgettext_lazy("key for text search", "listed-building-notes"),
+ "listed_building_notes__iexact"
+ ),
}
ALT_NAMES.update(BaseHistorizedItem.ALT_NAMES)
ALT_NAMES.update(DocumentItem.ALT_NAMES)
@@ -1962,6 +2079,7 @@ class Find(
SearchVectorConfig("museum_id", "raw"),
SearchVectorConfig("label", "raw"),
SearchVectorConfig("description", "local"),
+ SearchVectorConfig("comparanda", "local"),
SearchVectorConfig("museum_id_comment", "local"),
SearchVectorConfig("mark"),
SearchVectorConfig("comment", "local"),
@@ -1987,6 +2105,8 @@ class Find(
SearchVectorConfig("periods__label", "local"),
SearchVectorConfig("integrities__label", "raw"),
SearchVectorConfig("material_types__label", "local"),
+ SearchVectorConfig("iconographic_patterns__label", "local"),
+ SearchVectorConfig("workshop_movement_styles__label", "local"),
SearchVectorConfig("object_types__label", "raw"),
SearchVectorConfig("remarkabilities__label", "raw"),
SearchVectorConfig("technical_processes__label", "raw"),
@@ -2089,6 +2209,8 @@ class Find(
]
HISTORICAL_M2M = [
"material_types",
+ "iconographic_patterns",
+ "workshop_movement_styles",
"technical_processes",
"periods",
"datings",
@@ -2117,6 +2239,8 @@ class Find(
"cultural_attributions",
"functional_areas",
"material_types",
+ "iconographic_patterns",
+ "workshop_movement_styles",
"integrities",
"recommended_treatments",
"museum_former_collections",
@@ -2175,6 +2299,7 @@ class Find(
order = models.IntegerField(_("Order"), default=1)
label = models.TextField(_("Free ID"))
denomination = models.TextField(_("Denomination"), blank=True, default="")
+ title = models.TextField(_("Title"), blank=True, default="")
# museum module IDs
museum_id_prefix = models.TextField(_("Museum ID prefix"), blank=True, default="")
museum_id = models.TextField(_("Museum inventory number"), blank=True, default="")
@@ -2184,6 +2309,21 @@ class Find(
description = models.TextField(_("Description"), blank=True, default="")
decoration = models.TextField(_("Decoration"), blank=True, default="")
inscription = models.TextField(_("Inscription"), blank=True, default="")
+ comparanda = models.TextField(_("Comparanda"), blank=True, default="")
+ iconographic_patterns = models.ManyToManyField(
+ IconographicPatternType,
+ verbose_name=_("Iconographic patterns"),
+ related_name="finds",
+ blank=True,
+ )
+ iconography_notes = models.TextField(_("Notes on iconography"), blank=True,
+ default="")
+ workshop_movement_styles = models.ManyToManyField(
+ WorkshopMovementStyleType,
+ verbose_name=_("Workshop, movement, style"),
+ related_name="finds",
+ blank=True,
+ )
manufacturing_place = models.TextField(
_("Manufacturing place"), blank=True, default=""
)
@@ -2242,6 +2382,28 @@ class Find(
cultural_attributions = models.ManyToManyField(
CulturalAttributionType, verbose_name=_("Cultural attribution"), blank=True
)
+ actors = models.ManyToManyField(
+ QualifiedBiographicalNote, related_name="finds", verbose_name=_("Actors"),
+ blank=True
+ )
+ ## listed building
+ listed_building_id = models.TextField(
+ _("Listed building ID"), default="", blank=True,
+ )
+ listed_building_protection_nature = models.ForeignKey(
+ ListedBuildingProtectionNature,
+ verbose_name=_("Nature of listed buildings protection"),
+ blank=True,
+ null=True,
+ related_name="finds",
+ on_delete=models.SET_NULL,
+ )
+ listed_building_date = models.DateField(
+ _("Date of listing as a listed building"), blank=True, null=True)
+ listed_building_notes = models.TextField(
+ _("Notes on listed building"), default="", blank=True,
+ )
+ ## containers
container = models.ForeignKey(
"archaeological_warehouse.Container",
verbose_name=_("Container"),
@@ -2326,7 +2488,8 @@ class Find(
dimensions_comment = models.TextField(
_("Dimensions comment"), blank=True, default=""
)
- mark = models.TextField(_("Mark"), blank=True, default="")
+ mark_text = models.TextField(_("Transcription of the marking"), blank=True, default="")
+ mark = models.TextField(_("Marking details"), blank=True, default="")
comment = models.TextField(_("General comment"), blank=True, default="")
dating_comment = models.TextField(_("Comment on dating"), blank=True, default="")
previous_id = models.TextField(_("Previous ID"), blank=True, default="")
@@ -2423,6 +2586,9 @@ class Find(
verbose_name=_("Conservatory states"),
blank=True,
)
+ conservatory_states_details = models.TextField(
+ _("Conservatory state details"), blank=True, default=""
+ )
conservatory_comment = models.TextField(
_("Conservatory comment"), blank=True, default=""
)
@@ -2556,16 +2722,55 @@ class Find(
]
)
+ def _has_section(self, name, attrs):
+ """
+ For sheets: evaluate availability of a section.
+ Cache is set.
+ """
+ if getattr(self, "_cache_section", None) is None:
+ self._cache_section = {}
+ if name in self._cache_section:
+ return self._cache_section[name]
+ has_value = False
+ for attr in attrs:
+ if getattr(self, attr):
+ has_value = True
+ break
+ self._cache_section[name] = has_value
+ return self._cache_section[name]
+
+ @property
+ def has_listed_building_section(self):
+ attrs = ["listed_building_protection_nature_id", "listed_building_id",
+ "listed_building_notes", "listed_building_date"]
+ return self._has_section("has_listed_building_section", attrs)
+
+ @property
+ def has_preservation_fields(self):
+ attrs = [
+ "integrities_count", "remarkabilities_count", "conservatory_states_count",
+ "conservatory_comment", "alterations_count", "alteration_causes_count",
+ "recommended_treatments_count", "appraisal_date", "treatment_emergency",
+ "insurance_value", "estimated_value", "conservatory_states_details"
+ ]
+ return self._has_section("has_preservation_fields", attrs)
+
@property
def has_museum_section(self):
- if get_current_profile().museum and self.mark:
+ if getattr(self, "_has_museum_section", None) is not None:
+ return self._has_museum_section
+ if self.mark or self.mark_text:
+ self._has_museum_section = True
return True
for field in self._meta.get_fields():
- if not field.name.startswith("museum_"):
+ if not field.name.startswith("museum_") and \
+ not field.name.startswith("iconograph"):
continue
instanced_field = getattr(self, field.name)
if instanced_field and (not field.many_to_many or instanced_field.count()):
+ self._has_museum_section = True
return True
+ self._has_museum_section = False
return False
@property
@@ -2574,7 +2779,6 @@ class Find(
@property
def museum_entry_date_label(self):
- from django.utils.formats import date_format
if not self.museum_entry_date:
return
if self.museum_entry_date and self.museum_entry_date_end and (
@@ -2583,9 +2787,12 @@ class Find(
self.museum_entry_date.day == 1 and self.museum_entry_date_end.day == 31
):
return self.museum_entry_date.year
- dates = [date_format(self.museum_entry_date, format='SHORT_DATE_FORMAT', use_l10n=True)]
+ dates = [date_format(self.museum_entry_date, format='SHORT_DATE_FORMAT',
+ use_l10n=True)]
if self.museum_entry_date_end:
- dates.append(date_format(self.museum_entry_date_end, format='SHORT_DATE_FORMAT', use_l10n=True))
+ dates.append(
+ date_format(self.museum_entry_date_end, format='SHORT_DATE_FORMAT',
+ use_l10n=True))
return " / ".join(dates)
@classmethod
@@ -3034,29 +3241,52 @@ class Find(
return ""
return "{}-{}".format(bf.context_record.operation.get_reference(), self.index)
+ def _get_count(self, attr):
+ """
+ For sheets: evaluate count of m2m.
+ Cache is set.
+ """
+ if getattr(self, "_cache_count", None) is None:
+ self._cache_count = {}
+ if attr not in self._cache_count:
+ self._cache_count[attr] = getattr(self, attr).count()
+ return self._cache_count[attr]
+
@property
def integrities_count(self):
- return self.integrities.count()
+ return self._get_count("integrities")
@property
def conservatory_states_count(self):
- return self.conservatory_states.count()
+ return self._get_count("conservatory_states")
@property
def remarkabilities_count(self):
- return self.remarkabilities.count()
+ return self._get_count("remarkabilities")
@property
def cultural_attributions_count(self):
- return self.cultural_attributions.count()
+ return self._get_count("cultural_attributions")
@property
def documents_count(self):
- return self.documents.count()
+ return self._get_count("documents")
@property
def periods_count(self):
- return self.periods.count()
+ return self._get_count("periods")
+
+ @property
+ def alterations_count(self):
+ return self._get_count("alterations")
+
+ @property
+ def alteration_causes_count(self):
+ return self._get_count("alteration_causes")
+
+ @property
+ def recommended_treatments_count(self):
+ return self._get_count("recommended_treatments")
@property
def operation(self):