diff options
Diffstat (limited to 'archaeological_finds')
37 files changed, 5424 insertions, 1262 deletions
diff --git a/archaeological_finds/admin.py b/archaeological_finds/admin.py index 1513c7eeb..45050eb2e 100644 --- a/archaeological_finds/admin.py +++ b/archaeological_finds/admin.py @@ -156,8 +156,13 @@ admin_site.register(models.CommunicabilityType, HierarchicalTypeAdmin) class TreatmentTypeAdmin(GeneralTypeAdmin): - list_display = HierarchicalTypeAdmin.list_display + [ - 'order', 'virtual', 'upstream_is_many', 'downstream_is_many'] + list_display = HierarchicalTypeAdmin.list_display[:-1] + ['order'] + \ + [HierarchicalTypeAdmin.list_display[-1]] + list_filter = [ + 'virtual', 'destructive', 'create_new_find', 'upstream_is_many', + 'downstream_is_many', 'destructive', 'change_reference_location', + 'change_current_location', 'restore_reference_location' + ] model = models.TreatmentType @@ -177,10 +182,19 @@ class ConservatoryStateAdmin(GeneralTypeAdmin): list_display = GeneralTypeAdmin.list_display + ['order'] +@admin.register(models.TreatmentFileType, site=admin_site) +class TreatmentFileType(GeneralTypeAdmin): + list_display = GeneralTypeAdmin.list_display + ["treatment_type"] + + +@admin.register(models.TreatmentState, site=admin_site) +class TreatmentState(GeneralTypeAdmin): + list_display = GeneralTypeAdmin.list_display[:-1] + ["order", "executed"] + + general_models = [ models.RemarkabilityType, models.IntegrityType, - models.TreatmentFileType, models.TreatmentState, models.BatchType, models.AlterationCauseType, models.AlterationType, models.TreatmentEmergencyType, models.ObjectTypeQualityType, models.MaterialTypeQualityType diff --git a/archaeological_finds/fixtures/initial_data-fr.json b/archaeological_finds/fixtures/initial_data-fr.json index a346da9ab..3125ab8da 100644 --- a/archaeological_finds/fixtures/initial_data-fr.json +++ b/archaeological_finds/fixtures/initial_data-fr.json @@ -890,6 +890,38 @@ } }, { + "model": "archaeological_finds.treatmenttype", + "fields": { + "label": "Pr\u00eat", + "txt_idx": "loan", + "comment": "Un pr\u00eat est un changement temporaire de contenant pour du mobilier.", + "available": true, + "parent": null, + "order": 10, + "virtual": false, + "destructive": false, + "create_new_find": false, + "upstream_is_many": false, + "downstream_is_many": false + } +}, +{ + "model": "archaeological_finds.treatmenttype", + "fields": { + "label": "Retour de pr\u00eat", + "txt_idx": "loan-return", + "comment": "Retour de mobilier dans son contenant de r\u00e9f\u00e9rence.", + "available": true, + "parent": null, + "order": 10, + "virtual": false, + "destructive": false, + "create_new_find": false, + "upstream_is_many": false, + "downstream_is_many": false + } +}, +{ "model": "archaeological_finds.treatmentstate", "fields": { "label": "Pr\u00e9vu", diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py index 5ca8618d5..ae592d013 100644 --- a/archaeological_finds/forms.py +++ b/archaeological_finds/forms.py @@ -43,8 +43,8 @@ from archaeological_finds.forms_treatments import TreatmentSelect, \ AdministrativeActTreatmentFileForm, \ AdministrativeActTreatmentFileFormSelection, \ AdministrativeActTreatmentFileModifForm, \ - DashboardForm as DashboardTreatmentForm, \ - DashboardTreatmentFileForm, QAFindTreatmentForm + DashboardForm as DashboardTreatmentForm, N1TreatmentForm,\ + DashboardTreatmentFileForm, QAFindTreatmentForm, OneNTreatmentForm from archaeological_operations.models import Period, ArchaeologicalSite, \ RelationType as OpeRelationType from archaeological_operations.widgets import OAWidget @@ -53,10 +53,11 @@ 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, HistorySelect + ManageOldType, FieldType, IshtarForm, FormHeader, QAForm, HistorySelect, \ + PkWizardSearch from ishtar_common.forms_common import get_town_field from ishtar_common.models import valid_id, valid_ids, get_current_profile, \ - SpatialReferenceSystem, Area, OperationType + SpatialReferenceSystem, Area, OperationType, IshtarUser from ishtar_common.utils import convert_coordinates_to_point __all__ = [ @@ -71,17 +72,21 @@ __all__ = [ 'AdministrativeActTreatmentFormSelection', 'AdministrativeActTreatmentFileModifForm', 'DashboardTreatmentForm', 'DashboardTreatmentFileForm', - 'RecordFormSelection', 'FindForm', 'DateForm', 'DatingFormSet', - 'PreservationForm', 'FindBasketFormSelection', 'FindBasketForm', - 'FindSelect', 'FindFormSelection', 'FindFormSelectionWarehouseModule', - 'MultipleFindFormSelection', 'MultipleFindFormSelectionWarehouseModule', - 'FindMultipleFormSelection', 'check_form', 'check_exist', 'check_not_exist', + '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', 'DeleteFindBasketForm', 'FindBasketAddItemForm', + 'SelectFindBasketForm', 'FindBasketAddItemForm', 'QAFindFormSingle', 'QAFindFormMulti', 'QAFindBasketForm', - 'QAFindTreatmentForm' + 'QAFindTreatmentForm', 'QAFindbasketDuplicateForm', + 'N1TreatmentForm', 'OneNTreatmentForm', 'ResultingFindForm', + 'ResultingFindsForm', 'SingleUpstreamFindFormSelection' ] logger = logging.getLogger(__name__) @@ -121,23 +126,33 @@ class RecordFormSelection(CustomForm, forms.Form): cr.operation.pk) -class FindForm(CustomForm, ManageOldType): +class BaseFindForm(CustomForm, ManageOldType): + """ + Base find form with no field related to base_find + """ file_upload = True form_label = _("Find") - form_admin_name = _(u"Find - 020 - General") - form_slug = "find-020-general" - base_models = ['get_first_base_find', 'object_type', 'material_type', - 'communicabilitie'] + form_admin_name = _(u"Simple find - 020 - General") + form_slug = "simplefind-020-general" + base_models = ['object_type', 'material_type', 'communicabilitie'] associated_models = { 'material_type': models.MaterialType, 'object_type': models.ObjectType, 'communicabilitie': models.CommunicabilityType, - 'get_first_base_find__batch': models.BatchType, - 'get_first_base_find__spatial_reference_system': SpatialReferenceSystem, 'material_type_quality': models.MaterialTypeQualityType, 'object_type_quality': models.ObjectTypeQualityType, 'checked_type': models.CheckedType, } + field_order = [ + 'label', 'denomination', 'previous_id', 'museum_id', 'seal_number', + 'mark', 'description', 'is_complete', 'material_type', + 'material_type_quality', 'object_type', 'object_type_quality', + 'find_number', 'min_number_of_individuals', 'inscription', + 'manufacturing_place', 'communicabilitie', 'comment', '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 = {} HEADERS['label'] = FormHeader(_(u"Identification")) @@ -146,8 +161,6 @@ class FindForm(CustomForm, ManageOldType): validators=[validators.MaxLengthValidator(60)]) denomination = forms.CharField(label=_(u"Denomination"), required=False) previous_id = forms.CharField(label=_("Previous ID"), required=False) - get_first_base_find__excavation_id = forms.CharField( - label=_(u"Excavation ID"), required=False) museum_id = forms.CharField(label=_(u"Museum ID"), required=False) seal_number = forms.CharField(label=_(u"Seal number"), required=False) mark = forms.CharField(label=_(u"Mark"), required=False) @@ -155,14 +168,6 @@ class FindForm(CustomForm, ManageOldType): HEADERS['description'] = FormHeader(_(u"Description")) description = forms.CharField(label=_(u"Description"), widget=forms.Textarea, required=False) - get_first_base_find__discovery_date = forms.DateField( - label=_(u"Discovery date (exact or TPQ)"), widget=DatePicker, - required=False) - get_first_base_find__discovery_date_taq = forms.DateField( - label=_(u"Discovery date (TAQ)"), widget=DatePicker, required=False) - get_first_base_find__batch = forms.ChoiceField( - label=_(u"Batch/object"), choices=[], - required=False) is_complete = forms.NullBooleanField(label=_(u"Is complete?"), required=False) material_type = widgets.Select2MultipleField( @@ -194,24 +199,115 @@ class FindForm(CustomForm, ManageOldType): label=_(u"Comment on dating"), required=False, widget=forms.Textarea) HEADERS['length'] = FormHeader(_(u"Dimensions")) - length = FloatField(label=_(u"Length (cm)"), required=False) - width = FloatField(label=_(u"Width (cm)"), required=False) - height = FloatField(label=_(u"Height (cm)"), required=False) - diameter = FloatField(label=_(u"Diameter (cm)"), required=False) - thickness = FloatField(label=_(u"Thickness (cm)"), required=False) + length = FloatField(label=_(u"Length (cm)"), + widget=widgets.CentimeterMeterWidget, required=False) + width = FloatField(label=_(u"Width (cm)"), required=False, + widget=widgets.CentimeterMeterWidget) + height = FloatField(label=_(u"Height (cm)"), + widget=widgets.CentimeterMeterWidget, required=False) + thickness = FloatField(label=_(u"Thickness (cm)"), + widget=widgets.CentimeterMeterWidget, required=False) + diameter = FloatField(label=_(u"Diameter (cm)"), + widget=widgets.CentimeterMeterWidget, required=False) + circumference = FloatField( + label=_(u"Circumference (cm)"), widget=widgets.CentimeterMeterWidget, + required=False) volume = FloatField(label=_(u"Volume (l)"), required=False) - weight = FloatField(label=_(u"Weight (g)"), required=False) + weight = FloatField(label=_(u"Weight (g)"), + widget=widgets.GramKilogramWidget, required=False) clutter_long_side = FloatField( - label=_(u"Clutter long side (cm)"), required=False) + label=_(u"Clutter long side (cm)"), + widget=widgets.CentimeterMeterWidget, required=False) clutter_short_side = FloatField( - label=_(u"Clutter short side (cm)"), required=False) + label=_(u"Clutter short side (cm)"), + widget=widgets.CentimeterMeterWidget, required=False) clutter_height = FloatField( - label=_(u"Clutter height (cm)"), required=False) + label=_(u"Clutter height (cm)"), + widget=widgets.CentimeterMeterWidget, required=False) dimensions_comment = forms.CharField( label=_(u"Dimensions comment"), required=False, widget=forms.Textarea) - HEADERS['get_first_base_find__x'] = FormHeader( - _(u"Coordinates")) + HEADERS['checked_type'] = FormHeader(_(u"Sheet")) + checked_type = forms.ChoiceField(label=_(u"Check"), required=False) + check_date = forms.DateField( + initial=get_now, label=_(u"Check date"), widget=DatePicker) + + TYPES = [ + FieldType('material_type', models.MaterialType, is_multiple=True), + FieldType('material_type_quality', models.MaterialTypeQualityType), + FieldType('object_type', models.ObjectType, is_multiple=True), + FieldType('object_type_quality', models.ObjectTypeQualityType), + FieldType('communicabilitie', models.CommunicabilityType, + is_multiple=True), + FieldType('checked_type', models.CheckedType, is_multiple=True), + ] + + def __init__(self, *args, **kwargs): + context_record = kwargs.pop('context_record') + super(BaseFindForm, self).__init__(*args, **kwargs) + if not context_record or \ + not context_record.operation.operation_type.judiciary: + self.fields.pop('seal_number') + + 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( + unicode(_( + u"Clutter: short side cannot be bigger than the long side." + )) + ) + return self.cleaned_data + + +class FindForm(BaseFindForm): + file_upload = True + form_label = _("Find") + form_admin_name = _(u"Find - 020 - General") + form_slug = "find-020-general" + base_models = ['get_first_base_find'] + BaseFindForm.base_models + associated_models = BaseFindForm.associated_models.copy() + associated_models.update({ + 'get_first_base_find__batch': models.BatchType, + 'get_first_base_find__spatial_reference_system': SpatialReferenceSystem, + }) + field_order = [ + 'label', 'denomination', 'previous_id', + 'get_first_base_find__excavation_id', 'museum_id', 'seal_number', + 'mark', 'description', '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', 'object_type', + 'object_type_quality', 'find_number', 'min_number_of_individuals', + 'inscription', 'manufacturing_place', 'communicabilitie', 'comment', + 'dating_comment', 'length', 'width', 'height', 'thickness', 'diameter', + 'circumference', + 'volume', 'weight', 'clutter_long_side', 'clutter_short_side', + 'clutter_height', 'dimensions_comment', 'get_first_base_find__x', + 'get_first_base_find__estimated_error_x', 'get_first_base_find__y', + 'get_first_base_find__estimated_error_y', 'get_first_base_find__z', + 'get_first_base_find__estimated_error_z', + 'get_first_base_find__spatial_reference_system', + 'get_first_base_find__topographic_localisation', 'checked_type', + 'check_date', + ] + + HEADERS = BaseFindForm.HEADERS.copy() + get_first_base_find__excavation_id = forms.CharField( + label=_(u"Excavation ID"), required=False) + + get_first_base_find__discovery_date = forms.DateField( + label=_(u"Discovery date (exact or TPQ)"), widget=DatePicker, + required=False) + get_first_base_find__discovery_date_taq = forms.DateField( + label=_(u"Discovery date (TAQ)"), widget=DatePicker, required=False) + get_first_base_find__batch = forms.ChoiceField( + label=_(u"Batch/object"), choices=[], + required=False) + + HEADERS['get_first_base_find__x'] = FormHeader(_(u"Coordinates")) get_first_base_find__x = forms.FloatField(label=_(u"X"), required=False) get_first_base_find__estimated_error_x = \ forms.FloatField(label=_(u"Estimated error for X"), required=False) @@ -229,22 +325,10 @@ class FindForm(CustomForm, ManageOldType): required=False, max_length=120 ) - HEADERS['checked_type'] = FormHeader(_(u"Sheet")) - checked_type = forms.ChoiceField(label=_(u"Check"), required=False) - check_date = forms.DateField( - initial=get_now, label=_(u"Check date"), widget=DatePicker) - - TYPES = [ - FieldType('material_type', models.MaterialType, is_multiple=True), - FieldType('material_type_quality', models.MaterialTypeQualityType), - FieldType('object_type', models.ObjectType, is_multiple=True), - FieldType('object_type_quality', models.ObjectTypeQualityType), - FieldType('communicabilitie', models.CommunicabilityType, - is_multiple=True), + TYPES = BaseFindForm.TYPES + [ FieldType('get_first_base_find__batch', models.BatchType), FieldType('get_first_base_find__spatial_reference_system', SpatialReferenceSystem), - FieldType('checked_type', models.CheckedType, is_multiple=True), ] PROFILE_FILTER = { 'mapping': [ @@ -256,14 +340,8 @@ class FindForm(CustomForm, ManageOldType): ], } - def __init__(self, *args, **kwargs): - context_record = kwargs.pop('context_record') - super(FindForm, self).__init__(*args, **kwargs) - if not context_record or \ - not context_record.operation.operation_type.judiciary: - self.fields.pop('seal_number') - def clean(self): + self.cleaned_data = super(FindForm, self).clean() taq = self.cleaned_data.get('get_first_base_find__discovery_date_taq', None) tpq = self.cleaned_data.get('get_first_base_find__discovery_date', @@ -280,17 +358,6 @@ class FindForm(CustomForm, ManageOldType): unicode(_(u"Discovery date: TAQ date must be older than TPQ " u"date."))) - 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( - unicode(_( - u"Clutter: short side cannot be bigger than the long side." - )) - ) - if not get_current_profile().mapping: return self.cleaned_data x = self.cleaned_data.get('get_first_base_find__x', None) @@ -318,6 +385,154 @@ class FindForm(CustomForm, ManageOldType): return self.cleaned_data +class SimpleFindForm(BaseFindForm): + 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 = _(u"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(_(u"Identification")) + + resulting_label = forms.CharField( + label=_(u"Free ID"), + validators=[validators.MaxLengthValidator(60)]) + resulting_denomination = forms.CharField(label=_(u"Denomination"), + required=False) + + HEADERS['resulting_description'] = FormHeader(_(u"Description")) + resulting_description = forms.CharField( + label=_(u"Description"), widget=forms.Textarea, required=False) + resulting_is_complete = forms.NullBooleanField( + label=_(u"Is complete?"), required=False) + resulting_material_type = widgets.Select2MultipleField( + label=_(u"Material types"), required=False + ) + resulting_material_type_quality = forms.ChoiceField( + label=_(u"Material type quality"), required=False, choices=[]) + resulting_object_type = widgets.Select2MultipleField( + label=_(u"Object types"), required=False, + ) + resulting_object_type_quality = forms.ChoiceField( + label=_(u"Object type quality"), required=False, choices=[]) + resulting_find_number = forms.IntegerField( + label=_(u"Find number"), required=False) + resulting_min_number_of_individuals = forms.IntegerField( + label=_(u"Minimum number of individuals (MNI)"), required=False) + + resulting_decoration = forms.CharField( + label=_(u"Decoration"), widget=forms.Textarea, required=False) + resulting_inscription = forms.CharField( + label=_(u"Inscription"), widget=forms.Textarea, required=False) + resulting_manufacturing_place = forms.CharField( + label=_(u"Manufacturing place"), required=False) + resulting_communicabilitie = widgets.Select2MultipleField( + label=_(u"Communicability"), required=False + ) + resulting_comment = forms.CharField(label=_(u"Comment"), required=False, + widget=forms.Textarea) + resulting_dating_comment = forms.CharField( + label=_(u"Comment on dating"), required=False, widget=forms.Textarea) + + HEADERS['resulting_length'] = FormHeader(_(u"Dimensions")) + resulting_length = FloatField(label=_(u"Length (cm)"), required=False) + resulting_width = FloatField(label=_(u"Width (cm)"), required=False) + resulting_height = FloatField(label=_(u"Height (cm)"), required=False) + resulting_diameter = FloatField(label=_(u"Diameter (cm)"), required=False) + resulting_circumference = FloatField(label=_(u"Circumference (cm)"), + required=False) + resulting_thickness = FloatField(label=_(u"Thickness (cm)"), required=False) + resulting_volume = FloatField(label=_(u"Volume (l)"), required=False) + resulting_weight = FloatField(label=_(u"Weight (g)"), required=False) + resulting_clutter_long_side = FloatField( + label=_(u"Clutter long side (cm)"), required=False) + resulting_clutter_short_side = FloatField( + label=_(u"Clutter short side (cm)"), required=False) + resulting_clutter_height = FloatField( + label=_(u"Clutter height (cm)"), required=False) + resulting_dimensions_comment = forms.CharField( + label=_(u"Dimensions comment"), required=False, widget=forms.Textarea) + + HEADERS['resulting_checked_type'] = FormHeader(_(u"Sheet")) + resulting_checked_type = forms.ChoiceField(label=_(u"Check"), + required=False) + resulting_check_date = forms.DateField( + initial=get_now, label=_(u"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 = _(u"Treatment 1-n - 030 - Resulting finds") + form_slug = "treatment1n-030-resulting-finds" + associated_models = {} + + resultings_number = forms.IntegerField( + label=_(u"Number of resulting finds"), + min_value=1 + ) + resultings_label = forms.CharField( + label=_(u"Prefix label for resulting finds"), + validators=[validators.MaxLengthValidator(200)], + help_text=_( + u'E.g.: with a prefix "item-", each resulting item will be named ' + u'"item-1", "item-2", "item-3"') + ) + resultings_start_number = forms.IntegerField( + label=_(u"Numbering starting from"), initial=1, min_value=0 + ) + resultings_basket_name = forms.CharField( + label=_(u"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(_(u"A basket with this label already " + u"exists.")) + return self.cleaned_data + + class QAFindFormMulti(QAForm): form_admin_name = _(u"Find - Quick action - Modify") form_slug = "find-quickaction-modify" @@ -333,19 +548,20 @@ class QAFindFormMulti(QAForm): MULTI = True REPLACE_FIELDS = [ - 'qa_ue', 'qa_manufacturing_place', 'qa_checked_type', 'qa_check_date' + 'qa_denomination', 'qa_ue', 'qa_manufacturing_place', 'qa_checked_type', + 'qa_check_date' ] HEADERS = { 'qa_ue': FormHeader(_(u"Context record")), - 'qa_label': FormHeader(_(u"Identification")), + 'qa_denomination': FormHeader(_(u"Identification")), 'qa_description': FormHeader(_(u"Description")), 'qa_checked_type': FormHeader(_(u"Sheet")), 'qa_period': FormHeader(_(u"Datation")), } SINGLE_FIELDS = [ - 'qa_label', 'qa_denomination', 'qa_previous_id', + 'qa_label', 'qa_previous_id', 'qa_get_first_base_find__excavation_id', 'qa_museum_id', 'qa_seal_number', 'qa_mark' ] @@ -494,6 +710,35 @@ class QAFindBasketForm(IshtarForm): basket.items.add(item) +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 + unicode( + _(u" - duplicate")) + + def clean(self): + label = self.cleaned_data['label'].strip() + if not label: + raise forms.ValidationError(_(u"A label is required.")) + if models.FindBasket.objects.filter(user=self.user, + label=label).count(): + raise forms.ValidationError(_(u"A basket with this label already " + u"exists.")) + return self.cleaned_data + + def save(self): + self.basket.duplicate(label=self.cleaned_data['label'], + ishtaruser=self.user) + + class PreservationForm(CustomForm, ManageOldType): form_label = _("Preservation") form_admin_name = _(u"Find - 030 - Preservation") @@ -654,6 +899,10 @@ class FindSelect(HistorySelect): label=_(u"Batch/object"), choices=[]) checked_type = forms.ChoiceField(label=_("Check")) documents__image__isnull = forms.NullBooleanField(label=_(u"Has an image?")) + loan = forms.NullBooleanField(label=_(u"Loan?")) + treatments_file_end_date = forms.DateField( + label=_(u"Treatment file end date before"), widget=DatePicker + ) TYPES = [ FieldType('datings__period', Period), @@ -683,7 +932,8 @@ class FindSelect(HistorySelect): if self.current_user: self.fields['basket'].choices += [ (b.pk, b.label) for b in models.FindBasket.objects.filter( - user=self.current_user).all()] + models.FindBasket.get_query_owns(self.current_user) + ).all()] def get_input_ids(self): ids = super(FindSelect, self).get_input_ids() @@ -699,20 +949,36 @@ class FindSelect(HistorySelect): class FindSelectWarehouseModule(FindSelect): + container_ref__location = forms.IntegerField( + label=_(u"Reference container - Warehouse (location)"), + widget=widgets.JQueryAutoComplete( + reverse_lazy('autocomplete-warehouse'), + associated_model=Warehouse), + validators=[valid_id(Warehouse)]) + container_ref__responsible = forms.IntegerField( + label=_(u"Reference container - Warehouse (responsible)"), + widget=widgets.JQueryAutoComplete( + reverse_lazy('autocomplete-warehouse'), + associated_model=Warehouse), + validators=[valid_id(Warehouse)]) + container_ref__index = forms.IntegerField( + label=_(u"Reference container ID")) + container_ref__reference = forms.CharField( + label=_(u"Reference container ref.")) container__location = forms.IntegerField( - label=_(u"Warehouse (location)"), + label=_(u"Current container - Warehouse (location)"), widget=widgets.JQueryAutoComplete( reverse_lazy('autocomplete-warehouse'), associated_model=Warehouse), validators=[valid_id(Warehouse)]) container__responsible = forms.IntegerField( - label=_(u"Warehouse (responsible)"), + label=_(u"Current container - Warehouse (responsible)"), widget=widgets.JQueryAutoComplete( reverse_lazy('autocomplete-warehouse'), associated_model=Warehouse), validators=[valid_id(Warehouse)]) - container__index = forms.IntegerField(label=_(u"Container ID")) - container__reference = forms.CharField(label=_(u"Container ref.")) + container__index = forms.IntegerField(label=_(u"Current container ID")) + container__reference = forms.CharField(label=_(u"Current container ref.")) class FindFormSelection(CustomFormSearch): @@ -725,7 +991,7 @@ class FindFormSelection(CustomFormSearch): label="", required=False, widget=widgets.DataTable( reverse_lazy('get-find'), - FindSelect, models.Find, + FindSelect, models.Find, source_full=reverse_lazy('get-find-full')), validators=[valid_id(models.Find)]) @@ -910,8 +1176,19 @@ class FindDeletionForm(FinalForm): confirm_end_msg = _(u"Would you like to delete this find?") -class UpstreamFindFormSelection(FindFormSelection): - form_label = _(u"Upstream find") +class UpstreamFindFormSelection(PkWizardSearch, FindFormSelection): + form_label = _(u"Upstream finds") + current_model = models.Find + pk_key = 'resulting_pk' + + pk = forms.CharField( + label="", required=False, + widget=widgets.DataTable( + reverse_lazy('get-find'), + FindSelect, current_model, + multiple_select=True, + source_full=reverse_lazy('get-find-full')), + validators=[valid_ids(current_model)]) def __init__(self, *args, **kwargs): super(UpstreamFindFormSelection, self).__init__(*args, **kwargs) @@ -919,6 +1196,17 @@ class UpstreamFindFormSelection(FindFormSelection): self.fields['resulting_pk'] = self.fields.pop('pk') +class SingleUpstreamFindFormSelection(UpstreamFindFormSelection): + current_model = models.Find + pk = forms.CharField( + label="", required=False, + widget=widgets.DataTable( + reverse_lazy('get-find'), + FindSelect, current_model, + source_full=reverse_lazy('get-find-full')), + validators=[valid_ids(current_model)]) + + class FindBasketSelect(CustomForm, TableSelect): _model = models.FindBasket @@ -947,19 +1235,57 @@ class FindBasketFormSelection(CustomFormSearch): 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 = _(u"Find basket") + associated_models = {"shared_with": IshtarUser, + "shared_write_with": IshtarUser} label = forms.CharField( label=_(u"Label"), validators=[validators.MaxLengthValidator(1000)]) comment = forms.CharField(label=_(u"Comment"), widget=forms.Textarea, required=False) + shared_with = widgets.Select2MultipleField( + model=IshtarUser, remote=True, + label=_(u"Shared (read) with"), + required=False, long_widget=True + ) + shared_write_with = widgets.Select2MultipleField( + model=IshtarUser, remote=True, + label=_(u"Shared (read/edit) with"), + required=False, long_widget=True + ) -class NewFindBasketForm(forms.ModelForm): +class NewFindBasketForm(forms.ModelForm, IshtarForm): + shared_with = widgets.Select2MultipleField( + model=IshtarUser, remote=True, + label=_(u"Shared (read) with"), + required=False, long_widget=True + ) + shared_write_with = widgets.Select2MultipleField( + model=IshtarUser, remote=True, + label=_(u"Shared (read/edit) with"), + required=False, long_widget=True + ) + class Meta: model = models.FindBasket - fields = ('label', 'comment') + fields = ('label', 'comment', 'shared_with', 'shared_write_with') def __init__(self, *args, **kwargs): self.user = kwargs.pop('user') @@ -995,22 +1321,15 @@ class SelectFindBasketForm(IshtarForm): super(SelectFindBasketForm, self).__init__(*args, **kwargs) if not self.user: return - self.fields['basket'].choices = [('', '--')] + [ - (b.pk, unicode(b)) - for b in models.FindBasket.objects.filter( - Q(user=self.user) | Q(shared_with=self.user) - )] + self.fields['basket'].choices = self.get_basket_choices() - -class DeleteFindBasketForm(SelectFindBasketForm): - def save(self): - try: - models.FindBasket.objects.get(pk=self.cleaned_data['basket'], - user=self.user).delete() - except models.FindBasket.DoesNotExist: - # something strange... TODO: log it - pass - return + def get_basket_choices(self): + return [('', u'--')] + [ + (str(b.pk), unicode(b)) + for b in models.FindBasket.objects.filter( + Q(user=self.user) | Q(shared_write_with=self.user) + ) + ] class FindBasketAddItemForm(forms.Form): @@ -1020,8 +1339,8 @@ class FindBasketAddItemForm(forms.Form): def save(self, user): try: basket = models.FindBasket.objects.filter( - Q(user=user) | Q(shared_with=user) - ).get(pk=self.cleaned_data['basket_id']) + 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\ diff --git a/archaeological_finds/forms_treatments.py b/archaeological_finds/forms_treatments.py index 7ada0f4bc..10c4527ef 100644 --- a/archaeological_finds/forms_treatments.py +++ b/archaeological_finds/forms_treatments.py @@ -23,10 +23,9 @@ from collections import OrderedDict from django import forms from django.core import validators -from django.forms.formsets import formset_factory from django.utils.translation import ugettext_lazy as _ -import models +from archaeological_finds import models from archaeological_operations.forms import AdministrativeActForm, \ AdministrativeActOpeFormSelection, AdministrativeActModifForm from archaeological_operations.models import ActType, AdministrativeAct @@ -80,7 +79,9 @@ class TreatmentFormSelection(forms.Form): class BaseTreatmentForm(CustomForm, ManageOldType): - form_label = _(u"Base treatment") + UPSTREAM_IS_MANY = False + DOWNSTREAM_IS_MANY = False + form_label = _(u"Treatment") form_admin_name = _(u"Treatment - 020 - General") form_slug = "treatment-020-general" base_models = ['treatment_type'] @@ -94,20 +95,20 @@ class BaseTreatmentForm(CustomForm, ManageOldType): file_upload = True need_user_for_initialization = True - label = forms.CharField(label=_(u"Label"), - max_length=200, required=False) - other_reference = forms.CharField( - label=_(u"Other ref."), max_length=200, required=False) + treatment_type = widgets.Select2MultipleField( + label=_(u"Treatment type"), choices=[], + widget=widgets.CheckboxSelectMultiple) + treatment_state = forms.ChoiceField(label=_(u"State"), choices=[]) year = forms.IntegerField(label=_("Year"), initial=lambda: datetime.datetime.now().year, validators=[validators.MinValueValidator(1000), validators.MaxValueValidator(2100)]) - treatment_type = forms.MultipleChoiceField( - label=_(u"Treatment type"), choices=[], - widget=widgets.CheckboxSelectMultiple) - treatment_state = forms.ChoiceField(label=_(u"State"), - choices=[], required=False) - target_is_basket = forms.NullBooleanField(label=_(u"Target")) + location = forms.IntegerField( + label=_(u"Location"), + widget=widgets.JQueryAutoComplete( + reverse_lazy('autocomplete-warehouse'), associated_model=Warehouse, + new=True), + validators=[valid_id(Warehouse)]) person = forms.IntegerField( label=_(u"Responsible"), widget=widgets.JQueryAutoComplete( @@ -120,30 +121,29 @@ class BaseTreatmentForm(CustomForm, ManageOldType): reverse_lazy('autocomplete-organization'), associated_model=Organization, new=True), validators=[valid_id(Organization)], required=False) - location = forms.IntegerField( - label=_(u"Location"), - widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-warehouse'), associated_model=Warehouse, - new=True), - validators=[valid_id(Warehouse)]) + label = forms.CharField(label=_(u"Label"), + max_length=200, required=False) + other_reference = forms.CharField( + label=_(u"Other ref."), max_length=200, required=False) + # external_id = forms.CharField( + # label=_(u"External ref."), max_length=200, required=False) + start_date = forms.DateField(label=_(u"Start date"), required=False, + widget=DatePicker, initial=datetime.date.today) + end_date = forms.DateField(label=_(u"Closing date"), required=False, + widget=DatePicker) container = forms.IntegerField( - label=_(u"Container (relevant for packaging)"), + label=_(u"Destination container (relevant for treatment that change " + u"location)"), widget=widgets.JQueryAutoComplete( reverse_lazy('autocomplete-container'), associated_model=Container, new=True), validators=[valid_id(Container)], required=False) - external_id = forms.CharField( - label=_(u"External ref."), max_length=200, required=False) goal = forms.CharField(label=_(u"Goal"), widget=forms.Textarea, required=False) description = forms.CharField(label=_(u"Description"), widget=forms.Textarea, required=False) comment = forms.CharField(label=_(u"Comment"), widget=forms.Textarea, required=False) - start_date = forms.DateField(label=_(u"Start date"), required=False, - widget=DatePicker) - end_date = forms.DateField(label=_(u"Closing date"), required=False, - widget=DatePicker) estimated_cost = forms.FloatField(label=_(u"Estimated cost ({currency})"), required=False) quoted_cost = forms.FloatField(label=_(u"Quoted cost ({currency})"), @@ -152,12 +152,15 @@ class BaseTreatmentForm(CustomForm, ManageOldType): required=False) insurance_cost = forms.FloatField(label=_(u"Insurance cost ({currency})"), required=False) + executed = forms.BooleanField(required=False, disabled=True, + widget=forms.HiddenInput) TYPES = [ - FieldType('treatment_state', models.TreatmentState), - FieldType('treatment_type', models.TreatmentType, is_multiple=True, - extra_args={'dct': {'upstream_is_many': False, - 'downstream_is_many': False}}) + FieldType('treatment_state', models.TreatmentState, True), + FieldType( + 'treatment_type', models.TreatmentType, is_multiple=True, + extra_args={'dct': {'upstream_is_many': False, + 'downstream_is_many': False}}) ] def __init__(self, *args, **kwargs): @@ -170,14 +173,20 @@ class BaseTreatmentForm(CustomForm, ManageOldType): self.fields[key].label = self.fields[key].label.format( currency=currency) + initial = kwargs.get('initial', {}) + if initial.get('executed', False): + self.fields['treatment_state'].choices = \ + models.TreatmentState.get_types(empty_first=False, + dct={'executed': True}) + q = Person.objects.filter(ishtaruser__pk=user.pk) if q.count(): person = q.all()[0] self.fields['person'].initial = person.pk if person.attached_to: self.fields['organization'].initial = person.attached_to.pk - self.fields['target_is_basket'].widget.choices = \ - ((False, _(u"Single find")), (True, _(u"Basket"))) + # self.fields['target_is_basket'].widget.choices = \ + # ((False, _(u"Single find")), (True, _(u"Basket"))) # TODO """ self.fields['basket'].required = False @@ -194,38 +203,97 @@ class BaseTreatmentForm(CustomForm, ManageOldType): def clean(self, *args, **kwargs): data = self.cleaned_data - packaging = models.TreatmentType.get_cache('packaging') - if not packaging: - logger.warning("No 'packaging' treatment type defined") - return + + try: + treatment_types = [ + models.TreatmentType.objects.get( + pk=pk, available=True, + upstream_is_many=self.UPSTREAM_IS_MANY, + downstream_is_many=self.DOWNSTREAM_IS_MANY) + for pk in data.get('treatment_type', [])] + except models.TreatmentType.DoesNotExist: + raise forms.ValidationError(_(u"Unknow treatment type")) + + + change_current_location = [ + unicode(tp) for tp in treatment_types + if tp.change_current_location + ] + restore_reference_location = [ + unicode(tp) for tp in treatment_types + if tp.restore_reference_location + ] + change_ref_location = [ + unicode(tp) for tp in treatment_types + if tp.change_reference_location + ] + + if (change_ref_location or change_current_location + ) and restore_reference_location: + if change_ref_location: + raise forms.ValidationError( + unicode( + _(u"{} is not compatible with {} " + u"treatment(s).")).format( + u' ; '.join(restore_reference_location), + u' ; '.join(change_ref_location), + ) + ) + else: + raise forms.ValidationError( + unicode( + _(u"{} is not compatible with {} " + u"treatment(s).")).format( + u' ; '.join(restore_reference_location), + u' ; '.join(change_current_location) + ) + ) + if data.get('container', None) \ - and str(packaging.pk) not in data.get('treatment_type', []): + and not change_ref_location\ + and not change_current_location: raise forms.ValidationError( - _(u"The container field is attached to the treatment. If " - u"no packaging treatment is done it is not relevant.")) - if not data.get('container', None) \ - and str(packaging.pk) in data.get('treatment_type', []): + _(u"The container field is attached to the treatment but " + u"no treatment with container change is defined.")) + if not data.get('container', None) and ( + change_ref_location or change_current_location): raise forms.ValidationError( - _(u"If a packaging treatment is done, the container field " - u"must be filled.")) + _(u"A treatment with location change is defined, the container " + u"field must be filled.")) if not data.get('person', None) and not data.get('organization', None): raise forms.ValidationError( _(u"A responsible or an organization must be defined.")) return data - # TODO - """ - for treatment_type in self.cleaned_data.get('treatment_type', []): - try: - treatment = models.TreatmentType.objects.get( - pk=treatment_type, available=True) - except models.TreatmentType.DoesNotExist: - raise forms.ValidationError(_(u"This treatment type is not " - u"available.")) - if treatment.upstream_is_many and \ - not self.cleaned_data.get('basket'): - raise forms.ValidationError(_(u"This treatment needs a " - u"basket.")) - """ + + +class N1TreatmentForm(BaseTreatmentForm): + UPSTREAM_IS_MANY = True + form_admin_name = _(u"Treatment n-1 - 020 - General") + form_slug = "treatmentn1-020-general" + + TYPES = [ + FieldType('treatment_state', models.TreatmentState, True, + extra_args={'dct': {"executed": True}}), + FieldType( + 'treatment_type', models.TreatmentType, is_multiple=True, + extra_args={'dct': {'upstream_is_many': True, + 'downstream_is_many': False}}) + ] + + +class OneNTreatmentForm(BaseTreatmentForm): + DOWNSTREAM_IS_MANY = True + form_admin_name = _(u"Treatment 1-n - 020 - General") + form_slug = "treatment1n-020-general" + + TYPES = [ + FieldType('treatment_state', models.TreatmentState, True, + extra_args={'dct': {"executed": True}}), + FieldType( + 'treatment_type', models.TreatmentType, is_multiple=True, + extra_args={'dct': {'upstream_is_many': False, + 'downstream_is_many': True}}) + ] class TreatmentModifyForm(BaseTreatmentForm): @@ -240,7 +308,7 @@ class TreatmentModifyForm(BaseTreatmentForm): fields[key] = value if key == 'year': fields['index'] = idx - fields.pop('target_is_basket') + # fields.pop('target_is_basket') self.fields = fields def clean(self, *args, **kwargs): @@ -287,6 +355,11 @@ class QAFindTreatmentForm(IshtarForm): reverse_lazy('autocomplete-container'), associated_model=Container, new=True), validators=[valid_id(Container)]) + reference_container = forms.BooleanField( + label=_(u"Change the reference container"), required=False, + widget=widgets.CheckboxInput, initial=True, + help_text=_(u"If unchecked the current container will be changed") + ) create_treatment = forms.BooleanField( label=_(u"Create a treatment"), required=False, widget=widgets.CheckboxInput @@ -344,8 +417,9 @@ class QAFindTreatmentForm(IshtarForm): container = Container.objects.get(pk=self.cleaned_data['container']) if self.cleaned_data['create_treatment']: packaging, created = models.TreatmentType.objects.get_or_create( - label=u"Conditionnement", - txt_idx='packaging' + txt_idx='packaging', + defaults={"label": _(u"Packaging"), + "change_reference_location": True} ) t = models.Treatment.objects.create( container=container, @@ -359,10 +433,13 @@ class QAFindTreatmentForm(IshtarForm): t.treatment_types.add(packaging) t.save(items=items) return + container_attr = 'container' + if self.cleaned_data.get('reference_container', False): + container_attr = 'container_ref' for find in items: - if find.container == container: + if getattr(find, container_attr) == container: continue - find.container = container + setattr(find, container_attr, container) find.save() @@ -542,7 +619,9 @@ class TreatmentFileForm(ManageOldType): base_models = ['treatment_type_type'] associated_models = { 'type': models.TreatmentFileType, 'in_charge': Person, - 'applicant': Person, 'applicant_organisation': Organization} + 'applicant': Person, 'applicant_organisation': Organization, + 'associated_basket': models.FindBasket + } need_user_for_initialization = True name = forms.CharField(label=_(u"Name"), @@ -575,6 +654,11 @@ class TreatmentFileForm(ManageOldType): reverse_lazy('autocomplete-organization'), associated_model=Organization, new=True), validators=[valid_id(Organization)], required=False) + associated_basket = forms.IntegerField( + _(u"Associated basket"), + widget=widgets.JQueryAutoComplete( + reverse_lazy('autocomplete-findbasket'), + associated_model=models.FindBasket), required=False) comment = forms.CharField(label=_(u"Comment"), widget=forms.Textarea, required=False) creation_date = forms.DateField(label=_(u"Start date"), required=False, diff --git a/archaeological_finds/ishtar_menu.py b/archaeological_finds/ishtar_menu.py index afd624b74..21a582a18 100644 --- a/archaeological_finds/ishtar_menu.py +++ b/archaeological_finds/ishtar_menu.py @@ -99,23 +99,23 @@ MENU_SECTIONS = [ MenuItem('treatmentfle_search', _(u"Search"), model=models.TreatmentFile, - access_controls=['view_filetreatment', - 'view_own_filetreatment']), + access_controls=['view_treatmentfile', + 'view_own_treatmentfile']), MenuItem('treatmentfle_creation', _(u"Creation"), model=models.TreatmentFile, - access_controls=['change_filetreatment', - 'change_own_filetreatment']), + access_controls=['change_treatmentfile', + 'change_own_treatmentfile']), MenuItem('treatmentfle_modification', _(u"Modification"), model=models.TreatmentFile, - access_controls=['change_filetreatment', - 'change_own_filetreatment']), + access_controls=['change_treatmentfile', + 'change_own_treatmentfile']), MenuItem('treatmentfle_deletion', _(u"Deletion"), model=models.TreatmentFile, - access_controls=['change_filetreatment', - 'change_own_filetreatment']), + access_controls=['change_treatmentfile', + 'change_own_treatmentfile']), SectionItem( 'admin_act_fletreatments', _(u"Administrative act"), childs=[ @@ -134,10 +134,6 @@ MENU_SECTIONS = [ _(u"Deletion"), model=AdministrativeAct, access_controls=['change_administrativeact']), - MenuItem('treatmentfle_administrativeact_document', - _(u"Documents"), - model=AdministrativeAct, - access_controls=['change_administrativeact']), ] ), ] @@ -148,41 +144,47 @@ MENU_SECTIONS = [ profile_restriction='warehouse', css='menu-warehouse', childs=[ - SectionItem( - 'find_treatments', _(u"Simple treatments"), - childs=[ - MenuItem('treatment_search', - _(u"Search"), - model=models.Treatment, - access_controls=['view_treatment', - 'view_own_treatment']), - MenuItem('treatment_creation', - _(u"Creation"), - model=models.Treatment, - access_controls=['change_treatment', - 'change_own_treatment']), - MenuItem('treatment_modification', - _(u"Modification"), - model=models.Treatment, - access_controls=['change_treatment', - 'change_own_treatment']), - MenuItem('treatment_deletion', - _(u"Deletion"), - model=models.Treatment, - access_controls=['change_treatment', - 'change_own_treatment']), - ]), - SectionItem( + MenuItem('treatment_search', + _(u"Search"), + model=models.Treatment, + access_controls=['view_treatment', + 'view_own_treatment']), + MenuItem( + 'treatment_creation', + _(u"Simple treatment - creation"), + model=models.Treatment, + access_controls=['change_find', 'change_own_find']), + MenuItem( + 'treatment_creation_n1', + _(u"Treatment many to one - creation"), + model=models.Treatment, + access_controls=['change_find', 'change_own_find']), + MenuItem( + 'treatment_creation_1n', + _(u"Treatment one to many - creation"), + model=models.Treatment, + access_controls=['change_find', 'change_own_find']), + MenuItem('treatment_modification', + _(u"Modification"), + model=models.Treatment, + access_controls=['change_treatment', + 'change_own_treatment']), + MenuItem('treatment_deletion', + _(u"Deletion"), + model=models.Treatment, + access_controls=['change_treatment', + 'change_own_treatment']), + SectionItem( 'admin_act_treatments', _(u"Administrative act"), childs=[ MenuItem('treatment_admacttreatment_search', _(u"Search"), model=AdministrativeAct, - access_controls=['change_administrativeact']), + access_controls=['view_administrativeact']), MenuItem('treatment_admacttreatment', _(u"Creation"), model=AdministrativeAct, - access_controls=['change_administrativeact']), + access_controls=['add_administrativeact']), MenuItem( 'treatment_admacttreatment_modification', _(u"Modification"), model=AdministrativeAct, @@ -191,10 +193,6 @@ MENU_SECTIONS = [ _(u"Deletion"), model=AdministrativeAct, access_controls=['change_administrativeact']), - MenuItem('treatment_administrativeact_document', - _(u"Documents"), - model=AdministrativeAct, - access_controls=['change_administrativeact']), ]), ] )), diff --git a/archaeological_finds/locale/django.pot b/archaeological_finds/locale/django.pot index 4ca54a290..65b0b22ba 100644 --- a/archaeological_finds/locale/django.pot +++ b/archaeological_finds/locale/django.pot @@ -9,853 +9,961 @@ msgid "" msgstr "" -#: admin.py:39 models_finds.py:288 +#: admin.py:39 models_finds.py:303 msgid "Point (2D)" msgstr "" -#: admin.py:41 models_finds.py:290 +#: admin.py:41 models_finds.py:305 msgid "Line" msgstr "" -#: admin.py:43 models_finds.py:291 +#: admin.py:43 models_finds.py:306 msgid "Multi polygon" msgstr "" -#: forms.py:91 forms.py:97 forms.py:340 forms.py:353 forms.py:631 -#: models_finds.py:660 models_finds.py:1213 wizards.py:75 +#: forms.py:96 forms.py:102 forms.py:556 forms.py:569 forms.py:876 +#: models_finds.py:722 models_finds.py:1337 wizards.py:86 msgid "Context record" msgstr "" -#: forms.py:92 +#: forms.py:97 msgid "Find - 010 - Context record choice" msgstr "" -#: forms.py:126 ishtar_menu.py:32 models_finds.py:1089 models_finds.py:1717 -#: models_treatments.py:349 templates/ishtar/sheet_find.html:4 +#: forms.py:134 forms.py:268 ishtar_menu.py:32 models_finds.py:1192 +#: models_finds.py:1959 models_treatments.py:585 +#: templates/ishtar/sheet_find.html:4 msgid "Find" msgstr "" -#: forms.py:127 -msgid "Find - 020 - General" +#: forms.py:135 +msgid "Simple find - 020 - General" msgstr "" -#: forms.py:142 forms.py:341 templates/ishtar/sheet_find.html:40 +#: forms.py:157 forms.py:409 forms.py:557 templates/ishtar/sheet_find.html:110 msgid "Identification" msgstr "" -#: forms.py:145 forms.py:360 forms.py:600 forms.py:889 models_finds.py:253 -#: models_finds.py:968 +#: forms.py:160 forms.py:412 forms.py:576 forms.py:845 forms.py:1155 +#: models_finds.py:268 models_finds.py:1060 msgid "Free ID" msgstr "" -#: forms.py:147 forms.py:362 forms.py:601 forms.py:932 models_finds.py:969 +#: forms.py:162 forms.py:414 forms.py:578 forms.py:846 forms.py:1220 +#: models_finds.py:1061 msgid "Denomination" msgstr "" -#: forms.py:148 forms.py:363 models_finds.py:1042 +#: forms.py:163 forms.py:579 models_finds.py:1141 msgid "Previous ID" msgstr "" -#: forms.py:150 forms.py:365 models_finds.py:257 -msgid "Excavation ID" -msgstr "" - -#: forms.py:151 forms.py:366 models_finds.py:970 +#: forms.py:164 forms.py:582 models_finds.py:1062 msgid "Museum ID" msgstr "" -#: forms.py:152 forms.py:367 models_finds.py:965 +#: forms.py:165 forms.py:583 models_finds.py:1057 msgid "Seal number" msgstr "" -#: forms.py:153 forms.py:368 models_finds.py:1038 +#: forms.py:166 forms.py:584 models_finds.py:1137 msgid "Mark" msgstr "" -#: forms.py:155 forms.py:156 forms.py:342 forms.py:371 forms.py:652 -#: forms_treatments.py:139 models_finds.py:258 models_finds.py:971 -#: models_treatments.py:146 templates/ishtar/sheet_find.html:58 +#: forms.py:168 forms.py:169 forms.py:417 forms.py:419 forms.py:558 +#: forms.py:587 forms.py:897 forms_treatments.py:141 models_finds.py:273 +#: models_finds.py:1063 models_treatments.py:164 +#: templates/ishtar/sheet_find.html:128 msgid "Description" msgstr "" -#: forms.py:159 models_finds.py:265 -msgid "Discovery date (exact or TPQ)" -msgstr "" - -#: forms.py:162 models_finds.py:267 templates/ishtar/sheet_basefind.html:29 -msgid "Discovery date (TAQ)" -msgstr "" - -#: forms.py:164 forms.py:654 models_finds.py:269 -msgid "Batch/object" -msgstr "" - -#: forms.py:166 models_finds.py:1003 +#: forms.py:171 forms.py:421 models_finds.py:1100 msgid "Is complete?" msgstr "" -#: forms.py:169 forms.py:373 models_finds.py:57 models_finds.py:685 -#: models_finds.py:977 +#: forms.py:174 forms.py:423 forms.py:589 models_finds.py:57 +#: models_finds.py:748 models_finds.py:1069 msgid "Material types" msgstr "" -#: forms.py:172 models_finds.py:982 +#: forms.py:177 forms.py:426 models_finds.py:1074 msgid "Material type quality" msgstr "" -#: forms.py:174 forms.py:376 models_finds.py:152 models_finds.py:686 -#: models_finds.py:1006 +#: forms.py:179 forms.py:428 forms.py:592 models_finds.py:167 +#: models_finds.py:749 models_finds.py:1103 msgid "Object types" msgstr "" -#: forms.py:177 models_finds.py:1011 +#: forms.py:182 forms.py:431 models_finds.py:1108 msgid "Object type quality" msgstr "" -#: forms.py:178 forms.py:896 models_finds.py:989 +#: forms.py:183 forms.py:433 forms.py:1162 models_finds.py:1081 msgid "Find number" msgstr "" -#: forms.py:180 models_finds.py:1024 +#: forms.py:185 forms.py:435 models_finds.py:1121 msgid "Minimum number of individuals (MNI)" msgstr "" -#: forms.py:182 models_finds.py:972 +#: forms.py:187 forms.py:438 models_finds.py:1064 msgid "Decoration" msgstr "" -#: forms.py:184 models_finds.py:973 +#: forms.py:189 forms.py:440 models_finds.py:1065 msgid "Inscription" msgstr "" -#: forms.py:187 forms.py:379 models_finds.py:975 +#: forms.py:192 forms.py:442 forms.py:595 models_finds.py:1067 msgid "Manufacturing place" msgstr "" -#: forms.py:189 forms.py:381 models_finds.py:1021 +#: forms.py:194 forms.py:444 forms.py:597 models_finds.py:1118 msgid "Communicability" msgstr "" -#: forms.py:191 forms.py:384 forms.py:955 forms_treatments.py:141 -#: forms_treatments.py:578 models_finds.py:259 models_finds.py:1039 -#: models_treatments.py:145 models_treatments.py:609 +#: forms.py:196 forms.py:446 forms.py:600 forms.py:1260 forms_treatments.py:143 +#: forms_treatments.py:657 models_finds.py:274 models_finds.py:1138 +#: models_treatments.py:163 models_treatments.py:847 msgid "Comment" msgstr "" -#: forms.py:194 forms.py:394 models_finds.py:1040 +#: forms.py:199 forms.py:449 forms.py:610 models_finds.py:1139 msgid "Comment on dating" msgstr "" -#: forms.py:196 templates/ishtar/sheet_find.html:76 +#: forms.py:201 forms.py:451 templates/ishtar/sheet_find.html:146 msgid "Dimensions" msgstr "" -#: forms.py:197 models_finds.py:1025 +#: forms.py:202 forms.py:452 models_finds.py:1122 msgid "Length (cm)" msgstr "" -#: forms.py:198 models_finds.py:1026 +#: forms.py:204 forms.py:453 models_finds.py:1123 msgid "Width (cm)" msgstr "" -#: forms.py:199 models_finds.py:1027 +#: forms.py:206 forms.py:454 models_finds.py:1124 msgid "Height (cm)" msgstr "" -#: forms.py:200 models_finds.py:1028 +#: forms.py:208 forms.py:458 models_finds.py:1128 +msgid "Thickness (cm)" +msgstr "" + +#: forms.py:210 forms.py:455 models_finds.py:1125 msgid "Diameter (cm)" msgstr "" -#: forms.py:201 models_finds.py:1029 -msgid "Thickness (cm)" +#: forms.py:213 forms.py:456 models_finds.py:1126 +msgid "Circumference (cm)" msgstr "" -#: forms.py:202 forms.py:894 models_finds.py:985 +#: forms.py:215 forms.py:459 forms.py:1160 models_finds.py:1077 msgid "Volume (l)" msgstr "" -#: forms.py:203 forms.py:895 templates/ishtar/sheet_find.html:84 +#: forms.py:216 forms.py:460 forms.py:1161 templates/ishtar/sheet_find.html:155 msgid "Weight (g)" msgstr "" -#: forms.py:205 +#: forms.py:219 forms.py:462 msgid "Clutter long side (cm)" msgstr "" -#: forms.py:207 +#: forms.py:222 forms.py:464 msgid "Clutter short side (cm)" msgstr "" -#: forms.py:209 +#: forms.py:225 forms.py:466 msgid "Clutter height (cm)" msgstr "" -#: forms.py:211 models_finds.py:1036 +#: forms.py:228 forms.py:468 models_finds.py:1135 msgid "Dimensions comment" msgstr "" -#: forms.py:214 templates/ishtar/sheet_basefind.html:46 -#: templates/ishtar/sheet_basefind.html:50 +#: forms.py:230 forms.py:470 forms.py:559 +#: templates/ishtar/sheet_basefind.html:70 templates/ishtar/sheet_find.html:164 +msgid "Sheet" +msgstr "" + +#: forms.py:231 forms.py:471 forms.py:603 forms.py:900 models_finds.py:1143 +msgid "Check" +msgstr "" + +#: forms.py:233 forms.py:474 forms.py:605 models_finds.py:1145 +msgid "Check date" +msgstr "" + +#: forms.py:260 +msgid "Clutter: short side cannot be bigger than the long side." +msgstr "" + +#: forms.py:269 +msgid "Find - 020 - General" +msgstr "" + +#: forms.py:299 forms.py:581 models_finds.py:272 +msgid "Excavation ID" +msgstr "" + +#: forms.py:302 models_finds.py:280 +msgid "Discovery date (exact or TPQ)" +msgstr "" + +#: forms.py:305 models_finds.py:282 templates/ishtar/sheet_basefind.html:33 +msgid "Discovery date (TAQ)" +msgstr "" + +#: forms.py:307 forms.py:899 models_finds.py:284 +msgid "Batch/object" +msgstr "" + +#: forms.py:310 templates/ishtar/sheet_basefind.html:50 +#: templates/ishtar/sheet_basefind.html:54 msgid "Coordinates" msgstr "" -#: forms.py:215 models_finds.py:276 +#: forms.py:311 models_finds.py:291 msgid "X" msgstr "" -#: forms.py:217 models_finds.py:279 +#: forms.py:313 models_finds.py:294 msgid "Estimated error for X" msgstr "" -#: forms.py:218 models_finds.py:277 +#: forms.py:314 models_finds.py:292 msgid "Y" msgstr "" -#: forms.py:220 models_finds.py:281 +#: forms.py:316 models_finds.py:296 msgid "Estimated error for Y" msgstr "" -#: forms.py:221 models_finds.py:278 +#: forms.py:317 models_finds.py:293 msgid "Z" msgstr "" -#: forms.py:223 models_finds.py:283 +#: forms.py:319 models_finds.py:298 msgid "Estimated error for Z" msgstr "" -#: forms.py:225 models_finds.py:286 +#: forms.py:321 models_finds.py:301 msgid "Spatial Reference System" msgstr "" -#: forms.py:228 models_finds.py:274 +#: forms.py:324 models_finds.py:289 msgid "Point of topographic reference" msgstr "" -#: forms.py:232 forms.py:343 templates/ishtar/sheet_basefind.html:66 -#: templates/ishtar/sheet_find.html:93 -msgid "Sheet" +#: forms.py:352 +msgid "" +"Discovery date: if a TAQ date is provided a TPQ date has to be informed. If " +"you have a precise date fill only the TPQ - discovery date field." msgstr "" -#: forms.py:233 forms.py:387 forms.py:655 models_finds.py:1044 -msgid "Check" +#: forms.py:358 +msgid "Discovery date: TAQ date must be older than TPQ date." msgstr "" -#: forms.py:235 forms.py:389 models_finds.py:1046 -msgid "Check date" +#: forms.py:374 +msgid "You should at least provide X, Y and the spatial reference system used." msgstr "" -#: forms.py:274 -msgid "" -"Discovery date: if a TAQ date is provided a TPQ date has to be informed. If " -"you have a precise date fill only the TPQ - discovery date field." +#: forms.py:383 +msgid "Coordinates are not relevant for the spatial reference system used: {}." msgstr "" -#: forms.py:280 -msgid "Discovery date: TAQ date must be older than TPQ date." +#: forms.py:396 forms.py:1152 +msgid "Resulting find" msgstr "" -#: forms.py:290 -msgid "Clutter: short side cannot be bigger than the long side." +#: forms.py:397 +msgid "Treatment n-1 - 030 - Resulting find" msgstr "" -#: forms.py:307 -msgid "You should at least provide X, Y and the spatial reference system used." +#: forms.py:493 forms.py:1171 +msgid "Resulting finds" msgstr "" -#: forms.py:316 -msgid "Coordinates are not relevant for the spatial reference system used: {}." +#: forms.py:494 +msgid "Treatment 1-n - 030 - Resulting finds" msgstr "" -#: forms.py:322 +#: forms.py:499 +msgid "Number of resulting finds" +msgstr "" + +#: forms.py:503 +msgid "Prefix label for resulting finds" +msgstr "" + +#: forms.py:506 +msgid "" +"E.g.: with a prefix \"item-\", each resulting item will be named \"item-1\", " +"\"item-2\", \"item-3\"" +msgstr "" + +#: forms.py:510 +msgid "Numbering starting from" +msgstr "" + +#: forms.py:513 +msgid "Name of the new basket containing the resulting items" +msgstr "" + +#: forms.py:531 forms.py:697 forms.py:733 +msgid "A basket with this label already exists." +msgstr "" + +#: forms.py:537 msgid "Find - Quick action - Modify" msgstr "" -#: forms.py:344 +#: forms.py:560 msgid "Datation" msgstr "" -#: forms.py:392 forms.py:565 forms.py:641 templates/ishtar/sheet_find.html:123 +#: forms.py:608 forms.py:810 forms.py:886 templates/ishtar/sheet_find.html:196 msgid "Period" msgstr "" -#: forms.py:436 +#: forms.py:652 msgid "Find - Quick action - Modify single" msgstr "" -#: forms.py:449 +#: forms.py:665 msgid "Create" msgstr "" -#: forms.py:450 +#: forms.py:666 msgid "Update" msgstr "" -#: forms.py:452 forms.py:636 forms.py:982 forms.py:986 forms_treatments.py:180 -#: ishtar_menu.py:57 models_finds.py:926 -#: templates/ishtar/sheet_findbasket.html:4 views.py:646 +#: forms.py:668 forms.py:881 forms.py:1308 forms.py:1312 ishtar_menu.py:57 +#: models_finds.py:605 models_finds.py:1018 +#: templates/ishtar/sheet_findbasket.html:4 views.py:824 wizards.py:360 msgid "Basket" msgstr "" -#: forms.py:474 +#: forms.py:690 msgid "On update, you have to select a basket." msgstr "" -#: forms.py:478 +#: forms.py:694 forms.py:730 msgid "A label is required." msgstr "" -#: forms.py:481 -msgid "A basket with this label already exists." +#: forms.py:725 +msgid " - duplicate" msgstr "" -#: forms.py:498 templates/ishtar/sheet_find.html:102 +#: forms.py:743 templates/ishtar/sheet_find.html:175 msgid "Preservation" msgstr "" -#: forms.py:499 +#: forms.py:744 msgid "Find - 030 - Preservation" msgstr "" -#: forms.py:513 forms.py:648 models_finds.py:1015 +#: forms.py:758 forms.py:893 models_finds.py:1112 msgid "Integrity / interest" msgstr "" -#: forms.py:516 forms.py:650 models_finds.py:1018 +#: forms.py:761 forms.py:895 models_finds.py:1115 msgid "Remarkability" msgstr "" -#: forms.py:518 forms.py:646 models_finds.py:1056 +#: forms.py:763 forms.py:891 models_finds.py:1155 msgid "Conservatory state" msgstr "" -#: forms.py:521 models_finds.py:1065 +#: forms.py:766 models_finds.py:1164 msgid "Alteration" msgstr "" -#: forms.py:524 models_finds.py:1069 +#: forms.py:769 models_finds.py:1168 msgid "Alteration cause" msgstr "" -#: forms.py:527 models_finds.py:1062 +#: forms.py:772 models_finds.py:1161 msgid "Recommended treatments" msgstr "" -#: forms.py:529 models_finds.py:1073 +#: forms.py:774 models_finds.py:1172 msgid "Treatment emergency" msgstr "" -#: forms.py:531 models_finds.py:1048 +#: forms.py:776 models_finds.py:1147 msgid "Estimated value" msgstr "" -#: forms.py:532 models_finds.py:1076 +#: forms.py:777 models_finds.py:1175 msgid "Insurance value" msgstr "" -#: forms.py:534 models_finds.py:1078 +#: forms.py:779 models_finds.py:1177 msgid "Appraisal date" msgstr "" -#: forms.py:536 models_finds.py:1058 +#: forms.py:781 models_finds.py:1157 msgid "Conservatory comment" msgstr "" -#: forms.py:560 forms.py:584 models_finds.py:997 -#: templates/ishtar/sheet_find.html:119 +#: forms.py:805 forms.py:829 models_finds.py:1089 +#: templates/ishtar/sheet_find.html:192 msgid "Dating" msgstr "" -#: forms.py:566 forms_treatments.py:143 forms_treatments.py:370 -#: forms_treatments.py:580 models_finds.py:1722 models_treatments.py:148 -#: models_treatments.py:360 templates/ishtar/sheet_find.html:124 -#: templates/ishtar/sheet_find.html:185 templates/ishtar/sheet_find.html:223 +#: forms.py:811 forms_treatments.py:128 forms_treatments.py:442 +#: forms_treatments.py:659 models_finds.py:1964 models_treatments.py:166 +#: models_treatments.py:596 templates/ishtar/sheet_find.html:197 +#: templates/ishtar/sheet_find.html:265 templates/ishtar/sheet_find.html:302 +#: templates/ishtar/sheet_find.html:340 msgid "Start date" msgstr "" -#: forms.py:568 models_finds.py:1723 models_treatments.py:361 -#: templates/ishtar/sheet_find.html:125 templates/ishtar/sheet_find.html:186 -#: templates/ishtar/sheet_find.html:224 +#: forms.py:813 models_finds.py:1965 models_treatments.py:597 +#: templates/ishtar/sheet_find.html:198 templates/ishtar/sheet_find.html:266 +#: templates/ishtar/sheet_find.html:303 templates/ishtar/sheet_find.html:341 msgid "End date" msgstr "" -#: forms.py:569 templates/ishtar/sheet_find.html:127 +#: forms.py:814 templates/ishtar/sheet_find.html:200 msgid "Quality" msgstr "" -#: forms.py:571 templates/ishtar/sheet_find.html:126 +#: forms.py:816 templates/ishtar/sheet_find.html:199 msgid "Dating type" msgstr "" -#: forms.py:573 templates/ishtar/sheet_find.html:128 +#: forms.py:818 templates/ishtar/sheet_find.html:201 msgid "Precise dating" msgstr "" -#: forms.py:585 +#: forms.py:830 msgid "Find - 040 - Dating" msgstr "" -#: forms.py:592 +#: forms.py:837 msgid "Find - 001 - Search" msgstr "" -#: forms.py:595 forms.py:928 forms_treatments.py:50 forms_treatments.py:419 -#: forms_treatments.py:493 forms_treatments.py:686 +#: forms.py:840 forms.py:1216 forms_treatments.py:49 forms_treatments.py:491 +#: forms_treatments.py:565 forms_treatments.py:765 msgid "Full text search" msgstr "" -#: forms.py:598 models_finds.py:294 +#: forms.py:843 models_finds.py:309 msgid "Short ID" msgstr "" -#: forms.py:599 models_finds.py:297 +#: forms.py:844 models_finds.py:312 msgid "Complete ID" msgstr "" -#: forms.py:604 forms_treatments.py:56 forms_treatments.py:101 -#: forms_treatments.py:295 forms_treatments.py:423 forms_treatments.py:498 -#: forms_treatments.py:550 forms_treatments.py:690 models_treatments.py:122 -#: models_treatments.py:582 +#: forms.py:849 forms_treatments.py:55 forms_treatments.py:100 +#: forms_treatments.py:363 forms_treatments.py:495 forms_treatments.py:570 +#: forms_treatments.py:624 forms_treatments.py:769 models_treatments.py:137 +#: models_treatments.py:820 msgid "Year" msgstr "" -#: forms.py:606 +#: forms.py:851 msgid "Operation's number (index by year)" msgstr "" -#: forms.py:609 +#: forms.py:854 msgid "Code PATRIARCHE" msgstr "" -#: forms.py:613 +#: forms.py:858 msgid "Operation type" msgstr "" -#: forms.py:616 +#: forms.py:861 msgid "Areas" msgstr "" -#: forms.py:619 +#: forms.py:864 msgid "Archaeological site (attached to the operation)" msgstr "" -#: forms.py:625 +#: forms.py:870 msgid "Archaeological site (attached to the context record)" msgstr "" -#: forms.py:638 +#: forms.py:883 msgid "Search within related operations" msgstr "" -#: forms.py:640 +#: forms.py:885 msgid "Search within related context records" msgstr "" -#: forms.py:642 forms.py:893 models_finds.py:56 +#: forms.py:887 forms.py:1159 models_finds.py:56 msgid "Material type" msgstr "" -#: forms.py:643 models_finds.py:151 +#: forms.py:888 models_finds.py:166 msgid "Object type" msgstr "" -#: forms.py:645 +#: forms.py:890 msgid "Preservation type" msgstr "" -#: forms.py:656 forms_treatments.py:59 +#: forms.py:901 forms_treatments.py:58 msgid "Has an image?" msgstr "" -#: forms.py:703 -msgid "Warehouse (location)" +#: forms.py:902 +msgid "Loan?" +msgstr "" + +#: forms.py:904 +msgid "Treatment file end date before" +msgstr "" + +#: forms.py:953 +msgid "Reference container - Warehouse (location)" +msgstr "" + +#: forms.py:959 +msgid "Reference container - Warehouse (responsible)" msgstr "" -#: forms.py:709 -msgid "Warehouse (responsible)" +#: forms.py:965 +msgid "Reference container ID" msgstr "" -#: forms.py:714 -msgid "Container ID" +#: forms.py:967 +msgid "Reference container ref." msgstr "" -#: forms.py:715 -msgid "Container ref." +#: forms.py:969 +msgid "Current container - Warehouse (location)" msgstr "" -#: forms.py:720 forms.py:744 views.py:185 +#: forms.py:975 +msgid "Current container - Warehouse (responsible)" +msgstr "" + +#: forms.py:980 +msgid "Current container ID" +msgstr "" + +#: forms.py:981 +msgid "Current container ref." +msgstr "" + +#: forms.py:986 forms.py:1010 views.py:241 msgid "Find search" msgstr "" -#: forms.py:769 models_treatments.py:258 -#: templates/ishtar/sheet_treatment.html:56 +#: forms.py:1035 forms.py:1180 models_treatments.py:280 +#: templates/ishtar/sheet_treatment.html:102 msgid "Upstream finds" msgstr "" -#: forms.py:771 models_finds.py:1090 +#: forms.py:1037 models_finds.py:1193 #: templates/ishtar/forms/qa_find_treatment.html:11 +#: templates/ishtar/sheet_treatment.html:24 msgid "Finds" msgstr "" -#: forms.py:783 +#: forms.py:1049 msgid "You should at least select one archaeological find." msgstr "" -#: forms.py:886 -msgid "Resulting find" -msgstr "" - -#: forms.py:891 +#: forms.py:1157 msgid "Precise description" msgstr "" -#: forms.py:905 -msgid "Resulting finds" -msgstr "" - -#: forms.py:910 +#: forms.py:1176 msgid "Would you like to delete this find?" msgstr "" -#: forms.py:914 models_treatments.py:68 -msgid "Upstream find" -msgstr "" - -#: forms.py:925 +#: forms.py:1213 msgid "Find basket - 001 - Search" msgstr "" -#: forms.py:937 views.py:122 +#: forms.py:1225 forms.py:1240 views.py:164 msgid "Basket search" msgstr "" -#: forms.py:951 +#: forms.py:1254 msgid "Find basket" msgstr "" -#: forms.py:953 forms_treatments.py:54 forms_treatments.py:97 -#: models_treatments.py:118 templates/ishtar/sheet_find.html:179 -#: templates/ishtar/sheet_find.html:217 +#: forms.py:1258 forms_treatments.py:53 forms_treatments.py:122 +#: models_treatments.py:133 +#: templates/ishtar/forms/qa_findbasket_duplicate.html:15 +#: templates/ishtar/sheet_find.html:259 templates/ishtar/sheet_find.html:296 +#: templates/ishtar/sheet_find.html:334 msgid "Label" msgstr "" -#: forms.py:972 +#: forms.py:1264 forms.py:1277 +msgid "Shared (read) with" +msgstr "" + +#: forms.py:1269 forms.py:1282 +msgid "Shared (read/edit) with" +msgstr "" + +#: forms.py:1298 msgid "Another basket already exists with this name." msgstr "" -#: forms_treatments.py:55 forms_treatments.py:100 models_treatments.py:120 +#: forms_treatments.py:54 forms_treatments.py:125 models_treatments.py:135 msgid "Other ref." msgstr "" -#: forms_treatments.py:57 forms_treatments.py:232 forms_treatments.py:424 -#: forms_treatments.py:486 forms_treatments.py:499 forms_treatments.py:603 -#: forms_treatments.py:691 forms_treatments.py:758 models_treatments.py:123 -#: models_treatments.py:583 +#: forms_treatments.py:56 forms_treatments.py:295 forms_treatments.py:496 +#: forms_treatments.py:558 forms_treatments.py:571 forms_treatments.py:682 +#: forms_treatments.py:770 forms_treatments.py:837 models_treatments.py:138 +#: models_treatments.py:821 msgid "Index" msgstr "" -#: forms_treatments.py:58 forms_treatments.py:106 forms_treatments.py:378 -#: forms_treatments.py:440 models_finds.py:106 models_treatments.py:128 -#: models_treatments.py:359 +#: forms_treatments.py:57 forms_treatments.py:97 forms_treatments.py:450 +#: forms_treatments.py:512 models_finds.py:121 models_treatments.py:143 +#: models_treatments.py:595 msgid "Treatment type" msgstr "" -#: forms_treatments.py:71 views.py:420 +#: forms_treatments.py:70 views.py:479 msgid "Treatment search" msgstr "" -#: forms_treatments.py:83 -msgid "Base treatment" +#: forms_treatments.py:82 ishtar_menu.py:143 models_treatments.py:187 +#: models_treatments.py:587 templates/ishtar/sheet_treatment.html:4 +#: templates/ishtar/sheet_treatment.html:17 +msgid "Treatment" msgstr "" -#: forms_treatments.py:84 +#: forms_treatments.py:83 msgid "Treatment - 020 - General" msgstr "" -#: forms_treatments.py:108 models_treatments.py:70 models_treatments.py:130 -#: templates/ishtar/sheet_find.html:181 templates/ishtar/sheet_find.html:219 +#: forms_treatments.py:99 models_treatments.py:83 models_treatments.py:145 +#: templates/ishtar/sheet_find.html:261 templates/ishtar/sheet_find.html:298 +#: templates/ishtar/sheet_find.html:336 msgid "State" msgstr "" -#: forms_treatments.py:110 -msgid "Target" +#: forms_treatments.py:105 models_treatments.py:151 models_treatments.py:598 +msgid "Location" msgstr "" -#: forms_treatments.py:112 forms_treatments.py:301 forms_treatments.py:561 -#: models_treatments.py:71 models_treatments.py:138 +#: forms_treatments.py:111 forms_treatments.py:369 forms_treatments.py:635 +#: models_treatments.py:84 models_treatments.py:156 msgid "Responsible" msgstr "" -#: forms_treatments.py:118 forms_treatments.py:307 models_treatments.py:141 +#: forms_treatments.py:117 forms_treatments.py:375 models_treatments.py:159 msgid "Organization" msgstr "" -#: forms_treatments.py:124 models_treatments.py:133 models_treatments.py:362 -msgid "Location" -msgstr "" - -#: forms_treatments.py:130 -msgid "Container (relevant for packaging)" +#: forms_treatments.py:130 forms_treatments.py:442 forms_treatments.py:665 +#: forms_treatments.py:718 models_treatments.py:167 models_treatments.py:841 +msgid "Closing date" msgstr "" -#: forms_treatments.py:136 forms_treatments.py:557 -msgid "External ref." +#: forms_treatments.py:133 +msgid "Destination container (relevant for treatment that change location)" msgstr "" -#: forms_treatments.py:137 models_treatments.py:147 +#: forms_treatments.py:139 models_treatments.py:165 msgid "Goal" msgstr "" -#: forms_treatments.py:145 forms_treatments.py:370 forms_treatments.py:586 -#: forms_treatments.py:639 models_treatments.py:149 models_treatments.py:603 -msgid "Closing date" -msgstr "" - -#: forms_treatments.py:147 +#: forms_treatments.py:145 #, python-brace-format msgid "Estimated cost ({currency})" msgstr "" -#: forms_treatments.py:149 +#: forms_treatments.py:147 #, python-brace-format msgid "Quoted cost ({currency})" msgstr "" -#: forms_treatments.py:151 +#: forms_treatments.py:149 #, python-brace-format msgid "Realized cost ({currency})" msgstr "" -#: forms_treatments.py:153 +#: forms_treatments.py:151 #, python-brace-format msgid "Insurance cost ({currency})" msgstr "" -#: forms_treatments.py:180 -msgid "Single find" +#: forms_treatments.py:212 +msgid "Unknow treatment type" msgstr "" -#: forms_treatments.py:204 +#: forms_treatments.py:233 forms_treatments.py:242 +msgid "{} is not compatible with {} treatment(s)." +msgstr "" + +#: forms_treatments.py:253 msgid "" -"The container field is attached to the treatment. If no packaging treatment " -"is done it is not relevant." +"The container field is attached to the treatment but no treatment with " +"container change is defined." msgstr "" -#: forms_treatments.py:209 -msgid "If a packaging treatment is done, the container field must be filled." +#: forms_treatments.py:258 +msgid "" +"A treatment with location change is defined, the container field must be " +"filled." msgstr "" -#: forms_treatments.py:213 +#: forms_treatments.py:262 msgid "A responsible or an organization must be defined." msgstr "" -#: forms_treatments.py:256 +#: forms_treatments.py:267 +msgid "Treatment n-1 - 020 - General" +msgstr "" + +#: forms_treatments.py:281 +msgid "Treatment 1-n - 020 - General" +msgstr "" + +#: forms_treatments.py:319 msgid "Another treatment with this index exists for {}." msgstr "" -#: forms_treatments.py:262 models_treatments.py:126 +#: forms_treatments.py:325 models_treatments.py:141 msgid "Associated request" msgstr "" -#: forms_treatments.py:263 +#: forms_treatments.py:326 msgid "Treatment - 010 - Request choice" msgstr "" -#: forms_treatments.py:268 forms_treatments.py:541 ishtar_menu.py:95 -#: models_treatments.py:618 models_treatments.py:646 -#: templates/ishtar/sheet_treatmentfile.html:4 wizards.py:207 +#: forms_treatments.py:331 forms_treatments.py:613 ishtar_menu.py:95 +#: models_treatments.py:860 models_treatments.py:882 +#: templates/ishtar/sheet_treatmentfile.html:4 wizards.py:465 msgid "Treatment request" msgstr "" -#: forms_treatments.py:277 +#: forms_treatments.py:340 msgid "" "Are you sure you want to delete this treatment? All changes made to the " "associated finds since this treatment record will be lost!" msgstr "" -#: forms_treatments.py:280 +#: forms_treatments.py:343 msgid "Would you like to delete this treatment?" msgstr "" -#: forms_treatments.py:285 models_finds.py:683 models_finds.py:1000 -#: models_treatments.py:150 models_treatments.py:363 -#: templates/ishtar/sheet_find.html:184 templates/ishtar/sheet_find.html:222 +#: forms_treatments.py:348 models_finds.py:1092 models_treatments.py:169 +#: models_treatments.py:599 templates/ishtar/sheet_find.html:264 +#: templates/ishtar/sheet_find.html:301 templates/ishtar/sheet_find.html:339 msgid "Container" msgstr "" -#: forms_treatments.py:291 +#: forms_treatments.py:354 templates/ishtar/forms/qa_find_treatment.html:31 +msgid "Change the reference container" +msgstr "" + +#: forms_treatments.py:356 +msgid "If unchecked the current container will be changed" +msgstr "" + +#: forms_treatments.py:359 msgid "Create a treatment" msgstr "" -#: forms_treatments.py:298 +#: forms_treatments.py:366 msgid "Precise date" msgstr "" -#: forms_treatments.py:340 +#: forms_treatments.py:408 msgid "At least a year is required." msgstr "" -#: forms_treatments.py:369 +#: forms_treatments.py:416 models_finds.py:1022 models_finds.py:1304 +#: templates/ishtar/forms/qa_find_treatment.html:16 views.py:844 +msgid "Packaging" +msgstr "" + +#: forms_treatments.py:441 msgid "months" msgstr "" -#: forms_treatments.py:369 +#: forms_treatments.py:441 msgid "years" msgstr "" -#: forms_treatments.py:374 forms_treatments.py:643 +#: forms_treatments.py:446 forms_treatments.py:722 msgid "Slicing" msgstr "" -#: forms_treatments.py:377 forms_treatments.py:646 +#: forms_treatments.py:449 forms_treatments.py:725 msgid "Date get from" msgstr "" -#: forms_treatments.py:380 forms_treatments.py:649 +#: forms_treatments.py:452 forms_treatments.py:728 msgid "Date after" msgstr "" -#: forms_treatments.py:382 forms_treatments.py:651 +#: forms_treatments.py:454 forms_treatments.py:730 msgid "Date before" msgstr "" -#: forms_treatments.py:425 forms_treatments.py:475 forms_treatments.py:692 -#: forms_treatments.py:747 +#: forms_treatments.py:497 forms_treatments.py:547 forms_treatments.py:771 +#: forms_treatments.py:826 msgid "Act type" msgstr "" -#: forms_treatments.py:426 forms_treatments.py:693 +#: forms_treatments.py:498 forms_treatments.py:772 msgid "Indexed?" msgstr "" -#: forms_treatments.py:427 forms_treatments.py:694 +#: forms_treatments.py:499 forms_treatments.py:773 msgid "Object" msgstr "" -#: forms_treatments.py:431 forms_treatments.py:698 +#: forms_treatments.py:503 forms_treatments.py:777 msgid "Signature date after" msgstr "" -#: forms_treatments.py:433 forms_treatments.py:700 +#: forms_treatments.py:505 forms_treatments.py:779 msgid "Signature date before" msgstr "" -#: forms_treatments.py:435 +#: forms_treatments.py:507 msgid "Treatment name" msgstr "" -#: forms_treatments.py:436 +#: forms_treatments.py:508 msgid "Treatment year" msgstr "" -#: forms_treatments.py:437 +#: forms_treatments.py:509 msgid "Treatment index" msgstr "" -#: forms_treatments.py:439 +#: forms_treatments.py:511 msgid "Treatment internal reference" msgstr "" -#: forms_treatments.py:443 forms_treatments.py:714 +#: forms_treatments.py:515 forms_treatments.py:793 msgid "Modified by" msgstr "" -#: forms_treatments.py:473 +#: forms_treatments.py:545 msgid "Treatment - Administrative act - General" msgstr "" -#: forms_treatments.py:496 forms_treatments.py:548 models_treatments.py:588 +#: forms_treatments.py:568 forms_treatments.py:622 models_treatments.py:826 msgid "Name" msgstr "" -#: forms_treatments.py:497 forms_treatments.py:555 +#: forms_treatments.py:569 forms_treatments.py:629 msgid "Internal ref." msgstr "" -#: forms_treatments.py:500 forms_treatments.py:559 models_treatments.py:69 -#: templates/ishtar/sheet_find.html:180 templates/ishtar/sheet_find.html:218 +#: forms_treatments.py:572 forms_treatments.py:633 models_treatments.py:82 +#: templates/ishtar/sheet_find.html:260 templates/ishtar/sheet_find.html:297 +#: templates/ishtar/sheet_find.html:335 msgid "Type" msgstr "" -#: forms_treatments.py:503 +#: forms_treatments.py:575 msgid "In charge" msgstr "" -#: forms_treatments.py:509 forms_treatments.py:567 models_treatments.py:597 -#: templates/ishtar/sheet_treatmentfile.html:45 +#: forms_treatments.py:581 forms_treatments.py:641 models_treatments.py:835 +#: templates/ishtar/sheet_treatmentfile.html:46 msgid "Applicant" msgstr "" -#: forms_treatments.py:515 forms_treatments.py:573 models_treatments.py:601 -#: templates/ishtar/sheet_treatmentfile.html:53 +#: forms_treatments.py:587 forms_treatments.py:647 models_treatments.py:839 +#: templates/ishtar/sheet_treatmentfile.html:54 msgid "Applicant organisation" msgstr "" -#: forms_treatments.py:529 views.py:524 +#: forms_treatments.py:601 views.py:681 msgid "Treatment request search" msgstr "" -#: forms_treatments.py:584 forms_treatments.py:638 models_treatments.py:607 +#: forms_treatments.py:631 +msgid "External ref." +msgstr "" + +#: forms_treatments.py:653 +msgid "Associated basket" +msgstr "" + +#: forms_treatments.py:663 forms_treatments.py:717 models_treatments.py:845 msgid "Reception date" msgstr "" -#: forms_treatments.py:626 +#: forms_treatments.py:705 msgid "Another treatment request with this index exists for {}." msgstr "" -#: forms_treatments.py:632 +#: forms_treatments.py:711 msgid "Are you sure you want to delete this treatment request?" msgstr "" -#: forms_treatments.py:633 +#: forms_treatments.py:712 msgid "Would you like to delete this treatment request?" msgstr "" -#: forms_treatments.py:637 models_treatments.py:605 +#: forms_treatments.py:716 models_treatments.py:843 msgid "Creation date" msgstr "" -#: forms_treatments.py:647 forms_treatments.py:711 models_treatments.py:519 -#: models_treatments.py:590 +#: forms_treatments.py:726 forms_treatments.py:790 models_treatments.py:757 +#: models_treatments.py:828 msgid "Treatment request type" msgstr "" -#: forms_treatments.py:703 +#: forms_treatments.py:782 msgid "Treatment request name" msgstr "" -#: forms_treatments.py:705 +#: forms_treatments.py:784 msgid "Treatment request year" msgstr "" -#: forms_treatments.py:707 +#: forms_treatments.py:786 msgid "Treatment request index" msgstr "" -#: forms_treatments.py:709 +#: forms_treatments.py:788 msgid "Treatment request internal reference" msgstr "" -#: forms_treatments.py:745 +#: forms_treatments.py:824 msgid "Treatment request - Administrative act - General" msgstr "" #: ishtar_menu.py:37 ishtar_menu.py:60 ishtar_menu.py:100 ishtar_menu.py:123 -#: ishtar_menu.py:155 ishtar_menu.py:179 +#: ishtar_menu.py:148 ishtar_menu.py:181 msgid "Search" msgstr "" #: ishtar_menu.py:42 ishtar_menu.py:65 ishtar_menu.py:105 ishtar_menu.py:127 -#: ishtar_menu.py:160 ishtar_menu.py:183 +#: ishtar_menu.py:185 msgid "Creation" msgstr "" #: ishtar_menu.py:47 ishtar_menu.py:70 ishtar_menu.py:110 ishtar_menu.py:131 -#: ishtar_menu.py:165 ishtar_menu.py:188 +#: ishtar_menu.py:168 ishtar_menu.py:190 msgid "Modification" msgstr "" #: ishtar_menu.py:52 ishtar_menu.py:82 ishtar_menu.py:115 ishtar_menu.py:134 -#: ishtar_menu.py:170 ishtar_menu.py:191 +#: ishtar_menu.py:173 ishtar_menu.py:193 msgid "Deletion" msgstr "" @@ -863,22 +971,20 @@ msgstr "" msgid "Manage items" msgstr "" -#: ishtar_menu.py:120 ishtar_menu.py:176 models_finds.py:1719 +#: ishtar_menu.py:120 ishtar_menu.py:178 models_finds.py:1961 msgid "Administrative act" msgstr "" -#: ishtar_menu.py:138 ishtar_menu.py:195 models_finds.py:1081 -#: models_treatments.py:163 models_treatments.py:611 -msgid "Documents" +#: ishtar_menu.py:154 +msgid "Simple treatment - creation" msgstr "" -#: ishtar_menu.py:147 models_treatments.py:170 models_treatments.py:351 -#: templates/ishtar/sheet_treatment.html:4 -msgid "Treatment" +#: ishtar_menu.py:159 +msgid "Treatment many to one - creation" msgstr "" -#: ishtar_menu.py:152 -msgid "Simple treatments" +#: ishtar_menu.py:164 +msgid "Treatment one to many - creation" msgstr "" #: models_finds.py:51 @@ -889,9 +995,9 @@ msgstr "" msgid "Recommendation" msgstr "" -#: models_finds.py:66 models_finds.py:79 models_finds.py:92 models_finds.py:138 -#: models_finds.py:161 models_finds.py:218 models_finds.py:967 -#: models_treatments.py:355 +#: models_finds.py:66 models_finds.py:79 models_finds.py:92 models_finds.py:153 +#: models_finds.py:176 models_finds.py:233 models_finds.py:1059 +#: models_treatments.py:45 models_treatments.py:591 msgid "Order" msgstr "" @@ -904,12 +1010,10 @@ msgid "Material type quality types" msgstr "" #: models_finds.py:82 -#| msgid "Conservatory state" msgid "Conservatory state type" msgstr "" #: models_finds.py:83 -#| msgid "Conservatory states" msgid "Conservatory state types" msgstr "" @@ -917,573 +1021,697 @@ msgstr "" msgid "Virtual" msgstr "" -#: models_finds.py:95 -msgid "Upstream is many" +#: models_finds.py:94 +msgid "Destructive" +msgstr "" + +#: models_finds.py:96 +msgid "Create a new find" msgstr "" #: models_finds.py:97 -msgid "Check this if for this treatment from many finds you'll get one." +msgid "" +"If True when this treatment is applied a new version of the object will be " +"created." msgstr "" #: models_finds.py:100 -msgid "Downstream is many" +msgid "Upstream is many" msgstr "" #: models_finds.py:102 +msgid "Check this if for this treatment from many finds you'll get one." +msgstr "" + +#: models_finds.py:105 +msgid "Downstream is many" +msgstr "" + +#: models_finds.py:107 msgid "Check this if for this treatment from one find you'll get many." msgstr "" -#: models_finds.py:107 models_treatments.py:240 -msgid "Treatment types" +#: models_finds.py:110 +msgid "Change reference location" +msgstr "" + +#: models_finds.py:111 +msgid "The treatment change the reference location." +msgstr "" + +#: models_finds.py:113 +msgid "Change current location" +msgstr "" + +#: models_finds.py:114 +msgid "The treatment change the current location." +msgstr "" + +#: models_finds.py:116 +msgid "Restore the reference location" msgstr "" #: models_finds.py:117 +msgid "" +"The treatment change restore reference location to the current location." +msgstr "" + +#: models_finds.py:122 models_treatments.py:262 +msgid "Treatment types" +msgstr "" + +#: models_finds.py:132 msgid "Integrity / interest type" msgstr "" -#: models_finds.py:118 +#: models_finds.py:133 msgid "Integrity / interest types" msgstr "" -#: models_finds.py:128 +#: models_finds.py:143 msgid "Remarkability type" msgstr "" -#: models_finds.py:129 +#: models_finds.py:144 msgid "Remarkability types" msgstr "" -#: models_finds.py:140 +#: models_finds.py:155 msgid "Batch type" msgstr "" -#: models_finds.py:141 +#: models_finds.py:156 msgid "Batch types" msgstr "" -#: models_finds.py:164 +#: models_finds.py:179 msgid "Object type quality type" msgstr "" -#: models_finds.py:165 +#: models_finds.py:180 msgid "Object type quality types" msgstr "" -#: models_finds.py:175 +#: models_finds.py:190 msgid "Alteration type" msgstr "" -#: models_finds.py:176 +#: models_finds.py:191 msgid "Alteration types" msgstr "" -#: models_finds.py:186 +#: models_finds.py:201 msgid "Alteration cause type" msgstr "" -#: models_finds.py:187 +#: models_finds.py:202 msgid "Alteration cause types" msgstr "" -#: models_finds.py:197 +#: models_finds.py:212 msgid "Treatment emergency type" msgstr "" -#: models_finds.py:198 +#: models_finds.py:213 msgid "Treatment emergency types" msgstr "" -#: models_finds.py:208 +#: models_finds.py:223 msgid "Communicability type" msgstr "" -#: models_finds.py:209 +#: models_finds.py:224 msgid "Communicability types" msgstr "" -#: models_finds.py:221 +#: models_finds.py:236 msgid "Checked type" msgstr "" -#: models_finds.py:222 +#: models_finds.py:237 msgid "Checked types" msgstr "" -#: models_finds.py:254 models_finds.py:960 models_treatments.py:143 -#: models_treatments.py:586 +#: models_finds.py:269 models_finds.py:1052 models_treatments.py:161 +#: models_treatments.py:824 msgid "External ID" msgstr "" -#: models_finds.py:256 models_finds.py:962 +#: models_finds.py:271 models_finds.py:1054 msgid "External ID is set automatically" msgstr "" -#: models_finds.py:260 +#: models_finds.py:275 msgid "Special interest" msgstr "" -#: models_finds.py:264 +#: models_finds.py:279 msgid "Context Record" msgstr "" -#: models_finds.py:272 +#: models_finds.py:287 msgid "Material index" msgstr "" -#: models_finds.py:289 +#: models_finds.py:304 msgid "Point (3D)" msgstr "" -#: models_finds.py:295 models_finds.py:298 +#: models_finds.py:310 models_finds.py:313 msgid "Cached value - do not edit" msgstr "" -#: models_finds.py:308 models_finds.py:958 +#: models_finds.py:323 models_finds.py:1050 msgid "Base find" msgstr "" -#: models_finds.py:309 +#: models_finds.py:324 msgid "Base finds" msgstr "" -#: models_finds.py:565 +#: models_finds.py:589 msgid "g" msgstr "" -#: models_finds.py:566 +#: models_finds.py:590 msgid "kg" msgstr "" -#: models_finds.py:592 views.py:301 +#: models_finds.py:600 views.py:863 views.py:882 +msgid "Duplicate" +msgstr "" + +#: models_finds.py:626 views.py:379 msgid "Manage basket" msgstr "" -#: models_finds.py:661 +#: models_finds.py:633 models_finds.py:1299 +msgid "Add treatment" +msgstr "" + +#: models_finds.py:723 msgid "Base find - Short ID" msgstr "" -#: models_finds.py:662 +#: models_finds.py:724 msgid "Base find - Complete ID" msgstr "" -#: models_finds.py:664 +#: models_finds.py:726 msgid "Operation (code)" msgstr "" -#: models_finds.py:666 +#: models_finds.py:728 msgid "Town" msgstr "" -#: models_finds.py:668 +#: models_finds.py:730 msgid "Operation (name)" msgstr "" -#: models_finds.py:672 +#: models_finds.py:734 msgid "Parcel" msgstr "" -#: models_finds.py:673 +#: models_finds.py:735 msgid "Batch" msgstr "" -#: models_finds.py:674 +#: models_finds.py:736 msgid "Base find - Comment" msgstr "" -#: models_finds.py:675 +#: models_finds.py:737 msgid "Base find - Description" msgstr "" -#: models_finds.py:676 +#: models_finds.py:738 msgid "Base find - Topographic localisation" msgstr "" -#: models_finds.py:678 +#: models_finds.py:740 msgid "Base find - Special interest" msgstr "" -#: models_finds.py:680 +#: models_finds.py:742 msgid "Base find - Discovery date (exact or TPQ)" msgstr "" -#: models_finds.py:682 +#: models_finds.py:744 msgid "Base find - Discovery date (TAQ)" msgstr "" -#: models_finds.py:684 +#: models_finds.py:745 +msgid "Current container" +msgstr "" + +#: models_finds.py:746 models_finds.py:1097 +msgid "Reference container" +msgstr "" + +#: models_finds.py:747 msgid "Periods" msgstr "" -#: models_finds.py:760 +#: models_finds.py:823 msgctxt "key for text search" msgid "short-id" msgstr "" -#: models_finds.py:764 +#: models_finds.py:827 msgctxt "key for text search" msgid "complete-id" msgstr "" -#: models_finds.py:768 +#: models_finds.py:831 msgctxt "key for text search" msgid "free-id" msgstr "" -#: models_finds.py:772 +#: models_finds.py:835 msgctxt "key for text search" msgid "denomination" msgstr "" -#: models_finds.py:776 +#: models_finds.py:839 msgctxt "key for text search" msgid "town" msgstr "" -#: models_finds.py:780 models_treatments.py:87 models_treatments.py:551 +#: models_finds.py:843 models_treatments.py:102 models_treatments.py:789 msgctxt "key for text search" msgid "year" msgstr "" -#: models_finds.py:784 +#: models_finds.py:847 msgctxt "key for text search" msgid "operation-code" msgstr "" -#: models_finds.py:788 +#: models_finds.py:851 msgctxt "key for text search" msgid "code-patriarche" msgstr "" -#: models_finds.py:792 +#: models_finds.py:855 msgctxt "key for text search" msgid "operation-type" msgstr "" -#: models_finds.py:797 +#: models_finds.py:860 msgctxt "key for text search" msgid "area" msgstr "" -#: models_finds.py:801 +#: models_finds.py:864 msgctxt "key for text search" msgid "site" msgstr "" -#: models_finds.py:806 models_finds.py:945 +#: models_finds.py:869 models_finds.py:1037 msgctxt "key for text search" msgid "context-record-site" msgstr "" -#: models_finds.py:811 models_finds.py:939 +#: models_finds.py:874 models_finds.py:1031 msgctxt "key for text search" msgid "context-record" msgstr "" -#: models_finds.py:815 +#: models_finds.py:878 msgctxt "key for text search" msgid "operation-relation-type" msgstr "" -#: models_finds.py:819 +#: models_finds.py:882 msgctxt "key for text search" msgid "context-record-relation-type" msgstr "" -#: models_finds.py:823 +#: models_finds.py:886 msgctxt "key for text search" msgid "period" msgstr "" -#: models_finds.py:827 +#: models_finds.py:890 msgctxt "key for text search" msgid "material" msgstr "" -#: models_finds.py:831 +#: models_finds.py:894 msgctxt "key for text search" msgid "object-type" msgstr "" -#: models_finds.py:835 +#: models_finds.py:898 msgctxt "key for text search" msgid "preservation" msgstr "" -#: models_finds.py:839 +#: models_finds.py:902 msgctxt "key for text search" msgid "conservatory" msgstr "" -#: models_finds.py:843 +#: models_finds.py:906 msgctxt "key for text search" msgid "integrity" msgstr "" -#: models_finds.py:847 +#: models_finds.py:910 msgctxt "key for text search" msgid "remarkability" msgstr "" -#: models_finds.py:851 +#: models_finds.py:914 msgctxt "key for text search" msgid "description" msgstr "" -#: models_finds.py:855 +#: models_finds.py:918 msgctxt "key for text search" msgid "batch" msgstr "" -#: models_finds.py:859 +#: models_finds.py:922 msgctxt "key for text search" msgid "checked" msgstr "" -#: models_finds.py:863 models_treatments.py:95 +#: models_finds.py:926 models_treatments.py:110 msgctxt "key for text search" msgid "has-image" msgstr "" -#: models_finds.py:867 models_finds.py:942 +#: models_finds.py:930 models_finds.py:1034 msgctxt "key for text search" msgid "location" msgstr "" -#: models_finds.py:871 +#: models_finds.py:934 msgctxt "key for text search" msgid "warehouse" msgstr "" -#: models_finds.py:875 +#: models_finds.py:938 msgctxt "key for text search" msgid "container-index" msgstr "" -#: models_finds.py:879 +#: models_finds.py:942 msgctxt "key for text search" msgid "container-ref" msgstr "" -#: models_finds.py:883 +#: models_finds.py:946 +msgctxt "key for text search" +msgid "current-location" +msgstr "" + +#: models_finds.py:950 +msgctxt "key for text search" +msgid "current-warehouse" +msgstr "" + +#: models_finds.py:954 +msgctxt "key for text search" +msgid "current-container-index" +msgstr "" + +#: models_finds.py:958 +msgctxt "key for text search" +msgid "current-container-ref" +msgstr "" + +#: models_finds.py:962 wizards.py:399 msgctxt "key for text search" msgid "basket" msgstr "" -#: models_finds.py:887 models_finds.py:936 +#: models_finds.py:966 models_finds.py:1028 msgctxt "key for text search" msgid "operation" msgstr "" -#: models_finds.py:891 +#: models_finds.py:970 msgctxt "key for text search" msgid "last-modified-by" msgstr "" -#: models_finds.py:895 +#: models_finds.py:974 msgctxt "key for text search" msgid "modified-since" msgstr "" -#: models_finds.py:919 -msgid "Bulk update" +#: models_finds.py:978 +msgctxt "key for text search" +msgid "created-by" msgstr "" -#: models_finds.py:930 models_finds.py:1180 -#: templates/ishtar/forms/qa_find_treatment.html:16 views.py:666 -msgid "Packaging" +#: models_finds.py:982 +msgctxt "key for text search" +msgid "loan" msgstr "" #: models_finds.py:986 +msgctxt "key for text search" +msgid "treatment-end-date-before" +msgstr "" + +#: models_finds.py:1011 +msgid "Bulk update" +msgstr "" + +#: models_finds.py:1078 msgid "Weight" msgstr "" -#: models_finds.py:987 +#: models_finds.py:1079 msgid "Weight unit" msgstr "" -#: models_finds.py:993 templates/ishtar/sheet_find.html:174 +#: models_finds.py:1085 templates/ishtar/sheet_find.html:291 msgid "Upstream treatment" msgstr "" -#: models_finds.py:996 templates/ishtar/sheet_find.html:212 +#: models_finds.py:1088 templates/ishtar/sheet_find.html:329 msgid "Downstream treatment" msgstr "" -#: models_finds.py:1031 +#: models_finds.py:1130 msgid "Clutter - long side (cm)" msgstr "" -#: models_finds.py:1033 +#: models_finds.py:1132 msgid "Clutter - short side (cm)" msgstr "" -#: models_finds.py:1035 +#: models_finds.py:1134 msgid "Clutter - height (cm)" msgstr "" -#: models_finds.py:1051 +#: models_finds.py:1150 msgid "Collection" msgstr "" -#: models_finds.py:1083 models_treatments.py:165 models_treatments.py:613 +#: models_finds.py:1180 models_treatments.py:180 models_treatments.py:849 +#: templates/ishtar/sheet_find.html:56 templates/ishtar/sheet_treatment.html:32 +msgid "Documents" +msgstr "" + +#: models_finds.py:1183 models_treatments.py:188 +#: templates/ishtar/sheet_find.html:254 +#: templates/ishtar/sheet_treatmentfile.html:62 +msgid "Treatments" +msgstr "" + +#: models_finds.py:1185 +msgid "Related treatments when no new find is created" +msgstr "" + +#: models_finds.py:1186 models_treatments.py:182 models_treatments.py:855 msgid "Cached name" msgstr "" -#: models_finds.py:1105 +#: models_finds.py:1208 msgid "FIND" msgstr "" -#: models_finds.py:1174 +#: models_finds.py:1296 msgid "Add to basket" msgstr "" -#: models_finds.py:1222 wizards.py:74 wizards.py:219 +#: models_finds.py:1346 wizards.py:85 wizards.py:477 msgid "Operation" msgstr "" -#: models_finds.py:1544 +#: models_finds.py:1738 +msgid "No reference container have been set - the localisation cannot be set." +msgstr "" + +#: models_finds.py:1742 msgid "No container have been set - the localisation cannot be set." msgstr "" -#: models_finds.py:1550 +#: models_finds.py:1748 msgid "The division number {} have not been set for the warehouse {}." msgstr "" -#: models_finds.py:1720 +#: models_finds.py:1962 msgid "Person" msgstr "" -#: models_finds.py:1726 +#: models_finds.py:1968 msgid "Property" msgstr "" -#: models_finds.py:1727 +#: models_finds.py:1969 msgid "Properties" msgstr "" -#: models_treatments.py:42 +#: models_treatments.py:44 +msgid "Treatment is executed" +msgstr "" + +#: models_treatments.py:48 msgid "Treatment state type" msgstr "" -#: models_treatments.py:43 +#: models_treatments.py:49 msgid "Treatment state types" msgstr "" -#: models_treatments.py:67 +#: models_treatments.py:80 msgid "Downstream find" msgstr "" -#: models_treatments.py:79 +#: models_treatments.py:81 +msgid "Upstream find" +msgstr "" + +#: models_treatments.py:94 msgctxt "key for text search" msgid "label" msgstr "" -#: models_treatments.py:83 +#: models_treatments.py:98 msgctxt "key for text search" msgid "other-reference" msgstr "" -#: models_treatments.py:91 models_treatments.py:555 +#: models_treatments.py:106 models_treatments.py:793 msgctxt "key for text search" msgid "index" msgstr "" -#: models_treatments.py:99 models_treatments.py:559 +#: models_treatments.py:114 models_treatments.py:797 msgctxt "key for text search" msgid "type" msgstr "" -#: models_treatments.py:135 +#: models_treatments.py:149 +msgid "Treatment have been executed" +msgstr "" + +#: models_treatments.py:153 msgid "Location where the treatment is done. Target warehouse for a move." msgstr "" -#: models_treatments.py:152 +#: models_treatments.py:171 msgid "Estimated cost" msgstr "" -#: models_treatments.py:154 +#: models_treatments.py:173 msgid "Quoted cost" msgstr "" -#: models_treatments.py:156 +#: models_treatments.py:175 msgid "Realized cost" msgstr "" -#: models_treatments.py:158 +#: models_treatments.py:177 msgid "Insurance cost" msgstr "" -#: models_treatments.py:160 -msgid "Target a basket" +#: models_treatments.py:208 +msgid "TREATMENT" msgstr "" -#: models_treatments.py:171 templates/ishtar/sheet_find.html:171 -#: templates/ishtar/sheet_treatmentfile.html:61 -msgid "Treatments" +#: models_treatments.py:271 templates/ishtar/sheet_treatment.html:107 +msgid "Downstream finds" msgstr "" -#: models_treatments.py:190 -msgid "TREATMENT" +#: models_treatments.py:289 models_treatments.py:911 +msgid "Add associated administrative act" msgstr "" -#: models_treatments.py:249 templates/ishtar/sheet_treatment.html:61 -msgid "Downstream finds" +#: models_treatments.py:290 models_treatments.py:912 +msgid "admin. act" msgstr "" -#: models_treatments.py:364 templates/ishtar/sheet_find.html:183 -#: templates/ishtar/sheet_find.html:221 +#: models_treatments.py:600 templates/ishtar/sheet_find.html:263 +#: templates/ishtar/sheet_find.html:300 templates/ishtar/sheet_find.html:338 msgid "Doer" msgstr "" -#: models_treatments.py:365 models_treatments.py:366 +#: models_treatments.py:601 models_treatments.py:602 +#: templates/ishtar/sheet_treatment.html:97 msgid "Related finds" msgstr "" -#: models_treatments.py:508 +#: models_treatments.py:744 msgid "Is upstream" msgstr "" -#: models_treatments.py:520 +#: models_treatments.py:758 msgid "Treatment request types" msgstr "" -#: models_treatments.py:543 +#: models_treatments.py:781 msgctxt "key for text search" msgid "name" msgstr "" -#: models_treatments.py:547 +#: models_treatments.py:785 msgctxt "key for text search" msgid "reference" msgstr "" -#: models_treatments.py:563 +#: models_treatments.py:801 msgctxt "key for text search" msgid "in-charge" msgstr "" -#: models_treatments.py:567 +#: models_treatments.py:805 msgctxt "key for text search" msgid "applicant" msgstr "" -#: models_treatments.py:571 +#: models_treatments.py:809 msgctxt "key for text search" msgid "applicant-organisation" msgstr "" -#: models_treatments.py:584 +#: models_treatments.py:822 msgid "Internal reference" msgstr "" -#: models_treatments.py:593 +#: models_treatments.py:831 msgid "Person in charge" msgstr "" -#: models_treatments.py:619 +#: models_treatments.py:861 msgid "Treatment requests" msgstr "" +#: models_treatments.py:924 +msgid "Add associated treatment" +msgstr "" + +#: templates/ishtar/blocks/window_find_nav.html:9 +msgid "Baskets" +msgstr "" + #: templates/ishtar/forms/qa_find_basket.html:22 msgid "New" msgstr "" @@ -1492,49 +1720,54 @@ msgstr "" msgid "Add" msgstr "" -#: templates/ishtar/forms/qa_find_treatment.html:31 +#: templates/ishtar/forms/qa_find_treatment.html:37 msgid "Associate a treatment" msgstr "" -#: templates/ishtar/sheet_basefind.html:6 +#: templates/ishtar/forms/qa_findbasket_duplicate.html:6 +msgid "" +"Items of the basket will be attached to the new basket but not the shares." +msgstr "" + +#: templates/ishtar/sheet_basefind.html:10 msgid "Internal ID" msgstr "" -#: templates/ishtar/sheet_basefind.html:21 +#: templates/ishtar/sheet_basefind.html:25 msgid "Discovery date" msgstr "" -#: templates/ishtar/sheet_basefind.html:24 +#: templates/ishtar/sheet_basefind.html:28 msgid "Discovery year" msgstr "" -#: templates/ishtar/sheet_basefind.html:27 +#: templates/ishtar/sheet_basefind.html:31 msgid "Discovery date (TPQ)" msgstr "" -#: templates/ishtar/sheet_basefind.html:52 +#: templates/ishtar/sheet_basefind.html:56 msgid "X:" msgstr "" -#: templates/ishtar/sheet_basefind.html:53 -#: templates/ishtar/sheet_basefind.html:55 #: templates/ishtar/sheet_basefind.html:57 +#: templates/ishtar/sheet_basefind.html:59 +#: templates/ishtar/sheet_basefind.html:61 msgid "error:" msgstr "" -#: templates/ishtar/sheet_basefind.html:54 +#: templates/ishtar/sheet_basefind.html:58 msgid "Y:" msgstr "" -#: templates/ishtar/sheet_basefind.html:56 +#: templates/ishtar/sheet_basefind.html:60 msgid "Z:" msgstr "" -#: templates/ishtar/sheet_basefind.html:60 +#: templates/ishtar/sheet_basefind.html:64 msgid "SRID" msgstr "" -#: templates/ishtar/sheet_basefind.html:75 +#: templates/ishtar/sheet_basefind.html:79 msgid "Last modified by" msgstr "" @@ -1544,65 +1777,85 @@ msgid "" "the find." msgstr "" -#: templates/ishtar/sheet_find.html:29 -msgid "Associated base finds" +#: templates/ishtar/sheet_find.html:23 +msgid "Image / Base find" +msgstr "" + +#: templates/ishtar/sheet_find.html:30 +msgid "Identification / Description / Dimensions" +msgstr "" + +#: templates/ishtar/sheet_find.html:38 +msgid "Datings / Preservation" +msgstr "" + +#: templates/ishtar/sheet_find.html:47 +msgid "Warehouse / Treatments" +msgstr "" + +#: templates/ishtar/sheet_find.html:64 +msgid "Custom fields" msgstr "" -#: templates/ishtar/sheet_find.html:53 +#: templates/ishtar/sheet_find.html:123 msgid "Administrative index" msgstr "" -#: templates/ishtar/sheet_find.html:95 +#: templates/ishtar/sheet_find.html:166 msgid "Checked" msgstr "" -#: templates/ishtar/sheet_find.html:160 -msgid "Warehouse" +#: templates/ishtar/sheet_find.html:233 +msgid "Warehouse - reference container" msgstr "" -#: templates/ishtar/sheet_find.html:178 templates/ishtar/sheet_find.html:216 +#: templates/ishtar/sheet_find.html:243 +msgid "Warehouse - current container" +msgstr "" + +#: templates/ishtar/sheet_find.html:258 templates/ishtar/sheet_find.html:295 +#: templates/ishtar/sheet_find.html:333 msgid "Year - index" msgstr "" -#: templates/ishtar/sheet_find.html:182 templates/ishtar/sheet_find.html:220 +#: templates/ishtar/sheet_find.html:262 templates/ishtar/sheet_find.html:299 +#: templates/ishtar/sheet_find.html:337 msgid "Related finds (max. 15 displayed)" msgstr "" -#: templates/ishtar/sheet_find.html:208 +#: templates/ishtar/sheet_find.html:325 msgid "Export as CSV" msgstr "" -#: templates/ishtar/sheet_find.html:208 templates/ishtar/sheet_find.html:247 +#: templates/ishtar/sheet_find.html:325 templates/ishtar/sheet_find.html:364 msgid "CSV" msgstr "" -#: templates/ishtar/sheet_find.html:252 +#: templates/ishtar/sheet_find.html:371 +#: templates/ishtar/sheet_treatment.html:124 msgid "Associated documents" msgstr "" -#: templates/ishtar/sheet_findbasket.html:19 +#: templates/ishtar/sheet_findbasket.html:20 msgid "Content" msgstr "" -#: templates/ishtar/sheet_treatment.html:25 +#: templates/ishtar/sheet_treatment.html:41 +#: templates/ishtar/sheet_treatment.html:132 +#: templates/ishtar/sheet_treatmentfile.html:74 +msgid "Administrative acts" +msgstr "" + +#: templates/ishtar/sheet_treatment.html:63 msgctxt "Treatment" msgid "Closed" msgstr "" -#: templates/ishtar/sheet_treatment.html:27 +#: templates/ishtar/sheet_treatment.html:65 msgctxt "Treatment" msgid "Active" msgstr "" -#: templates/ishtar/sheet_treatment.html:66 -msgid "Related operations" -msgstr "" - -#: templates/ishtar/sheet_treatment.html:77 -#: templates/ishtar/sheet_treatmentfile.html:73 -msgid "Administrative acts" -msgstr "" - #: templates/ishtar/sheet_treatmentfile.html:24 msgctxt "Treatment request" msgid "Closed" @@ -1613,86 +1866,132 @@ msgctxt "Treatment request" msgid "Active" msgstr "" -#: views.py:132 +#: templates/ishtar/wizard/wizard_findbasket_deletion.html:8 +msgid "This basket is attached to treatments requests:" +msgstr "" + +#: templates/ishtar/wizard/wizard_findbasket_deletion.html:12 +msgid "Are you sure you want to delete this basket?" +msgstr "" + +#: templates/ishtar/wizard/wizard_findbasket_deletion.html:16 +msgid "Items inside the basket (these items will not be deleted):" +msgstr "" + +#: templates/ishtar/wizard/wizard_findbasket_deletion.html:23 +msgid "Basket informations:" +msgstr "" + +#: templates/ishtar/wizard/wizard_simplefind.html:6 +msgid "" +"This find is related to many base finds. To edit field related to base finds " +"edit the corresponding find between theses:" +msgstr "" + +#: templates/ishtar/wizard/wizard_treatement_deletion.html:8 +msgid "Are you sure you want to delete this treatment?" +msgstr "" + +#: templates/ishtar/wizard/wizard_treatement_deletion.html:10 +msgid "The following finds will be deleted and restored to a previous version." +msgstr "" + +#: templates/ishtar/wizard/wizard_treatement_deletion.html:16 +msgid "" +"All changes made to the associated finds since this treatment record will be " +"lost!" +msgstr "" + +#: templates/ishtar/wizard/wizard_treatement_deletion.html:21 +msgid "Treatment informations:" +msgstr "" + +#: views.py:175 msgid "Basket modify" msgstr "" -#: views.py:173 +#: views.py:198 +msgid "Basket deletion" +msgstr "" + +#: views.py:229 msgid "New find" msgstr "" -#: views.py:209 +#: views.py:281 msgid "Find modification" msgstr "" -#: views.py:238 +#: views.py:316 msgid "Find deletion" msgstr "" -#: views.py:251 +#: views.py:329 msgid "New basket" msgstr "" -#: views.py:280 +#: views.py:358 msgid "Manage items in basket" msgstr "" -#: views.py:389 -msgid "Delete basket" -msgstr "" - -#: views.py:441 +#: views.py:484 views.py:497 views.py:510 msgid "New treatment" msgstr "" -#: views.py:449 +#: views.py:518 msgid "Treatment modification" msgstr "" -#: views.py:466 +#: views.py:609 msgid "Treatment deletion" msgstr "" -#: views.py:473 +#: views.py:616 msgid "Treatment: search administrative act" msgstr "" -#: views.py:482 +#: views.py:625 msgid "Treatment: new administrative act" msgstr "" -#: views.py:492 +#: views.py:635 msgid "Treatment: administrative act modification" msgstr "" -#: views.py:501 +#: views.py:644 msgid "Treatment: administrative act deletion" msgstr "" -#: views.py:534 +#: views.py:691 msgid "New treatment request" msgstr "" -#: views.py:541 +#: views.py:700 msgid "Treatment request modification" msgstr "" -#: views.py:557 +#: views.py:716 msgid "Treatment request deletion" msgstr "" -#: views.py:564 +#: views.py:723 msgid "Treatment request: search administrative act" msgstr "" -#: views.py:574 +#: views.py:734 msgid "Treatment request: new administrative act" msgstr "" -#: views.py:584 +#: views.py:744 msgid "Treatment request: administrative act modification" msgstr "" -#: views.py:593 +#: views.py:753 msgid "Treatment request: administrative act deletion" msgstr "" + +#: wizards.py:394 +msgid "" +"The new basket: \"{}\" have been created with the resulting items. This " +"search have been pinned." +msgstr "" diff --git a/archaeological_finds/migrations/0039_auto_20181115_1649.py b/archaeological_finds/migrations/0039_auto_20181115_1649.py new file mode 100644 index 000000000..3752c173c --- /dev/null +++ b/archaeological_finds/migrations/0039_auto_20181115_1649.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-11-15 16:49 +from __future__ import unicode_literals + +from django.db import migrations, models +import virtualtime + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_finds', '0038_auto_20181112_1625'), + ] + + operations = [ + migrations.AddField( + model_name='historicaltreatment', + name='creation_date', + field=models.DateTimeField(default=virtualtime.virtual_datetime.now), + ), + migrations.AddField( + model_name='treatment', + name='creation_date', + field=models.DateTimeField(default=virtualtime.virtual_datetime.now), + ), + migrations.AddField( + model_name='treatment', + name='finds', + field=models.ManyToManyField(blank=True, help_text='Related finds for non-destructive treatment', related_name='treatments', to='archaeological_finds.Find', verbose_name='Finds'), + ), + migrations.AddField( + model_name='treatmenttype', + name='destructive', + field=models.BooleanField(default=False, verbose_name='Destructive'), + ), + ] diff --git a/archaeological_finds/migrations/0040_auto_20181120_1027.py b/archaeological_finds/migrations/0040_auto_20181120_1027.py new file mode 100644 index 000000000..fd649dd8f --- /dev/null +++ b/archaeological_finds/migrations/0040_auto_20181120_1027.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-11-20 10:27 +from __future__ import unicode_literals + +from django.db import migrations, models + + +def init_create_new_find(apps, schema): + TreatmentType = apps.get_model('archaeological_finds', 'TreatmentType') + for tp in TreatmentType.objects.all(): + if (tp.upstream_is_many or tp.downstream_is_many) and not tp.virtual: + tp.create_new_find = True + tp.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_finds', '0039_auto_20181115_1649'), + ] + + operations = [ + migrations.AlterModelOptions( + name='treatment', + options={'ordering': ('start_date',), 'permissions': (('view_treatment', 'Can view all Treatments'), ('view_own_treatment', 'Can view own Treatment'), ('add_own_treatment', 'Can add own Treatment'), ('change_own_treatment', 'Can change own Treatment'), ('delete_own_treatment', 'Can delete own Treatment')), 'verbose_name': 'Treatment', 'verbose_name_plural': 'Treatments'}, + ), + migrations.AddField( + model_name='treatmenttype', + name='create_new_find', + field=models.BooleanField(default=False, help_text='If True when this treatment is applied a new version of the object will be created.', verbose_name='Create a new find'), + ), + migrations.RunPython(init_create_new_find) + ] diff --git a/archaeological_finds/migrations/0041_auto_20181121_1225.py b/archaeological_finds/migrations/0041_auto_20181121_1225.py new file mode 100644 index 000000000..248dc6499 --- /dev/null +++ b/archaeological_finds/migrations/0041_auto_20181121_1225.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-11-21 12:25 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_finds', '0040_auto_20181120_1027'), + ] + + operations = [ + migrations.RemoveField( + model_name='treatment', + name='finds', + ), + migrations.AddField( + model_name='find', + name='treatments', + field=models.ManyToManyField(blank=True, help_text='Related treatments when no new find is created', related_name='finds', to='archaeological_finds.Treatment', verbose_name='Treatments'), + ), + ] diff --git a/archaeological_finds/migrations/0042_auto_20181129_1755.py b/archaeological_finds/migrations/0042_auto_20181129_1755.py new file mode 100644 index 000000000..42d732cf2 --- /dev/null +++ b/archaeological_finds/migrations/0042_auto_20181129_1755.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-11-29 17:55 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ishtar_common', '0077_auto_20181129_1755'), + ('archaeological_finds', '0041_auto_20181121_1225'), + ] + + operations = [ + migrations.AlterModelOptions( + name='treatmentfile', + options={'ordering': ('cached_label',), 'permissions': (('view_treatmentfile', 'Can view all Treatment requests'), ('view_own_treatmentfile', 'Can view own Treatment request'), ('add_own_treatmentfile', 'Can add own Treatment request'), ('change_own_treatmentfile', 'Can change own Treatment request'), ('delete_own_treatmentfile', 'Can delete own Treatment request')), 'verbose_name': 'Treatment request', 'verbose_name_plural': 'Treatment requests'}, + ), + migrations.AddField( + model_name='findbasket', + name='shared_write_with', + field=models.ManyToManyField(blank=True, related_name='shared_write_findbaskets', to='ishtar_common.IshtarUser', verbose_name='Shared (read/edit) with'), + ), + migrations.AlterField( + model_name='findbasket', + name='shared_with', + field=models.ManyToManyField(blank=True, related_name='shared_findbaskets', to='ishtar_common.IshtarUser', verbose_name='Shared (read) with'), + ), + ] diff --git a/archaeological_finds/migrations/0043_auto_20181130_1310.py b/archaeological_finds/migrations/0043_auto_20181130_1310.py new file mode 100644 index 000000000..e8881e45d --- /dev/null +++ b/archaeological_finds/migrations/0043_auto_20181130_1310.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-11-30 13:10 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_finds', '0042_auto_20181129_1755'), + ] + + operations = [ + migrations.RemoveField( + model_name='historicaltreatment', + name='target_is_basket', + ), + migrations.RemoveField( + model_name='treatment', + name='target_is_basket', + ), + migrations.AddField( + model_name='historicaltreatmentfile', + name='associated_basket', + field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='archaeological_finds.FindBasket'), + ), + migrations.AddField( + model_name='treatmentfile', + name='associated_basket', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='archaeological_finds.FindBasket'), + ), + ] diff --git a/archaeological_finds/migrations/0044_auto_20181201_1854.py b/archaeological_finds/migrations/0044_auto_20181201_1854.py new file mode 100644 index 000000000..e11a9db81 --- /dev/null +++ b/archaeological_finds/migrations/0044_auto_20181201_1854.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-12-01 18:54 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_warehouse', '0025_auto_20181112_1842'), + ('archaeological_finds', '0043_auto_20181130_1310'), + ] + + operations = [ + migrations.AlterModelOptions( + name='findbasket', + options={'permissions': (('view_find', 'Can view all Finds'), ('view_own_find', 'Can view own Find')), 'verbose_name': 'Basket'}, + ), + migrations.AddField( + model_name='find', + name='container_ref', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='finds_ref', to='archaeological_warehouse.Container', verbose_name='Reference container'), + ), + migrations.AddField( + model_name='historicalfind', + name='container_ref', + field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='archaeological_warehouse.Container'), + ), + migrations.AlterField( + model_name='treatmentfile', + name='associated_basket', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='treatment_files', to='archaeological_finds.FindBasket'), + ), + ] diff --git a/archaeological_finds/migrations/0045_migrate_current_container_to_ref_container.py b/archaeological_finds/migrations/0045_migrate_current_container_to_ref_container.py new file mode 100644 index 000000000..7639f95b7 --- /dev/null +++ b/archaeological_finds/migrations/0045_migrate_current_container_to_ref_container.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-12-01 19:17 +from __future__ import unicode_literals + +from django.db import migrations + + +def migrate_containers(apps, schema): + Find = apps.get_model('archaeological_finds', 'find') + for f in Find.objects.filter(container__isnull=False).all(): + f.skip_history_when_saving = True + f.container_ref = f.container + f.save() + TreatmentType = apps.get_model('archaeological_finds', 'TreatmentType') + TreatmentType.objects.get_or_create( + txt_idx="loan", + defaults={ + "label": u"Prêt", + "virtual": False, + "comment": u"Un prêt est un changement temporaire de contenant " + u"pour du mobilier."} + ) + TreatmentType.objects.get_or_create( + txt_idx="loan-return", + defaults={ + "label": u"Retour de prêt", + "virtual": False, + "comment": u"Retour de mobilier dans son contenant de référence."} + ) + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_finds', '0044_auto_20181201_1854'), + ] + + operations = [ + migrations.RunPython(migrate_containers) + ] diff --git a/archaeological_finds/migrations/0046_treatmentfiletype_treatment_type.py b/archaeological_finds/migrations/0046_treatmentfiletype_treatment_type.py new file mode 100644 index 000000000..867cd4545 --- /dev/null +++ b/archaeological_finds/migrations/0046_treatmentfiletype_treatment_type.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-12-02 18:31 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_finds', '0045_migrate_current_container_to_ref_container'), + ] + + operations = [ + migrations.AddField( + model_name='treatmentfiletype', + name='treatment_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='archaeological_finds.TreatmentType'), + ), + ] diff --git a/archaeological_finds/migrations/0047_auto_20181203_1442.py b/archaeological_finds/migrations/0047_auto_20181203_1442.py new file mode 100644 index 000000000..90ed25028 --- /dev/null +++ b/archaeological_finds/migrations/0047_auto_20181203_1442.py @@ -0,0 +1,1523 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-12-03 14:42 +from __future__ import unicode_literals + +import datetime +from django.conf import settings +import django.contrib.gis.db.models.fields +import django.contrib.postgres.search +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion +import ishtar_common.utils +import re + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_finds', '0046_treatmentfiletype_treatment_type'), + ] + + operations = [ + migrations.AlterModelOptions( + name='alterationcausetype', + options={'ordering': ('parent__label', 'label'), 'verbose_name': "Type de cause d'alt\xe9ration", 'verbose_name_plural': "Types de cause d'alt\xe9ration"}, + ), + migrations.AlterModelOptions( + name='alterationtype', + options={'ordering': ('parent__label', 'label'), 'verbose_name': "Type d'alt\xe9ration", 'verbose_name_plural': "Types d'alt\xe9ration"}, + ), + migrations.AlterModelOptions( + name='basefind', + options={'permissions': (('view_basefind', 'Can view all Base finds'), ('view_own_basefind', 'Can view own Base find'), ('add_own_basefind', 'Can add own Base find'), ('change_own_basefind', 'Can change own Base find'), ('delete_own_basefind', 'Can delete own Base find')), 'verbose_name': "Mobilier d'origine", 'verbose_name_plural': "Mobilier d'origine"}, + ), + migrations.AlterModelOptions( + name='batchtype', + options={'ordering': ('order',), 'verbose_name': 'Type de lot', 'verbose_name_plural': 'Types de lot'}, + ), + migrations.AlterModelOptions( + name='checkedtype', + options={'ordering': ('order',), 'verbose_name': 'Type de v\xe9rification', 'verbose_name_plural': 'Types de v\xe9rification'}, + ), + migrations.AlterModelOptions( + name='communicabilitytype', + options={'ordering': ('parent__label', 'label'), 'verbose_name': 'Type de communicabilit\xe9', 'verbose_name_plural': 'Types de communicabilit\xe9'}, + ), + migrations.AlterModelOptions( + name='find', + options={'ordering': ('cached_label',), 'permissions': (('view_find', 'Can view all Finds'), ('view_own_find', 'Can view own Find'), ('add_own_find', 'Can add own Find'), ('change_own_find', 'Can change own Find'), ('delete_own_find', 'Can delete own Find')), 'verbose_name': 'Mobilier', 'verbose_name_plural': 'Mobilier'}, + ), + migrations.AlterModelOptions( + name='findbasket', + options={'permissions': (('view_find', 'Can view all Finds'), ('view_own_find', 'Can view own Find')), 'verbose_name': 'Panier'}, + ), + migrations.AlterModelOptions( + name='historicalbasefind', + options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': "historical Mobilier d'origine"}, + ), + migrations.AlterModelOptions( + name='historicalfind', + options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Mobilier'}, + ), + migrations.AlterModelOptions( + name='historicaltreatment', + options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Traitement'}, + ), + migrations.AlterModelOptions( + name='historicaltreatmentfile', + options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Demande de traitement'}, + ), + migrations.AlterModelOptions( + name='integritytype', + options={'ordering': ('label',), 'verbose_name': "Type d'int\xe9grit\xe9 / int\xe9r\xeat", 'verbose_name_plural': "Types d'int\xe9grit\xe9 / int\xe9r\xeat"}, + ), + migrations.AlterModelOptions( + name='materialtype', + options={'ordering': ('label',), 'verbose_name': 'Type de mat\xe9riau', 'verbose_name_plural': 'Types de mat\xe9riau'}, + ), + migrations.AlterModelOptions( + name='materialtypequalitytype', + options={'ordering': ('order',), 'verbose_name': 'Type de qualit\xe9 du type de mat\xe9riaux', 'verbose_name_plural': 'Types de qualit\xe9 du type de mat\xe9riaux'}, + ), + migrations.AlterModelOptions( + name='objecttype', + options={'ordering': ('parent__label', 'label'), 'verbose_name': "Type d'objet", 'verbose_name_plural': "Types d'objet"}, + ), + migrations.AlterModelOptions( + name='objecttypequalitytype', + options={'ordering': ('order',), 'verbose_name': "Type de qualit\xe9 du type d'objet", 'verbose_name_plural': "Types de qualit\xe9 du type d'objet"}, + ), + migrations.AlterModelOptions( + name='property', + options={'verbose_name': 'Propri\xe9t\xe9', 'verbose_name_plural': 'Propri\xe9t\xe9s'}, + ), + migrations.AlterModelOptions( + name='remarkabilitytype', + options={'ordering': ('label',), 'verbose_name': 'Type de remarquabilit\xe9', 'verbose_name_plural': 'Types de remarquabilit\xe9'}, + ), + migrations.AlterModelOptions( + name='treatment', + options={'ordering': ('start_date',), 'permissions': (('view_treatment', 'Can view all Treatments'), ('view_own_treatment', 'Can view own Treatment'), ('add_own_treatment', 'Can add own Treatment'), ('change_own_treatment', 'Can change own Treatment'), ('delete_own_treatment', 'Can delete own Treatment')), 'verbose_name': 'Traitement', 'verbose_name_plural': 'Traitements'}, + ), + migrations.AlterModelOptions( + name='treatmentemergencytype', + options={'ordering': ('label',), 'verbose_name': "Type d'urgence de traitement", 'verbose_name_plural': "Types d'urgence du traitement"}, + ), + migrations.AlterModelOptions( + name='treatmentfile', + options={'ordering': ('cached_label',), 'permissions': (('view_treatmentfile', 'Can view all Treatment requests'), ('view_own_treatmentfile', 'Can view own Treatment request'), ('add_own_treatmentfile', 'Can add own Treatment request'), ('change_own_treatmentfile', 'Can change own Treatment request'), ('delete_own_treatmentfile', 'Can delete own Treatment request')), 'verbose_name': 'Demande de traitement', 'verbose_name_plural': 'Demandes de traitement'}, + ), + migrations.AlterModelOptions( + name='treatmentfiletype', + options={'ordering': ('label',), 'verbose_name': 'Type de demande de traitement', 'verbose_name_plural': 'Types de demande de traitement'}, + ), + migrations.AlterModelOptions( + name='treatmentstate', + options={'ordering': ('label',), 'verbose_name': "Type d'\xe9tat de traitement", 'verbose_name_plural': "Types d'\xe9tat de traitement"}, + ), + migrations.AlterModelOptions( + name='treatmenttype', + options={'ordering': ('order', 'label'), 'verbose_name': 'Type de traitement', 'verbose_name_plural': 'Types de traitement'}, + ), + migrations.AlterField( + model_name='alterationcausetype', + name='available', + field=models.BooleanField(default=True, verbose_name='Disponible'), + ), + migrations.AlterField( + model_name='alterationcausetype', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='alterationcausetype', + name='label', + field=models.TextField(verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='alterationcausetype', + name='txt_idx', + field=models.TextField(help_text='Le "slug" est une version standardis\xe9e du nom. Il ne contient que des lettres en minuscule, des nombres et des tirets (-). Chaque "slug" doit \xeatre unique dans la typologie.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Ce champ ne doit contenir que des lettres, des nombres, des tirets bas _ et des traits d'union.", 'invalid')], verbose_name='Identifiant textuel'), + ), + migrations.AlterField( + model_name='alterationtype', + name='available', + field=models.BooleanField(default=True, verbose_name='Disponible'), + ), + migrations.AlterField( + model_name='alterationtype', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='alterationtype', + name='label', + field=models.TextField(verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='alterationtype', + name='txt_idx', + field=models.TextField(help_text='Le "slug" est une version standardis\xe9e du nom. Il ne contient que des lettres en minuscule, des nombres et des tirets (-). Chaque "slug" doit \xeatre unique dans la typologie.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Ce champ ne doit contenir que des lettres, des nombres, des tirets bas _ et des traits d'union.", 'invalid')], verbose_name='Identifiant textuel'), + ), + migrations.AlterField( + model_name='basefind', + name='auto_external_id', + field=models.BooleanField(default=False, verbose_name="L'identifiant est attribu\xe9 automatiquement"), + ), + migrations.AlterField( + model_name='basefind', + name='batch', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='archaeological_finds.BatchType', verbose_name='Lot/objet'), + ), + migrations.AlterField( + model_name='basefind', + name='cache_complete_id', + field=models.TextField(blank=True, db_index=True, help_text='Valeur en cache - ne pas \xe9diter', null=True, verbose_name='Identifiant complet'), + ), + migrations.AlterField( + model_name='basefind', + name='cache_short_id', + field=models.TextField(blank=True, db_index=True, help_text='Valeur en cache - ne pas \xe9diter', null=True, verbose_name='Identifiant court'), + ), + migrations.AlterField( + model_name='basefind', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='basefind', + name='context_record', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='base_finds', to='archaeological_context_records.ContextRecord', verbose_name="Unit\xe9 d'Enregistrement"), + ), + migrations.AlterField( + model_name='basefind', + name='discovery_date', + field=models.DateField(blank=True, null=True, verbose_name='Date de d\xe9couverte (exacte ou TPQ)'), + ), + migrations.AlterField( + model_name='basefind', + name='discovery_date_taq', + field=models.DateField(blank=True, null=True, verbose_name='Date de d\xe9couverte (TAQ)'), + ), + migrations.AlterField( + model_name='basefind', + name='estimated_error_x', + field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour X'), + ), + migrations.AlterField( + model_name='basefind', + name='estimated_error_y', + field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour Y'), + ), + migrations.AlterField( + model_name='basefind', + name='estimated_error_z', + field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour Z'), + ), + migrations.AlterField( + model_name='basefind', + name='excavation_id', + field=models.TextField(blank=True, null=True, verbose_name='Identifiant fouille'), + ), + migrations.AlterField( + model_name='basefind', + name='external_id', + field=models.TextField(blank=True, null=True, verbose_name='Identifiant'), + ), + migrations.AlterField( + model_name='basefind', + name='history_creator', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Cr\xe9ateur'), + ), + migrations.AlterField( + model_name='basefind', + name='history_modifier', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Dernier \xe9diteur'), + ), + migrations.AlterField( + model_name='basefind', + name='label', + field=models.TextField(verbose_name='Identifiant libre'), + ), + migrations.AlterField( + model_name='basefind', + name='line', + field=django.contrib.gis.db.models.fields.LineStringField(blank=True, null=True, srid=4326, verbose_name='Ligne'), + ), + migrations.AlterField( + model_name='basefind', + name='material_index', + field=models.IntegerField(default=0, verbose_name='Index mat\xe9riel'), + ), + migrations.AlterField( + model_name='basefind', + name='multi_polygon', + field=django.contrib.gis.db.models.fields.MultiPolygonField(blank=True, null=True, srid=4326, verbose_name='Polygones multi-parties'), + ), + migrations.AlterField( + model_name='basefind', + name='search_vector', + field=django.contrib.postgres.search.SearchVectorField(blank=True, help_text='Auto-rempli \xe0 la sauvegarde', null=True, verbose_name='Vecteur de recherche'), + ), + migrations.AlterField( + model_name='basefind', + name='spatial_reference_system', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='ishtar_common.SpatialReferenceSystem', verbose_name='Syst\xe8me de r\xe9f\xe9rence spatiale'), + ), + migrations.AlterField( + model_name='basefind', + name='special_interest', + field=models.CharField(blank=True, max_length=120, null=True, verbose_name='Int\xe9r\xeat sp\xe9cifique'), + ), + migrations.AlterField( + model_name='basefind', + name='topographic_localisation', + field=models.CharField(blank=True, max_length=120, null=True, verbose_name='Point topographique'), + ), + migrations.AlterField( + model_name='batchtype', + name='available', + field=models.BooleanField(default=True, verbose_name='Disponible'), + ), + migrations.AlterField( + model_name='batchtype', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='batchtype', + name='label', + field=models.TextField(verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='batchtype', + name='order', + field=models.IntegerField(default=10, verbose_name='Ordre'), + ), + migrations.AlterField( + model_name='batchtype', + name='txt_idx', + field=models.TextField(help_text='Le "slug" est une version standardis\xe9e du nom. Il ne contient que des lettres en minuscule, des nombres et des tirets (-). Chaque "slug" doit \xeatre unique dans la typologie.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Ce champ ne doit contenir que des lettres, des nombres, des tirets bas _ et des traits d'union.", 'invalid')], verbose_name='Identifiant textuel'), + ), + migrations.AlterField( + model_name='checkedtype', + name='available', + field=models.BooleanField(default=True, verbose_name='Disponible'), + ), + migrations.AlterField( + model_name='checkedtype', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='checkedtype', + name='label', + field=models.TextField(verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='checkedtype', + name='order', + field=models.IntegerField(default=10, verbose_name='Ordre'), + ), + migrations.AlterField( + model_name='checkedtype', + name='txt_idx', + field=models.TextField(help_text='Le "slug" est une version standardis\xe9e du nom. Il ne contient que des lettres en minuscule, des nombres et des tirets (-). Chaque "slug" doit \xeatre unique dans la typologie.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Ce champ ne doit contenir que des lettres, des nombres, des tirets bas _ et des traits d'union.", 'invalid')], verbose_name='Identifiant textuel'), + ), + migrations.AlterField( + model_name='communicabilitytype', + name='available', + field=models.BooleanField(default=True, verbose_name='Disponible'), + ), + migrations.AlterField( + model_name='communicabilitytype', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='communicabilitytype', + name='label', + field=models.TextField(verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='communicabilitytype', + name='txt_idx', + field=models.TextField(help_text='Le "slug" est une version standardis\xe9e du nom. Il ne contient que des lettres en minuscule, des nombres et des tirets (-). Chaque "slug" doit \xeatre unique dans la typologie.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Ce champ ne doit contenir que des lettres, des nombres, des tirets bas _ et des traits d'union.", 'invalid')], verbose_name='Identifiant textuel'), + ), + migrations.AlterField( + model_name='conservatorystate', + name='available', + field=models.BooleanField(default=True, verbose_name='Disponible'), + ), + migrations.AlterField( + model_name='conservatorystate', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='conservatorystate', + name='label', + field=models.TextField(verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='conservatorystate', + name='order', + field=models.IntegerField(default=10, verbose_name='Ordre'), + ), + migrations.AlterField( + model_name='conservatorystate', + name='txt_idx', + field=models.TextField(help_text='Le "slug" est une version standardis\xe9e du nom. Il ne contient que des lettres en minuscule, des nombres et des tirets (-). Chaque "slug" doit \xeatre unique dans la typologie.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Ce champ ne doit contenir que des lettres, des nombres, des tirets bas _ et des traits d'union.", 'invalid')], verbose_name='Identifiant textuel'), + ), + migrations.AlterField( + model_name='find', + name='alteration_causes', + field=models.ManyToManyField(blank=True, related_name='finds', to='archaeological_finds.AlterationCauseType', verbose_name="Cause d'alt\xe9ration"), + ), + migrations.AlterField( + model_name='find', + name='alterations', + field=models.ManyToManyField(blank=True, related_name='finds', to='archaeological_finds.AlterationType', verbose_name='Alt\xe9ration'), + ), + migrations.AlterField( + model_name='find', + name='appraisal_date', + field=models.DateField(blank=True, null=True, verbose_name="Date d'\xe9valuation"), + ), + migrations.AlterField( + model_name='find', + name='auto_external_id', + field=models.BooleanField(default=False, verbose_name="L'identifiant est attribu\xe9 automatiquement"), + ), + migrations.AlterField( + model_name='find', + name='base_finds', + field=models.ManyToManyField(related_name='find', to='archaeological_finds.BaseFind', verbose_name="Mobilier d'origine"), + ), + migrations.AlterField( + model_name='find', + name='cached_label', + field=models.TextField(blank=True, db_index=True, null=True, verbose_name='Nom en cache'), + ), + migrations.AlterField( + model_name='find', + name='check_date', + field=models.DateField(default=datetime.date.today, verbose_name='Date de v\xe9rification'), + ), + migrations.AlterField( + model_name='find', + name='checked_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='archaeological_finds.CheckedType', verbose_name='V\xe9rification'), + ), + migrations.AlterField( + model_name='find', + name='clutter_height', + field=models.FloatField(blank=True, null=True, verbose_name='Encombrement - hauteur (cm)'), + ), + migrations.AlterField( + model_name='find', + name='clutter_long_side', + field=models.FloatField(blank=True, null=True, verbose_name='Encombrement - grand c\xf4t\xe9 (cm)'), + ), + migrations.AlterField( + model_name='find', + name='clutter_short_side', + field=models.FloatField(blank=True, null=True, verbose_name='Encombrement - petit c\xf4t\xe9 (cm)'), + ), + migrations.AlterField( + model_name='find', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='find', + name='communicabilities', + field=models.ManyToManyField(blank=True, related_name='find', to='archaeological_finds.CommunicabilityType', verbose_name='Communicabilit\xe9'), + ), + migrations.AlterField( + model_name='find', + name='conservatory_comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire relatif \xe0 la conservation'), + ), + migrations.AlterField( + model_name='find', + name='conservatory_state', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='archaeological_finds.ConservatoryState', verbose_name='\xc9tat de conservation'), + ), + migrations.AlterField( + model_name='find', + name='container', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='finds', to='archaeological_warehouse.Container', verbose_name='Contenant'), + ), + migrations.AlterField( + model_name='find', + name='dating_comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire relatif aux datations'), + ), + migrations.AlterField( + model_name='find', + name='datings', + field=models.ManyToManyField(related_name='find', to='archaeological_context_records.Dating', verbose_name='Datation'), + ), + migrations.AlterField( + model_name='find', + name='decoration', + field=models.TextField(blank=True, null=True, verbose_name='D\xe9cor'), + ), + migrations.AlterField( + model_name='find', + name='denomination', + field=models.TextField(blank=True, null=True, verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='find', + name='diameter', + field=models.FloatField(blank=True, null=True, verbose_name='Diam\xe8tre (cm)'), + ), + migrations.AlterField( + model_name='find', + name='dimensions_comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire relatif aux dimensions'), + ), + migrations.AlterField( + model_name='find', + name='downstream_treatment', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='upstream', to='archaeological_finds.Treatment', verbose_name='Traitement aval'), + ), + migrations.AlterField( + model_name='find', + name='estimated_value', + field=models.FloatField(blank=True, null=True, verbose_name='Valeur estim\xe9e'), + ), + migrations.AlterField( + model_name='find', + name='external_id', + field=models.TextField(blank=True, null=True, verbose_name='Identifiant'), + ), + migrations.AlterField( + model_name='find', + name='find_number', + field=models.IntegerField(blank=True, null=True, verbose_name='Mobilier (en nombre)'), + ), + migrations.AlterField( + model_name='find', + name='height', + field=models.FloatField(blank=True, null=True, verbose_name='Hauteur (cm)'), + ), + migrations.AlterField( + model_name='find', + name='history_creator', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Cr\xe9ateur'), + ), + migrations.AlterField( + model_name='find', + name='history_modifier', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Dernier \xe9diteur'), + ), + migrations.AlterField( + model_name='find', + name='insurance_value', + field=models.FloatField(blank=True, null=True, verbose_name="Valeur d'assurance"), + ), + migrations.AlterField( + model_name='find', + name='integrities', + field=models.ManyToManyField(blank=True, related_name='find', to='archaeological_finds.IntegrityType', verbose_name='Int\xe9grit\xe9 / int\xe9r\xeat'), + ), + migrations.AlterField( + model_name='find', + name='is_complete', + field=models.NullBooleanField(verbose_name='Est complet ?'), + ), + migrations.AlterField( + model_name='find', + name='label', + field=models.TextField(verbose_name='Identifiant libre'), + ), + migrations.AlterField( + model_name='find', + name='length', + field=models.FloatField(blank=True, null=True, verbose_name='Longueur (cm)'), + ), + migrations.AlterField( + model_name='find', + name='manufacturing_place', + field=models.TextField(blank=True, null=True, verbose_name='Lieu de fabrication'), + ), + migrations.AlterField( + model_name='find', + name='mark', + field=models.TextField(blank=True, null=True, verbose_name='Marquage'), + ), + migrations.AlterField( + model_name='find', + name='material_type_quality', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='finds', to='archaeological_finds.MaterialTypeQualityType', verbose_name='Qualit\xe9 du type de mat\xe9riaux'), + ), + migrations.AlterField( + model_name='find', + name='material_types', + field=models.ManyToManyField(blank=True, related_name='finds', to='archaeological_finds.MaterialType', verbose_name='Types de mat\xe9riau'), + ), + migrations.AlterField( + model_name='find', + name='min_number_of_individuals', + field=models.IntegerField(blank=True, null=True, verbose_name="Nombre minimum d'individus (NMI)"), + ), + migrations.AlterField( + model_name='find', + name='museum_id', + field=models.TextField(blank=True, null=True, verbose_name='Identifiant mus\xe9e'), + ), + migrations.AlterField( + model_name='find', + name='object_type_quality', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='finds', to='archaeological_finds.ObjectTypeQualityType', verbose_name="Qualit\xe9 du type d'objet"), + ), + migrations.AlterField( + model_name='find', + name='object_types', + field=models.ManyToManyField(blank=True, related_name='find', to='archaeological_finds.ObjectType', verbose_name="Types d'objet"), + ), + migrations.AlterField( + model_name='find', + name='order', + field=models.IntegerField(default=1, verbose_name='Ordre'), + ), + migrations.AlterField( + model_name='find', + name='preservation_to_considers', + field=models.ManyToManyField(blank=True, related_name='finds_recommended', to='archaeological_finds.TreatmentType', verbose_name='Traitements recommand\xe9s'), + ), + migrations.AlterField( + model_name='find', + name='previous_id', + field=models.TextField(blank=True, null=True, verbose_name='Identifiant pr\xe9c\xe9dent'), + ), + migrations.AlterField( + model_name='find', + name='remarkabilities', + field=models.ManyToManyField(blank=True, related_name='find', to='archaeological_finds.RemarkabilityType', verbose_name='Remarquabilit\xe9'), + ), + migrations.AlterField( + model_name='find', + name='seal_number', + field=models.TextField(blank=True, null=True, verbose_name='Num\xe9ro de scell\xe9'), + ), + migrations.AlterField( + model_name='find', + name='search_vector', + field=django.contrib.postgres.search.SearchVectorField(blank=True, help_text='Auto-rempli \xe0 la sauvegarde', null=True, verbose_name='Vecteur de recherche'), + ), + migrations.AlterField( + model_name='find', + name='thickness', + field=models.FloatField(blank=True, null=True, verbose_name='\xc9paisseur (cm)'), + ), + migrations.AlterField( + model_name='find', + name='treatment_emergency', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='archaeological_finds.TreatmentEmergencyType', verbose_name='Urgence du traitement'), + ), + migrations.AlterField( + model_name='find', + name='treatments', + field=models.ManyToManyField(blank=True, help_text='Related treatments when no new find is created', related_name='finds', to='archaeological_finds.Treatment', verbose_name='Traitements'), + ), + migrations.AlterField( + model_name='find', + name='upstream_treatment', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='downstream', to='archaeological_finds.Treatment', verbose_name='Traitement amont'), + ), + migrations.AlterField( + model_name='find', + name='weight', + field=models.FloatField(blank=True, null=True, verbose_name='Poids'), + ), + migrations.AlterField( + model_name='find', + name='weight_unit', + field=models.CharField(blank=True, choices=[(b'g', 'g'), (b'kg', 'kg')], max_length=4, null=True, verbose_name='Unit\xe9 de poids'), + ), + migrations.AlterField( + model_name='find', + name='width', + field=models.FloatField(blank=True, null=True, verbose_name='Largeur (cm)'), + ), + migrations.AlterField( + model_name='findbasket', + name='available', + field=models.BooleanField(default=True, verbose_name='Disponible'), + ), + migrations.AlterField( + model_name='findbasket', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='findbasket', + name='label', + field=models.CharField(max_length=1000, verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='findbasket', + name='search_vector', + field=django.contrib.postgres.search.SearchVectorField(blank=True, help_text='Auto-rempli \xe0 la sauvegarde', null=True, verbose_name='Vecteur de recherche'), + ), + migrations.AlterField( + model_name='findbasket', + name='user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='findbaskets', to='ishtar_common.IshtarUser', verbose_name='Propri\xe9taire'), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='auto_external_id', + field=models.BooleanField(default=False, verbose_name="L'identifiant est attribu\xe9 automatiquement"), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='cache_complete_id', + field=models.TextField(blank=True, db_index=True, help_text='Valeur en cache - ne pas \xe9diter', null=True, verbose_name='Identifiant complet'), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='cache_short_id', + field=models.TextField(blank=True, db_index=True, help_text='Valeur en cache - ne pas \xe9diter', null=True, verbose_name='Identifiant court'), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='discovery_date', + field=models.DateField(blank=True, null=True, verbose_name='Date de d\xe9couverte (exacte ou TPQ)'), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='discovery_date_taq', + field=models.DateField(blank=True, null=True, verbose_name='Date de d\xe9couverte (TAQ)'), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='estimated_error_x', + field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour X'), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='estimated_error_y', + field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour Y'), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='estimated_error_z', + field=models.FloatField(blank=True, null=True, verbose_name='Erreur estim\xe9e pour Z'), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='excavation_id', + field=models.TextField(blank=True, null=True, verbose_name='Identifiant fouille'), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='external_id', + field=models.TextField(blank=True, null=True, verbose_name='Identifiant'), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='label', + field=models.TextField(verbose_name='Identifiant libre'), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='line', + field=django.contrib.gis.db.models.fields.LineStringField(blank=True, null=True, srid=4326, verbose_name='Ligne'), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='material_index', + field=models.IntegerField(default=0, verbose_name='Index mat\xe9riel'), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='multi_polygon', + field=django.contrib.gis.db.models.fields.MultiPolygonField(blank=True, null=True, srid=4326, verbose_name='Polygones multi-parties'), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='search_vector', + field=django.contrib.postgres.search.SearchVectorField(blank=True, help_text='Auto-rempli \xe0 la sauvegarde', null=True, verbose_name='Vecteur de recherche'), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='special_interest', + field=models.CharField(blank=True, max_length=120, null=True, verbose_name='Int\xe9r\xeat sp\xe9cifique'), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='topographic_localisation', + field=models.CharField(blank=True, max_length=120, null=True, verbose_name='Point topographique'), + ), + migrations.AlterField( + model_name='historicalfind', + name='appraisal_date', + field=models.DateField(blank=True, null=True, verbose_name="Date d'\xe9valuation"), + ), + migrations.AlterField( + model_name='historicalfind', + name='auto_external_id', + field=models.BooleanField(default=False, verbose_name="L'identifiant est attribu\xe9 automatiquement"), + ), + migrations.AlterField( + model_name='historicalfind', + name='cached_label', + field=models.TextField(blank=True, db_index=True, null=True, verbose_name='Nom en cache'), + ), + migrations.AlterField( + model_name='historicalfind', + name='check_date', + field=models.DateField(default=datetime.date.today, verbose_name='Date de v\xe9rification'), + ), + migrations.AlterField( + model_name='historicalfind', + name='clutter_height', + field=models.FloatField(blank=True, null=True, verbose_name='Encombrement - hauteur (cm)'), + ), + migrations.AlterField( + model_name='historicalfind', + name='clutter_long_side', + field=models.FloatField(blank=True, null=True, verbose_name='Encombrement - grand c\xf4t\xe9 (cm)'), + ), + migrations.AlterField( + model_name='historicalfind', + name='clutter_short_side', + field=models.FloatField(blank=True, null=True, verbose_name='Encombrement - petit c\xf4t\xe9 (cm)'), + ), + migrations.AlterField( + model_name='historicalfind', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='historicalfind', + name='conservatory_comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire relatif \xe0 la conservation'), + ), + migrations.AlterField( + model_name='historicalfind', + name='dating_comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire relatif aux datations'), + ), + migrations.AlterField( + model_name='historicalfind', + name='decoration', + field=models.TextField(blank=True, null=True, verbose_name='D\xe9cor'), + ), + migrations.AlterField( + model_name='historicalfind', + name='denomination', + field=models.TextField(blank=True, null=True, verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='historicalfind', + name='diameter', + field=models.FloatField(blank=True, null=True, verbose_name='Diam\xe8tre (cm)'), + ), + migrations.AlterField( + model_name='historicalfind', + name='dimensions_comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire relatif aux dimensions'), + ), + migrations.AlterField( + model_name='historicalfind', + name='estimated_value', + field=models.FloatField(blank=True, null=True, verbose_name='Valeur estim\xe9e'), + ), + migrations.AlterField( + model_name='historicalfind', + name='external_id', + field=models.TextField(blank=True, null=True, verbose_name='Identifiant'), + ), + migrations.AlterField( + model_name='historicalfind', + name='find_number', + field=models.IntegerField(blank=True, null=True, verbose_name='Mobilier (en nombre)'), + ), + migrations.AlterField( + model_name='historicalfind', + name='height', + field=models.FloatField(blank=True, null=True, verbose_name='Hauteur (cm)'), + ), + migrations.AlterField( + model_name='historicalfind', + name='insurance_value', + field=models.FloatField(blank=True, null=True, verbose_name="Valeur d'assurance"), + ), + migrations.AlterField( + model_name='historicalfind', + name='is_complete', + field=models.NullBooleanField(verbose_name='Est complet ?'), + ), + migrations.AlterField( + model_name='historicalfind', + name='label', + field=models.TextField(verbose_name='Identifiant libre'), + ), + migrations.AlterField( + model_name='historicalfind', + name='length', + field=models.FloatField(blank=True, null=True, verbose_name='Longueur (cm)'), + ), + migrations.AlterField( + model_name='historicalfind', + name='manufacturing_place', + field=models.TextField(blank=True, null=True, verbose_name='Lieu de fabrication'), + ), + migrations.AlterField( + model_name='historicalfind', + name='mark', + field=models.TextField(blank=True, null=True, verbose_name='Marquage'), + ), + migrations.AlterField( + model_name='historicalfind', + name='min_number_of_individuals', + field=models.IntegerField(blank=True, null=True, verbose_name="Nombre minimum d'individus (NMI)"), + ), + migrations.AlterField( + model_name='historicalfind', + name='museum_id', + field=models.TextField(blank=True, null=True, verbose_name='Identifiant mus\xe9e'), + ), + migrations.AlterField( + model_name='historicalfind', + name='order', + field=models.IntegerField(default=1, verbose_name='Ordre'), + ), + migrations.AlterField( + model_name='historicalfind', + name='previous_id', + field=models.TextField(blank=True, null=True, verbose_name='Identifiant pr\xe9c\xe9dent'), + ), + migrations.AlterField( + model_name='historicalfind', + name='seal_number', + field=models.TextField(blank=True, null=True, verbose_name='Num\xe9ro de scell\xe9'), + ), + migrations.AlterField( + model_name='historicalfind', + name='search_vector', + field=django.contrib.postgres.search.SearchVectorField(blank=True, help_text='Auto-rempli \xe0 la sauvegarde', null=True, verbose_name='Vecteur de recherche'), + ), + migrations.AlterField( + model_name='historicalfind', + name='thickness', + field=models.FloatField(blank=True, null=True, verbose_name='\xc9paisseur (cm)'), + ), + migrations.AlterField( + model_name='historicalfind', + name='weight', + field=models.FloatField(blank=True, null=True, verbose_name='Poids'), + ), + migrations.AlterField( + model_name='historicalfind', + name='weight_unit', + field=models.CharField(blank=True, choices=[(b'g', 'g'), (b'kg', 'kg')], max_length=4, null=True, verbose_name='Unit\xe9 de poids'), + ), + migrations.AlterField( + model_name='historicalfind', + name='width', + field=models.FloatField(blank=True, null=True, verbose_name='Largeur (cm)'), + ), + migrations.AlterField( + model_name='historicaltreatment', + name='cached_label', + field=models.TextField(blank=True, db_index=True, null=True, verbose_name='Nom en cache'), + ), + migrations.AlterField( + model_name='historicaltreatment', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='historicaltreatment', + name='end_date', + field=models.DateField(blank=True, null=True, verbose_name='Date de cl\xf4ture'), + ), + migrations.AlterField( + model_name='historicaltreatment', + name='estimated_cost', + field=models.FloatField(blank=True, null=True, verbose_name='Co\xfbt estim\xe9'), + ), + migrations.AlterField( + model_name='historicaltreatment', + name='external_id', + field=models.CharField(blank=True, max_length=200, null=True, verbose_name='Identifiant'), + ), + migrations.AlterField( + model_name='historicaltreatment', + name='goal', + field=models.TextField(blank=True, null=True, verbose_name='But'), + ), + migrations.AlterField( + model_name='historicaltreatment', + name='insurance_cost', + field=models.FloatField(blank=True, null=True, verbose_name="Co\xfbt d'assurance"), + ), + migrations.AlterField( + model_name='historicaltreatment', + name='label', + field=models.CharField(blank=True, max_length=200, null=True, verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='historicaltreatment', + name='other_reference', + field=models.CharField(blank=True, max_length=200, null=True, verbose_name='Autre r\xe9f.'), + ), + migrations.AlterField( + model_name='historicaltreatment', + name='quoted_cost', + field=models.FloatField(blank=True, null=True, verbose_name='Co\xfbt devis\xe9'), + ), + migrations.AlterField( + model_name='historicaltreatment', + name='realized_cost', + field=models.FloatField(blank=True, null=True, verbose_name='Co\xfbt r\xe9alis\xe9'), + ), + migrations.AlterField( + model_name='historicaltreatment', + name='search_vector', + field=django.contrib.postgres.search.SearchVectorField(blank=True, help_text='Auto-rempli \xe0 la sauvegarde', null=True, verbose_name='Vecteur de recherche'), + ), + migrations.AlterField( + model_name='historicaltreatment', + name='start_date', + field=models.DateField(blank=True, null=True, verbose_name='Date de d\xe9but'), + ), + migrations.AlterField( + model_name='historicaltreatment', + name='year', + field=models.IntegerField(default=ishtar_common.utils.get_current_year, verbose_name='Ann\xe9e'), + ), + migrations.AlterField( + model_name='historicaltreatmentfile', + name='cached_label', + field=models.TextField(blank=True, db_index=True, null=True, verbose_name='Nom en cache'), + ), + migrations.AlterField( + model_name='historicaltreatmentfile', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='historicaltreatmentfile', + name='creation_date', + field=models.DateField(blank=True, default=datetime.date.today, null=True, verbose_name='Date de cr\xe9ation'), + ), + migrations.AlterField( + model_name='historicaltreatmentfile', + name='end_date', + field=models.DateField(blank=True, null=True, verbose_name='Date de cl\xf4ture'), + ), + migrations.AlterField( + model_name='historicaltreatmentfile', + name='external_id', + field=models.CharField(blank=True, max_length=200, null=True, verbose_name='Identifiant'), + ), + migrations.AlterField( + model_name='historicaltreatmentfile', + name='internal_reference', + field=models.CharField(blank=True, max_length=200, null=True, verbose_name='R\xe9f\xe9rence interne'), + ), + migrations.AlterField( + model_name='historicaltreatmentfile', + name='name', + field=models.TextField(blank=True, null=True, verbose_name='Nom'), + ), + migrations.AlterField( + model_name='historicaltreatmentfile', + name='reception_date', + field=models.DateField(blank=True, null=True, verbose_name='Date de r\xe9ception'), + ), + migrations.AlterField( + model_name='historicaltreatmentfile', + name='search_vector', + field=django.contrib.postgres.search.SearchVectorField(blank=True, help_text='Auto-rempli \xe0 la sauvegarde', null=True, verbose_name='Vecteur de recherche'), + ), + migrations.AlterField( + model_name='historicaltreatmentfile', + name='year', + field=models.IntegerField(default=ishtar_common.utils.get_current_year, verbose_name='Ann\xe9e'), + ), + migrations.AlterField( + model_name='integritytype', + name='available', + field=models.BooleanField(default=True, verbose_name='Disponible'), + ), + migrations.AlterField( + model_name='integritytype', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='integritytype', + name='label', + field=models.TextField(verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='integritytype', + name='txt_idx', + field=models.TextField(help_text='Le "slug" est une version standardis\xe9e du nom. Il ne contient que des lettres en minuscule, des nombres et des tirets (-). Chaque "slug" doit \xeatre unique dans la typologie.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Ce champ ne doit contenir que des lettres, des nombres, des tirets bas _ et des traits d'union.", 'invalid')], verbose_name='Identifiant textuel'), + ), + migrations.AlterField( + model_name='materialtype', + name='available', + field=models.BooleanField(default=True, verbose_name='Disponible'), + ), + migrations.AlterField( + model_name='materialtype', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='materialtype', + name='label', + field=models.TextField(verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='materialtype', + name='recommendation', + field=models.TextField(blank=True, null=True, verbose_name='Recommandation'), + ), + migrations.AlterField( + model_name='materialtype', + name='txt_idx', + field=models.TextField(help_text='Le "slug" est une version standardis\xe9e du nom. Il ne contient que des lettres en minuscule, des nombres et des tirets (-). Chaque "slug" doit \xeatre unique dans la typologie.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Ce champ ne doit contenir que des lettres, des nombres, des tirets bas _ et des traits d'union.", 'invalid')], verbose_name='Identifiant textuel'), + ), + migrations.AlterField( + model_name='materialtypequalitytype', + name='available', + field=models.BooleanField(default=True, verbose_name='Disponible'), + ), + migrations.AlterField( + model_name='materialtypequalitytype', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='materialtypequalitytype', + name='label', + field=models.TextField(verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='materialtypequalitytype', + name='order', + field=models.IntegerField(default=10, verbose_name='Ordre'), + ), + migrations.AlterField( + model_name='materialtypequalitytype', + name='txt_idx', + field=models.TextField(help_text='Le "slug" est une version standardis\xe9e du nom. Il ne contient que des lettres en minuscule, des nombres et des tirets (-). Chaque "slug" doit \xeatre unique dans la typologie.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Ce champ ne doit contenir que des lettres, des nombres, des tirets bas _ et des traits d'union.", 'invalid')], verbose_name='Identifiant textuel'), + ), + migrations.AlterField( + model_name='objecttype', + name='available', + field=models.BooleanField(default=True, verbose_name='Disponible'), + ), + migrations.AlterField( + model_name='objecttype', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='objecttype', + name='label', + field=models.TextField(verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='objecttype', + name='txt_idx', + field=models.TextField(help_text='Le "slug" est une version standardis\xe9e du nom. Il ne contient que des lettres en minuscule, des nombres et des tirets (-). Chaque "slug" doit \xeatre unique dans la typologie.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Ce champ ne doit contenir que des lettres, des nombres, des tirets bas _ et des traits d'union.", 'invalid')], verbose_name='Identifiant textuel'), + ), + migrations.AlterField( + model_name='objecttypequalitytype', + name='available', + field=models.BooleanField(default=True, verbose_name='Disponible'), + ), + migrations.AlterField( + model_name='objecttypequalitytype', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='objecttypequalitytype', + name='label', + field=models.TextField(verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='objecttypequalitytype', + name='order', + field=models.IntegerField(default=10, verbose_name='Ordre'), + ), + migrations.AlterField( + model_name='objecttypequalitytype', + name='txt_idx', + field=models.TextField(help_text='Le "slug" est une version standardis\xe9e du nom. Il ne contient que des lettres en minuscule, des nombres et des tirets (-). Chaque "slug" doit \xeatre unique dans la typologie.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Ce champ ne doit contenir que des lettres, des nombres, des tirets bas _ et des traits d'union.", 'invalid')], verbose_name='Identifiant textuel'), + ), + migrations.AlterField( + model_name='property', + name='administrative_act', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='archaeological_operations.AdministrativeAct', verbose_name='Acte administratif'), + ), + migrations.AlterField( + model_name='property', + name='end_date', + field=models.DateField(verbose_name='Date de fin'), + ), + migrations.AlterField( + model_name='property', + name='find', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='archaeological_finds.Find', verbose_name='Mobilier'), + ), + migrations.AlterField( + model_name='property', + name='history_creator', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Cr\xe9ateur'), + ), + migrations.AlterField( + model_name='property', + name='history_modifier', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Dernier \xe9diteur'), + ), + migrations.AlterField( + model_name='property', + name='person', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='properties', to='ishtar_common.Person', verbose_name='Personne'), + ), + migrations.AlterField( + model_name='property', + name='search_vector', + field=django.contrib.postgres.search.SearchVectorField(blank=True, help_text='Auto-rempli \xe0 la sauvegarde', null=True, verbose_name='Vecteur de recherche'), + ), + migrations.AlterField( + model_name='property', + name='start_date', + field=models.DateField(verbose_name='Date de d\xe9but'), + ), + migrations.AlterField( + model_name='remarkabilitytype', + name='available', + field=models.BooleanField(default=True, verbose_name='Disponible'), + ), + migrations.AlterField( + model_name='remarkabilitytype', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='remarkabilitytype', + name='label', + field=models.TextField(verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='remarkabilitytype', + name='txt_idx', + field=models.TextField(help_text='Le "slug" est une version standardis\xe9e du nom. Il ne contient que des lettres en minuscule, des nombres et des tirets (-). Chaque "slug" doit \xeatre unique dans la typologie.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Ce champ ne doit contenir que des lettres, des nombres, des tirets bas _ et des traits d'union.", 'invalid')], verbose_name='Identifiant textuel'), + ), + migrations.AlterField( + model_name='treatment', + name='cached_label', + field=models.TextField(blank=True, db_index=True, null=True, verbose_name='Nom en cache'), + ), + migrations.AlterField( + model_name='treatment', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='treatment', + name='container', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='archaeological_warehouse.Container', verbose_name='Contenant'), + ), + migrations.AlterField( + model_name='treatment', + name='end_date', + field=models.DateField(blank=True, null=True, verbose_name='Date de cl\xf4ture'), + ), + migrations.AlterField( + model_name='treatment', + name='estimated_cost', + field=models.FloatField(blank=True, null=True, verbose_name='Co\xfbt estim\xe9'), + ), + migrations.AlterField( + model_name='treatment', + name='external_id', + field=models.CharField(blank=True, max_length=200, null=True, verbose_name='Identifiant'), + ), + migrations.AlterField( + model_name='treatment', + name='file', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='treatments', to='archaeological_finds.TreatmentFile', verbose_name='Demande associ\xe9e'), + ), + migrations.AlterField( + model_name='treatment', + name='goal', + field=models.TextField(blank=True, null=True, verbose_name='But'), + ), + migrations.AlterField( + model_name='treatment', + name='history_creator', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Cr\xe9ateur'), + ), + migrations.AlterField( + model_name='treatment', + name='history_modifier', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Dernier \xe9diteur'), + ), + migrations.AlterField( + model_name='treatment', + name='insurance_cost', + field=models.FloatField(blank=True, null=True, verbose_name="Co\xfbt d'assurance"), + ), + migrations.AlterField( + model_name='treatment', + name='label', + field=models.CharField(blank=True, max_length=200, null=True, verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='treatment', + name='location', + field=models.ForeignKey(blank=True, help_text='Endroit o\xf9 le traitement est r\xe9alis\xe9. Renseignez le lieu de conservation de destination pour un d\xe9placement.', null=True, on_delete=django.db.models.deletion.CASCADE, to='archaeological_warehouse.Warehouse', verbose_name='Localisation'), + ), + migrations.AlterField( + model_name='treatment', + name='organization', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='treatments', to='ishtar_common.Organization', verbose_name='Organisation'), + ), + migrations.AlterField( + model_name='treatment', + name='other_reference', + field=models.CharField(blank=True, max_length=200, null=True, verbose_name='Autre r\xe9f.'), + ), + migrations.AlterField( + model_name='treatment', + name='person', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='treatments', to='ishtar_common.Person', verbose_name='Responsable'), + ), + migrations.AlterField( + model_name='treatment', + name='quoted_cost', + field=models.FloatField(blank=True, null=True, verbose_name='Co\xfbt devis\xe9'), + ), + migrations.AlterField( + model_name='treatment', + name='realized_cost', + field=models.FloatField(blank=True, null=True, verbose_name='Co\xfbt r\xe9alis\xe9'), + ), + migrations.AlterField( + model_name='treatment', + name='search_vector', + field=django.contrib.postgres.search.SearchVectorField(blank=True, help_text='Auto-rempli \xe0 la sauvegarde', null=True, verbose_name='Vecteur de recherche'), + ), + migrations.AlterField( + model_name='treatment', + name='start_date', + field=models.DateField(blank=True, null=True, verbose_name='Date de d\xe9but'), + ), + migrations.AlterField( + model_name='treatment', + name='treatment_state', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='archaeological_finds.TreatmentState', verbose_name='\xc9tat'), + ), + migrations.AlterField( + model_name='treatment', + name='treatment_types', + field=models.ManyToManyField(to='archaeological_finds.TreatmentType', verbose_name='Type de traitement'), + ), + migrations.AlterField( + model_name='treatment', + name='year', + field=models.IntegerField(default=ishtar_common.utils.get_current_year, verbose_name='Ann\xe9e'), + ), + migrations.AlterField( + model_name='treatmentemergencytype', + name='available', + field=models.BooleanField(default=True, verbose_name='Disponible'), + ), + migrations.AlterField( + model_name='treatmentemergencytype', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='treatmentemergencytype', + name='label', + field=models.TextField(verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='treatmentemergencytype', + name='txt_idx', + field=models.TextField(help_text='Le "slug" est une version standardis\xe9e du nom. Il ne contient que des lettres en minuscule, des nombres et des tirets (-). Chaque "slug" doit \xeatre unique dans la typologie.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Ce champ ne doit contenir que des lettres, des nombres, des tirets bas _ et des traits d'union.", 'invalid')], verbose_name='Identifiant textuel'), + ), + migrations.AlterField( + model_name='treatmentfile', + name='applicant', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='treatmentfile_applicant', to='ishtar_common.Person', verbose_name='Demandeur'), + ), + migrations.AlterField( + model_name='treatmentfile', + name='applicant_organisation', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='treatmentfile_applicant', to='ishtar_common.Organization', verbose_name='Organisation du demandeur'), + ), + migrations.AlterField( + model_name='treatmentfile', + name='cached_label', + field=models.TextField(blank=True, db_index=True, null=True, verbose_name='Nom en cache'), + ), + migrations.AlterField( + model_name='treatmentfile', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='treatmentfile', + name='creation_date', + field=models.DateField(blank=True, default=datetime.date.today, null=True, verbose_name='Date de cr\xe9ation'), + ), + migrations.AlterField( + model_name='treatmentfile', + name='end_date', + field=models.DateField(blank=True, null=True, verbose_name='Date de cl\xf4ture'), + ), + migrations.AlterField( + model_name='treatmentfile', + name='external_id', + field=models.CharField(blank=True, max_length=200, null=True, verbose_name='Identifiant'), + ), + migrations.AlterField( + model_name='treatmentfile', + name='history_creator', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Cr\xe9ateur'), + ), + migrations.AlterField( + model_name='treatmentfile', + name='history_modifier', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Dernier \xe9diteur'), + ), + migrations.AlterField( + model_name='treatmentfile', + name='in_charge', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='treatmentfile_responsability', to='ishtar_common.Person', verbose_name='Dossier suivi par'), + ), + migrations.AlterField( + model_name='treatmentfile', + name='internal_reference', + field=models.CharField(blank=True, max_length=200, null=True, verbose_name='R\xe9f\xe9rence interne'), + ), + migrations.AlterField( + model_name='treatmentfile', + name='name', + field=models.TextField(blank=True, null=True, verbose_name='Nom'), + ), + migrations.AlterField( + model_name='treatmentfile', + name='reception_date', + field=models.DateField(blank=True, null=True, verbose_name='Date de r\xe9ception'), + ), + migrations.AlterField( + model_name='treatmentfile', + name='search_vector', + field=django.contrib.postgres.search.SearchVectorField(blank=True, help_text='Auto-rempli \xe0 la sauvegarde', null=True, verbose_name='Vecteur de recherche'), + ), + migrations.AlterField( + model_name='treatmentfile', + name='type', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='archaeological_finds.TreatmentFileType', verbose_name='Type de demande de traitement'), + ), + migrations.AlterField( + model_name='treatmentfile', + name='year', + field=models.IntegerField(default=ishtar_common.utils.get_current_year, verbose_name='Ann\xe9e'), + ), + migrations.AlterField( + model_name='treatmentfiletype', + name='available', + field=models.BooleanField(default=True, verbose_name='Disponible'), + ), + migrations.AlterField( + model_name='treatmentfiletype', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='treatmentfiletype', + name='label', + field=models.TextField(verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='treatmentfiletype', + name='txt_idx', + field=models.TextField(help_text='Le "slug" est une version standardis\xe9e du nom. Il ne contient que des lettres en minuscule, des nombres et des tirets (-). Chaque "slug" doit \xeatre unique dans la typologie.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Ce champ ne doit contenir que des lettres, des nombres, des tirets bas _ et des traits d'union.", 'invalid')], verbose_name='Identifiant textuel'), + ), + migrations.AlterField( + model_name='treatmentstate', + name='available', + field=models.BooleanField(default=True, verbose_name='Disponible'), + ), + migrations.AlterField( + model_name='treatmentstate', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='treatmentstate', + name='label', + field=models.TextField(verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='treatmentstate', + name='txt_idx', + field=models.TextField(help_text='Le "slug" est une version standardis\xe9e du nom. Il ne contient que des lettres en minuscule, des nombres et des tirets (-). Chaque "slug" doit \xeatre unique dans la typologie.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Ce champ ne doit contenir que des lettres, des nombres, des tirets bas _ et des traits d'union.", 'invalid')], verbose_name='Identifiant textuel'), + ), + migrations.AlterField( + model_name='treatmenttype', + name='available', + field=models.BooleanField(default=True, verbose_name='Disponible'), + ), + migrations.AlterField( + model_name='treatmenttype', + name='comment', + field=models.TextField(blank=True, null=True, verbose_name='Commentaire'), + ), + migrations.AlterField( + model_name='treatmenttype', + name='downstream_is_many', + field=models.BooleanField(default=False, help_text="Cochez cela si, pour ce traitement, \xe0 partir d'un seul \xe9l\xe9ment vous en obtenez plusieurs.", verbose_name='Les \xe9l\xe9ments aval sont multiples'), + ), + migrations.AlterField( + model_name='treatmenttype', + name='label', + field=models.TextField(verbose_name='D\xe9nomination'), + ), + migrations.AlterField( + model_name='treatmenttype', + name='order', + field=models.IntegerField(default=10, verbose_name='Ordre'), + ), + migrations.AlterField( + model_name='treatmenttype', + name='txt_idx', + field=models.TextField(help_text='Le "slug" est une version standardis\xe9e du nom. Il ne contient que des lettres en minuscule, des nombres et des tirets (-). Chaque "slug" doit \xeatre unique dans la typologie.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Ce champ ne doit contenir que des lettres, des nombres, des tirets bas _ et des traits d'union.", 'invalid')], verbose_name='Identifiant textuel'), + ), + migrations.AlterField( + model_name='treatmenttype', + name='upstream_is_many', + field=models.BooleanField(default=False, help_text='Cochez cela si, pour ce traitement, \xe0 partir de plusieurs \xe9l\xe9ments vous en obtenez un seul.', verbose_name='Les \xe9l\xe9ments amont sont multiples'), + ), + migrations.AlterField( + model_name='treatmenttype', + name='virtual', + field=models.BooleanField(verbose_name='Virtuel'), + ), + ] diff --git a/archaeological_finds/migrations/0048_auto_20181203_1746.py b/archaeological_finds/migrations/0048_auto_20181203_1746.py new file mode 100644 index 000000000..567832d72 --- /dev/null +++ b/archaeological_finds/migrations/0048_auto_20181203_1746.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-12-03 17:46 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_finds', '0047_auto_20181203_1442'), + ] + + operations = [ + migrations.AddField( + model_name='find', + name='circumference', + field=models.FloatField(blank=True, null=True, verbose_name='Circumference (cm)'), + ), + migrations.AddField( + model_name='historicalfind', + name='circumference', + field=models.FloatField(blank=True, null=True, verbose_name='Circumference (cm)'), + ), + ] diff --git a/archaeological_finds/migrations/0049_auto_20181210_1518.py b/archaeological_finds/migrations/0049_auto_20181210_1518.py new file mode 100644 index 000000000..28f790ab0 --- /dev/null +++ b/archaeological_finds/migrations/0049_auto_20181210_1518.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-12-10 15:18 +from __future__ import unicode_literals + +from django.db import migrations, models + + +def migrate_treatment_types(apps, schema): + TreatmentType = apps.get_model('archaeological_finds', 'TreatmentType') + q = TreatmentType.objects.filter(txt_idx="loan") + if q.count(): + loan = q.all()[0] + loan.change_current_location = True + loan.save() + q = TreatmentType.objects.filter(txt_idx="loan-return") + if q.count(): + loan_r = q.all()[0] + loan_r.restore_reference_location = True + loan_r.save() + q = TreatmentType.objects.filter(txt_idx="packaging") + if q.count(): + packaging = q.all()[0] + packaging.change_reference_location = True + packaging.change_current_location = True + packaging.save() + q = TreatmentType.objects.filter(txt_idx="virtual-reassembly") + if q.count(): + v = q.all()[0] + v.upstream_is_many = False + v.save() + q = TreatmentType.objects.filter(txt_idx="virtual_group") + if q.count(): + v = q.all()[0] + v.upstream_is_many = False + v.save() + for t in TreatmentType.objects.all(): + t.txt_idx = t.txt_idx.replace("_", "-") + t.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_finds', '0048_auto_20181203_1746'), + ] + + operations = [ + migrations.AddField( + model_name='treatmenttype', + name='change_current_location', + field=models.BooleanField(default=False, help_text='The treatment change the current location.', verbose_name='Change current location'), + ), + migrations.AddField( + model_name='treatmenttype', + name='change_reference_location', + field=models.BooleanField(default=False, help_text='The treatment change the reference location.', verbose_name='Change reference location'), + ), + migrations.AddField( + model_name='treatmenttype', + name='restore_reference_location', + field=models.BooleanField(default=False, help_text='The treatment change restore reference location to the current location.', verbose_name='Restore the reference location'), + ), + migrations.RunPython(migrate_treatment_types) + ] diff --git a/archaeological_finds/migrations/0050_auto_20181211_1509.py b/archaeological_finds/migrations/0050_auto_20181211_1509.py new file mode 100644 index 000000000..c9928d617 --- /dev/null +++ b/archaeological_finds/migrations/0050_auto_20181211_1509.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-12-11 15:09 +from __future__ import unicode_literals + +from django.db import migrations, models + + +def migrate_treatment_states(apps, schema): + TreatmentState = apps.get_model('archaeological_finds', 'TreatmentState') + q = TreatmentState.objects.filter(txt_idx="completed") + if q.count(): + t = q.all()[0] + t.executed = True + t.save() + for t in TreatmentState.objects.all(): + t.txt_idx = t.txt_idx.replace("_", "-") + t.save() + orders = [(10, "planned"), (20, "to-be-confirmed"), (30, "in-progress"), + (40, "completed"), (50, "cancelled"), (60, "unknown"),] + for order, txt_idx in orders: + q = TreatmentState.objects.filter(txt_idx=txt_idx) + if not q.count(): + continue + t = q.all()[0] + t.order = order + t.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_finds', '0049_auto_20181210_1518'), + ] + + operations = [ + migrations.AlterModelOptions( + name='treatmentstate', + options={'ordering': ('order', 'label'), 'verbose_name': "Type d'\xe9tat de traitement", 'verbose_name_plural': "Types d'\xe9tat de traitement"}, + ), + migrations.AddField( + model_name='treatmentstate', + name='executed', + field=models.BooleanField(default=False, verbose_name='Treatment is executed'), + ), + migrations.AddField( + model_name='treatmentstate', + name='order', + field=models.IntegerField(default=10, verbose_name='Ordre'), + ), + migrations.RunPython(migrate_treatment_states) + ] diff --git a/archaeological_finds/migrations/0051_auto_20181211_1530.py b/archaeological_finds/migrations/0051_auto_20181211_1530.py new file mode 100644 index 000000000..9bcdb60a7 --- /dev/null +++ b/archaeological_finds/migrations/0051_auto_20181211_1530.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-12-11 15:30 +from __future__ import unicode_literals + +import archaeological_finds.models_treatments +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_finds', '0050_auto_20181211_1509'), + ] + + operations = [ + migrations.AlterField( + model_name='treatment', + name='treatment_state', + field=models.ForeignKey(default=archaeological_finds.models_treatments.TreatmentState.get_default, on_delete=django.db.models.deletion.CASCADE, to='archaeological_finds.TreatmentState', verbose_name='\xc9tat'), + ), + ] diff --git a/archaeological_finds/migrations/0052_auto_20181211_1558.py b/archaeological_finds/migrations/0052_auto_20181211_1558.py new file mode 100644 index 000000000..5c0f63d7c --- /dev/null +++ b/archaeological_finds/migrations/0052_auto_20181211_1558.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-12-11 15:58 +from __future__ import unicode_literals + +from django.db import migrations, models + + +def migrate_treatment_states(apps, schema): + Treatment = apps.get_model('archaeological_finds', 'Treatment') + for t in Treatment.objects.all(): + t.executed = True + t.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_finds', '0051_auto_20181211_1530'), + ] + + operations = [ + migrations.AddField( + model_name='historicaltreatment', + name='executed', + field=models.BooleanField(default=False, verbose_name='Treatment have been executed'), + ), + migrations.AddField( + model_name='treatment', + name='executed', + field=models.BooleanField(default=False, verbose_name='Treatment have been executed'), + ), + migrations.RunPython(migrate_treatment_states) + ] diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py index e53ad6e6d..393583749 100644 --- a/archaeological_finds/models_finds.py +++ b/archaeological_finds/models_finds.py @@ -23,7 +23,7 @@ from django.conf import settings from django.contrib.gis.db import models from django.core.urlresolvers import reverse from django.db import connection -from django.db.models import Max, Q +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 @@ -91,6 +91,11 @@ post_delete.connect(post_save_cache, sender=ConservatoryState) class TreatmentType(HierarchicalType): order = models.IntegerField(_(u"Order"), default=10) virtual = models.BooleanField(_(u"Virtual")) + destructive = models.BooleanField(_(u"Destructive"), default=False) + create_new_find = models.BooleanField( + _(u"Create a new find"), default=False, + help_text=_(u"If True when this treatment is applied a new version " + u"of the object will be created.")) upstream_is_many = models.BooleanField( _(u"Upstream is many"), default=False, help_text=_( @@ -101,6 +106,16 @@ class TreatmentType(HierarchicalType): help_text=_( u"Check this if for this treatment from one find you'll get " u"many.")) + change_reference_location = models.BooleanField( + _(u"Change reference location"), default=False, + help_text=_(u"The treatment change the reference location.")) + change_current_location = models.BooleanField( + _(u"Change current location"), default=False, + help_text=_(u"The treatment change the current location.")) + restore_reference_location = models.BooleanField( + _(u"Restore the reference location"), default=False, + help_text=_(u"The treatment change restore reference location to the " + u"current location.")) class Meta: verbose_name = _(u"Treatment type") @@ -326,6 +341,15 @@ class BaseFind(BulkUpdatedItem, BaseHistorizedItem, OwnPerms): finds = self.find.filter().order_by("-order").all() return finds and finds[0] + def get_main_find(self): + """ + Get the last find which is not related to many base_find + """ + for find in self.find.order_by('-pk'): + if find.base_finds.count() == 1: + return find + return + def generate_index(self): """ Generate index based on operation or context record (based on @@ -566,31 +590,54 @@ WEIGHT_UNIT = (('g', _(u"g")), ('kg', _(u"kg")),) -class FindBasket(Basket, OwnPerms): +class FindBasket(Basket, MainItem): + SHOW_URL = 'show-findbasket' items = models.ManyToManyField('Find', blank=True, related_name='basket') + QUICK_ACTIONS = [ + QuickAction( + url="findbasket-qa-duplicate", icon_class="fa fa-clone", + text=_(u"Duplicate"), target="one", + rights=['view_find', 'view_own_find']), + ] + class Meta: + verbose_name = _(u"Basket") permissions = ( ("view_find", u"Can view all Finds"), ("view_own_find", u"Can view own Find"), ) - @classmethod - def get_query_owns(cls, ishtaruser): - return Q(user=ishtaruser) - def get_extra_actions(self, request): """ For sheet template: return "Manage basket" action """ # url, base_text, icon, extra_text, extra css class, is a quick action - # no particular rights: if you can view an itm you can add it to your - # own basket - actions = [ - (reverse("select_itemsinbasket", args=[self.pk]), - _(u"Manage basket"), - "fa fa-shopping-basket", "", "", False), + if not request.user or not request.user.ishtaruser: + return [] + + ishtaruser = request.user.ishtaruser + actions = [] + if self.user == ishtaruser or ishtaruser.pk in [ + user.pk for user in self.shared_write_with.all()]: + actions = [ + (reverse("select_itemsinbasket", args=[self.pk]), + _(u"Manage basket"), + "fa fa-shopping-basket", "", "", False), + ] + can_edit_find = self.can_do(request, 'change_find') + if can_edit_find: + actions += [ + (reverse('findbasket-add-treatment', args=[self.pk]), + _(u"Add treatment"), "fa fa-exchange", "", "", False), + ] + + duplicate = self.QUICK_ACTIONS[0] + actions += [ + (reverse(duplicate.url, args=[self.pk]), + duplicate.text, duplicate.icon_class, + "", "", True), ] return actions @@ -631,6 +678,20 @@ class FBulkView(object): """ +def query_loan(is_true=True): + """ + Query to get loan find + + :return: (filter, exclude, extra) + """ + if is_true: + return Q(container_ref__isnull=False, container__isnull=False), \ + Q(container_ref=F('container')), None + else: + return Q(container_ref__isnull=False, container__isnull=False, + container_ref=F('container')), None, None + + class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, MainItem): EXTERNAL_ID_KEY = 'find_external_id' @@ -642,7 +703,8 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, 'base_finds__context_record__label', 'material_types__label', 'object_types__label', 'datings__period__label', - 'container__cached_label', ] + 'container__cached_label', + 'container_ref__cached_label'] if settings.COUNTRY == 'fr': TABLE_COLS.insert( 3, 'base_finds__context_record__operation__code_patriarche') @@ -652,7 +714,7 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, 'previous_id', 'label', 'material_types__label', 'datings__period__label', 'find_number', 'object_types__label', 'container__cached_label', - 'container__cached_location', + 'container_ref__cached_label', 'description', 'base_finds__context_record__town__name', 'base_finds__context_record__parcel', ] @@ -670,7 +732,7 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, 'base_finds__context_record__archaeological_site__name': IshtarSiteProfile.get_default_site_label, 'base_finds__context_record__parcel': _(u"Parcel"), - 'base_finds__batch':_(u"Batch"), + 'base_finds__batch': _(u"Batch"), 'base_finds__comment': _(u"Base find - Comment"), 'base_finds__description': _(u"Base find - Description"), 'base_finds__topographic_localisation': _(u"Base find - " @@ -680,7 +742,8 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, u"Base find - Discovery date (exact or TPQ)"), 'base_finds__discovery_date_taq': _( u"Base find - Discovery date (TAQ)"), - 'container__cached_label': _(u"Container"), + 'container__cached_label': _(u"Current container"), + 'container_ref__cached_label': _(u"Reference container"), 'datings__period__label': _(u"Periods"), 'material_types__label': _(u"Material types"), 'object_types__label': _(u"Object types"), @@ -706,7 +769,7 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, 'base_finds__context_record__', } - DATED_FIELDS = ['last_modified__gte'] + DATED_FIELDS = ['last_modified__gte', 'treatments__file__end_date__lte'] BASE_REQUEST = {'downstream_treatment__isnull': True} EXTRA_REQUEST_KEYS = { 'base_finds__context_record': @@ -863,20 +926,36 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, pgettext_lazy("key for text search", u"has-image"), 'documents__image__isnull', ), - 'container__location': ( + 'container_ref__location': ( pgettext_lazy("key for text search", u"location"), + 'container_ref__location__name__iexact', + ), + 'container_ref__responsible': ( + pgettext_lazy("key for text search", u"warehouse"), + 'container_ref__responsible__name__iexact', + ), + 'container_ref__index': ( + pgettext_lazy("key for text search", u"container-index"), + 'container_ref__index', + ), + 'container_ref__reference': ( + pgettext_lazy("key for text search", u"container-ref"), + 'container_ref__reference__iexact', + ), + 'container__location': ( + pgettext_lazy("key for text search", u"current-location"), 'container__location__name__iexact', ), 'container__responsible': ( - pgettext_lazy("key for text search", u"warehouse"), + pgettext_lazy("key for text search", u"current-warehouse"), 'container__responsible__name__iexact', ), 'container__index': ( - pgettext_lazy("key for text search", u"container-index"), + pgettext_lazy("key for text search", u"current-container-index"), 'container__index', ), 'container__reference': ( - pgettext_lazy("key for text search", u"container-ref"), + pgettext_lazy("key for text search", u"current-container-ref"), 'container__reference__iexact', ), 'basket': ( @@ -899,6 +978,14 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, pgettext_lazy("key for text search", u"created-by"), 'history_creator__ishtaruser__person__cached_label__iexact' ), + 'loan': ( + pgettext_lazy("key for text search", u"loan"), + query_loan + ), + 'treatments_file_end_date': ( + pgettext_lazy("key for text search", u"treatment-end-date-before"), + 'treatments__file__end_date__lte' + ) } for v in ALT_NAMES.values(): for language_code, language_lbl in settings.LANGUAGES: @@ -906,6 +993,8 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, EXTRA_REQUEST_KEYS[unicode(v[0])] = v[1] deactivate() + EXTRA_REQUEST_FUNC = {""} + PARENT_SEARCH_VECTORS = ['base_finds'] BASE_SEARCH_VECTORS = [ "cached_label", "label", "description", "container__location__name", @@ -1003,6 +1092,11 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, "archaeological_warehouse.Container", verbose_name=_(u"Container"), blank=True, null=True, related_name='finds', on_delete=models.SET_NULL) + container_ref = models.ForeignKey( + "archaeological_warehouse.Container", + verbose_name=_(u"Reference container"), + blank=True, null=True, + related_name='finds_ref', on_delete=models.SET_NULL) is_complete = models.NullBooleanField(_(u"Is complete?"), blank=True, null=True) object_types = models.ManyToManyField( @@ -1029,6 +1123,8 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, width = models.FloatField(_(u"Width (cm)"), blank=True, null=True) height = models.FloatField(_(u"Height (cm)"), blank=True, null=True) diameter = models.FloatField(_(u"Diameter (cm)"), blank=True, null=True) + circumference = models.FloatField(_(u"Circumference (cm)"), blank=True, + null=True) thickness = models.FloatField(_(u"Thickness (cm)"), blank=True, null=True) clutter_long_side = models.FloatField( _(u"Clutter - long side (cm)"), blank=True, null=True) @@ -1083,6 +1179,10 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, documents = models.ManyToManyField( Document, related_name='finds', verbose_name=_(u"Documents"), blank=True) + treatments = models.ManyToManyField( + "Treatment", verbose_name=_(u"Treatments"), + related_name='finds', blank=True, + help_text=_(u"Related treatments when no new find is created")) cached_label = models.TextField(_(u"Cached name"), null=True, blank=True, db_index=True) history = HistoricalRecords() @@ -1156,6 +1256,22 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, return return self.base_finds.order_by('-pk').all()[0] + def get_values(self, prefix=''): + values = super(Find, self).get_values(prefix=prefix) + return values + # TODO + bf = self.get_first_base_find() + if not bf: + return values + operation = bf.context_record.operation + values[prefix + "operation"] = [ + { + "common_name": operation.common_name, + "code_patriarche": operation.code_patriarche, + "address": operation.address + } + ] + @property def reference(self): bf = self.get_first_base_find() @@ -1179,6 +1295,8 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, (reverse("find-qa-basket", args=[self.pk]), _(u"Add to basket"), "fa fa-shopping-basket", "", "", True), + (reverse('find-add-treatment', args=[self.pk]), + _(u"Add treatment"), "fa fa-exchange", "", "", False), ] if get_current_profile().warehouse: actions.append( @@ -1338,7 +1456,7 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, q = q.filter(**fltr) return q.filter(downstream_treatment__isnull=True).count() - def duplicate(self, user): + def duplicate(self, user, copy_datings=True): model = self.__class__ new = model.objects.get(pk=self.pk) @@ -1356,12 +1474,22 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, m2m = [field.name for field in model._meta.many_to_many if field.name not in PRIVATE_FIELDS] for field in m2m: - if field == 'images': - for doc in Document.objects.filter(finds__pk=self.pk).all(): - doc.finds.add(new.pk) + if field == 'datings' and copy_datings: + for dating in self.datings.all(): + is_present = False + for current_dating in new.datings.all(): + if Dating.is_identical(current_dating, dating): + is_present = True + break + if is_present: + continue + dating.pk = None + dating.save() + new.datings.add(dating) else: for val in getattr(self, field).all(): - getattr(new, field).add(val) + if val not in getattr(new, field).all(): + getattr(new, field).add(val) return new @classmethod @@ -1375,6 +1503,9 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, ) | cls._construct_query_own( 'base_finds__context_record__operation__', Operation._get_query_owns_dicts(ishtaruser) + ) | cls._construct_query_own( + 'basket__', + [{"shared_with": ishtaruser, "shared_write_with": ishtaruser}] ) | cls._construct_query_own('', [ {'history_creator': ishtaruser.user_ptr}, {'base_finds__context_record__operation__end_date__isnull': True} @@ -1493,21 +1624,62 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, with connection.cursor() as c: c.execute(sql, args) - def get_localisation(self, place): + def get_localisation(self, place, is_ref=False): """ Get localisation reference in the warehouse :param place: number of the localisation starting with 0 + :param is_ref: if true - reference container else current container :return: reference - empty string if not available """ - if not self.container: + if is_ref: + container = self.container_ref + else: + container = self.container + if not container: return "" - locas = self.container.get_localisations() + locas = container.get_localisations() if len(locas) < (place + 1): return "" return locas[place] @property + def reference_localisation_1(self): + return self.get_localisation(0, is_ref=True) + + @property + def reference_localisation_2(self): + return self.get_localisation(1, is_ref=True) + + @property + def reference_localisation_3(self): + return self.get_localisation(2, is_ref=True) + + @property + def reference_localisation_4(self): + return self.get_localisation(3, is_ref=True) + + @property + def reference_localisation_5(self): + return self.get_localisation(4, is_ref=True) + + @property + def reference_localisation_6(self): + return self.get_localisation(5, is_ref=True) + + @property + def reference_localisation_7(self): + return self.get_localisation(6, is_ref=True) + + @property + def reference_localisation_8(self): + return self.get_localisation(7, is_ref=True) + + @property + def reference_localisation_9(self): + return self.get_localisation(8, is_ref=True) + + @property def localisation_1(self): return self.get_localisation(0) @@ -1543,19 +1715,75 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, def localisation_9(self): return self.get_localisation(8) - def set_localisation(self, place, context, value): - if not self.container: + def set_localisation(self, place, context, value, is_ref=False): + """ + Get localisation reference in the warehouse + + :param place: number of the localisation starting with 0 + :param context: context of the request - not used + :param value: localisation value + :param is_ref: if true - reference container else current container + :return: None + """ + if is_ref: + container = self.container_ref + else: + container = self.container + + if not container: if not value: return - raise ImporterError(_(u"No container have been set - the " - u"localisation cannot be set.")) + if is_ref: + raise ImporterError( + _(u"No reference container have been set - the " + u"localisation cannot be set.")) + else: + raise ImporterError( + _(u"No container have been set - the localisation cannot " + u"be set.")) - localisation = self.container.set_localisation(place, value) + localisation = container.set_localisation(place, value) if value and value != '-' and not localisation: raise ImporterError( unicode(_(u"The division number {} have not been set " u"for the warehouse {}.")).format( - place + 1, self.container.location)) + place + 1, container.location)) + + @post_importer_action + def set_reference_localisation_1(self, context, value): + return self.set_localisation(0, context, value, is_ref=True) + + @post_importer_action + def set_reference_localisation_2(self, context, value): + return self.set_localisation(1, context, value, is_ref=True) + + @post_importer_action + def set_reference_localisation_3(self, context, value): + return self.set_localisation(2, context, value, is_ref=True) + + @post_importer_action + def set_reference_localisation_4(self, context, value): + return self.set_localisation(3, context, value, is_ref=True) + + @post_importer_action + def set_reference_localisation_5(self, context, value): + return self.set_localisation(4, context, value, is_ref=True) + + @post_importer_action + def set_reference_localisation_6(self, context, value): + return self.set_localisation(5, context, value, is_ref=True) + + @post_importer_action + def set_reference_localisation_7(self, context, value): + return self.set_localisation(6, context, value, is_ref=True) + + @post_importer_action + def set_reference_localisation_8(self, context, value): + return self.set_localisation(7, context, value, is_ref=True) + + @post_importer_action + def set_reference_localisation_9(self, context, value): + return self.set_localisation(8, context, value, is_ref=True) @post_importer_action def set_localisation_1(self, context, value): @@ -1634,6 +1862,9 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, super(Find, self).save(*args, **kwargs) self.skip_history_when_saving = True + if self.container_ref and not self.container: + self.container = self.container_ref + updated = self.update_external_id(save=False) if updated: self._cached_label_checked = False @@ -1649,6 +1880,9 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, for base_find in self.base_finds.filter( context_record__operation__pk__isnull=False).all(): modified = False + if self.label and not base_find.label: + base_find.label = self.label + modified = True if not base_find.index: modified = base_find.generate_index() short_id = base_find.short_id() @@ -1659,6 +1893,8 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, if base_find.cache_complete_id != complete_id: base_find.cache_complete_id = complete_id modified = True + if base_find.update_external_id(): + modified = True if modified: base_find.skip_history_when_saving = True base_find._cached_label_checked = False diff --git a/archaeological_finds/models_treatments.py b/archaeological_finds/models_treatments.py index 6a57a77f5..06f61068b 100644 --- a/archaeological_finds/models_treatments.py +++ b/archaeological_finds/models_treatments.py @@ -21,6 +21,7 @@ import datetime from django.conf import settings from django.contrib.gis.db import models +from django.core.urlresolvers import reverse from django.db.models import Max, Q from django.db.models.signals import post_save, post_delete, pre_delete from django.template.defaultfilters import slugify @@ -29,19 +30,31 @@ from django.utils.translation import ugettext_lazy as _, pgettext_lazy, \ from archaeological_finds.models_finds import Find, FindBasket, TreatmentType from archaeological_operations.models import ClosedItem, Operation +from archaeological_context_records.models import Dating from archaeological_warehouse.models import Warehouse, Container from ishtar_common.models import Document, GeneralType, \ ImageModel, BaseHistorizedItem, OwnPerms, HistoricalRecords, Person, \ Organization, ValueGetter, post_save_cache, ShortMenuItem, \ DashboardFormItem, ExternalIdManager -from ishtar_common.utils import cached_label_changed, get_current_year +from ishtar_common.utils import cached_label_changed, get_current_year, \ + update_data class TreatmentState(GeneralType): + executed = models.BooleanField(_(u"Treatment is executed"), default=False) + order = models.IntegerField(verbose_name=_(u"Order"), default=10) + class Meta: verbose_name = _(u"Treatment state type") verbose_name_plural = _(u"Treatment state types") - ordering = ('label',) + ordering = ('order', 'label',) + + @classmethod + def get_default(cls): + q = cls.objects.filter(executed=True) + if not q.count(): + return None + return q.all()[0].pk post_save.connect(post_save_cache, sender=TreatmentState) @@ -68,10 +81,12 @@ class Treatment(DashboardFormItem, ValueGetter, BaseHistorizedItem, "upstream_cached_label": _(u"Upstream find"), "treatment_types__label": _(u"Type"), "treatment_state__label": _(u"State"), - 'person__cached_label': _(u"Responsible"), + "person__cached_label": _(u"Responsible"), } # extra keys than can be passed to save method - EXTRA_SAVED_KEYS = ('items', 'user') + EXTRA_SAVED_KEYS = ('items', 'user', 'resulting_find', 'upstream_items', + 'resulting_finds', 'upstream_item', + 'treatment_type_list') # alternative names of fields for searches ALT_NAMES = { @@ -127,8 +142,11 @@ class Treatment(DashboardFormItem, ValueGetter, BaseHistorizedItem, treatment_types = models.ManyToManyField( TreatmentType, verbose_name=_(u"Treatment type")) treatment_state = models.ForeignKey( - TreatmentState, verbose_name=_(u"State"), blank=True, null=True, + TreatmentState, verbose_name=_(u"State"), + default=TreatmentState.get_default ) + executed = models.BooleanField( + _(u"Treatment have been executed"), default=False) location = models.ForeignKey( Warehouse, verbose_name=_(u"Location"), blank=True, null=True, help_text=_( @@ -147,6 +165,7 @@ class Treatment(DashboardFormItem, ValueGetter, BaseHistorizedItem, goal = models.TextField(_(u"Goal"), blank=True, null=True) start_date = models.DateField(_(u"Start date"), blank=True, null=True) end_date = models.DateField(_(u"Closing date"), blank=True, null=True) + creation_date = models.DateTimeField(default=datetime.datetime.now) container = models.ForeignKey(Container, verbose_name=_(u"Container"), blank=True, null=True) estimated_cost = models.FloatField(_(u"Estimated cost"), @@ -157,8 +176,6 @@ class Treatment(DashboardFormItem, ValueGetter, BaseHistorizedItem, blank=True, null=True) insurance_cost = models.FloatField(_(u"Insurance cost"), blank=True, null=True) - target_is_basket = models.BooleanField(_(u"Target a basket"), - default=False) documents = models.ManyToManyField( Document, related_name='treatments', verbose_name=_(u"Documents"), blank=True) @@ -177,6 +194,7 @@ class Treatment(DashboardFormItem, ValueGetter, BaseHistorizedItem, ("change_own_treatment", u"Can change own Treatment"), ("delete_own_treatment", u"Can delete own Treatment"), ) + ordering = ("start_date", ) def __unicode__(self): if self.cached_label: @@ -189,6 +207,10 @@ class Treatment(DashboardFormItem, ValueGetter, BaseHistorizedItem, def short_class_name(self): return _(u"TREATMENT") + @property + def limited_finds(self): + return self.finds.all()[:15] + def natural_key(self): return (self.external_id, ) @@ -258,6 +280,17 @@ class Treatment(DashboardFormItem, ValueGetter, BaseHistorizedItem, upstream_lbl.short_description = _(u"Upstream finds") upstream_lbl.admin_order_field = 'upstream__cached_label' + def get_extra_actions(self, request): + # url, base_text, icon, extra_text, extra css class, is a quick action + actions = [] + if self.can_do(request, 'add_administrativeact'): + actions += [ + (reverse('treatment-add-adminact', args=[self.pk]), + _(u"Add associated administrative act"), "fa fa-plus", + _(u"admin. act"), "", False), + ] + return actions + def get_values(self, prefix=''): values = super(Treatment, self).get_values(prefix=prefix) values[prefix + "upstream_finds"] = u" ; ".join( @@ -283,41 +316,243 @@ class Treatment(DashboardFormItem, ValueGetter, BaseHistorizedItem, if q.count(): self.index = q.all().aggregate(Max('index'))['index__max'] + 1 + def _create_n_1_resulting_find(self, resulting_find, upstream_items, + treatment_types): + """ + Manage creation of n<->1 treatment + """ + m2m = {} + base_fields = [f.name for f in Find._meta.get_fields()] + for k in resulting_find.keys(): + # if not in base fields should be a m2m + if k not in base_fields: + values = resulting_find.pop(k) + if values: + m2m[k + "s"] = values + + resulting_find['history_modifier'] = self.history_modifier + new_find = Find.objects.create(**resulting_find) + + for k in m2m: + m2m_field = getattr(new_find, k) + try: + for value in m2m[k]: + m2m_field.add(value) + except TypeError: + m2m_field.add(m2m[k]) + + create_new_find = bool([tp for tp in treatment_types + if tp.create_new_find]) + + current_base_finds = [] + current_documents = [] + for upstream_item in upstream_items: + # datings are not explicitly part of the resulting_find + # need to reassociate with no duplicate + for dating in upstream_item.datings.all(): + is_present = False + for current_dating in new_find.datings.all(): + if Dating.is_identical(current_dating, dating): + is_present = True + break + if is_present: + continue + dating.pk = None # duplicate + dating.save() + new_find.datings.add(dating) + + # associate base finds + for base_find in upstream_item.base_finds.all(): + if base_find.pk in current_base_finds: + continue + current_base_finds.append(base_find.pk) + new_find.base_finds.add(base_find) + + # documents + for document in upstream_item.documents.all(): + if document.pk in current_documents: + continue + current_documents.append(document.pk) + new_find.documents.add(document) + + # data + new_find.data = update_data(new_find.data, upstream_item.data, + merge=True) + + if create_new_find: + upstream_item.downstream_treatment = self + upstream_item.history_modifier = self.history_modifier + upstream_item.save() + else: + self.finds.add(upstream_item) + + new_find.upstream_treatment = self + new_find.skip_history_when_saving = True + new_find.save() + + def _create_1_n_resulting_find(self, resulting_finds, upstream_item, user, + treatment_types): + """ + Manage creation of 1<->n treatment + """ + new_items = [] + start_number = resulting_finds['start_number'] + for idx in range(resulting_finds['number']): + label = resulting_finds['label'] + unicode(start_number + idx) + new_find = Find.objects.get( + pk=upstream_item.pk).duplicate(user) + new_find.upstream_treatment = self + new_find.label = label + new_find.skip_history_when_saving = True + new_find.save() + new_items.append(new_find) + + create_new_find = bool([tp for tp in treatment_types + if tp.create_new_find]) + + if create_new_find: + upstream_item.downstream_treatment = self + upstream_item.skip_history_when_saving = True + upstream_item.save() + else: + self.finds.add(upstream_item) + + if getattr(user, 'ishtaruser', None): + b = FindBasket.objects.create( + label=resulting_finds['basket_name'], user=user.ishtaruser) + for item in new_items: + b.items.add(item) + def save(self, *args, **kwargs): - items, user, extra_args_for_new = [], None, [] + items, user, extra_args_for_new, resulting_find = [], None, [], None + upstream_items, upstream_item, resulting_finds = [], None, None + treatment_types = [] if "items" in kwargs: items = kwargs.pop('items') + if "resulting_find" in kwargs: + resulting_find = kwargs.pop('resulting_find') + if "resulting_finds" in kwargs: + resulting_finds = kwargs.pop('resulting_finds') + if "upstream_items" in kwargs: + upstream_items = kwargs.pop('upstream_items') + if "upstream_item" in kwargs: + upstream_item = kwargs.pop('upstream_item') if "user" in kwargs: user = kwargs.pop('user') if "extra_args_for_new" in kwargs: extra_args_for_new = kwargs.pop('extra_args_for_new') + if "treatment_type_list" in kwargs: + treatment_types = kwargs.pop('treatment_type_list') self.pre_save() super(Treatment, self).save(*args, **kwargs) + to_be_executed = not self.executed and self.treatment_state.executed + updated = [] + # baskets if hasattr(items, "items"): items = items.items.all() + if hasattr(upstream_items, "items"): + upstream_items = upstream_items.items.all() + if not items and self.finds.count(): + items = list(self.finds.all()) + if not treatment_types and self.treatment_types.count(): + treatment_types = list(self.treatment_types.all()) + + # execute the treatment + if upstream_items and resulting_find: + if not to_be_executed: + # should not happen but bad validation check... + return + self._create_n_1_resulting_find(resulting_find, upstream_items, + treatment_types) + self.executed = True + self.save() + return + + if upstream_item and resulting_finds: + if not to_be_executed: + # should not happen but bad validation check... + return + self._create_1_n_resulting_find( + resulting_finds, upstream_item, self.history_modifier, + treatment_types) + self.executed = True + self.save() + return + + create_new_find = bool([tp for tp in treatment_types + if tp.create_new_find]) + for item in items: - new = item.duplicate(user) - item.downstream_treatment = self - item.save() - new.upstream_treatment = self - for k in extra_args_for_new: - setattr(new, k, extra_args_for_new[k]) - new.save() - updated.append(new.pk) - # update baskets - for basket in \ - FindBasket.objects.filter(items__pk=item.pk).all(): - basket.items.remove(item) - basket.items.add(new) + if not create_new_find or not to_be_executed: + self.finds.add(item) + else: + self.finds.clear() + new = item.duplicate(user) + item.downstream_treatment = self + item.save() + new.upstream_treatment = self + for k in extra_args_for_new: + setattr(new, k, extra_args_for_new[k]) + new.save() + updated.append(new.pk) + # update baskets + for basket in \ + FindBasket.objects.filter(items__pk=item.pk).all(): + basket.items.remove(item) + basket.items.add(new) + + if not to_be_executed: + return + + if create_new_find: + q = Find.objects.filter(upstream_treatment=self) + else: + q = Find.objects.filter(treatments=self) + + # manage loan return + for tp in treatment_types: + if tp.restore_reference_location: + for find in q.all(): + if find.container_ref: + find.container = find.container_ref + if find.pk in updated: + # don't record twice history + find.skip_history_when_saving = True + find.save() + self.executed = True + self.save() + break + # manage containers - for find in Find.objects.filter(upstream_treatment=self).all(): - if find.container != self.container: - find.container = self.container - if find.pk in updated: - # don't record twice history - find.skip_history_when_saving = True - find.save() + if not self.container: + return + + container_attrs = [] + for tp in treatment_types: + if tp.change_current_location: + if 'container' in container_attrs: + continue + container_attrs.append('container') + if tp.change_reference_location: + if 'container_ref' in container_attrs: + continue + container_attrs.append('container_ref') + + if not container_attrs: + # non consistent treatment + return + + for find in q.all(): + for container_attr in container_attrs: + if getattr(find, container_attr) != self.container: + setattr(find, container_attr, self.container) + if find.pk in updated: + # don't record twice history + find.skip_history_when_saving = True + find.save() + self.executed = True + self.save() @property def associated_filename(self): @@ -515,6 +750,8 @@ class FindTreatments(AbsFindTreatments): class TreatmentFileType(GeneralType): + treatment_type = models.ForeignKey(TreatmentType, blank=True, null=True) + class Meta: verbose_name = _(u"Treatment request type") verbose_name_plural = _(u"Treatment request types") @@ -610,6 +847,10 @@ class TreatmentFile(DashboardFormItem, ClosedItem, BaseHistorizedItem, documents = models.ManyToManyField( Document, related_name='treatment_files', verbose_name=_(u"Documents"), blank=True) + associated_basket = models.ForeignKey( + FindBasket, null=True, blank=True, on_delete=models.SET_NULL, + related_name='treatment_files' + ) cached_label = models.TextField(_(u"Cached name"), null=True, blank=True, db_index=True) history = HistoricalRecords() @@ -619,21 +860,15 @@ class TreatmentFile(DashboardFormItem, ClosedItem, BaseHistorizedItem, verbose_name_plural = _(u"Treatment requests") unique_together = ('year', 'index') permissions = ( - ("view_filetreatment", + ("view_treatmentfile", u"Can view all Treatment requests"), - ("add_filetreatment", - u"Can add Treatment request"), - ("change_filetreatment", - u"Can change Treatment request"), - ("delete_filetreatment", - u"Can delete Treatment request"), - ("view_own_filetreatment", + ("view_own_treatmentfile", u"Can view own Treatment request"), - ("add_own_filetreatment", + ("add_own_treatmentfile", u"Can add own Treatment request"), - ("change_own_filetreatment", + ("change_own_treatmentfile", u"Can change own Treatment request"), - ("delete_own_filetreatment", + ("delete_own_treatmentfile", u"Can delete own Treatment request"), ) ordering = ('cached_label',) @@ -657,6 +892,39 @@ class TreatmentFile(DashboardFormItem, ClosedItem, BaseHistorizedItem, for attr in ('year', 'index', 'internal_reference', 'name') if getattr(self, attr)]) + def get_values(self, prefix=''): + values = super(TreatmentFile, self).get_values(prefix=prefix) + if not self.associated_basket: + return + values[prefix + "basket"] = [ + find.get_values() for find in self.associated_basket.items.all() + ] + return values + + def get_extra_actions(self, request): + # url, base_text, icon, extra_text, extra css class, is a quick action + actions = [] + if self.can_do(request, 'add_administrativeact'): + actions += [ + (reverse('treatmentfile-add-adminact', args=[self.pk]), + _(u"Add associated administrative act"), "fa fa-plus", + _(u"admin. act"), "", False), + ] + if not self.associated_basket: + return actions + if self.type.treatment_type and self.treatments.filter( + treatment_types__pk=self.type.treatment_type.pk).count(): + # a treatment of this type already exists + return actions + can_edit_find = self.can_do(request, 'change_find') + if can_edit_find: + actions += [ + (reverse('treatmentfile-add-treatment', args=[self.pk]), + _(u"Add associated treatment"), "fa fa-exchange", "", "", + False), + ] + return actions + @classmethod def get_owns(cls, user, menu_filtr=None, limit=None, values=None, get_short_menu_class=None): diff --git a/archaeological_finds/templates/ishtar/blocks/window_find_nav.html b/archaeological_finds/templates/ishtar/blocks/window_find_nav.html new file mode 100644 index 000000000..74c6858a1 --- /dev/null +++ b/archaeological_finds/templates/ishtar/blocks/window_find_nav.html @@ -0,0 +1,21 @@ +{% extends "ishtar/blocks/window_nav.html" %} +{% load i18n link_to_window %} +{% block post_pin %}{% if baskets %} +<div class="dropdown btn-secondary"> + <button class="btn btn-sm btn-secondary dropdown-toggle" type="button" + id="dropdown-post-pin-{{window_id}}" + data-toggle="dropdown"aria-haspopup="true" + aria-expanded="false"> + <i class="fa fa-shopping-basket"></i> {% trans "Baskets" %} + </button> + <div class="dropdown-menu" aria-labelledby="dropdown-post-pin-{{window_id}}"> + {% for basket_id, lbl in baskets %} + <a class="dropdown-item" href="#" + onclick="load_window('{% url 'show-findbasket' basket_id %}')"> + <i class="fa fa-info-circle display_details" aria-hidden="true"></i> + {{lbl}} + </a> + {% endfor %} + </div> +</div> +{% endif %}{% endblock %} diff --git a/archaeological_finds/templates/ishtar/forms/qa_find_treatment.html b/archaeological_finds/templates/ishtar/forms/qa_find_treatment.html index ef3906735..f20f0cb65 100644 --- a/archaeological_finds/templates/ishtar/forms/qa_find_treatment.html +++ b/archaeological_finds/templates/ishtar/forms/qa_find_treatment.html @@ -27,20 +27,26 @@ </div> <div class="form-row"> + {{ form.reference_container }} <label for="{{form.reference_container.auto_id}}"> + {% trans "Change the reference container" %} + </label> + </div> + + <div class="form-row"> {{ form.create_treatment }} <label for="{{form.create_treatment.auto_id}}"> {% trans "Associate a treatment" %} </label> </div> <div id="new-treatment"> - {% for field in form %} - {% if field.name != 'container' and field.name != 'create_treatment' %} - {% if forloop.counter0|divisibleby:2 %} + {% with force_large_col=True %}{% for field in form %} + {% if field.name != 'reference_container' and field.name != 'container' and field.name != 'create_treatment' %} + {% if forloop.counter|divisibleby:2 %} <div class="form-row">{% endif %} {% include "blocks/bs_field_snippet.html" %} {% if not forloop.counter0|divisibleby:2 %} </div>{% endif %} {% endif %} - {% endfor %} + {% endfor %}{% endwith %} </div> {% endblock %} diff --git a/archaeological_finds/templates/ishtar/forms/qa_findbasket_duplicate.html b/archaeological_finds/templates/ishtar/forms/qa_findbasket_duplicate.html new file mode 100644 index 000000000..b9ec50f22 --- /dev/null +++ b/archaeological_finds/templates/ishtar/forms/qa_findbasket_duplicate.html @@ -0,0 +1,22 @@ +{% extends "ishtar/forms/qa_base.html" %} +{% load i18n inline_formset table_form %} + +{% block main_form %} +<div class="alert alert-info"> + {% trans "Items of the basket will be attached to the new basket but not the shares." %} +</div> +{% if form.non_field_errors %} +<div class="alert alert-danger" role="alert"> + {{form.non_field_errors}} +</div> +{% endif %} +<div class="form-row"> + <div class="form-group col-lg-6 required"> + <label>{% trans "Label" %}</label> + </div> + {% with form.label as field %} + {% include "blocks/bs_field_snippet.html" %} + {% endwith %} +</div> +{% endblock %} + diff --git a/archaeological_finds/templates/ishtar/sheet_basefind.html b/archaeological_finds/templates/ishtar/sheet_basefind.html index c20ca66ee..7ea16fecb 100644 --- a/archaeological_finds/templates/ishtar/sheet_basefind.html +++ b/archaeological_finds/templates/ishtar/sheet_basefind.html @@ -1,6 +1,10 @@ {% load i18n window_field from_dict link_to_window window_tables window_header humanize %} - <p class='window-refs text-center'>{{base_find.complete_id }}</p> - <p class='window-refs text-center'>{{base_find.short_id }}</p> +<div id="{{window_id}}-base-find-{{forloop.counter}}" role="tabpanel" + class="tab-pane fade{% if forloop.first %} show active{% endif %}"> + <p class='window-refs text-center'>{{ base_find.complete_id }}</p> + {% if base_find.complete_id != base_find.short_id %} + <p class='window-refs text-center'>{{ base_find.short_id }}</p> + {% endif %} {% if base_find.external_id %} <p class='window-refs text-center external-id'> <small title="{% trans 'Internal ID' %}"> @@ -77,11 +81,5 @@ {% endwith %}{% endwith %} {% endif %} </div> - -{% if first %} - </div> </div> -<div class="subsection"> -{% endif %} -{% if forloop.counter0 %}<hr/>{% endif %} diff --git a/archaeological_finds/templates/ishtar/sheet_find.html b/archaeological_finds/templates/ishtar/sheet_find.html index 021ea5652..7171c3deb 100644 --- a/archaeological_finds/templates/ishtar/sheet_find.html +++ b/archaeological_finds/templates/ishtar/sheet_find.html @@ -1,10 +1,10 @@ {% extends "ishtar/sheet.html" %} -{% load i18n window_field from_dict link_to_window window_tables window_header humanize %} +{% load i18n ishtar_helpers window_field from_dict link_to_window window_tables window_header humanize %} {% block head_title %}<strong>{% trans "Find" %}</strong>{% if item.denomination %} - {{item.denomination|default:""}}{% endif %} - {{item.label|default:""}}{% endblock %} {% block toolbar %} -{% window_nav item window_id 'show-find' 'find_modify' 'show-historized-find' 'revert-find' previous next 1 %} +{% window_find_nav item window_id 'show-find' 'find_modify' 'show-historized-find' 'revert-find' previous next 1 baskets %} {% endblock %} {% block content %} @@ -15,243 +15,387 @@ </div> {% endif %} +{# trick to set to null non existing variable #} +{% with permission_view_document=permission_view_document %} +{% with permission_view_own_document=permission_view_own_document %} -{% with nb_image=item.images.count %} -{% if nb_image %} -<div class="clearfix"> - <div class="card float-left col-12 col-md-6 col-lg-4"> - {% include "ishtar/blocks/window_image.html" %} - <div class="card-body"> - </div> - </div> -{% endif %} +{% with display_identification=item.integrities.count|or_:item.remarkabilities.count|or_:item.conservatory_state|or_:item.conservatory_comment|or_:item.alterations.count|or_:item.alteration_causes.count|or_:item.preservation_to_considers.count|or_:item.appraisal_date|or_:item.treatment_emergency|or_:item.insurance_value|or_:item.estimated_value|or_:item.datings.count|or_:item.dating_comment %} +{% with display_warehouse_treatments=item.container|or_:item.container_ref|or_:item.upstream_treatment|or_:item.downstream_treatment|or_:item.treatments.count %} +{% with can_view_documents=permission_view_own_document|or_:permission_view_document %} +{% with display_documents=can_view_documents|and_:item.documents.count %} - <h2>{% trans "Associated base finds"%}</h2> +<ul class="nav nav-tabs" id="{{window_id}}-tabs" role="tablist"> + <li class="nav-item"> + <a class="nav-link active" id="{{window_id}}-basefind-tab" + data-toggle="tab" href="#{{window_id}}-basefind" role="tab" + aria-controls="{{window_id}}-basefind" aria-selected="true"> + {% trans "Image / Base find" %} + </a> + </li> + <li class="nav-item"> + <a class="nav-link" id="{{window_id}}-identification-tab" + data-toggle="tab" href="#{{window_id}}-identification" role="tab" + aria-controls="{{window_id}}-identification" aria-selected="false"> + {% trans "Identification / Description / Dimensions" %} + </a> + </li> + {% if display_identification %} + <li class="nav-item"> + <a class="nav-link" id="{{window_id}}-preservation-tab" + data-toggle="tab" href="#{{window_id}}-preservation" role="tab" + aria-controls="{{window_id}}-preservation" aria-selected="false"> + {% trans "Datings / Preservation" %} + </a> + </li> + {% endif %} + {% if display_warehouse_treatments %} + <li class="nav-item"> + <a class="nav-link" id="{{window_id}}-warehouse-tab" + data-toggle="tab" href="#{{window_id}}-warehouse" role="tab" + aria-controls="{{window_id}}-warehouse" aria-selected="false"> + {% trans "Warehouse / Treatments" %} + </a> + </li> + {% endif %} + {% if display_documents %} + <li class="nav-item"> + <a class="nav-link" id="{{window_id}}-documents-tab" + data-toggle="tab" href="#{{window_id}}-documents" role="tab" + aria-controls="{{window_id}}-treatments" aria-selected="false"> + {% trans "Documents" %} + </a> + </li> + {% endif %} + {% if item.data %} + <li class="nav-item"> + <a class="nav-link" id="{{window_id}}-json-tab" + data-toggle="tab" href="#{{window_id}}-json" role="tab" + aria-controls="{{window_id}}-json" aria-selected="false"> + {% trans "Custom fields" %} + </a> + </li> + {% endif %} +</ul> - <div class="subsection"> - {% for base_find in item.base_finds.all %} - {% with first=forloop.first|add:nb_image %} - {% include "ishtar/sheet_basefind.html" %} - {% endwith %} - {% endfor %} - </div> -{% endwith %} +<div class="tab-content" id="{{window_id}}-tab-content"> -<h3>{% trans "Identification" %}</h3> + <div class="tab-pane fade show active" id="{{window_id}}-basefind" + role="tabpanel" aria-labelledby="{{window_id}}-basefind-tab"> + {% with nb_image=item.images.count %} + {% if nb_image %} + <div class="clearfix"> + <div class="card float-left col-12 col-md-6 col-lg-4"> + {% include "ishtar/blocks/window_image.html" %} + <div class="card-body"> + </div> + </div> + {% endif %} -<div class='text-center'> - {% include "ishtar/blocks/sheet_external_id.html" %} -</div> + <ul class="nav nav-pills" role="tablist"> + {% for base_find in item.base_finds.all %} + <li class="nav-item"> + <a class="nav-link{% if forloop.first %} active{% endif %}" + data-toggle="tab" href="#{{window_id}}-base-find-{{forloop.counter}}" + role="tab"> + {{base_find.short_id}} + </a> + </li> + {% endfor %} + </ul> -<div class='row'> - {% field_flex "Denomination" item.denomination %} - {% field_flex "Free ID" item.label %} - {% field_flex "Previous ID" item.previous_id %} - {% field_flex "Excavation ID" item.excavation_ids %} - {% field_flex "Museum ID" item.museum_id %} - {% field_flex "Seal number" item.seal_number %} - {% trans "Administrative index" as admin_index_label %} - {% field_flex admin_index_label item.administrative_index %} - {% field_flex_full "Mark" item.mark "<pre>" "</pre>" %} -</div> + <div class="tab-content"> + {% for base_find in item.base_finds.all %} + {% with first=forloop.first|add:nb_image %} + {% include "ishtar/sheet_basefind.html" %} + {% endwith %} + {% endfor %} + </div> + {% if nb_image %} + </div> + {% endif %} + {% endwith %} + </div> -<h3>{% trans "Description" %}</h3> -<div class='row'> - {% field_flex_full "Description" item.description "<pre>" "</pre>" %} - {% field_flex "Is complete?" item.is_complete %} - {% field_flex_multiple "Material types" item.material_types %} - {% field_flex "Material type quality" item.material_type_quality %} - {% field_flex_multiple "Object types" item.object_types %} - {% field_flex "Object type quality" item.object_type_quality %} - {% field_flex "Find number" item.find_number %} - {% field_flex "Minimum number of individuals (MNI)" item.min_number_of_individuals %} - {% field_flex_full "Decoration" item.decoration "<pre>" "</pre>" %} - {% field_flex_full "Inscription" item.inscription "<pre>" "</pre>" %} - {% field_flex "Manufacturing place" item.manufacturing_place %} - {% field_flex_multiple "Communicability" item.communicabilities %} - {% field_flex_full "Comment" item.comment "<pre>" "</pre>" %} -</div> + <div class="tab-pane fade" id="{{window_id}}-identification" + role="tabpanel" aria-labelledby="{{window_id}}-identification-tab"> + <h3>{% trans "Identification" %}</h3> -{% if item.length or item.width or item.height or item.diameter or item.thickness or item.volume or item.weight_string or item.dimensions_comment or item.clutter_long_side or item.clutter_short_side or item.clutter_height %} -<h3>{% trans "Dimensions" %}</h3> -<div class='row'> - {% field_flex "Length (cm)" item.length %} - {% field_flex "Width (cm)" item.width %} - {% field_flex "Height (cm)" item.height %} - {% field_flex "Diameter (cm)" item.diameter %} - {% field_flex "Thickness (cm)" item.thickness %} - {% field_flex "Volume (l)" item.volume %} - {% trans "Weight (g)" as weight_label %} - {% field_flex weight_label item.weight_string %} - {% field_flex "Clutter long side (cm)" item.clutter_long_side %} - {% field_flex "Clutter short side (cm)" item.clutter_short_side %} - {% field_flex "Clutter height (cm)" item.clutter_height %} - {% field_flex_full "Dimensions comment" item.dimensions_comment "<pre>" "</pre>" %} -</div> -{% endif %} - -<h3>{% trans "Sheet" %}</h3> -<div class='row'> - {% trans "Checked" as checked_label %} - {% field_flex checked_label item.checked_type %} - {% field_flex "Check date" item.check_date %} - {% include "ishtar/blocks/sheet_creation_section.html" %} -</div> - -{% if item.integrities.count or item.remarkabilities.count or item.conservatory_state or item.conservatory_comment or item.alterations.count or item.alteration_causes.count or item.preservation_to_considers.count or item.appraisal_date or item.treatment_emergency or item.insurance_value or item.estimated_value %} -<h3>{% trans "Preservation" %}</h3> -<div class='row'> - {% field_flex_multiple "Integrity / interest" item.integrities %} - {% field_flex_multiple "Remarkability" item.remarkabilities %} - {% field_flex "Conservatory state" item.conservatory_state %} - {% field_flex_multiple "Alteration" item.alterations %} - {% field_flex_multiple "Alteration cause" item.alteration_causes %} - {% field_flex_multiple "Recommended treatments" item.preservation_to_considers %} - {% field_flex "Treatment emergency" item.treatment_emergency %} - {% field_flex "Estimated value" item.estimated_value|default_if_none:''|intcomma '' ' '|add:CURRENCY %} - {% field_flex "Insurance value" item.insurance_value|default_if_none:''|intcomma '' ' '|add:CURRENCY %} - {% field_flex "Appraisal date" item.appraisal_date %} - {% field_flex_full "Conservatory comment" item.conservatory_comment "<pre>" "</pre>" %} -</div> -{% endif %} + <div class='text-center'> + {% include "ishtar/blocks/sheet_external_id.html" %} + </div> -{% if item.dating or item.dating_comment %} -<h3>{% trans "Dating" %}</h3> -{% if item.datings.count %} -<table id='{{window_id}}-datings' class="table table-striped"> - <tr> - <th>{% trans "Period" %}</th> - <th>{% trans "Start date" %}</th> - <th>{% trans "End date" %}</th> - <th>{% trans "Dating type" %}</th> - <th>{% trans "Quality" %}</th> - <th>{% trans "Precise dating" %}</th> - </tr> -{% for dating in item.datings.all %} - <tr> - <td> - {{dating.period}} - </td> - <td> - {{dating.start_date|default_if_none:"-"}} - </td> - <td> - {{dating.end_date|default_if_none:"-"}} - </td> - <td> - {{dating.dating_type|default_if_none:"-"}} - </td> - <td> - {{dating.quality|default_if_none:"-"}} - </td> - <td> - {{dating.precise_dating|default_if_none:"-"}} - </td> - </tr> -{% endfor %} -</table> -{% endif %} - {% field_flex_full "Comment on dating" item.dating_comment "<pre>" "</pre>" %} -{% endif %} + <div class='row'> + {% field_flex "Denomination" item.denomination %} + {% field_flex "Free ID" item.label %} + {% field_flex "Previous ID" item.previous_id %} + {% field_flex "Excavation ID" item.excavation_ids %} + {% field_flex "Museum ID" item.museum_id %} + {% field_flex "Seal number" item.seal_number %} + {% trans "Administrative index" as admin_index_label %} + {% field_flex admin_index_label item.administrative_index %} + {% field_flex_full "Mark" item.mark "<pre>" "</pre>" %} + </div> -{% include "ishtar/blocks/sheet_json.html" %} + <h3>{% trans "Description" %}</h3> + <div class='row'> + {% field_flex_full "Description" item.description "<pre>" "</pre>" %} + {% field_flex "Is complete?" item.is_complete %} + {% field_flex_multiple "Material types" item.material_types %} + {% field_flex "Material type quality" item.material_type_quality %} + {% field_flex_multiple "Object types" item.object_types %} + {% field_flex "Object type quality" item.object_type_quality %} + {% field_flex "Find number" item.find_number %} + {% field_flex "Minimum number of individuals (MNI)" item.min_number_of_individuals %} + {% field_flex_full "Decoration" item.decoration "<pre>" "</pre>" %} + {% field_flex_full "Inscription" item.inscription "<pre>" "</pre>" %} + {% field_flex "Manufacturing place" item.manufacturing_place %} + {% field_flex_multiple "Communicability" item.communicabilities %} + {% field_flex_full "Comment" item.comment "<pre>" "</pre>" %} + </div> -{% if item.container %} -<h3>{% trans "Warehouse"%}</h3> -<div class='row'> - {% field_flex_detail "Container" item.container %} - {% field_flex "Container ID" item.container.cached_location %} - {% field_flex_detail "Responsible warehouse" item.container.responsible %} - {% field_flex_detail "Location (warehouse)" item.container.location %} - {% field_flex "Precise localisation" item.container.cached_division %} -</div> -{% endif %} + {% if item.length or item.width or item.height or item.diameter or item.thickness or item.volume or item.weight_string or item.dimensions_comment or item.clutter_long_side or item.clutter_short_side or item.clutter_height %} + <h3>{% trans "Dimensions" %}</h3> + <div class='row'> + {% field_flex "Length (cm)" item.length %} + {% field_flex "Width (cm)" item.width %} + {% field_flex "Height (cm)" item.height %} + {% field_flex "Thickness (cm)" item.thickness %} + {% field_flex "Diameter (cm)" item.diameter %} + {% field_flex "Circumference (cm)" item.circumference %} + {% field_flex "Volume (l)" item.volume %} + {% trans "Weight (g)" as weight_label %} + {% field_flex weight_label item.weight_string %} + {% field_flex "Clutter long side (cm)" item.clutter_long_side %} + {% field_flex "Clutter short side (cm)" item.clutter_short_side %} + {% field_flex "Clutter height (cm)" item.clutter_height %} + {% field_flex_full "Dimensions comment" item.dimensions_comment "<pre>" "</pre>" %} + </div> + {% endif %} -{% if item.upstream_treatment or item.downstream_treatment %} -<h3>{% trans "Treatments"%}</h3> + <h3>{% trans "Sheet" %}</h3> + <div class='row'> + {% trans "Checked" as checked_label %} + {% field_flex checked_label item.checked_type %} + {% field_flex "Check date" item.check_date %} + {% include "ishtar/blocks/sheet_creation_section.html" %} + </div> + </div> + {% if display_identification %} + <div class="tab-pane fade" id="{{window_id}}-preservation" + role="tabpanel" aria-labelledby="{{window_id}}-preservation-tab"> + {% if item.integrities.count or item.remarkabilities.count or item.conservatory_state or item.conservatory_comment or item.alterations.count or item.alteration_causes.count or item.preservation_to_considers.count or item.appraisal_date or item.treatment_emergency or item.insurance_value or item.estimated_value %} + <h3>{% trans "Preservation" %}</h3> + <div class='row'> + {% field_flex_multiple "Integrity / interest" item.integrities %} + {% field_flex_multiple "Remarkability" item.remarkabilities %} + {% field_flex "Conservatory state" item.conservatory_state %} + {% field_flex_multiple "Alteration" item.alterations %} + {% field_flex_multiple "Alteration cause" item.alteration_causes %} + {% field_flex_multiple "Recommended treatments" item.preservation_to_considers %} + {% field_flex "Treatment emergency" item.treatment_emergency %} + {% field_flex "Estimated value" item.estimated_value|default_if_none:''|intcomma '' ' '|add:CURRENCY %} + {% field_flex "Insurance value" item.insurance_value|default_if_none:''|intcomma '' ' '|add:CURRENCY %} + {% field_flex "Appraisal date" item.appraisal_date %} + {% field_flex_full "Conservatory comment" item.conservatory_comment "<pre>" "</pre>" %} + </div> + {% endif %} -{% if item.upstream_treatment %} -<h3>{% trans "Upstream treatment" %}</h3> -<table id='{{window_id}}-upstream' class="table table-striped"> - <tr> - <th> </th> - <th>{% trans "Year - index" %}</th> - <th>{% trans "Label" %}</th> - <th>{% trans "Type" %}</th> - <th>{% trans "State" %}</th> - <th>{% trans "Related finds (max. 15 displayed)" %}</th> - <th>{% trans "Doer" %}</th> - <th>{% trans "Container" %}</th> - <th>{% trans "Start date" %}</th> - <th>{% trans "End date" %}</th> - </tr> - {% for items, treatment in item.limited_upstream_treatments %} - <tr> - <td> - <a class="display_details" href="#" - onclick="load_window('{% url 'show-treatment' treatment.id %}/');"> - <i class="fa fa-info-circle" aria-hidden="true"></i> - </a> - </td> - <td class='string'>{{ treatment.year }} - {{treatment.index}}</td> - <td class='string'>{{ treatment.label|default_if_none:"-" }}</td> - <td class='string'>{{ treatment.treatment_types_lbl }}</td> - <td class='string'>{{ treatment.treatment_state|default_if_none:"-" }}</td> - <td class='item-list'>{% for item in items %}<span>{{item}} {{ item|link_to_window}}</span>{% endfor %}</td> - <td class='string'>{{ treatment.person|default_if_none:"-" }}</td> - <td class='string'>{{ treatment.container|default_if_none:"-" }}</td> - <td class='string'>{{ treatment.start_date|default_if_none:"-" }}</td> - <td class='string'>{{ treatment.end_date|default_if_none:"-" }}</td> - </tr> - {% endfor %} -</table> -<p class='tool'><a class='badge' href="{% url 'get-upstreamtreatment' 'csv' %}?submited=1&find_id={{item.pk}}" target="_blank" title='{% trans "Export as CSV"%}'>{% trans "CSV" %}</a> ({{ENCODING}})</p> -{% endif %} + {% if item.datings.count or item.dating_comment %} + <h3>{% trans "Dating" %}</h3> + {% if item.datings.count %} + <table id='{{window_id}}-datings' class="table table-striped"> + <tr> + <th>{% trans "Period" %}</th> + <th>{% trans "Start date" %}</th> + <th>{% trans "End date" %}</th> + <th>{% trans "Dating type" %}</th> + <th>{% trans "Quality" %}</th> + <th>{% trans "Precise dating" %}</th> + </tr> + {% for dating in item.datings.all %} + <tr> + <td> + {{dating.period}} + </td> + <td> + {{dating.start_date|default_if_none:"-"}} + </td> + <td> + {{dating.end_date|default_if_none:"-"}} + </td> + <td> + {{dating.dating_type|default_if_none:"-"}} + </td> + <td> + {{dating.quality|default_if_none:"-"}} + </td> + <td> + {{dating.precise_dating|default_if_none:"-"}} + </td> + </tr> + {% endfor %} + </table> + {% endif %} + {% field_flex_full "Comment on dating" item.dating_comment "<pre>" "</pre>" %} + {% endif %} + </div> + {% endif %} + {% if display_warehouse_treatments %} + <div class="tab-pane fade" id="{{window_id}}-warehouse" + role="tabpanel" aria-labelledby="{{window_id}}-warehouse-tab"> + {% if item.container_ref %} + <h3>{% trans "Warehouse - reference container"%}</h3> + <div class='row'> + {% field_flex_detail "Container" item.container_ref %} + {% field_flex "Container ID" item.container_ref.cached_location %} + {% field_flex_detail "Responsible warehouse" item.container_ref.responsible %} + {% field_flex_detail "Location (warehouse)" item.container_ref.location %} + {% field_flex "Precise localisation" item.container_ref.cached_division %} + </div> + {% endif %} + {% if item.container and item.container_ref.pk != item.container.pk %} + <h3>{% trans "Warehouse - current container"%}</h3> + <div class='row'> + {% field_flex_detail "Container" item.container %} + {% field_flex "Container ID" item.container.cached_location %} + {% field_flex_detail "Responsible warehouse" item.container.responsible %} + {% field_flex_detail "Location (warehouse)" item.container.location %} + {% field_flex "Precise localisation" item.container.cached_division %} + </div> + {% endif %} + {% if item.upstream_treatment or item.downstream_treatment or item.treatments.count %} + {% if item.treatments.all %} + <h3>{% trans "Treatments"%}</h3> + <table id='{{window_id}}-treatments' class="table table-striped"> + <tr> + <th> </th> + <th>{% trans "Year - index" %}</th> + <th>{% trans "Label" %}</th> + <th>{% trans "Type" %}</th> + <th>{% trans "State" %}</th> + <th>{% trans "Related finds (max. 15 displayed)" %}</th> + <th>{% trans "Doer" %}</th> + <th>{% trans "Container" %}</th> + <th>{% trans "Start date" %}</th> + <th>{% trans "End date" %}</th> + </tr> + {% for treatment in item.treatments.all %} + <tr> + <td> + <a class="display_details" href="#" + onclick="load_window('{% url 'show-treatment' treatment.id %}/');"> + <i class="fa fa-info-circle" aria-hidden="true"></i> + </a> + </td> + <td class='string'>{{ treatment.year }} - {{treatment.index}}</td> + <td class='string'>{{ treatment.label|default_if_none:"-" }}</td> + <td class='string'>{{ treatment.treatment_types_lbl }}</td> + <td class='string'>{{ treatment.treatment_state|default_if_none:"-" }}</td> + <td class='item-list'>{% for it in treatment.limited_finds %}<span>{{it}} {{it|link_to_window}}</span>{% endfor %}</td> + <td class='string'>{{ treatment.person|default_if_none:"-" }}</td> + <td class='string'>{{ treatment.container|default_if_none:"-" }}</td> + <td class='string'>{{ treatment.start_date|default_if_none:"-" }}</td> + <td class='string'>{{ treatment.end_date|default_if_none:"-" }}</td> + </tr> + {% endfor %} + </table> + {% endif %} -{% if item.downstream_treatment %} -<h3>{% trans "Downstream treatment" %}</h3> -<table id='{{window_id}}-downstream' class="table table-striped"> - <tr> - <th> </th> - <th>{% trans "Year - index" %}</th> - <th>{% trans "Label" %}</th> - <th>{% trans "Type" %}</th> - <th>{% trans "State" %}</th> - <th>{% trans "Related finds (max. 15 displayed)" %}</th> - <th>{% trans "Doer" %}</th> - <th>{% trans "Container" %}</th> - <th>{% trans "Start date" %}</th> - <th>{% trans "End date" %}</th> - </tr> - {% for items, treatment in item.limited_downstream_treatments %} - <tr> - <td> - <a class="display_details" href="#" - onclick="load_window('{% url 'show-treatment' treatment.id %}/');"> - <i class="fa fa-info-circle" aria-hidden="true"></i> - </a> - </td> - <td class='string'>{{ treatment.year }} - {{treatment.index}}</td> - <td class='string'>{{ treatment.label|default_if_none:"-" }}</td> - <td class='string'>{{ treatment.treatment_types_lbl }}</td> - <td class='string'>{{ treatment.treatment_state|default_if_none:"-" }}</td> - <td class='item-list'>{% for item in items %}<span>{{item}} {{ item|link_to_window}}</span>{% endfor %}</td> - <td class='string'>{{ treatment.person|default_if_none:"" }}</td> - <td class='string'>{{ treatment.container|default_if_none:"-" }}</td> - <td class='string'>{{ treatment.start_date|default_if_none:"" }}</td> - <td class='string'>{{ treatment.end_date|default_if_none:"" }}</td> - </tr> - {% endfor %} -</table> + {% if item.upstream_treatment %} + <h3>{% trans "Upstream treatment" %}</h3> + <table id='{{window_id}}-upstream' class="table table-striped"> + <tr> + <th> </th> + <th>{% trans "Year - index" %}</th> + <th>{% trans "Label" %}</th> + <th>{% trans "Type" %}</th> + <th>{% trans "State" %}</th> + <th>{% trans "Related finds (max. 15 displayed)" %}</th> + <th>{% trans "Doer" %}</th> + <th>{% trans "Container" %}</th> + <th>{% trans "Start date" %}</th> + <th>{% trans "End date" %}</th> + </tr> + {% for items, treatment in item.limited_upstream_treatments %} + <tr> + <td> + <a class="display_details" href="#" + onclick="load_window('{% url 'show-treatment' treatment.id %}/');"> + <i class="fa fa-info-circle" aria-hidden="true"></i> + </a> + </td> + <td class='string'>{{ treatment.year }} - {{treatment.index}}</td> + <td class='string'>{{ treatment.label|default_if_none:"-" }}</td> + <td class='string'>{{ treatment.treatment_types_lbl }}</td> + <td class='string'>{{ treatment.treatment_state|default_if_none:"-" }}</td> + <td class='item-list'>{% for it in items %}<span>{{it}} {{it|link_to_window}}</span>{% endfor %}</td> + <td class='string'>{{ treatment.person|default_if_none:"-" }}</td> + <td class='string'>{{ treatment.container|default_if_none:"-" }}</td> + <td class='string'>{{ treatment.start_date|default_if_none:"-" }}</td> + <td class='string'>{{ treatment.end_date|default_if_none:"-" }}</td> + </tr> + {% endfor %} + </table> + <p class='tool'><a class='badge' href="{% url 'get-upstreamtreatment' 'csv' %}?submited=1&find_id={{item.pk}}" target="_blank" title='{% trans "Export as CSV"%}'>{% trans "CSV" %}</a> ({{ENCODING}})</p> + {% endif %} -<p class='tool'><a class='badge' href="{% url 'get-downstreamtreatment' 'csv' %}?submited=1&find_id={{item.pk}}" target="_blank">{% trans "CSV" %}</a> ({{ENCODING}})</p> -{% endif %} + {% if item.downstream_treatment %} + <h3>{% trans "Downstream treatment" %}</h3> + <table id='{{window_id}}-downstream' class="table table-striped"> + <tr> + <th> </th> + <th>{% trans "Year - index" %}</th> + <th>{% trans "Label" %}</th> + <th>{% trans "Type" %}</th> + <th>{% trans "State" %}</th> + <th>{% trans "Related finds (max. 15 displayed)" %}</th> + <th>{% trans "Doer" %}</th> + <th>{% trans "Container" %}</th> + <th>{% trans "Start date" %}</th> + <th>{% trans "End date" %}</th> + </tr> + {% for items, treatment in item.limited_downstream_treatments %} + <tr> + <td> + <a class="display_details" href="#" + onclick="load_window('{% url 'show-treatment' treatment.id %}/');"> + <i class="fa fa-info-circle" aria-hidden="true"></i> + </a> + </td> + <td class='string'>{{ treatment.year }} - {{treatment.index}}</td> + <td class='string'>{{ treatment.label|default_if_none:"-" }}</td> + <td class='string'>{{ treatment.treatment_types_lbl }}</td> + <td class='string'>{{ treatment.treatment_state|default_if_none:"-" }}</td> + <td class='item-list'>{% for it in items %}<span>{{it}} {{ it|link_to_window}}</span>{% endfor %}</td> + <td class='string'>{{ treatment.person|default_if_none:"" }}</td> + <td class='string'>{{ treatment.container|default_if_none:"-" }}</td> + <td class='string'>{{ treatment.start_date|default_if_none:"" }}</td> + <td class='string'>{{ treatment.end_date|default_if_none:"" }}</td> + </tr> + {% endfor %} + </table> -{% endif %} + <p class='tool'><a class='badge' href="{% url 'get-downstreamtreatment' 'csv' %}?submited=1&find_id={{item.pk}}" target="_blank">{% trans "CSV" %}</a> ({{ENCODING}})</p> + {% endif %} + {% endif %} + </div> + {% endif %} + {% if display_documents %} + <div class="tab-pane fade" id="{{window_id}}-documents" + role="tabpanel" aria-labelledby="{{window_id}}-documents-tab"> + {% trans "Associated documents" as finds_docs %} + {% dynamic_table_document finds_docs 'documents' 'finds' item.pk '' output %} + </div> + {% endif %} + {% if item.data %} + <div class="tab-pane fade" id="{{window_id}}-json" + role="tabpanel" aria-labelledby="{{window_id}}-json-tab"> + {% include "ishtar/blocks/sheet_json.html" %} + </div> + {% endif %} +</div> -{% trans "Associated documents" as finds_docs %} -{% if item.documents.count %} -{% dynamic_table_document finds_docs 'documents' 'finds' item.pk '' output %} -{% endif %} +{% endwith %}{% endwith %}{% endwith %}{% endwith %}{% endwith %}{% endwith %} {% endblock %} + diff --git a/archaeological_finds/templates/ishtar/sheet_findbasket.html b/archaeological_finds/templates/ishtar/sheet_findbasket.html index 3c3ca1d3f..4a101d8f2 100644 --- a/archaeological_finds/templates/ishtar/sheet_findbasket.html +++ b/archaeological_finds/templates/ishtar/sheet_findbasket.html @@ -12,8 +12,9 @@ <div class='row'> {% field_flex "Label" item.label %} {% field_flex_detail "Owned by" item.user.person %} - {% field_flex_multiple "Shared_with" item.shared_with %} {% field_flex "Comment" item.comment %} + {% field_flex_multiple_full "Shared (read) with" item.shared_with %} + {% field_flex_multiple_full "Shared (read/edit) with" item.shared_write_with %} </div> <h3>{% trans "Content" %}</h3> diff --git a/archaeological_finds/templates/ishtar/sheet_treatment.html b/archaeological_finds/templates/ishtar/sheet_treatment.html index 1a3bb931f..78460d002 100644 --- a/archaeological_finds/templates/ishtar/sheet_treatment.html +++ b/archaeological_finds/templates/ishtar/sheet_treatment.html @@ -1,7 +1,7 @@ {% extends "ishtar/sheet.html" %} {% load i18n window_field from_dict link_to_window window_tables window_ope_tables window_header humanize %} -{% block head_title %}<strong>{% trans "Treatment" %}</strong> - {{ item.label|default:"" }}{% endblock %} +{% block head_title %}<strong>{% trans "Treatment" %}</strong> - {{ item|default:"" }}{% endblock %} {% block toolbar %} {% window_nav item window_id 'show-treatment' 'treatment_modify' 'show-historized-treatment' 'revert-treatment' previous next 1 %} @@ -9,73 +9,130 @@ {% block content %} -<div class="row"> - <div class="offset-lg-4 col-lg-4 offset-md-3 col-md-6 offset-sm-1 col-sm-10 col-12"> - <div class="card"> - {% include "ishtar/blocks/window_image.html" %} - <div class="card-body"> - <p class="card-text"> - <p class="window-refs">{{ item.label|default:"" }}</p> - {% if item.other_reference %} - <p class="window-refs">{{ item.other_reference }}</p>{% endif %} - <p class="window-refs">{{ item.year }} - {{ item.index }}</p> - {% if item.external_id %} - <p class="window-refs">{{ item.external_id }}</p>{% endif %} - {% if item.end_date %} - <p class="window-refs">{% trans "Closed" context "Treatment" %} ({{item.end_date}})</p> - {% else %} - <p class="window-refs">{% trans "Active" context "Treatment" %}</p> - {% endif %} - </p> +<ul class="nav nav-tabs" id="{{window_id}}-tabs" role="tablist"> + <li class="nav-item"> + <a class="nav-link active" id="{{window_id}}-treatment-tab" + data-toggle="tab" href="#{{window_id}}-treatment" role="tab" + aria-controls="{{window_id}}-treatment" aria-selected="true"> + {% trans "Treatment" %} + </a> + </li> + <li class="nav-item"> + <a class="nav-link" id="{{window_id}}-find-tab" + data-toggle="tab" href="#{{window_id}}-find" role="tab" + aria-controls="{{window_id}}-find" aria-selected="true"> + {% trans "Finds" %} + </a> + </li> + {% if item.documents.count %} + <li class="nav-item"> + <a class="nav-link" id="{{window_id}}-documents-tab" + data-toggle="tab" href="#{{window_id}}-documents" role="tab" + aria-controls="{{window_id}}-documents" aria-selected="true"> + {% trans "Documents" %} + </a> + </li> + {% endif %} + {% if item.administrative_act.count %} + <li class="nav-item"> + <a class="nav-link" id="{{window_id}}-admin-tab" + data-toggle="tab" href="#{{window_id}}-admin" role="tab" + aria-controls="{{window_id}}-admin" aria-selected="true"> + {% trans "Administrative acts" %} + </a> + </li> + {% endif %} +</ul> + +<div class="tab-content" id="{{window_id}}-tab-content"> + <div class="tab-pane fade show active" id="{{window_id}}-treatment" + role="tabpanel" aria-labelledby="{{window_id}}-treatment-tab"> + <div class="row"> + <div class="offset-lg-4 col-lg-4 offset-md-3 col-md-6 offset-sm-1 col-sm-10 col-12"> + <div class="card"> + {% include "ishtar/blocks/window_image.html" %} + <div class="card-body"> + <p class="card-text"> + <p class="window-refs">{{ item.label|default:"" }}</p> + {% if item.other_reference %} + <p class="window-refs">{{ item.other_reference }}</p>{% endif %} + <p class="window-refs">{{ item.year }} - {{ item.index }}</p> + {% if item.external_id %} + <p class="window-refs">{{ item.external_id }}</p>{% endif %} + {% if item.end_date %} + <p class="window-refs">{% trans "Closed" context "Treatment" %} ({{item.end_date}})</p> + {% else %} + <p class="window-refs">{% trans "Active" context "Treatment" %}</p> + {% endif %} + </p> + </div> + </div> </div> </div> + + <div class="row"> + {% field_flex_multiple "Treatment type" item.treatment_types %} + {% field_flex "State" item.treatment_state %} + {% field_flex_detail "Associated request" item.file %} + {% field_flex "Location" item.location %} + {% field_flex "Container" item.container %} + {% field_flex "Responsible" item.person %} + {% field_flex "Organization" item.organization %} + {% field_flex "Start date" item.start_date %} + {% field_flex "Closing date" item.end_date %} + {% field_flex "Estimated cost" item.estimated_cost|intcomma '' " "|add:CURRENCY %} + {% field_flex "Quoted cost" item.quoted_cost|intcomma '' " "|add:CURRENCY %} + {% field_flex "Realized cost" item.realized_cost|intcomma '' " "|add:CURRENCY %} + {% field_flex "Insurance cost" item.insurance_cost|intcomma '' " "|add:CURRENCY %} + {% field_flex_full "Comment" item.comment "<pre>" "</pre>" %} + {% field_flex_full "Description" item.description "<pre>" "</pre>" %} + {% field_flex_full "Goal" item.goal "<pre>" "</pre>" %} + + {% include "ishtar/blocks/sheet_json.html" %} + </div> </div> -</div> -<div class="row"> - {% field_flex_multiple "Treatment type" item.treatment_types %} - {% field_flex "State" item.treatment_state %} - {% field_flex_detail "Associated request" item.file %} - {% field_flex "Location" item.location %} - {% field_flex "Container" item.container %} - {% field_flex "Responsible" item.person %} - {% field_flex "Organization" item.organization %} - {% field_flex "Start date" item.start_date %} - {% field_flex "Closing date" item.end_date %} - {% field_flex "Estimated cost" item.estimated_cost|intcomma '' " "|add:CURRENCY %} - {% field_flex "Quoted cost" item.quoted_cost|intcomma '' " "|add:CURRENCY %} - {% field_flex "Realized cost" item.realized_cost|intcomma '' " "|add:CURRENCY %} - {% field_flex "Insurance cost" item.insurance_cost|intcomma '' " "|add:CURRENCY %} - {% field_flex_full "Comment" item.comment "<pre>" "</pre>" %} - {% field_flex_full "Description" item.description "<pre>" "</pre>" %} - {% field_flex_full "Goal" item.goal "<pre>" "</pre>" %} - - {% include "ishtar/blocks/sheet_json.html" %} -</div> + <div class="tab-pane fade" id="{{window_id}}-find" + role="tabpanel" aria-labelledby="{{window_id}}-find-tab"> + {% trans "Related finds" as finds %} + {% if item.finds.count %} + {% dynamic_table_document finds 'finds_for_treatment' 'treatments' item.pk 'TABLE_COLS_FOR_OPE' output %} + {% endif %} -{% trans "Upstream finds" as finds %} -{% if item.upstream.count %} -{% dynamic_table_document finds 'finds_for_treatment' 'downstream_treatment' item.pk 'TABLE_COLS_FOR_OPE' output %} -{% endif %} + {% trans "Upstream finds" as finds %} + {% if item.upstream.count %} + {% dynamic_table_document finds 'finds_for_treatment' 'downstream_treatment' item.pk 'TABLE_COLS_FOR_OPE' output %} + {% endif %} -{% trans "Downstream finds" as finds %} -{% if item.downstream.count %} -{% dynamic_table_document finds 'finds_for_treatment' 'upstream_treatment' item.pk 'TABLE_COLS_FOR_OPE' output %} -{% endif %} + {% trans "Downstream finds" as finds %} + {% if item.downstream.count %} + {% dynamic_table_document finds 'finds_for_treatment' 'upstream_treatment' item.pk 'TABLE_COLS_FOR_OPE' output %} + {% endif %} -{% trans "Related operations" as related_operations %} -{% dynamic_table_document related_operations 'operations' 'related_treatment' item.pk 'TABLE_COLS' output %} + {% comment %} + {% trans "Related operations" as related_operations %} + {% dynamic_table_document related_operations 'operations' 'related_treatment' item.pk 'TABLE_COLS' output %} + {% endcomment %} -{% comment %} -{% if item.source.count %} -{% trans "Associated documents" as associated_docs %} -{% dynamic_table_document associated_docs 'treatments_docs' 'treatment' item.pk '' output %} -{% endif %} -{% endcomment %} -{% if item.administrative_act.count %} -{% trans "Administrative acts" as admact_lbl %} -{% table_administrativact admact_lbl item.administrative_act.all %} -{% endif %} + </div> + {% if item.documents.count %} + <div class="tab-pane fade" id="{{window_id}}-documents" + role="tabpanel" aria-labelledby="{{window_id}}-documents-tab"> + {% trans "Associated documents" as treat_docs %} + {% dynamic_table_document treat_docs 'documents' 'treatments' item.pk '' output %} + </div> + {% endif %} + + {% if item.administrative_act.count %} + <div class="tab-pane fade" id="{{window_id}}-admin" + role="tabpanel" aria-labelledby="{{window_id}}-admin-tab"> + {% trans "Administrative acts" as admact_lbl %} + {% table_administrativact admact_lbl item.administrative_act.all %} + </div> + {% endif %} + + +</div> {% endblock %} diff --git a/archaeological_finds/templates/ishtar/sheet_treatmentfile.html b/archaeological_finds/templates/ishtar/sheet_treatmentfile.html index 08398a6c2..072285262 100644 --- a/archaeological_finds/templates/ishtar/sheet_treatmentfile.html +++ b/archaeological_finds/templates/ishtar/sheet_treatmentfile.html @@ -34,6 +34,7 @@ <div class="row"> {% field_flex "Type" item.type %} {% field_flex_detail "Responsible" item.in_charge %} + {% field_flex_detail "Associated basket" item.associated_basket %} {% field_flex "Creation date" item.creation_date %} {% field_flex "Reception date" item.reception_date %} {% field_flex "Closing date" item.end_date %} diff --git a/archaeological_finds/templates/ishtar/wizard/wizard_findbasket_deletion.html b/archaeological_finds/templates/ishtar/wizard/wizard_findbasket_deletion.html new file mode 100644 index 000000000..ffd5f0398 --- /dev/null +++ b/archaeological_finds/templates/ishtar/wizard/wizard_findbasket_deletion.html @@ -0,0 +1,25 @@ +{% extends "ishtar/wizard/confirm_wizard.html" %} +{% load i18n link_to_window %} + +{% block "warning_message" %} +{% if current_object.treatment_files.count %} +<div class="alert alert-{% if has_downstream %}danger{% else %}warning{% endif%}"> + <i class="fa fa-exclamation-triangle" aria-hidden="true"></i> + {% trans "This basket is attached to treatments requests:" %} + <ul>{% for tf in current_object.treatment_files.all %} + <li>{{ tf }} {{tf|link_to_window}}</li> + {% endfor %}</ul> + {% trans "Are you sure you want to delete this basket?" %} +</div> +{% endif %} +<div class="alert alert-info"> + {% trans "Items inside the basket (these items will not be deleted):" %} +</div> +<ul>{% for item in current_object.items.all %} + <li>{{item}} {{item|link_to_window}}</li> +{% endfor %}</ul> + +<div class="alert alert-info"> + {% trans "Basket informations:" %} +</div> +{% endblock %} diff --git a/archaeological_finds/templates/ishtar/wizard/wizard_simplefind.html b/archaeological_finds/templates/ishtar/wizard/wizard_simplefind.html new file mode 100644 index 000000000..b1d77ba81 --- /dev/null +++ b/archaeological_finds/templates/ishtar/wizard/wizard_simplefind.html @@ -0,0 +1,13 @@ +{% extends "ishtar/wizard/default_wizard.html" %} +{% load i18n %} +{% block form_head %} +<div class="alert alert-warning"> + <i class="fa fa-exclamation-triangle"></i> + {% trans 'This find is related to many base finds. To edit field related to base finds edit the corresponding find between theses:' %} + <ul>{% for base_find in wizard.form.base_finds %} + {% with find=base_find.get_main_find %}<li> + {{find.short_label }} + <a href="{% url 'find_modify' find.pk %}"><i class="fa fa-pencil"></i></a> + </li>{% endwith %}{% endfor %}</ul> +</div> +{% endblock %} diff --git a/archaeological_finds/templates/ishtar/wizard/wizard_treatement_deletion.html b/archaeological_finds/templates/ishtar/wizard/wizard_treatement_deletion.html new file mode 100644 index 000000000..be46bfd05 --- /dev/null +++ b/archaeological_finds/templates/ishtar/wizard/wizard_treatement_deletion.html @@ -0,0 +1,27 @@ +{% extends "ishtar/wizard/confirm_wizard.html" %} +{% load i18n link_to_window %} + +{% block "warning_message" %} +{% with has_downstream=current_object.downstream.count %} +<div class="alert alert-{% if has_downstream %}danger{% else %}warning{% endif%}"> + <i class="fa fa-exclamation-triangle" aria-hidden="true"></i> + {% trans "Are you sure you want to delete this treatment?" %} +{% if has_downstream %} + {% trans "The following finds will be deleted and restored to a previous version."%} + <ul>{% for item in current_object.downstream.all %} + <li> + {{item}} {{item|link_to_window}} + </li> + {% endfor %}</ul> + {% trans "All changes made to the associated finds since this treatment record will be lost!" %} +{% endif %} +</div> + +<div class="alert alert-info"> + {% trans "Treatment informations:" %} +</div> + + + +{% endwith %} +{% endblock %} diff --git a/archaeological_finds/tests.py b/archaeological_finds/tests.py index a55e075b7..ae03b2ba4 100644 --- a/archaeological_finds/tests.py +++ b/archaeological_finds/tests.py @@ -215,8 +215,7 @@ class TreatmentWizardCreationTest(WizardTest, FindInit, TestCase): 'treatment_type': None, 'person': 1, # doer 'location': 1, # associated warehouse - 'year': 2016, - 'target_is_basket': False + 'year': 2016 }, 'selecfind': { 'pk': 1, @@ -243,6 +242,13 @@ class TreatmentWizardCreationTest(WizardTest, FindInit, TestCase): trt_type = models.TreatmentType.objects.get(txt_idx='moving') self.form_datas[0].set('basetreatment', 'treatment_type', trt_type.pk) + completed, created = models.TreatmentState.objects.get_or_create( + txt_idx='completed', defaults={"executed": True, "label": u"Done"} + ) + completed.executed = True + completed.save() + + self.form_datas[0].set('basetreatment', 'treatment_state', completed.pk) self.find, base_find = self.get_default_find(force=True) self.form_datas[0].form_datas['selecfind'][ @@ -258,9 +264,10 @@ class TreatmentWizardCreationTest(WizardTest, FindInit, TestCase): treat = models.Treatment.objects.order_by('-pk').all()[0] self.find = models.Find.objects.get(pk=self.find.pk) self.assertEqual(models.Find.objects.filter( - upstream_treatment=treat).count(), 1) - self.assertEqual(self.find.downstream_treatment, - treat) + treatments=treat).count(), 1) + # TODO: test treatment with new find creation + # self.assertEqual(self.find.downstream_treatment, + # treat) class ImportFindTest(ImportTest, TestCase): @@ -796,7 +803,8 @@ class FindQATest(FindInit, TestCase): reverse('find-qa-bulk-update-confirm', args=[pks]), {'qa_period': period, 'qa_description': extra_desc} ) - self.assertRedirects(response, '/success/') + if response.status_code != 200: + self.assertRedirects(response, '/success/') self.assertIn(period, [dating.period.pk for dating in find_0.datings.all()]) self.assertIn(period, @@ -807,7 +815,7 @@ class FindQATest(FindInit, TestCase): base_desc_1 + u"\n" + extra_desc) -class PackagingTest(FindInit, TestCase): +class TreatmentTest(FindInit, TestCase): fixtures = FIND_FIXTURES model = models.Find @@ -832,18 +840,33 @@ class PackagingTest(FindInit, TestCase): self.basket.items.add(find) self.other_basket.items.add(find) - def testPackaging(self): + def test_packaging_with_new_find_creation(self): treatment_type = models.TreatmentType.objects.get(txt_idx='packaging') + # make packaging a treatment with a new version of the find created + treatment_type.create_new_find = True + treatment_type.save() + treatment = models.Treatment() items_nb = models.Find.objects.count() first_find = self.finds[0] - treatment.save(user=self.get_default_user(), items=self.basket) + completed, created = models.TreatmentState.objects.get_or_create( + txt_idx='completed', defaults={"executed": True, "label": u"Done"} + ) + completed.executed = True + completed.save() + + treatment.treatment_state = completed + treatment.save( + user=self.get_default_user(), items=self.basket, + treatment_type_list=[treatment_type], + ) + treatment.treatment_types.add(treatment_type) + self.assertEqual(items_nb + self.basket.items.count(), models.Find.objects.count(), msg="Packaging doesn't generate enough new finds") - treatment.treatment_types.add(treatment_type) resulting_find = models.Find.objects.get( upstream_treatment__upstream=first_find, @@ -866,15 +889,69 @@ class PackagingTest(FindInit, TestCase): item, self.finds, msg="Other basket have not been upgraded after packaging") - def test_delete(self): - # manage treatment deletion + def test_simple_delete(self): treatment_type = models.TreatmentType.objects.get(txt_idx='packaging') + treatment_type.create_new_find = False + treatment_type.save() + + nb_find = models.Find.objects.count() + treatment = models.Treatment() initial_find = self.finds[0] - treatment.save(user=self.get_default_user(), items=self.basket) + completed, created = models.TreatmentState.objects.get_or_create( + txt_idx='completed', defaults={"executed": True, "label": u"Done"} + ) + completed.executed = True + completed.save() + + treatment.treatment_state = completed + treatment.save( + user=self.get_default_user(), items=self.basket, + treatment_type_list=[treatment_type], + ) treatment.treatment_types.add(treatment_type) + self.assertEqual(nb_find, models.Find.objects.count()) + + treatment.delete() + self.assertEqual( + models.Treatment.objects.filter(pk=treatment.pk).count(), 0) + + q = models.Find.objects.filter(pk=initial_find.pk) + # initial find not deleted + self.assertEqual(q.count(), 1) + initial_find = q.all()[0] + self.assertEqual(initial_find.upstream_treatment, None) + + def test_upstream_find_delete(self): + treatment_type = models.TreatmentType.objects.get(txt_idx='packaging') + # make packaging a treatment with a new version of the find created + treatment_type.create_new_find = True + treatment_type.save() + + nb_find = models.Find.objects.count() + + treatment = models.Treatment() + + initial_find = self.finds[0] + completed, created = models.TreatmentState.objects.get_or_create( + txt_idx='completed', defaults={"executed": True, "label": u"Done"} + ) + completed.executed = True + completed.save() + + treatment.treatment_state = completed + treatment.save( + user=self.get_default_user(), items=self.basket, + treatment_type_list=[treatment_type], + ) + treatment.treatment_types.add(treatment_type) + + nb_b = self.basket.items.count() + self.assertEqual( + nb_find + nb_b, models.Find.objects.count()) + resulting_find = models.Find.objects.get( upstream_treatment__upstream=initial_find, base_finds__pk=initial_find.base_finds.all()[0].pk @@ -888,3 +965,42 @@ class PackagingTest(FindInit, TestCase): self.assertEqual(q.count(), 1) initial_find = q.all()[0] self.assertEqual(initial_find.upstream_treatment, None) + + def test_treatment_delete(self): + treatment_type = models.TreatmentType.objects.get(txt_idx='packaging') + treatment_type.create_new_find = True + treatment_type.save() + + nb_find = models.Find.objects.count() + + treatment = models.Treatment() + + initial_find = self.finds[0] + completed, created = models.TreatmentState.objects.get_or_create( + txt_idx='completed', defaults={"executed": True, "label": u"Done"} + ) + completed.executed = True + completed.save() + + treatment.treatment_state = completed + treatment.save( + user=self.get_default_user(), items=self.basket, + treatment_type_list=[treatment_type], + ) + treatment.treatment_types.add(treatment_type) + + nb_b = self.basket.items.count() + self.assertEqual( + nb_find + nb_b, models.Find.objects.count()) + + treatment.delete() + + self.assertEqual(nb_find, models.Find.objects.count()) + + self.assertEqual( + models.Treatment.objects.filter(pk=treatment.pk).count(), 0) + q = models.Find.objects.filter(pk=initial_find.pk) + # initial find not deleted + self.assertEqual(q.count(), 1) + initial_find = q.all()[0] + self.assertEqual(initial_find.upstream_treatment, None) diff --git a/archaeological_finds/urls.py b/archaeological_finds/urls.py index 588c8d520..fe7b2acd2 100644 --- a/archaeological_finds/urls.py +++ b/archaeological_finds/urls.py @@ -45,6 +45,8 @@ urlpatterns = [ views.find_modify, name='find_modify'), url(r'get-findbasket/$', views.get_find_basket, name='get-findbasket'), + url(r'get-findbasket-write/$', views.get_find_basket_for_write, + name='get-findbasket-write'), url(r'find_basket_search/(?P<step>.+)?$', check_rights(['view_find', 'view_own_find'])( views.basket_search_wizard), name='find_basket_search'), @@ -78,9 +80,36 @@ urlpatterns = [ check_rights(['view_find', 'view_own_find'])( views.FindBasketListView.as_view()), name='list_iteminbasket'), - url(r'^find_basket_deletion/$', + url(r'^find_basket_deletion/(?P<step>.+)?$', check_rights(['view_find', 'view_own_find'])( - views.DeleteFindBasketView.as_view()), name='delete_findbasket'), + views.basket_delete_wizard), + name='find_basket_deletion'), + url(r'^findbasket-qa-duplicate/(?P<pks>[0-9-]+)?/$', + check_rights(['view_find', 'view_own_find'])( + views.QAFindbasketDuplicateFormView.as_view()), + name='findbasket-qa-duplicate'), + + url(r'^findbasket-add-treatment/(?P<pk>[0-9-]+)/$', + check_rights(['change_find', 'change_own_find'])( + views.findbasket_treatment_add), + name='findbasket-add-treatment'), + url(r'^find-add-treatment/(?P<pk>[0-9-]+)/$', + check_rights(['change_find', 'change_own_find'])( + views.find_treatment_add), + name='find-add-treatment'), + url(r'^treatmentfile-add-treatment/(?P<pk>[0-9-]+)/$', + check_rights(['change_find', 'change_own_find'])( + views.treatmentfile_treatment_add), + name='treatmentfile-add-treatment'), + url(r'^treatment-add-adminact/(?P<pk>[0-9-]+)/$', + check_rights(['add_administrativeact'])( + views.treatment_adminact_add), + name='treatment-add-adminact'), + + url(r'^treatmentfile-add-adminact/(?P<pk>[0-9-]+)/$', + check_rights(['add_administrativeact'])( + views.treatmentfile_adminact_add), + name='treatmentfile-add-adminact'), url(r'^find-qa-bulk-update/(?P<pks>[0-9-]+)?/$', check_rights(['change_find', 'change_own_find'])( @@ -100,10 +129,16 @@ urlpatterns = [ views.QAFindTreatmentFormView.as_view()), name='find-qa-packaging'), - url(r'^treatment_creation/(?P<step>.+)?$', check_rights(['change_find', 'change_own_find'])( views.treatment_creation_wizard), name='treatment_creation'), + url(r'^treatment_creation_n1/(?P<step>.+)?$', + check_rights(['change_find', 'change_own_find'])( + views.treatment_creation_n1_wizard), name='treatment_creation_n1'), + url(r'^treatment_creation_1n/(?P<step>.+)?$', + check_rights(['change_find', 'change_own_find'])( + views.treatment_creation_1n_wizard), name='treatment_creation_1n'), + url(r'^treatment_modification/(?P<step>.+)?$', check_rights(['change_find', 'change_own_find'])( views.treatment_modification_wizard), @@ -248,6 +283,10 @@ urlpatterns = [ administrativeactfile_document, name='treatmentfle-administrativeact-document', kwargs={'treatment_file': True}), + url(r'autocomplete-findbasket/$', + check_rights(['change_find', 'change_own_find'])( + views.autocomplete_findbasket), + name='autocomplete-findbasket'), ] urlpatterns += get_urls_for_model(models.Find, views, own=True, diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py index c340639c5..fb5cdc11e 100644 --- a/archaeological_finds/views.py +++ b/archaeological_finds/views.py @@ -19,6 +19,7 @@ import json +from django.core.exceptions import PermissionDenied from django.core.urlresolvers import reverse from django.db.models import Q from django.http import HttpResponseRedirect, HttpResponse, Http404 @@ -27,18 +28,24 @@ from django.utils.translation import ugettext_lazy as _ from django.views.generic import TemplateView from django.views.generic.edit import CreateView, FormView + +from ishtar_common.models import IshtarUser, get_current_profile +from archaeological_operations.models import AdministrativeAct +from archaeological_finds import models + +from ishtar_common.forms import FinalForm from archaeological_context_records.forms \ import RecordFormSelection as RecordFormSelectionTable from archaeological_operations.forms import FinalAdministrativeActDeleteForm -from archaeological_operations.wizards import AdministrativeActDeletionWizard -from forms import * -from ishtar_common.forms import FinalForm -from ishtar_common.models import IshtarUser, get_current_profile +from archaeological_finds import forms + from ishtar_common.views import get_autocomplete_generic, IshtarMixin, \ LoginRequiredMixin, QAItemEditForm, QAItemForm from ishtar_common.views_item import display_item, get_item, show_item, \ - revert_item, get_autocomplete_item -from wizards import * + revert_item, get_autocomplete_item, get_autocomplete_query + +from archaeological_operations.wizards import AdministrativeActDeletionWizard +from archaeological_finds import wizards get_find = get_item(models.Find, 'get_find', 'find') @@ -105,30 +112,66 @@ def autocomplete_treatmentfile(request): return HttpResponse(data, content_type='text/plain') -show_find = show_item(models.Find, 'find') +def show_find_extra(request, find): + if not request.user or not request.user.ishtaruser: + return {} + user = request.user.ishtaruser + q = models.FindBasket.objects.filter(items__pk=find.pk).filter( + Q(user=user) | Q(shared_with__pk=user.pk) | + Q(shared_write_with__pk=user.pk) + ) + return {"baskets": [(basket.pk, basket.full_label) for basket in q.all()]} + + +show_find = show_item(models.Find, 'find', extra_dct=show_find_extra) display_find = display_item(models.Find) revert_find = revert_item(models.Find) -show_findbasket = show_item(models.FindBasket, 'findbasket') +show_findbasket = show_item(models.FindBasket, 'findbasket', + model_for_perms=models.Find) display_findbasket = display_item(models.FindBasket, show_url='show-find/basket-') + +def autocomplete_findbasket(request, current_right=None): + if not request.GET.get('term'): + return HttpResponse(content_type='text/plain') + + query = get_autocomplete_query(request, ['label']) + limit = 20 + query = query & models.FindBasket.get_write_query_owns( + request.user.ishtaruser) + items = models.FindBasket.objects.filter(query).order_by('label')[:limit] + data = json.dumps( + [{'id': item.pk, + 'value': u"{} - {}".format(item.label, item.user)[:60]} + for item in items] + ) + return HttpResponse(data, content_type='text/plain') + get_find_basket = get_item( models.FindBasket, 'get_findbasket', 'findbasket', + model_for_perms=models.Find ) -basket_search_wizard = FindBasketSearch.as_view( - [('selec-find_basket_search', FindBasketFormSelection)], +get_find_basket_for_write = get_item( + models.FindBasket, 'get_findbasket', 'findbasket', + model_for_perms=models.Find, alt_query_own='get_write_query_owns' +) + +basket_search_wizard = wizards.FindBasketSearch.as_view( + [('selec-find_basket_search', forms.FindBasketFormSelection)], label=_(u"Basket search"), url_name='find_basket_search', ) -basket_modify_wizard = FindBasketEditWizard.as_view( +basket_modify_wizard = wizards.FindBasketEditWizard.as_view( [ - ('selec-find_basket_modification', FindBasketFormSelection), - ('basket-find_basket_modification', FindBasketForm), + ('selec-find_basket_modification', + forms.FindBasketForWriteFormSelection), + ('basket-find_basket_modification', forms.FindBasketForm), ('final-find_basket_modification', FinalForm) - ], + ], label=_(u"Basket modify"), url_name='find_basket_modification', ) @@ -137,13 +180,26 @@ basket_modify_wizard = FindBasketEditWizard.as_view( def find_basket_modify(request, pk): basket_modify_wizard(request) key = 'selec-find_basket_modification' - FindBasketEditWizard.session_set_value( + wizards.FindBasketEditWizard.session_set_value( request, key, 'pk', pk, reset=True) return redirect( reverse('find_basket_modification', kwargs={'step': 'basket-find_basket_modification'})) +findbasket_deletion_steps = [ + ('selec-find_basket_deletion', forms.FindBasketForWriteFormSelection), + ('final-find_basket_deletion', FinalForm) +] + + +basket_delete_wizard = wizards.FindBasketDeletionWizard.as_view( + findbasket_deletion_steps, + label=_(u"Basket deletion"), + url_name='find_basket_deletion', +) + + def check_preservation_module(self): return get_current_profile().preservation @@ -158,9 +214,9 @@ def check_not_warehouse_module(self): find_creation_steps = [ ('selecrecord-find_creation', RecordFormSelectionTable), - ('find-find_creation', FindForm), - ('preservation-find_creation', PreservationForm), - ('dating-find_creation', DatingFormSet), + ('find-find_creation', forms.FindForm), + ('preservation-find_creation', forms.PreservationForm), + ('dating-find_creation', forms.DatingFormSet), ('final-find_creation', FinalForm) ] @@ -168,7 +224,7 @@ find_creation_condition_dict = { 'preservation-find_creation': check_preservation_module, } -find_creation_wizard = FindWizard.as_view( +find_creation_wizard = wizards.FindWizard.as_view( find_creation_steps, label=_(u"New find"), condition_dict=find_creation_condition_dict, @@ -179,31 +235,47 @@ find_search_condition_dict = { 'generalwarehouse-find_search': check_warehouse_module, } -find_search_wizard = FindSearch.as_view([ - ('general-find_search', FindFormSelection), - ('generalwarehouse-find_search', FindFormSelectionWarehouseModule)], +find_search_wizard = wizards.FindSearch.as_view([ + ('general-find_search', forms.FindFormSelection), + ('generalwarehouse-find_search', forms.FindFormSelectionWarehouseModule)], label=_(u"Find search"), url_name='find_search', condition_dict=find_search_condition_dict ) + +def has_many_base_find(wizard): + find = wizard.get_current_object() + if not find: + return False + return find.base_finds.count() > 1 + + +def has_only_one_base_find(wizard): + return not has_many_base_find(wizard) + + find_modification_condition_dict = { 'selec-find_modification': check_not_warehouse_module, 'selecw-find_modification': check_warehouse_module, 'preservation-find_modification': check_preservation_module, + 'selecrecord-find_modification': has_only_one_base_find, + 'find-find_modification': has_only_one_base_find, + 'simplefind-find_modification': has_many_base_find, } find_modification_steps = [ - ('selec-find_modification', FindFormSelection), - ('selecw-find_modification', FindFormSelectionWarehouseModule), - ('selecrecord-find_modification', RecordFormSelection), - ('find-find_modification', FindForm), - ('preservation-find_modification', PreservationForm), - ('dating-find_modification', DatingFormSet), + ('selec-find_modification', forms.FindFormSelection), + ('selecw-find_modification', forms.FindFormSelectionWarehouseModule), + ('selecrecord-find_modification', forms.RecordFormSelection), + ('find-find_modification', forms.FindForm), + ('simplefind-find_modification', forms.SimpleFindForm), + ('preservation-find_modification', forms.PreservationForm), + ('dating-find_modification', forms.DatingFormSet), ('final-find_modification', FinalForm) ] -find_modification_wizard = FindModificationWizard.as_view( +find_modification_wizard = wizards.FindModificationWizard.as_view( find_modification_steps, condition_dict=find_modification_condition_dict, label=_(u"Find modification"), @@ -216,11 +288,18 @@ def find_modify(request, pk): key = 'selec-find_modification' if get_current_profile().warehouse: key = 'selecw-find_modification' - FindModificationWizard.session_set_value( + wizards.FindModificationWizard.session_set_value( request, key, 'pk', pk, reset=True) + q = models.Find.objects.filter(pk=pk) + if not q.count(): + raise Http404() + step = 'find-find_modification' + find = q.all()[0] + if find.base_finds.count() > 1: + step = 'simplefind-find_modification' + return redirect( - reverse('find_modification', - kwargs={'step': 'selecrecord-find_modification'})) + reverse('find_modification', kwargs={'step': step})) find_deletion_condition_dict = { 'selec-find_deletion': check_not_warehouse_module, @@ -228,11 +307,11 @@ find_deletion_condition_dict = { } find_deletion_steps = [ - ('selec-find_deletion', FindFormSelection), - ('selecw-find_deletion', FindFormSelectionWarehouseModule), - ('final-find_deletion', FindDeletionForm)] + ('selec-find_deletion', forms.FindFormSelection), + ('selecw-find_deletion', forms.FindFormSelectionWarehouseModule), + ('final-find_deletion', forms.FindDeletionForm)] -find_deletion_wizard = FindDeletionWizard.as_view( +find_deletion_wizard = wizards.FindDeletionWizard.as_view( find_deletion_steps, condition_dict=find_deletion_condition_dict, label=_(u"Find deletion"), @@ -247,7 +326,7 @@ autocomplete_integritytype = get_autocomplete_generic(models.IntegrityType) class NewFindBasketView(IshtarMixin, LoginRequiredMixin, CreateView): template_name = 'ishtar/form.html' model = models.FindBasket - form_class = NewFindBasketForm + form_class = forms.NewFindBasketForm page_name = _(u"New basket") def get_form_kwargs(self): @@ -268,15 +347,15 @@ class OwnBasket(object): def get_basket(self, user, pk): try: return models.FindBasket.objects.filter( - Q(user=user) | Q(shared_with=user) - ).get(pk=pk) + Q(user=user) | Q(shared_with=user) | Q(shared_write_with=user) + ).distinct().get(pk=pk) except models.FindBasket.DoesNotExist: raise PermissionDenied class SelectBasketForManagement(IshtarMixin, LoginRequiredMixin, FormView): template_name = 'ishtar/form.html' - form_class = SelectFindBasketForm + form_class = forms.SelectFindBasketForm page_name = _(u"Manage items in basket") def get_form_kwargs(self): @@ -309,9 +388,9 @@ class SelectItemsInBasket(OwnBasket, IshtarMixin, LoginRequiredMixin, ) context['basket'] = self.basket if get_current_profile().warehouse: - context['form'] = MultipleFindFormSelectionWarehouseModule() + context['form'] = forms.MultipleFindFormSelectionWarehouseModule() else: - context['form'] = MultipleFindFormSelection() + context['form'] = forms.MultipleFindFormSelection() context['add_url'] = reverse('add_iteminbasket') context['list_url'] = reverse('list_iteminbasket', kwargs={'pk': self.basket.pk}) @@ -323,7 +402,7 @@ class SelectItemsInBasket(OwnBasket, IshtarMixin, LoginRequiredMixin, class FindBasketAddItemView(IshtarMixin, LoginRequiredMixin, FormView): template_name = 'ishtar/simple_form.html' - form_class = FindBasketAddItemForm + form_class = forms.FindBasketAddItemForm def get_success_url(self, basket): return reverse('list_iteminbasket', kwargs={'pk': basket.pk}) @@ -381,22 +460,6 @@ class FindBasketDeleteItemView(OwnBasket, IshtarMixin, LoginRequiredMixin, basket.items.remove(find) return HttpResponseRedirect(self.get_success_url(basket)) - -class DeleteFindBasketView(IshtarMixin, LoginRequiredMixin, FormView): - template_name = 'ishtar/form_delete.html' - form_class = DeleteFindBasketForm - success_url = '/' - page_name = _(u"Delete basket") - - def get_form_kwargs(self): - kwargs = super(DeleteFindBasketView, self).get_form_kwargs() - kwargs['user'] = IshtarUser.objects.get(pk=self.request.user.pk) - return kwargs - - def form_valid(self, form): - form.save() - return HttpResponseRedirect(self.get_success_url()) - get_upstreamtreatment = get_item( models.FindUpstreamTreatments, 'get_upstreamtreatment', 'uptreatment') @@ -405,46 +468,53 @@ get_downstreamtreatment = get_item( 'downtreatment') treatment_wizard_steps = [ - ('file-treatment_creation', TreatmentFormFileChoice), - ('basetreatment-treatment_creation', BaseTreatmentForm), - ('selecfind-treatment_creation', UpstreamFindFormSelection), - ('selecbasket-treatment_creation', SelectFindBasketForm), - # ('resultfind-treatment_creation', ResultFindForm), - # ('resultfinds-treatment_creation', ResultFindFormSet), + ('selecfind-treatment_creation', forms.UpstreamFindFormSelection), + ('file-treatment_creation', forms.TreatmentFormFileChoice), + ('basetreatment-treatment_creation', forms.BaseTreatmentForm), ('final-treatment_creation', FinalForm) ] -treatment_search_wizard = TreatmentSearch.as_view([ - ('general-treatment_search', TreatmentFormSelection)], +treatment_search_wizard = wizards.TreatmentSearch.as_view([ + ('general-treatment_search', forms.TreatmentFormSelection)], label=_(u"Treatment search"), url_name='treatment_search',) -treatment_creation_wizard = TreatmentWizard.as_view( +treatment_creation_wizard = wizards.TreatmentWizard.as_view( treatment_wizard_steps, - condition_dict={ - 'selecfind-treatment_creation': - check_value('basetreatment-treatment_creation', - 'target_is_basket', False), - 'selecbasket-treatment_creation': - check_value('basetreatment-treatment_creation', - 'target_is_basket', True), - # 'resultfinds-treatment_creation': - # check_type_field('basetreatment-treatment_creation', - # 'treatment_type', models.TreatmentType, - # 'downstream_is_many'), - # 'resultfind-treatment_creation': - # check_type_field('basetreatment-treatment_creation', - # 'treatment_type', models.TreatmentType, - # 'upstream_is_many') - }, label=_(u"New treatment"), url_name='treatment_creation',) -treatment_modification_wizard = TreatmentModificationWizard.as_view( - [('selec-treatment_modification', TreatmentFormSelection), - ('file-treatment_modification', TreatmentFormFileChoice), - ('basetreatment-treatment_modification', TreatmentModifyForm), +treatment_n1_wizard_steps = [ + ('selecfind-treatment_creation_n1', forms.UpstreamFindFormSelection), + ('file-treatment_creation_n1', forms.TreatmentFormFileChoice), + ('basetreatment-treatment_creation_n1', forms.N1TreatmentForm), + ('resultingfind-treatment_creation_n1', forms.ResultingFindForm), + ('final-treatment_creation_n1', FinalForm) +] + +treatment_creation_n1_wizard = wizards.TreatmentN1Wizard.as_view( + treatment_n1_wizard_steps, + label=_(u"New treatment"), + url_name='treatment_creation_n1',) + +treatment_1n_wizard_steps = [ + ('selecfind-treatment_creation_1n', forms.SingleUpstreamFindFormSelection), + ('file-treatment_creation_1n', forms.TreatmentFormFileChoice), + ('basetreatment-treatment_creation_1n', forms.OneNTreatmentForm), + ('resultingfinds-treatment_creation_1n', forms.ResultingFindsForm), + ('final-treatment_creation_1n', FinalForm) +] + +treatment_creation_1n_wizard = wizards.Treatment1NWizard.as_view( + treatment_1n_wizard_steps, + label=_(u"New treatment"), + url_name='treatment_creation_1n',) + +treatment_modification_wizard = wizards.TreatmentModificationWizard.as_view( + [('selec-treatment_modification', forms.TreatmentFormSelection), + ('file-treatment_modification', forms.TreatmentFormFileChoice), + ('basetreatment-treatment_modification', forms.TreatmentModifyForm), ('final-treatment_modification', FinalForm)], label=_(u"Treatment modification"), url_name='treatment_modification', @@ -453,41 +523,116 @@ treatment_modification_wizard = TreatmentModificationWizard.as_view( def treatment_modify(request, pk): treatment_modification_wizard(request) - TreatmentModificationWizard.session_set_value( + wizards.TreatmentModificationWizard.session_set_value( request, 'selec-treatment_modification', 'pk', pk, reset=True) return redirect(reverse( 'treatment_modification', - kwargs={'step': 'basetreatment-treatment_modification'})) - - -treatment_deletion_wizard = TreatmentDeletionWizard.as_view([ - ('selec-treatment_deletion', TreatmentFormSelection), - ('final-treatment_deletion', TreatmentDeletionForm)], + kwargs={'step': 'file-treatment_modification'})) + + +def treatment_add(request, pks, treatment_file=None): + treatment_creation_wizard(request) + wizards.TreatmentWizard.session_set_value( + request, 'selecfind-treatment_creation', + 'resulting_pk', pks, reset=True) + if treatment_file: + wizards.TreatmentWizard.session_set_value( + request, 'file-treatment_creation', 'file', treatment_file.pk) + else: + wizards.TreatmentWizard.session_set_value( + request, 'file-treatment_creation', 'file', '') + if treatment_file: + in_charge = treatment_file.in_charge + if not in_charge: + in_charge = request.user.ishtaruser.person + dct = { + "treatment_type": treatment_file.type.treatment_type.pk + if treatment_file.type and treatment_file.type.treatment_type + else "", + "year": treatment_file.year, + "person": in_charge.pk, + } + locas = list( + set([str(f.container.location.pk) + for f in treatment_file.associated_basket.items.all() + if f.container and f.container.location]) + ) + if len(locas) == 1: # one and only one location for all finds + dct["location"] = locas[0] + for k in dct: + wizards.TreatmentWizard.session_set_value( + request, 'basetreatment-treatment_creation', k, dct[k]) + return redirect(reverse( + 'treatment_creation', + kwargs={'step': 'basetreatment-treatment_creation'})) + + +def find_treatment_add(request, pk, current_right=None): + if not models.Find.objects.filter(pk=pk).count(): + raise Http404() + return treatment_add(request, str(pk)) + + +def findbasket_treatment_add(request, pk, current_right=None): + try: + basket = models.FindBasket.objects.get(pk=pk) + except models.FindBasket.DoesNotExist: + raise Http404() + return treatment_add( + request, ",".join([str(f.pk) for f in basket.items.all()])) + + +def container_treatment_add(request, pk, current_right=None): + try: + basket = models.FindBasket.objects.get(pk=pk) + except models.FindBasket.DoesNotExist: + raise Http404() + return treatment_add(request, + ",".join([str(f.pk) for f in basket.items.all()])) + + +def treatmentfile_treatment_add(request, pk, current_right=None): + try: + tf = models.TreatmentFile.objects.get(pk=pk) + except models.TreatmentFile.DoesNotExist: + raise Http404() + if not tf.associated_basket: + raise Http404() + basket = tf.associated_basket + return treatment_add( + request, ",".join([str(f.pk) for f in basket.items.all()]), + treatment_file=tf + ) + + +treatment_deletion_wizard = wizards.TreatmentDeletionWizard.as_view([ + ('selec-treatment_deletion', forms.TreatmentFormSelection), + ('final-treatment_deletion', forms.TreatmentDeletionForm)], label=_(u"Treatment deletion"), url_name='treatment_deletion',) treatment_administrativeact_search_wizard = \ - SearchWizard.as_view([ + wizards.SearchWizard.as_view([ ('selec-treatment_admacttreatment_search', - AdministrativeActTreatmentFormSelection)], + forms.AdministrativeActTreatmentFormSelection)], label=_(u"Treatment: search administrative act"), url_name='treatment_admacttreatment_search',) treatment_administrativeact_wizard = \ - TreatmentAdministrativeActWizard.as_view([ - ('selec-treatment_admacttreatment', TreatmentFormSelection), + wizards.TreatmentAdministrativeActWizard.as_view([ + ('selec-treatment_admacttreatment', forms.TreatmentFormSelection), ('administrativeact-treatment_admacttreatment', - AdministrativeActTreatmentForm), + forms.AdministrativeActTreatmentForm), ('final-treatment_admacttreatment', FinalForm)], label=_(u"Treatment: new administrative act"), url_name='treatment_admacttreatment',) treatment_administrativeact_modification_wizard = \ - TreatmentEditAdministrativeActWizard.as_view([ + wizards.TreatmentEditAdministrativeActWizard.as_view([ ('selec-treatment_admacttreatment_modification', - AdministrativeActTreatmentFormSelection), + forms.AdministrativeActTreatmentFormSelection), ('administrativeact-treatment_admacttreatment_modification', - AdministrativeActTreatmentModifForm), + forms.AdministrativeActTreatmentModifForm), ('final-treatment_admacttreatment_modification', FinalForm)], label=_(u"Treatment: administrative act modification"), url_name='treatment_admacttreatment_modification',) @@ -495,7 +640,7 @@ treatment_administrativeact_modification_wizard = \ treatment_admacttreatment_deletion_wizard = \ AdministrativeActDeletionWizard.as_view([ ('selec-treatment_admacttreatment_deletion', - AdministrativeActTreatmentFormSelection), + forms.AdministrativeActTreatmentFormSelection), ('final-treatment_admacttreatment_deletion', FinalAdministrativeActDeleteForm)], label=_(u"Treatment: administrative act deletion"), @@ -504,7 +649,7 @@ treatment_admacttreatment_deletion_wizard = \ def treatment_administrativeacttreatment_modify(request, pk): treatment_administrativeact_modification_wizard(request) - TreatmentEditAdministrativeActWizard.session_set_value( + wizards.TreatmentEditAdministrativeActWizard.session_set_value( request, 'selec-treatment_admacttreatment_modification', 'pk', pk, reset=True) @@ -517,69 +662,86 @@ def treatment_administrativeacttreatment_modify(request, pk): })) +def treatment_adminact_add(request, pk, current_right=None): + try: + models.Treatment.objects.get(pk=pk) + except models.Treatment.DoesNotExist: + raise Http404() + treatment_administrativeact_wizard(request) + + wizards.TreatmentAdministrativeActWizard.session_set_value( + request, 'selec-treatment_admacttreatment', 'pk', pk, reset=True) + return redirect(reverse( + 'treatment_admacttreatment', + kwargs={'step': 'administrativeact-treatment_admacttreatment'})) + + # treatment request -treatmentfile_search_wizard = TreatmentFileSearch.as_view([ - ('general-treatmentfile_search', TreatmentFileFormSelection)], +treatmentfile_search_wizard = wizards.TreatmentFileSearch.as_view([ + ('general-treatmentfile_search', forms.TreatmentFileFormSelection)], label=_(u"Treatment request search"), url_name='treatmentfile_search',) treatmentfile_wizard_steps = [ - ('treatmentfile-treatmentfile_creation', TreatmentFileForm), + ('treatmentfile-treatmentfile_creation', forms.TreatmentFileForm), ('final-treatmentfile_creation', FinalForm)] -treatmentfile_creation_wizard = TreatmentFileWizard.as_view( +treatmentfile_creation_wizard = wizards.TreatmentFileWizard.as_view( treatmentfile_wizard_steps, label=_(u"New treatment request"), url_name='treatmentfile_creation',) -treatmentfile_modification_wizard = TreatmentFileModificationWizard.as_view( - [('selec-treatmentfile_modification', TreatmentFileFormSelection), - ('treatmentfile-treatmentfile_modification', TreatmentFileModifyForm), - ('final-treatmentfile_modification', FinalForm)], - label=_(u"Treatment request modification"), - url_name='treatmentfile_modification', -) +treatmentfile_modification_wizard = \ + wizards.TreatmentFileModificationWizard.as_view( + [('selec-treatmentfile_modification', forms.TreatmentFileFormSelection), + ('treatmentfile-treatmentfile_modification', + forms.TreatmentFileModifyForm), + ('final-treatmentfile_modification', FinalForm)], + label=_(u"Treatment request modification"), + url_name='treatmentfile_modification', + ) def treatmentfile_modify(request, pk): treatmentfile_modification_wizard(request) - TreatmentFileModificationWizard.session_set_value( + wizards.TreatmentFileModificationWizard.session_set_value( request, 'selec-treatmentfile_modification', 'pk', pk, reset=True) return redirect(reverse( 'treatmentfile_modification', kwargs={'step': 'treatmentfile-treatmentfile_modification'})) -treatmentfile_deletion_wizard = TreatmentFileDeletionWizard.as_view([ - ('selec-treatmentfile_deletion', TreatmentFileFormSelection), - ('final-treatmentfile_deletion', TreatmentFileDeletionForm)], +treatmentfile_deletion_wizard = wizards.TreatmentFileDeletionWizard.as_view([ + ('selec-treatmentfile_deletion', forms.TreatmentFileFormSelection), + ('final-treatmentfile_deletion', forms.TreatmentFileDeletionForm)], label=_(u"Treatment request deletion"), url_name='treatmentfile_deletion',) treatmentfile_admacttreatmentfile_search_wizard = \ - SearchWizard.as_view([ + wizards.SearchWizard.as_view([ ('selec-treatmentfle_admacttreatmentfle_search', - AdministrativeActTreatmentFileFormSelection)], + forms.AdministrativeActTreatmentFileFormSelection)], label=_(u"Treatment request: search administrative act"), url_name='treatmentfle_admacttreatmentfle_search',) treatmentfile_admacttreatmentfile_wizard = \ - TreatmentFileAdministrativeActWizard.as_view([ - ('selec-treatmentfle_admacttreatmentfle', TreatmentFileFormSelection), + wizards.TreatmentFileAdministrativeActWizard.as_view([ + ('selec-treatmentfle_admacttreatmentfle', + forms.TreatmentFileFormSelection), ('admact-treatmentfle_admacttreatmentfle', - AdministrativeActTreatmentFileForm), + forms.AdministrativeActTreatmentFileForm), ('final-treatmentfle_admacttreatmentfle', FinalForm)], label=_(u"Treatment request: new administrative act"), url_name='treatmentfle_admacttreatmentfle',) treatmentfile_admacttreatmentfile_modification_wizard = \ - TreatmentFileEditAdministrativeActWizard.as_view([ + wizards.TreatmentFileEditAdministrativeActWizard.as_view([ ('selec-treatmentfle_admacttreatmentfle_modification', - AdministrativeActTreatmentFileFormSelection), + forms.AdministrativeActTreatmentFileFormSelection), ('admact-treatmentfle_admacttreatmentfle_modification', - AdministrativeActTreatmentFileModifForm), + forms.AdministrativeActTreatmentFileModifForm), ('final-treatmentfle_admacttreatmentfle_modification', FinalForm)], label=_(u"Treatment request: administrative act modification"), url_name='treatmentfle_admacttreatmentfle_modification',) @@ -587,7 +749,7 @@ treatmentfile_admacttreatmentfile_modification_wizard = \ treatmentfile_admacttreatmentfile_deletion_wizard = \ AdministrativeActDeletionWizard.as_view([ ('selec-treatmentfle_admacttreatmentfle_deletion', - AdministrativeActTreatmentFileFormSelection), + forms.AdministrativeActTreatmentFileFormSelection), ('final-treatmentfle_admacttreatmentfle_deletion', FinalAdministrativeActDeleteForm)], label=_(u"Treatment request: administrative act deletion"), @@ -596,7 +758,7 @@ treatmentfile_admacttreatmentfile_deletion_wizard = \ def treatmentfile_administrativeacttreatmentfile_modify(request, pk): treatmentfile_admacttreatmentfile_modification_wizard(request) - TreatmentFileEditAdministrativeActWizard.session_set_value( + wizards.TreatmentFileEditAdministrativeActWizard.session_set_value( request, 'selec-treatmentfle_admacttreatmentfle_modification', 'pk', pk, reset=True) @@ -609,24 +771,42 @@ def treatmentfile_administrativeacttreatmentfile_modify(request, pk): })) +def treatmentfile_adminact_add(request, pk, current_right=None): + try: + models.TreatmentFile.objects.get(pk=pk) + except models.TreatmentFile.DoesNotExist: + raise Http404() + treatmentfile_admacttreatmentfile_wizard(request) + + wizards.TreatmentFileAdministrativeActWizard.session_set_value( + request, 'selec-treatmentfle_admacttreatmentfle', 'pk', pk, reset=True) + return redirect(reverse( + 'treatmentfle_admacttreatmentfle', + kwargs={'step': 'admact-treatmentfle_admacttreatmentfle'})) + + def reset_wizards(request): for wizard_class, url_name in ( - (FindWizard, 'find_creation'), - (FindModificationWizard, 'find_modification'), - (FindDeletionWizard, 'find_deletion'), - (TreatmentWizard, 'treatement_creation'), - (TreatmentModificationWizard, 'treatment_modification'), - (TreatmentDeletionWizard, 'treatment_deletion'), - (TreatmentAdministrativeActWizard, 'treatment_admacttreatment'), - (TreatmentEditAdministrativeActWizard, + (wizards.FindWizard, 'find_creation'), + (wizards.FindModificationWizard, 'find_modification'), + (wizards.FindDeletionWizard, 'find_deletion'), + (wizards.TreatmentWizard, 'treatement_creation'), + (wizards.TreatmentModificationWizard, 'treatment_modification'), + (wizards.TreatmentDeletionWizard, 'treatment_deletion'), + (wizards.TreatmentAdministrativeActWizard, + 'treatment_admacttreatment'), + (wizards.TreatmentEditAdministrativeActWizard, 'treatment_admacttreatment_modification'), - (TreatmentDeletionWizard, 'treatment_admacttreatment_deletion'), - (TreatmentFileWizard, 'treatmentfile_creation'), - (TreatmentFileModificationWizard, 'treatmentfile_modification'), - (TreatmentFileDeletionWizard, 'treatmentfile_deletion'), - (TreatmentFileAdministrativeActWizard, + (wizards.TreatmentDeletionWizard, + 'treatment_admacttreatment_deletion'), + (wizards.TreatmentFileWizard, + 'treatmentfile_creation'), + (wizards.TreatmentFileModificationWizard, + 'treatmentfile_modification'), + (wizards.TreatmentFileDeletionWizard, 'treatmentfile_deletion'), + (wizards.TreatmentFileAdministrativeActWizard, 'treatmentfle_admacttreatmentfle'), - (TreatmentFileEditAdministrativeActWizard, + (wizards.TreatmentFileEditAdministrativeActWizard, 'treatmentfle_admacttreatmentfle_modification'), (AdministrativeActDeletionWizard, 'treatmentfle_admacttreatmentfle_deletion'), @@ -636,13 +816,13 @@ def reset_wizards(request): class QAFindForm(QAItemEditForm): model = models.Find - form_class = QAFindFormMulti + form_class = forms.QAFindFormMulti class QAFindBasketFormView(QAItemForm): template_name = 'ishtar/forms/qa_find_basket.html' model = models.Find - form_class = QAFindBasketForm + form_class = forms.QAFindBasketForm page_name = _(u"Basket") modal_size = "small" @@ -662,7 +842,7 @@ class QAFindBasketFormView(QAItemForm): class QAFindTreatmentFormView(QAItemForm): template_name = 'ishtar/forms/qa_find_treatment.html' model = models.Find - form_class = QAFindTreatmentForm + form_class = forms.QAFindTreatmentForm page_name = _(u"Packaging") def get_quick_action(self): @@ -677,3 +857,29 @@ class QAFindTreatmentFormView(QAItemForm): def form_valid(self, form): form.save(self.items, self.request.user) return HttpResponseRedirect(reverse("success")) + + +class QAFindbasketDuplicateFormView(QAItemForm): + template_name = 'ishtar/forms/qa_findbasket_duplicate.html' + model = models.FindBasket + page_name = _(u"Duplicate") + modal_size = "small" + form_class = forms.QAFindbasketDuplicateForm + + def get_quick_action(self): + return models.FindBasket.QUICK_ACTIONS[0] + + def get_form_kwargs(self): + kwargs = super(QAFindbasketDuplicateFormView, self).get_form_kwargs() + kwargs['user'] = self.request.user + return kwargs + + def form_valid(self, form): + form.save() + return HttpResponseRedirect(reverse("success")) + + def get_context_data(self, **kwargs): + data = super(QAFindbasketDuplicateFormView, self).get_context_data( + **kwargs) + data['action_name'] = _(u"Duplicate") + return data diff --git a/archaeological_finds/wizards.py b/archaeological_finds/wizards.py index 0e0fe80e1..7f4e1b498 100644 --- a/archaeological_finds/wizards.py +++ b/archaeological_finds/wizards.py @@ -17,8 +17,9 @@ # See the file COPYING for details. +from django.contrib import messages from django.core.exceptions import ObjectDoesNotExist, PermissionDenied -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import ugettext_lazy as _, pgettext from ishtar_common.forms import reverse_lazy from ishtar_common.wizards import Wizard, DeletionWizard, SearchWizard @@ -55,11 +56,21 @@ class FindWizard(Wizard): if base_finds: return base_finds[0].context_record + def get_current_basefinds(self): + find = self.get_current_object() + if not find: + return [] + return find.base_finds.all() + def get_form_kwargs(self, step=None): kwargs = super(FindWizard, self).get_form_kwargs(step) - if step not in ('find-find_creation', 'find-find_modification'): + if step not in ( + 'find-find_creation', 'find-find_modification', + 'simplefind-find_modification',): return kwargs kwargs['context_record'] = self.get_current_contextrecord() + if step == 'simplefind-find_modification': + kwargs['base_finds'] = self.get_current_basefinds() return kwargs def get_context_data(self, form, **kwargs): @@ -75,8 +86,8 @@ class FindWizard(Wizard): (_(u"Context record"), unicode(current_cr))) return context - def get_extra_model(self, dct, form_list): - dct = super(FindWizard, self).get_extra_model(dct, form_list) + def get_extra_model(self, dct, m2m, form_list): + dct = super(FindWizard, self).get_extra_model(dct, m2m, form_list) dct['order'] = 1 if 'pk' in dct and type(dct['pk']) == ContextRecord: dct['base_finds__context_record'] = dct.pop('pk') @@ -90,6 +101,10 @@ class FindModificationWizard(FindWizard): 'selec-find_modification': ['pk'], 'selecw-find_modification': ['pk'], } + wizard_templates = { + 'simplefind-find_modification': + 'ishtar/wizard/wizard_simplefind.html', + } class FindDeletionWizard(DeletionWizard): @@ -106,11 +121,59 @@ class TreatmentSearch(SearchWizard): model = models.Treatment -class TreatmentWizard(Wizard): +class TreatmentBase(Wizard): model = models.Treatment wizard_done_window = reverse_lazy('show-treatment') + base_url = "" + saved_args = {"treatment_type_list": []} + + def get_current_finds(self): + step = self.steps.current + if not step: + return + find_form_key = 'selecfind-' + self.base_url + find_ids = self.session_get_value(find_form_key, "resulting_pk") + try: + return [ + models.Find.objects.get(pk=int(find_id.strip())) + for find_id in find_ids.split(u',') + ] + except(TypeError, ValueError, AttributeError, ObjectDoesNotExist): + pass + + def get_form_initial(self, step, data=None): + initial = super(TreatmentBase, self).get_form_initial(step) + base_step = 'basetreatment-' + self.base_url + if step != base_step: + return initial + finds = self.get_current_finds() + if not finds: + return initial + locations = [find.container.location.pk for find in finds + if find.container] + # no location or multiple locations + if not locations or len(set(locations)) != 1: + return initial + if not initial: + initial = {} + initial['location'] = locations[0] + return initial + + def get_extra_model(self, dct, m2m, form_list): + dct = super(TreatmentBase, self).get_extra_model(dct, m2m, form_list) + dct['treatment_type_list'] = [] + for k, v in m2m: + if k == 'treatment_type': + if type(v) not in (list, tuple): + v = [v] + dct['treatment_type_list'] += v + return dct + + +class TreatmentWizard(TreatmentBase): basket_step = 'basetreatment-treatment_creation' - saved_args = {"items": []} + saved_args = {"items": [], "treatment_type_list": []} + base_url = 'treatment_creation' def get_form_kwargs(self, step, **kwargs): kwargs = super(TreatmentWizard, self).get_form_kwargs(step, **kwargs) @@ -119,25 +182,31 @@ class TreatmentWizard(Wizard): kwargs['user'] = self.request.user return kwargs - def get_extra_model(self, dct, form_list): + def get_extra_model(self, dct, m2m, form_list): """ Get items concerned by the treatment """ - dct = super(TreatmentWizard, self).get_extra_model(dct, form_list) + dct = super(TreatmentWizard, self).get_extra_model(dct, m2m, form_list) if 'resulting_pk' in dct: - try: - find = models.Find.objects.get(pk=dct.pop('resulting_pk')) - if 'own' in self.current_right \ - and not find.is_own(dct['history_modifier']): + dct['items'] = [] + pks = dct.pop('resulting_pk').split(u',') + for pk in pks: + try: + find = models.Find.objects.get(pk=pk) + dct['items'].append(find) + except models.Find.DoesNotExist: raise PermissionDenied - dct['items'] = [find] - except models.Find.DoesNotExist: - raise PermissionDenied if 'basket' in dct: basket = dct.pop('basket') if basket.user.pk != dct['history_modifier'].pk: raise PermissionDenied dct['items'] = list(basket.items.all()) + + if 'items' in dct: + for find in dct['items']: + if 'own' in self.current_right \ + and not find.is_own(dct['history_modifier']): + raise PermissionDenied return dct @@ -145,7 +214,196 @@ class TreatmentModificationWizard(TreatmentWizard): modification = True +class TreatmentN1Wizard(TreatmentBase): + saved_args = {"upstream_items": [], "resulting_find": None, + "treatment_type_list": []} + base_url = 'treatment_creation_n1' + + def _update_simple_initial_from_finds(self, initial, find, k): + r_k = "resulting_" + k + if getattr(find, k) and r_k in initial: + # pop k when value is inconsistent between finds + if initial[r_k] and initial[r_k] != getattr(find, k).pk: + initial.pop(r_k) + else: + initial[r_k] = getattr(find, k).pk + return initial + + def _update_multi_initial_from_finds(self, initial, find, k): + r_k = "resulting_" + k + for value in getattr(find, k + 's').all(): + if value.pk not in initial[r_k]: + initial[r_k].append(value.pk) + return initial + + def _update_num_initial_from_finds(self, initial, find, k): + r_k = "resulting_" + k + if not getattr(find, k): + return initial + if initial[r_k] is None: + initial[r_k] = 0 + initial[r_k] += getattr(find, k) + return initial + + def _update_char_initial_from_finds(self, initial, find, k, sep=' ; '): + r_k = "resulting_" + k + value = getattr(find, k) + if not value: + return initial + value = value.strip() + if not initial[r_k]: + initial[r_k] = value + else: + # new value is entirely inside the current value + if value == initial[r_k] or (value + sep) in initial[r_k] or \ + (sep + value) in initial[r_k]: + return initial + initial[r_k] += sep + value + return initial + + def get_form_initial(self, step, data=None): + initial = super(TreatmentN1Wizard, self).get_form_initial(step) + if step != 'resultingfind-treatment_creation_n1': + return initial + finds = self.get_current_finds() + if not finds: + return initial + simple_key = ['material_type_quality'] + multi_key = ['material_type', 'object_type', 'communicabilitie'] + numeric_key = ['find_number', 'min_number_of_individuals'] + desc_key = ['decoration', 'inscription', 'comment', 'dating_comment'] + char_key = ['manufacturing_place'] + + for k in simple_key + numeric_key + desc_key + char_key: + initial["resulting_" + k] = None + for k in multi_key: + initial["resulting_" + k] = [] + + for find in finds: + for k in simple_key: + initial = self._update_simple_initial_from_finds( + initial, find, k) + for k in multi_key: + initial = self._update_multi_initial_from_finds( + initial, find, k) + for k in numeric_key: + initial = self._update_num_initial_from_finds( + initial, find, k) + for k in char_key: + initial = self._update_char_initial_from_finds( + initial, find, k, sep=' ; ') + for k in desc_key: + initial = self._update_char_initial_from_finds( + initial, find, k, sep='\n') + + for k in initial.keys(): + if initial[k] is None: + initial.pop(k) + return initial + + def get_extra_model(self, dct, m2m, form_list): + """ + Get items concerned by the treatment + """ + dct = super(TreatmentN1Wizard, self).get_extra_model( + dct, m2m, form_list) + if 'resulting_pk' not in dct: + return dct + + dct['upstream_items'] = [] + # manage upstream items + pks = dct.pop('resulting_pk') + if hasattr(pks, 'split'): + pks = pks.split(u',') # unicode or string + for pk in pks: + try: + find = models.Find.objects.get(pk=pk) + dct['upstream_items'].append(find) + except models.Find.DoesNotExist: + raise PermissionDenied + + for find in dct['upstream_items']: + if 'own' in self.current_right \ + and not find.is_own(dct['history_modifier']): + raise PermissionDenied + + # extract data of the new find + dct['resulting_find'] = {} + for k in dct.keys(): + if k.startswith('resulting_') and k != "resulting_find": + dct['resulting_find'][ + k[len('resulting_'):] + ] = dct.pop(k) + return dct + + +class Treatment1NWizard(TreatmentBase): + saved_args = {"upstream_item": None, "resulting_finds": None, + "treatment_type_list": []} + base_url = 'treatment_creation_1n' + + def get_form_kwargs(self, step, **kwargs): + kwargs = super(Treatment1NWizard, self).get_form_kwargs(step, **kwargs) + if step != 'resultingfind-treatment_creation_1n': + return kwargs + kwargs['user'] = self.request.user + return kwargs + + def get_form_initial(self, step, data=None): + initial = super(Treatment1NWizard, self).get_form_initial(step) + if step != 'resultingfinds-treatment_creation_1n': + return initial + finds = self.get_current_finds() + if not finds: + return initial + lbl = finds[0].label + initial['resultings_basket_name'] = unicode(_(u"Basket")) + u" - " + lbl + initial['resultings_label'] = lbl + u"-" + return initial + + def get_extra_model(self, dct, m2m, form_list): + """ + Get items concerned by the treatment + """ + dct = super(Treatment1NWizard, self).get_extra_model( + dct, m2m, form_list) + if 'resulting_pk' not in dct: + return dct + + # manage upstream item + pk = dct.pop('resulting_pk') + try: + find = models.Find.objects.get(pk=pk) + dct['upstream_item'] = find + except models.Find.DoesNotExist: + raise PermissionDenied + + if 'own' in self.current_right \ + and not find.is_own(dct['history_modifier']): + raise PermissionDenied + + # extract attributes to generate the new find + dct['resulting_finds'] = {} + for k in dct.keys(): + if k.startswith('resultings_'): + dct['resulting_finds'][ + k[len('resultings_'):] + ] = dct.pop(k) + messages.add_message( + self.request, messages.INFO, + unicode(_(u"The new basket: \"{}\" have been created with the " + u"resulting items. This search have been pinned.") + ).format(dct["resulting_finds"]["basket_name"]) + ) + self.request.session["pin-search-find"] = u'{}="{}"'.format( + unicode(pgettext("key for text search", u"basket")), + dct["resulting_finds"]["basket_name"]) + self.request.session['find'] = '' + return dct + + class TreatmentDeletionWizard(DeletionWizard): + wizard_confirm = 'ishtar/wizard/wizard_treatement_deletion.html' model = models.Treatment fields = ['label', 'other_reference', 'year', 'index', 'treatment_types', 'location', 'person', 'organization', @@ -243,3 +501,9 @@ class FindBasketWizard(Wizard): class FindBasketEditWizard(FindBasketWizard): edit = True + alt_is_own_method = 'get_write_query_owns' + + +class FindBasketDeletionWizard(DeletionWizard): + wizard_confirm = 'ishtar/wizard/wizard_findbasket_deletion.html' + model = models.FindBasket |
