summaryrefslogtreecommitdiff
path: root/archaeological_finds
diff options
context:
space:
mode:
Diffstat (limited to 'archaeological_finds')
-rw-r--r--archaeological_finds/forms.py278
-rw-r--r--archaeological_finds/forms_treatments.py87
-rw-r--r--archaeological_finds/ishtar_menu.py25
-rw-r--r--archaeological_finds/locale/django.pot947
-rw-r--r--archaeological_finds/migrations/0035_auto_20181017_1642.py72
-rw-r--r--archaeological_finds/migrations/0036_auto_20181017_1854.py60
-rw-r--r--archaeological_finds/migrations/0037_auto_20181018_1756.py41
-rw-r--r--archaeological_finds/models_finds.py135
-rw-r--r--archaeological_finds/templates/ishtar/forms/qa_find_basket.html69
-rw-r--r--archaeological_finds/templates/ishtar/forms/qa_find_treatment.html63
-rw-r--r--archaeological_finds/templates/ishtar/sheet_find.html7
-rw-r--r--archaeological_finds/templates/ishtar/sheet_findbasket.html23
-rw-r--r--archaeological_finds/tests.py66
-rw-r--r--archaeological_finds/urls.py47
-rw-r--r--archaeological_finds/views.py129
-rw-r--r--archaeological_finds/wizards.py13
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 >
+ &nbsp;<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">
+ &nbsp;<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 }}&nbsp;<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