#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2010-2025 Étienne Loks # 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 . # See the file COPYING for details. """ Finds forms definitions """ from collections import OrderedDict import logging from bootstrap_datepicker.widgets import DateField from django import forms from django.core import validators from django.core.exceptions import PermissionDenied from django.db.models import Q from django.forms.formsets import formset_factory from ishtar_common.utils import ugettext_lazy as _ from . import models from archaeological_operations.models import CulturalAttributionType, RemainType from archaeological_context_records.models import ( Dating, DatingType, DatingQuality, ContextRecord, RelationType as CRRelationType, Unit, ) from archaeological_finds.forms_treatments import ( TreatmentSelect, TreatmentFormSelection, BaseTreatmentForm, TreatmentModifyForm, AdministrativeActTreatmentForm, TreatmentFormFileChoice, TreatmentDeletionForm, TreatmentFileSelect, TreatmentFileFormSelection, TreatmentFileForm, TreatmentFileModifyForm, TreatmentFileDeletionForm, AdministrativeActTreatmentFormSelection, AdministrativeActTreatmentModifForm, AdministrativeActTreatmentFileForm, AdministrativeActTreatmentFileFormSelection, AdministrativeActTreatmentFileModifForm, N1TreatmentForm, QAFindTreatmentForm, OneNTreatmentForm, ) from archaeological_operations.models import ( Period, ArchaeologicalSite, RelationType as OpeRelationType, ) from archaeological_operations.widgets import OAWidget from archaeological_warehouse.models import Warehouse, Container from ishtar_common import widgets from ishtar_common.forms import ( CustomForm, CustomFormSearch, FormSet, FloatField, reverse_lazy, TableSelect, get_now, FinalForm, ManageOldType, FieldType, IshtarForm, FormHeader, QAForm, MultiSearchForm, LockForm, GeoItemSelect, ) from ishtar_common.forms_common import get_town_field from archaeological_context_records.forms import PeriodSelect from ishtar_common.models import ( Area, BiographicalNote, get_current_profile, IshtarUser, OperationType, Organization, Person, person_type_pks_lazy, valid_id, valid_ids, ) __all__ = [ "TreatmentSelect", "TreatmentFormSelection", "BaseTreatmentForm", "TreatmentModifyForm", "AdministrativeActTreatmentForm", "TreatmentFormFileChoice", "TreatmentDeletionForm", "AdministrativeActTreatmentModifForm", "TreatmentFileSelect", "TreatmentFileFormSelection", "TreatmentFileForm", "TreatmentFileModifyForm", "TreatmentFileDeletionForm", "AdministrativeActTreatmentFileForm", "AdministrativeActTreatmentFileFormSelection", "AdministrativeActTreatmentFormSelection", "AdministrativeActTreatmentFileModifForm", "RecordFormSelection", "FindForm", "SimpleFindForm", "DateForm", "DatingFormSet", "PreservationForm", "FindBasketFormSelection", "FindBasketForWriteFormSelection", "FindBasketForm", "FindSelect", "FindFormSelection", "FindFormSelectionWarehouseModule", "MultipleFindFormSelection", "MultipleFindFormSelectionWarehouseModule", "FindMultipleFormSelection", "check_form", "check_exist", "check_not_exist", "check_value", "check_type_field", "check_type_not_field", "check_treatment", "ResultFindForm", "ResultFindFormSet", "FindDeletionForm", "UpstreamFindFormSelection", "NewFindBasketForm", "SelectFindBasketForm", "SelectFindBasketWriteForm", "FindBasketAddItemForm", "QAFindFormSingle", "QAFindFormMulti", "QAFindBasketForm", "QAFindTreatmentForm", "QAFindbasketDuplicateForm", "N1TreatmentForm", "OneNTreatmentForm", "ResultingFindForm", "ResultingFindsForm", "SingleUpstreamFindFormSelection", ] logger = logging.getLogger(__name__) class RecordFormSelection(CustomForm, forms.Form): form_label = _("Context record") form_admin_name = _("Find - 010 - Context record choice") form_slug = "find-010-contextrecord" base_models = ["get_first_base_find"] associated_models = {"get_first_base_find__context_record": ContextRecord} get_first_base_find__context_record = forms.IntegerField( label=_("Context record"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-contextrecord"), associated_model=ContextRecord ), validators=[valid_id(ContextRecord)], ) def __init__(self, *args, **kwargs): super(RecordFormSelection, self).__init__(*args, **kwargs) # get the current operation and restrict search to it cr_pk = None if "data" in kwargs and kwargs["data"]: cr_pk = kwargs["data"].get("get_first_base_find__context_record") if not cr_pk and "initial" in kwargs and kwargs["initial"]: cr_pk = kwargs["initial"].get("get_first_base_find__context_record") if not cr_pk: return try: cr = ContextRecord.objects.get(pk=cr_pk) except ContextRecord.DoesNotExist: return widget = self.fields["get_first_base_find__context_record"].widget widget.source = str(widget.source) + "?operation__pk={}".format(cr.operation.pk) class MuseumForm: MARK_FIELD = "mark" def update_museum_fields(self): """ Overload fields labels for museum """ if not getattr(self, "site_profile"): self.site_profile = get_current_profile() # changes for museum profile if not self.site_profile.museum: return # reorder museum id (second position after museum_id_prefix) if "museum_id" in self.fields: fields = {} if "museum_id_prefix" in self.fields: fields["museum_id_prefix"] = self.fields.pop("museum_id_prefix") fields["museum_id"] = self.fields.pop("museum_id") fields.update(self.fields) self.fields = fields # update label of mark field if self.MARK_FIELD not in self.fields: return self.fields[self.MARK_FIELD].label = _("Marking details") class BasicFindForm(MuseumForm, CustomForm, ManageOldType): """ Basic find form with no field related to base_find """ file_upload = True form_label = _("Find") form_admin_name = _("Simple find - 020 - General") form_slug = "find-020-simplegeneral" base_models = [ "object_type", "material_type", "communicabilitie", "cultural_attribution", "functional_area", "technical_area", "technical_processe", "museum_former_collection", "museum_donor", "museum_inventory_marking_presence", "museum_marking_type", "museum_collection", ] associated_models = { "material_type": models.MaterialType, "cultural_attribution": CulturalAttributionType, "object_type": models.ObjectType, "functional_area": models.FunctionalArea, "technical_area": models.TechnicalAreaType, "technical_processe": models.TechnicalProcessType, "communicabilitie": models.CommunicabilityType, "material_type_quality": models.MaterialTypeQualityType, "object_type_quality": models.ObjectTypeQualityType, "checked_type": models.CheckedType, "museum_collection_entry_mode": models.CollectionEntryModeType, "museum_inventory_marking_presence": models.InventoryMarkingPresence, "museum_marking_type": models.MarkingType, "museum_collection": models.MuseumCollection, "museum_inventory_conformity": models.InventoryConformity, "museum_original_repro": models.OriginalReproduction, "museum_donor": BiographicalNote, "museum_former_collection": BiographicalNote, "get_first_base_find__discovery_method": models.DiscoveryMethod, "owner": models.OwnerType, "ownership_status": models.OwnershipStatus } field_order = [ "museum_id_prefix", "museum_id_suffix", "label", "denomination", "previous_id", "laboratory_id", "museum_id", "museum_id_comment", "seal_number", "museum_inventory_marking_presence", "museum_marking_type", "mark", "museum_owner_institution", "museum_assigned_institution", "museum_custodian_institution", "museum_depositor_inventory_number", "museum_collection_entry_mode", "museum_entry_mode_comment", "museum_entry_date", "museum_entry_date_end", "museum_entry_date_comment", "museum_donor", "museum_collection", "museum_former_collection", "museum_inventory_entry_year", "museum_inventory_conformity", "museum_conformity_comment", "museum_inventory_transcript", "museum_original_repro", "museum_allocation_date", "museum_purchase_price", "description", "public_description", "get_first_base_find__discovery_method", "is_complete", "material_type", "material_type_quality", "technical_processe", "material_comment", "object_type", "object_type_quality", "functional_area", "technical_area", "find_number", "min_number_of_individuals", "museum_inventory_quantity", "museum_observed_quantity", "quantity_comment", "decoration", "inscription", "manufacturing_place", "communicabilitie", "comment", "cultural_attribution", "dating_comment", "length", "width", "height", "thickness", "diameter", "circumference", "volume", "weight", "clutter_long_side", "clutter_short_side", "clutter_height", "dimensions_comment", "checked_type", "check_date", ] extra_form_modals = [ "biographicalnote", "person", "organization", ] PROFILE_FILTER = { "museum": [ "museum_id_prefix", "museum_id_suffix", "museum_id_comment", "museum_owner_institution", "museum_assigned_institution", "museum_custodian_institution", "museum_depositor_inventory_number", "museum_collection_entry_mode", "museum_entry_mode_comment", "museum_entry_date", "museum_entry_date_end", "museum_entry_date_comment", "museum_donor", "museum_inventory_marking_presence", "museum_marking_type", "museum_collection", "museum_former_collection", "museum_inventory_entry_year", "museum_inventory_conformity", "museum_conformity_comment", "museum_inventory_transcript", "museum_original_repro", "museum_allocation_date", "museum_purchase_price", "museum_inventory_quantity", "museum_observed_quantity", ], } HEADERS = {} HEADERS["museum_id_prefix"] = FormHeader(_("Museum identification")) museum_id_prefix = forms.CharField(label=_("Museum ID prefix"), required=False) museum_id = forms.CharField(label=_("Museum inventory number"), required=False) museum_id_suffix = forms.CharField(label=_("Museum ID suffix"), required=False) museum_id_comment = forms.CharField(label=_("Comment on museum ID"), widget=forms.Textarea, required=False) HEADERS["label"] = FormHeader(_("Identification")) label = forms.CharField( label=_("Free ID"), validators=[validators.MaxLengthValidator(60)] ) denomination = forms.CharField(label=_("Denomination"), required=False) previous_id = forms.CharField(label=_("Previous ID"), required=False) laboratory_id = forms.CharField(label=_("Laboratory ID"), required=False) seal_number = forms.CharField(label=_("Seal number"), required=False) museum_inventory_marking_presence = widgets.Select2MultipleField( label=_("Presence of inventory marking"), required=False ) museum_marking_type = widgets.Select2MultipleField( label=_("Type of marking"), required=False ) mark = forms.CharField(label=_("Mark"), required=False) HEADERS["ownership_status"] = FormHeader(_("Ownership")) ownership_status = forms.ChoiceField( label=_("Ownership status"), required=False, choices=[] ) owner = forms.ChoiceField( label=_("Owner"), required=False, choices=[] ) HEADERS["museum_owner_institution"] = FormHeader(_("Museum")) museum_owner_institution = widgets.ModelJQueryAutocompleteField( model=Organization, label=_("Owner institution"), new=True, required=False ) museum_assigned_institution = widgets.ModelJQueryAutocompleteField( model=Organization, label=_("Assigned institution"), new=True, required=False ) museum_custodian_institution = widgets.ModelJQueryAutocompleteField( model=Organization, label=_("Custodian institution"), new=True, required=False ) museum_depositor_inventory_number = forms.CharField(label=_("Depositor inventory number"), required=False) museum_collection_entry_mode = forms.ChoiceField( label=_("Collections entry mode"), required=False, choices=[] ) museum_entry_mode_comment = forms.CharField(label=_("Comment on museum entry mode"), widget=forms.Textarea, required=False) museum_entry_date = DateField(label=_("Museum entry date (exact or start)"), required=False) museum_entry_date_end = DateField(label=_("Museum entry date (end)"), required=False) museum_entry_date_comment = forms.CharField(label=_("Comment on museum entry date"), required=False) museum_donor = widgets.Select2MultipleField( model=BiographicalNote, label=_("Donors, testators or vendors"), required=False, remote=True, new=True) museum_collection = widgets.Select2MultipleField( model=models.MuseumCollection, label=_("Collections"), required=False) museum_former_collection = widgets.Select2MultipleField( model=BiographicalNote, label=_("Former collections"), required=False, remote=True, new=True) museum_inventory_entry_year = forms.IntegerField( label=_("Inventory entry year"), required=False, min_value=0, max_value=2100 ) museum_inventory_conformity = forms.ChoiceField( label=_("Conformity with inventory"), required=False, choices=[] ) museum_conformity_comment = forms.CharField( label=_("Comment on conformity"), widget=forms.Textarea, required=False ) museum_original_repro = forms.ChoiceField( label=_("Original/reproduction"), required=False, choices=[] ) museum_allocation_date = DateField(label=_("Date of museum allocation"), required=False) museum_purchase_price = forms.CharField(label=_("Purchase price"), required=False) HEADERS["museum_inventory_transcript"] = FormHeader(_("Description")) museum_inventory_transcript = forms.CharField( label=_("Inventory transcript"), widget=forms.Textarea, required=False ) description = forms.CharField( label=_("Description"), widget=forms.Textarea, required=False ) public_description = forms.CharField( label=_("Public description"), widget=forms.Textarea, required=False ) get_first_base_find__discovery_method = forms.ChoiceField( label=_("Discovery method"), required=False, choices=[] ) is_complete = forms.NullBooleanField(label=_("Is complete?"), required=False) material_type = widgets.Select2MultipleField( label=_("Material types"), required=False ) material_type_quality = forms.ChoiceField( label=_("Material type quality"), required=False, choices=[] ) technical_processe = widgets.Select2MultipleField( label=_("Technical processes"), required=False, ) material_comment = forms.CharField( label=_("Comment on the material"), required=False, widget=forms.Textarea ) object_type = widgets.Select2MultipleField( label=_("Object types"), required=False, ) object_type_quality = forms.ChoiceField( label=_("Object type quality"), required=False, choices=[] ) functional_area = widgets.Select2MultipleField( label=_("Functional areas"), required=False, ) technical_area = widgets.Select2MultipleField( label=_("Technical areas"), required=False, ) find_number = forms.IntegerField(label=_("Number of remains"), required=False) min_number_of_individuals = forms.IntegerField( label=_("Minimum number of individuals (MNI)"), required=False ) museum_inventory_quantity = forms.IntegerField(label=_("Inventory quantity"), required=False, max_value=32000) museum_observed_quantity = forms.IntegerField(label=_("Observed quantity"), required=False, max_value=32000) quantity_comment = forms.CharField( label=_("Comment on quantity"), required=False, widget=forms.Textarea ) decoration = forms.CharField( label=_("Decoration"), widget=forms.Textarea, required=False ) inscription = forms.CharField( label=_("Inscription"), widget=forms.Textarea, required=False ) manufacturing_place = forms.CharField( label=_("Manufacturing place"), required=False ) communicabilitie = widgets.Select2MultipleField( label=_("Communicability"), required=False ) comment = forms.CharField(label=_("General comment"), required=False, widget=forms.Textarea) cultural_attribution = widgets.Select2MultipleField( label=_("Cultural attribution"), required=False, ) dating_comment = forms.CharField( label=_("Comment on dating"), required=False, widget=forms.Textarea ) HEADERS["length"] = FormHeader(_("Dimensions")) length = FloatField( label=_("Length (cm)"), widget=widgets.CentimeterMeterWidget, required=False ) width = FloatField( label=_("Width (cm)"), required=False, widget=widgets.CentimeterMeterWidget ) height = FloatField( label=_("Height (cm)"), widget=widgets.CentimeterMeterWidget, required=False ) thickness = FloatField( label=_("Thickness (cm)"), widget=widgets.CentimeterMeterWidget, required=False ) diameter = FloatField( label=_("Diameter (cm)"), widget=widgets.CentimeterMeterWidget, required=False ) circumference = FloatField( label=_("Circumference (cm)"), widget=widgets.CentimeterMeterWidget, required=False, ) volume = FloatField(label=_("Volume (l)"), required=False) weight = FloatField( label=_("Weight (g)"), widget=widgets.GramKilogramWidget, required=False ) clutter_long_side = FloatField( label=_("Clutter long side (cm)"), widget=widgets.CentimeterMeterWidget, required=False, ) clutter_short_side = FloatField( label=_("Clutter short side (cm)"), widget=widgets.CentimeterMeterWidget, required=False, ) clutter_height = FloatField( label=_("Clutter height (cm)"), widget=widgets.CentimeterMeterWidget, required=False, ) dimensions_comment = forms.CharField( label=_("Dimensions comment"), required=False, widget=forms.Textarea ) HEADERS["checked_type"] = FormHeader(_("Sheet")) checked_type = forms.ChoiceField(label=_("Check"), required=False) check_date = DateField(initial=get_now, label=_("Check date")) TYPES = [ FieldType( "material_type", models.MaterialType, is_multiple=True, extra_args={"full_hierarchy": True}, ), FieldType("cultural_attribution", CulturalAttributionType, is_multiple=True), FieldType("material_type_quality", models.MaterialTypeQualityType), FieldType( "object_type", models.ObjectType, is_multiple=True, extra_args={"full_hierarchy": True}, ), FieldType("get_first_base_find__discovery_method", models.DiscoveryMethod), FieldType("object_type_quality", models.ObjectTypeQualityType), FieldType("functional_area", models.FunctionalArea, is_multiple=True), FieldType("technical_area", models.TechnicalAreaType, is_multiple=True), FieldType("technical_processe", models.TechnicalProcessType, is_multiple=True), FieldType("communicabilitie", models.CommunicabilityType, is_multiple=True), FieldType("checked_type", models.CheckedType, is_multiple=True), FieldType("museum_collection_entry_mode", models.CollectionEntryModeType), FieldType("museum_inventory_marking_presence", models.InventoryMarkingPresence, is_multiple=True), FieldType("museum_marking_type", models.MarkingType, is_multiple=True), FieldType("museum_collection", models.MuseumCollection), FieldType("museum_inventory_conformity", models.InventoryConformity), FieldType("museum_original_repro", models.OriginalReproduction), FieldType("owner", models.OwnerType), FieldType("ownership_status", models.OwnershipStatus), ] def __init__(self, *args, **kwargs): context_record = kwargs.pop("context_record") super().__init__(*args, **kwargs) if not context_record or not context_record.operation.operation_type.judiciary: self._remove_fields(("seal_number",)) self.update_museum_fields() def get_headers(self): if self._headers: return self._headers self._headers = self.HEADERS.copy() profile = get_current_profile() if not profile.museum: if "museum_inventory_transcript" in self._headers: self._headers.pop("museum_inventory_transcript") self._headers["description"] = FormHeader(_("Description")) return self._headers def clean(self): clutter_long_side = self.cleaned_data.get("clutter_long_side", None) clutter_short_side = self.cleaned_data.get("clutter_short_side", None) if ( clutter_long_side and clutter_short_side and clutter_short_side > clutter_long_side ): raise forms.ValidationError( str(_("Clutter: short side cannot be bigger than the long side.")) ) return self.cleaned_data class FindForm(BasicFindForm): file_upload = True form_label = _("Find") form_admin_name = _("Find - 020 - General") form_slug = "find-020-general" base_models = ["get_first_base_find"] + BasicFindForm.base_models associated_models = BasicFindForm.associated_models.copy() associated_models.update( { "get_first_base_find__batch": models.BatchType, } ) field_order = [ "museum_id_prefix", "museum_id_suffix", "museum_id_comment", "label", "denomination", "previous_id", "get_first_base_find__excavation_id", "laboratory_id", "museum_id", "seal_number", "museum_inventory_marking_presence", "museum_marking_type", "mark", "ownership_status", "owner", "museum_owner_institution", "museum_assigned_institution", "museum_custodian_institution", "museum_depositor_inventory_number", "museum_collection_entry_mode", "museum_entry_mode_comment", "museum_entry_date", "museum_entry_date_end", "museum_entry_date_comment", "museum_donor", "museum_collection", "museum_former_collection", "museum_inventory_entry_year", "museum_inventory_conformity", "museum_conformity_comment", "museum_original_repro", "museum_allocation_date", "museum_purchase_price", "museum_inventory_transcript", "description", "public_description", "get_first_base_find__discovery_method", "get_first_base_find__comment", "get_first_base_find__discovery_date", "get_first_base_find__discovery_date_taq", "get_first_base_find__batch", "is_complete", "material_type", "material_type_quality", "technical_processe", "material_comment", "object_type", "object_type_quality", "functional_area", "technical_area", "find_number", "min_number_of_individuals", "museum_inventory_quantity", "museum_observed_quantity", "quantity_comment", "inscription", "decoration", "manufacturing_place", "communicabilitie", "comment", "cultural_attribution", "dating_comment", "length", "width", "height", "thickness", "diameter", "circumference", "volume", "weight", "clutter_long_side", "clutter_short_side", "clutter_height", "dimensions_comment", "checked_type", "check_date", ] HEADERS = BasicFindForm.HEADERS.copy() get_first_base_find__comment = forms.CharField(label=_("Comment on the circumstances of discovery"), widget=forms.Textarea, required=False) get_first_base_find__excavation_id = forms.CharField( label=_("Excavation ID"), required=False ) get_first_base_find__discovery_method = forms.ChoiceField( label=_("Discovery method"), required=False, choices=[] ) get_first_base_find__discovery_date = DateField( label=_("Discovery date (exact or beginning)"), required=False ) get_first_base_find__discovery_date_taq = DateField( label=_("Discovery date (end)"), required=False ) get_first_base_find__batch = forms.ChoiceField( label=_("Batch/object"), choices=[], required=False ) HEADERS["get_first_base_find__topographic_localisation"] = FormHeader(_("Topography")) get_first_base_find__topographic_localisation = forms.CharField( label=_("Point of topographic reference"), required=False, max_length=120 ) TYPES = BasicFindForm.TYPES + [ FieldType("get_first_base_find__batch", models.BatchType), ] class SimpleFindForm(BasicFindForm): def __init__(self, *args, **kwargs): self.base_finds = kwargs.pop("base_finds") super(SimpleFindForm, self).__init__(*args, **kwargs) class ResultingFindForm(CustomForm, ManageOldType): file_upload = True form_label = _("Resulting find") form_admin_name = _("Treatment n-1 - 030 - Resulting find") form_slug = "treatment-030-n1-resulting-find" associated_models = { "resulting_material_type": models.MaterialType, "resulting_object_type": models.ObjectType, "resulting_communicabilitie": models.CommunicabilityType, "resulting_material_type_quality": models.MaterialTypeQualityType, "resulting_object_type_quality": models.ObjectTypeQualityType, "resulting_checked_type": models.CheckedType, } HEADERS = {} HEADERS["resulting_label"] = FormHeader(_("Identification")) resulting_label = forms.CharField( label=_("Free ID"), validators=[validators.MaxLengthValidator(60)] ) resulting_denomination = forms.CharField(label=_("Denomination"), required=False) HEADERS["resulting_description"] = FormHeader(_("Description")) resulting_description = forms.CharField( label=_("Description"), widget=forms.Textarea, required=False ) resulting_is_complete = forms.NullBooleanField( label=_("Is complete?"), required=False ) resulting_material_type = widgets.Select2MultipleField( label=_("Material types"), required=False ) resulting_material_type_quality = forms.ChoiceField( label=_("Material type quality"), required=False, choices=[] ) resulting_object_type = widgets.Select2MultipleField( label=_("Object types"), required=False, ) resulting_object_type_quality = forms.ChoiceField( label=_("Object type quality"), required=False, choices=[] ) resulting_find_number = forms.IntegerField(label=_("Number of remains"), required=False) resulting_min_number_of_individuals = forms.IntegerField( label=_("Minimum number of individuals (MNI)"), required=False ) resulting_museum_inventory_quantity = forms.IntegerField(label=_("Inventory quantity"), required=False, max_value=32000) resulting_museum_observed_quantity = forms.IntegerField(label=_("Observed quantity"), required=False, max_value=32000) resulting_quantity_comment = forms.CharField( label=_("Comment on quantity"), required=False, widget=forms.Textarea ) resulting_decoration = forms.CharField( label=_("Decoration"), widget=forms.Textarea, required=False ) resulting_inscription = forms.CharField( label=_("Inscription"), widget=forms.Textarea, required=False ) resulting_manufacturing_place = forms.CharField( label=_("Manufacturing place"), required=False ) resulting_communicabilitie = widgets.Select2MultipleField( label=_("Communicability"), required=False ) resulting_comment = forms.CharField( label=_("Comment"), required=False, widget=forms.Textarea ) resulting_dating_comment = forms.CharField( label=_("Comment on dating"), required=False, widget=forms.Textarea ) HEADERS["resulting_length"] = FormHeader(_("Dimensions")) resulting_length = FloatField(label=_("Length (cm)"), required=False) resulting_width = FloatField(label=_("Width (cm)"), required=False) resulting_height = FloatField(label=_("Height (cm)"), required=False) resulting_diameter = FloatField(label=_("Diameter (cm)"), required=False) resulting_circumference = FloatField(label=_("Circumference (cm)"), required=False) resulting_thickness = FloatField(label=_("Thickness (cm)"), required=False) resulting_volume = FloatField(label=_("Volume (l)"), required=False) resulting_weight = FloatField(label=_("Weight (g)"), required=False) resulting_clutter_long_side = FloatField( label=_("Clutter long side (cm)"), required=False ) resulting_clutter_short_side = FloatField( label=_("Clutter short side (cm)"), required=False ) resulting_clutter_height = FloatField( label=_("Clutter height (cm)"), required=False ) resulting_dimensions_comment = forms.CharField( label=_("Dimensions comment"), required=False, widget=forms.Textarea ) HEADERS["resulting_checked_type"] = FormHeader(_("Sheet")) resulting_checked_type = forms.ChoiceField(label=_("Check"), required=False) resulting_check_date = DateField(initial=get_now, label=_("Check date")) TYPES = [ FieldType("resulting_material_type", models.MaterialType, is_multiple=True), FieldType("resulting_material_type_quality", models.MaterialTypeQualityType), FieldType("resulting_object_type", models.ObjectType, is_multiple=True), FieldType("resulting_object_type_quality", models.ObjectTypeQualityType), FieldType( "resulting_communicabilitie", models.CommunicabilityType, is_multiple=True ), FieldType("resulting_checked_type", models.CheckedType, is_multiple=True), ] class ResultingFindsForm(CustomForm, ManageOldType): form_label = _("Resulting finds") form_admin_name = _("Treatment 1-n - 030 - Resulting finds") form_slug = "treatment-030-1n-resulting-finds" associated_models = {} resultings_number = forms.IntegerField( label=_("Number of resulting finds"), min_value=1 ) resultings_label = forms.CharField( label=_("Prefix label for resulting finds"), validators=[validators.MaxLengthValidator(200)], help_text=_( 'E.g.: with a prefix "item-", each resulting item will be named ' '"item-1", "item-2", "item-3"' ), ) resultings_start_number = forms.IntegerField( label=_("Numbering starting from"), initial=1, min_value=0 ) resultings_basket_name = forms.CharField( label=_("Name of the new basket containing the resulting items"), max_length=200 ) def __init__(self, *args, **kwargs): self.user = None if "user" in kwargs: self.user = kwargs.pop("user") if hasattr(self.user, "ishtaruser"): self.user = self.user.ishtaruser super(ResultingFindsForm, self).__init__(*args, **kwargs) if not self.user: return def clean(self): q = models.FindBasket.objects.filter( user=self.user, label=self.cleaned_data["resultings_basket_name"] ) if q.count(): raise forms.ValidationError( _("A basket with this label already exists.") ) return self.cleaned_data class QAFindFormMulti(MuseumForm, QAForm): form_admin_name = _("Find - Quick action - Modify") form_slug = "find-quickaction-modify" base_models = [ "get_first_base_find", "qa_object_types", "qa_functional_areas", "qa_material_types", "qa_communicabilities", "qa_integrities", "qa_cultural_attributions", "qa_alterations", "qa_alteration_causes", "qa_recommended_treatments", "qa_museum_collection_entry_mode", "qa_museum_inventory_marking_presence", "qa_museum_marking_type", "qa_museum_collections", "qa_museum_original_repro", "qa_owner", "qa_ownership_status", ] associated_models = { "qa_material_types": models.MaterialType, "qa_technical_processes": models.TechnicalProcessType, "qa_object_types": models.ObjectType, "qa_functional_areas": models.FunctionalArea, "qa_technical_areas": models.TechnicalAreaType, "qa_communicabilities": models.CommunicabilityType, "qa_integrities": models.IntegrityType, "qa_cultural_attributions": CulturalAttributionType, "qa_alterations": models.AlterationType, "qa_alteration_causes": models.AlterationCauseType, "qa_checked_type": models.CheckedType, "qa_period": Period, "qa_conservatory_states": models.ConservatoryState, "qa_treatment_emergency": models.TreatmentEmergencyType, "qa_recommended_treatments": models.RecommendedTreatmentType, "qa_museum_collection_entry_mode": models.CollectionEntryModeType, "qa_museum_owner_institution": Organization, "qa_museum_assigned_institution": Organization, "qa_museum_custodian_institution": Organization, "qa_museum_donors": BiographicalNote, "qa_museum_marking_type": models.MarkingType, "qa_museum_inventory_marking_presence": models.InventoryMarkingPresence, "qa_museum_collections": models.MuseumCollection, "qa_museum_original_repro": models.OriginalReproduction, "qa_museum_former_collections": BiographicalNote, "qa_owner": models.OwnerType, "qa_ownership_status": models.OwnershipStatus, } MULTI = True REPLACE_FIELDS = [ "qa_denomination", "qa_previous_id", "qa_ue", "qa_manufacturing_place", "qa_checked_type", "qa_check_date", "qa_treatment_emergency", "qa_appraisal_date", "qa_insurance_value", "qa_find_number", "qa_min_number_of_individuals", "qa_museum_inventory_quantity", "qa_museum_observed_quantity", "qa_museum_collection_entry_mode", "qa_museum_owner_institution", "qa_museum_assigned_institution", "qa_museum_custodian_institution", "qa_museum_entry_date", "qa_museum_entry_date_end", "qa_museum_inventory_entry_year", "qa_museum_original_repro", "qa_owner", "qa_ownership_status", ] PROFILE_FILTER = { "museum": [ "qa_museum_collection_entry_mode", "qa_museum_inventory_quantity", "qa_museum_observed_quantity", "qa_museum_owner_institution", "qa_museum_assigned_institution", "qa_museum_custodian_institution", "qa_museum_entry_mode_comment", "qa_museum_entry_date", "qa_museum_entry_date_end", "qa_museum_donors", "qa_museum_inventory_marking_presence", "qa_museum_marking_type", "qa_museum_collections", "qa_museum_former_collections", "qa_museum_inventory_entry_year", "qa_museum_original_repro", ], } HEADERS = { "qa_ue": FormHeader(_("Context record")), "qa_label": FormHeader(_("Identification"), slug='identification'), "qa_denomination": FormHeader(_("Identification"), slug='identification'), "qa_ownership_status": FormHeader(_("Ownership")), "qa_description": FormHeader(_("Description")), "qa_checked_type": FormHeader(_("Sheet")), "qa_period": FormHeader(_("Datation")), "qa_conservatory_comment": FormHeader(_("Preservation")), "qa_museum_owner_institution": FormHeader(_("Museum")), } SINGLE_FIELDS = [ "qa_get_first_base_find__excavation_id", "qa_museum_id_prefix", "qa_museum_id", "qa_museum_id_suffix", "qa_laboratory_id", "qa_seal_number", ] qa_ue = forms.IntegerField( label=_("Context record"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-contextrecord"), associated_model=ContextRecord ), validators=[valid_id(ContextRecord)], required=False, ) qa_label = forms.CharField( label=_("Free ID"), validators=[validators.MaxLengthValidator(60)], required=False, ) qa_denomination = forms.CharField(label=_("Denomination"), required=False) qa_previous_id = forms.CharField(label=_("Previous ID"), required=False) qa_get_first_base_find__excavation_id = forms.CharField( label=_("Excavation ID"), required=False ) qa_museum_id_prefix = forms.CharField(label=_("Museum ID prefix"), required=False) qa_museum_id = forms.CharField(label=_("Museum inventory number"), required=False) qa_museum_id_suffix = forms.CharField(label=_("Museum ID suffix"), required=False) qa_laboratory_id = forms.CharField(label=_("Laboratory ID"), required=False) qa_seal_number = forms.CharField(label=_("Seal number"), required=False) qa_mark = forms.CharField(label=_("Mark"), required=False) ## Ownership qa_ownership_status = forms.ChoiceField(label=_("Ownership status"), required=False, choices=[]) qa_owner = forms.ChoiceField(label=_("Owner"), required=False, choices=[]) ## Museum qa_museum_owner_institution = forms.IntegerField( label=_("Owner institution"), widget=widgets.JQueryAutoComplete( reverse_lazy('autocomplete-organization'), associated_model=Organization, new=True), validators=[valid_id(Organization)], required=False) qa_museum_assigned_institution = forms.IntegerField( label=_("Assigned institution"), widget=widgets.JQueryAutoComplete( reverse_lazy('autocomplete-organization'), associated_model=Organization, new=True), validators=[valid_id(Organization)], required=False) qa_museum_custodian_institution = forms.IntegerField( label=_("Custodian institution"), widget=widgets.JQueryAutoComplete( reverse_lazy('autocomplete-organization'), associated_model=Organization, new=True), validators=[valid_id(Organization)], required=False) qa_museum_collection_entry_mode = forms.ChoiceField(label=_("Collections entry mode"), required=False, choices=[]) qa_museum_entry_mode_comment = forms.CharField( label=_("Comment on museum entry mode"), required=False, widget=forms.Textarea ) qa_museum_entry_date = DateField( label=_("Museum entry date (exact or start)"), required=False ) qa_museum_entry_date_end = DateField(label=_("Museum entry date (end)"), required=False) qa_museum_donors = forms.IntegerField( label=_("Donors, testators or vendors"), widget=widgets.JQueryAutoComplete( reverse_lazy('autocomplete-biographicalnote'), associated_model=BiographicalNote), validators=[valid_id(BiographicalNote)], required=False ) qa_museum_inventory_marking_presence = widgets.Select2MultipleField( label=_("Presence of inventory marking"), required=False, choices=[] ) qa_museum_marking_type = widgets.Select2MultipleField( label=_("Type of marking"), required=False, choices=[] ) qa_museum_collections = forms.ChoiceField(label=_("Collections"), required=False, choices=[]) qa_museum_former_collections = forms.IntegerField( label=_("Former collections"), required=False, widget=widgets.JQueryAutoComplete( reverse_lazy('autocomplete-biographicalnote') ), ) qa_museum_inventory_entry_year = forms.IntegerField(label=_("Inventory entry year"), required=False, max_value=32000) qa_museum_original_repro = forms.ChoiceField(label=_("Original/reproduction"), required=False, choices=[]) qa_description = forms.CharField( label=_("Description"), widget=forms.Textarea, required=False ) qa_find_number = forms.IntegerField(label=_("Number of remains"), required=False) qa_min_number_of_individuals = forms.IntegerField( label=_("Minimum number of individuals (MNI)"), required=False ) qa_museum_inventory_quantity = forms.IntegerField(label=_("Inventory quantity"), required=False, max_value=32000) qa_museum_observed_quantity = forms.IntegerField(label=_("Observed quantity"), required=False, max_value=32000) qa_material_types = widgets.Select2MultipleField( label=_("Material types"), required=False ) qa_technical_processes = widgets.Select2MultipleField( label=_("Technical processes"), required=False, ) qa_object_types = widgets.Select2MultipleField( label=_("Object types"), required=False, ) qa_functional_areas = widgets.Select2MultipleField( label=_("Functional areas"), required=False, ) qa_technical_areas = widgets.Select2MultipleField( label=_("Technical areas"), required=False, ) qa_manufacturing_place = forms.CharField( label=_("Manufacturing place"), required=False ) qa_communicabilities = widgets.Select2MultipleField( label=_("Communicability"), required=False ) qa_alterations = widgets.Select2MultipleField(label=_("Alteration"), required=False) qa_alteration_causes = widgets.Select2MultipleField( label=_("Alteration cause"), required=False ) qa_conservatory_states = widgets.Select2MultipleField(label=_("Conservatory states"), required=False) qa_treatment_emergency = forms.ChoiceField( label=_("Treatment emergency"), choices=[], required=False ) qa_recommended_treatments = widgets.Select2MultipleField( label=_("Recommended treatments"), choices=[], required=False, ) qa_integrities = widgets.Select2MultipleField( label=_("Integrity"), required=False ) qa_remarkabilities = widgets.Select2MultipleField( label=_("Remarkability"), required=False ) qa_comment = forms.CharField( label=_("Comment"), required=False, widget=forms.Textarea ) qa_checked_type = forms.ChoiceField(label=_("Check"), required=False) qa_check_date = DateField(label=_("Check date"), required=False) qa_appraisal_date = DateField(label=_("Appraisal date"), required=False) qa_insurance_value = forms.FloatField(label=_("Insurance value"), required=False) qa_period = widgets.Select2MultipleField( label=_("Chronological period"), choices=[], required=False ) qa_cultural_attributions = widgets.Select2MultipleField( label=_("Cultural attribution"), required=False ) qa_dating_comment = forms.CharField( label=_("Comment on dating"), required=False, widget=forms.Textarea ) qa_conservatory_comment = forms.CharField( label=_("Comment on conservatory"), required=False, widget=forms.Textarea ) TYPES = [ FieldType("qa_material_types", models.MaterialType, is_multiple=True), FieldType("qa_object_types", models.ObjectType, is_multiple=True), FieldType("qa_functional_areas", models.FunctionalArea, is_multiple=True), FieldType("qa_technical_areas", models.TechnicalAreaType, is_multiple=True), FieldType("qa_technical_processes", models.TechnicalProcessType, is_multiple=True), FieldType("qa_communicabilities", models.CommunicabilityType, is_multiple=True), FieldType("qa_integrities", models.IntegrityType, is_multiple=True), FieldType("qa_cultural_attributions", CulturalAttributionType, is_multiple=True), FieldType("qa_alterations", models.AlterationType, is_multiple=True), FieldType("qa_alteration_causes", models.AlterationCauseType, is_multiple=True), FieldType("qa_recommended_treatments", models.RecommendedTreatmentType, is_multiple=True), FieldType("qa_remarkabilities", models.RemarkabilityType, is_multiple=True), FieldType("qa_checked_type", models.CheckedType), FieldType("qa_conservatory_states", models.ConservatoryState, is_multiple=True), FieldType("qa_treatment_emergency", models.TreatmentEmergencyType), FieldType("qa_period", Period, is_multiple=True), FieldType("qa_museum_collection_entry_mode", models.CollectionEntryModeType), FieldType("qa_museum_marking_type", models.MarkingType, is_multiple=True), FieldType("qa_museum_inventory_marking_presence", models.InventoryMarkingPresence, is_multiple=True), FieldType("qa_museum_collections", models.MuseumCollection), FieldType("qa_museum_original_repro", models.OriginalReproduction), FieldType("qa_ownership_status", models.OwnershipStatus), FieldType("qa_owner", models.OwnerType), ] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if "qa_insurance_value" in self.fields: self.fields["qa_insurance_value"].label = "{} ({})".format( str(self.fields["qa_insurance_value"].label), get_current_profile().currency, ) if not get_current_profile().museum or "qa_mark" not in self.fields: return # reorder mark field current_fields_keys = self.fields.keys() previous_key = None nok = True for k in reversed(self.base_field_keys): if k == "qa_museum_collection": nok = False continue if nok: continue if k in current_fields_keys: previous_key = k break fields = OrderedDict() if not previous_key: fields["qa_mark"] = self.fields["qa_mark"] for k in current_fields_keys: if k == "qa_mark": continue fields[k] = self.fields[k] if k == previous_key: fields["qa_mark"] = self.fields["qa_mark"] self.fields = fields def _get_qa_museum_owner_institution(self, value): return self._get_organization(value) def _get_qa_museum_assigned_institution(self, value): return self._get_organization(value) def _get_qa_museum_custodian_institution(self, value): return self._get_organization(value) def _get_bio(self, value): try: value = BiographicalNote.objects.get(pk=value).denomination except BiographicalNote.DoesNotExist: return "" return value def _get_qa_museum_donors(self, value): return self._get_bio(value) def _get_qa_museum_former_collections(self, value): return self._get_bio(value) def _get_qa_ue(self, value): try: value = ContextRecord.objects.get(pk=value).cached_label except ContextRecord.DoesNotExist: return "" return value # def _get_qa_collection(self, value): # try: # value = Warehouse.objects.get(pk=value).name # except Warehouse.DoesNotExist: # return "" # return value def _set_qa_ue(self, item, user): ue = self.cleaned_data["qa_ue"] if not ue: return cr = ContextRecord.objects.get(pk=ue) bf = item.get_first_base_find() bf.context_record = cr bf.history_modifier = user bf.save() def _set_qa_period(self, item, user): periods = self.cleaned_data["qa_period"] if not periods: return for period in periods: if Dating.objects.filter(find=item, period__pk=period).count(): continue d = Dating.objects.create(period_id=period) item.datings.add(d) class QAFindFormSingle(QAFindFormMulti): # TODO: not used? MULTI = False form_admin_name = _("Find - Quick action - Modify single") form_slug = "find-quickaction-modifysingle" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if ( not self.items or not self.items[0] .get_first_base_find() .context_record.operation.operation_type.judiciary ): self._remove_fields(("qa_seal_number",)) class QAFindBasketForm(IshtarForm): qa_bf_create_or_update = forms.ChoiceField( choices=(("create", _("Create")), ("update", _("Update"))), initial="create" ) qa_bf_label = forms.CharField(label="", max_length=None, required=False) qa_bf_basket = forms.IntegerField( label=_("Basket"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-findbasket-write"), associated_model=models.FindBasket, ), validators=[valid_id(models.FindBasket)], required=False, ) def __init__(self, *args, **kwargs): self.user = None if "user" in kwargs: self.user = kwargs.pop("user") if hasattr(self.user, "ishtaruser"): self.user = self.user.ishtaruser self.items = kwargs.pop("items") super(QAFindBasketForm, self).__init__(*args, **kwargs) def clean(self): if self.cleaned_data["qa_bf_create_or_update"] == "update": if not self.cleaned_data["qa_bf_basket"]: raise forms.ValidationError( _("On update, you have to select a basket.") ) q = Q(user=self.user) | Q(shared_write_with__pk=self.user.pk) q = models.FindBasket.objects.filter(q).filter( pk=self.cleaned_data["qa_bf_basket"] ) if not q.count(): raise forms.ValidationError(_("You cannot update the selected basket.")) return self.cleaned_data label = self.cleaned_data["qa_bf_label"].strip() if not label: raise forms.ValidationError(_("A label is required.")) if models.FindBasket.objects.filter(user=self.user, label=label).count(): raise forms.ValidationError( _("A basket with this label already " "exists.") ) return self.cleaned_data def save(self, items): if self.cleaned_data["qa_bf_create_or_update"] == "update": q = Q(user=self.user) | Q(shared_write_with__pk=self.user.pk) basket = ( models.FindBasket.objects.filter(q) .distinct() .get(pk=self.cleaned_data["qa_bf_basket"]) ) else: label = self.cleaned_data["qa_bf_label"].strip() basket = models.FindBasket.objects.create(user=self.user, label=label) for item in items: basket.items.add(item) class QAFindDuplicateForm(IshtarForm): label = forms.CharField(label=_("Free ID"), max_length=None, required=True) denomination = forms.CharField( label=_("Denomination"), max_length=None, required=False ) # modify = forms.BooleanField(label=_("Edit the new find"), required=False) def __init__(self, *args, **kwargs): self.user = None if "user" in kwargs: self.user = kwargs.pop("user") if hasattr(self.user, "ishtaruser"): self.user = self.user.ishtaruser self.find = kwargs.pop("items")[0] super(QAFindDuplicateForm, self).__init__(*args, **kwargs) self.fields["label"].initial = self.find.label + str(_(" - duplicate")) self.fields["denomination"].initial = self.find.denomination or "" def save(self): return self.find.duplicate( self.user, duplicate_for_treatment=False, data={ "label": self.cleaned_data["label"], "denomination": self.cleaned_data["denomination"], }, ) class QAFindbasketDuplicateForm(IshtarForm): label = forms.CharField(label="", max_length=None, required=True) def __init__(self, *args, **kwargs): self.user = None if "user" in kwargs: self.user = kwargs.pop("user") if hasattr(self.user, "ishtaruser"): self.user = self.user.ishtaruser self.basket = kwargs.pop("items")[0] super(QAFindbasketDuplicateForm, self).__init__(*args, **kwargs) self.fields["label"].initial = self.basket.label + str(_(" - duplicate")) def clean(self): label = self.cleaned_data["label"].strip() if not label: raise forms.ValidationError(_("A label is required.")) if models.FindBasket.objects.filter(user=self.user, label=label).count(): raise forms.ValidationError( _("A basket with this label already " "exists.") ) return self.cleaned_data def save(self): self.basket.duplicate(label=self.cleaned_data["label"], ishtaruser=self.user) class QAFindBasketModify(QAForm): form_admin_name = _("Find - Quick action - Modify") form_slug = "findbasket-quickaction-modify" MULTI = True SINGLE_FIELDS = ["qa_slug"] qa_label = forms.CharField( label="Denomination", validators=[validators.MaxLengthValidator(1000)], required=False ) qa_slug = forms.SlugField(label=_("Slug"), required=False) qa_public = forms.BooleanField(label=_("Is public"), required=False) qa_comment = forms.CharField(label=_("Comment"), widget=forms.Textarea, required=False) qa_shared_with = widgets.Select2MultipleField( model=IshtarUser, remote=True, label=_("Shared (read) with"), required=False, long_widget=True, ) qa_shared_write_with = widgets.Select2MultipleField( model=IshtarUser, remote=True, label=_("Shared (read/edit) with"), required=False, long_widget=True, ) REPLACE_FIELDS = [ "qa_label", "qa_slug", "qa_public", ] def _get_ishtar_user_list(self, value): if not isinstance(value, list): value = [value] values = [] for v in value: try: values.append(str(IshtarUser.objects.get(pk=v))) except IshtarUser.DoesNotExist: pass return " ; ".join(values) def _get_qa_shared_with(self, value): return self._get_ishtar_user_list(value) def _get_qa_shared_write_with(self, value): return self._get_ishtar_user_list(value) class PreservationForm(CustomForm, ManageOldType): form_label = _("Preservation") form_admin_name = _("Find - 030 - Preservation") form_slug = "find-030-preservation" base_models = [ "alteration", "alteration_cause", "recommended_treatment", "integritie", "remarkabilitie", "conservatory_state", ] associated_models = { "alteration": models.AlterationType, "alteration_cause": models.AlterationCauseType, "treatment_emergency": models.TreatmentEmergencyType, "conservatory_state": models.ConservatoryState, "recommended_treatment": models.RecommendedTreatmentType, "remarkabilitie": models.RemarkabilityType, "integritie": models.IntegrityType, } integritie = forms.MultipleChoiceField( label=_("Integrity"), choices=[], widget=widgets.Select2Multiple, required=False, ) remarkabilitie = forms.MultipleChoiceField( label=_("Remarkability"), choices=[], widget=widgets.Select2Multiple, required=False, ) conservatory_state = forms.MultipleChoiceField( label=_("Conservatory states"), choices=[], widget=widgets.Select2Multiple, required=False, ) alteration = forms.MultipleChoiceField( label=_("Alteration"), choices=[], widget=widgets.Select2Multiple, required=False, ) alteration_cause = forms.MultipleChoiceField( label=_("Alteration cause"), choices=[], widget=widgets.Select2Multiple, required=False, ) recommended_treatment = forms.MultipleChoiceField( label=_("Recommended treatments"), choices=[], widget=widgets.Select2Multiple, required=False, ) treatment_emergency = forms.ChoiceField( label=_("Treatment emergency"), choices=[], required=False ) estimated_value = FloatField(label=_("Estimated value"), required=False) insurance_value = FloatField(label=_("Insurance value"), required=False) appraisal_date = DateField(label=_("Appraisal date"), required=False) conservatory_comment = forms.CharField( label=_("Conservatory comment"), required=False, widget=forms.Textarea ) TYPES = [ FieldType("treatment_emergency", models.TreatmentEmergencyType), FieldType("recommended_treatment", models.RecommendedTreatmentType, True), FieldType("alteration", models.AlterationType, True), FieldType("alteration_cause", models.AlterationCauseType, True), FieldType("integritie", models.IntegrityType, is_multiple=True), FieldType("remarkabilitie", models.RemarkabilityType, is_multiple=True), FieldType("conservatory_state", models.ConservatoryState, is_multiple=True), ] def __init__(self, *args, **kwargs): super(PreservationForm, self).__init__(*args, **kwargs) if "insurance_value" in self.fields: self.fields["insurance_value"].label = "{} ({})".format( str(self.fields["insurance_value"].label), get_current_profile().currency, ) if "estimated_value" in self.fields: self.fields["estimated_value"].label = "{} ({})".format( str(self.fields["estimated_value"].label), get_current_profile().currency, ) class DateForm(ManageOldType, forms.Form): form_label = _("Dating") base_model = "dating" associated_models = { "dating_type": DatingType, "quality": DatingQuality, "period": Period, } period = forms.ChoiceField(label=_("Chronological period"), choices=[]) dating_type = forms.ChoiceField(label=_("Dating type"), required=False, choices=[]) start_date = forms.IntegerField(label=_("Start date"), required=False) end_date = forms.IntegerField(label=_("End date"), required=False) quality = forms.ChoiceField(label=_("Quality"), required=False, choices=[]) precise_dating = forms.CharField(label=_("Precise on this dating"), required=False) TYPES = [ FieldType("dating_type", DatingType), FieldType("period", Period), FieldType("quality", DatingQuality), ] DatingFormSet = formset_factory(DateForm, can_delete=True, formset=FormSet) DatingFormSet.form_label = _("Dating") DatingFormSet.form_admin_name = _("Find - 040 - Dating") DatingFormSet.form_slug = "find-040-dating" class FindSelect(MuseumForm, GeoItemSelect, PeriodSelect): _model = models.Find form_admin_name = _("Find - 001 - Search") form_slug = "find-001-search" FORM_FILTERS = [ ( _("Find origin"), [ "base_finds__cache_short_id", "base_finds__cache_complete_id", "base_finds__context_record__town", "base_finds__context_record__operation__year", "base_finds__context_record__operation__operation_code", "base_finds__context_record__operation__code_patriarche", "base_finds__context_record__operation__operation_type", "base_finds__context_record__operation__person_in_charge", "base_finds__context_record__operation__common_name" "base_finds__context_record__operation__operator", "base_finds__context_record__operation__address", "base_finds__context_record__town__areas", "base_finds__context_record__unit", "archaeological_sites", "archaeological_sites_context_record", "base_finds__context_record", "ope_relation_types", "cr_relation_types", ], ), ( _("Discovery"), [ "base_finds__comment", "base_finds__discovery_date", "base_finds__discovery_date_taq", ], ), ( _("Dimensions"), [ "length", "width", "height", "thickness", "diameter", "circumference", "volume", "weight", "clutter_long_side", "clutter_short_side", "clutter_height", "dimensions_comment", ], ), ( _("Preservation"), ( "integrities", "remarkabilities", "conservatory_states", "conservatory_comment", "alterations", "alteration_causes", "recommended_treatments", "treatment_emergency", ), ), ( _("Museum"), ( "museum_id_comment", "museum_owner_institution", "museum_assigned_institution", "museum_custodian_institution", "museum_depositor_inventory_number", "museum_collection_entry_mode", "museum_entry_mode_comment", "museum_entry_date", "museum_entry_date_end", "museum_entry_date_comment", "museum_donors", "museum_inventory_marking_presence", "museum_marking_type", "museum_collections", "museum_former_collections", "museum_inventory_entry_year", "museum_inventory_conformity", "museum_conformity_comment", "museum_inventory_transcript", "museum_original_repro", "museum_allocation_date", "museum_purchase_price", ), ), ] PROFILE_FILTER = { "museum": [ "cache_complete_museum_id", "museum_id_comment", "museum_owner_institution", "museum_assigned_institution", "museum_custodian_institution", "museum_depositor_inventory_number", "museum_collection_entry_mode", "museum_entry_mode_comment", "museum_entry_date", "museum_entry_date_end", "museum_entry_date_comment", "museum_donors", "museum_inventory_marking_presence", "museum_marking_type", "museum_collections", "museum_former_collections", "museum_inventory_entry_year", "museum_inventory_conformity", "museum_conformity_comment", "museum_inventory_transcript", "museum_original_repro", "museum_allocation_date", "museum_purchase_price", "museum_inventory_quantity", "museum_observed_quantity", ], } search_vector = forms.CharField( label=_("Full text search"), widget=widgets.SearchWidget("archaeological-finds", "find"), ) label = forms.CharField(label=_("Free ID")) denomination = forms.CharField(label=_("Denomination")) museum_id = forms.CharField(label=_("Museum inventory number")) cache_complete_museum_id = forms.CharField(label=_("Complete museum ID")) previous_id = forms.CharField(label=_("Previous ID")) base_finds__excavation_id = forms.CharField(label=_("Excavation ID")) seal_number = forms.CharField(label=_("Seal number")) laboratory_id = forms.CharField(label=_("Laboratory ID")) base_finds__cache_short_id = forms.CharField(label=_("Base find - Short ID")) base_finds__cache_complete_id = forms.CharField(label=_("Base find - Complete ID")) base_finds__context_record__town = get_town_field() base_finds__context_record__operation__year = forms.IntegerField(label=_("Year")) base_finds__context_record__operation__operation_code = forms.IntegerField( label=_("Operation - number (index by year)") ) base_finds__context_record__operation__code_patriarche = forms.IntegerField( label=_("Operation - Code (PATRIARCHE)"), widget=OAWidget ) base_finds__context_record__operation__operation_type = forms.ChoiceField( label=_("Operation - Type"), choices=[] ) base_finds__context_record__operation__address = forms.CharField( label=_("Operation - Address / Locality") ) base_finds__context_record__operation__in_charge = forms.IntegerField( label=_("Operation - In charge"), widget=widgets.JQueryAutoComplete(reverse_lazy("autocomplete-person")), ) base_finds__context_record__operation__scientist = forms.IntegerField( widget=widgets.JQueryAutoComplete( reverse_lazy( "autocomplete-person-permissive", args=[person_type_pks_lazy(["sra_agent", "head_scientist"])], ), associated_model=Person, ), label=_("Operation - Scientist in charge"), ) base_finds__context_record__operation__operator = forms.IntegerField( label=_("Operation - Operator"), widget=widgets.JQueryAutoComplete(reverse_lazy("autocomplete-organization")), ) base_finds__context_record__operation__common_name = forms.CharField( label=_("Operation - Name"), ) base_finds__context_record__operation__remains = forms.ChoiceField( label=_("Operation - Remains"), choices=[] ) base_finds__context_record__town__areas = forms.ChoiceField( label=_("Areas"), choices=[] ) archaeological_sites = forms.IntegerField( label=_("Archaeological site (attached to the operation)"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-archaeologicalsite"), associated_model=ArchaeologicalSite, ), validators=[valid_id(ArchaeologicalSite)], ) archaeological_sites_name = forms.CharField( label=_("Archaeological site name (attached to the operation)") ) archaeological_sites_context_record = forms.IntegerField( label=_("Archaeological site (attached to the context record)"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-archaeologicalsite"), associated_model=ArchaeologicalSite, ), validators=[valid_id(ArchaeologicalSite)], ) archaeological_sites_context_record_name = forms.CharField( label=_("Archaeological site name (attached to the context record)") ) base_finds__context_record__archaeological_site__remains = forms.ChoiceField( label=_("Archaeological site - Remains"), choices=[] ) base_finds__context_record = forms.IntegerField( label=_("Context record"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-contextrecord"), associated_model=ContextRecord ), validators=[valid_id(ContextRecord)], ) base_finds__context_record__unit = forms.ChoiceField(label=_("Context record - Type")) ope_relation_types = forms.ChoiceField( label=_("Search within related operations"), choices=[] ) cr_relation_types = forms.ChoiceField( label=_("Search within related context records"), choices=[] ) basket = forms.IntegerField( label=_("Basket"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-findbasket"), associated_model=models.FindBasket ), validators=[valid_id(models.FindBasket)], ) description = forms.CharField(label=_("Description")) base_finds__discovery_method = forms.ChoiceField(label=_("Discovery method"), choices=[]) base_finds__comment = forms.CharField(label=_("Base find - Comment on the circumstances of discovery")) base_finds__discovery_date = DateField(label=_("Discovery date (exact or beginning)")) base_finds__discovery_date_taq = DateField(label=_("Discovery date (end)")) base_finds__batch = forms.ChoiceField(label=_("Batch/object"), choices=[]) is_complete = forms.NullBooleanField(label=_("Is complete?")) material_types = forms.IntegerField( label=_("Material type"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-materialtype"), associated_model=models.MaterialType, ), ) material_type_quality = forms.ChoiceField( label=_("Material type quality"), choices=[] ) technical_processes = forms.IntegerField( label=_("Technical processes"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-technicalprocess"), associated_model=models.TechnicalProcessType, ), ) material_comment = forms.CharField(label=_("Comment on the material")) object_types = forms.IntegerField( label=_("Object type"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-objecttype"), associated_model=models.ObjectType ), ) object_type_quality = forms.ChoiceField(label=_("Object type quality"), choices=[]) functional_areas = forms.IntegerField( label=_("Functional areas"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-functionalarea"), associated_model=models.FunctionalArea, ), ) technical_areas = forms.IntegerField( label=_("Technical areas"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-technicalarea"), associated_model=models.TechnicalAreaType, ), ) find_number = forms.IntegerField(label=_("Number of remains")) min_number_of_individuals = forms.IntegerField( label=_("Minimum number of individuals (MNI)") ) museum_inventory_quantity = forms.IntegerField(label=_("Inventory quantity")) museum_observed_quantity = forms.IntegerField(label=_("Observed quantity")) manufacturing_place = forms.CharField(label=_("Manufacturing place")) decoration = forms.CharField(label=_("Decoration")) inscription = forms.CharField(label=_("Inscription")) communicabilities = forms.ChoiceField(label=_("Communicability")) comment = forms.CharField(label=_("General comment")) cultural_attributions = forms.ChoiceField( label=_("Cultural attribution"), choices=[], required=False ) dating_comment = forms.CharField(label=_("Comment on dating")) length = FloatField(label=_("Length (cm)"), widget=widgets.CentimeterMeterWidget) width = FloatField(label=_("Width (cm)"), widget=widgets.CentimeterMeterWidget) height = FloatField(label=_("Height (cm)"), widget=widgets.CentimeterMeterWidget) thickness = FloatField(label=_("Thickness (cm)"), widget=widgets.CentimeterMeterWidget) diameter = FloatField(label=_("Diameter (cm)"), widget=widgets.CentimeterMeterWidget) circumference = FloatField(label=_("Circumference (cm)"), widget=widgets.CentimeterMeterWidget) volume = FloatField(label=_("Volume (l)")) weight = FloatField(label=_("Weight - lower than (g)"), widget=widgets.GramKilogramWidget) clutter_long_side = FloatField( label=_("Clutter long side (cm)"), widget=widgets.CentimeterMeterWidget, ) clutter_short_side = FloatField( label=_("Clutter short side (cm)"), widget=widgets.CentimeterMeterWidget, ) clutter_height = FloatField( label=_("Clutter height (cm)"), widget=widgets.CentimeterMeterWidget, ) dimensions_comment = forms.CharField(label=_("Dimensions comment")) base_finds__topographic_localisation = forms.CharField( label=_("Point of topographic reference"), ) checked_type = forms.ChoiceField(label=_("Check")) check_date = DateField(label=_("Check date")) integrities = forms.ChoiceField(label=_("Integrity"), choices=[]) remarkabilities = forms.ChoiceField(label=_("Remarkability"), choices=[]) conservatory_states = forms.ChoiceField(label=_("Conservatory states"), choices=[]) conservatory_comment = forms.CharField(label=_("Conservatory comment")) alterations = forms.ChoiceField(label=_("Alteration"), choices=[]) alteration_causes = forms.ChoiceField(label=_("Alteration cause"), choices=[]) recommended_treatments = forms.ChoiceField( choices=[], label=_("Recommended treatments") ) treatment_emergency = forms.ChoiceField(choices=[], label=_("Treatment emergency")) estimated_value = FloatField(label=_("Estimated value")) insurance_value = FloatField(label=_("Insurance value")) appraisal_date = DateField(label=_("Appraisal date")) loan = forms.NullBooleanField(label=_("Loan?")) treatments_file_end_date = DateField(label=_("Treatment file end date")) treatments_end_date = DateField(label=_("Treatment end date")) # museum museum_id_comment = forms.CharField(label=_("Museum - Comment on museum ID")) museum_owner_institution = forms.IntegerField( label=_("Museum - Owner institution"), widget=widgets.JQueryAutoComplete( reverse_lazy('autocomplete-organization'), associated_model=Organization), validators=[valid_id(Organization)]) museum_assigned_institution = forms.IntegerField( label=_("Museum - Assigned institution"), widget=widgets.JQueryAutoComplete( reverse_lazy('autocomplete-organization'), associated_model=Organization), validators=[valid_id(Organization)]) museum_custodian_institution = forms.IntegerField( label=_("Museum - Custodian institution"), widget=widgets.JQueryAutoComplete( reverse_lazy('autocomplete-organization'), associated_model=Organization), validators=[valid_id(Organization)]) museum_depositor_inventory_number = forms.CharField(label=_("Museum - Depositor inventory number")) museum_collection_entry_mode = forms.ChoiceField(label=_("Museum - Collections entry mode"), choices=[]) museum_entry_mode_comment = forms.CharField(label=_("Museum - Comment on museum entry mode")) museum_entry_date = DateField(label=_("Museum - Entry date (exact or start)")) museum_entry_date_end = DateField(label=_("Museum - Entry date end")) museum_entry_date_comment = forms.CharField(label=_("Museum - Comment on entry date")) museum_donors = forms.IntegerField( label=_("Museum - Donors, testators or vendors"), widget=widgets.JQueryAutoComplete( reverse_lazy('autocomplete-biographicalnote'), associated_model=BiographicalNote), validators=[valid_id(BiographicalNote)]) museum_inventory_marking_presence = forms.ChoiceField( label=_("Museum - Presence of inventory marking"), choices=[] ) museum_marking_type = forms.ChoiceField( label=_("Museum - Type of marking"), choices=[] ) mark = forms.CharField(label=_("Mark")) museum_collections = forms.ChoiceField( label=_("Museum - Collection"), choices=[] ) museum_former_collections = forms.IntegerField( label=_("Museum - Former collection"), widget=widgets.JQueryAutoComplete( reverse_lazy('autocomplete-biographicalnote'), associated_model=BiographicalNote), validators=[valid_id(BiographicalNote)]) museum_inventory_entry_year= forms.IntegerField(label=_("Museum - Inventory entry year")) museum_inventory_conformity = forms.ChoiceField( label=_("Museum - Conformity with inventory"), choices=[] ) museum_conformity_comment = forms.CharField(label=_("Museum - Comment on conformity")) museum_inventory_transcript = forms.CharField(label=_("Museum - Inventory transcript")) museum_original_repro = forms.ChoiceField( label=_("Museum - Original/reproduction"), choices=[] ) museum_allocation_date = DateField(label=_("Museum - Date of allocation")) museum_purchase_price = forms.CharField(label=_("Museum - Purchase price")) TYPES = PeriodSelect.TYPES + [ FieldType("conservatory_states", models.ConservatoryState), FieldType("base_finds__batch", models.BatchType), FieldType("recommended_treatments", models.RecommendedTreatmentType), FieldType("integrities", models.IntegrityType), FieldType("remarkabilities", models.RemarkabilityType), FieldType("base_finds__discovery_method", models.DiscoveryMethod), FieldType("base_finds__context_record__town__areas", Area), FieldType( "base_finds__context_record__operation__operation_type", OperationType ), FieldType("base_finds__context_record__unit", Unit), FieldType("checked_type", models.CheckedType), FieldType("material_type_quality", models.MaterialTypeQualityType), FieldType("object_type_quality", models.ObjectTypeQualityType), FieldType("communicabilities", models.CommunicabilityType), FieldType("alterations", models.AlterationType), FieldType("alteration_causes", models.AlterationCauseType), FieldType("treatment_emergency", models.TreatmentEmergencyType), FieldType("cultural_attributions", CulturalAttributionType), FieldType( "base_finds__context_record__archaeological_site__remains", RemainType ), FieldType( "base_finds__context_record__operation__remains", RemainType ), FieldType("museum_collection_entry_mode", models.CollectionEntryModeType), FieldType("museum_inventory_marking_presence", models.InventoryMarkingPresence), FieldType("museum_marking_type", models.MarkingType), FieldType("museum_collections", models.MuseumCollection), FieldType("museum_inventory_conformity", models.InventoryConformity), FieldType("museum_original_repro", models.OriginalReproduction), ] + GeoItemSelect.TYPES SITE_KEYS = { "archaeological_sites": "attached-to-operation", "archaeological_sites_name": "name-attached-to-operation", "archaeological_sites_context_record": "attached-to-cr", "archaeological_sites_context_record_name": "name-attached-to-cr", } def __init__(self, *args, **kwargs): super(FindSelect, self).__init__(*args, **kwargs) if "ope_relation_types" in self.fields: self.fields["ope_relation_types"].choices = OpeRelationType.get_types() if "cr_relation_types" in self.fields: self.fields["cr_relation_types"].choices = CRRelationType.get_types() self._reorder_period_fields("cultural_attributions") def get_input_ids(self): ids = super(FindSelect, self).get_input_ids() if "ope_relation_types" in ids: ids.pop(ids.index("ope_relation_types")) for idx, c in enumerate(self.fields["ope_relation_types"].choices): ids.append("ope_relation_types_{}".format(idx)) if "cr_relation_types" in ids: ids.pop(ids.index("cr_relation_types")) for idx, c in enumerate(self.fields["cr_relation_types"].choices): ids.append("cr_relation_types_{}".format(idx)) return ids class FindSelectWarehouseModule(FindSelect): container_ref = forms.IntegerField( label=_("Reference container"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-container"), associated_model=Container ), validators=[valid_id(Container)], ) container_ref__location = forms.IntegerField( label=_("Reference container - Warehouse (location)"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-warehouse"), associated_model=Warehouse ), validators=[valid_id(Warehouse)], ) """ container_ref__responsible = forms.IntegerField( label=_("Reference container - Warehouse (responsible)"), widget=widgets.JQueryAutoComplete( reverse_lazy('autocomplete-warehouse'), associated_model=Warehouse), validators=[valid_id(Warehouse)]) container_ref__index = forms.IntegerField( label=_("Reference container ID")) container_ref__reference = forms.CharField( label=_("Reference container ref.")) """ container = forms.IntegerField( label=_("Current container"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-container"), associated_model=Container ), validators=[valid_id(Container)], ) container__location = forms.IntegerField( label=_("Current container - Warehouse (location)"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-warehouse"), associated_model=Warehouse ), validators=[valid_id(Warehouse)], ) """ container__responsible = forms.IntegerField( label=_("Current container - Warehouse (responsible)"), widget=widgets.JQueryAutoComplete( reverse_lazy('autocomplete-warehouse'), associated_model=Warehouse), validators=[valid_id(Warehouse)]) container__index = forms.IntegerField(label=_("Current container ID")) container__reference = forms.CharField(label=_("Current container ref.")) """ class FindFormSelection(LockForm, CustomFormSearch): SEARCH_AND_SELECT = True form_label = _("Find search") associated_models = {"pk": models.Find} currents = {"pk": models.Find} pk_key = "pk" pk = forms.IntegerField( label="", required=False, widget=widgets.DataTable( reverse_lazy("get-find"), FindSelect, models.Find, gallery=True, map=True, source_full=reverse_lazy("get-find-full"), ), validators=[valid_id(models.Find)], ) class FindFormMultiSelection(LockForm, MultiSearchForm): form_label = _("Find search") associated_models = {"pks": models.Find} pk_key = "pks" pk = forms.CharField( label="", required=False, widget=widgets.DataTable( reverse_lazy("get-find"), FindSelect, models.Find, gallery=True, map=True, multiple_select=True, source_full=reverse_lazy("get-find-full"), ), validators=[valid_ids(models.Find)], ) class FindFormSelectionWarehouseModule(FindFormSelection): pk = forms.IntegerField( label="", required=False, widget=widgets.DataTable( reverse_lazy("get-find"), FindSelectWarehouseModule, models.Find, gallery=True, map=True, source_full=reverse_lazy("get-find-full"), ), validators=[valid_id(models.Find)], ) class FindFormMultiSelectionWarehouseModule(FindFormMultiSelection): pk = forms.CharField( label="", required=False, widget=widgets.DataTable( reverse_lazy("get-find"), FindSelectWarehouseModule, models.Find, gallery=True, map=True, multiple_select=True, source_full=reverse_lazy("get-find-full"), ), validators=[valid_ids(models.Find)], ) class MultipleFindFormSelection(CustomForm, forms.Form): # used for basket management # TODO: could probably use FindFormMultiSelection form_label = _("Find search") associated_models = {"pk": models.Find} currents = {"pk": models.Find} pk = forms.IntegerField( label="", required=False, widget=widgets.DataTable( reverse_lazy("get-find"), FindSelect, models.Find, gallery=True, map=True, multiple_select=True, source_full=reverse_lazy("get-find-full"), ), validators=[valid_id(models.Find)], ) class MultipleFindFormSelectionWarehouseModule(MultipleFindFormSelection): # used for basket management # TODO: could probably use FindFormMultiSelectionWarehouse pk = forms.IntegerField( label="", required=False, widget=widgets.DataTable( reverse_lazy("get-find"), FindSelectWarehouseModule, models.Find, gallery=True, map=True, multiple_select=True, source_full=reverse_lazy("get-find-full"), ), validators=[valid_id(models.Find)], ) class FindMultipleFormSelection(CustomForm, forms.Form): form_label = _("Upstream finds") associated_models = {"finds": models.Find} associated_labels = {"finds": _("Finds")} # using FindSelectWarehouseModule because this form is only used with # the warehouse module activated finds = forms.CharField( label="", required=False, widget=widgets.DataTable( reverse_lazy("get-find"), FindSelectWarehouseModule, models.Find, gallery=True, map=True, multiple=True, multiple_cols=[2, 3, 4], ), validators=[valid_ids(models.Find)], ) def clean(self): if "finds" not in self.cleaned_data or not self.cleaned_data["finds"]: raise forms.ValidationError( _("You should at least select one " "archaeological find.") ) return self.cleaned_data def check_form(wizard, form_name, key): request = wizard.request storage = wizard.storage if ( storage.prefix not in request.session or "step_data" not in request.session[storage.prefix] or form_name not in request.session[storage.prefix]["step_data"] or form_name + "-" + key not in request.session[storage.prefix]["step_data"][form_name] ): return False return True def check_exist(form_name, key): def func(self): request = self.request storage = self.storage if not check_form(self, form_name, key): return False try: val = request.session[storage.prefix]["step_data"][form_name][ form_name + "-" + key ] if val and len(val) > 0: val = val[0] return bool(val) except ValueError: return False return func def check_not_exist(form_name, key): def func(self): return not check_exist(form_name, key)(self) return func def check_value(form_name, key, value): def func(self): request = self.request storage = self.storage if not check_form(self, form_name, key): return False try: val = request.session[storage.prefix]["step_data"][form_name][ form_name + "-" + key ] if val and len(val) > 0: val = val[0] return str(val) == str(value) except ValueError: return False return func def check_type_field(form_name, key, model, field): def func(self): request = self.request storage = self.storage if not check_form(self, form_name, key): return False try: val = model.objects.get( pk=request.session[storage.prefix]["step_data"][form_name][ form_name + "-" + key ][0] ) return bool(getattr(val, field)) except (ValueError, model.DoesNotExist): return False return func def check_type_not_field(form_name, key, model, field): def func(self): return not check_type_field(form_name, key, model, field)(self) return func def check_treatment(form_name, type_key, type_list=[], not_type_list=[]): type_list = [models.TreatmentType.objects.get(txt_idx=tpe).pk for tpe in type_list] not_type_list = [ models.TreatmentType.objects.get(txt_idx=tpe).pk for tpe in not_type_list ] def func(self): request = self.request storage = self.storage if not check_form(self, form_name, type_key): return False try: tpe = request.session[storage.prefix]["step_data"][form_name][ form_name + "-" + type_key ] if not tpe: return False type = int(tpe[0]) return (not type_list or type in type_list) and type not in not_type_list except ValueError: return False return func class ResultFindForm(ManageOldType, forms.Form): form_label = _("Resulting find") associated_models = {"material_type": models.MaterialType} label = forms.CharField( label=_("Free ID"), validators=[validators.MaxLengthValidator(60)] ) description = forms.CharField(label=_("Precise description"), widget=forms.Textarea) material_type = forms.ChoiceField(label=_("Material type"), choices=[]) volume = forms.IntegerField(label=_("Volume (l)")) weight = forms.IntegerField(label=_("Weight (g)")) find_number = forms.IntegerField(label=_("Number of remains")) TYPES = [FieldType("material_type", models.MaterialType)] ResultFindFormSet = formset_factory(ResultFindForm, can_delete=True, formset=FormSet) ResultFindFormSet.form_label = _("Resulting finds") class FindDeletionForm(FinalForm): confirm_msg = " " confirm_end_msg = _("Would you like to delete this find?") class UpstreamFindFormSelection(MultiSearchForm, FindFormSelection): form_label = _("Upstream finds") current_model = models.Find pk_key = "resulting_pk" associated_models = {"resulting_pk": models.Find} pk = forms.CharField( label="", required=False, widget=widgets.DataTable( reverse_lazy("get-find"), FindSelect, current_model, gallery=True, multiple_select=True, source_full=reverse_lazy("get-find-full"), ), validators=[valid_ids(current_model)], ) class SingleUpstreamFindFormSelection(UpstreamFindFormSelection): current_model = models.Find pk = forms.CharField( label="", required=False, widget=widgets.DataTable( reverse_lazy("get-find"), FindSelect, current_model, gallery=True, source_full=reverse_lazy("get-find-full"), ), validators=[valid_ids(current_model)], ) class FindBasketSelect(CustomForm, TableSelect): _model = models.FindBasket form_admin_name = _("Find basket - 001 - Search") form_slug = "findbasket-001-search" search_vector = forms.CharField( label=_("Full text search"), widget=widgets.SearchWidget("archaeological-finds", "findbasket"), ) label = forms.CharField(label=_("Denomination")) class FindBasketFormSelection(CustomFormSearch): SEARCH_AND_SELECT = True form_label = _("Basket search") associated_models = {"pk": models.FindBasket} currents = {"pk": models.FindBasket} pk = forms.IntegerField( label="", required=False, widget=widgets.DataTable( reverse_lazy("get-findbasket"), FindBasketSelect, models.FindBasket, ), validators=[valid_id(models.FindBasket)], ) class FindBasketForWriteFormSelection(CustomFormSearch): SEARCH_AND_SELECT = True form_label = _("Basket search") associated_models = {"pk": models.FindBasket} currents = {"pk": models.FindBasket} pk = forms.IntegerField( label="", required=False, widget=widgets.DataTable( reverse_lazy("get-findbasket-write"), FindBasketSelect, models.FindBasket, ), validators=[valid_id(models.FindBasket)], ) class FindBasketForm(IshtarForm): form_label = _("Find basket") associated_models = {"shared_with": IshtarUser, "shared_write_with": IshtarUser} label = forms.CharField( label=_("Label"), validators=[validators.MaxLengthValidator(1000)] ) slug = forms.SlugField(label=_("Slug"), required=False) public = forms.BooleanField(label=_("Is public"), required=False) comment = forms.CharField(label=_("Comment"), widget=forms.Textarea, required=False) shared_with = widgets.Select2MultipleField( model=IshtarUser, remote=True, label=_("Shared (read) with"), required=False, long_widget=True, ) shared_write_with = widgets.Select2MultipleField( model=IshtarUser, remote=True, label=_("Shared (read/edit) with"), required=False, long_widget=True, ) def __init__(self, *args, **kwargs): self.basket_pk = None if "basket_pk" in kwargs: self.basket_pk = kwargs.pop("basket_pk") self.is_admin = None if "user" in kwargs: self.user = kwargs.pop("user") self.is_admin = getattr(self.user, "is_superuser", None) super(FindBasketForm, self).__init__(*args, **kwargs) if not self.is_admin: self.fields.pop("slug") self.fields.pop("public") def clean(self): slug = self.cleaned_data.get("slug", None) if ( slug and slug.strip() and models.FindBasket.objects.filter(slug=slug.strip()) .exclude(pk=self.basket_pk) .count() ): raise forms.ValidationError(_("A basket with this slug already " "exists.")) return self.cleaned_data class NewFindBasketForm(forms.ModelForm, IshtarForm): shared_with = widgets.Select2MultipleField( model=IshtarUser, remote=True, label=_("Shared (read) with"), required=False, long_widget=True, ) shared_write_with = widgets.Select2MultipleField( model=IshtarUser, remote=True, label=_("Shared (read/edit) with"), required=False, long_widget=True, ) class Meta: model = models.FindBasket fields = ( "label", "slug", "public", "comment", "shared_with", "shared_write_with", ) def __init__(self, *args, **kwargs): self.user = kwargs.pop("user") self.is_admin = False if getattr(self.user, "user_ptr", None): self.is_admin = getattr(self.user.user_ptr, "is_superuser", None) super(NewFindBasketForm, self).__init__(*args, **kwargs) if not self.is_admin: self.fields.pop("slug") self.fields.pop("public") def clean(self): q = models.FindBasket.objects.filter( user=self.user, label=self.cleaned_data["label"] ) if q.count(): raise forms.ValidationError( _("Another basket already exists with " "this name.") ) slug = self.cleaned_data.get("slug", None) if ( slug and slug.strip() and models.FindBasket.objects.filter(slug=slug.strip()).count() ): raise forms.ValidationError(_("A basket with this slug already " "exists.")) return self.cleaned_data def save(self, commit=True): self.instance.user = self.user return super(NewFindBasketForm, self).save(commit) class SelectFindBasketForm(IshtarForm): form_label = _("Basket") associated_models = {"basket": models.FindBasket} need_user_for_initialization = True basket = forms.IntegerField( label=_("Basket"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-findbasket"), associated_model=models.FindBasket ), validators=[valid_id(models.FindBasket)], ) def __init__(self, *args, **kwargs): self.user = None if "user" in kwargs: self.user = kwargs.pop("user") if hasattr(self.user, "ishtaruser"): self.user = self.user.ishtaruser super(SelectFindBasketForm, self).__init__(*args, **kwargs) class SelectFindBasketWriteForm(IshtarForm): form_label = _("Basket") associated_models = {"basket": models.FindBasket} need_user_for_initialization = True basket = forms.IntegerField( label=_("Basket"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-findbasket-write"), associated_model=models.FindBasket, ), validators=[valid_id(models.FindBasket)], ) def __init__(self, *args, **kwargs): self.user = None if "user" in kwargs: self.user = kwargs.pop("user") if hasattr(self.user, "ishtaruser"): self.user = self.user.ishtaruser super(SelectFindBasketWriteForm, self).__init__(*args, **kwargs) class FindBasketAddItemForm(forms.Form): basket_id = forms.IntegerField(required=True) item_id = forms.IntegerField(required=True) def save(self, ishtaruser): try: basket = ( models.FindBasket.objects.filter( Q(user=ishtaruser) | Q(shared_with=ishtaruser) | Q(shared_write_with=ishtaruser) ) .distinct() .get(pk=self.cleaned_data["basket_id"]) ) item = models.Find.objects.get(pk=self.cleaned_data["item_id"]) except models.FindBasket.DoesNotExist or models.Find.DoesNotExist: # something strange... TODO: log it raise PermissionDenied # check rights if ( not ishtaruser.user_ptr.is_superuser and not ishtaruser.has_permission("archaeological_finds.view_find") and not ishtaruser.has_permission( "archaeological_finds.view_own_find", obj=item) ): raise PermissionDenied basket.items.add(item) return basket