diff options
Diffstat (limited to 'archaeological_finds')
| -rw-r--r-- | archaeological_finds/forms.py | 278 | ||||
| -rw-r--r-- | archaeological_finds/forms_treatments.py | 87 | ||||
| -rw-r--r-- | archaeological_finds/ishtar_menu.py | 25 | ||||
| -rw-r--r-- | archaeological_finds/locale/django.pot | 947 | ||||
| -rw-r--r-- | archaeological_finds/migrations/0035_auto_20181017_1642.py | 72 | ||||
| -rw-r--r-- | archaeological_finds/migrations/0036_auto_20181017_1854.py | 60 | ||||
| -rw-r--r-- | archaeological_finds/migrations/0037_auto_20181018_1756.py | 41 | ||||
| -rw-r--r-- | archaeological_finds/models_finds.py | 135 | ||||
| -rw-r--r-- | archaeological_finds/templates/ishtar/forms/qa_find_basket.html | 69 | ||||
| -rw-r--r-- | archaeological_finds/templates/ishtar/forms/qa_find_treatment.html | 63 | ||||
| -rw-r--r-- | archaeological_finds/templates/ishtar/sheet_find.html | 7 | ||||
| -rw-r--r-- | archaeological_finds/templates/ishtar/sheet_findbasket.html | 23 | ||||
| -rw-r--r-- | archaeological_finds/tests.py | 66 | ||||
| -rw-r--r-- | archaeological_finds/urls.py | 47 | ||||
| -rw-r--r-- | archaeological_finds/views.py | 129 | ||||
| -rw-r--r-- | archaeological_finds/wizards.py | 13 |
16 files changed, 1552 insertions, 510 deletions
diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py index fbcc32013..5ca8618d5 100644 --- a/archaeological_finds/forms.py +++ b/archaeological_finds/forms.py @@ -26,12 +26,13 @@ import logging from django import forms from django.core import validators from django.core.exceptions import PermissionDenied +from django.db.models import Q from django.forms.formsets import formset_factory from django.utils.translation import ugettext_lazy as _ import models from archaeological_context_records.models import DatingType, DatingQuality, \ - ContextRecord, RelationType as CRRelationType + ContextRecord, RelationType as CRRelationType, Dating from archaeological_finds.forms_treatments import TreatmentSelect, \ TreatmentFormSelection, BaseTreatmentForm, TreatmentModifyForm, \ AdministrativeActTreatmentForm, TreatmentFormFileChoice, \ @@ -43,7 +44,7 @@ from archaeological_finds.forms_treatments import TreatmentSelect, \ AdministrativeActTreatmentFileFormSelection, \ AdministrativeActTreatmentFileModifForm, \ DashboardForm as DashboardTreatmentForm, \ - DashboardTreatmentFileForm + DashboardTreatmentFileForm, QAFindTreatmentForm from archaeological_operations.models import Period, ArchaeologicalSite, \ RelationType as OpeRelationType from archaeological_operations.widgets import OAWidget @@ -52,7 +53,7 @@ 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 + ManageOldType, FieldType, IshtarForm, FormHeader, QAForm, HistorySelect from ishtar_common.forms_common import get_town_field from ishtar_common.models import valid_id, valid_ids, get_current_profile, \ SpatialReferenceSystem, Area, OperationType @@ -71,7 +72,7 @@ __all__ = [ 'AdministrativeActTreatmentFileModifForm', 'DashboardTreatmentForm', 'DashboardTreatmentFileForm', 'RecordFormSelection', 'FindForm', 'DateForm', 'DatingFormSet', - 'PreservationForm', + 'PreservationForm', 'FindBasketFormSelection', 'FindBasketForm', 'FindSelect', 'FindFormSelection', 'FindFormSelectionWarehouseModule', 'MultipleFindFormSelection', 'MultipleFindFormSelectionWarehouseModule', 'FindMultipleFormSelection', 'check_form', 'check_exist', 'check_not_exist', @@ -79,6 +80,8 @@ __all__ = [ 'check_treatment', 'ResultFindForm', 'ResultFindFormSet', 'FindDeletionForm', 'UpstreamFindFormSelection', 'NewFindBasketForm', 'SelectFindBasketForm', 'DeleteFindBasketForm', 'FindBasketAddItemForm', + 'QAFindFormSingle', 'QAFindFormMulti', 'QAFindBasketForm', + 'QAFindTreatmentForm' ] logger = logging.getLogger(__name__) @@ -207,24 +210,24 @@ class FindForm(CustomForm, ManageOldType): dimensions_comment = forms.CharField( label=_(u"Dimensions comment"), required=False, widget=forms.Textarea) - HEADERS['get_first_base_find__topographic_localisation'] = FormHeader( + HEADERS['get_first_base_find__x'] = FormHeader( _(u"Coordinates")) - get_first_base_find__topographic_localisation = forms.CharField( - label=_(u"Point of topographic reference"), - required=False, max_length=120 - ) get_first_base_find__x = forms.FloatField(label=_(u"X"), required=False) - get_first_base_find__y = forms.FloatField(label=_(u"Y"), required=False) - get_first_base_find__z = forms.FloatField(label=_(u"Z"), required=False) - get_first_base_find__spatial_reference_system = \ - forms.ChoiceField(label=_(u"Spatial Reference System"), required=False, - choices=[]) get_first_base_find__estimated_error_x = \ forms.FloatField(label=_(u"Estimated error for X"), required=False) + get_first_base_find__y = forms.FloatField(label=_(u"Y"), required=False) get_first_base_find__estimated_error_y = \ forms.FloatField(label=_(u"Estimated error for Y"), required=False) + get_first_base_find__z = forms.FloatField(label=_(u"Z"), required=False) get_first_base_find__estimated_error_z = \ forms.FloatField(label=_(u"Estimated error for Z"), required=False) + get_first_base_find__spatial_reference_system = \ + forms.ChoiceField(label=_(u"Spatial Reference System"), required=False, + choices=[]) + get_first_base_find__topographic_localisation = forms.CharField( + label=_(u"Point of topographic reference"), + required=False, max_length=120 + ) HEADERS['checked_type'] = FormHeader(_(u"Sheet")) checked_type = forms.ChoiceField(label=_(u"Check"), required=False) @@ -315,20 +318,197 @@ class FindForm(CustomForm, ManageOldType): return self.cleaned_data +class QAFindFormMulti(QAForm): + form_admin_name = _(u"Find - Quick action - Modify") + form_slug = "find-quickaction-modify" + base_models = ['get_first_base_find', 'qa_object_types', + 'qa_material_types', 'qa_communicabilities'] + associated_models = { + 'qa_material_types': models.MaterialType, + 'qa_object_types': models.ObjectType, + 'qa_communicabilities': models.CommunicabilityType, + 'qa_checked_type': models.CheckedType, + 'qa_period': Period + } + + MULTI = True + REPLACE_FIELDS = [ + 'qa_ue', 'qa_manufacturing_place', 'qa_checked_type', 'qa_check_date' + ] + + HEADERS = { + 'qa_ue': FormHeader(_(u"Context record")), + 'qa_label': 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_get_first_base_find__excavation_id', 'qa_museum_id', + 'qa_seal_number', 'qa_mark' + ] + qa_ue = forms.IntegerField( + label=_(u"Context record"), + widget=widgets.JQueryAutoComplete( + reverse_lazy('autocomplete-contextrecord'), + associated_model=ContextRecord), + validators=[valid_id(ContextRecord)], required=False) + + qa_label = forms.CharField( + label=_(u"Free ID"), + validators=[validators.MaxLengthValidator(60)], required=False) + qa_denomination = forms.CharField(label=_(u"Denomination"), required=False) + qa_previous_id = forms.CharField(label=_("Previous ID"), required=False) + qa_get_first_base_find__excavation_id = forms.CharField( + label=_(u"Excavation ID"), required=False) + qa_museum_id = forms.CharField(label=_(u"Museum ID"), required=False) + qa_seal_number = forms.CharField(label=_(u"Seal number"), required=False) + qa_mark = forms.CharField(label=_(u"Mark"), required=False) + + qa_description = forms.CharField( + label=_(u"Description"), widget=forms.Textarea, required=False) + qa_material_types = widgets.Select2MultipleField( + label=_(u"Material types"), required=False + ) + qa_object_types = widgets.Select2MultipleField( + label=_(u"Object types"), required=False, + ) + qa_manufacturing_place = forms.CharField( + label=_(u"Manufacturing place"), required=False) + qa_communicabilities = widgets.Select2MultipleField( + label=_(u"Communicability"), required=False + ) + qa_comment = forms.CharField( + label=_(u"Comment"), required=False, + widget=forms.Textarea) + + qa_checked_type = forms.ChoiceField(label=_(u"Check"), required=False) + qa_check_date = forms.DateField( + label=_(u"Check date"), widget=DatePicker, required=False) + + qa_period = widgets.Select2MultipleField( + label=_("Period"), choices=[], required=False) + qa_dating_comment = forms.CharField( + label=_(u"Comment on dating"), required=False, + widget=forms.Textarea) + + TYPES = [ + FieldType('qa_material_types', models.MaterialType, is_multiple=True), + FieldType('qa_object_types', models.ObjectType, is_multiple=True), + FieldType('qa_communicabilities', models.CommunicabilityType, + is_multiple=True), + FieldType('qa_checked_type', models.CheckedType), + FieldType('qa_period', Period, is_multiple=True), + ] + + def _get_qa_ue(self, value): + try: + value = ContextRecord.objects.get(pk=value).cached_label + except ContextRecord.DoesNotExist: + return "" + return value + + def _set_qa_ue(self, item, user): + ue = self.cleaned_data['qa_ue'] + if not ue: + return + cr = ContextRecord.objects.get(pk=ue) + bf = item.get_first_base_find() + bf.context_record = cr + bf.history_modifier = user + bf.save() + + def _set_qa_period(self, item, user): + periods = self.cleaned_data['qa_period'] + if not periods: + return + for period in periods: + if Dating.objects.filter(find=item, period__pk=period).count(): + continue + d = Dating.objects.create(period_id=period) + item.datings.add(d) + + +class QAFindFormSingle(QAFindFormMulti): + MULTI = False + form_admin_name = _(u"Find - Quick action - Modify single") + form_slug = "find-quickaction-modifysingle" + + def __init__(self, *args, **kwargs): + super(QAFindFormSingle, self).__init__(*args, **kwargs) + if not self.items or \ + not self.items[0].get_first_base_find( + ).context_record.operation.operation_type.judiciary: + self.fields.pop('qa_seal_number') + + +class QAFindBasketForm(IshtarForm): + create_or_update = forms.ChoiceField( + choices=(('create', _(u"Create")), + ('update', _(u"Update"))), initial='create') + label = forms.CharField(label="", max_length=None, required=False) + basket = forms.ChoiceField(label=_(u"Basket"), required=False, choices=[]) + + def __init__(self, *args, **kwargs): + self.user = None + if 'user' in kwargs: + self.user = kwargs.pop('user') + if hasattr(self.user, 'ishtaruser'): + self.user = self.user.ishtaruser + self.items = kwargs.pop('items') + + super(QAFindBasketForm, self).__init__(*args, **kwargs) + if not self.user: + return + self.fields['basket'].choices = [ + (b.pk, unicode(b)) + for b in models.FindBasket.objects.filter(user=self.user) + ] + + def clean(self): + if self.cleaned_data['create_or_update'] == 'update': + if not self.cleaned_data['basket']: + raise forms.ValidationError( + _(u"On update, you have to select a basket.")) + return self.cleaned_data + 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, items): + if self.cleaned_data['create_or_update'] == 'update': + basket = models.FindBasket.objects.get( + user=self.user, pk=self.cleaned_data['basket']) + else: + label = self.cleaned_data['label'].strip() + basket = models.FindBasket.objects.create( + user=self.user, label=label) + for item in items: + basket.items.add(item) + + class PreservationForm(CustomForm, ManageOldType): form_label = _("Preservation") form_admin_name = _(u"Find - 030 - Preservation") form_slug = "find-030-preservation" base_models = ['alteration', 'alteration_cause', 'preservation_to_consider', 'integritie', 'remarkabilitie'] - associated_models = {'alteration': models.AlterationType, - 'alteration_cause': models.AlterationCauseType, - 'treatment_emergency': models.TreatmentEmergencyType, - 'conservatory_state': models.ConservatoryState, - 'preservation_to_consider': models.TreatmentType, - 'remarkabilitie': models.RemarkabilityType, - 'integritie': models.IntegrityType, - } + associated_models = { + 'alteration': models.AlterationType, + 'alteration_cause': models.AlterationCauseType, + 'treatment_emergency': models.TreatmentEmergencyType, + 'conservatory_state': models.ConservatoryState, + 'preservation_to_consider': models.TreatmentType, + 'remarkabilitie': models.RemarkabilityType, + 'integritie': models.IntegrityType, + } integritie = forms.MultipleChoiceField( label=_(u"Integrity / interest"), choices=[], widget=widgets.Select2Multiple, required=False) @@ -406,7 +586,7 @@ DatingFormSet.form_admin_name = _(u"Find - 040 - Dating") DatingFormSet.form_slug = "find-040-dating" -class FindSelect(CustomForm, TableSelect): +class FindSelect(HistorySelect): _model = models.Find form_admin_name = _(u"Find - 001 - Search") @@ -545,7 +725,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)]) @@ -739,6 +919,43 @@ class UpstreamFindFormSelection(FindFormSelection): self.fields['resulting_pk'] = self.fields.pop('pk') +class FindBasketSelect(CustomForm, TableSelect): + _model = models.FindBasket + + form_admin_name = _(u"Find basket - 001 - Search") + form_slug = "findbasket-001-search" + search_vector = forms.CharField( + label=_(u"Full text search"), widget=widgets.SearchWidget( + 'archaeological-finds', 'findbasket' + )) + + label = forms.CharField(label=_(u"Denomination")) + + +class FindBasketFormSelection(CustomFormSearch): + SEARCH_AND_SELECT = True + form_label = _("Basket search") + associated_models = {'pk': models.FindBasket} + currents = {'pk': models.FindBasket} + + pk = forms.IntegerField( + label="", required=False, + widget=widgets.DataTable( + reverse_lazy('get-findbasket'), + FindBasketSelect, models.FindBasket, + ), + validators=[valid_id(models.FindBasket)]) + + +class FindBasketForm(IshtarForm): + form_label = _(u"Find basket") + label = forms.CharField( + label=_(u"Label"), + validators=[validators.MaxLengthValidator(1000)]) + comment = forms.CharField(label=_(u"Comment"), + widget=forms.Textarea, required=False) + + class NewFindBasketForm(forms.ModelForm): class Meta: model = models.FindBasket @@ -780,7 +997,9 @@ class SelectFindBasketForm(IshtarForm): return self.fields['basket'].choices = [('', '--')] + [ (b.pk, unicode(b)) - for b in models.FindBasket.objects.filter(user=self.user)] + for b in models.FindBasket.objects.filter( + Q(user=self.user) | Q(shared_with=self.user) + )] class DeleteFindBasketForm(SelectFindBasketForm): @@ -800,8 +1019,9 @@ class FindBasketAddItemForm(forms.Form): def save(self, user): try: - basket = models.FindBasket.objects.get( - pk=self.cleaned_data['basket_id'], user=user) + basket = models.FindBasket.objects.filter( + Q(user=user) | Q(shared_with=user) + ).get(pk=self.cleaned_data['basket_id']) item = models.Find.objects.get( pk=self.cleaned_data['item_id']) except models.FindBasket.DoesNotExist or\ @@ -810,8 +1030,8 @@ class FindBasketAddItemForm(forms.Form): raise PermissionDenied # check rights if not user.user_ptr.is_superuser and \ - not user.has_right('change_find') and \ - not (user.has_right('change_own_find') + not user.has_right('view_find') and \ + not (user.has_right('view_own_find') and item.is_own(user)): raise PermissionDenied basket.items.add(item) diff --git a/archaeological_finds/forms_treatments.py b/archaeological_finds/forms_treatments.py index 11cfd3173..b09d234f0 100644 --- a/archaeological_finds/forms_treatments.py +++ b/archaeological_finds/forms_treatments.py @@ -280,6 +280,92 @@ class TreatmentDeletionForm(FinalForm): confirm_end_msg = _(u"Would you like to delete this treatment?") +class QAFindTreatmentForm(IshtarForm): + container = forms.IntegerField( + label=_(u"Container"), + widget=widgets.JQueryAutoComplete( + reverse_lazy('autocomplete-container'), + associated_model=Container, new=True), + validators=[valid_id(Container)]) + create_treatment = forms.BooleanField( + label=_(u"Create a treatment"), required=False, + widget=widgets.CheckboxInput + ) + year = forms.IntegerField( + label=_("Year"), initial=lambda: datetime.datetime.now().year, + validators=[validators.MinValueValidator(1000), + validators.MaxValueValidator(2100)], required=False) + start_date = forms.DateField(label=_(u"Precise date"), required=False, + widget=DatePicker) + person = forms.IntegerField( + label=_(u"Responsible"), + widget=widgets.JQueryAutoComplete( + reverse_lazy('autocomplete-person'), associated_model=Person, + new=True), + validators=[valid_id(Person)], required=False) + organization = forms.IntegerField( + label=_(u"Organization"), + widget=widgets.JQueryAutoComplete( + reverse_lazy('autocomplete-organization'), + associated_model=Organization, new=True), + validators=[valid_id(Organization)], required=False) + + def __init__(self, *args, **kwargs): + self.confirm = False + self.user = None + if 'user' in kwargs: + self.user = kwargs.pop('user') + if hasattr(self.user, 'ishtaruser'): + self.user = self.user.ishtaruser + self.items = kwargs.pop('items') + + super(QAFindTreatmentForm, self).__init__(*args, **kwargs) + if not self.user: + return + + q = Person.objects.filter(ishtaruser__pk=self.user.pk) + if q.count(): + person = q.all()[0] + self.fields['person'].initial = person.pk + + def clean(self): + if not self.cleaned_data['create_treatment']: + return self.cleaned_data + + year = self.cleaned_data['year'] + if not year: + if self.cleaned_data['start_date']: + self.cleaned_data['year'] = self.cleaned_data['start_date'].year + else: + raise forms.ValidationError(_(u"At least a year is required.")) + return self.cleaned_data + + def save(self, items, user): + 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' + ) + t = models.Treatment.objects.create( + container=container, + year=self.cleaned_data['year'], + start_date=self.cleaned_data['start_date'], + location=container.location, + person_id=self.cleaned_data['person'], + organization_id=self.cleaned_data['organization'], + history_modifier=user + ) + t.treatment_types.add(packaging) + t.save(items=items) + return + for find in items: + if find.container == container: + continue + find.container = container + find.save() + + SLICING = (("month", _(u"months")), ('year', _(u"years")),) DATE_SOURCE = (("start", _(u"Start date")), ("end", _(u"Closing date")),) @@ -545,6 +631,7 @@ class TreatmentFileDeletionForm(FinalForm): confirm_msg = _(u"Are you sure you want to delete this treatment request?") confirm_end_msg = _(u"Would you like to delete this treatment request?") + DATE_SOURCE_FILE = ( ("creation", _(u"Creation date")), ("reception", _(u"Reception date")), diff --git a/archaeological_finds/ishtar_menu.py b/archaeological_finds/ishtar_menu.py index c72e9c089..afd624b74 100644 --- a/archaeological_finds/ishtar_menu.py +++ b/archaeological_finds/ishtar_menu.py @@ -24,7 +24,7 @@ from ishtar_common.menu_base import SectionItem, MenuItem from archaeological_operations.models import AdministrativeAct import models -# be carreful: each access_controls must be relevant with check_rights in urls +# be careful: each access_controls must be relevant with check_rights in urls MENU_SECTIONS = [ (50, @@ -56,22 +56,33 @@ MENU_SECTIONS = [ SectionItem( 'find_basket', _(u"Basket"), childs=[ + MenuItem('find_basket_search', + _(u"Search"), + model=models.FindBasket, + access_controls=['view_find', + 'view_own_find']), MenuItem('find_basket_creation', _(u"Creation"), model=models.FindBasket, - access_controls=['change_find', - 'change_own_find']), + access_controls=['view_find', + 'view_own_find']), + MenuItem('find_basket_modification', + _(u"Modification"), + model=models.FindBasket, + access_controls=[ + 'view_find', + 'view_own_find']), MenuItem('find_basket_modification_add', _(u"Manage items"), model=models.FindBasket, access_controls=[ - 'change_find', - 'change_own_find']), + 'view_find', + 'view_own_find']), MenuItem('find_basket_deletion', _(u"Deletion"), model=models.FindBasket, - access_controls=['change_find', - 'change_own_find']), + access_controls=['view_find', + 'view_own_find']), ]), # MenuItem( # 'treatment_creation', _(u"Add a treatment"), diff --git a/archaeological_finds/locale/django.pot b/archaeological_finds/locale/django.pot index 63d0d1c18..a15710acc 100644 --- a/archaeological_finds/locale/django.pot +++ b/archaeological_finds/locale/django.pot @@ -9,505 +9,559 @@ msgid "" msgstr "" -#: admin.py:39 models_finds.py:285 +#: admin.py:39 models_finds.py:288 msgid "Point (2D)" msgstr "" -#: admin.py:41 models_finds.py:287 +#: admin.py:41 models_finds.py:290 msgid "Line" msgstr "" -#: admin.py:43 models_finds.py:288 +#: admin.py:43 models_finds.py:291 msgid "Multi polygon" msgstr "" -#: forms.py:88 forms.py:94 forms.py:451 models_finds.py:619 -#: models_finds.py:1085 wizards.py:71 +#: forms.py:91 forms.py:97 forms.py:340 forms.py:353 forms.py:631 +#: models_finds.py:660 models_finds.py:1212 wizards.py:75 msgid "Context record" msgstr "" -#: forms.py:89 +#: forms.py:92 msgid "Find - 010 - Context record choice" msgstr "" -#: forms.py:123 ishtar_menu.py:32 models_finds.py:986 models_finds.py:1579 -#: models_treatments.py:338 templates/ishtar/sheet_find.html:4 +#: forms.py:126 ishtar_menu.py:32 models_finds.py:1089 models_finds.py:1716 +#: models_treatments.py:349 templates/ishtar/sheet_find.html:4 msgid "Find" msgstr "" -#: forms.py:124 +#: forms.py:127 msgid "Find - 020 - General" msgstr "" -#: forms.py:139 templates/ishtar/sheet_find.html:119 +#: forms.py:142 forms.py:341 templates/ishtar/sheet_find.html:40 msgid "Identification" msgstr "" -#: forms.py:142 forms.py:420 forms.py:702 models_finds.py:250 -#: models_finds.py:855 templates/ishtar/sheet_find.html:19 +#: forms.py:145 forms.py:360 forms.py:600 forms.py:889 models_finds.py:253 +#: models_finds.py:968 msgid "Free ID" msgstr "" -#: forms.py:144 forms.py:421 models_finds.py:856 -#: templates/ishtar/sheet_find.html:18 +#: forms.py:147 forms.py:362 forms.py:601 forms.py:932 models_finds.py:969 msgid "Denomination" msgstr "" -#: forms.py:145 models_finds.py:929 +#: forms.py:148 forms.py:363 models_finds.py:1042 msgid "Previous ID" msgstr "" -#: forms.py:147 models_finds.py:254 +#: forms.py:150 forms.py:365 models_finds.py:257 msgid "Excavation ID" msgstr "" -#: forms.py:148 models_finds.py:857 +#: forms.py:151 forms.py:366 models_finds.py:970 msgid "Museum ID" msgstr "" -#: forms.py:149 models_finds.py:852 +#: forms.py:152 forms.py:367 models_finds.py:965 msgid "Seal number" msgstr "" -#: forms.py:150 models_finds.py:925 +#: forms.py:153 forms.py:368 models_finds.py:1038 msgid "Mark" msgstr "" -#: forms.py:152 forms.py:153 forms.py:471 forms_treatments.py:139 -#: models_finds.py:255 models_finds.py:858 models_treatments.py:138 -#: templates/ishtar/sheet_find.html:134 +#: 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 msgid "Description" msgstr "" -#: forms.py:156 models_finds.py:262 +#: forms.py:159 models_finds.py:265 msgid "Discovery date (exact or TPQ)" msgstr "" -#: forms.py:159 models_finds.py:264 templates/ishtar/sheet_find.html:78 +#: forms.py:162 models_finds.py:267 templates/ishtar/sheet_basefind.html:29 msgid "Discovery date (TAQ)" msgstr "" -#: forms.py:161 forms.py:473 models_finds.py:266 +#: forms.py:164 forms.py:654 models_finds.py:269 msgid "Batch/object" msgstr "" -#: forms.py:163 models_finds.py:890 +#: forms.py:166 models_finds.py:1003 msgid "Is complete?" msgstr "" -#: forms.py:166 models_finds.py:54 models_finds.py:642 models_finds.py:864 +#: forms.py:169 forms.py:373 models_finds.py:57 models_finds.py:685 +#: models_finds.py:977 msgid "Material types" msgstr "" -#: forms.py:169 models_finds.py:869 +#: forms.py:172 models_finds.py:982 msgid "Material type quality" msgstr "" -#: forms.py:171 models_finds.py:149 models_finds.py:643 models_finds.py:893 +#: forms.py:174 forms.py:376 models_finds.py:152 models_finds.py:686 +#: models_finds.py:1006 msgid "Object types" msgstr "" -#: forms.py:174 models_finds.py:898 +#: forms.py:177 models_finds.py:1011 msgid "Object type quality" msgstr "" -#: forms.py:175 forms.py:709 models_finds.py:876 +#: forms.py:178 forms.py:896 models_finds.py:989 msgid "Find number" msgstr "" -#: forms.py:177 models_finds.py:911 +#: forms.py:180 models_finds.py:1024 msgid "Minimum number of individuals (MNI)" msgstr "" -#: forms.py:179 models_finds.py:859 +#: forms.py:182 models_finds.py:972 msgid "Decoration" msgstr "" -#: forms.py:181 models_finds.py:860 +#: forms.py:184 models_finds.py:973 msgid "Inscription" msgstr "" -#: forms.py:184 models_finds.py:862 +#: forms.py:187 forms.py:379 models_finds.py:975 msgid "Manufacturing place" msgstr "" -#: forms.py:186 models_finds.py:908 +#: forms.py:189 forms.py:381 models_finds.py:1021 msgid "Communicability" msgstr "" -#: forms.py:188 forms_treatments.py:141 forms_treatments.py:491 -#: models_finds.py:256 models_finds.py:926 models_treatments.py:137 -#: models_treatments.py:595 +#: forms.py:191 forms.py:384 forms.py:955 forms_treatments.py:141 +#: forms_treatments.py:577 models_finds.py:259 models_finds.py:1039 +#: models_treatments.py:145 models_treatments.py:609 msgid "Comment" msgstr "" -#: forms.py:191 models_finds.py:927 +#: forms.py:194 forms.py:394 models_finds.py:1040 msgid "Comment on dating" msgstr "" -#: forms.py:193 templates/ishtar/sheet_find.html:152 +#: forms.py:196 templates/ishtar/sheet_find.html:76 msgid "Dimensions" msgstr "" -#: forms.py:194 models_finds.py:912 +#: forms.py:197 models_finds.py:1025 msgid "Length (cm)" msgstr "" -#: forms.py:195 models_finds.py:913 +#: forms.py:198 models_finds.py:1026 msgid "Width (cm)" msgstr "" -#: forms.py:196 models_finds.py:914 +#: forms.py:199 models_finds.py:1027 msgid "Height (cm)" msgstr "" -#: forms.py:197 models_finds.py:915 +#: forms.py:200 models_finds.py:1028 msgid "Diameter (cm)" msgstr "" -#: forms.py:198 models_finds.py:916 +#: forms.py:201 models_finds.py:1029 msgid "Thickness (cm)" msgstr "" -#: forms.py:199 forms.py:707 models_finds.py:872 +#: forms.py:202 forms.py:894 models_finds.py:985 msgid "Volume (l)" msgstr "" -#: forms.py:200 forms.py:708 templates/ishtar/sheet_find.html:160 +#: forms.py:203 forms.py:895 templates/ishtar/sheet_find.html:84 msgid "Weight (g)" msgstr "" -#: forms.py:202 +#: forms.py:205 msgid "Clutter long side (cm)" msgstr "" -#: forms.py:204 +#: forms.py:207 msgid "Clutter short side (cm)" msgstr "" -#: forms.py:206 +#: forms.py:209 msgid "Clutter height (cm)" msgstr "" -#: forms.py:208 models_finds.py:923 +#: forms.py:211 models_finds.py:1036 msgid "Dimensions comment" msgstr "" -#: forms.py:211 templates/ishtar/sheet_find.html:94 -#: templates/ishtar/sheet_find.html:98 +#: forms.py:214 templates/ishtar/sheet_basefind.html:46 +#: templates/ishtar/sheet_basefind.html:50 msgid "Coordinates" msgstr "" -#: forms.py:213 models_finds.py:271 -msgid "Point of topographic reference" +#: forms.py:215 models_finds.py:276 +msgid "X" msgstr "" -#: forms.py:216 models_finds.py:273 -msgid "X" +#: forms.py:217 models_finds.py:279 +msgid "Estimated error for X" msgstr "" -#: forms.py:217 models_finds.py:274 +#: forms.py:218 models_finds.py:277 msgid "Y" msgstr "" -#: forms.py:218 models_finds.py:275 -msgid "Z" +#: forms.py:220 models_finds.py:281 +msgid "Estimated error for Y" msgstr "" -#: forms.py:220 models_finds.py:283 -msgid "Spatial Reference System" +#: forms.py:221 models_finds.py:278 +msgid "Z" msgstr "" -#: forms.py:223 models_finds.py:276 -msgid "Estimated error for X" +#: forms.py:223 models_finds.py:283 +msgid "Estimated error for Z" msgstr "" -#: forms.py:225 models_finds.py:278 -msgid "Estimated error for Y" +#: forms.py:225 models_finds.py:286 +msgid "Spatial Reference System" msgstr "" -#: forms.py:227 models_finds.py:280 -msgid "Estimated error for Z" +#: forms.py:228 models_finds.py:274 +msgid "Point of topographic reference" msgstr "" -#: forms.py:229 templates/ishtar/sheet_find.html:169 +#: forms.py:232 forms.py:343 templates/ishtar/sheet_basefind.html:66 +#: templates/ishtar/sheet_find.html:93 msgid "Sheet" msgstr "" -#: forms.py:230 forms.py:474 models_finds.py:931 +#: forms.py:233 forms.py:387 forms.py:655 models_finds.py:1044 msgid "Check" msgstr "" -#: forms.py:232 models_finds.py:933 +#: forms.py:235 forms.py:389 models_finds.py:1046 msgid "Check date" msgstr "" -#: forms.py:271 +#: 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." msgstr "" -#: forms.py:277 +#: forms.py:280 msgid "Discovery date: TAQ date must be older than TPQ date." msgstr "" -#: forms.py:287 +#: forms.py:290 msgid "Clutter: short side cannot be bigger than the long side." msgstr "" -#: forms.py:304 +#: forms.py:307 msgid "You should at least provide X, Y and the spatial reference system used." msgstr "" -#: forms.py:313 +#: forms.py:316 msgid "Coordinates are not relevant for the spatial reference system used: {}." msgstr "" -#: forms.py:319 templates/ishtar/sheet_find.html:182 +#: forms.py:322 +msgid "Find - Quick action - Modify" +msgstr "" + +#: forms.py:344 +msgid "Datation" +msgstr "" + +#: forms.py:392 forms.py:565 forms.py:641 templates/ishtar/sheet_find.html:123 +msgid "Period" +msgstr "" + +#: forms.py:436 +msgid "Find - Quick action - Modify single" +msgstr "" + +#: forms.py:449 +msgid "Create" +msgstr "" + +#: forms.py:450 +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 +msgid "Basket" +msgstr "" + +#: forms.py:474 +msgid "On update, you have to select a basket." +msgstr "" + +#: forms.py:478 +msgid "A label is required." +msgstr "" + +#: forms.py:481 +msgid "A basket with this label already exists." +msgstr "" + +#: forms.py:498 templates/ishtar/sheet_find.html:102 msgid "Preservation" msgstr "" -#: forms.py:320 +#: forms.py:499 msgid "Find - 030 - Preservation" msgstr "" -#: forms.py:333 forms.py:467 models_finds.py:902 +#: forms.py:513 forms.py:648 models_finds.py:1015 msgid "Integrity / interest" msgstr "" -#: forms.py:336 forms.py:469 models_finds.py:905 +#: forms.py:516 forms.py:650 models_finds.py:1018 msgid "Remarkability" msgstr "" -#: forms.py:338 forms.py:465 models_finds.py:77 models_finds.py:943 +#: forms.py:518 forms.py:646 models_finds.py:80 models_finds.py:1056 msgid "Conservatory state" msgstr "" -#: forms.py:341 models_finds.py:952 +#: forms.py:521 models_finds.py:1065 msgid "Alteration" msgstr "" -#: forms.py:344 models_finds.py:956 +#: forms.py:524 models_finds.py:1069 msgid "Alteration cause" msgstr "" -#: forms.py:347 models_finds.py:949 +#: forms.py:527 models_finds.py:1062 msgid "Recommended treatments" msgstr "" -#: forms.py:349 models_finds.py:960 +#: forms.py:529 models_finds.py:1073 msgid "Treatment emergency" msgstr "" -#: forms.py:351 models_finds.py:935 +#: forms.py:531 models_finds.py:1048 msgid "Estimated value" msgstr "" -#: forms.py:352 models_finds.py:963 +#: forms.py:532 models_finds.py:1076 msgid "Insurance value" msgstr "" -#: forms.py:354 models_finds.py:965 +#: forms.py:534 models_finds.py:1078 msgid "Appraisal date" msgstr "" -#: forms.py:356 models_finds.py:945 +#: forms.py:536 models_finds.py:1058 msgid "Conservatory comment" msgstr "" -#: forms.py:380 forms.py:404 models_finds.py:884 -#: templates/ishtar/sheet_find.html:199 +#: forms.py:560 forms.py:584 models_finds.py:997 +#: templates/ishtar/sheet_find.html:119 msgid "Dating" msgstr "" -#: forms.py:385 forms.py:460 -msgid "Period" -msgstr "" - -#: forms.py:386 forms_treatments.py:143 forms_treatments.py:284 -#: forms_treatments.py:493 models_finds.py:1584 models_treatments.py:140 -#: models_treatments.py:349 templates/ishtar/sheet_find.html:232 -#: templates/ishtar/sheet_find.html:270 +#: forms.py:566 forms_treatments.py:143 forms_treatments.py:370 +#: forms_treatments.py:579 models_finds.py:1721 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 msgid "Start date" msgstr "" -#: forms.py:388 models_finds.py:1585 models_treatments.py:350 -#: templates/ishtar/sheet_find.html:233 templates/ishtar/sheet_find.html:271 +#: forms.py:568 models_finds.py:1722 models_treatments.py:361 +#: templates/ishtar/sheet_find.html:125 templates/ishtar/sheet_find.html:186 +#: templates/ishtar/sheet_find.html:224 msgid "End date" msgstr "" -#: forms.py:389 +#: forms.py:569 templates/ishtar/sheet_find.html:127 msgid "Quality" msgstr "" -#: forms.py:391 +#: forms.py:571 templates/ishtar/sheet_find.html:126 msgid "Dating type" msgstr "" -#: forms.py:393 +#: forms.py:573 templates/ishtar/sheet_find.html:128 msgid "Precise dating" msgstr "" -#: forms.py:405 +#: forms.py:585 msgid "Find - 040 - Dating" msgstr "" -#: forms.py:412 +#: forms.py:592 msgid "Find - 001 - Search" msgstr "" -#: forms.py:415 forms_treatments.py:50 forms_treatments.py:333 -#: forms_treatments.py:406 forms_treatments.py:598 +#: forms.py:595 forms.py:928 forms_treatments.py:50 forms_treatments.py:419 +#: forms_treatments.py:492 forms_treatments.py:685 msgid "Full text search" msgstr "" -#: forms.py:418 models_finds.py:291 +#: forms.py:598 models_finds.py:294 msgid "Short ID" msgstr "" -#: forms.py:419 models_finds.py:294 +#: forms.py:599 models_finds.py:297 msgid "Complete ID" msgstr "" -#: forms.py:424 forms_treatments.py:56 forms_treatments.py:101 -#: forms_treatments.py:336 forms_treatments.py:411 forms_treatments.py:463 -#: forms_treatments.py:601 models_treatments.py:114 models_treatments.py:568 +#: forms.py:604 forms_treatments.py:56 forms_treatments.py:101 +#: forms_treatments.py:295 forms_treatments.py:422 forms_treatments.py:497 +#: forms_treatments.py:549 forms_treatments.py:688 models_treatments.py:122 +#: models_treatments.py:582 msgid "Year" msgstr "" -#: forms.py:426 +#: forms.py:606 msgid "Operation's number (index by year)" msgstr "" -#: forms.py:429 +#: forms.py:609 msgid "Code PATRIARCHE" msgstr "" -#: forms.py:433 +#: forms.py:613 msgid "Operation type" msgstr "" -#: forms.py:436 +#: forms.py:616 msgid "Areas" msgstr "" -#: forms.py:439 +#: forms.py:619 msgid "Archaeological site (attached to the operation)" msgstr "" -#: forms.py:445 +#: forms.py:625 msgid "Archaeological site (attached to the context record)" msgstr "" -#: forms.py:457 +#: forms.py:638 msgid "Search within related operations" msgstr "" -#: forms.py:459 +#: forms.py:640 msgid "Search within related context records" msgstr "" -#: forms.py:461 forms.py:706 models_finds.py:53 +#: forms.py:642 forms.py:893 models_finds.py:56 msgid "Material type" msgstr "" -#: forms.py:462 models_finds.py:148 +#: forms.py:643 models_finds.py:151 msgid "Object type" msgstr "" -#: forms.py:464 +#: forms.py:645 msgid "Preservation type" msgstr "" -#: forms.py:475 forms_treatments.py:59 +#: forms.py:656 forms_treatments.py:59 msgid "Has an image?" msgstr "" -#: forms.py:516 +#: forms.py:703 msgid "Warehouse (location)" msgstr "" -#: forms.py:522 +#: forms.py:709 msgid "Warehouse (responsible)" msgstr "" -#: forms.py:527 +#: forms.py:714 msgid "Container ID" msgstr "" -#: forms.py:528 +#: forms.py:715 msgid "Container ref." msgstr "" -#: forms.py:533 forms.py:557 views.py:156 +#: forms.py:720 forms.py:744 views.py:185 msgid "Find search" msgstr "" -#: forms.py:582 models_treatments.py:247 +#: forms.py:769 models_treatments.py:258 #: templates/ishtar/sheet_treatment.html:56 msgid "Upstream finds" msgstr "" -#: forms.py:584 models_finds.py:987 +#: forms.py:771 models_finds.py:1090 +#: templates/ishtar/forms/qa_find_treatment.html:11 msgid "Finds" msgstr "" -#: forms.py:596 +#: forms.py:783 msgid "You should at least select one archaeological find." msgstr "" -#: forms.py:699 +#: forms.py:886 msgid "Resulting find" msgstr "" -#: forms.py:704 +#: forms.py:891 msgid "Precise description" msgstr "" -#: forms.py:718 +#: forms.py:905 msgid "Resulting finds" msgstr "" -#: forms.py:723 +#: forms.py:910 msgid "Would you like to delete this find?" msgstr "" -#: forms.py:727 models_treatments.py:66 +#: forms.py:914 models_treatments.py:68 msgid "Upstream find" msgstr "" -#: forms.py:748 -msgid "Another basket already exists with this name." +#: forms.py:925 +#| msgid "Find - 001 - Search" +msgid "Find basket - 001 - Search" msgstr "" -#: forms.py:758 forms.py:762 forms_treatments.py:180 ishtar_menu.py:57 -msgid "Basket" +#: forms.py:937 views.py:122 +#| msgid "Treatment search" +msgid "Basket search" +msgstr "" + +#: forms.py:951 +msgid "Find basket" msgstr "" -#: forms_treatments.py:54 forms_treatments.py:97 models_treatments.py:110 -#: templates/ishtar/sheet_find.html:226 templates/ishtar/sheet_find.html:264 +#: 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 msgid "Label" msgstr "" -#: forms_treatments.py:55 forms_treatments.py:100 models_treatments.py:112 +#: forms.py:972 +msgid "Another basket already exists with this name." +msgstr "" + +#: forms_treatments.py:55 forms_treatments.py:100 models_treatments.py:120 msgid "Other ref." msgstr "" -#: forms_treatments.py:57 forms_treatments.py:232 forms_treatments.py:337 -#: forms_treatments.py:399 forms_treatments.py:412 forms_treatments.py:516 -#: forms_treatments.py:602 forms_treatments.py:669 models_treatments.py:115 -#: models_treatments.py:569 +#: forms_treatments.py:57 forms_treatments.py:232 forms_treatments.py:423 +#: forms_treatments.py:485 forms_treatments.py:498 forms_treatments.py:602 +#: forms_treatments.py:689 forms_treatments.py:756 models_treatments.py:123 +#: models_treatments.py:583 msgid "Index" msgstr "" -#: forms_treatments.py:58 forms_treatments.py:106 forms_treatments.py:292 -#: forms_treatments.py:353 models_finds.py:103 models_treatments.py:120 -#: models_treatments.py:348 +#: forms_treatments.py:58 forms_treatments.py:106 forms_treatments.py:378 +#: forms_treatments.py:439 models_finds.py:106 models_treatments.py:128 +#: models_treatments.py:359 msgid "Treatment type" msgstr "" -#: forms_treatments.py:71 views.py:383 +#: forms_treatments.py:71 views.py:420 msgid "Treatment search" msgstr "" @@ -519,8 +573,8 @@ msgstr "" msgid "Treatment - 020 - General" msgstr "" -#: forms_treatments.py:108 models_treatments.py:68 models_treatments.py:122 -#: templates/ishtar/sheet_find.html:228 templates/ishtar/sheet_find.html:266 +#: forms_treatments.py:108 models_treatments.py:70 models_treatments.py:130 +#: templates/ishtar/sheet_find.html:181 templates/ishtar/sheet_find.html:219 msgid "State" msgstr "" @@ -528,15 +582,16 @@ msgstr "" msgid "Target" msgstr "" -#: forms_treatments.py:112 forms_treatments.py:474 models_treatments.py:130 +#: forms_treatments.py:112 forms_treatments.py:301 forms_treatments.py:560 +#: models_treatments.py:71 models_treatments.py:138 msgid "Responsible" msgstr "" -#: forms_treatments.py:118 models_treatments.py:133 +#: forms_treatments.py:118 forms_treatments.py:307 models_treatments.py:141 msgid "Organization" msgstr "" -#: forms_treatments.py:124 models_treatments.py:125 models_treatments.py:351 +#: forms_treatments.py:124 models_treatments.py:133 models_treatments.py:362 msgid "Location" msgstr "" @@ -544,16 +599,16 @@ msgstr "" msgid "Container (relevant for packaging)" msgstr "" -#: forms_treatments.py:136 forms_treatments.py:470 +#: forms_treatments.py:136 forms_treatments.py:556 msgid "External ref." msgstr "" -#: forms_treatments.py:137 models_treatments.py:139 +#: forms_treatments.py:137 models_treatments.py:147 msgid "Goal" msgstr "" -#: forms_treatments.py:145 forms_treatments.py:284 forms_treatments.py:499 -#: forms_treatments.py:551 models_treatments.py:141 models_treatments.py:589 +#: forms_treatments.py:145 forms_treatments.py:370 forms_treatments.py:585 +#: forms_treatments.py:638 models_treatments.py:149 models_treatments.py:603 msgid "Closing date" msgstr "" @@ -599,7 +654,7 @@ msgstr "" msgid "Another treatment with this index exists for {}." msgstr "" -#: forms_treatments.py:262 models_treatments.py:118 +#: forms_treatments.py:262 models_treatments.py:126 msgid "Associated request" msgstr "" @@ -607,9 +662,9 @@ msgstr "" msgid "Treatment - 010 - Request choice" msgstr "" -#: forms_treatments.py:268 forms_treatments.py:454 ishtar_menu.py:84 -#: models_treatments.py:604 models_treatments.py:632 -#: templates/ishtar/sheet_treatmentfile.html:4 wizards.py:195 +#: forms_treatments.py:268 forms_treatments.py:540 ishtar_menu.py:95 +#: models_treatments.py:618 models_treatments.py:646 +#: templates/ishtar/sheet_treatmentfile.html:4 wizards.py:207 msgid "Treatment request" msgstr "" @@ -623,852 +678,913 @@ msgstr "" msgid "Would you like to delete this treatment?" msgstr "" -#: forms_treatments.py:283 +#: 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 +msgid "Container" +msgstr "" + +#: forms_treatments.py:291 +msgid "Create a treatment" +msgstr "" + +#: forms_treatments.py:298 +msgid "Precise date" +msgstr "" + +#: forms_treatments.py:340 +msgid "At least a year is required." +msgstr "" + +#: forms_treatments.py:369 msgid "months" msgstr "" -#: forms_treatments.py:283 +#: forms_treatments.py:369 msgid "years" msgstr "" -#: forms_treatments.py:288 forms_treatments.py:555 +#: forms_treatments.py:374 forms_treatments.py:642 msgid "Slicing" msgstr "" -#: forms_treatments.py:291 forms_treatments.py:558 +#: forms_treatments.py:377 forms_treatments.py:645 msgid "Date get from" msgstr "" -#: forms_treatments.py:294 forms_treatments.py:561 +#: forms_treatments.py:380 forms_treatments.py:648 msgid "Date after" msgstr "" -#: forms_treatments.py:296 forms_treatments.py:563 +#: forms_treatments.py:382 forms_treatments.py:650 msgid "Date before" msgstr "" -#: forms_treatments.py:338 forms_treatments.py:388 forms_treatments.py:603 -#: forms_treatments.py:658 +#: forms_treatments.py:424 forms_treatments.py:474 forms_treatments.py:690 +#: forms_treatments.py:745 msgid "Act type" msgstr "" -#: forms_treatments.py:339 forms_treatments.py:604 +#: forms_treatments.py:425 forms_treatments.py:691 msgid "Indexed?" msgstr "" -#: forms_treatments.py:340 forms_treatments.py:605 +#: forms_treatments.py:426 forms_treatments.py:692 msgid "Object" msgstr "" -#: forms_treatments.py:344 forms_treatments.py:609 +#: forms_treatments.py:430 forms_treatments.py:696 msgid "Signature date after" msgstr "" -#: forms_treatments.py:346 forms_treatments.py:611 +#: forms_treatments.py:432 forms_treatments.py:698 msgid "Signature date before" msgstr "" -#: forms_treatments.py:348 +#: forms_treatments.py:434 msgid "Treatment name" msgstr "" -#: forms_treatments.py:349 +#: forms_treatments.py:435 msgid "Treatment year" msgstr "" -#: forms_treatments.py:350 +#: forms_treatments.py:436 msgid "Treatment index" msgstr "" -#: forms_treatments.py:352 +#: forms_treatments.py:438 msgid "Treatment internal reference" msgstr "" -#: forms_treatments.py:356 forms_treatments.py:625 +#: forms_treatments.py:442 forms_treatments.py:712 msgid "Modified by" msgstr "" -#: forms_treatments.py:386 +#: forms_treatments.py:472 msgid "Treatment - Administrative act - General" msgstr "" -#: forms_treatments.py:409 forms_treatments.py:461 models_treatments.py:574 +#: forms_treatments.py:495 forms_treatments.py:547 models_treatments.py:588 msgid "Name" msgstr "" -#: forms_treatments.py:410 forms_treatments.py:468 +#: forms_treatments.py:496 forms_treatments.py:554 msgid "Internal ref." msgstr "" -#: forms_treatments.py:413 forms_treatments.py:472 models_treatments.py:67 -#: templates/ishtar/sheet_find.html:227 templates/ishtar/sheet_find.html:265 +#: forms_treatments.py:499 forms_treatments.py:558 models_treatments.py:69 +#: templates/ishtar/sheet_find.html:180 templates/ishtar/sheet_find.html:218 msgid "Type" msgstr "" -#: forms_treatments.py:416 +#: forms_treatments.py:502 msgid "In charge" msgstr "" -#: forms_treatments.py:422 forms_treatments.py:480 models_treatments.py:583 +#: forms_treatments.py:508 forms_treatments.py:566 models_treatments.py:597 #: templates/ishtar/sheet_treatmentfile.html:45 msgid "Applicant" msgstr "" -#: forms_treatments.py:428 forms_treatments.py:486 models_treatments.py:587 +#: forms_treatments.py:514 forms_treatments.py:572 models_treatments.py:601 #: templates/ishtar/sheet_treatmentfile.html:53 msgid "Applicant organisation" msgstr "" -#: forms_treatments.py:442 views.py:487 +#: forms_treatments.py:528 views.py:524 msgid "Treatment request search" msgstr "" -#: forms_treatments.py:497 forms_treatments.py:550 models_treatments.py:593 +#: forms_treatments.py:583 forms_treatments.py:637 models_treatments.py:607 msgid "Reception date" msgstr "" -#: forms_treatments.py:539 +#: forms_treatments.py:625 msgid "Another treatment request with this index exists for {}." msgstr "" -#: forms_treatments.py:545 +#: forms_treatments.py:631 msgid "Are you sure you want to delete this treatment request?" msgstr "" -#: forms_treatments.py:546 +#: forms_treatments.py:632 msgid "Would you like to delete this treatment request?" msgstr "" -#: forms_treatments.py:549 models_treatments.py:591 +#: forms_treatments.py:636 models_treatments.py:605 msgid "Creation date" msgstr "" -#: forms_treatments.py:559 forms_treatments.py:622 models_treatments.py:508 -#: models_treatments.py:576 +#: forms_treatments.py:646 forms_treatments.py:709 models_treatments.py:519 +#: models_treatments.py:590 msgid "Treatment request type" msgstr "" -#: forms_treatments.py:614 +#: forms_treatments.py:701 msgid "Treatment request name" msgstr "" -#: forms_treatments.py:616 +#: forms_treatments.py:703 msgid "Treatment request year" msgstr "" -#: forms_treatments.py:618 +#: forms_treatments.py:705 msgid "Treatment request index" msgstr "" -#: forms_treatments.py:620 +#: forms_treatments.py:707 msgid "Treatment request internal reference" msgstr "" -#: forms_treatments.py:656 +#: forms_treatments.py:743 msgid "Treatment request - Administrative act - General" msgstr "" -#: ishtar_menu.py:37 ishtar_menu.py:89 ishtar_menu.py:112 ishtar_menu.py:144 -#: ishtar_menu.py:168 +#: ishtar_menu.py:37 ishtar_menu.py:60 ishtar_menu.py:100 ishtar_menu.py:123 +#: ishtar_menu.py:155 ishtar_menu.py:179 msgid "Search" msgstr "" -#: ishtar_menu.py:42 ishtar_menu.py:60 ishtar_menu.py:94 ishtar_menu.py:116 -#: ishtar_menu.py:149 ishtar_menu.py:172 +#: ishtar_menu.py:42 ishtar_menu.py:65 ishtar_menu.py:105 ishtar_menu.py:127 +#: ishtar_menu.py:160 ishtar_menu.py:183 msgid "Creation" msgstr "" -#: ishtar_menu.py:47 ishtar_menu.py:99 ishtar_menu.py:120 ishtar_menu.py:154 -#: ishtar_menu.py:177 +#: ishtar_menu.py:47 ishtar_menu.py:70 ishtar_menu.py:110 ishtar_menu.py:131 +#: ishtar_menu.py:165 ishtar_menu.py:188 msgid "Modification" msgstr "" -#: ishtar_menu.py:52 ishtar_menu.py:71 ishtar_menu.py:104 ishtar_menu.py:123 -#: ishtar_menu.py:159 ishtar_menu.py:180 +#: ishtar_menu.py:52 ishtar_menu.py:82 ishtar_menu.py:115 ishtar_menu.py:134 +#: ishtar_menu.py:170 ishtar_menu.py:191 msgid "Deletion" msgstr "" -#: ishtar_menu.py:65 +#: ishtar_menu.py:76 msgid "Manage items" msgstr "" -#: ishtar_menu.py:109 ishtar_menu.py:165 models_finds.py:1581 +#: ishtar_menu.py:120 ishtar_menu.py:176 models_finds.py:1718 msgid "Administrative act" msgstr "" -#: ishtar_menu.py:127 ishtar_menu.py:184 models_finds.py:968 -#: models_treatments.py:155 models_treatments.py:597 +#: ishtar_menu.py:138 ishtar_menu.py:195 models_finds.py:1081 +#: models_treatments.py:163 models_treatments.py:611 msgid "Documents" msgstr "" -#: ishtar_menu.py:136 models_treatments.py:162 models_treatments.py:340 +#: ishtar_menu.py:147 models_treatments.py:170 models_treatments.py:351 #: templates/ishtar/sheet_treatment.html:4 msgid "Treatment" msgstr "" -#: ishtar_menu.py:141 +#: ishtar_menu.py:152 msgid "Simple treatments" msgstr "" -#: models_finds.py:48 +#: models_finds.py:51 msgid "Code" msgstr "" -#: models_finds.py:49 +#: models_finds.py:52 msgid "Recommendation" msgstr "" -#: models_finds.py:63 models_finds.py:87 models_finds.py:135 -#: models_finds.py:158 models_finds.py:215 models_finds.py:854 -#: models_treatments.py:344 +#: models_finds.py:66 models_finds.py:90 models_finds.py:138 +#: models_finds.py:161 models_finds.py:218 models_finds.py:967 +#: models_treatments.py:355 msgid "Order" msgstr "" -#: models_finds.py:66 +#: models_finds.py:69 msgid "Material type quality type" msgstr "" -#: models_finds.py:67 +#: models_finds.py:70 msgid "Material type quality types" msgstr "" -#: models_finds.py:78 +#: models_finds.py:81 msgid "Conservatory states" msgstr "" -#: models_finds.py:88 +#: models_finds.py:91 msgid "Parent type" msgstr "" -#: models_finds.py:90 +#: models_finds.py:93 msgid "Virtual" msgstr "" -#: models_finds.py:92 +#: models_finds.py:95 msgid "Upstream is many" msgstr "" -#: models_finds.py:94 +#: models_finds.py:97 msgid "Check this if for this treatment from many finds you'll get one." msgstr "" -#: models_finds.py:97 +#: models_finds.py:100 msgid "Downstream is many" msgstr "" -#: models_finds.py:99 +#: models_finds.py:102 msgid "Check this if for this treatment from one find you'll get many." msgstr "" -#: models_finds.py:104 models_treatments.py:229 +#: models_finds.py:107 models_treatments.py:240 msgid "Treatment types" msgstr "" -#: models_finds.py:114 +#: models_finds.py:117 msgid "Integrity / interest type" msgstr "" -#: models_finds.py:115 +#: models_finds.py:118 msgid "Integrity / interest types" msgstr "" -#: models_finds.py:125 +#: models_finds.py:128 msgid "Remarkability type" msgstr "" -#: models_finds.py:126 +#: models_finds.py:129 msgid "Remarkability types" msgstr "" -#: models_finds.py:137 +#: models_finds.py:140 msgid "Batch type" msgstr "" -#: models_finds.py:138 +#: models_finds.py:141 msgid "Batch types" msgstr "" -#: models_finds.py:161 +#: models_finds.py:164 msgid "Object type quality type" msgstr "" -#: models_finds.py:162 +#: models_finds.py:165 msgid "Object type quality types" msgstr "" -#: models_finds.py:172 +#: models_finds.py:175 msgid "Alteration type" msgstr "" -#: models_finds.py:173 +#: models_finds.py:176 msgid "Alteration types" msgstr "" -#: models_finds.py:183 +#: models_finds.py:186 msgid "Alteration cause type" msgstr "" -#: models_finds.py:184 +#: models_finds.py:187 msgid "Alteration cause types" msgstr "" -#: models_finds.py:194 +#: models_finds.py:197 msgid "Treatment emergency type" msgstr "" -#: models_finds.py:195 +#: models_finds.py:198 msgid "Treatment emergency types" msgstr "" -#: models_finds.py:205 +#: models_finds.py:208 msgid "Communicability type" msgstr "" -#: models_finds.py:206 +#: models_finds.py:209 msgid "Communicability types" msgstr "" -#: models_finds.py:218 +#: models_finds.py:221 msgid "Checked type" msgstr "" -#: models_finds.py:219 +#: models_finds.py:222 msgid "Checked types" msgstr "" -#: models_finds.py:251 models_finds.py:847 models_treatments.py:135 -#: models_treatments.py:572 +#: models_finds.py:254 models_finds.py:960 models_treatments.py:143 +#: models_treatments.py:586 msgid "External ID" msgstr "" -#: models_finds.py:253 models_finds.py:849 +#: models_finds.py:256 models_finds.py:962 msgid "External ID is set automatically" msgstr "" -#: models_finds.py:257 +#: models_finds.py:260 msgid "Special interest" msgstr "" -#: models_finds.py:261 +#: models_finds.py:264 msgid "Context Record" msgstr "" -#: models_finds.py:269 +#: models_finds.py:272 msgid "Material index" msgstr "" -#: models_finds.py:286 +#: models_finds.py:289 msgid "Point (3D)" msgstr "" -#: models_finds.py:292 models_finds.py:295 +#: models_finds.py:295 models_finds.py:298 msgid "Cached value - do not edit" msgstr "" -#: models_finds.py:304 models_finds.py:845 +#: models_finds.py:308 models_finds.py:958 msgid "Base find" msgstr "" -#: models_finds.py:305 +#: models_finds.py:309 msgid "Base finds" msgstr "" -#: models_finds.py:549 +#: models_finds.py:565 msgid "g" msgstr "" -#: models_finds.py:550 +#: models_finds.py:566 msgid "kg" msgstr "" -#: models_finds.py:620 templates/ishtar/sheet_find.html:21 +#: models_finds.py:592 views.py:301 +msgid "Manage basket" +msgstr "" + +#: models_finds.py:661 msgid "Base find - Short ID" msgstr "" -#: models_finds.py:621 templates/ishtar/sheet_find.html:20 +#: models_finds.py:662 msgid "Base find - Complete ID" msgstr "" -#: models_finds.py:623 +#: models_finds.py:664 msgid "Operation (code)" msgstr "" -#: models_finds.py:625 +#: models_finds.py:666 msgid "Town" msgstr "" -#: models_finds.py:627 +#: models_finds.py:668 msgid "Operation (name)" msgstr "" -#: models_finds.py:629 +#: models_finds.py:672 msgid "Parcel" msgstr "" -#: models_finds.py:630 +#: models_finds.py:673 msgid "Batch" msgstr "" -#: models_finds.py:631 +#: models_finds.py:674 msgid "Base find - Comment" msgstr "" -#: models_finds.py:632 +#: models_finds.py:675 msgid "Base find - Description" msgstr "" -#: models_finds.py:633 +#: models_finds.py:676 msgid "Base find - Topographic localisation" msgstr "" -#: models_finds.py:635 +#: models_finds.py:678 msgid "Base find - Special interest" msgstr "" -#: models_finds.py:637 +#: models_finds.py:680 msgid "Base find - Discovery date (exact or TPQ)" msgstr "" -#: models_finds.py:639 +#: models_finds.py:682 msgid "Base find - Discovery date (TAQ)" msgstr "" -#: models_finds.py:640 models_finds.py:887 models_treatments.py:142 -#: models_treatments.py:352 templates/ishtar/sheet_find.html:231 -#: templates/ishtar/sheet_find.html:269 -msgid "Container" -msgstr "" - -#: models_finds.py:641 +#: models_finds.py:684 msgid "Periods" msgstr "" -#: models_finds.py:718 +#: models_finds.py:760 msgctxt "key for text search" msgid "short-id" msgstr "" -#: models_finds.py:722 +#: models_finds.py:764 msgctxt "key for text search" msgid "complete-id" msgstr "" -#: models_finds.py:726 +#: models_finds.py:768 msgctxt "key for text search" msgid "free-id" msgstr "" -#: models_finds.py:730 +#: models_finds.py:772 msgctxt "key for text search" msgid "denomination" msgstr "" -#: models_finds.py:734 +#: models_finds.py:776 msgctxt "key for text search" msgid "town" msgstr "" -#: models_finds.py:738 models_treatments.py:84 models_treatments.py:540 +#: models_finds.py:780 models_treatments.py:87 models_treatments.py:551 msgctxt "key for text search" msgid "year" msgstr "" -#: models_finds.py:742 +#: models_finds.py:784 msgctxt "key for text search" msgid "operation-code" msgstr "" -#: models_finds.py:746 +#: models_finds.py:788 msgctxt "key for text search" msgid "code-patriarche" msgstr "" -#: models_finds.py:750 +#: models_finds.py:792 msgctxt "key for text search" msgid "operation-type" msgstr "" -#: models_finds.py:755 +#: models_finds.py:797 msgctxt "key for text search" msgid "area" msgstr "" -#: models_finds.py:759 +#: models_finds.py:801 msgctxt "key for text search" msgid "site" msgstr "" -#: models_finds.py:764 +#: models_finds.py:806 models_finds.py:945 msgctxt "key for text search" msgid "context-record-site" msgstr "" -#: models_finds.py:769 +#: models_finds.py:811 models_finds.py:939 msgctxt "key for text search" msgid "context-record" msgstr "" -#: models_finds.py:773 +#: models_finds.py:815 msgctxt "key for text search" msgid "operation-relation-type" msgstr "" -#: models_finds.py:777 +#: models_finds.py:819 msgctxt "key for text search" msgid "context-record-relation-type" msgstr "" -#: models_finds.py:781 +#: models_finds.py:823 msgctxt "key for text search" msgid "period" msgstr "" -#: models_finds.py:785 +#: models_finds.py:827 msgctxt "key for text search" msgid "material" msgstr "" -#: models_finds.py:789 +#: models_finds.py:831 msgctxt "key for text search" msgid "object-type" msgstr "" -#: models_finds.py:793 +#: models_finds.py:835 msgctxt "key for text search" msgid "preservation" msgstr "" -#: models_finds.py:797 +#: models_finds.py:839 msgctxt "key for text search" msgid "conservatory" msgstr "" -#: models_finds.py:801 +#: models_finds.py:843 msgctxt "key for text search" msgid "integrity" msgstr "" -#: models_finds.py:805 +#: models_finds.py:847 msgctxt "key for text search" msgid "remarkability" msgstr "" -#: models_finds.py:809 +#: models_finds.py:851 msgctxt "key for text search" msgid "description" msgstr "" -#: models_finds.py:813 +#: models_finds.py:855 msgctxt "key for text search" msgid "batch" msgstr "" -#: models_finds.py:817 +#: models_finds.py:859 msgctxt "key for text search" msgid "checked" msgstr "" -#: models_finds.py:821 models_treatments.py:92 +#: models_finds.py:863 models_treatments.py:95 msgctxt "key for text search" msgid "has-image" msgstr "" -#: models_finds.py:825 +#: models_finds.py:867 models_finds.py:942 msgctxt "key for text search" msgid "location" msgstr "" -#: models_finds.py:829 +#: models_finds.py:871 msgctxt "key for text search" msgid "warehouse" msgstr "" -#: models_finds.py:833 +#: models_finds.py:875 msgctxt "key for text search" msgid "container-index" msgstr "" -#: models_finds.py:837 +#: models_finds.py:879 msgctxt "key for text search" msgid "container-ref" msgstr "" -#: models_finds.py:873 +#: models_finds.py:883 +msgctxt "key for text search" +msgid "basket" +msgstr "" + +#: models_finds.py:887 models_finds.py:936 +msgctxt "key for text search" +msgid "operation" +msgstr "" + +#: models_finds.py:891 +#| msgid "Last modified by" +msgctxt "key for text search" +msgid "last-modified-by" +msgstr "" + +#: models_finds.py:895 +msgctxt "key for text search" +msgid "modified-since" +msgstr "" + +#: models_finds.py:919 +msgid "Bulk update" +msgstr "" + +#: models_finds.py:930 models_finds.py:1179 +#: templates/ishtar/forms/qa_find_treatment.html:16 views.py:666 +msgid "Packaging" +msgstr "" + +#: models_finds.py:986 msgid "Weight" msgstr "" -#: models_finds.py:874 +#: models_finds.py:987 msgid "Weight unit" msgstr "" -#: models_finds.py:880 templates/ishtar/sheet_find.html:221 +#: models_finds.py:993 templates/ishtar/sheet_find.html:174 msgid "Upstream treatment" msgstr "" -#: models_finds.py:883 templates/ishtar/sheet_find.html:259 +#: models_finds.py:996 templates/ishtar/sheet_find.html:212 msgid "Downstream treatment" msgstr "" -#: models_finds.py:918 +#: models_finds.py:1031 msgid "Clutter - long side (cm)" msgstr "" -#: models_finds.py:920 +#: models_finds.py:1033 msgid "Clutter - short side (cm)" msgstr "" -#: models_finds.py:922 +#: models_finds.py:1035 msgid "Clutter - height (cm)" msgstr "" -#: models_finds.py:938 +#: models_finds.py:1051 msgid "Collection" msgstr "" -#: models_finds.py:970 models_treatments.py:157 models_treatments.py:599 +#: models_finds.py:1083 models_treatments.py:165 models_treatments.py:613 msgid "Cached name" msgstr "" -#: models_finds.py:999 +#: models_finds.py:1105 msgid "FIND" msgstr "" -#: models_finds.py:1094 wizards.py:70 wizards.py:207 +#: models_finds.py:1173 +#| msgid "Find basket" +msgid "Add to basket" +msgstr "" + +#: models_finds.py:1221 wizards.py:74 wizards.py:219 msgid "Operation" msgstr "" -#: models_finds.py:1406 +#: models_finds.py:1543 msgid "No container have been set - the localisation cannot be set." msgstr "" -#: models_finds.py:1412 +#: models_finds.py:1549 msgid "The division number {} have not been set for the warehouse {}." msgstr "" -#: models_finds.py:1582 +#: models_finds.py:1719 msgid "Person" msgstr "" -#: models_finds.py:1588 +#: models_finds.py:1725 msgid "Property" msgstr "" -#: models_finds.py:1589 +#: models_finds.py:1726 msgid "Properties" msgstr "" -#: models_treatments.py:41 +#: models_treatments.py:42 msgid "Treatment state type" msgstr "" -#: models_treatments.py:42 +#: models_treatments.py:43 msgid "Treatment state types" msgstr "" -#: models_treatments.py:65 +#: models_treatments.py:67 msgid "Downstream find" msgstr "" -#: models_treatments.py:76 +#: models_treatments.py:79 msgctxt "key for text search" msgid "label" msgstr "" -#: models_treatments.py:80 +#: models_treatments.py:83 msgctxt "key for text search" msgid "other-reference" msgstr "" -#: models_treatments.py:88 models_treatments.py:544 +#: models_treatments.py:91 models_treatments.py:555 msgctxt "key for text search" msgid "index" msgstr "" -#: models_treatments.py:96 models_treatments.py:548 +#: models_treatments.py:99 models_treatments.py:559 msgctxt "key for text search" msgid "type" msgstr "" -#: models_treatments.py:127 +#: models_treatments.py:135 msgid "Location where the treatment is done. Target warehouse for a move." msgstr "" -#: models_treatments.py:144 +#: models_treatments.py:152 msgid "Estimated cost" msgstr "" -#: models_treatments.py:146 +#: models_treatments.py:154 msgid "Quoted cost" msgstr "" -#: models_treatments.py:148 +#: models_treatments.py:156 msgid "Realized cost" msgstr "" -#: models_treatments.py:150 +#: models_treatments.py:158 msgid "Insurance cost" msgstr "" -#: models_treatments.py:152 +#: models_treatments.py:160 msgid "Target a basket" msgstr "" -#: models_treatments.py:163 templates/ishtar/sheet_find.html:218 +#: models_treatments.py:171 templates/ishtar/sheet_find.html:171 #: templates/ishtar/sheet_treatmentfile.html:61 msgid "Treatments" msgstr "" -#: models_treatments.py:182 +#: models_treatments.py:190 msgid "TREATMENT" msgstr "" -#: models_treatments.py:238 templates/ishtar/sheet_treatment.html:61 +#: models_treatments.py:249 templates/ishtar/sheet_treatment.html:61 msgid "Downstream finds" msgstr "" -#: models_treatments.py:353 templates/ishtar/sheet_find.html:230 -#: templates/ishtar/sheet_find.html:268 +#: models_treatments.py:364 templates/ishtar/sheet_find.html:183 +#: templates/ishtar/sheet_find.html:221 msgid "Doer" msgstr "" -#: models_treatments.py:354 models_treatments.py:355 +#: models_treatments.py:365 models_treatments.py:366 msgid "Related finds" msgstr "" -#: models_treatments.py:497 +#: models_treatments.py:508 msgid "Is upstream" msgstr "" -#: models_treatments.py:509 +#: models_treatments.py:520 msgid "Treatment request types" msgstr "" -#: models_treatments.py:532 +#: models_treatments.py:543 msgctxt "key for text search" msgid "name" msgstr "" -#: models_treatments.py:536 +#: models_treatments.py:547 msgctxt "key for text search" msgid "reference" msgstr "" -#: models_treatments.py:552 +#: models_treatments.py:563 msgctxt "key for text search" msgid "in-charge" msgstr "" -#: models_treatments.py:556 +#: models_treatments.py:567 msgctxt "key for text search" msgid "applicant" msgstr "" -#: models_treatments.py:560 +#: models_treatments.py:571 msgctxt "key for text search" msgid "applicant-organisation" msgstr "" -#: models_treatments.py:570 +#: models_treatments.py:584 msgid "Internal reference" msgstr "" -#: models_treatments.py:579 +#: models_treatments.py:593 msgid "Person in charge" msgstr "" -#: models_treatments.py:605 +#: models_treatments.py:619 msgid "Treatment requests" msgstr "" -#: templates/ishtar/sheet_find.html:22 -msgid "Find - Administrative ID" +#: templates/ishtar/forms/qa_find_basket.html:22 +msgid "New" msgstr "" -#: templates/ishtar/sheet_find.html:32 -msgid "" -"This sheet has a downstream treatment: it is related to an old version of " -"the find." +#: templates/ishtar/forms/qa_find_basket.html:38 +msgid "Add" msgstr "" -#: templates/ishtar/sheet_find.html:36 -msgid "Associated base finds" +#: templates/ishtar/forms/qa_find_treatment.html:31 +msgid "Associate a treatment" msgstr "" -#: templates/ishtar/sheet_find.html:44 +#: templates/ishtar/sheet_basefind.html:6 msgid "Internal ID" msgstr "" -#: templates/ishtar/sheet_find.html:58 -msgid "Last modified by" -msgstr "" - -#: templates/ishtar/sheet_find.html:70 +#: templates/ishtar/sheet_basefind.html:21 msgid "Discovery date" msgstr "" -#: templates/ishtar/sheet_find.html:73 +#: templates/ishtar/sheet_basefind.html:24 msgid "Discovery year" msgstr "" -#: templates/ishtar/sheet_find.html:76 +#: templates/ishtar/sheet_basefind.html:27 msgid "Discovery date (TPQ)" msgstr "" -#: templates/ishtar/sheet_find.html:100 +#: templates/ishtar/sheet_basefind.html:52 msgid "X:" msgstr "" -#: templates/ishtar/sheet_find.html:101 templates/ishtar/sheet_find.html:103 -#: templates/ishtar/sheet_find.html:105 +#: templates/ishtar/sheet_basefind.html:53 +#: templates/ishtar/sheet_basefind.html:55 +#: templates/ishtar/sheet_basefind.html:57 msgid "error:" msgstr "" -#: templates/ishtar/sheet_find.html:102 +#: templates/ishtar/sheet_basefind.html:54 msgid "Y:" msgstr "" -#: templates/ishtar/sheet_find.html:104 +#: templates/ishtar/sheet_basefind.html:56 msgid "Z:" msgstr "" -#: templates/ishtar/sheet_find.html:108 +#: templates/ishtar/sheet_basefind.html:60 msgid "SRID" msgstr "" -#: templates/ishtar/sheet_find.html:128 +#: templates/ishtar/sheet_basefind.html:75 +msgid "Last modified by" +msgstr "" + +#: templates/ishtar/sheet_find.html:14 +msgid "" +"This sheet has a downstream treatment: it is related to an old version of " +"the find." +msgstr "" + +#: templates/ishtar/sheet_find.html:29 +msgid "Associated base finds" +msgstr "" + +#: templates/ishtar/sheet_find.html:53 msgid "Administrative index" msgstr "" -#: templates/ishtar/sheet_find.html:171 +#: templates/ishtar/sheet_find.html:95 msgid "Checked" msgstr "" -#: templates/ishtar/sheet_find.html:207 +#: templates/ishtar/sheet_find.html:160 msgid "Warehouse" msgstr "" -#: templates/ishtar/sheet_find.html:225 templates/ishtar/sheet_find.html:263 +#: templates/ishtar/sheet_find.html:178 templates/ishtar/sheet_find.html:216 msgid "Year - index" msgstr "" -#: templates/ishtar/sheet_find.html:229 templates/ishtar/sheet_find.html:267 +#: templates/ishtar/sheet_find.html:182 templates/ishtar/sheet_find.html:220 msgid "Related finds (max. 15 displayed)" msgstr "" -#: templates/ishtar/sheet_find.html:255 +#: templates/ishtar/sheet_find.html:208 msgid "Export as CSV" msgstr "" -#: templates/ishtar/sheet_find.html:255 templates/ishtar/sheet_find.html:294 +#: templates/ishtar/sheet_find.html:208 templates/ishtar/sheet_find.html:247 msgid "CSV" msgstr "" -#: templates/ishtar/sheet_find.html:299 +#: templates/ishtar/sheet_find.html:252 msgid "Associated documents" msgstr "" -#: templates/ishtar/sheet_findbasket.html:4 -msgid "Find basket" +#: templates/ishtar/sheet_findbasket.html:19 +#| msgid "Container" +msgid "Content" msgstr "" #: templates/ishtar/sheet_treatment.html:25 @@ -1500,86 +1616,87 @@ msgctxt "Treatment request" msgid "Active" msgstr "" -#: views.py:144 +#: views.py:132 +#| msgid "Last modified by" +msgid "Basket modify" +msgstr "" + +#: views.py:173 msgid "New find" msgstr "" -#: views.py:180 +#: views.py:209 msgid "Find modification" msgstr "" -#: views.py:209 +#: views.py:238 msgid "Find deletion" msgstr "" -#: views.py:222 +#: views.py:251 msgid "New basket" msgstr "" -#: views.py:241 +#: views.py:280 msgid "Manage items in basket" msgstr "" -#: views.py:261 -msgid "Manage basket" -msgstr "" - -#: views.py:352 +#: views.py:389 msgid "Delete basket" msgstr "" -#: views.py:404 +#: views.py:441 msgid "New treatment" msgstr "" -#: views.py:412 +#: views.py:449 msgid "Treatment modification" msgstr "" -#: views.py:429 +#: views.py:466 msgid "Treatment deletion" msgstr "" -#: views.py:436 +#: views.py:473 msgid "Treatment: search administrative act" msgstr "" -#: views.py:445 +#: views.py:482 msgid "Treatment: new administrative act" msgstr "" -#: views.py:455 +#: views.py:492 msgid "Treatment: administrative act modification" msgstr "" -#: views.py:464 +#: views.py:501 msgid "Treatment: administrative act deletion" msgstr "" -#: views.py:497 +#: views.py:534 msgid "New treatment request" msgstr "" -#: views.py:504 +#: views.py:541 msgid "Treatment request modification" msgstr "" -#: views.py:520 +#: views.py:557 msgid "Treatment request deletion" msgstr "" -#: views.py:527 +#: views.py:564 msgid "Treatment request: search administrative act" msgstr "" -#: views.py:537 +#: views.py:574 msgid "Treatment request: new administrative act" msgstr "" -#: views.py:547 +#: views.py:584 msgid "Treatment request: administrative act modification" msgstr "" -#: views.py:556 +#: views.py:593 msgid "Treatment request: administrative act deletion" msgstr "" diff --git a/archaeological_finds/migrations/0035_auto_20181017_1642.py b/archaeological_finds/migrations/0035_auto_20181017_1642.py new file mode 100644 index 000000000..d8515bdb5 --- /dev/null +++ b/archaeological_finds/migrations/0035_auto_20181017_1642.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-10-17 16:42 +from __future__ import unicode_literals + +from django.db import migrations, models +import virtualtime + +from ishtar_common.utils_migrations import reinit_last_modified + + +def migrate_codes(apps, schema_editor): + models = ['Find', 'BaseFind', 'Property', 'Treatment', 'TreatmentFile', + 'Property'] + reinit_last_modified( + apps, 'archaeological_finds', models + ) + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_finds', '0034_auto_20180814_1133'), + ] + + operations = [ + migrations.AddField( + model_name='basefind', + name='last_modified', + field=models.DateTimeField(default=virtualtime.virtual_datetime.now), + ), + migrations.AddField( + model_name='find', + name='last_modified', + field=models.DateTimeField(default=virtualtime.virtual_datetime.now), + ), + migrations.AddField( + model_name='historicalbasefind', + name='last_modified', + field=models.DateTimeField(default=virtualtime.virtual_datetime.now), + ), + migrations.AddField( + model_name='historicalfind', + name='last_modified', + field=models.DateTimeField(default=virtualtime.virtual_datetime.now), + ), + migrations.AddField( + model_name='historicaltreatment', + name='last_modified', + field=models.DateTimeField(default=virtualtime.virtual_datetime.now), + ), + migrations.AddField( + model_name='historicaltreatmentfile', + name='last_modified', + field=models.DateTimeField(default=virtualtime.virtual_datetime.now), + ), + migrations.AddField( + model_name='property', + name='last_modified', + field=models.DateTimeField(default=virtualtime.virtual_datetime.now), + ), + migrations.AddField( + model_name='treatment', + name='last_modified', + field=models.DateTimeField(default=virtualtime.virtual_datetime.now), + ), + migrations.AddField( + model_name='treatmentfile', + name='last_modified', + field=models.DateTimeField(default=virtualtime.virtual_datetime.now), + ), + migrations.RunPython(migrate_codes) + ] diff --git a/archaeological_finds/migrations/0036_auto_20181017_1854.py b/archaeological_finds/migrations/0036_auto_20181017_1854.py new file mode 100644 index 000000000..76a0590b9 --- /dev/null +++ b/archaeological_finds/migrations/0036_auto_20181017_1854.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-10-17 18:54 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_finds', '0035_auto_20181017_1642'), + ] + + operations = [ + migrations.AlterField( + model_name='basefind', + name='last_modified', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='find', + name='last_modified', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='historicalbasefind', + name='last_modified', + field=models.DateTimeField(blank=True, editable=False), + ), + migrations.AlterField( + model_name='historicalfind', + name='last_modified', + field=models.DateTimeField(blank=True, editable=False), + ), + migrations.AlterField( + model_name='historicaltreatment', + name='last_modified', + field=models.DateTimeField(blank=True, editable=False), + ), + migrations.AlterField( + model_name='historicaltreatmentfile', + name='last_modified', + field=models.DateTimeField(blank=True, editable=False), + ), + migrations.AlterField( + model_name='property', + name='last_modified', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='treatment', + name='last_modified', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='treatmentfile', + name='last_modified', + field=models.DateTimeField(auto_now=True), + ), + ] diff --git a/archaeological_finds/migrations/0037_auto_20181018_1756.py b/archaeological_finds/migrations/0037_auto_20181018_1756.py new file mode 100644 index 000000000..0a91b860c --- /dev/null +++ b/archaeological_finds/migrations/0037_auto_20181018_1756.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-10-18 17:56 +from __future__ import unicode_literals + +import django.contrib.postgres.search +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('ishtar_common', '0074_auto_20181017_1854'), + ('archaeological_finds', '0036_auto_20181017_1854'), + ] + + operations = [ + migrations.AlterModelOptions( + name='findbasket', + options={'permissions': (('view_find', 'Can view all Finds'), ('view_own_find', 'Can view own Find'))}, + ), + migrations.AddField( + model_name='findbasket', + name='search_vector', + field=django.contrib.postgres.search.SearchVectorField(blank=True, help_text='Auto filled at save', null=True, verbose_name='Search vector'), + ), + migrations.AddField( + model_name='findbasket', + name='shared_with', + field=models.ManyToManyField(blank=True, related_name='shared_findbaskets', to='ishtar_common.IshtarUser', verbose_name='Shared with'), + ), + 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='Owner'), + ), + migrations.AlterUniqueTogether( + name='findbasket', + unique_together=set([]), + ), + ] diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py index 1ef9d5846..fd22be34c 100644 --- a/archaeological_finds/models_finds.py +++ b/archaeological_finds/models_finds.py @@ -39,10 +39,12 @@ from ishtar_common.models import Document, GeneralType, \ HierarchicalType, BaseHistorizedItem, ShortMenuItem, LightHistorizedItem, \ HistoricalRecords, OwnPerms, Person, Basket, post_save_cache, \ ValueGetter, get_current_profile, IshtarSiteProfile, PRIVATE_FIELDS, \ - SpatialReferenceSystem, BulkUpdatedItem, ExternalIdManager + SpatialReferenceSystem, BulkUpdatedItem, ExternalIdManager, QuickAction, \ + MainItem from archaeological_operations.models import AdministrativeAct, Operation from archaeological_context_records.models import ContextRecord, Dating +from archaeological_warehouse.models import Warehouse class MaterialType(HierarchicalType): @@ -564,9 +566,34 @@ WEIGHT_UNIT = (('g', _(u"g")), ('kg', _(u"kg")),) -class FindBasket(Basket): +class FindBasket(Basket, OwnPerms): items = models.ManyToManyField('Find', blank=True, related_name='basket') + class Meta: + 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), + ] + return actions + class FirstBaseFindView(object): CREATE_SQL = """ @@ -605,7 +632,7 @@ class FBulkView(object): class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, - ShortMenuItem): + MainItem): EXTERNAL_ID_KEY = 'find_external_id' SHOW_URL = 'show-find' SLUG = 'find' @@ -678,11 +705,8 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, 'cr_relation_types': 'base_finds__context_record__', } - RELATIVE_SESSION_NAMES = [ - ('contextrecord', 'base_finds__context_record__pk'), - ('operation', 'base_finds__context_record__operation__pk'), - ('file', 'base_finds__context_record__operation__associated_file__pk') - ] + + DATED_FIELDS = ['last_modified__gte'] BASE_REQUEST = {'downstream_treatment__isnull': True} EXTRA_REQUEST_KEYS = { 'base_finds__context_record': @@ -709,7 +733,7 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, 'base_finds__find__description': 'base_finds__find__description__icontains', 'base_finds__batch': 'base_finds__batch', - 'basket': 'basket', + 'basket_id': 'basket__pk', 'denomination': 'denomination', 'cached_label': 'cached_label__icontains', 'documents__image__isnull': 'documents__image__isnull', @@ -857,7 +881,20 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, ), 'basket': ( pgettext_lazy("key for text search", u"basket"), - 'basket__label__exact' + 'basket__label__iexact' + ), + 'base_finds__context_record__operation__cached_label': ( + pgettext_lazy("key for text search", u"operation"), + 'base_finds__context_record__operation__cached_label__icontains' + ), + 'history_modifier': ( + pgettext_lazy("key for text search", u"last-modified-by"), + 'history_modifier__ishtaruser__person__cached_label__icontains' + ), + 'modified_since': ( + pgettext_lazy("key for text search", u"modified-since"), + 'last_modified__gte' + ), } for v in ALT_NAMES.values(): @@ -876,6 +913,45 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, M2M_SEARCH_VECTORS = [ "datings__period__label", "object_types__label", "integrities__label", "remarkabilities__label", "material_types__label"] + + QA_EDIT = QuickAction( + url="find-qa-bulk-update", icon_class="fa fa-pencil", + text=_(u"Bulk update"), target="many", + rights=['change_find', 'change_own_find']) + + QUICK_ACTIONS = [ + QA_EDIT, + QuickAction( + url="find-qa-basket", icon_class="fa fa-shopping-basket", + text=_(u"Basket"), target="many", + rights=['change_find', 'change_own_find']), + QuickAction( + url="find-qa-packaging", icon_class="fa fa-gift", + text=_(u"Packaging"), target="many", + rights=['change_find', 'change_own_find'], + module='warehouse' + ), + ] + UP_MODEL_QUERY = { + "operation": (pgettext_lazy("key for text search", u"operation"), + 'cached_label'), + "contextrecord": ( + pgettext_lazy("key for text search", u"context-record"), + 'cached_label'), + "warehouse": ( + pgettext_lazy("key for text search", u"location"), + 'name'), + "site": ( + pgettext_lazy("key for text search", u"context-record-site"), + 'cached_label'), + } + RELATIVE_SESSION_NAMES = [ + ('contextrecord', 'base_finds__context_record__pk'), + ('operation', 'base_finds__context_record__operation__pk'), + ('file', 'base_finds__context_record__operation__associated_file__pk'), + ('warehouse', 'container__location__pk'), + ('site', 'base_finds__context_record__archaeological_site__pk') + ] objects = ExternalIdManager() # fields @@ -1084,6 +1160,28 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, return "00" return bf.short_id() + def get_extra_actions(self, request): + """ + For sheet template: return "Add to 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 = super(Find, self).get_extra_actions(request) + actions += [ + (reverse("find-qa-basket", args=[self.pk]), + _(u"Add to basket"), + "fa fa-shopping-basket", "", "", True), + ] + if get_current_profile().warehouse: + actions.append( + (reverse("find-qa-packaging", args=[self.pk]), + _(u"Packaging"), + "fa fa-gift", "", "", True) + ) + return actions + def _get_base_image_path(self): bf = None if self.id: @@ -1263,6 +1361,12 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, @classmethod def get_query_owns(cls, ishtaruser): q = cls._construct_query_own( + 'container__location__', + Warehouse._get_query_owns_dicts(ishtaruser) + ) | cls._construct_query_own( + 'container__responsible__', + Warehouse._get_query_owns_dicts(ishtaruser) + ) | cls._construct_query_own( 'base_finds__context_record__operation__', Operation._get_query_owns_dicts(ishtaruser) ) | cls._construct_query_own('', [ @@ -1337,6 +1441,12 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, profile = get_current_profile() + index = "" + if profile.find_use_index: + index = """|| '-' || + to_char(find_cached_bulk_update.index, 'fm{zeros}') + """.format(zeros=settings.ISHTAR_FINDS_INDEX_ZERO_LEN * "0") + sql = """ UPDATE "archaeological_finds_find" AS f SET cached_label = @@ -1359,8 +1469,7 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, '{main_ope_prefix}' || find_cached_bulk_update.main_ope_code END - || '-' || - to_char(find_cached_bulk_update.index, 'fm{zeros}') + {index} || '{join}' || find_cached_bulk_update.label @@ -1374,7 +1483,7 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms, """.format(main_ope_prefix=profile.operation_prefix, ope_prefix=profile.default_operation_prefix, join=settings.JOINT, filters=filters, - zeros=settings.ISHTAR_FINDS_INDEX_ZERO_LEN * "0") + index=index) with connection.cursor() as c: c.execute(sql, args) diff --git a/archaeological_finds/templates/ishtar/forms/qa_find_basket.html b/archaeological_finds/templates/ishtar/forms/qa_find_basket.html new file mode 100644 index 000000000..77fc2abcd --- /dev/null +++ b/archaeological_finds/templates/ishtar/forms/qa_find_basket.html @@ -0,0 +1,69 @@ +{% extends "ishtar/forms/qa_base.html" %} +{% load i18n inline_formset table_form %} + +{% block main_form %} + {% if form.non_field_errors %} + <div class="alert alert-danger" role="alert"> + {{form.non_field_errors}} + </div> + {% endif %} + + {% for hidden in form.hidden_fields %} + {{hidden}} + {% if hidden.errors %}<div class="invalid-feedback"> + {{ hidden.errors }} + </div>{% endif %} + {% endfor %} + + {% if form.basket %} + <div class="form-row"> + <input type="radio" name="create_or_update" value="create" + id="create-choice" checked > + <label for="create-choice">{% trans "New" %}</label> + </div> + {% else %} + <input type="hidden" name="create_or_update" value="create"> + {% endif %} + <div id="new-basket"> + <div class="form-row"> + {% with form.label as field %} + {% include "blocks/bs_field_snippet.html" %} + {% endwith %} + </div> + </div> + {% if form.basket %} + <div class="form-row"> + <input type="radio" name="create_or_update" value="update" + id="update-choice"> + <label for="update-choice">{% trans "Add" %}</label> + </div> + <div id="update-basket"> + <div class="form-row"> + {% with form.basket as field %} + {% include "blocks/bs_field_snippet.html" %} + {% endwith %} + </div> + </div> + {% endif %} +{% endblock %} + +{% block js %} +var update_form_display = function(){ + if ($("#update-choice:checked").length){ + $("#new-basket").hide(); + $("#update-basket").show(); + } else { + $("#update-basket").hide(); + $("#new-basket").show(); + } +} + +$(document).ready(function(){ + $("#create-choice").click(update_form_display); + $("#update-choice").click(update_form_display); + update_form_display(); +}); + +{% endblock %} + + diff --git a/archaeological_finds/templates/ishtar/forms/qa_find_treatment.html b/archaeological_finds/templates/ishtar/forms/qa_find_treatment.html new file mode 100644 index 000000000..ef3906735 --- /dev/null +++ b/archaeological_finds/templates/ishtar/forms/qa_find_treatment.html @@ -0,0 +1,63 @@ +{% extends "ishtar/forms/qa_base.html" %} +{% load i18n inline_formset table_form %} + +{% block main_form %} + {% if form.non_field_errors %} + <div class="alert alert-danger" role="alert"> + {{form.non_field_errors}} + </div> + {% endif %} + + <h4>{% trans "Finds" %}</h4> + <ul>{% for item in items %} + <li>{{item}}</li>{% endfor %} + </ul> + + <h4>{% trans "Packaging" %}</h4> + {% for hidden in form.hidden_fields %} + {{hidden}} + {% if hidden.errors %}<div class="invalid-feedback"> + {{ hidden.errors }} + </div>{% endif %} + {% endfor %} + <div class="form-row"> + {% with form.container as field %} + {% include "blocks/bs_field_snippet.html" %} + {% endwith %} + </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 %} + <div class="form-row">{% endif %} + {% include "blocks/bs_field_snippet.html" %} + {% if not forloop.counter0|divisibleby:2 %} + </div>{% endif %} + {% endif %} + {% endfor %} + </div> +{% endblock %} + +{% block js %} +var update_form_display = function(){ + if ($("#{{form.create_treatment.auto_id}}:checked").length){ + $("#new-treatment").show(); + } else { + $("#new-treatment").hide(); + } +} + +$(document).ready(function(){ + $("#{{form.create_treatment.auto_id}}").click(update_form_display); + update_form_display(); +}); + +{% endblock %} + + diff --git a/archaeological_finds/templates/ishtar/sheet_find.html b/archaeological_finds/templates/ishtar/sheet_find.html index 43136e357..021ea5652 100644 --- a/archaeological_finds/templates/ishtar/sheet_find.html +++ b/archaeological_finds/templates/ishtar/sheet_find.html @@ -93,12 +93,7 @@ <h3>{% trans "Sheet" %}</h3> <div class='row'> {% trans "Checked" as checked_label %} - {% if item.CHECK_DICT %} - {% field_flex checked_label item.checked|from_dict:item.CHECK_DICT %} - {% endif%} - {% if item.history_object and item.history_object.CHECK_DICT %} - {% field_flex checked_label item.checked|from_dict:item.history_object.CHECK_DICT %} - {% endif%} + {% field_flex checked_label item.checked_type %} {% field_flex "Check date" item.check_date %} {% include "ishtar/blocks/sheet_creation_section.html" %} </div> diff --git a/archaeological_finds/templates/ishtar/sheet_findbasket.html b/archaeological_finds/templates/ishtar/sheet_findbasket.html index b6d4ffd42..3c3ca1d3f 100644 --- a/archaeological_finds/templates/ishtar/sheet_findbasket.html +++ b/archaeological_finds/templates/ishtar/sheet_findbasket.html @@ -1,13 +1,24 @@ {% extends "ishtar/sheet.html" %} {% load i18n window_tables window_header from_dict window_field %} -{% block head_title %}{% trans "Find basket" %}{% endblock %} +{% block head_title %}{% trans "Basket" %} - {{item.label}}{% endblock %} + +{% block toolbar %} +{% window_nav item window_id 'show-findbasket' 'find_basket_modify' %} +{% endblock %} {% block content %} -{% window_nav item window_id 'show-findbasket' 'select_itemsinbasket' %} -<p class="window-refs">{{ item.label|default:"" }}</p> -{% field "Owned by" item.user %} -{% field "Comment" item.comment %} -{% dynamic_table_document finds 'finds_for_ope' 'basket' item.pk 'TABLE_COLS_FOR_OPE' output %} +<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 %} +</div> + +<h3>{% trans "Content" %}</h3> + +{% dynamic_table_document finds 'finds' 'basket_id' item.pk 'TABLE_COLS' output %} + + {% endblock %} diff --git a/archaeological_finds/tests.py b/archaeological_finds/tests.py index 353ebbdbb..a55e075b7 100644 --- a/archaeological_finds/tests.py +++ b/archaeological_finds/tests.py @@ -20,7 +20,7 @@ import json from django.conf import settings -from django.contrib.auth.models import User, Permission +from django.contrib.auth.models import User, Permission, ContentType from django.core.files import File from django.core.files.uploadedfile import SimpleUploadedFile from django.core.urlresolvers import reverse @@ -683,10 +683,12 @@ class FindPermissionTest(FindInit, TestCase): def setUp(self): self.username, self.password, self.user = create_superuser() self.alt_username, self.alt_password, self.alt_user = create_user() + ct_find = ContentType.objects.get(app_label='archaeological_finds', + model='find') self.alt_user.user_permissions.add(Permission.objects.get( - codename='view_own_find')) + codename='view_own_find', content_type=ct_find)) self.alt_user.user_permissions.add(Permission.objects.get( - codename='change_own_find')) + codename='change_own_find', content_type=ct_find)) self.alt_username2, self.alt_password2, self.alt_user2 = create_user( username='luke', password='iamyourfather' ) @@ -747,6 +749,64 @@ class FindPermissionTest(FindInit, TestCase): self.assertEqual(json.loads(response.content)['recordsTotal'], 1) +class FindQATest(FindInit, TestCase): + fixtures = FIND_FIXTURES + model = models.Find + + def setUp(self): + self.create_finds(data_base={"label": u"Find 1"}, force=True) + self.create_finds(data_base={"label": u"Find 2"}, force=True) + self.username, self.password, self.user = create_superuser() + self.alt_username, self.alt_password, self.alt_user = create_user() + self.alt_user.user_permissions.add(Permission.objects.get( + codename='change_find')) + + def test_bulk_update(self): + c = Client() + pks = u"{}-{}".format(self.finds[0].pk, self.finds[1].pk) + response = c.get(reverse('find-qa-bulk-update', args=[pks])) + self.assertRedirects(response, '/') + + c = Client() + c.login(username=self.username, password=self.password) + response = c.get(reverse('find-qa-bulk-update', args=[pks])) + self.assertEqual(response.status_code, 200) + + c = Client() + c.login(username=self.alt_username, password=self.alt_password) + response = c.get(reverse('find-qa-bulk-update', args=[pks])) + self.assertEqual(response.status_code, 200) + + find_0 = self.finds[0] + find_1 = self.finds[1] + base_desc_0 = u"Base description 1" + find_0.description = base_desc_0 + find_0.save() + base_desc_1 = u"Base description 2" + find_1.description = base_desc_1 + find_1.save() + + period = Period.objects.all()[0].pk + self.assertNotIn(period, + [dating.period.pk for dating in find_0.datings.all()]) + self.assertNotIn(period, + [dating.period.pk for dating in find_1.datings.all()]) + extra_desc = u"Extra description" + response = c.post( + reverse('find-qa-bulk-update-confirm', args=[pks]), + {'qa_period': period, 'qa_description': extra_desc} + ) + self.assertRedirects(response, '/success/') + self.assertIn(period, + [dating.period.pk for dating in find_0.datings.all()]) + self.assertIn(period, + [dating.period.pk for dating in find_1.datings.all()]) + self.assertEqual(models.Find.objects.get(pk=find_0.pk).description, + base_desc_0 + u"\n" + extra_desc) + self.assertEqual(models.Find.objects.get(pk=find_1.pk).description, + base_desc_1 + u"\n" + extra_desc) + + class PackagingTest(FindInit, TestCase): fixtures = FIND_FIXTURES model = models.Find diff --git a/archaeological_finds/urls.py b/archaeological_finds/urls.py index 9a71c66d8..588c8d520 100644 --- a/archaeological_finds/urls.py +++ b/archaeological_finds/urls.py @@ -43,34 +43,64 @@ urlpatterns = [ views.find_deletion_wizard), name='find_deletion'), url(r'find_modify/(?P<pk>.+)/$', views.find_modify, name='find_modify'), + url(r'get-findbasket/$', views.get_find_basket, + name='get-findbasket'), + url(r'find_basket_search/(?P<step>.+)?$', + check_rights(['view_find', 'view_own_find'])( + views.basket_search_wizard), name='find_basket_search'), url(r'^find_basket_creation/$', - check_rights(['change_find', 'change_own_find'])( + check_rights(['view_find', 'view_own_find'])( views.NewFindBasketView.as_view()), name='new_findbasket'), + url(r'^find_basket_modification/(?P<step>.+)?$', + check_rights(['view_find', 'view_own_find'])( + views.basket_modify_wizard), + name='find_basket_modification'), + url(r'find_basket_modify/(?P<pk>.+)/$', + views.find_basket_modify, name='find_basket_modify'), url(r'^find_basket_modification_add/$', - check_rights(['change_find', 'change_own_find'])( + check_rights(['view_find', 'view_own_find'])( views.SelectBasketForManagement.as_view()), name='select_findbasketforadd'), url(r'^find_basket_modification_add/(?P<pk>[0-9]+)?/$', - check_rights(['change_find', 'change_own_find'])( + check_rights(['view_find', 'view_own_find'])( views.SelectItemsInBasket.as_view()), name='select_itemsinbasket'), url(r'^find_basket_modification_add_item/$', - check_rights(['change_find', 'change_own_find'])( + check_rights(['view_find', 'view_own_find'])( views.FindBasketAddItemView.as_view()), name='add_iteminbasket'), url(r'^find_basket_modification_delete_item/(?P<basket>[0-9]+)?' r'/(?P<find_pk>[0-9]+)?/$', - check_rights(['change_find', 'change_own_find'])( + check_rights(['view_find', 'view_own_find'])( views.FindBasketDeleteItemView.as_view()), name='delete_iteminbasket'), url(r'^find_basket_list/(?P<pk>[0-9]+)?/$', - check_rights(['change_find', 'change_own_find'])( + check_rights(['view_find', 'view_own_find'])( views.FindBasketListView.as_view()), name='list_iteminbasket'), url(r'^find_basket_deletion/$', - check_rights(['change_find', 'change_own_find'])( + check_rights(['view_find', 'view_own_find'])( views.DeleteFindBasketView.as_view()), name='delete_findbasket'), + url(r'^find-qa-bulk-update/(?P<pks>[0-9-]+)?/$', + check_rights(['change_find', 'change_own_find'])( + views.QAFindForm.as_view()), + name='find-qa-bulk-update'), + url(r'^find-qa-bulk-update/(?P<pks>[0-9-]+)?/confirm/$', + check_rights(['change_find', 'change_own_find'])( + views.QAFindForm.as_view()), + name='find-qa-bulk-update-confirm', kwargs={"confirm": True}), + url(r'^find-qa-basket/(?P<pks>[0-9-]+)?/$', + check_rights(['change_find', 'change_own_find'])( + views.QAFindBasketFormView.as_view()), + name='find-qa-basket'), + + url(r'^find-qa-packaging/(?P<pks>[0-9-]+)?/$', + check_rights(['change_find', 'change_own_find'])( + 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'), @@ -182,7 +212,8 @@ urlpatterns = [ url(r'get-find-shortcut/(?P<type>.+)?$', views.get_find, name='get-find-shortcut', kwargs={'full': 'shortcut'}), - url(r'^show-find/basket-(?P<pk>.+)/(?P<type>.+)?$', views.show_findbasket, + url(r'^show-find/basket-(?:(?P<pk>.+)/(?P<type>.+)?)?$', + views.show_findbasket, name='show-findbasket'), url(r'^display-find/basket-(?P<pk>.+)/$', views.display_findbasket, name='display-findbasket'), diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py index 6c6d9fff9..c340639c5 100644 --- a/archaeological_finds/views.py +++ b/archaeological_finds/views.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Copyright (C) 2010-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> +# Copyright (C) 2010-2018 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -21,7 +21,7 @@ import json from django.core.urlresolvers import reverse from django.db.models import Q -from django.http import HttpResponseRedirect, HttpResponse +from django.http import HttpResponseRedirect, HttpResponse, Http404 from django.shortcuts import redirect from django.utils.translation import ugettext_lazy as _ from django.views.generic import TemplateView @@ -35,7 +35,7 @@ from forms import * from ishtar_common.forms import FinalForm from ishtar_common.models import IshtarUser, get_current_profile from ishtar_common.views import get_autocomplete_generic, IshtarMixin, \ - LoginRequiredMixin + LoginRequiredMixin, QAItemEditForm, QAItemForm from ishtar_common.views_item import display_item, get_item, show_item, \ revert_item, get_autocomplete_item from wizards import * @@ -113,6 +113,36 @@ show_findbasket = show_item(models.FindBasket, 'findbasket') display_findbasket = display_item(models.FindBasket, show_url='show-find/basket-') +get_find_basket = get_item( + models.FindBasket, 'get_findbasket', 'findbasket', +) + +basket_search_wizard = FindBasketSearch.as_view( + [('selec-find_basket_search', FindBasketFormSelection)], + label=_(u"Basket search"), + url_name='find_basket_search', +) + +basket_modify_wizard = FindBasketEditWizard.as_view( + [ + ('selec-find_basket_modification', FindBasketFormSelection), + ('basket-find_basket_modification', FindBasketForm), + ('final-find_basket_modification', FinalForm) + ], + label=_(u"Basket modify"), + url_name='find_basket_modification', +) + + +def find_basket_modify(request, pk): + basket_modify_wizard(request) + key = 'selec-find_basket_modification' + FindBasketEditWizard.session_set_value( + request, key, 'pk', pk, reset=True) + return redirect( + reverse('find_basket_modification', + kwargs={'step': 'basket-find_basket_modification'})) + def check_preservation_module(self): return get_current_profile().preservation @@ -234,6 +264,16 @@ class NewFindBasketView(IshtarMixin, LoginRequiredMixin, CreateView): return HttpResponseRedirect(self.get_success_url()) +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) + except models.FindBasket.DoesNotExist: + raise PermissionDenied + + class SelectBasketForManagement(IshtarMixin, LoginRequiredMixin, FormView): template_name = 'ishtar/form.html' form_class = SelectFindBasketForm @@ -255,7 +295,8 @@ class SelectBasketForManagement(IshtarMixin, LoginRequiredMixin, FormView): form.cleaned_data['basket'])) -class SelectItemsInBasket(IshtarMixin, LoginRequiredMixin, TemplateView): +class SelectItemsInBasket(OwnBasket, IshtarMixin, LoginRequiredMixin, + TemplateView): template_name = 'ishtar/manage_basket.html' page_name = _(u"Manage basket") @@ -263,11 +304,9 @@ class SelectItemsInBasket(IshtarMixin, LoginRequiredMixin, TemplateView): context = super(SelectItemsInBasket, self).get_context_data( *args, **kwargs) self.user = IshtarUser.objects.get(pk=self.request.user.pk) - try: - self.basket = models.FindBasket.objects.get( - pk=self.kwargs['pk'], user=self.user) - except models.FindBasket.DoesNotExist: - raise PermissionDenied + self.basket = self.get_basket( + user=self.user, pk=self.kwargs['pk'] + ) context['basket'] = self.basket if get_current_profile().warehouse: context['form'] = MultipleFindFormSelectionWarehouseModule() @@ -296,18 +335,17 @@ class FindBasketAddItemView(IshtarMixin, LoginRequiredMixin, FormView): return HttpResponseRedirect(self.get_success_url(basket)) -class FindBasketListView(IshtarMixin, LoginRequiredMixin, TemplateView): +class FindBasketListView(OwnBasket, IshtarMixin, LoginRequiredMixin, + TemplateView): template_name = 'ishtar/basket_list.html' def get_context_data(self, *args, **kwargs): context = super(FindBasketListView, self).get_context_data( *args, **kwargs) self.user = IshtarUser.objects.get(pk=self.request.user.pk) - try: - self.basket = models.FindBasket.objects.get( - pk=self.kwargs['pk'], user=self.user) - except models.FindBasket.DoesNotExist: - raise PermissionDenied + self.basket = self.get_basket( + user=self.user, pk=self.kwargs['pk'] + ) context['basket'] = self.basket context['item_url'] = '/'.join( reverse(models.Find.SHOW_URL, args=[1]).split('/')[:-1]) @@ -316,7 +354,8 @@ class FindBasketListView(IshtarMixin, LoginRequiredMixin, TemplateView): return context -class FindBasketDeleteItemView(IshtarMixin, LoginRequiredMixin, TemplateView): +class FindBasketDeleteItemView(OwnBasket, IshtarMixin, LoginRequiredMixin, + TemplateView): template_name = 'ishtar/simple_form.html' def get_success_url(self, basket): @@ -330,14 +369,13 @@ class FindBasketDeleteItemView(IshtarMixin, LoginRequiredMixin, TemplateView): pk=self.kwargs['find_pk']) except models.Find.DoesNotExist: raise PermissionDenied - try: - basket = models.FindBasket.objects.get( - pk=self.kwargs['basket'], user=ishtaruser) - except models.FindBasket.DoesNotExist: - raise PermissionDenied + + basket = self.get_basket( + user=ishtaruser, pk=self.kwargs['basket'] + ) if not user.is_superuser and \ - not ishtaruser.has_right('change_find') and \ - not (ishtaruser.has_right('change_own_find') + not ishtaruser.has_right('view_find') and \ + not (ishtaruser.has_right('view_own_find') and find.is_own(user)): raise PermissionDenied basket.items.remove(find) @@ -594,3 +632,48 @@ def reset_wizards(request): 'treatmentfle_admacttreatmentfle_deletion'), ): wizard_class.session_reset(request, url_name) + + +class QAFindForm(QAItemEditForm): + model = models.Find + form_class = QAFindFormMulti + + +class QAFindBasketFormView(QAItemForm): + template_name = 'ishtar/forms/qa_find_basket.html' + model = models.Find + form_class = QAFindBasketForm + page_name = _(u"Basket") + modal_size = "small" + + def get_quick_action(self): + return models.Find.QUICK_ACTIONS[1] + + def get_form_kwargs(self): + kwargs = super(QAFindBasketFormView, self).get_form_kwargs() + kwargs['user'] = self.request.user + return kwargs + + def form_valid(self, form): + form.save(self.items) + return HttpResponseRedirect(reverse("success")) + + +class QAFindTreatmentFormView(QAItemForm): + template_name = 'ishtar/forms/qa_find_treatment.html' + model = models.Find + form_class = QAFindTreatmentForm + page_name = _(u"Packaging") + + def get_quick_action(self): + return models.Find.QUICK_ACTIONS[2] + + def get_form_kwargs(self): + kwargs = super(QAFindTreatmentFormView, self).get_form_kwargs() + kwargs['user'] = self.request.user + kwargs['prefix'] = "qa-packaging" + return kwargs + + def form_valid(self, form): + form.save(self.items, self.request.user) + return HttpResponseRedirect(reverse("success")) diff --git a/archaeological_finds/wizards.py b/archaeological_finds/wizards.py index 6486e5da1..0e0fe80e1 100644 --- a/archaeological_finds/wizards.py +++ b/archaeological_finds/wizards.py @@ -230,3 +230,16 @@ class TreatmentFileEditAdministrativeActWizard( def get_associated_item(self, dct): return self.get_current_object().treatment_file + + +class FindBasketSearch(SearchWizard): + model = models.FindBasket + + +class FindBasketWizard(Wizard): + model = models.FindBasket + wizard_done_window = reverse_lazy('show-findbasket') + + +class FindBasketEditWizard(FindBasketWizard): + edit = True |
