diff options
Diffstat (limited to 'archaeological_finds')
-rw-r--r-- | archaeological_finds/admin.py | 22 | ||||
-rw-r--r-- | archaeological_finds/forms.py | 2 | ||||
-rw-r--r-- | archaeological_finds/migrations/0115_auto_20240208_1636.py | 432 | ||||
-rw-r--r-- | archaeological_finds/models.py | 102 | ||||
-rw-r--r-- | archaeological_finds/models_finds.py | 275 | ||||
-rw-r--r-- | archaeological_finds/templates/ishtar/sheet_find.html | 2 |
6 files changed, 758 insertions, 77 deletions
diff --git a/archaeological_finds/admin.py b/archaeological_finds/admin.py index 98c86141b..934089a7a 100644 --- a/archaeological_finds/admin.py +++ b/archaeological_finds/admin.py @@ -162,6 +162,18 @@ class FunctionalAreaAdmin(GeneralTypeAdmin): admin_site.register(models.FunctionalArea, FunctionalAreaAdmin) +@admin.register(models.TechnicalAreaType, site=admin_site) +class TechnicalAreaTypeAdmin(GeneralTypeAdmin): + model = models.TechnicalAreaType + autocomplete_fields = ("parent",) + + +@admin.register(models.TechnicalProcessType, site=admin_site) +class TechnicalProcessTypeAdmin(GeneralTypeAdmin): + model = models.TechnicalProcessType + autocomplete_fields = ("parent",) + + class MaterialTypeAdmin(GeneralTypeAdmin): search_fields = ('label', 'parent__label', 'comment',) model = models.MaterialType @@ -225,11 +237,11 @@ class TreatmentState(GeneralTypeAdmin): general_models = [ - models.RemarkabilityType, - models.IntegrityType, - models.BatchType, models.AlterationCauseType, models.AlterationType, - models.TreatmentEmergencyType, models.ObjectTypeQualityType, - models.MaterialTypeQualityType + models.AlterationCauseType, models.AlterationType, models.BatchType, + models.CollectionEntryModeType, models.IntegrityType, models.InventoryConformity, + models.InventoryMarkingPresence, models.MarkingType, models.MaterialTypeQualityType, + models.MuseumCollection, models.ObjectTypeQualityType, models.OriginalReproduction, + models.RemarkabilityType, models.TreatmentEmergencyType, ] for model in general_models: diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py index 691383cc6..460e34375 100644 --- a/archaeological_finds/forms.py +++ b/archaeological_finds/forms.py @@ -277,7 +277,7 @@ class BasicFindForm(CustomForm, ManageOldType): ) denomination = forms.CharField(label=_("Denomination"), required=False) previous_id = forms.CharField(label=_("Previous ID"), required=False) - museum_id = forms.CharField(label=_("Museum inventory number"), required=False) + museum_id = forms.CharField(label=_("Museum ID"), required=False) laboratory_id = forms.CharField(label=_("Laboratory ID"), required=False) seal_number = forms.CharField(label=_("Seal number"), required=False) mark = forms.CharField(label=_("Mark"), required=False) diff --git a/archaeological_finds/migrations/0115_auto_20240208_1636.py b/archaeological_finds/migrations/0115_auto_20240208_1636.py new file mode 100644 index 000000000..3c39093a6 --- /dev/null +++ b/archaeological_finds/migrations/0115_auto_20240208_1636.py @@ -0,0 +1,432 @@ +# Generated by Django 2.2.24 on 2024-02-08 16:36 + +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion +import ishtar_common.models_common +import re + + +class Migration(migrations.Migration): + + dependencies = [ + ('ishtar_common', '0236_auto_20240208_1635'), + ('archaeological_finds', '0114_auto_20231115_1617'), + ] + + operations = [ + migrations.CreateModel( + name='InventoryConformity', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('label', models.TextField(verbose_name='Label')), + ('txt_idx', models.TextField(help_text='The slug is the standardized version of the name. It contains only lowercase letters, numbers and hyphens. Each slug must be unique.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens.", 'invalid')], verbose_name='Textual ID')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('available', models.BooleanField(default=True, verbose_name='Available')), + ('order', models.IntegerField(default=10, verbose_name='Order')), + ], + options={ + 'verbose_name': 'Inventory conformity type', + 'verbose_name_plural': 'Inventory conformity types', + 'ordering': ('order', 'label'), + }, + bases=(ishtar_common.models_common.Cached, models.Model), + ), + migrations.CreateModel( + name='InventoryMarkingPresence', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('label', models.TextField(verbose_name='Label')), + ('txt_idx', models.TextField(help_text='The slug is the standardized version of the name. It contains only lowercase letters, numbers and hyphens. Each slug must be unique.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens.", 'invalid')], verbose_name='Textual ID')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('available', models.BooleanField(default=True, verbose_name='Available')), + ('order', models.IntegerField(default=10, verbose_name='Order')), + ], + options={ + 'verbose_name': 'Presence of inventory marking type', + 'verbose_name_plural': 'Presence of inventory marking types', + 'ordering': ('order', 'label'), + }, + bases=(ishtar_common.models_common.Cached, models.Model), + ), + migrations.CreateModel( + name='MarkingType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('label', models.TextField(verbose_name='Label')), + ('txt_idx', models.TextField(help_text='The slug is the standardized version of the name. It contains only lowercase letters, numbers and hyphens. Each slug must be unique.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens.", 'invalid')], verbose_name='Textual ID')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('available', models.BooleanField(default=True, verbose_name='Available')), + ('order', models.IntegerField(default=10, verbose_name='Order')), + ], + options={ + 'verbose_name': 'Marking type', + 'verbose_name_plural': 'Marking types', + 'ordering': ('order', 'label'), + }, + bases=(ishtar_common.models_common.Cached, models.Model), + ), + migrations.CreateModel( + name='MuseumCollection', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('label', models.TextField(verbose_name='Label')), + ('txt_idx', models.TextField(help_text='The slug is the standardized version of the name. It contains only lowercase letters, numbers and hyphens. Each slug must be unique.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens.", 'invalid')], verbose_name='Textual ID')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('available', models.BooleanField(default=True, verbose_name='Available')), + ('order', models.IntegerField(default=10, verbose_name='Order')), + ], + options={ + 'verbose_name': 'Museum collection', + 'verbose_name_plural': 'Museum collections', + 'ordering': ('order', 'label'), + }, + bases=(ishtar_common.models_common.Cached, models.Model), + ), + migrations.CreateModel( + name='OriginalReproduction', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('label', models.TextField(verbose_name='Label')), + ('txt_idx', models.TextField(help_text='The slug is the standardized version of the name. It contains only lowercase letters, numbers and hyphens. Each slug must be unique.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens.", 'invalid')], verbose_name='Textual ID')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('available', models.BooleanField(default=True, verbose_name='Available')), + ('order', models.IntegerField(default=10, verbose_name='Order')), + ], + options={ + 'verbose_name': 'Original/reproduction type', + 'verbose_name_plural': 'Original/reproduction types', + 'ordering': ('order', 'label'), + }, + bases=(ishtar_common.models_common.Cached, models.Model), + ), + migrations.AddField( + model_name='find', + name='cache_complete_museum_id', + field=models.TextField(blank=True, db_index=True, default='', help_text='Cached value - do not edit', verbose_name='Complete museum ID'), + ), + migrations.AddField( + model_name='find', + name='museum_allocation_date', + field=models.DateField(blank=True, null=True, verbose_name='Date of museum allocation'), + ), + migrations.AddField( + model_name='find', + name='museum_custodian_institution', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='deposited', to='ishtar_common.Organization', verbose_name='Custodian institution'), + ), + migrations.AddField( + model_name='find', + name='museum_depositor_inventory_number', + field=models.TextField(blank=True, default='', verbose_name='Depositor inventory number'), + ), + migrations.AddField( + model_name='find', + name='museum_donor', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='has_provided', to='ishtar_common.BiographicalNote', verbose_name='Donor, testator or vendor'), + ), + migrations.AddField( + model_name='find', + name='museum_entry_date', + field=models.DateField(blank=True, null=True, verbose_name='Museum entry date (exact or start)'), + ), + migrations.AddField( + model_name='find', + name='museum_entry_date_comment', + field=models.TextField(blank=True, default='', verbose_name='Comment on museum entry date'), + ), + migrations.AddField( + model_name='find', + name='museum_entry_date_end', + field=models.DateField(blank=True, null=True, verbose_name='Museum entry date (end)'), + ), + migrations.AddField( + model_name='find', + name='museum_entry_mode_comment', + field=models.TextField(blank=True, default='', verbose_name='Comment on museum entry mode'), + ), + migrations.AddField( + model_name='find', + name='museum_former_collection', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='ishtar_common.BiographicalNote', verbose_name='Former collection'), + ), + migrations.AddField( + model_name='find', + name='museum_id_comment', + field=models.TextField(blank=True, default='', verbose_name='Comment on museum ID'), + ), + migrations.AddField( + model_name='find', + name='museum_id_prefix', + field=models.TextField(blank=True, default='', verbose_name='Museum ID prefix'), + ), + migrations.AddField( + model_name='find', + name='museum_id_suffix', + field=models.TextField(blank=True, default='', verbose_name='Museum ID suffix'), + ), + migrations.AddField( + model_name='find', + name='museum_inventory_entry_year', + field=models.PositiveIntegerField(blank=True, null=True, verbose_name='Inventory entry year'), + ), + migrations.AddField( + model_name='find', + name='museum_inventory_transcript', + field=models.TextField(blank=True, default='', verbose_name='Inventory transcript'), + ), + migrations.AddField( + model_name='find', + name='museum_marking_comment', + field=models.TextField(blank=True, default='', verbose_name='Comment on marking'), + ), + migrations.AddField( + model_name='find', + name='museum_non_conformity_comment', + field=models.TextField(blank=True, default='', verbose_name='Comment of non-conformity'), + ), + migrations.AddField( + model_name='find', + name='museum_owner_institution', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='owns', to='ishtar_common.Organization', verbose_name='Owner institution'), + ), + migrations.AddField( + model_name='find', + name='museum_purchase_price', + field=models.TextField(blank=True, default='', verbose_name='Purchase price'), + ), + migrations.AddField( + model_name='find', + name='quantity_comment', + field=models.TextField(blank=True, default='', verbose_name='Comment on quantity'), + ), + migrations.AddField( + model_name='historicalfind', + name='cache_complete_museum_id', + field=models.TextField(blank=True, db_index=True, default='', help_text='Cached value - do not edit', verbose_name='Complete museum ID'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_allocation_date', + field=models.DateField(blank=True, null=True, verbose_name='Date of museum allocation'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_custodian_institution', + field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='ishtar_common.Organization', verbose_name='Custodian institution'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_depositor_inventory_number', + field=models.TextField(blank=True, default='', verbose_name='Depositor inventory number'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_donor', + field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='ishtar_common.BiographicalNote', verbose_name='Donor, testator or vendor'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_entry_date', + field=models.DateField(blank=True, null=True, verbose_name='Museum entry date (exact or start)'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_entry_date_comment', + field=models.TextField(blank=True, default='', verbose_name='Comment on museum entry date'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_entry_date_end', + field=models.DateField(blank=True, null=True, verbose_name='Museum entry date (end)'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_entry_mode_comment', + field=models.TextField(blank=True, default='', verbose_name='Comment on museum entry mode'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_former_collection', + field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='ishtar_common.BiographicalNote', verbose_name='Former collection'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_id_comment', + field=models.TextField(blank=True, default='', verbose_name='Comment on museum ID'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_id_prefix', + field=models.TextField(blank=True, default='', verbose_name='Museum ID prefix'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_id_suffix', + field=models.TextField(blank=True, default='', verbose_name='Museum ID suffix'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_inventory_entry_year', + field=models.PositiveIntegerField(blank=True, null=True, verbose_name='Inventory entry year'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_inventory_transcript', + field=models.TextField(blank=True, default='', verbose_name='Inventory transcript'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_marking_comment', + field=models.TextField(blank=True, default='', verbose_name='Comment on marking'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_non_conformity_comment', + field=models.TextField(blank=True, default='', verbose_name='Comment of non-conformity'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_owner_institution', + field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='ishtar_common.Organization', verbose_name='Owner institution'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_purchase_price', + field=models.TextField(blank=True, default='', verbose_name='Purchase price'), + ), + migrations.AddField( + model_name='historicalfind', + name='quantity_comment', + field=models.TextField(blank=True, default='', verbose_name='Comment on quantity'), + ), + migrations.AlterField( + model_name='find', + name='functional_areas', + field=models.ManyToManyField(blank=True, related_name='find', to='archaeological_finds.FunctionalArea', verbose_name='Functional areas'), + ), + migrations.AlterField( + model_name='find', + name='museum_id', + field=models.TextField(blank=True, default='', verbose_name='Museum ID'), + ), + migrations.AlterField( + model_name='historicalfind', + name='museum_id', + field=models.TextField(blank=True, default='', verbose_name='Museum ID'), + ), + migrations.CreateModel( + name='TechnicalProcessType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('label', models.TextField(verbose_name='Label')), + ('txt_idx', models.TextField(help_text='The slug is the standardized version of the name. It contains only lowercase letters, numbers and hyphens. Each slug must be unique.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens.", 'invalid')], verbose_name='Textual ID')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('available', models.BooleanField(default=True, verbose_name='Available')), + ('order', models.IntegerField(default=10, verbose_name='Order')), + ('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='archaeological_finds.TechnicalProcessType', verbose_name='Parent')), + ], + options={ + 'verbose_name': 'Technical process type', + 'verbose_name_plural': 'Technical process types', + 'ordering': ('order', 'parent__label', 'label'), + }, + bases=(ishtar_common.models_common.Cached, models.Model), + ), + migrations.CreateModel( + name='TechnicalAreaType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('label', models.TextField(verbose_name='Label')), + ('txt_idx', models.TextField(help_text='The slug is the standardized version of the name. It contains only lowercase letters, numbers and hyphens. Each slug must be unique.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens.", 'invalid')], verbose_name='Textual ID')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('available', models.BooleanField(default=True, verbose_name='Available')), + ('order', models.IntegerField(default=10, verbose_name='Order')), + ('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='archaeological_finds.TechnicalAreaType', verbose_name='Parent')), + ], + options={ + 'verbose_name': 'Technical area type', + 'verbose_name_plural': 'Technical area types', + 'ordering': ('order', 'parent__label', 'label'), + }, + bases=(ishtar_common.models_common.Cached, models.Model), + ), + migrations.CreateModel( + name='CollectionEntryModeType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('label', models.TextField(verbose_name='Label')), + ('txt_idx', models.TextField(help_text='The slug is the standardized version of the name. It contains only lowercase letters, numbers and hyphens. Each slug must be unique.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens.", 'invalid')], verbose_name='Textual ID')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('available', models.BooleanField(default=True, verbose_name='Available')), + ('order', models.IntegerField(default=10, verbose_name='Order')), + ('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='archaeological_finds.CollectionEntryModeType', verbose_name='Parent')), + ], + options={ + 'verbose_name': 'Collection entry mode type', + 'verbose_name_plural': 'Collection entry mode types', + 'ordering': ('order', 'parent__label', 'label'), + }, + bases=(ishtar_common.models_common.Cached, models.Model), + ), + migrations.AddField( + model_name='find', + name='museum_collection', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='current_collection_of', to='archaeological_finds.MuseumCollection', verbose_name='Collection'), + ), + migrations.AddField( + model_name='find', + name='museum_collection_entry_mode', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='archaeological_finds.CollectionEntryModeType', verbose_name='Collections entry mode'), + ), + migrations.AddField( + model_name='find', + name='museum_inventory_conformity', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='archaeological_finds.InventoryConformity', verbose_name='Conformity with inventory'), + ), + migrations.AddField( + model_name='find', + name='museum_inventory_marking_presence', + field=models.ManyToManyField(blank=True, related_name='finds', to='archaeological_finds.InventoryMarkingPresence', verbose_name='Presence of inventory marking'), + ), + migrations.AddField( + model_name='find', + name='museum_marking_type', + field=models.ManyToManyField(blank=True, related_name='finds', to='archaeological_finds.MarkingType', verbose_name='Type of marking'), + ), + migrations.AddField( + model_name='find', + name='museum_original_repro', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='archaeological_finds.OriginalReproduction', verbose_name='Original/reproduction'), + ), + migrations.AddField( + model_name='find', + name='technical_areas', + field=models.ManyToManyField(blank=True, related_name='find', to='archaeological_finds.TechnicalAreaType', verbose_name='Technical areas'), + ), + migrations.AddField( + model_name='find', + name='technical_processes', + field=models.ManyToManyField(blank=True, related_name='find', to='archaeological_finds.TechnicalProcessType', verbose_name='Technical processes'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_collection', + field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='archaeological_finds.MuseumCollection', verbose_name='Collection'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_collection_entry_mode', + field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='archaeological_finds.CollectionEntryModeType', verbose_name='Collections entry mode'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_inventory_conformity', + field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='archaeological_finds.InventoryConformity', verbose_name='Conformity with inventory'), + ), + migrations.AddField( + model_name='historicalfind', + name='museum_original_repro', + field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='archaeological_finds.OriginalReproduction', verbose_name='Original/reproduction'), + ), + ] diff --git a/archaeological_finds/models.py b/archaeological_finds/models.py index c8c526d2f..052e493a4 100644 --- a/archaeological_finds/models.py +++ b/archaeological_finds/models.py @@ -1,71 +1,87 @@ from archaeological_finds.models_finds import ( - MaterialType, - ConservatoryState, - CheckedType, - IntegrityType, - RemarkabilityType, - ObjectType, - BaseFind, - FindBasket, - Find, - Property, + AlterationType, + AlterationCauseType, BatchType, + BaseFind, BFBulkView, + CheckedType, + CollectionEntryModeType, + CommunicabilityType, + ConservatoryState, FBulkView, + Find, + FindBasket, + FindInsideContainer, FirstBaseFindView, - AlterationType, - AlterationCauseType, - TreatmentEmergencyType, - TreatmentType, - CommunicabilityType, + FunctionalArea, + IntegrityType, + InventoryConformity, + InventoryMarkingPresence, + MarkingType, + MaterialType, MaterialTypeQualityType, + MuseumCollection, + ObjectType, ObjectTypeQualityType, - FindInsideContainer, - FunctionalArea, + OriginalReproduction, + Property, + RemarkabilityType, + TechnicalAreaType, + TechnicalProcessType, + TreatmentEmergencyType, + TreatmentType, ) from archaeological_finds.models_treatments import ( - Treatment, AbsFindTreatments, - FindUpstreamTreatments, + Treatment, FindDownstreamTreatments, + FindNonModifTreatments, FindTreatments, + FindUpstreamTreatments, TreatmentFile, TreatmentFileType, TreatmentState, - FindNonModifTreatments, ) __all__ = [ - "MaterialType", - "ConservatoryState", - "IntegrityType", - "CheckedType", - "RemarkabilityType", - "ObjectType", + "AbsFindTreatments", + "AlterationType", + "AlterationCauseType", "BaseFind", - "FindBasket", - "Find", - "Property", + "BatchType", "BFBulkView", + "CheckedType", + "CollectionEntryModeType", + "CommunicabilityType", + "ConservatoryState", "FBulkView", + "Find", "FirstBaseFindView", - "AlterationType", - "AlterationCauseType", - "TreatmentEmergencyType", - "BatchType", - "TreatmentType", - "TreatmentState", - "Treatment", - "AbsFindTreatments", - "FindUpstreamTreatments", - "FindNonModifTreatments", + "FindBasket", "FindDownstreamTreatments", + "FindInsideContainer", + "FindNonModifTreatments", "FindTreatments", + "FindUpstreamTreatments", "FunctionalArea", - "TreatmentFile", - "TreatmentFileType", - "CommunicabilityType", + "IntegrityType", + "InventoryConformity", + "InventoryMarkingPresence", + "MarkingType", + "MaterialType", "MaterialTypeQualityType", + "MuseumCollection", + "ObjectType", "ObjectTypeQualityType", - "FindInsideContainer", + "OriginalReproduction", + "Property", + "RemarkabilityType", + "TechnicalAreaType", + "TechnicalProcessType", + "Treatment", + "TreatmentEmergencyType", + "TreatmentFile", + "TreatmentFileType", + "TreatmentType", + "TreatmentState", ] diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py index f41b388e7..96f3ded64 100644 --- a/archaeological_finds/models_finds.py +++ b/archaeological_finds/models_finds.py @@ -25,48 +25,52 @@ from django.apps import apps from django.conf import settings from django.contrib.gis.db import models from django.contrib.postgres.indexes import GinIndex -from django.db import connection from django.db.models import Max, Q, F from django.db.models.signals import m2m_changed, post_save, post_delete, pre_delete from django.core.exceptions import ObjectDoesNotExist from django.urls import reverse -from ishtar_common.utils import ugettext_lazy as _, pgettext_lazy from ishtar_common.data_importer import post_importer_action, ImporterError from ishtar_common.utils import ( cached_label_changed, - post_save_geo, + get_generated_id, m2m_historization_changed, + pgettext_lazy, + post_save_geo, + ugettext_lazy as _ ) from ishtar_common.alternative_configs import ALTERNATE_CONFIGS -from ishtar_common.model_managers import ExternalIdManager, UUIDModelManager +from ishtar_common.model_managers import UUIDModelManager from ishtar_common.models import ( + BaseHistorizedItem, + Basket, + BiographicalNote, + BulkUpdatedItem, + CompleteIdentifierItem, Document, + DocumentItem, + document_attached_changed, GeneralType, + GeoItem, + get_current_profile, HierarchicalType, - BaseHistorizedItem, + HistoryModel, + Imported, + IshtarSiteProfile, LightHistorizedItem, + MainItem, + OrderedHierarchicalType, + OrderedType, + Organization, OwnPerms, - Imported, Person, - Basket, post_save_cache, - ValueGetter, - get_current_profile, - IshtarSiteProfile, - BulkUpdatedItem, QuickAction, - MainItem, - document_attached_changed, - HistoryModel, - DynamicRequest, SearchAltName, - CompleteIdentifierItem, SearchVectorConfig, - DocumentItem, - GeoItem + ValueGetter, ) from ishtar_common.models_common import HistoricalRecords, SerializeItem, \ GeoVectorData, geodata_attached_changed @@ -296,6 +300,38 @@ post_save.connect(post_save_cache, sender=FunctionalArea) post_delete.connect(post_save_cache, sender=FunctionalArea) +class TechnicalAreaType(OrderedHierarchicalType): + class Meta: + verbose_name = _("Technical area type") + verbose_name_plural = _("Technical area types") + ordering = ( + "order", + "parent__label", + "label", + ) + ADMIN_SECTION = _("Finds") + + +post_save.connect(post_save_cache, sender=TechnicalAreaType) +post_delete.connect(post_save_cache, sender=TechnicalAreaType) + + +class TechnicalProcessType(OrderedHierarchicalType): + class Meta: + verbose_name = _("Technical process type") + verbose_name_plural = _("Technical process types") + ordering = ( + "order", + "parent__label", + "label", + ) + ADMIN_SECTION = _("Finds") + + +post_save.connect(post_save_cache, sender=TechnicalProcessType) +post_delete.connect(post_save_cache, sender=TechnicalProcessType) + + class ObjectTypeQualityType(GeneralType): order = models.IntegerField(_("Order"), default=10) @@ -381,6 +417,99 @@ post_save.connect(post_save_cache, sender=CheckedType) post_delete.connect(post_save_cache, sender=CheckedType) +class CollectionEntryModeType(OrderedHierarchicalType): + class Meta: + verbose_name = _("Collection entry mode type") + verbose_name_plural = _("Collection entry mode types") + ordering = ( + "order", + "parent__label", + "label", + ) + ADMIN_SECTION = _("Museum") + + +post_save.connect(post_save_cache, sender=CollectionEntryModeType) +post_delete.connect(post_save_cache, sender=CollectionEntryModeType) + + +class InventoryMarkingPresence(OrderedType): + class Meta: + verbose_name = _("Presence of inventory marking type") + verbose_name_plural = _("Presence of inventory marking types") + ordering = ( + "order", + "label", + ) + ADMIN_SECTION = _("Museum") + + +post_save.connect(post_save_cache, sender=InventoryMarkingPresence) +post_delete.connect(post_save_cache, sender=InventoryMarkingPresence) + + +class MarkingType(OrderedType): + class Meta: + verbose_name = _("Marking type") + verbose_name_plural = _("Marking types") + ordering = ( + "order", + "label", + ) + ADMIN_SECTION = _("Museum") + + +post_save.connect(post_save_cache, sender=MarkingType) +post_delete.connect(post_save_cache, sender=MarkingType) + + +class MuseumCollection(OrderedType): + class Meta: + verbose_name = _("Museum collection") + verbose_name_plural = _("Museum collections") + ordering = ( + "order", + "label", + ) + ADMIN_SECTION = _("Museum") + + +post_save.connect(post_save_cache, sender=MuseumCollection) +post_delete.connect(post_save_cache, sender=MuseumCollection) + + +class InventoryConformity(OrderedType): + class Meta: + verbose_name = _("Inventory conformity type") + verbose_name_plural = _("Inventory conformity types") + ordering = ( + "order", + "label", + ) + ADMIN_SECTION = _("Museum") + + +post_save.connect(post_save_cache, sender=InventoryConformity) +post_delete.connect(post_save_cache, sender=InventoryConformity) + + +class OriginalReproduction(OrderedType): + class Meta: + verbose_name = _("Original/reproduction type") + verbose_name_plural = _("Original/reproduction types") + ordering = ( + "order", + "label", + ) + ADMIN_SECTION = _("Museum") + + +post_save.connect(post_save_cache, sender=OriginalReproduction) +post_delete.connect(post_save_cache, sender=OriginalReproduction) + + + + class BFBulkView(object): CREATE_SQL = """ CREATE VIEW basefind_cached_bulk_update @@ -1549,6 +1678,7 @@ class Find( PARENT_ONLY_SEARCH_VECTORS = ["container"] BASE_SEARCH_VECTORS = [ SearchVectorConfig("cached_label", "raw"), + SearchVectorConfig("cache_complete_museum_id", "raw"), SearchVectorConfig("label", "raw"), SearchVectorConfig("description", "local"), SearchVectorConfig("mark"), @@ -1667,6 +1797,7 @@ class Find( "alteration_causes", ] CACHED_LABELS = [ + "cache_complete_museum_id", "cached_label", "cached_periods", "cached_object_types", @@ -1702,7 +1833,11 @@ class Find( order = models.IntegerField(_("Order"), default=1) label = models.TextField(_("Free ID")) denomination = models.TextField(_("Denomination"), blank=True, default="") - museum_id = models.TextField(_("Museum inventory number"), blank=True, default="") + # museum module IDs + museum_id_prefix = models.TextField(_("Museum ID prefix"), blank=True, default="") + museum_id = models.TextField(_("Museum ID"), blank=True, default="") + museum_id_suffix = models.TextField(_("Museum ID suffix"), blank=True, default="") + museum_id_comment = models.TextField(_("Comment on museum ID"), blank=True, default="") laboratory_id = models.TextField(_("Laboratory ID"), blank=True, default="") description = models.TextField(_("Description"), blank=True, default="") decoration = models.TextField(_("Decoration"), blank=True, default="") @@ -1730,6 +1865,12 @@ class Find( _("Weight unit"), max_length=4, blank=True, null=True, choices=WEIGHT_UNIT ) find_number = models.IntegerField(_("Number of remains"), blank=True, null=True) + min_number_of_individuals = models.IntegerField( + _("Minimum number of individuals (MNI)"), blank=True, null=True + ) + quantity_comment = models.TextField( + _("Comment on quantity"), blank=True, default="" + ) upstream_treatment = models.ForeignKey( "Treatment", blank=True, @@ -1782,7 +1923,19 @@ class Find( ) functional_areas = models.ManyToManyField( FunctionalArea, - verbose_name=_("Functional area"), + verbose_name=_("Functional areas"), + related_name="find", + blank=True, + ) + technical_areas = models.ManyToManyField( + TechnicalAreaType, + verbose_name=_("Technical areas"), + related_name="find", + blank=True, + ) + technical_processes = models.ManyToManyField( + TechnicalProcessType, + verbose_name=_("Technical processes"), related_name="find", blank=True, ) @@ -1804,9 +1957,6 @@ class Find( related_name="find", blank=True, ) - min_number_of_individuals = models.IntegerField( - _("Minimum number of individuals (MNI)"), blank=True, null=True - ) length = models.FloatField(_("Length (cm)"), blank=True, null=True) width = models.FloatField(_("Width (cm)"), blank=True, null=True) height = models.FloatField(_("Height (cm)"), blank=True, null=True) @@ -1840,14 +1990,72 @@ class Find( check_date = models.DateField(_("Check date"), default=datetime.date.today) estimated_value = models.FloatField(_("Estimated value"), blank=True, null=True) collection = models.ForeignKey( - "archaeological_warehouse.Warehouse", + "archaeological_warehouse.Warehouse", blank=True, null=True, on_delete=models.SET_NULL, + related_name="finds", verbose_name=_("Collection"), + help_text=_("Do not use - need evolutions"), + ) + # museum module + museum_owner_institution = models.ForeignKey( + Organization, blank=True, null=True, on_delete=models.SET_NULL, + related_name="owns", + verbose_name=_("Owner institution"), + ) + museum_custodian_institution = models.ForeignKey( + Organization, blank=True, null=True, on_delete=models.SET_NULL, + related_name="deposited", + verbose_name=_("Custodian institution"), + ) + museum_depositor_inventory_number = models.TextField(_("Depositor inventory number"), blank=True, default="") + museum_collection_entry_mode = models.ForeignKey( + CollectionEntryModeType, blank=True, null=True, on_delete=models.SET_NULL, + verbose_name=_("Collections entry mode"), + ) + museum_entry_mode_comment = models.TextField(_("Comment on museum entry mode"), blank=True, default="") + museum_entry_date = models.DateField(_("Museum entry date (exact or start)"), blank=True, null=True) + museum_entry_date_end = models.DateField(_("Museum entry date (end)"), blank=True, null=True) + museum_entry_date_comment = models.TextField(_("Comment on museum entry date"), blank=True, default="") + museum_donor = models.ForeignKey( + BiographicalNote, blank=True, null=True, on_delete=models.SET_NULL, + related_name='has_provided', + verbose_name=_("Donor, testator or vendor"), + ) + museum_inventory_marking_presence = models.ManyToManyField( + InventoryMarkingPresence, blank=True, + related_name="finds", + verbose_name=_("Presence of inventory marking"), + ) + museum_marking_type = models.ManyToManyField( + MarkingType, + verbose_name=_("Type of marking"), blank=True, - null=True, related_name="finds", - on_delete=models.SET_NULL, - help_text=_("Do not use - need evolutions"), ) + museum_marking_comment = models.TextField(_("Comment on marking"), blank=True, default="") + museum_collection = models.ForeignKey( + MuseumCollection, blank=True, null=True, on_delete=models.SET_NULL, + related_name='current_collection_of', + verbose_name=_("Collection"), + ) + museum_former_collection = models.ForeignKey( + BiographicalNote, blank=True, null=True, on_delete=models.SET_NULL, + verbose_name=_("Former collection"), + ) + museum_inventory_entry_year = models.PositiveIntegerField( + _("Inventory entry year"), blank=True, null=True + ) + museum_inventory_conformity = models.ForeignKey( + InventoryConformity, blank=True, null=True, on_delete=models.SET_NULL, + verbose_name=_("Conformity with inventory"), + ) + museum_non_conformity_comment = models.TextField(_("Comment of non-conformity"), blank=True, default="") + museum_inventory_transcript = models.TextField(_("Inventory transcript"), blank=True, default="") + museum_original_repro = models.ForeignKey( + OriginalReproduction, blank=True, null=True, on_delete=models.SET_NULL, + verbose_name=_("Original/reproduction"), + ) + museum_allocation_date = models.DateField(_("Date of museum allocation"), blank=True, null=True) + museum_purchase_price = models.TextField(_("Purchase price"), blank=True, default="") # preservation module conservatory_state = models.ForeignKey( @@ -1923,6 +2131,13 @@ class Find( default="", help_text=_("Generated automatically - do not edit"), ) + cache_complete_museum_id = models.TextField( + _("Complete museum ID"), + blank=True, + default="", + db_index=True, + help_text=_("Cached value - do not edit"), + ) history = HistoricalRecords(bases=[HistoryModel]) BASKET_MODEL = FindBasket @@ -2584,6 +2799,12 @@ class Find( return "-" return self.base_finds.all()[0].cached_label + def complete_museum_id(self): + return self.cache_complete_museum_id + + def _generate_cache_complete_museum_id(self): + return get_generated_id("find_complete_museum_id", self) or "" + def _generate_cached_periods(self): return " & ".join([dating.period.label for dating in self.datings.all()]) diff --git a/archaeological_finds/templates/ishtar/sheet_find.html b/archaeological_finds/templates/ishtar/sheet_find.html index 076c20c47..fdbc0c6c1 100644 --- a/archaeological_finds/templates/ishtar/sheet_find.html +++ b/archaeological_finds/templates/ishtar/sheet_find.html @@ -158,7 +158,7 @@ {% field_flex "Free ID" item.label %} {% field_flex "Previous ID" item.previous_id %} {% field_flex "Excavation ID" item.excavation_ids %} - {% field_flex "Museum inventory number" item.museum_id %} + {% field_flex "Museum ID" item.museum_id %} {% field_flex "Laboratory ID" item.laboratory_id %} {% field_flex "Seal number" item.seal_number %} {% trans "Administrative index" as admin_index_label %} |