#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (C) 2010-2016 É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 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 ( DatingType, DatingQuality, ContextRecord, RelationType as CRRelationType, Dating, ) from archaeological_finds.forms_treatments import ( TreatmentSelect, TreatmentFormSelection, BaseTreatmentForm, TreatmentModifyForm, AdministrativeActTreatmentForm, TreatmentFormFileChoice, TreatmentDeletionForm, TreatmentFileSelect, TreatmentFileFormSelection, TreatmentFileForm, TreatmentFileModifyForm, TreatmentFileDeletionForm, TreatmentFileFormSelectionMultiple, 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 bootstrap_datepicker.widgets import DatePicker 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 BasicFindForm(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 = "simplefind-020-general" base_models = [ "object_type", "material_type", "communicabilitie", "cultural_attribution", "functional_area", "technical_area", "technical_processe", "museum_former_collection", "museum_inventory_marking_presence", "museum_marking_type", ] 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, #'collection': Warehouse, } field_order = [ "museum_id_prefix", "museum_id", "museum_id_suffix", "label", "denomination", "museum_id_comment", "previous_id", "laboratory_id", "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", "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", "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")) label = forms.CharField( label=_("Free ID"), validators=[validators.MaxLengthValidator(60)] ) 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")) 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=_("Marking details"), required=False) # collection = forms.IntegerField( # label=_("Collection (warehouse)"), # widget=widgets.JQueryAutoComplete( # reverse_lazy('autocomplete-warehouse'), # associated_model=Warehouse, new=True), # validators=[valid_id(Warehouse)], required=False) 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 = forms.DateField( label=_("Museum entry date (exact or start)"), widget=DatePicker, required=False ) museum_entry_date_end = forms.DateField( label=_("Museum entry date (end)"), widget=DatePicker, required=False ) museum_entry_date_comment = forms.CharField(label=_("Comment on museum entry date"), required=False) museum_donor = forms.IntegerField( widget=widgets.JQueryAutoComplete( reverse_lazy('autocomplete-biographicalnote'), associated_model=BiographicalNote, new=True), label=_("Donor, testator or vendor"), required=False ) museum_collection = forms.ChoiceField( label=_("Collection"), required=False, choices=[] ) 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 = forms.DateField( label=_("Date of museum allocation"), widget=DatePicker, 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 ) 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 = forms.DateField( initial=get_now, label=_("Check date"), widget=DatePicker ) 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("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), ] 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",)) 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", "museum_id_suffix", "museum_id_comment", "label", "denomination", "previous_id", "get_first_base_find__excavation_id", "laboratory_id", "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_original_repro", "museum_allocation_date", "museum_purchase_price", "museum_inventory_transcript", "description", "public_description", "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_date = forms.DateField( label=_("Discovery date (exact or beginning)"), widget=DatePicker, required=False ) get_first_base_find__discovery_date_taq = forms.DateField( label=_("Discovery date (end)"), widget=DatePicker, 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 = "treatmentn1-030-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 = forms.DateField( initial=get_now, label=_("Check date"), widget=DatePicker ) 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 = "treatment1n-030-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(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_museum_collection_entry_mode", "qa_museum_inventory_marking_presence", "qa_museum_marking_type", "qa_museum_collection", "qa_museum_original_repro", ] 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_state": models.ConservatoryState, "qa_treatment_emergency": models.TreatmentEmergencyType, "qa_museum_collection_entry_mode": models.CollectionEntryModeType, "qa_museum_owner_institution": Organization, "qa_museum_assigned_institution": Organization, "qa_museum_custodian_institution": Organization, "qa_museum_donor": BiographicalNote, "qa_museum_marking_type": models.MarkingType, "qa_museum_inventory_marking_presence": models.InventoryMarkingPresence, "qa_museum_collection": models.MuseumCollection, "qa_museum_original_repro": models.OriginalReproduction, "qa_museum_former_collections": BiographicalNote, } MULTI = True REPLACE_FIELDS = [ "qa_denomination", "qa_ue", "qa_manufacturing_place", "qa_checked_type", "qa_check_date", "qa_conservatory_state", "qa_treatment_emergency", "qa_appraisal_date", "qa_insurance_value", # 'qa_collection', "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_donor", "qa_museum_collection", "qa_museum_inventory_entry_year", "qa_museum_original_repro", ] 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_donor", "qa_museum_inventory_marking_presence", "qa_museum_marking_type", "qa_museum_collection", "qa_museum_former_collections", "qa_museum_inventory_entry_year", "qa_museum_original_repro", ], } HEADERS = { "qa_ue": FormHeader(_("Context record")), "qa_denomination": FormHeader(_("Identification")), "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_label", "qa_previous_id", "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=_("Marking details"), required=False) # qa_collection = forms.IntegerField( # label=_("Collection"), # widget=widgets.JQueryAutoComplete( # reverse_lazy('autocomplete-warehouse'), # associated_model=Warehouse), # validators=[valid_id(Warehouse)], required=False) ## 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 = forms.DateField( label=_("Museum entry date (exact or start)"), widget=DatePicker, required=False ) qa_museum_entry_date_end = forms.DateField( label=_("Museum entry date (end)"), widget=DatePicker, required=False ) qa_museum_donor = forms.IntegerField( label=_("Donor, testator or vendor"), 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_collection = forms.ChoiceField(label=_("Collection"), 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_state = forms.ChoiceField( label=_("Conservatory state"), required=False, choices=[] ) qa_treatment_emergency = forms.ChoiceField( label=_("Treatment emergency"), 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 = forms.DateField( label=_("Check date"), widget=DatePicker, required=False ) qa_appraisal_date = forms.DateField( label=_("Appraisal date"), widget=DatePicker, 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_remarkabilities", models.RemarkabilityType, is_multiple=True), FieldType("qa_checked_type", models.CheckedType), FieldType("qa_conservatory_state", models.ConservatoryState), 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_collection", models.MuseumCollection), FieldType("qa_museum_original_repro", models.OriginalReproduction), ] 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_donor(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", "preservation_to_consider", "integritie", "remarkabilitie", ] associated_models = { "alteration": models.AlterationType, "alteration_cause": models.AlterationCauseType, "treatment_emergency": models.TreatmentEmergencyType, "conservatory_state": models.ConservatoryState, "preservation_to_consider": models.TreatmentType, "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.ChoiceField( label=_("Conservatory state"), choices=[], 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, ) preservation_to_consider = 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 = forms.DateField( label=_("Appraisal date"), widget=DatePicker, required=False ) conservatory_comment = forms.CharField( label=_("Conservatory comment"), required=False, widget=forms.Textarea ) TYPES = [ FieldType("conservatory_state", models.ConservatoryState), FieldType("treatment_emergency", models.TreatmentEmergencyType), FieldType("preservation_to_consider", models.TreatmentType, 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), ] 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 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(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", "archaeological_sites", "archaeological_sites_context_record", "base_finds__context_record", "ope_relation_types", "cr_relation_types", ], ), ( _("Discovery"), [ "base_finds__comment", "base_finds__discovery_date__before", "base_finds__discovery_date__after", "base_finds__discovery_date_taq__before", "base_finds__discovery_date_taq__after", ], ), ( _("Dimensions"), [ "length__higher", "width__higher", "height__higher", "thickness__higher", "diameter__higher", "circumference__higher", "volume__higher", "weight__higher", "clutter_long_side__higher", "clutter_short_side__higher", "clutter_height__higher", "length__lower", "width__lower", "height__lower", "thickness__lower", "diameter__lower", "circumference__lower", "volume__lower", "weight__lower", "clutter_long_side__lower", "clutter_short_side__lower", "clutter_height__lower", "dimensions_comment", ], ), ( _("Preservation"), ( "integrities", "remarkabilities", "conservatory_state", "conservatory_comment", "alterations", "alteration_causes", "preservation_to_considers", "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_before", "museum_entry_date_after", "museum_entry_date_end_before", "museum_entry_date_end_after", "museum_entry_date_comment", "museum_donor", "museum_inventory_marking_presence", "museum_marking_type", "museum_collection", "museum_former_collections", "museum_inventory_entry_year_before", "museum_inventory_entry_year_after", "museum_inventory_conformity", "museum_conformity_comment", "museum_inventory_transcript", "museum_original_repro", "museum_allocation_date_before", "museum_allocation_date_after", "museum_purchase_price", ), ), ] PROFILE_FILTER = { "museum": [ "museum_id", "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_before", "museum_entry_date_after", "museum_entry_date_end_before", "museum_entry_date_end_after", "museum_entry_date_comment", "museum_donor", "museum_inventory_marking_presence", "museum_marking_type", "museum_collection", "museum_former_collections", "museum_inventory_entry_year_before", "museum_inventory_entry_year_after", "museum_inventory_conformity", "museum_conformity_comment", "museum_inventory_transcript", "museum_original_repro", "museum_allocation_date_before", "museum_allocation_date_after", "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)], ) 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__comment = forms.CharField(label=_("Base find - Comment on the circumstances of discovery")) base_finds__discovery_date__after = forms.DateField( label=_("Discovery date (exact or beginning) after"), widget=DatePicker ) base_finds__discovery_date__before = forms.DateField( label=_("Discovery date (exact or beginning) before"), widget=DatePicker ) base_finds__discovery_date_taq__after = forms.DateField( label=_("Discovery date (end) after"), widget=DatePicker ) base_finds__discovery_date_taq__before = forms.DateField( label=_("Discovery date (end) before"), widget=DatePicker ) 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__higher = FloatField( label=_("Length - higher than (cm)"), widget=widgets.CentimeterMeterWidget ) length__lower = FloatField( label=_("Length - lower than (cm)"), widget=widgets.CentimeterMeterWidget ) width__lower = FloatField( label=_("Width - lower than (cm)"), widget=widgets.CentimeterMeterWidget ) width__higher = FloatField( label=_("Width - higher than (cm)"), widget=widgets.CentimeterMeterWidget ) height__lower = FloatField( label=_("Height - lower than (cm)"), widget=widgets.CentimeterMeterWidget ) height__higher = FloatField( label=_("Height - higher than (cm)"), widget=widgets.CentimeterMeterWidget ) thickness__lower = FloatField( label=_("Thickness - lower than (cm)"), widget=widgets.CentimeterMeterWidget ) thickness__higher = FloatField( label=_("Thickness - higher than (cm)"), widget=widgets.CentimeterMeterWidget ) diameter__lower = FloatField( label=_("Diameter - lower than (cm)"), widget=widgets.CentimeterMeterWidget ) diameter__higher = FloatField( label=_("Diameter - higher than (cm)"), widget=widgets.CentimeterMeterWidget ) circumference__lower = FloatField( label=_("Circumference - lower than (cm)"), widget=widgets.CentimeterMeterWidget ) circumference__higher = FloatField( label=_("Circumference - higher than (cm)"), widget=widgets.CentimeterMeterWidget, ) volume__lower = FloatField(label=_("Volume - lower than (l)")) volume__higher = FloatField(label=_("Volume - higher than (l)")) weight__lower = FloatField( label=_("Weight - lower than (g)"), widget=widgets.GramKilogramWidget ) weight__higher = FloatField( label=_("Weight - higher than (g)"), widget=widgets.GramKilogramWidget ) clutter_long_side__lower = FloatField( label=_("Clutter long side - lower than (cm)"), widget=widgets.CentimeterMeterWidget, ) clutter_long_side__higher = FloatField( label=_("Clutter long side - higher than (cm)"), widget=widgets.CentimeterMeterWidget, ) clutter_short_side__lower = FloatField( label=_("Clutter short side - lower than (cm)"), widget=widgets.CentimeterMeterWidget, ) clutter_short_side__higher = FloatField( label=_("Clutter short side - higher than (cm)"), widget=widgets.CentimeterMeterWidget, ) clutter_height__lower = FloatField( label=_("Clutter height - lower than (cm)"), widget=widgets.CentimeterMeterWidget, ) clutter_height__higher = FloatField( label=_("Clutter height - higher than (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__after = forms.DateField(label=_("Check date after"), widget=DatePicker) check_date__before = forms.DateField( label=_("Check date before"), widget=DatePicker ) integrities = forms.ChoiceField(label=_("Integrity"), choices=[]) remarkabilities = forms.ChoiceField(label=_("Remarkability"), choices=[]) conservatory_state = forms.ChoiceField(label=_("Conservatory state"), choices=[]) conservatory_comment = forms.CharField(label=_("Conservatory comment")) alterations = forms.ChoiceField(label=_("Alteration"), choices=[]) alteration_causes = forms.ChoiceField(label=_("Alteration cause"), choices=[]) preservation_to_considers = forms.ChoiceField( choices=[], label=_("Recommended treatments") ) treatment_emergency = forms.ChoiceField(choices=[], label=_("Treatment emergency")) estimated_value__higher = FloatField(label=_("Estimated value - higher than")) estimated_value__lower = FloatField(label=_("Estimated value - lower than")) insurance_value__higher = FloatField(label=_("Insurance value - higher than")) insurance_value__lower = FloatField(label=_("Insurance value - lower than")) appraisal_date__after = forms.DateField( label=_("Appraisal date after"), widget=DatePicker ) appraisal_date__before = forms.DateField( label=_("Appraisal date before"), widget=DatePicker ) loan = forms.NullBooleanField(label=_("Loan?")) treatments_file_end_date = forms.DateField( label=_("Treatment file end date before"), widget=DatePicker ) treatments_end_date = forms.DateField( label=_("Treatment end date before"), widget=DatePicker ) # 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_before = forms.DateField( label=_("Museum - Entry date (exact or start) - before"), widget=DatePicker ) museum_entry_date_after = forms.DateField( label=_("Museum - Entry date (exact or start) - after"), widget=DatePicker ) museum_entry_date_end_before = forms.DateField( label=_("Museum - Entry date end - before"), widget=DatePicker ) museum_entry_date_end_after = forms.DateField( label=_("Museum - Entry date end - after"), widget=DatePicker ) museum_entry_date_comment = forms.CharField(label=_("Museum - Comment on entry date")) museum_donor = forms.IntegerField( label=_("Museum - Donor, testator or vendor"), 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=_("Marking details")) museum_collection = 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_before = forms.IntegerField(label=_("Museum - Inventory entry year - before")) museum_inventory_entry_year_after = forms.IntegerField(label=_("Museum - Inventory entry year - after")) 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_before = forms.DateField( label=_("Museum - Date of allocation - before"), widget=DatePicker ) museum_allocation_date_after = forms.DateField( label=_("Museum - Date of allocation - after"), widget=DatePicker ) museum_purchase_price = forms.CharField(label=_("Museum - Purchase price")) TYPES = PeriodSelect.TYPES + [ FieldType("conservatory_state", models.ConservatoryState), FieldType("base_finds__batch", models.BatchType), FieldType("preservation_to_considers", models.TreatmentType), FieldType("integrities", models.IntegrityType), FieldType("remarkabilities", models.RemarkabilityType), FieldType("base_finds__context_record__town__areas", Area), FieldType( "base_finds__context_record__operation__operation_type", OperationType ), 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_collection", 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): # collection = forms.IntegerField( # label=_("Collection (warehouse)"), # widget=widgets.JQueryAutoComplete( # reverse_lazy('autocomplete-warehouse'), # associated_model=Warehouse), # validators=[valid_id(Warehouse)]) 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(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(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: user = kwargs.pop("user") self.is_admin = getattr(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, user): try: basket = ( models.FindBasket.objects.filter( Q(user=user) | Q(shared_with=user) | Q(shared_write_with=user) ) .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 user.user_ptr.is_superuser and not user.has_right("view_find") and not (user.has_right("view_own_find") and item.is_own(user)) ): raise PermissionDenied basket.items.add(item) return basket