diff options
Diffstat (limited to 'archaeological_warehouse')
-rw-r--r-- | archaeological_warehouse/admin.py | 48 | ||||
-rw-r--r-- | archaeological_warehouse/forms.py | 665 | ||||
-rw-r--r-- | archaeological_warehouse/ishtar_menu.py | 136 | ||||
-rw-r--r-- | archaeological_warehouse/lookups.py | 26 | ||||
-rw-r--r-- | archaeological_warehouse/models.py | 1049 | ||||
-rw-r--r-- | archaeological_warehouse/serializers.py | 134 | ||||
-rw-r--r-- | archaeological_warehouse/tests.py | 682 | ||||
-rw-r--r-- | archaeological_warehouse/urls.py | 294 | ||||
-rw-r--r-- | archaeological_warehouse/views.py | 395 | ||||
-rw-r--r-- | archaeological_warehouse/wizards.py | 116 |
10 files changed, 1995 insertions, 1550 deletions
diff --git a/archaeological_warehouse/admin.py b/archaeological_warehouse/admin.py index b29c2a8e3..c186950d3 100644 --- a/archaeological_warehouse/admin.py +++ b/archaeological_warehouse/admin.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> @@ -34,17 +34,19 @@ class DivisionInline(admin.TabularInline): class WarehouseAdmin(HistorizedObjectAdmin): - list_display = ('name', 'warehouse_type', 'town') - list_filter = ('warehouse_type',) - search_fields = ('name', 'town') + list_display = ("name", "warehouse_type", "town") + list_filter = ("warehouse_type",) + search_fields = ("name", "town") model = models.Warehouse ajax_form_dict = HistorizedObjectAdmin.AJAX_FORM_DICT.copy() - ajax_form_dict.update({ - 'town': 'town', - 'precise_town': 'town', - 'person_in_charge': 'person', - 'organization': 'organization' - }) + ajax_form_dict.update( + { + "town": "town", + "precise_town": "town", + "person_in_charge": "person", + "organization": "organization", + } + ) form = make_ajax_form(model, ajax_form_dict) inlines = [DivisionInline] exclude = ["documents", "main_image"] @@ -54,8 +56,15 @@ admin_site.register(models.Warehouse, WarehouseAdmin) class ContainerTypeAdmin(GeneralTypeAdmin): - LIST_DISPLAY = ('label', 'reference', 'stationary', 'length', 'width', - 'height', 'volume') + LIST_DISPLAY = ( + "label", + "reference", + "stationary", + "length", + "width", + "height", + "volume", + ) model = models.ContainerType list_filter = ("available", "stationary") @@ -64,17 +73,16 @@ admin_site.register(models.ContainerType, ContainerTypeAdmin) class ContainerAdmin(HistorizedObjectAdmin): - list_display = ('reference', 'location', 'container_type',) + list_display = ( + "reference", + "location", + "container_type", + ) list_filter = ("container_type",) model = models.Container - readonly_fields = HistorizedObjectAdmin.readonly_fields + [ - 'history_date' - ] + readonly_fields = HistorizedObjectAdmin.readonly_fields + ["history_date"] ajax_form_dict = HistorizedObjectAdmin.AJAX_FORM_DICT.copy() - ajax_form_dict.update({ - 'location': 'warehouse', - 'responsible': 'warehouse' - }) + ajax_form_dict.update({"location": "warehouse", "responsible": "warehouse"}) form = make_ajax_form(model, ajax_form_dict) exclude = ["documents", "main_image"] diff --git a/archaeological_warehouse/forms.py b/archaeological_warehouse/forms.py index 68adc66c1..9bc6de5b0 100644 --- a/archaeological_warehouse/forms.py +++ b/archaeological_warehouse/forms.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2010-2017 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> @@ -26,68 +26,106 @@ from django.conf import settings from django.forms.formsets import formset_factory from ishtar_common.utils import ugettext_lazy as _ -from ishtar_common.models import Person, valid_id, Town, \ - SpatialReferenceSystem, Organization, valid_ids, person_type_pks_lazy +from ishtar_common.models import ( + Person, + valid_id, + Town, + SpatialReferenceSystem, + Organization, + valid_ids, + person_type_pks_lazy, +) from archaeological_operations.models import ArchaeologicalSite from archaeological_context_records.models import ContextRecord -from archaeological_finds.models import TreatmentType, FindBasket, \ - MaterialType, ObjectType, IntegrityType, RemarkabilityType, \ - ConservatoryState, AlterationType, AlterationCauseType, \ - TreatmentEmergencyType +from archaeological_finds.models import ( + TreatmentType, + FindBasket, + MaterialType, + ObjectType, + IntegrityType, + RemarkabilityType, + ConservatoryState, + AlterationType, + AlterationCauseType, + TreatmentEmergencyType, +) from . import models from ishtar_common import widgets from archaeological_operations.widgets import OAWidget from bootstrap_datepicker.widgets import DatePicker -from ishtar_common.forms import name_validator, reverse_lazy, \ - get_form_selection, ManageOldType, FinalForm, FormSet, \ - CustomForm, FieldType, DocumentItemSelect, FormHeader, TableSelect, \ - CustomFormSearch, MultiSearchForm, LockForm, QAForm -from ishtar_common.forms_common import get_town_field, MergeForm, ManualMerge,\ - MergeIntoForm -from archaeological_finds.forms import FindMultipleFormSelection, \ - SelectFindBasketForm +from ishtar_common.forms import ( + name_validator, + reverse_lazy, + get_form_selection, + ManageOldType, + FinalForm, + FormSet, + CustomForm, + FieldType, + DocumentItemSelect, + FormHeader, + TableSelect, + CustomFormSearch, + MultiSearchForm, + LockForm, + QAForm, +) +from ishtar_common.forms_common import ( + get_town_field, + MergeForm, + ManualMerge, + MergeIntoForm, +) +from archaeological_finds.forms import FindMultipleFormSelection, SelectFindBasketForm def get_warehouse_field(label=_("Warehouse"), required=True): # !FIXME hard_link, reverse_lazy doen't seem to work with formsets - url = "/" + settings.URL_PATH + 'autocomplete-warehouse' + url = "/" + settings.URL_PATH + "autocomplete-warehouse" widget = widgets.JQueryAutoComplete(url, associated_model=models.Warehouse) - return forms.IntegerField(widget=widget, label=label, required=required, - validators=[valid_id(models.Warehouse)]) + return forms.IntegerField( + widget=widget, + label=label, + required=required, + validators=[valid_id(models.Warehouse)], + ) class SelectedDivisionForm(ManageOldType, forms.Form): form_label = _("Default divisions") - base_model = 'associated_division' - associated_models = {'container_type': models.ContainerType, - 'associated_division': models.WarehouseDivisionLink} + base_model = "associated_division" + associated_models = { + "container_type": models.ContainerType, + "associated_division": models.WarehouseDivisionLink, + } container_type = forms.ChoiceField( - label=_("Division type"), choices=(), - validators=[valid_id(models.ContainerType)]) - order = forms.IntegerField(label=_("Order"), min_value=0, - required=False) + label=_("Division type"), + choices=(), + validators=[valid_id(models.ContainerType)], + ) + order = forms.IntegerField(label=_("Order"), min_value=0, required=False) def __init__(self, *args, **kwargs): super(SelectedDivisionForm, self).__init__(*args, **kwargs) - self.fields['container_type'].choices = \ - models.ContainerType.get_types( - dct={"stationary": True}, - initial=self.init_data.get('container_type')) + self.fields["container_type"].choices = models.ContainerType.get_types( + dct={"stationary": True}, initial=self.init_data.get("container_type") + ) class DivisionFormSet(FormSet): def clean(self): """Checks that no divisions are duplicated.""" - self.check_duplicate(('container_type',), - _("There are identical divisions.")) - self.check_duplicate(('order',), _("Order fields must be different."), - check_null=True) + self.check_duplicate(("container_type",), _("There are identical divisions.")) + self.check_duplicate( + ("order",), _("Order fields must be different."), check_null=True + ) SelectedDivisionFormset = formset_factory( - SelectedDivisionForm, can_delete=True, formset=DivisionFormSet) + SelectedDivisionForm, can_delete=True, formset=DivisionFormSet +) SelectedDivisionFormset.form_label = _("Divisions") SelectedDivisionFormset.form_admin_name = _("Warehouse - 020 - Divisions") SelectedDivisionFormset.form_slug = "warehouse-020-divisions" @@ -99,45 +137,54 @@ class WarehouseSelect(CustomForm, TableSelect): form_slug = "warehouse-001-search" search_vector = forms.CharField( - label=_("Full text search"), widget=widgets.SearchWidget( - 'archaeological-warehouse', 'warehouse' - )) + label=_("Full text search"), + widget=widgets.SearchWidget("archaeological-warehouse", "warehouse"), + ) name = forms.CharField(label=_("Name")) warehouse_type = forms.ChoiceField(label=_("Warehouse type"), choices=[]) town = get_town_field(label=_("Town")) def __init__(self, *args, **kwargs): super(WarehouseSelect, self).__init__(*args, **kwargs) - self.fields['warehouse_type'].choices = \ - models.WarehouseType.get_types() - self.fields['warehouse_type'].help_text = \ - models.WarehouseType.get_help() + self.fields["warehouse_type"].choices = models.WarehouseType.get_types() + self.fields["warehouse_type"].help_text = models.WarehouseType.get_help() class WarehouseFormSelection(LockForm, CustomFormSearch): SEARCH_AND_SELECT = True form_label = _("Warehouse search") - associated_models = {'pk': models.Warehouse} - currents = {'pk': models.Warehouse} + associated_models = {"pk": models.Warehouse} + currents = {"pk": models.Warehouse} pk = forms.IntegerField( - label="", required=False, + label="", + required=False, widget=widgets.DataTable( - reverse_lazy('get-warehouse'), - WarehouseSelect, models.Warehouse, gallery=True, map=True), - validators=[valid_id(models.Warehouse)]) + reverse_lazy("get-warehouse"), + WarehouseSelect, + models.Warehouse, + gallery=True, + map=True, + ), + validators=[valid_id(models.Warehouse)], + ) class WarehouseFormMultiSelection(LockForm, MultiSearchForm): form_label = _("Warehouse search") - associated_models = {'pks': models.Warehouse} + associated_models = {"pks": models.Warehouse} pk = forms.CharField( - label="", required=False, + label="", + required=False, widget=widgets.DataTable( - reverse_lazy('get-warehouse'), - WarehouseSelect, models.Warehouse, gallery=True, map=True, - multiple_select=True + reverse_lazy("get-warehouse"), + WarehouseSelect, + models.Warehouse, + gallery=True, + map=True, + multiple_select=True, ), - validators=[valid_ids(models.Warehouse)]) + validators=[valid_ids(models.Warehouse)], + ) class WarehouseForm(CustomForm, ManageOldType, forms.Form): @@ -146,93 +193,98 @@ class WarehouseForm(CustomForm, ManageOldType, forms.Form): form_admin_name = _("Warehouse - 010 - General") form_slug = "warehouse-010-general" associated_models = { - 'warehouse_type': models.WarehouseType, - 'person_in_charge': Person, - 'organization': Organization, - 'precise_town': Town, - 'spatial_reference_system': SpatialReferenceSystem + "warehouse_type": models.WarehouseType, + "person_in_charge": Person, + "organization": Organization, + "precise_town": Town, + "spatial_reference_system": SpatialReferenceSystem, } - name = forms.CharField(label=_("Name"), max_length=200, - validators=[name_validator]) - warehouse_type = forms.ChoiceField(label=_("Warehouse type"), - choices=[]) + name = forms.CharField(label=_("Name"), max_length=200, validators=[name_validator]) + warehouse_type = forms.ChoiceField(label=_("Warehouse type"), choices=[]) organization = forms.IntegerField( label=_("Organization"), widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-organization'), - associated_model=Organization, new=True), + reverse_lazy("autocomplete-organization"), + associated_model=Organization, + new=True, + ), validators=[valid_id(Organization)], - required=False) + required=False, + ) person_in_charge = forms.IntegerField( label=_("Person in charge"), widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-person'), - associated_model=Person, new=True), + reverse_lazy("autocomplete-person"), associated_model=Person, new=True + ), validators=[valid_id(Person)], - required=False) + required=False, + ) create_organization = forms.BooleanField( - label=_("Create a new organization from this warehouse"), - required=False + label=_("Create a new organization from this warehouse"), required=False ) - comment = forms.CharField(label=_("Comment"), widget=forms.Textarea, - required=False) - HEADERS['address'] = FormHeader( - _("Address"), collapse=True, + comment = forms.CharField(label=_("Comment"), widget=forms.Textarea, required=False) + HEADERS["address"] = FormHeader( + _("Address"), + collapse=True, help_message=_( "Only fill the following fields if no organization is provided or " "if the address of the warehouse is different from the one of the " "organization. If a new organization is created from this " - "warehouse, the following fields are used for the organization.")) - address = forms.CharField(label=_("Address"), widget=forms.Textarea, - required=False) - address_complement = forms.CharField(label=_("Address complement"), - widget=forms.Textarea, required=False) - postal_code = forms.CharField(label=_("Postal code"), max_length=10, - required=False) - town = forms.CharField(label=_("Town (freeform)"), max_length=150, - required=False) + "warehouse, the following fields are used for the organization." + ), + ) + address = forms.CharField(label=_("Address"), widget=forms.Textarea, required=False) + address_complement = forms.CharField( + label=_("Address complement"), widget=forms.Textarea, required=False + ) + postal_code = forms.CharField(label=_("Postal code"), max_length=10, required=False) + town = forms.CharField(label=_("Town (freeform)"), max_length=150, required=False) precise_town = get_town_field(required=False) - country = forms.CharField(label=_("Country"), max_length=30, - required=False) + country = forms.CharField(label=_("Country"), max_length=30, required=False) phone = forms.CharField(label=_("Phone"), max_length=18, required=False) - mobile_phone = forms.CharField(label=_("Mobile phone"), max_length=18, - required=False) - HEADERS['x'] = FormHeader(_("Coordinates")) + mobile_phone = forms.CharField( + label=_("Mobile phone"), max_length=18, required=False + ) + HEADERS["x"] = FormHeader(_("Coordinates")) x = forms.FloatField(label=_("X"), required=False) y = forms.FloatField(label=_("Y"), required=False) spatial_reference_system = forms.ChoiceField( - label=_("Spatial Reference System"), required=False, choices=[]) + label=_("Spatial Reference System"), required=False, choices=[] + ) TYPES = [ - FieldType('warehouse_type', models.WarehouseType), - FieldType('spatial_reference_system', SpatialReferenceSystem) + FieldType("warehouse_type", models.WarehouseType), + FieldType("spatial_reference_system", SpatialReferenceSystem), ] def __init__(self, *args, **kwargs): - if 'limits' in kwargs: - kwargs.pop('limits') + if "limits" in kwargs: + kwargs.pop("limits") super(WarehouseForm, self).__init__(*args, **kwargs) def clean(self): - if self.cleaned_data.get("organization", None) and \ - self.cleaned_data.get("create_organization", None): + if self.cleaned_data.get("organization", None) and self.cleaned_data.get( + "create_organization", None + ): raise forms.ValidationError( - _("A new organization is not created if an organization is " - "selected.")) + _( + "A new organization is not created if an organization is " + "selected." + ) + ) return self.cleaned_data def save(self, user): dct = self.cleaned_data - dct['history_modifier'] = user - dct['warehouse_type'] = models.WarehouseType.objects.get( - pk=dct['warehouse_type']) - if 'person_in_charge' in dct and dct['person_in_charge']: - dct['person_in_charge'] = Person.objects.get( - pk=dct['person_in_charge']) - if 'organization' in dct and dct['organization']: - dct['organization'] = Organization.objects.get( - pk=dct['organization']) + dct["history_modifier"] = user + dct["warehouse_type"] = models.WarehouseType.objects.get( + pk=dct["warehouse_type"] + ) + if "person_in_charge" in dct and dct["person_in_charge"]: + dct["person_in_charge"] = Person.objects.get(pk=dct["person_in_charge"]) + if "organization" in dct and dct["organization"]: + dct["organization"] = Organization.objects.get(pk=dct["organization"]) if not dct.get("spatial_reference_system", None): dct.pop("spatial_reference_system") create_orga = dct.pop("create_organization") @@ -261,54 +313,65 @@ class ContainerForm(CustomForm, ManageOldType, forms.Form): form_admin_name = _("Container - 010 - General") form_slug = "container-010-general" file_upload = True - associated_models = {'container_type': models.ContainerType, - 'location': models.Warehouse, - 'responsibility': models.Warehouse, - 'parent': models.Container} + associated_models = { + "container_type": models.ContainerType, + "location": models.Warehouse, + "responsibility": models.Warehouse, + "parent": models.Container, + } reference = forms.CharField(label=_("Ref."), max_length=200) - old_reference = forms.CharField(label=_("Old reference"), required=False, - max_length=200) + old_reference = forms.CharField( + label=_("Old reference"), required=False, max_length=200 + ) container_type = forms.ChoiceField(label=_("Container type"), choices=[]) location = forms.IntegerField( label=_("Current location (warehouse)"), widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-warehouse'), - associated_model=models.Warehouse, new=True), - validators=[valid_id(models.Warehouse)]) + reverse_lazy("autocomplete-warehouse"), + associated_model=models.Warehouse, + new=True, + ), + validators=[valid_id(models.Warehouse)], + ) parent = forms.IntegerField( label=_("Parent container"), widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-container'), + reverse_lazy("autocomplete-container"), associated_model=models.Container, - dynamic_limit=['location']), + dynamic_limit=["location"], + ), validators=[valid_id(models.Container)], - required=False + required=False, ) responsibility = forms.IntegerField( label=_("Responsibility"), widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-warehouse'), - associated_model=models.Warehouse, new=True), + reverse_lazy("autocomplete-warehouse"), + associated_model=models.Warehouse, + new=True, + ), validators=[valid_id(models.Warehouse)], - help_text=_("Automatically attached to the current warehouse if not " - "filled."), - required=False + help_text=_( + "Automatically attached to the current warehouse if not " "filled." + ), + required=False, ) weight = forms.FloatField( label=_("Measured weight (g)"), - widget=widgets.GramKilogramWidget, required=False) - comment = forms.CharField(label=_("Comment"), - widget=forms.Textarea, required=False) + widget=widgets.GramKilogramWidget, + required=False, + ) + comment = forms.CharField(label=_("Comment"), widget=forms.Textarea, required=False) TYPES = [ - FieldType('container_type', models.ContainerType), + FieldType("container_type", models.ContainerType), ] class Media: - js = ('forms/container.js',) + js = ("forms/container.js",) def __init__(self, *args, **kwargs): - if 'limits' in kwargs: - kwargs.pop('limits') + if "limits" in kwargs: + kwargs.pop("limits") super(ContainerForm, self).__init__(*args, **kwargs) def clean_parent(self): @@ -316,46 +379,54 @@ class ContainerForm(CustomForm, ManageOldType, forms.Form): return warehouse_id = self.cleaned_data.get("location") q = models.Container.objects.filter( - pk=self.cleaned_data["parent"], - location_id=warehouse_id) + pk=self.cleaned_data["parent"], location_id=warehouse_id + ) if not q.count(): raise forms.ValidationError( - _("The parent container is not attached to the same " - "warehouse.")) + _("The parent container is not attached to the same " "warehouse.") + ) return self.cleaned_data["parent"] def clean(self): cleaned_data = self.cleaned_data warehouse = cleaned_data.get("location") q = models.Container.objects.filter( - reference=cleaned_data.get("reference"), location__pk=warehouse, + reference=cleaned_data.get("reference"), + location__pk=warehouse, container_type_id=cleaned_data.get("container_type"), - parent_id=cleaned_data.get("parent") + parent_id=cleaned_data.get("parent"), ) pk = None - if 'pk' in cleaned_data and cleaned_data['pk']: - pk = int(cleaned_data['pk']) + if "pk" in cleaned_data and cleaned_data["pk"]: + pk = int(cleaned_data["pk"]) q = q.exclude(pk=pk) if q.count(): - raise forms.ValidationError(_("This reference already exists for " - "this warehouse.")) - if pk and cleaned_data.get("parent", None) and pk == int( - cleaned_data.get("parent")): - raise forms.ValidationError(_("A container cannot be a parent of " - "himself.")) + raise forms.ValidationError( + _("This reference already exists for " "this warehouse.") + ) + if ( + pk + and cleaned_data.get("parent", None) + and pk == int(cleaned_data.get("parent")) + ): + raise forms.ValidationError( + _("A container cannot be a parent of " "himself.") + ) return cleaned_data def save(self, user): dct = self.cleaned_data - dct['history_modifier'] = user - dct['container_type'] = models.ContainerType.objects.get( - pk=dct['container_type']) - dct['location'] = models.Warehouse.objects.get(pk=dct['location']) + dct["history_modifier"] = user + dct["container_type"] = models.ContainerType.objects.get( + pk=dct["container_type"] + ) + dct["location"] = models.Warehouse.objects.get(pk=dct["location"]) if dct.get("parent", None): - dct['parent'] = models.Container.objects.get(pk=dct['parent']) + dct["parent"] = models.Container.objects.get(pk=dct["parent"]) if dct.get("responsibility", None): - dct['responsibility'] = models.Warehouse.objects.get( - pk=dct['responsibility']) + dct["responsibility"] = models.Warehouse.objects.get( + pk=dct["responsibility"] + ) new_item = models.Container(**dct) new_item.save() return new_item @@ -368,15 +439,15 @@ class ContainerModifyForm(ContainerForm): def __init__(self, *args, **kwargs): super(ContainerModifyForm, self).__init__(*args, **kwargs) fields = OrderedDict() - idx = self.fields.pop('index') + idx = self.fields.pop("index") reordered = False for key, value in self.fields.items(): fields[key] = value - if key == 'container_type': - fields['index'] = idx + if key == "container_type": + fields["index"] = idx reordered = True if not reordered: - fields['index'] = idx + fields["index"] = idx self.fields = fields def clean(self): @@ -396,16 +467,15 @@ class ContainerModifyForm(ContainerForm): if not q.count(): cleaned_data["index"] = 1 else: - cleaned_data["index"] = int(q.aggregate( - Max("index"))["index__max"]) + 1 + cleaned_data["index"] = int(q.aggregate(Max("index"))["index__max"]) + 1 else: - q = models.Container.objects.filter( - index=index, location__pk=warehouse) - if 'pk' in cleaned_data and cleaned_data['pk']: - q = q.exclude(pk=int(cleaned_data['pk'])) + q = models.Container.objects.filter(index=index, location__pk=warehouse) + if "pk" in cleaned_data and cleaned_data["pk"]: + q = q.exclude(pk=int(cleaned_data["pk"])) if q.count(): - raise forms.ValidationError(_("This ID already exists for " - "this warehouse.")) + raise forms.ValidationError( + _("This ID already exists for " "this warehouse.") + ) return cleaned_data @@ -415,12 +485,11 @@ class ContainerSelect(DocumentItemSelect): form_slug = "container-001-search" search_vector = forms.CharField( - label=_("Full text search"), widget=widgets.SearchWidget( - 'archaeological-warehouse', 'container' - )) + label=_("Full text search"), + widget=widgets.SearchWidget("archaeological-warehouse", "container"), + ) location_name = get_warehouse_field(label=_("Warehouse")) - responsibility_name = get_warehouse_field( - label=_("Warehouse (responsibility)")) + responsibility_name = get_warehouse_field(label=_("Warehouse (responsibility)")) container_type = forms.ChoiceField(label=_("Container type"), choices=[]) reference = forms.CharField(label=_("Ref.")) old_reference = forms.CharField(label=_("Old reference")) @@ -432,75 +501,76 @@ class ContainerSelect(DocumentItemSelect): archaeological_sites = forms.IntegerField( label=_("Archaeological site (attached to the operation)"), widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-archaeologicalsite'), - associated_model=ArchaeologicalSite), - validators=[valid_id(ArchaeologicalSite)]) + reverse_lazy("autocomplete-archaeologicalsite"), + associated_model=ArchaeologicalSite, + ), + validators=[valid_id(ArchaeologicalSite)], + ) archaeological_sites_name = forms.CharField( label=_("Archaeological site name (attached to the operation)") ) archaeological_sites_context_record = forms.IntegerField( label=_("Archaeological site (attached to the context record)"), widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-archaeologicalsite'), - associated_model=ArchaeologicalSite), - validators=[valid_id(ArchaeologicalSite)]) + reverse_lazy("autocomplete-archaeologicalsite"), + associated_model=ArchaeologicalSite, + ), + validators=[valid_id(ArchaeologicalSite)], + ) archaeological_sites_context_record_name = forms.CharField( label=_("Archaeological site name (attached to the context record)") ) - code_patriarche = forms.IntegerField(label=_("Operation - Code PATRIARCHE"), - widget=OAWidget) + code_patriarche = forms.IntegerField( + label=_("Operation - Code PATRIARCHE"), widget=OAWidget + ) operation_town = get_town_field(label=_("Operation - town")) operation_scientist = forms.IntegerField( widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-person-permissive'), - associated_model=Person), - label=_("Operation - Scientist")) + reverse_lazy("autocomplete-person-permissive"), associated_model=Person + ), + label=_("Operation - Scientist"), + ) context_record = forms.IntegerField( label=_("Context record"), widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-contextrecord'), - associated_model=ContextRecord), - validators=[valid_id(ContextRecord)]) + reverse_lazy("autocomplete-contextrecord"), associated_model=ContextRecord + ), + validators=[valid_id(ContextRecord)], + ) find_label = forms.CharField(label=_("Find - Label")) find_denomination = forms.CharField(label=_("Find - Denomination")) description = forms.CharField(label=_("Find - Description")) material_types = forms.IntegerField( label=_("Material type"), widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-materialtype'), - associated_model=MaterialType), + reverse_lazy("autocomplete-materialtype"), associated_model=MaterialType + ), ) object_types = forms.IntegerField( label=_("Object type"), widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-objecttype'), - associated_model=ObjectType), - ) - integrities = forms.ChoiceField(label=_("Integrity / interest"), - choices=[]) - remarkabilities = forms.ChoiceField(label=_("Remarkability"), - choices=[]) - conservatory_state = forms.ChoiceField(label=_("Conservatory state"), - choices=[]) - alterations = forms.ChoiceField( - label=_("Alteration"), choices=[]) - alteration_causes = forms.ChoiceField( - label=_("Alteration cause"), choices=[]) + reverse_lazy("autocomplete-objecttype"), associated_model=ObjectType + ), + ) + integrities = forms.ChoiceField(label=_("Integrity / interest"), choices=[]) + remarkabilities = forms.ChoiceField(label=_("Remarkability"), choices=[]) + conservatory_state = forms.ChoiceField(label=_("Conservatory state"), choices=[]) + alterations = forms.ChoiceField(label=_("Alteration"), choices=[]) + alteration_causes = forms.ChoiceField(label=_("Alteration cause"), choices=[]) preservation_to_considers = forms.ChoiceField( - choices=[], label=_("Preservation type")) - treatment_emergency = forms.ChoiceField( - choices=[], label=_("Treatment emergency") + choices=[], label=_("Preservation type") ) + treatment_emergency = forms.ChoiceField(choices=[], label=_("Treatment emergency")) TYPES = [ - FieldType('integrities', IntegrityType), - FieldType('remarkabilities', RemarkabilityType), - FieldType('conservatory_state', ConservatoryState), - FieldType('alterations', AlterationType), - FieldType('alteration_causes', AlterationCauseType), - FieldType('preservation_to_considers', TreatmentType), - FieldType('treatment_emergency', TreatmentEmergencyType), - FieldType('container_type', models.ContainerType) + FieldType("integrities", IntegrityType), + FieldType("remarkabilities", RemarkabilityType), + FieldType("conservatory_state", ConservatoryState), + FieldType("alterations", AlterationType), + FieldType("alteration_causes", AlterationCauseType), + FieldType("preservation_to_considers", TreatmentType), + FieldType("treatment_emergency", TreatmentEmergencyType), + FieldType("container_type", models.ContainerType), ] SITE_KEYS = { "archaeological_sites": "attached-to-operation", @@ -511,27 +581,45 @@ class ContainerSelect(DocumentItemSelect): ContainerFormSelection = get_form_selection( - 'ContainerFormSelection', _("Container search"), 'container', - models.Container, ContainerSelect, 'get-container', - _("You should select a container."), new=True, + "ContainerFormSelection", + _("Container search"), + "container", + models.Container, + ContainerSelect, + "get-container", + _("You should select a container."), + new=True, new_message=_("Add a new container"), - base_form_select=(LockForm, CustomFormSearch) + base_form_select=(LockForm, CustomFormSearch), ) MainContainerFormSelection = get_form_selection( - 'ContainerFormSelection', _("Container search"), 'pk', - models.Container, ContainerSelect, 'get-container', - _("You should select a container."), gallery=True, map=True, - base_form_select=CustomFormSearch + "ContainerFormSelection", + _("Container search"), + "pk", + models.Container, + ContainerSelect, + "get-container", + _("You should select a container."), + gallery=True, + map=True, + base_form_select=CustomFormSearch, ) MainContainerFormMultiSelection = get_form_selection( - 'ContainerFormSelection', _("Container search"), 'pks', - models.Container, ContainerSelect, 'get-container', - _("You should select a container."), gallery=True, map=True, + "ContainerFormSelection", + _("Container search"), + "pks", + models.Container, + ContainerSelect, + "get-container", + _("You should select a container."), + gallery=True, + map=True, alt_pk_field="pk", - multi=True, base_form_select=(LockForm, MultiSearchForm) + multi=True, + base_form_select=(LockForm, MultiSearchForm), ) @@ -540,21 +628,25 @@ class MergeContainerForm(MergeForm): model = models.Container fields = [] - FROM_KEY = 'from_container' - TO_KEY = 'to_container' + FROM_KEY = "from_container" + TO_KEY = "to_container" class ContainerMergeFormSelection(ManualMerge, forms.Form): SEARCH_AND_SELECT = True form_label = _("Container to merge") - associated_models = {'to_merge': models.Container} - currents = {'to_merge': models.Container} + associated_models = {"to_merge": models.Container} + currents = {"to_merge": models.Container} to_merge = forms.CharField( - label="", required=False, + label="", + required=False, widget=widgets.DataTable( - reverse_lazy('get-container'), ContainerSelect, + reverse_lazy("get-container"), + ContainerSelect, models.Container, - multiple_select=True,),) + multiple_select=True, + ), + ) class ContainerMergeIntoForm(MergeIntoForm): @@ -563,19 +655,21 @@ class ContainerMergeIntoForm(MergeIntoForm): class BasePackagingForm(SelectFindBasketForm): form_label = _("Packaging") - associated_models = {'treatment_type': TreatmentType, - 'person': Person, - 'location': models.Warehouse, - 'basket': FindBasket} + associated_models = { + "treatment_type": TreatmentType, + "person": Person, + "location": models.Warehouse, + "basket": FindBasket, + } person = forms.IntegerField( label=_("Packager"), widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-person'), - associated_model=Person, new=True), - validators=[valid_id(Person)]) + reverse_lazy("autocomplete-person"), associated_model=Person, new=True + ), + validators=[valid_id(Person)], + ) start_date = forms.DateField( - label=_("Date"), required=False, widget=DatePicker, - initial=datetime.date.today + label=_("Date"), required=False, widget=DatePicker, initial=datetime.date.today ) @@ -592,52 +686,54 @@ class QAContainerFormMulti(QAForm): PREFIX = "qa" form_admin_name = _("Container - Quick action - Modify") form_slug = "container-quickaction-modify" - base_models = ['qaparent', 'qacontainer_type', - 'qalocation', 'qaresponsibility'] + base_models = ["qaparent", "qacontainer_type", "qalocation", "qaresponsibility"] associated_models = { - 'qaparent': models.Container, - 'qacontainer_type': models.ContainerType, - 'qalocation': models.Warehouse, - 'qaresponsibility': models.Warehouse, + "qaparent": models.Container, + "qacontainer_type": models.ContainerType, + "qalocation": models.Warehouse, + "qaresponsibility": models.Warehouse, } MULTI = True - REPLACE_FIELDS = [ - "qaparent", - "qacontainer_type", - "qalocation", - "qaresponsibility" - ] + REPLACE_FIELDS = ["qaparent", "qacontainer_type", "qalocation", "qaresponsibility"] HEADERS = { "qalocation": FormHeader(_("Warehouse")), } SINGLE_FIELDS = [] - qacontainer_type = forms.ChoiceField(label=_("Container type"), - required=False, choices=[]) + qacontainer_type = forms.ChoiceField( + label=_("Container type"), required=False, choices=[] + ) qalocation = forms.IntegerField( label=_("Location"), widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-warehouse'), - associated_model=models.Warehouse), - validators=[valid_id(models.Warehouse)], required=False) + reverse_lazy("autocomplete-warehouse"), associated_model=models.Warehouse + ), + validators=[valid_id(models.Warehouse)], + required=False, + ) qaresponsibility = forms.IntegerField( label=_("Responsibility"), widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-warehouse'), - associated_model=models.Warehouse), - validators=[valid_id(models.Warehouse)], required=False) + reverse_lazy("autocomplete-warehouse"), associated_model=models.Warehouse + ), + validators=[valid_id(models.Warehouse)], + required=False, + ) qaparent = forms.IntegerField( label=_("Parent"), widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-container'), - dynamic_limit=['qalocation'], - associated_model=models.Container), - validators=[valid_id(models.Container)], required=False) + reverse_lazy("autocomplete-container"), + dynamic_limit=["qalocation"], + associated_model=models.Container, + ), + validators=[valid_id(models.Container)], + required=False, + ) TYPES = [ - FieldType('qacontainer_type', models.ContainerType), + FieldType("qacontainer_type", models.ContainerType), ] def __init__(self, *args, **kwargs): @@ -668,43 +764,50 @@ class QAContainerFormMulti(QAForm): def clean(self): new_values = {} if self.cleaned_data.get("qacontainer_type", None): - new_values["container_type_id"] = self.cleaned_data[ - "qacontainer_type"] + new_values["container_type_id"] = self.cleaned_data["qacontainer_type"] if self.cleaned_data.get("qalocation", None): - new_values["location_id"] = self.cleaned_data[ - "qalocation"] + new_values["location_id"] = self.cleaned_data["qalocation"] if self.cleaned_data.get("qaparent", None): - new_values["parent_id"] = self.cleaned_data[ - "qaparent"] + new_values["parent_id"] = self.cleaned_data["qaparent"] new_tuples = [] for item in self.items: - if new_values.get("parent_id", None) and int( - new_values["parent_id"]) == item.pk: + if ( + new_values.get("parent_id", None) + and int(new_values["parent_id"]) == item.pk + ): raise forms.ValidationError( - _("A container cannot be a parent of himself.")) + _("A container cannot be a parent of himself.") + ) vals = { "container_type_id": item.container_type_id, "location_id": item.location_id, "parent_id": item.parent_id, - "reference": item.reference.strip() + "reference": item.reference.strip(), } vals.update(new_values) - c_tuple = (vals["location_id"], vals["container_type_id"], - vals["parent_id"], vals["reference"]) + c_tuple = ( + vals["location_id"], + vals["container_type_id"], + vals["parent_id"], + vals["reference"], + ) q = models.Container.objects.filter(**vals).exclude(id=item.id) if c_tuple in new_tuples or q.count(): parent = models.Container.objects.get(pk=vals["parent_id"]) raise forms.ValidationError( str( - _("Cannot do this changes because it would generate " - "many containers with location: {}, container type: " - "{}, parent: {} {} and reference: {}. " - "Merge these containers first?")).format( + _( + "Cannot do this changes because it would generate " + "many containers with location: {}, container type: " + "{}, parent: {} {} and reference: {}. " + "Merge these containers first?" + ) + ).format( models.Warehouse.objects.get(pk=vals["location_id"]), - models.ContainerType.objects.get( - pk=vals["container_type_id"]), - parent.container_type, parent.reference, - vals["reference"] + models.ContainerType.objects.get(pk=vals["container_type_id"]), + parent.container_type, + parent.reference, + vals["reference"], ) ) return self.cleaned_data diff --git a/archaeological_warehouse/ishtar_menu.py b/archaeological_warehouse/ishtar_menu.py index fe012d214..3064671e6 100644 --- a/archaeological_warehouse/ishtar_menu.py +++ b/archaeological_warehouse/ishtar_menu.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> @@ -27,51 +27,95 @@ from . import models MENU_SECTIONS = [ - (80, SectionItem('warehouse', _("Warehouse"), - profile_restriction='warehouse', - css='menu-warehouse', - childs=[ - MenuItem('warehouse_search', _("Search"), - model=models.Warehouse, - access_controls=['view_warehouse', 'view_own_warehouse']), - MenuItem('warehouse_creation', _("Creation"), - model=models.Warehouse, - access_controls=['add_warehouse',]), - MenuItem('warehouse_modification', _("Modification"), - model=models.Warehouse, - access_controls=['change_warehouse',]), - MenuItem('warehouse_deletion', _("Deletion"), - model=models.Warehouse, - access_controls=['change_warehouse',]), - SectionItem( - 'containers', _("Containers"), - childs=[ - MenuItem('container_search', _("Search"), - model=models.Warehouse, - access_controls=['view_container', - 'view_own_container']), - MenuItem('container_creation', _("Creation"), - model=models.Warehouse, - access_controls=['add_container', - 'add_own_container']), - MenuItem('container_modification', _("Modification"), - model=models.Warehouse, - access_controls=['change_container', - 'change_own_container']), - MenuItem( - 'container-merge', _("Automatic merge"), - model=models.Container, - access_controls=['administrator']), - MenuItem( - 'container-manual-merge', _("Manual merge"), - model=models.Container, - access_controls=['administrator']), - MenuItem('container_deletion', _("Deletion"), - model=models.Warehouse, - access_controls=['change_container', - 'change_own_container']), - ]) - ])) + ( + 80, + SectionItem( + "warehouse", + _("Warehouse"), + profile_restriction="warehouse", + css="menu-warehouse", + childs=[ + MenuItem( + "warehouse_search", + _("Search"), + model=models.Warehouse, + access_controls=["view_warehouse", "view_own_warehouse"], + ), + MenuItem( + "warehouse_creation", + _("Creation"), + model=models.Warehouse, + access_controls=[ + "add_warehouse", + ], + ), + MenuItem( + "warehouse_modification", + _("Modification"), + model=models.Warehouse, + access_controls=[ + "change_warehouse", + ], + ), + MenuItem( + "warehouse_deletion", + _("Deletion"), + model=models.Warehouse, + access_controls=[ + "change_warehouse", + ], + ), + SectionItem( + "containers", + _("Containers"), + childs=[ + MenuItem( + "container_search", + _("Search"), + model=models.Warehouse, + access_controls=["view_container", "view_own_container"], + ), + MenuItem( + "container_creation", + _("Creation"), + model=models.Warehouse, + access_controls=["add_container", "add_own_container"], + ), + MenuItem( + "container_modification", + _("Modification"), + model=models.Warehouse, + access_controls=[ + "change_container", + "change_own_container", + ], + ), + MenuItem( + "container-merge", + _("Automatic merge"), + model=models.Container, + access_controls=["administrator"], + ), + MenuItem( + "container-manual-merge", + _("Manual merge"), + model=models.Container, + access_controls=["administrator"], + ), + MenuItem( + "container_deletion", + _("Deletion"), + model=models.Warehouse, + access_controls=[ + "change_container", + "change_own_container", + ], + ), + ], + ), + ], + ), + ) ] """ MenuItem('warehouse_inventory', _("Inventory"), diff --git a/archaeological_warehouse/lookups.py b/archaeological_warehouse/lookups.py index ea06db3c5..9b221ea5b 100644 --- a/archaeological_warehouse/lookups.py +++ b/archaeological_warehouse/lookups.py @@ -9,22 +9,21 @@ from django.utils.html import escape from archaeological_warehouse import models -@register('container') +@register("container") class ContainerLookup(LookupChannel): model = models.Container def get_query(self, q, request): query = Q() - for term in q.strip().split(' '): + for term in q.strip().split(" "): subquery = ( - Q(reference__icontains=term) | - Q(container_type__label__icontains=term) | - Q(cached_label__icontains=term) | - Q(responsible__name__icontains=term) + Q(reference__icontains=term) + | Q(container_type__label__icontains=term) + | Q(cached_label__icontains=term) + | Q(responsible__name__icontains=term) ) query &= subquery - return self.model.objects.filter(query).order_by( - 'cached_label')[:20] + return self.model.objects.filter(query).order_by("cached_label")[:20] def format_match(self, obj): return escape(force_text(obj.cached_label)) @@ -33,19 +32,16 @@ class ContainerLookup(LookupChannel): return "<span class='ajax-label'>%s</span>" % item.cached_label -@register('warehouse') +@register("warehouse") class WarehouseLookup(LookupChannel): model = models.Warehouse def get_query(self, q, request): query = Q() - for term in q.strip().split(' '): - subquery = ( - Q(warehouse_type__label=term) | - Q(name__icontains=term) - ) + for term in q.strip().split(" "): + subquery = Q(warehouse_type__label=term) | Q(name__icontains=term) query &= subquery - return self.model.objects.filter(query).order_by('name')[:20] + return self.model.objects.filter(query).order_by("name")[:20] def format_item_display(self, item): return "<span class='ajax-label'>%s</span>" % item.name diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py index fc0184990..29615b6ef 100644 --- a/archaeological_warehouse/models.py +++ b/archaeological_warehouse/models.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2012-2017 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> @@ -27,24 +27,38 @@ from django.contrib.postgres.indexes import GinIndex from django.core.exceptions import ObjectDoesNotExist from django.core.urlresolvers import reverse from django.db.models import Q, Max, Count -from django.db.models.signals import post_save, post_delete, m2m_changed, \ - pre_delete +from django.db.models.signals import post_save, post_delete, m2m_changed, pre_delete from django.template.defaultfilters import slugify from ishtar_common.utils import ugettext_lazy as _, pgettext_lazy from django.apps import apps -from ishtar_common.data_importer import post_importer_action, \ - pre_importer_action +from ishtar_common.data_importer import post_importer_action, pre_importer_action from ishtar_common.model_managers import ExternalIdManager, UUIDModelManager from ishtar_common.models import ValueGetter, get_current_profile -from ishtar_common.models_common import GeneralType, \ - LightHistorizedItem, OwnPerms, Address, post_save_cache, \ - DashboardFormItem, document_attached_changed, SearchAltName, \ - DynamicRequest, GeoItem, CompleteIdentifierItem, SearchVectorConfig, \ - DocumentItem, QuickAction, MainItem, Merge +from ishtar_common.models_common import ( + GeneralType, + LightHistorizedItem, + OwnPerms, + Address, + post_save_cache, + DashboardFormItem, + document_attached_changed, + SearchAltName, + DynamicRequest, + GeoItem, + CompleteIdentifierItem, + SearchVectorConfig, + DocumentItem, + QuickAction, + MainItem, + Merge, +) from ishtar_common.model_merging import merge_model_objects -from ishtar_common.utils import cached_label_changed, \ - cached_label_and_geo_changed, get_generated_id +from ishtar_common.utils import ( + cached_label_changed, + cached_label_and_geo_changed, + get_generated_id, +) from ishtar_common.data_importer import ImporterError @@ -81,7 +95,7 @@ class DivisionContainer(DashboardFormItem): def number_divisions(self): q = { self.BASE_QUERY_LOCATION + "__id": self.pk, - "container_type__stationary": True + "container_type__stationary": True, } return Container.objects.filter(**q).count() @@ -89,7 +103,7 @@ class DivisionContainer(DashboardFormItem): def number_containers(self): q = { self.BASE_QUERY_LOCATION + "__id": self.pk, - "container_type__stationary": False + "container_type__stationary": False, } return Container.objects.filter(**q).count() @@ -111,27 +125,30 @@ class DivisionContainer(DashboardFormItem): @property def number_of_containers(self): - return Container.objects.filter( - **{self.BASE_QUERY_LOCATION: self}).count() + return Container.objects.filter(**{self.BASE_QUERY_LOCATION: self}).count() def _number_of_finds_by_place(self): Find = apps.get_model("archaeological_finds", "Find") return self._number_of_items_by_place( - Find, division_key='inside_container__container__') + Find, division_key="inside_container__container__" + ) @property def number_of_finds_by_place(self, update=False): - return self._get_or_set_stats('_number_of_finds_by_place', update, - expected_type=list) + return self._get_or_set_stats( + "_number_of_finds_by_place", update, expected_type=list + ) def _number_of_containers_by_place(self): return self._number_of_items_by_place( - ContainerTree, 'container_parent__', 'container__children') + ContainerTree, "container_parent__", "container__children" + ) @property def number_of_containers_by_place(self, update=False): - return self._get_or_set_stats('_number_of_containers_by_place', update, - expected_type=list) + return self._get_or_set_stats( + "_number_of_containers_by_place", update, expected_type=list + ) def _get_divisions(self, current_path, remaining_division, depth=0): if not remaining_division: @@ -144,7 +161,7 @@ class DivisionContainer(DashboardFormItem): base_q = Container.objects.filter(**{query_location: self}) q = base_q - if self.BASE_QUERY_LOCATION == 'location': + if self.BASE_QUERY_LOCATION == "location": exclude = "parent_" for idx in range(depth): exclude += "_parent_" @@ -161,31 +178,28 @@ class DivisionContainer(DashboardFormItem): if not q.count(): return [current_path] q = q.values( - 'id', 'reference', 'container_type__label', 'container_type_id' - ).order_by('container_type__label', 'reference') + "id", "reference", "container_type__label", "container_type_id" + ).order_by("container_type__label", "reference") for ref in q.all(): - if ref['reference'] == old_ref and \ - ref["container_type__label"] == ct: + if ref["reference"] == old_ref and ref["container_type__label"] == ct: continue - old_ref = ref['reference'] + old_ref = ref["reference"] ct = ref["container_type__label"] cpath = current_path[:] lbl = self.DIVISION_TEMPLATE.format( - id=ref["id"], container=ref["container_type__label"], - ref=ref['reference']) + id=ref["id"], + container=ref["container_type__label"], + ref=ref["reference"], + ) cpath.append((ref["id"], lbl)) query = { - "containers__parent__reference": ref['reference'], - "containers__parent__container_type_id": ref[ - "container_type_id"], - "containers__" + self.BASE_QUERY_LOCATION: self + "containers__parent__reference": ref["reference"], + "containers__parent__container_type_id": ref["container_type_id"], + "containers__" + self.BASE_QUERY_LOCATION: self, } - remaining_division = list( - ContainerType.objects.filter( - **query).distinct()) - for r in self._get_divisions(cpath, remaining_division[:], - depth + 1): + remaining_division = list(ContainerType.objects.filter(**query).distinct()) + for r in self._get_divisions(cpath, remaining_division[:], depth + 1): res.append(r) return res @@ -195,13 +209,10 @@ class DivisionContainer(DashboardFormItem): :return: ordered list of available paths. Each path is a list of tuple with the container type and the full reference. """ - q = { - "containers__" + self.BASE_QUERY_LOCATION: self - } - if self.BASE_QUERY_LOCATION == 'location': + q = {"containers__" + self.BASE_QUERY_LOCATION: self} + if self.BASE_QUERY_LOCATION == "location": q["containers__parent"] = None - top_divisions = list( - ContainerType.objects.filter(**q).distinct()) + top_divisions = list(ContainerType.objects.filter(**q).distinct()) divisions = self._get_divisions([], top_divisions) return divisions @@ -218,9 +229,7 @@ class DivisionContainer(DashboardFormItem): for idx, p in enumerate(reversed(cpath)): container_id, __ = p div_key = division_key + "parent__" * idx - attrs = { - div_key + "id": container_id - } + attrs = {div_key + "id": container_id} q = q.filter(**attrs) if count_filter: q = q.filter(**{count_filter: None}) @@ -236,10 +245,10 @@ class DivisionContainer(DashboardFormItem): final_res.append(current_res[:]) current_res = [] depth = len(path) - if path[-1] == '-': + if path[-1] == "-": continue path = [k[1] for k in path] - path = path + ['' for __ in range(len_divisions - len(path))] + path = path + ["" for __ in range(len_divisions - len(path))] current_res.append((path, nb)) final_res.append(current_res[:]) return final_res @@ -249,25 +258,32 @@ class WarehouseType(GeneralType): class Meta: verbose_name = _("Warehouse type") verbose_name_plural = _("Warehouse types") - ordering = ('label',) + ordering = ("label",) post_save.connect(post_save_cache, sender=WarehouseType) post_delete.connect(post_save_cache, sender=WarehouseType) -NO_DIVISION_ERROR = _( - "The division number {} has not been set for the warehouse {}.") +NO_DIVISION_ERROR = _("The division number {} has not been set for the warehouse {}.") -class Warehouse(Address, DocumentItem, GeoItem, CompleteIdentifierItem, - OwnPerms, MainItem, DivisionContainer, ValueGetter): - SLUG = 'warehouse' +class Warehouse( + Address, + DocumentItem, + GeoItem, + CompleteIdentifierItem, + OwnPerms, + MainItem, + DivisionContainer, + ValueGetter, +): + SLUG = "warehouse" APP = "archaeological-warehouse" MODEL = "warehouse" - SHOW_URL = 'show-warehouse' - DELETE_URL = 'delete-warehouse' - TABLE_COLS = ['name', 'warehouse_type__label'] + SHOW_URL = "show-warehouse" + DELETE_URL = "delete-warehouse" + TABLE_COLS = ["name", "warehouse_type__label"] NEW_QUERY_ENGINE = True BASE_SEARCH_VECTORS = [ SearchVectorConfig("name"), @@ -278,7 +294,7 @@ class Warehouse(Address, DocumentItem, GeoItem, CompleteIdentifierItem, SearchVectorConfig("comment", "local"), ] COL_LABELS = { - 'warehouse_type__label': _("Type"), + "warehouse_type__label": _("Type"), } EXTRA_REQUEST_KEYS = { @@ -288,28 +304,28 @@ class Warehouse(Address, DocumentItem, GeoItem, CompleteIdentifierItem, } # alternative names of fields for searches ALT_NAMES = { - 'name': SearchAltName( - pgettext_lazy("key for text search", "name"), - 'name__iexact' + "name": SearchAltName( + pgettext_lazy("key for text search", "name"), "name__iexact" ), - 'warehouse_type': SearchAltName( + "warehouse_type": SearchAltName( pgettext_lazy("key for text search", "type"), - 'warehouse_type__label__iexact' + "warehouse_type__label__iexact", + ), + "town": SearchAltName( + pgettext_lazy("key for text search", "town"), + "precise_town__cached_label__iexact", ), - 'town': - SearchAltName( - pgettext_lazy("key for text search", "town"), - 'precise_town__cached_label__iexact' - ), } GEO_LABEL = "name" DOWN_MODEL_UPDATE = ["containers"] CACHED_LABELS = [] QA_LOCK = QuickAction( - url="warehouse-qa-lock", icon_class="fa fa-lock", - text=_("Lock/Unlock"), target="many", - rights=['change_warehouse', 'change_own_warehouse'] + url="warehouse-qa-lock", + icon_class="fa fa-lock", + text=_("Lock/Unlock"), + target="many", + rights=["change_warehouse", "change_own_warehouse"], ) QUICK_ACTIONS = [QA_LOCK] @@ -317,35 +333,53 @@ class Warehouse(Address, DocumentItem, GeoItem, CompleteIdentifierItem, uuid = models.UUIDField(default=uuid.uuid4) name = models.CharField(_("Name"), max_length=200) - warehouse_type = models.ForeignKey(WarehouseType, - verbose_name=_("Warehouse type")) + warehouse_type = models.ForeignKey(WarehouseType, verbose_name=_("Warehouse type")) person_in_charge = models.ForeignKey( - "ishtar_common.Person", on_delete=models.SET_NULL, - related_name='warehouse_in_charge', - verbose_name=_("Person in charge"), null=True, blank=True) + "ishtar_common.Person", + on_delete=models.SET_NULL, + related_name="warehouse_in_charge", + verbose_name=_("Person in charge"), + null=True, + blank=True, + ) organization = models.ForeignKey( - "ishtar_common.Organization", blank=True, null=True, - related_name='warehouses', verbose_name=_("Organization"), - on_delete=models.SET_NULL) + "ishtar_common.Organization", + blank=True, + null=True, + related_name="warehouses", + verbose_name=_("Organization"), + on_delete=models.SET_NULL, + ) comment = models.TextField(_("Comment"), blank=True, default="") associated_divisions = models.ManyToManyField( - 'WarehouseDivision', verbose_name=_("Divisions"), blank=True, - through='WarehouseDivisionLink' + "WarehouseDivision", + verbose_name=_("Divisions"), + blank=True, + through="WarehouseDivisionLink", ) documents = models.ManyToManyField( - "ishtar_common.Document", related_name='warehouses', + "ishtar_common.Document", + related_name="warehouses", verbose_name=_("Documents"), - blank=True) + blank=True, + ) main_image = models.ForeignKey( - "ishtar_common.Document", related_name='main_image_warehouses', + "ishtar_common.Document", + related_name="main_image_warehouses", on_delete=models.SET_NULL, - verbose_name=_("Main image"), blank=True, null=True) + verbose_name=_("Main image"), + blank=True, + null=True, + ) external_id = models.TextField(_("External ID"), blank=True, default="") auto_external_id = models.BooleanField( - _("External ID is set automatically"), default=False) + _("External ID is set automatically"), default=False + ) max_division_number = models.IntegerField( - _("Maximum number of divisions"), default=0, - help_text=_("Automatically generated")) + _("Maximum number of divisions"), + default=0, + help_text=_("Automatically generated"), + ) SUB_ADDRESSES = ["organization", "person_in_charge"] class Meta: @@ -359,7 +393,7 @@ class Warehouse(Address, DocumentItem, GeoItem, CompleteIdentifierItem, ("delete_own_warehouse", "Can delete own Warehouse"), ) indexes = [ - GinIndex(fields=['data']), + GinIndex(fields=["data"]), ] def __str__(self): @@ -373,8 +407,7 @@ class Warehouse(Address, DocumentItem, GeoItem, CompleteIdentifierItem, :param place: place number :return: container type, other location or None, None """ - q = WarehouseDivisionLink.objects.filter( - warehouse=self).order_by('order') + q = WarehouseDivisionLink.objects.filter(warehouse=self).order_by("order") previous_container_types = [] for idx, division_link in enumerate(q.all()): if idx == place: @@ -388,6 +421,7 @@ class Warehouse(Address, DocumentItem, GeoItem, CompleteIdentifierItem, @post_importer_action def add_localisations(self, context, value): self._add_localisations(context, value) + add_localisations.post_save = True def _add_localisations(self, context, value, return_errors=False): @@ -415,17 +449,20 @@ class Warehouse(Address, DocumentItem, GeoItem, CompleteIdentifierItem, values = value.split(";") - divisions = list(WarehouseDivisionLink.objects.filter( - warehouse=self).order_by('order')) + divisions = list( + WarehouseDivisionLink.objects.filter(warehouse=self).order_by("order") + ) parent = None for idx, value in enumerate(values): if idx >= len(divisions): if return_errors: return str( - _("{} values for only {} default divisions set for " - "warehouse {}")).format( - len(values), len(divisions), self.name) + _( + "{} values for only {} default divisions set for " + "warehouse {}" + ) + ).format(len(values), len(divisions), self.name) return value = value.replace(TMP_SEMI_COLON, ";").strip() if not value or value == "-": @@ -434,7 +471,8 @@ class Warehouse(Address, DocumentItem, GeoItem, CompleteIdentifierItem, location=self, reference=value, container_type_id=divisions[idx].container_type_id, - parent=parent) + parent=parent, + ) if created and import_object: parent.imports.add(import_object) @@ -443,7 +481,7 @@ class Warehouse(Address, DocumentItem, GeoItem, CompleteIdentifierItem, return self.name def natural_key(self): - return (self.uuid, ) + return (self.uuid,) def _get_base_image_path(self): return "{}/{}".format(self.SLUG, self.external_id) @@ -462,8 +500,7 @@ class Warehouse(Address, DocumentItem, GeoItem, CompleteIdentifierItem, orga_type = q.all()[0] else: orga_type, __ = OrganizationType.objects.get_or_create( - txt_idx="undefined", - defaults={"label": _("Undefined")} + txt_idx="undefined", defaults={"label": _("Undefined")} ) dct_orga["organization_type"] = orga_type dct_orga["name"] = self.name @@ -491,53 +528,52 @@ class Warehouse(Address, DocumentItem, GeoItem, CompleteIdentifierItem, @property def default_location_types(self): return [ - wd.container_type.label - for wd in WarehouseDivisionLink.objects.filter( - warehouse=self).order_by('order').all() if wd.container_type + wd.container_type.label + for wd in WarehouseDivisionLink.objects.filter(warehouse=self) + .order_by("order") + .all() + if wd.container_type ] @property def associated_filename(self): - return datetime.date.today().strftime('%Y-%m-%d') + '-' + \ - slugify(str(self)) + return datetime.date.today().strftime("%Y-%m-%d") + "-" + slugify(str(self)) @classmethod def get_query_owns(cls, ishtaruser): - return cls._construct_query_own( - '', cls._get_query_owns_dicts(ishtaruser)) + return cls._construct_query_own("", cls._get_query_owns_dicts(ishtaruser)) @classmethod def _get_query_owns_dicts(cls, ishtaruser): - return [{'person_in_charge__ishtaruser': ishtaruser}] + return [{"person_in_charge__ishtaruser": ishtaruser}] def merge(self, item, keep_old=False): # do not recreate missing divisions available_divisions = [ - wd.division - for wd in WarehouseDivisionLink.objects.filter(warehouse=self) + wd.division for wd in WarehouseDivisionLink.objects.filter(warehouse=self) ] for container in list(item.containers.all()): container.location = self container.save() - for loca in ContainerLocalisation.objects.filter( - container=container).all(): + for loca in ContainerLocalisation.objects.filter(container=container).all(): if loca.division.division in available_divisions: div = WarehouseDivisionLink.objects.get( - warehouse=self, - division=loca.division.division + warehouse=self, division=loca.division.division ) ContainerLocalisation.objects.create( - container=container, division=div, - reference=loca.reference + container=container, division=div, reference=loca.reference ) loca.delete() container.save() # force label regeneration for container in list(item.containers.all()): - if Container.objects.filter(index=container.index, - location=self).count(): - container.index = Container.objects.filter( - location=self).exclude(id=container.id).all().aggregate( - Max("index"))["index__max"] + 1 + if Container.objects.filter(index=container.index, location=self).count(): + container.index = ( + Container.objects.filter(location=self) + .exclude(id=container.id) + .all() + .aggregate(Max("index"))["index__max"] + + 1 + ) container.location = self container.save() for wdiv in WarehouseDivisionLink.objects.filter(warehouse=item).all(): @@ -550,7 +586,7 @@ class Warehouse(Address, DocumentItem, GeoItem, CompleteIdentifierItem, self.skip_history_when_saving = True if not self.external_id or self.auto_external_id: - external_id = get_generated_id('warehouse_external_id', self) + external_id = get_generated_id("warehouse_external_id", self) if external_id != self.external_id: self.auto_external_id = True self.external_id = external_id @@ -559,8 +595,7 @@ class Warehouse(Address, DocumentItem, GeoItem, CompleteIdentifierItem, return -m2m_changed.connect(document_attached_changed, - sender=Warehouse.documents.through) +m2m_changed.connect(document_attached_changed, sender=Warehouse.documents.through) post_save.connect(cached_label_and_geo_changed, sender=Warehouse) @@ -577,28 +612,35 @@ post_delete.connect(post_save_cache, sender=WarehouseDivision) class WarehouseDivisionLinkManager(models.Manager): def get_by_natural_key(self, warehouse, container_type): - return self.get(warehouse__uuid=warehouse, - container_type__txt_idx=container_type) + return self.get( + warehouse__uuid=warehouse, container_type__txt_idx=container_type + ) class ContainerType(GeneralType): stationary = models.BooleanField( - _("Stationary"), default=False, - help_text=_("Container that will not usually be moved. Ex: building, " - "room, span, shelf.")) + _("Stationary"), + default=False, + help_text=_( + "Container that will not usually be moved. Ex: building, " + "room, span, shelf." + ), + ) length = models.IntegerField(_("Length (mm)"), blank=True, null=True) width = models.IntegerField(_("Width (mm)"), blank=True, null=True) height = models.IntegerField(_("Height (mm)"), blank=True, null=True) volume = models.FloatField(_("Volume (l)"), blank=True, null=True) tare_weight = models.FloatField(_("Tare weight (g)"), blank=True, null=True) - reference = models.CharField(_("Ref."), max_length=300, blank=True, - null=True) + reference = models.CharField(_("Ref."), max_length=300, blank=True, null=True) order = models.IntegerField(_("Order"), default=10) class Meta: verbose_name = _("Container type") verbose_name_plural = _("Container types") - ordering = ('order', 'label',) + ordering = ( + "order", + "label", + ) post_save.connect(post_save_cache, sender=ContainerType) @@ -608,18 +650,18 @@ post_delete.connect(post_save_cache, sender=ContainerType) class WarehouseDivisionLink(models.Model): RELATED_SET_NAME = "divisions" RELATED_ATTRS = ["order", "container_type"] - RELATIVE_MODELS = {Warehouse: 'warehouse'} - warehouse = models.ForeignKey(Warehouse, related_name='divisions') + RELATIVE_MODELS = {Warehouse: "warehouse"} + warehouse = models.ForeignKey(Warehouse, related_name="divisions") container_type = models.ForeignKey(ContainerType, blank=True, null=True) division = models.ForeignKey( - WarehouseDivision, help_text=_("Deprecated - do not use"), - blank=True, null=True) + WarehouseDivision, help_text=_("Deprecated - do not use"), blank=True, null=True + ) order = models.IntegerField(_("Order"), default=10) objects = WarehouseDivisionLinkManager() class Meta: - ordering = ('warehouse', 'order') - unique_together = ('warehouse', 'division') + ordering = ("warehouse", "order") + unique_together = ("warehouse", "division") def __str__(self): return "{} - {}".format(self.warehouse, self.container_type) @@ -682,31 +724,47 @@ class ContainerTree(models.Model): DROP VIEW IF EXISTS containers_tree; """ container = models.OneToOneField( - "archaeological_warehouse.Container", verbose_name=_("Container"), - related_name="container_tree_child", primary_key=True) + "archaeological_warehouse.Container", + verbose_name=_("Container"), + related_name="container_tree_child", + primary_key=True, + ) container_parent = models.ForeignKey( "archaeological_warehouse.Container", verbose_name=_("Container parent"), - related_name="container_tree_parent") + related_name="container_tree_parent", + ) class Meta: managed = False - db_table = 'containers_tree' - - -class Container(DocumentItem, Merge, LightHistorizedItem, - CompleteIdentifierItem, GeoItem, OwnPerms, MainItem, - DivisionContainer, ValueGetter): - SLUG = 'container' + db_table = "containers_tree" + + +class Container( + DocumentItem, + Merge, + LightHistorizedItem, + CompleteIdentifierItem, + GeoItem, + OwnPerms, + MainItem, + DivisionContainer, + ValueGetter, +): + SLUG = "container" APP = "archaeological-warehouse" MODEL = "container" - SHOW_URL = 'show-container' - DELETE_URL = 'delete-container' + SHOW_URL = "show-container" + DELETE_URL = "delete-container" NEW_QUERY_ENGINE = True - TABLE_COLS = ['container_type__label', 'reference', - 'location__name', - 'cached_division', 'old_reference'] - IMAGE_PREFIX = 'containers/' + TABLE_COLS = [ + "container_type__label", + "reference", + "location__name", + "cached_division", + "old_reference", + ] + IMAGE_PREFIX = "containers/" BASE_SEARCH_VECTORS = [ SearchVectorConfig("reference"), SearchVectorConfig("container_type__label"), @@ -720,210 +778,208 @@ class Container(DocumentItem, Merge, LightHistorizedItem, ] PARENT_SEARCH_VECTORS = ["parent"] - STATISTIC_MODALITIES_OPTIONS = OrderedDict([ - ("location__name", _("Location (warehouse)")), - ("responsibility__name", _("Responsibility (warehouse)")), - ('finds__base_finds__context_record__operation__cached_label', - _("Operation")), - ]) - STATISTIC_MODALITIES = [ - key for key, lbl in STATISTIC_MODALITIES_OPTIONS.items()] + STATISTIC_MODALITIES_OPTIONS = OrderedDict( + [ + ("location__name", _("Location (warehouse)")), + ("responsibility__name", _("Responsibility (warehouse)")), + ( + "finds__base_finds__context_record__operation__cached_label", + _("Operation"), + ), + ] + ) + STATISTIC_MODALITIES = [key for key, lbl in STATISTIC_MODALITIES_OPTIONS.items()] GET_VALUES_EXCLUDE_FIELDS = ValueGetter.GET_VALUES_EXCLUDE_FIELDS + [ - "inside_container", "parent"] + "inside_container", + "parent", + ] # search parameters EXTRA_REQUEST_KEYS = { - 'location': 'location__pk', - 'location__name': "location__name", - 'location_id': 'location__pk', - 'responsibility_id': 'responsibility__pk', - 'container_type': 'container_type__pk', - 'reference': 'reference__icontains', - 'old_reference': 'old_reference__icontains', - 'finds__base_finds__context_record__operation': - 'finds__base_finds__context_record__operation', - 'finds__base_finds__context_record': - 'finds__base_finds__context_record', - 'finds': 'finds', - 'container_type__label': 'container_type__label', - + "location": "location__pk", + "location__name": "location__name", + "location_id": "location__pk", + "responsibility_id": "responsibility__pk", + "container_type": "container_type__pk", + "reference": "reference__icontains", + "old_reference": "old_reference__icontains", + "finds__base_finds__context_record__operation": "finds__base_finds__context_record__operation", + "finds__base_finds__context_record": "finds__base_finds__context_record", + "finds": "finds", + "container_type__label": "container_type__label", # dynamic tables - 'container_tree_child__container_parent__id': - 'container_tree_child__container_parent__id' + "container_tree_child__container_parent__id": "container_tree_child__container_parent__id", } COL_LABELS = { - 'cached_location': _("Location - index"), - 'cached_division': _("Precise localisation"), - 'container_type__label': _("Type"), - "location__name": _("Warehouse") + "cached_location": _("Location - index"), + "cached_division": _("Precise localisation"), + "container_type__label": _("Type"), + "location__name": _("Warehouse"), } GEO_LABEL = "cached_label" - CACHED_LABELS = ['cached_division', 'cached_label', 'cached_location', - 'cached_weight'] + CACHED_LABELS = [ + "cached_division", + "cached_label", + "cached_location", + "cached_weight", + ] # alternative names of fields for searches ALT_NAMES = { - 'location_name': SearchAltName( - pgettext_lazy("key for text search", "location"), - 'location__name__iexact' + "location_name": SearchAltName( + pgettext_lazy("key for text search", "location"), "location__name__iexact" ), - 'responsibility_name': SearchAltName( + "responsibility_name": SearchAltName( pgettext_lazy("key for text search", "responsibility"), - 'responsibility__name__iexact' + "responsibility__name__iexact", ), - 'container_type': SearchAltName( + "container_type": SearchAltName( pgettext_lazy("key for text search", "type"), - 'container_type__label__iexact' + "container_type__label__iexact", ), - 'reference': SearchAltName( - pgettext_lazy("key for text search", "reference"), - 'reference__iexact' + "reference": SearchAltName( + pgettext_lazy("key for text search", "reference"), "reference__iexact" ), - 'old_reference': SearchAltName( + "old_reference": SearchAltName( pgettext_lazy("key for text search", "old-reference"), - 'old_reference__iexact' + "old_reference__iexact", ), - 'comment': SearchAltName( - pgettext_lazy("key for text search", "comment"), - 'comment__iexact' + "comment": SearchAltName( + pgettext_lazy("key for text search", "comment"), "comment__iexact" ), - 'operation_town': - SearchAltName( - pgettext_lazy("key for text search", "operation-town"), - 'finds__base_finds__context_record__operation__' - 'towns__cached_label__iexact' - ), - 'operation_scientist': - SearchAltName( - pgettext_lazy("key for text search", "operation-scientist"), - 'finds__base_finds__context_record__operation__' - 'scientist__cached_label__iexact' - ), - 'code_patriarche': - SearchAltName( - pgettext_lazy("key for text search", "code-patriarche"), - 'finds__base_finds__context_record__operation__' - 'code_patriarche__iexact' - ), - 'archaeological_sites': - SearchAltName( - pgettext_lazy("key for text search", "site"), - 'finds__base_finds__context_record__operation__' - 'archaeological_sites__cached_label__icontains'), - 'archaeological_sites_name': - SearchAltName( - pgettext_lazy("key for text search", "site-name"), - 'finds__base_finds__context_record__operation__' - 'archaeological_sites__name__iexact'), - 'archaeological_sites_context_record': - SearchAltName( - pgettext_lazy("key for text search", "context-record-site"), - 'finds__base_finds__context_record__archaeological_site__' - 'cached_label__icontains'), - 'archaeological_sites_context_record_name': - SearchAltName( - pgettext_lazy("key for text search", - "context-record-site-name"), - 'finds__base_finds__context_record__archaeological_site__' - 'name__iexact'), - 'context_record': - SearchAltName( - pgettext_lazy("key for text search", "context-record"), - 'finds__base_finds__context_record__cached_label__icontains'), - 'find_label': - SearchAltName( - pgettext_lazy("key for text search", "find-label"), - 'finds__label__icontains'), - 'find_denomination': - SearchAltName( - pgettext_lazy("key for text search", "find-denomination"), - 'finds__denomination__icontains'), - 'material_types': - SearchAltName( - pgettext_lazy("key for text search", "material"), - 'finds__material_types__label__iexact'), - 'object_types': - SearchAltName( - pgettext_lazy("key for text search", "object-type"), - 'finds__object_types__label__iexact'), - 'preservation_to_considers': - SearchAltName( - pgettext_lazy("key for text search", "preservation"), - 'finds__preservation_to_considers__label__iexact'), - 'conservatory_state': - SearchAltName( - pgettext_lazy("key for text search", "conservatory"), - 'finds__conservatory_state__label__iexact'), - 'integrities': - SearchAltName( - pgettext_lazy("key for text search", "integrity"), - 'finds__integrities__label__iexact'), - 'remarkabilities': - SearchAltName( - pgettext_lazy("key for text search", "remarkability"), - 'finds__remarkabilities__label__iexact'), - 'alterations': - SearchAltName( - pgettext_lazy("key for text search", "alterations"), - 'finds__alterations__label__iexact'), - 'alteration_causes': - SearchAltName( - pgettext_lazy("key for text search", "alteration-causes"), - 'finds__alteration_causes__label__iexact'), - 'treatment_emergency': - SearchAltName( - pgettext_lazy("key for text search", "treatment-emergency"), - 'finds__treatment_emergency__label__iexact'), - 'description': - SearchAltName( - pgettext_lazy("key for text search", "find-description"), - 'finds__description__iexact'), - 'empty': SearchAltName( - pgettext_lazy("key for text search", "empty"), - 'finds' + "operation_town": SearchAltName( + pgettext_lazy("key for text search", "operation-town"), + "finds__base_finds__context_record__operation__" + "towns__cached_label__iexact", + ), + "operation_scientist": SearchAltName( + pgettext_lazy("key for text search", "operation-scientist"), + "finds__base_finds__context_record__operation__" + "scientist__cached_label__iexact", + ), + "code_patriarche": SearchAltName( + pgettext_lazy("key for text search", "code-patriarche"), + "finds__base_finds__context_record__operation__" "code_patriarche__iexact", + ), + "archaeological_sites": SearchAltName( + pgettext_lazy("key for text search", "site"), + "finds__base_finds__context_record__operation__" + "archaeological_sites__cached_label__icontains", + ), + "archaeological_sites_name": SearchAltName( + pgettext_lazy("key for text search", "site-name"), + "finds__base_finds__context_record__operation__" + "archaeological_sites__name__iexact", + ), + "archaeological_sites_context_record": SearchAltName( + pgettext_lazy("key for text search", "context-record-site"), + "finds__base_finds__context_record__archaeological_site__" + "cached_label__icontains", + ), + "archaeological_sites_context_record_name": SearchAltName( + pgettext_lazy("key for text search", "context-record-site-name"), + "finds__base_finds__context_record__archaeological_site__" "name__iexact", + ), + "context_record": SearchAltName( + pgettext_lazy("key for text search", "context-record"), + "finds__base_finds__context_record__cached_label__icontains", + ), + "find_label": SearchAltName( + pgettext_lazy("key for text search", "find-label"), + "finds__label__icontains", + ), + "find_denomination": SearchAltName( + pgettext_lazy("key for text search", "find-denomination"), + "finds__denomination__icontains", + ), + "material_types": SearchAltName( + pgettext_lazy("key for text search", "material"), + "finds__material_types__label__iexact", + ), + "object_types": SearchAltName( + pgettext_lazy("key for text search", "object-type"), + "finds__object_types__label__iexact", + ), + "preservation_to_considers": SearchAltName( + pgettext_lazy("key for text search", "preservation"), + "finds__preservation_to_considers__label__iexact", + ), + "conservatory_state": SearchAltName( + pgettext_lazy("key for text search", "conservatory"), + "finds__conservatory_state__label__iexact", + ), + "integrities": SearchAltName( + pgettext_lazy("key for text search", "integrity"), + "finds__integrities__label__iexact", + ), + "remarkabilities": SearchAltName( + pgettext_lazy("key for text search", "remarkability"), + "finds__remarkabilities__label__iexact", + ), + "alterations": SearchAltName( + pgettext_lazy("key for text search", "alterations"), + "finds__alterations__label__iexact", + ), + "alteration_causes": SearchAltName( + pgettext_lazy("key for text search", "alteration-causes"), + "finds__alteration_causes__label__iexact", ), - 'contain_containers': SearchAltName( + "treatment_emergency": SearchAltName( + pgettext_lazy("key for text search", "treatment-emergency"), + "finds__treatment_emergency__label__iexact", + ), + "description": SearchAltName( + pgettext_lazy("key for text search", "find-description"), + "finds__description__iexact", + ), + "empty": SearchAltName(pgettext_lazy("key for text search", "empty"), "finds"), + "contain_containers": SearchAltName( pgettext_lazy("key for text search", "contain-containers"), - 'children__isnull' + "children__isnull", ), - 'is_stationary': SearchAltName( + "is_stationary": SearchAltName( pgettext_lazy("key for text search", "is-stationary"), - 'container_type__stationary' - ) + "container_type__stationary", + ), } REVERSED_BOOL_FIELDS = [ - 'children__isnull', - 'documents__image__isnull', - 'documents__associated_file__isnull', - 'documents__associated_url__isnull', + "children__isnull", + "documents__image__isnull", + "documents__associated_file__isnull", + "documents__associated_url__isnull", ] - BOOL_FIELDS = ['container_type__stationary'] - REVERSED_MANY_COUNTED_FIELDS = ['finds', 'finds_ref'] + BOOL_FIELDS = ["container_type__stationary"] + REVERSED_MANY_COUNTED_FIELDS = ["finds", "finds_ref"] ALT_NAMES.update(LightHistorizedItem.ALT_NAMES) ALT_NAMES.update(DocumentItem.ALT_NAMES) DYNAMIC_REQUESTS = { - 'division': DynamicRequest( + "division": DynamicRequest( label=_("Division -"), - app_name='archaeological_warehouse', model_name='WarehouseDivision', - form_key='division', - search_key=pgettext_lazy("key for text search", - 'division'), - type_query='division__division__division__txt_idx', - search_query='division__reference__iexact' + app_name="archaeological_warehouse", + model_name="WarehouseDivision", + form_key="division", + search_key=pgettext_lazy("key for text search", "division"), + type_query="division__division__division__txt_idx", + search_query="division__reference__iexact", ), } QA_EDIT = QuickAction( - url="container-qa-bulk-update", icon_class="fa fa-pencil", - text=_("Bulk update"), target="many", - rights=['change_container', 'change_own_container']) + url="container-qa-bulk-update", + icon_class="fa fa-pencil", + text=_("Bulk update"), + target="many", + rights=["change_container", "change_own_container"], + ) QA_LOCK = QuickAction( - url="container-qa-lock", icon_class="fa fa-lock", - text=_("Lock/Unlock"), target="many", - rights=['change_container', 'change_own_container'] + url="container-qa-lock", + icon_class="fa fa-lock", + text=_("Lock/Unlock"), + target="many", + rights=["change_container", "change_own_container"], ) QUICK_ACTIONS = [QA_EDIT, QA_LOCK] @@ -934,52 +990,76 @@ class Container(DocumentItem, Merge, LightHistorizedItem, # fields uuid = models.UUIDField(default=uuid.uuid4) location = models.ForeignKey( - Warehouse, verbose_name=_("Location (warehouse)"), - related_name='containers') + Warehouse, verbose_name=_("Location (warehouse)"), related_name="containers" + ) responsible = models.ForeignKey( - Warehouse, verbose_name=_("Responsible warehouse"), - related_name='owned_containers', blank=True, null=True, - help_text=_("Deprecated - do not use") + Warehouse, + verbose_name=_("Responsible warehouse"), + related_name="owned_containers", + blank=True, + null=True, + help_text=_("Deprecated - do not use"), ) responsibility = models.ForeignKey( - Warehouse, verbose_name=_("Responsibility"), - related_name='responsibilities', blank=True, null=True, - help_text=_("Warehouse that owns the container") + Warehouse, + verbose_name=_("Responsibility"), + related_name="responsibilities", + blank=True, + null=True, + help_text=_("Warehouse that owns the container"), + ) + container_type = models.ForeignKey( + ContainerType, verbose_name=_("Container type"), related_name="containers" ) - container_type = models.ForeignKey(ContainerType, - verbose_name=_("Container type"), - related_name="containers") reference = models.TextField(_("Container ref.")) comment = models.TextField(_("Comment"), blank=True, default="") - cached_label = models.TextField(_("Localisation"), blank=True, default="", - db_index=True) - cached_location = models.TextField(_("Cached location"), - blank=True, default="", db_index=True) - cached_division = models.TextField(_("Cached division"), - blank=True, default="", db_index=True) - parent = models.ForeignKey("Container", verbose_name=_("Parent container"), - on_delete=models.SET_NULL, - related_name="children", blank=True, null=True) - index = models.IntegerField(_("Container ID"), blank=True, null=True, - db_index=True) + cached_label = models.TextField( + _("Localisation"), blank=True, default="", db_index=True + ) + cached_location = models.TextField( + _("Cached location"), blank=True, default="", db_index=True + ) + cached_division = models.TextField( + _("Cached division"), blank=True, default="", db_index=True + ) + parent = models.ForeignKey( + "Container", + verbose_name=_("Parent container"), + on_delete=models.SET_NULL, + related_name="children", + blank=True, + null=True, + ) + index = models.IntegerField(_("Container ID"), blank=True, null=True, db_index=True) weight = models.FloatField(_("Measured weight (g)"), blank=True, null=True) calculated_weight = models.FloatField( - _("Calculated weight (g)"), blank=True, null=True) + _("Calculated weight (g)"), blank=True, null=True + ) cached_weight = models.FloatField( - _("Cached weight (g)"), blank=True, null=True, - help_text=_("Entered weight if available otherwise calculated weight.") + _("Cached weight (g)"), + blank=True, + null=True, + help_text=_("Entered weight if available otherwise calculated weight."), ) old_reference = models.TextField(_("Old reference"), blank=True, default="") external_id = models.TextField(_("External ID"), blank=True, default="") auto_external_id = models.BooleanField( - _("External ID is set automatically"), default=False) + _("External ID is set automatically"), default=False + ) documents = models.ManyToManyField( - "ishtar_common.Document", related_name='containers', - verbose_name=_("Documents"), blank=True) + "ishtar_common.Document", + related_name="containers", + verbose_name=_("Documents"), + blank=True, + ) main_image = models.ForeignKey( - "ishtar_common.Document", related_name='main_image_containers', + "ishtar_common.Document", + related_name="main_image_containers", on_delete=models.SET_NULL, - verbose_name=_("Main image"), blank=True, null=True) + verbose_name=_("Main image"), + blank=True, + null=True, + ) DISABLE_POLYGONS = False MERGE_ATTRIBUTE = "get_merge_key" @@ -988,9 +1068,12 @@ class Container(DocumentItem, Merge, LightHistorizedItem, class Meta: verbose_name = _("Container") verbose_name_plural = _("Containers") - ordering = ('location', 'index', 'cached_label',) - unique_together = [('location', 'container_type', 'parent', - 'reference')] + ordering = ( + "location", + "index", + "cached_label", + ) + unique_together = [("location", "container_type", "parent", "reference")] permissions = ( ("view_container", "Can view all Containers"), ("view_own_container", "Can view own Container"), @@ -999,7 +1082,7 @@ class Container(DocumentItem, Merge, LightHistorizedItem, ("delete_own_container", "Can delete own Container"), ) indexes = [ - GinIndex(fields=['data']), + GinIndex(fields=["data"]), ] def __str__(self): @@ -1017,8 +1100,7 @@ class Container(DocumentItem, Merge, LightHistorizedItem, return depth def get_max_division_number(self): - return self.location.get_max_division_number() \ - - self.start_division_number + return self.location.get_max_division_number() - self.start_division_number @property def number_of_finds_hosted(self): @@ -1049,13 +1131,12 @@ class Container(DocumentItem, Merge, LightHistorizedItem, return self.parent.external_id def natural_key(self): - return (self.uuid, ) + return (self.uuid,) @classmethod @pre_importer_action def import_get_location(cls, context, value): - if context.get("container_type", None) and context.get( - "reference", None): + if context.get("container_type", None) and context.get("reference", None): try: context["location"] = Warehouse.objects.get(external_id=value) return @@ -1085,15 +1166,23 @@ class Container(DocumentItem, Merge, LightHistorizedItem, :return: True if calculated weight is changed """ profile = get_current_profile() - if profile.calculate_weight_on_full and self.finds.filter( - weight__isnull=True).count(): + if ( + profile.calculate_weight_on_full + and self.finds.filter(weight__isnull=True).count() + ): weight = None else: weight = sum( - w for w in self.finds.filter(weight__isnull=False).values_list( - "weight", flat=True).all()) - weight += self.container_type.tare_weight \ - if self.container_type.tare_weight else 0 + w + for w in self.finds.filter(weight__isnull=False) + .values_list("weight", flat=True) + .all() + ) + weight += ( + self.container_type.tare_weight + if self.container_type.tare_weight + else 0 + ) if weight != self.calculated_weight: self.calculated_weight = weight return True @@ -1103,8 +1192,7 @@ class Container(DocumentItem, Merge, LightHistorizedItem, def get_calculated_weight_percent(self): if not self.calculated_weight or not self.weight: return 0 - return (self.calculated_weight - - self.weight) / self.calculated_weight * 100 + return (self.calculated_weight - self.weight) / self.calculated_weight * 100 @property def get_cached_division(self): @@ -1113,8 +1201,7 @@ class Container(DocumentItem, Merge, LightHistorizedItem, @property def get_merge_key(self): try: - return str(self.location.uuid) + "|" + \ - self._generate_cached_division() + return str(self.location.uuid) + "|" + self._generate_cached_division() except Warehouse.DoesNotExist: return @@ -1123,11 +1210,13 @@ class Container(DocumentItem, Merge, LightHistorizedItem, try: doc = Document.objects.get(**{key: value}) except Document.DoesNotExist: - raise ImporterError(str(_("Document with {}: {} does not " - "exists")).format(key, value)) + raise ImporterError( + str(_("Document with {}: {} does not " "exists")).format(key, value) + ) except Document.MultipleObjectsReturned: raise ImporterError( - str(_("Multiple document with {}: {}")).format(key, value)) + str(_("Multiple document with {}: {}")).format(key, value) + ) doc.container_id = self.pk doc.container_ref_id = self.pk doc.skip_history_when_saving = True @@ -1136,16 +1225,19 @@ class Container(DocumentItem, Merge, LightHistorizedItem, @post_importer_action def put_document_by_external_id(self, context, value): self.put_document_by_key(value, "external_id") + put_document_by_external_id.post_save = True @post_importer_action def put_document_by_reference(self, context, value): self.put_document_by_key(value, "reference") + put_document_by_reference.post_save = True @post_importer_action def put_document_by_complete_identifier(self, context, value): self.put_document_by_key(value, "complete_identifier") + put_document_by_complete_identifier.post_save = True def _generate_cached_division(self): @@ -1163,8 +1255,7 @@ class Container(DocumentItem, Merge, LightHistorizedItem, for loca in reversed(parents) ] try: - locas.append("{} {}".format(self.container_type.name, - self.reference)) + locas.append("{} {}".format(self.container_type.name, self.reference)) except ObjectDoesNotExist: # generate too early on item creation pass return " | ".join(locas) @@ -1174,8 +1265,9 @@ class Container(DocumentItem, Merge, LightHistorizedItem, @classmethod def _change_child_location(cls, parent): - for child in cls.objects.filter( - parent=parent).exclude(location=parent.location).all(): + for child in ( + cls.objects.filter(parent=parent).exclude(location=parent.location).all() + ): if child.location != parent.location: child.location = parent.location child.save() @@ -1198,13 +1290,15 @@ class Container(DocumentItem, Merge, LightHistorizedItem, child.parent = self child.save() self._change_child_location(self) - super(Container, self).merge(item, keep_old=keep_old, - exclude_fields=exclude_fields) + super(Container, self).merge( + item, keep_old=keep_old, exclude_fields=exclude_fields + ) @classmethod def get_query_owns(cls, ishtaruser): - return Q(history_creator=ishtaruser.user_ptr) | \ - Q(location__person_in_charge__ishtaruser=ishtaruser) + return Q(history_creator=ishtaruser.user_ptr) | Q( + location__person_in_charge__ishtaruser=ishtaruser + ) def get_precise_points(self): precise_points = super(Container, self).get_precise_points() @@ -1232,7 +1326,7 @@ class Container(DocumentItem, Merge, LightHistorizedItem, @property def associated_filename(self): - filename = datetime.date.today().strftime('%Y-%m-%d') + filename = datetime.date.today().strftime("%Y-%m-%d") filename += "-" + self.reference filename += "-" + self.location.name filename += "-" + str(self.index) @@ -1324,8 +1418,10 @@ class Container(DocumentItem, Merge, LightHistorizedItem, error_msg = str(NO_DIVISION_ERROR).format(place + 1, self.location) - current_container_type, previous_container_types = \ - self.location.get_container_type_by_place(place) + ( + current_container_type, + previous_container_types, + ) = self.location.get_container_type_by_place(place) if not current_container_type: # no division link set at this place if return_errors: @@ -1349,7 +1445,7 @@ class Container(DocumentItem, Merge, LightHistorizedItem, "reference": value, "container_type": current_container_type, "parent": current_parent, - "location": self.location + "location": self.location, } q = Container.objects.filter(**dct) if q.count(): @@ -1358,8 +1454,7 @@ class Container(DocumentItem, Merge, LightHistorizedItem, if static: if return_errors: error_msg = str( - _("The division {} {} do not exist for the " - "location {}.") + _("The division {} {} do not exist for the " "location {}.") ).format(current_container_type, value, self.location) return None, error_msg return @@ -1376,103 +1471,128 @@ class Container(DocumentItem, Merge, LightHistorizedItem, @post_importer_action def set_localisation_1(self, context, value): return self.set_localisation(0, value) + set_localisation_1.post_save = True @post_importer_action def set_localisation_2(self, context, value): return self.set_localisation(1, value) + set_localisation_2.post_save = True @post_importer_action def set_localisation_3(self, context, value): return self.set_localisation(2, value) + set_localisation_3.post_save = True @post_importer_action def set_localisation_4(self, context, value): return self.set_localisation(3, value) + set_localisation_4.post_save = True @post_importer_action def set_localisation_5(self, context, value): return self.set_localisation(4, value) + set_localisation_5.post_save = True @post_importer_action def set_localisation_6(self, context, value): return self.set_localisation(5, value) + set_localisation_6.post_save = True @post_importer_action def set_localisation_7(self, context, value): return self.set_localisation(6, value) + set_localisation_7.post_save = True @post_importer_action def set_localisation_8(self, context, value): return self.set_localisation(7, value) + set_localisation_8.post_save = True @post_importer_action def set_localisation_9(self, context, value): return self.set_localisation(8, value) + set_localisation_9.post_save = True @post_importer_action def set_static_localisation_1(self, context, value): return self.set_static_localisation(0, value) + set_static_localisation_1.post_save = True @post_importer_action def set_static_localisation_2(self, context, value): return self.set_static_localisation(1, value) + set_static_localisation_2.post_save = True @post_importer_action def set_static_localisation_3(self, context, value): return self.set_static_localisation(2, value) + set_static_localisation_3.post_save = True @post_importer_action def set_static_localisation_4(self, context, value): return self.set_static_localisation(3, value) + set_static_localisation_4.post_save = True @post_importer_action def set_static_localisation_5(self, context, value): return self.set_static_localisation(4, value) + set_static_localisation_5.post_save = True @post_importer_action def set_static_localisation_6(self, context, value): return self.set_static_localisation(5, value) + set_static_localisation_6.post_save = True @post_importer_action def set_static_localisation_7(self, context, value): return self.set_static_localisation(6, value) + set_static_localisation_7.post_save = True @post_importer_action def set_static_localisation_8(self, context, value): return self.set_static_localisation(7, value) + set_static_localisation_8.post_save = True @post_importer_action def set_static_localisation_9(self, context, value): return self.set_static_localisation(8, value) + set_static_localisation_9.post_save = True DOC_VALUES = [ - ("operation_", _("Associated operation - use it with caution, " - "only return the first found operation")), - ("context_record_", - _("Associated context record - use it with caution, " - "only return the first found context_record")), - ("material_types", - _("Material types inside the container - string")), - ("material_types_code", - _("Material types code - string")), + ( + "operation_", + _( + "Associated operation - use it with caution, " + "only return the first found operation" + ), + ), + ( + "context_record_", + _( + "Associated context record - use it with caution, " + "only return the first found context_record" + ), + ), + ("material_types", _("Material types inside the container - string")), + ("material_types_code", _("Material types code - string")), ("finds", _("List of associated finds")), ] @@ -1482,8 +1602,8 @@ class Container(DocumentItem, Merge, LightHistorizedItem, """ materials = set() for material in self.finds.exclude( - material_types__code__isnull=True).values_list( - "material_types__code", flat=True): + material_types__code__isnull=True + ).values_list("material_types__code", flat=True): materials.add(material) return "|".join(sorted(materials)) @@ -1493,38 +1613,43 @@ class Container(DocumentItem, Merge, LightHistorizedItem, """ materials = set() for material in self.finds.exclude( - material_types__label__isnull=True).values_list( - "material_types__label", flat=True): + material_types__label__isnull=True + ).values_list("material_types__label", flat=True): materials.add(material) return ", ".join(sorted(materials)) - def get_values(self, prefix='', no_values=False, filtr=None, **kwargs): + def get_values(self, prefix="", no_values=False, filtr=None, **kwargs): values = super(Container, self).get_values( - prefix=prefix, no_values=no_values, filtr=filtr, **kwargs) - from_find = prefix.startswith("container_") or \ - prefix.startswith("container_ref_") - if (not filtr or prefix + 'finds' in filtr) and not from_find and \ - "finds" not in kwargs.get("exclude", []): + prefix=prefix, no_values=no_values, filtr=filtr, **kwargs + ) + from_find = prefix.startswith("container_") or prefix.startswith( + "container_ref_" + ) + if ( + (not filtr or prefix + "finds" in filtr) + and not from_find + and "finds" not in kwargs.get("exclude", []) + ): kwargs["exclude"] = [prefix + "container", prefix + "container_ref"] # prevent recursive call - values[prefix + 'finds'] = [ - f.get_values( - prefix=prefix, no_values=True, filtr=None, **kwargs) - for f in self.finds.distinct().all()] + values[prefix + "finds"] = [ + f.get_values(prefix=prefix, no_values=True, filtr=None, **kwargs) + for f in self.finds.distinct().all() + ] if not self.finds.count(): return values operation_in_filter = filtr and any( - k for k in filtr if k.startswith(prefix + 'operation')) + k for k in filtr if k.startswith(prefix + "operation") + ) cr_in_filter = filtr and any( - k for k in filtr if k.startswith(prefix + 'context_record')) - if not filtr or prefix + 'material_types' in filtr: - values[prefix + 'material_types'] = self.get_material_types() - if not filtr or prefix + 'material_types_code' in filtr: - values[prefix + 'material_types_code'] = \ - self.get_material_types_code() - if not from_find and ( - not filtr or operation_in_filter or cr_in_filter): + k for k in filtr if k.startswith(prefix + "context_record") + ) + if not filtr or prefix + "material_types" in filtr: + values[prefix + "material_types"] = self.get_material_types() + if not filtr or prefix + "material_types_code" in filtr: + values[prefix + "material_types_code"] = self.get_material_types_code() + if not from_find and (not filtr or operation_in_filter or cr_in_filter): # assume that only one operation is in this container... # you should know what you are doing when using theses variables f = self.finds.all()[0] @@ -1534,15 +1659,15 @@ class Container(DocumentItem, Merge, LightHistorizedItem, if not filtr or cr_in_filter: kwargs["exclude"] = [prefix + "operation"] for k, v in cr.get_values( - prefix=prefix, no_values=True, filtr=None, - **kwargs).items(): - values[prefix + 'context_record_' + k] = v + prefix=prefix, no_values=True, filtr=None, **kwargs + ).items(): + values[prefix + "context_record_" + k] = v if not filtr or operation_in_filter: kwargs["exclude"] = [prefix + "context_records"] for k, v in cr.operation.get_values( - prefix=prefix, no_values=True, filtr=None, - **kwargs).items(): - values[prefix + 'operation_' + k] = v + prefix=prefix, no_values=True, filtr=None, **kwargs + ).items(): + values[prefix + "operation_" + k] = v return values def get_extra_actions(self, request): @@ -1551,11 +1676,17 @@ class Container(DocumentItem, Merge, LightHistorizedItem, """ # url, base_text, icon, extra_text, extra css class, is a quick action actions = super(Container, self).get_extra_actions(request) - can_edit_find = self.can_do(request, 'change_find') + can_edit_find = self.can_do(request, "change_find") if can_edit_find: actions += [ - (reverse('container-add-treatment', args=[self.pk]), - _("Add treatment"), "fa fa-flask", "", "", False), + ( + reverse("container-add-treatment", args=[self.pk]), + _("Add treatment"), + "fa fa-flask", + "", + "", + False, + ), ] return actions @@ -1579,8 +1710,7 @@ class Container(DocumentItem, Merge, LightHistorizedItem, return q = Container.objects.filter(location=self.location) if q.count(): - self.index = int( - q.all().aggregate(Max("index"))["index__max"]) + 1 + self.index = int(q.all().aggregate(Max("index"))["index__max"]) + 1 else: self.index = 1 if not self.cached_division: @@ -1591,8 +1721,7 @@ class Container(DocumentItem, Merge, LightHistorizedItem, parent = self.parent_id while parent: number += 1 - parent = Container.objects.filter(pk=parent).values_list( - "parent_id")[0][0] + parent = Container.objects.filter(pk=parent).values_list("parent_id")[0][0] if number > self.location.max_division_number: self.location.max_division_number = number self.location.save() @@ -1608,15 +1737,17 @@ class Container(DocumentItem, Merge, LightHistorizedItem, if not self.index and not self.container_type.stationary: self.skip_history_when_saving = True - q = Container.objects.filter( - location=self.location - ).exclude(pk=self.pk).order_by('-index') + q = ( + Container.objects.filter(location=self.location) + .exclude(pk=self.pk) + .order_by("-index") + ) self.index = q.all()[0].index + 1 if q.count() else 1 updated = True self.skip_history_when_saving = True if not self.external_id or self.auto_external_id: - external_id = get_generated_id('container_external_id', self) + external_id = get_generated_id("container_external_id", self) if external_id != self.external_id: updated = True self.auto_external_id = True @@ -1629,14 +1760,15 @@ class Container(DocumentItem, Merge, LightHistorizedItem, # remove old location in warehouse q = ContainerLocalisation.objects.filter(container=self).exclude( - division__warehouse=self.location) + division__warehouse=self.location + ) for loca in q.all(): loca.delete() def container_post_save(sender, **kwargs): cached_label_and_geo_changed(sender=sender, **kwargs) - #TODO: to be deleted??? + # TODO: to be deleted??? """ if not kwargs.get('instance'): return @@ -1657,8 +1789,7 @@ def container_post_save(sender, **kwargs): def container_pre_delete(sender, **kwargs): instance = kwargs["instance"] - q = Container.objects.filter( - container_tree_child__container_parent=instance) + q = Container.objects.filter(container_tree_child__container_parent=instance) q.update(cached_division="") @@ -1672,43 +1803,45 @@ def container_post_delete(sender, **kwargs): post_save.connect(container_post_save, sender=Container) pre_delete.connect(container_pre_delete, sender=Container) post_delete.connect(container_post_delete, sender=Container) -m2m_changed.connect(document_attached_changed, - sender=Container.documents.through) +m2m_changed.connect(document_attached_changed, sender=Container.documents.through) class ContainerLocalisationManager(models.Manager): - #TODO: to be deleted.... + # TODO: to be deleted.... def get_by_natural_key(self, container, warehouse, container_type): - return self.get(container__uuid=container, - division__warehouse__uuid=warehouse, - division__container_type__txt_idx=container_type) + return self.get( + container__uuid=container, + division__warehouse__uuid=warehouse, + division__container_type__txt_idx=container_type, + ) class ContainerLocalisation(models.Model): - #TODO: to be deleted.... - container = models.ForeignKey(Container, verbose_name=_("Container"), - related_name='division') - division = models.ForeignKey(WarehouseDivisionLink, - verbose_name=_("Division")) - reference = models.CharField(_("Reference"), max_length=200, default='') + # TODO: to be deleted.... + container = models.ForeignKey( + Container, verbose_name=_("Container"), related_name="division" + ) + division = models.ForeignKey(WarehouseDivisionLink, verbose_name=_("Division")) + reference = models.CharField(_("Reference"), max_length=200, default="") objects = ContainerLocalisationManager() TO_BE_DELETED = True class Meta: verbose_name = _("Container localisation") verbose_name_plural = _("Container localisations") - ordering = ('container', 'division__order') + ordering = ("container", "division__order") def __str__(self): - return " - ".join((str(self.container), str(self.division), - self.reference)) + return " - ".join((str(self.container), str(self.division), self.reference)) def natural_key(self): - return self.container.uuid, self.division.warehouse.uuid,\ - self.division.container_type.txt_idx + return ( + self.container.uuid, + self.division.warehouse.uuid, + self.division.container_type.txt_idx, + ) def save(self, *args, **kwargs): super(ContainerLocalisation, self).save(*args, **kwargs) self.container.skip_history_when_saving = True - cached_label_changed(Container, instance=self.container, - force_update=True) + cached_label_changed(Container, instance=self.container, force_update=True) diff --git a/archaeological_warehouse/serializers.py b/archaeological_warehouse/serializers.py index b0cf4d96f..19ae8ba99 100644 --- a/archaeological_warehouse/serializers.py +++ b/archaeological_warehouse/serializers.py @@ -1,13 +1,13 @@ from django.db.models import Q -from ishtar_common.serializers_utils import generic_get_results, \ - archive_serialization +from ishtar_common.serializers_utils import generic_get_results, archive_serialization from archaeological_warehouse import models WAREHOUSE_MODEL_LIST = [ - models.Warehouse, models.Container, + models.Warehouse, + models.Container, models.WarehouseDivisionLink, - models.ContainerLocalisation + models.ContainerLocalisation, ] # TODO: associated documents @@ -21,57 +21,76 @@ def generate_warehouse_queryset(base_query_key, ids): base_key = "{}__{}".format(find_key, base_query_key) q = Q(**{base_key: ids}) container_ids.update( - list(models.Container.objects.filter( - q).values_list("id", flat=True))) - q_loca = Q( - **{"container__{}__{}".format(find_key, base_query_key): ids}) + list(models.Container.objects.filter(q).values_list("id", flat=True)) + ) + q_loca = Q(**{"container__{}__{}".format(find_key, base_query_key): ids}) container_loca_ids.update( - list(models.ContainerLocalisation.objects.filter( - q_loca).values_list("id", flat=True))) + list( + models.ContainerLocalisation.objects.filter(q_loca).values_list( + "id", flat=True + ) + ) + ) for container_key in ("containers", "owned_containers"): - q = Q(** - {"{}__{}__{}".format(container_key, find_key, - base_query_key): ids}) - q_div = Q(** - {"warehouse__{}__{}__{}".format( - container_key, find_key, base_query_key): ids}) + q = Q(**{"{}__{}__{}".format(container_key, find_key, base_query_key): ids}) + q_div = Q( + **{ + "warehouse__{}__{}__{}".format( + container_key, find_key, base_query_key + ): ids + } + ) warehouse_ids.update( - list(models.Warehouse.objects.filter(q).values_list( - "id", flat=True))) + list(models.Warehouse.objects.filter(q).values_list("id", flat=True)) + ) warehouse_div_ids.update( - list(models.WarehouseDivisionLink.objects.filter( - q_div).values_list("id", flat=True))) + list( + models.WarehouseDivisionLink.objects.filter(q_div).values_list( + "id", flat=True + ) + ) + ) result_queryset = { - models.Warehouse.__name__: - models.Warehouse.objects.filter(id__in=warehouse_ids), - models.Container.__name__: - models.Container.objects.filter(id__in=container_ids), - models.WarehouseDivisionLink.__name__: - models.WarehouseDivisionLink.objects.filter( - id__in=warehouse_div_ids), - models.ContainerLocalisation.__name__: - models.ContainerLocalisation.objects.filter( - id__in=container_loca_ids) + models.Warehouse.__name__: models.Warehouse.objects.filter( + id__in=warehouse_ids + ), + models.Container.__name__: models.Container.objects.filter( + id__in=container_ids + ), + models.WarehouseDivisionLink.__name__: models.WarehouseDivisionLink.objects.filter( + id__in=warehouse_div_ids + ), + models.ContainerLocalisation.__name__: models.ContainerLocalisation.objects.filter( + id__in=container_loca_ids + ), } return result_queryset -def warehouse_serialization(archive=False, return_empty_types=False, - archive_name=None, operation_queryset=None, - site_queryset=None, cr_queryset=None, - find_queryset=None, warehouse_queryset=None, - get_queryset=False, no_geo=True, - put_locks=False, lock_user=None): +def warehouse_serialization( + archive=False, + return_empty_types=False, + archive_name=None, + operation_queryset=None, + site_queryset=None, + cr_queryset=None, + find_queryset=None, + warehouse_queryset=None, + get_queryset=False, + no_geo=True, + put_locks=False, + lock_user=None, +): result_queryset = {} if operation_queryset: operation_ids = operation_queryset.values_list("id", flat=True) base_query_key = "base_finds__context_record__operation_id__in" - result_queryset = generate_warehouse_queryset(base_query_key, - operation_ids) + result_queryset = generate_warehouse_queryset(base_query_key, operation_ids) elif site_queryset: site_ids = site_queryset.values_list("id", flat=True) - base_query_key = "base_finds__context_record__"\ - "operation__archaeological_sites__id__in" + base_query_key = ( + "base_finds__context_record__" "operation__archaeological_sites__id__in" + ) result_queryset = generate_warehouse_queryset(base_query_key, site_ids) elif cr_queryset: cr_ids = cr_queryset.values_list("id", flat=True) @@ -85,22 +104,24 @@ def warehouse_serialization(archive=False, return_empty_types=False, warehouse_ids = warehouse_queryset.values_list("id", flat=True) result_queryset = { models.Warehouse.__name__: warehouse_queryset, - models.Container.__name__: - models.Container.objects.filter( - Q(location__id__in=warehouse_ids) | - Q(responsible__id__in=warehouse_ids) - ), - models.WarehouseDivisionLink.__name__: - models.WarehouseDivisionLink.objects.filter( - warehouse_id__in=warehouse_ids), - models.ContainerLocalisation.__name__: - models.ContainerLocalisation.objects.filter( - division__warehouse_id__in=warehouse_ids) + models.Container.__name__: models.Container.objects.filter( + Q(location__id__in=warehouse_ids) | Q(responsible__id__in=warehouse_ids) + ), + models.WarehouseDivisionLink.__name__: models.WarehouseDivisionLink.objects.filter( + warehouse_id__in=warehouse_ids + ), + models.ContainerLocalisation.__name__: models.ContainerLocalisation.objects.filter( + division__warehouse_id__in=warehouse_ids + ), } if get_queryset: return result_queryset - result = generic_get_results(WAREHOUSE_MODEL_LIST, "warehouse", - result_queryset=result_queryset, no_geo=no_geo) + result = generic_get_results( + WAREHOUSE_MODEL_LIST, + "warehouse", + result_queryset=result_queryset, + no_geo=no_geo, + ) if put_locks: for model in WAREHOUSE_MODEL_LIST: if not hasattr(model, "locked"): @@ -111,7 +132,10 @@ def warehouse_serialization(archive=False, return_empty_types=False, q.update(locked=True, lock_user=lock_user) full_archive = archive_serialization( - result, archive_dir="warehouse", archive=archive, - return_empty_types=return_empty_types, archive_name=archive_name, + result, + archive_dir="warehouse", + archive=archive, + return_empty_types=return_empty_types, + archive_name=archive_name, ) return full_archive diff --git a/archaeological_warehouse/tests.py b/archaeological_warehouse/tests.py index dc1744312..503057cdf 100644 --- a/archaeological_warehouse/tests.py +++ b/archaeological_warehouse/tests.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2017 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> @@ -25,9 +25,15 @@ from django.test.client import Client from archaeological_finds.tests import FindInit -from ishtar_common.tests import WizardTest, WizardTestFormData as FormData, \ - TestCase, WAREHOUSE_FIXTURES, GenericSerializationTest, COMMON_FIXTURES, \ - create_user +from ishtar_common.tests import ( + WizardTest, + WizardTestFormData as FormData, + TestCase, + WAREHOUSE_FIXTURES, + GenericSerializationTest, + COMMON_FIXTURES, + create_user, +) from ishtar_common.models import IshtarSiteProfile, SpatialReferenceSystem from archaeological_operations.models import Operation @@ -47,12 +53,8 @@ class SerializationTest(GenericSerializationTest, FindInit, TestCase): def setUp(self): ope1 = self.create_operation()[0] ope2 = self.create_operation()[1] - cr = self.create_context_record( - data={"label": "CR 1", "operation": ope1} - )[0] - cr2 = self.create_context_record( - data={"label": "CR 2", "operation": ope2} - )[1] + cr = self.create_context_record(data={"label": "CR 1", "operation": ope1})[0] + cr2 = self.create_context_record(data={"label": "CR 2", "operation": ope2})[1] self.create_finds(data_base={"context_record": cr}) self.create_finds(data_base={"context_record": cr2}) self.create_finds(data_base={"context_record": cr2}) @@ -78,7 +80,7 @@ class SerializationTest(GenericSerializationTest, FindInit, TestCase): container_type=models.ContainerType.objects.all()[0], reference="Réf1", index=1, - external_id="ref1-1" + external_id="ref1-1", ) c2 = models.Container.objects.create( location=w2, @@ -86,7 +88,7 @@ class SerializationTest(GenericSerializationTest, FindInit, TestCase): container_type=models.ContainerType.objects.all()[0], reference="Réf2", index=2, - external_id="ref2-2" + external_id="ref2-2", ) f0 = self.finds[0] f0.container = c1 @@ -98,7 +100,7 @@ class SerializationTest(GenericSerializationTest, FindInit, TestCase): container_type=models.ContainerType.objects.all()[0], reference="Réf3", index=1, - external_id="ref3-1" + external_id="ref3-1", ) c4 = models.Container.objects.create( location=w2, @@ -106,7 +108,7 @@ class SerializationTest(GenericSerializationTest, FindInit, TestCase): container_type=models.ContainerType.objects.all()[0], reference="Réf4", index=2, - external_id="ref4-2" + external_id="ref4-2", ) f1 = self.finds[1] f1.container = c3 @@ -118,7 +120,7 @@ class SerializationTest(GenericSerializationTest, FindInit, TestCase): container_type=models.ContainerType.objects.all()[0], reference="Réf5", index=1, - external_id="ref5-2" + external_id="ref5-2", ) f2 = self.finds[2] f2.container = c5 @@ -127,20 +129,16 @@ class SerializationTest(GenericSerializationTest, FindInit, TestCase): ct1 = models.ContainerType.objects.all()[0] ct2 = models.ContainerType.objects.all()[1] wl1 = models.WarehouseDivisionLink.objects.create( - warehouse=w1, - container_type=ct1 + warehouse=w1, container_type=ct1 ) wl2 = models.WarehouseDivisionLink.objects.create( - warehouse=w1, - container_type=ct2 + warehouse=w1, container_type=ct2 ) wl3 = models.WarehouseDivisionLink.objects.create( - warehouse=w2, - container_type=ct2 + warehouse=w2, container_type=ct2 ) wl4 = models.WarehouseDivisionLink.objects.create( - warehouse=w3, - container_type=ct1 + warehouse=w3, container_type=ct1 ) models.Container.objects.create( location=c1.location, @@ -149,297 +147,280 @@ class SerializationTest(GenericSerializationTest, FindInit, TestCase): reference="A1", ) models.Container.objects.create( - location=c1.location, - parent=c1, - container_type=ct2, - reference="A2" + location=c1.location, parent=c1, container_type=ct2, reference="A2" ) models.Container.objects.create( - location=c2.location, - parent=c2, - container_type=ct2, - reference="A4" + location=c2.location, parent=c2, container_type=ct2, reference="A4" ) models.Container.objects.create( - location=c3.location, - parent=c3, - container_type=ct1, - reference="A5" + location=c3.location, parent=c3, container_type=ct1, reference="A5" ) def test_serialization(self): - res = self.generic_serialization_test( - serializers.warehouse_serialization) + res = self.generic_serialization_test(serializers.warehouse_serialization) warehouse_json = json.loads( - res[('warehouse', "archaeological_warehouse__Warehouse")] + res[("warehouse", "archaeological_warehouse__Warehouse")] ) self.assertEqual(len(warehouse_json), 3) container_json = json.loads( - res[('warehouse', "archaeological_warehouse__Container")] + res[("warehouse", "archaeological_warehouse__Container")] ) self.assertEqual(len(container_json), 5 + 4) div_json = json.loads( - res[('warehouse', - "archaeological_warehouse__WarehouseDivisionLink")] + res[("warehouse", "archaeological_warehouse__WarehouseDivisionLink")] ) self.assertEqual(len(div_json), 4) result_queryset = Operation.objects.filter(uuid=self.operations[0].uuid) res = self.generic_serialization_test( - serializers.warehouse_serialization, no_test=True, - kwargs={"operation_queryset": result_queryset} + serializers.warehouse_serialization, + no_test=True, + kwargs={"operation_queryset": result_queryset}, ) warehouse_json = json.loads( - res[('warehouse', "archaeological_warehouse__Warehouse")] + res[("warehouse", "archaeological_warehouse__Warehouse")] ) self.assertEqual(len(warehouse_json), 2) container_json = json.loads( - res[('warehouse', "archaeological_warehouse__Container")] + res[("warehouse", "archaeological_warehouse__Container")] ) self.assertEqual(len(container_json), 2) div_json = json.loads( - res[('warehouse', - "archaeological_warehouse__WarehouseDivisionLink")] + res[("warehouse", "archaeological_warehouse__WarehouseDivisionLink")] ) self.assertEqual(len(div_json), 3) result_queryset = ContextRecord.objects.filter( - uuid=self.context_records[0].uuid) + uuid=self.context_records[0].uuid + ) res = self.generic_serialization_test( - serializers.warehouse_serialization, no_test=True, - kwargs={"cr_queryset": result_queryset} + serializers.warehouse_serialization, + no_test=True, + kwargs={"cr_queryset": result_queryset}, ) warehouse_json = json.loads( - res[('warehouse', "archaeological_warehouse__Warehouse")] + res[("warehouse", "archaeological_warehouse__Warehouse")] ) self.assertEqual(len(warehouse_json), 2) container_json = json.loads( - res[('warehouse', "archaeological_warehouse__Container")] + res[("warehouse", "archaeological_warehouse__Container")] ) self.assertEqual(len(container_json), 2) div_json = json.loads( - res[('warehouse', - "archaeological_warehouse__WarehouseDivisionLink")] + res[("warehouse", "archaeological_warehouse__WarehouseDivisionLink")] ) self.assertEqual(len(div_json), 3) result_queryset = Find.objects.filter(uuid=self.finds[0].uuid) res = self.generic_serialization_test( - serializers.warehouse_serialization, no_test=True, - kwargs={"find_queryset": result_queryset} + serializers.warehouse_serialization, + no_test=True, + kwargs={"find_queryset": result_queryset}, ) warehouse_json = json.loads( - res[('warehouse', "archaeological_warehouse__Warehouse")] + res[("warehouse", "archaeological_warehouse__Warehouse")] ) self.assertEqual(len(warehouse_json), 2) container_json = json.loads( - res[('warehouse', "archaeological_warehouse__Container")] + res[("warehouse", "archaeological_warehouse__Container")] ) self.assertEqual(len(container_json), 2) div_json = json.loads( - res[('warehouse', - "archaeological_warehouse__WarehouseDivisionLink")] + res[("warehouse", "archaeological_warehouse__WarehouseDivisionLink")] ) self.assertEqual(len(div_json), 3) - result_queryset = models.Warehouse.objects.filter( - id=self.warehouses[0].id) + result_queryset = models.Warehouse.objects.filter(id=self.warehouses[0].id) res = self.generic_serialization_test( - serializers.warehouse_serialization, no_test=True, - kwargs={"warehouse_queryset": result_queryset} + serializers.warehouse_serialization, + no_test=True, + kwargs={"warehouse_queryset": result_queryset}, ) warehouse_json = json.loads( - res[('warehouse', "archaeological_warehouse__Warehouse")] + res[("warehouse", "archaeological_warehouse__Warehouse")] ) self.assertEqual(len(warehouse_json), 1) container_json = json.loads( - res[('warehouse', "archaeological_warehouse__Container")] + res[("warehouse", "archaeological_warehouse__Container")] ) self.assertEqual(len(container_json), 3 + 3) div_json = json.loads( - res[('warehouse', - "archaeological_warehouse__WarehouseDivisionLink")] + res[("warehouse", "archaeological_warehouse__WarehouseDivisionLink")] ) self.assertEqual(len(div_json), 2) def test_ope_serialization_with_warehouse_filter(self): res = self.generic_serialization_test( - operation_serialization, no_test=True, + operation_serialization, + no_test=True, ) ope_json = json.loads( - res[('operations', 'archaeological_operations__Operation')] + res[("operations", "archaeological_operations__Operation")] ) self.assertEqual(len(ope_json), 2) - result_queryset = models.Warehouse.objects.filter( - id=self.warehouses[0].pk) + result_queryset = models.Warehouse.objects.filter(id=self.warehouses[0].pk) res = self.generic_serialization_test( - operation_serialization, no_test=True, - kwargs={"warehouse_queryset": result_queryset} + operation_serialization, + no_test=True, + kwargs={"warehouse_queryset": result_queryset}, ) ope_json = json.loads( - res[('operations', 'archaeological_operations__Operation')] + res[("operations", "archaeological_operations__Operation")] ) self.assertEqual(len(ope_json), 1) def test_cr_serialization_with_warehouse_filter(self): res = self.generic_serialization_test( - cr_serialization, no_test=True, + cr_serialization, + no_test=True, ) cr_json = json.loads( - res[('context_records', - 'archaeological_context_records__ContextRecord')] + res[("context_records", "archaeological_context_records__ContextRecord")] ) self.assertEqual(len(cr_json), 2) - result_queryset = models.Warehouse.objects.filter( - id=self.warehouses[0].pk) + result_queryset = models.Warehouse.objects.filter(id=self.warehouses[0].pk) res = self.generic_serialization_test( - cr_serialization, no_test=True, - kwargs={"warehouse_queryset": result_queryset} + cr_serialization, + no_test=True, + kwargs={"warehouse_queryset": result_queryset}, ) cr_json = json.loads( - res[('context_records', - 'archaeological_context_records__ContextRecord')] + res[("context_records", "archaeological_context_records__ContextRecord")] ) self.assertEqual(len(cr_json), 1) def test_find_serialization_with_warehouse_filter(self): res = self.generic_serialization_test( - find_serialization, no_test=True, - ) - find_json = json.loads( - res[('finds', 'archaeological_finds__Find')] + find_serialization, + no_test=True, ) + find_json = json.loads(res[("finds", "archaeological_finds__Find")]) self.assertEqual(len(find_json), 3) - bfind_json = json.loads( - res[('finds', 'archaeological_finds__BaseFind')] - ) + bfind_json = json.loads(res[("finds", "archaeological_finds__BaseFind")]) self.assertEqual(len(bfind_json), 3) - result_queryset = models.Warehouse.objects.filter( - id=self.warehouses[0].pk) + result_queryset = models.Warehouse.objects.filter(id=self.warehouses[0].pk) res = self.generic_serialization_test( - find_serialization, no_test=True, - kwargs={"warehouse_queryset": result_queryset} - ) - find_json = json.loads( - res[('finds', 'archaeological_finds__Find')] + find_serialization, + no_test=True, + kwargs={"warehouse_queryset": result_queryset}, ) + find_json = json.loads(res[("finds", "archaeological_finds__Find")]) self.assertEqual(len(find_json), 1) - bfind_json = json.loads( - res[('finds', 'archaeological_finds__BaseFind')] - ) + bfind_json = json.loads(res[("finds", "archaeological_finds__BaseFind")]) self.assertEqual(len(bfind_json), 1) def test_restore(self): current_number, zip_filename = self.generic_restore_test_genzip( - serializers.WAREHOUSE_MODEL_LIST, - serializers.warehouse_serialization) - self.generic_restore_test(zip_filename, current_number, - serializers.WAREHOUSE_MODEL_LIST) + serializers.WAREHOUSE_MODEL_LIST, serializers.warehouse_serialization + ) + self.generic_restore_test( + zip_filename, current_number, serializers.WAREHOUSE_MODEL_LIST + ) class WarehouseWizardCreationTest(WizardTest, FindInit, TestCase): fixtures = WAREHOUSE_FIXTURES - url_name = 'warehouse_creation' - wizard_name = 'warehouse_wizard' + url_name = "warehouse_creation" + wizard_name = "warehouse_wizard" steps = views.warehouse_creation_steps - redirect_url = "/warehouse_modification/selec-warehouse_modification"\ - "?open_item={last_id}" + redirect_url = ( + "/warehouse_modification/selec-warehouse_modification" "?open_item={last_id}" + ) model = models.Warehouse # back is messing with divisions but it is not a real problem because # reinit is necessary test_back = False form_datas = [ FormData( - 'Warehouse creation', + "Warehouse creation", form_datas={ - 'warehouse-warehouse_creation': { - 'name': 'warehouse-ref', - 'warehouse_type': None, - 'location': None, - 'responsible': None, + "warehouse-warehouse_creation": { + "name": "warehouse-ref", + "warehouse_type": None, + "location": None, + "responsible": None, }, - 'divisions-warehouse_creation': [ - { - 'container_type': None, - 'order': 42 - } - ] + "divisions-warehouse_creation": [{"container_type": None, "order": 42}], }, ), FormData( - 'Warehouse creation with no division', + "Warehouse creation with no division", form_datas={ - 'warehouse-warehouse_creation': { - 'name': 'warehouse-ref', - 'warehouse_type': None, - 'location': None, - 'responsible': None, + "warehouse-warehouse_creation": { + "name": "warehouse-ref", + "warehouse_type": None, + "location": None, + "responsible": None, }, }, - ignored=['divisions-warehouse_creation'] + ignored=["divisions-warehouse_creation"], ), ] def pre_wizard(self): main_data = self.form_datas[0].form_datas alt_data = self.form_datas[1].form_datas - main_data['warehouse-warehouse_creation']['warehouse_type'] = \ - models.WarehouseType.objects.all()[0].pk - alt_data['warehouse-warehouse_creation']['warehouse_type'] = \ - models.WarehouseType.objects.all()[0].pk - main_data['divisions-warehouse_creation'][0]['container_type'] = \ - models.ContainerType.objects.all()[0].pk + main_data["warehouse-warehouse_creation"][ + "warehouse_type" + ] = models.WarehouseType.objects.all()[0].pk + alt_data["warehouse-warehouse_creation"][ + "warehouse_type" + ] = models.WarehouseType.objects.all()[0].pk + main_data["divisions-warehouse_creation"][0][ + "container_type" + ] = models.ContainerType.objects.all()[0].pk self.warehouse_number = models.Warehouse.objects.count() self.warehouse_div_link = models.WarehouseDivisionLink.objects.count() super(WarehouseWizardCreationTest, self).pre_wizard() def post_wizard(self): - self.assertEqual(models.Warehouse.objects.count(), - self.warehouse_number + 2) - self.assertEqual(models.WarehouseDivisionLink.objects.count(), - self.warehouse_div_link + 1) + self.assertEqual(models.Warehouse.objects.count(), self.warehouse_number + 2) + self.assertEqual( + models.WarehouseDivisionLink.objects.count(), self.warehouse_div_link + 1 + ) class ContainerWizardCreationTest(WizardTest, FindInit, TestCase): fixtures = WAREHOUSE_FIXTURES - url_name = 'container_creation' - wizard_name = 'container_wizard' + url_name = "container_creation" + wizard_name = "container_wizard" steps = views.container_creation_steps - redirect_url = '/container_modification/selec-container_modification'\ - '?open_item={last_id}' + redirect_url = ( + "/container_modification/selec-container_modification" "?open_item={last_id}" + ) model = models.Container form_datas = [ FormData( - 'Container creation', + "Container creation", form_datas={ - 'container-container_creation': { - 'reference': 'hop-ref', - 'container_type': None, - 'location': None, + "container-container_creation": { + "reference": "hop-ref", + "container_type": None, + "location": None, }, }, ), FormData( - 'Other container on the same warehouse', + "Other container on the same warehouse", form_datas={ - 'container-container_creation': { - 'reference': 'hop-ref2', - 'container_type': None, - 'location': None, + "container-container_creation": { + "reference": "hop-ref2", + "container_type": None, + "location": None, }, }, ), FormData( - 'Container creation', + "Container creation", form_datas={ - 'container-container_creation': { - 'reference': 'hop-ref3', - 'container_type': None, - 'location': None, - 'parent': None, + "container-container_creation": { + "reference": "hop-ref3", + "container_type": None, + "location": None, + "parent": None, }, }, ), @@ -447,35 +428,32 @@ class ContainerWizardCreationTest(WizardTest, FindInit, TestCase): def pre_wizard(self): main_warehouse = models.Warehouse.objects.create( - name="Main", - warehouse_type=models.WarehouseType.objects.all()[0] + name="Main", warehouse_type=models.WarehouseType.objects.all()[0] ) main_data = self.form_datas[0].form_datas main_data_bis = self.form_datas[1].form_datas alt_data = self.form_datas[2].form_datas for data in [main_data, main_data_bis, alt_data]: - forms_data = data['container-container_creation'] + forms_data = data["container-container_creation"] forms_data["responsible"] = main_warehouse.pk forms_data["location"] = main_warehouse.pk - forms_data["container_type"] = \ - models.ContainerType.objects.all()[0].pk + forms_data["container_type"] = models.ContainerType.objects.all()[0].pk alt_warehouse = models.Warehouse.objects.create( - name="Alt", - warehouse_type=models.WarehouseType.objects.all()[0] - ) - alt_data['container-container_creation']["location"] = alt_warehouse.pk - alt_data['container-container_creation']["parent"] = \ - models.Container.objects.create( - reference="Plop", - container_type=models.ContainerType.objects.all()[1], - location=alt_warehouse - ).pk + name="Alt", warehouse_type=models.WarehouseType.objects.all()[0] + ) + alt_data["container-container_creation"]["location"] = alt_warehouse.pk + alt_data["container-container_creation"][ + "parent" + ] = models.Container.objects.create( + reference="Plop", + container_type=models.ContainerType.objects.all()[1], + location=alt_warehouse, + ).pk self.container_number = models.Container.objects.count() super(ContainerWizardCreationTest, self).pre_wizard() def post_wizard(self): - self.assertEqual(models.Container.objects.count(), - self.container_number + 3) + self.assertEqual(models.Container.objects.count(), self.container_number + 3) class WarehouseTest(TestCase): @@ -483,8 +461,9 @@ class WarehouseTest(TestCase): def setUp(self): self.warehouse = models.Warehouse.objects.create( - name="Hophop", warehouse_type=models.WarehouseType.objects.all()[0], - address="Adresse" + name="Hophop", + warehouse_type=models.WarehouseType.objects.all()[0], + address="Adresse", ) self.container_types = models.ContainerType.objects.all()[:4] @@ -499,20 +478,20 @@ class WarehouseTest(TestCase): def test_localisation_import(self): container_nb = models.Container.objects.count() base_value = "A;42;allée 3\;2" - error = self.warehouse._add_localisations( - None, base_value, return_errors=True) + error = self.warehouse._add_localisations(None, base_value, return_errors=True) self.assertTrue(error) # no division set for idx, ct in enumerate(self.container_types): models.WarehouseDivisionLink.objects.create( - container_type=ct, order=idx * 10, warehouse=self.warehouse) + container_type=ct, order=idx * 10, warehouse=self.warehouse + ) too_many_value = "A;42;allée 3\;2;5;42;3" error = self.warehouse._add_localisations( - None, too_many_value, return_errors=True) + None, too_many_value, return_errors=True + ) self.assertTrue(error) - error = self.warehouse._add_localisations( - None, base_value, return_errors=True) + error = self.warehouse._add_localisations(None, base_value, return_errors=True) self.assertIsNone(error) parent = None for idx, reference in enumerate(("A", "42", "allée 3;2")): @@ -520,18 +499,21 @@ class WarehouseTest(TestCase): parent=parent, location=self.warehouse, container_type=self.container_types[idx], - reference=reference) + reference=reference, + ) self.assertEqual( - q.count(), 1, "Division {} {} - parent {} not created".format( - self.container_types[idx], reference, parent)) + q.count(), + 1, + "Division {} {} - parent {} not created".format( + self.container_types[idx], reference, parent + ), + ) parent = q.all()[0] new_container_nb = models.Container.objects.count() - self.assertEqual(container_nb + len(self.container_types), - new_container_nb) + self.assertEqual(container_nb + len(self.container_types), new_container_nb) value = "A;42;allée 4" - error = self.warehouse._add_localisations( - None, value, return_errors=True) + error = self.warehouse._add_localisations(None, value, return_errors=True) self.assertIsNone(error) # only create a new container self.assertEqual(new_container_nb + 1, models.Container.objects.count()) @@ -541,13 +523,13 @@ class WarehouseTest(TestCase): parent__location=self.warehouse, location=self.warehouse, container_type=self.container_types[2], - reference="allée 4") + reference="allée 4", + ) self.assertEqual(q.count(), 1) # test with an empty localisation value = "A;42;;35" - error = self.warehouse._add_localisations( - None, value, return_errors=True) + error = self.warehouse._add_localisations(None, value, return_errors=True) self.assertIsNone(error) q = models.Container.objects.filter( parent__reference="42", @@ -555,7 +537,8 @@ class WarehouseTest(TestCase): parent__location=self.warehouse, location=self.warehouse, container_type=self.container_types[3], - reference="35") + reference="35", + ) self.assertEqual(q.count(), 1) @@ -564,39 +547,37 @@ class ContainerTest(FindInit, TestCase): def setUp(self): self.main_warehouse = models.Warehouse.objects.create( - name="Main", - warehouse_type=models.WarehouseType.objects.all()[0] + name="Main", warehouse_type=models.WarehouseType.objects.all()[0] ) - self.division = models.WarehouseDivision.objects.create( - label='division') - self.alt_division = models.WarehouseDivision.objects.create( - label='division2') + self.division = models.WarehouseDivision.objects.create(label="division") + self.alt_division = models.WarehouseDivision.objects.create(label="division2") self.div_link = models.WarehouseDivisionLink.objects.create( - warehouse=self.main_warehouse, division=self.division) + warehouse=self.main_warehouse, division=self.division + ) self.alt_warehouse = models.Warehouse.objects.create( - name="Alt", - warehouse_type=models.WarehouseType.objects.all()[0] + name="Alt", warehouse_type=models.WarehouseType.objects.all()[0] ) def test_container_search(self): ct = models.ContainerType.objects.order_by("id").all()[0] ct2 = models.ContainerType.objects.order_by("id").all()[1] container_1 = models.Container.objects.create( - reference="Test", responsible=self.main_warehouse, + reference="Test", + responsible=self.main_warehouse, location=self.main_warehouse, - container_type=ct + container_type=ct, ) container_2 = models.Container.objects.create( - reference="35000", responsible=self.main_warehouse, + reference="35000", + responsible=self.main_warehouse, parent=container_1, location=self.main_warehouse, - container_type=ct2 + container_type=ct2, ) container_2.index = 42000 container_2.save() username, password, user = create_user() - user.user_permissions.add(Permission.objects.get( - codename='view_warehouse')) + user.user_permissions.add(Permission.objects.get(codename="view_warehouse")) client = Client() client.login(username=username, password=password) url = "/autocomplete-container/{}/".format(self.main_warehouse.pk) @@ -620,50 +601,57 @@ class ContainerTest(FindInit, TestCase): def test_form_creation(self): data = { - 'reference': 'hop-ref', + "reference": "hop-ref", "responsible": self.main_warehouse.pk, "location": self.main_warehouse.pk, - "container_type": models.ContainerType.objects.all()[0].pk + "container_type": models.ContainerType.objects.all()[0].pk, } form = forms.ContainerForm(data=data) self.assertTrue(form.is_valid(), msg="{}".format(form.errors)) self.container_number = models.Container.objects.count() self.create_user() form.save(self.user) - self.assertEqual(models.Container.objects.count(), - self.container_number + 1) + self.assertEqual(models.Container.objects.count(), self.container_number + 1) def test_change_location(self): container = models.Container.objects.create( - reference="Test", responsible=self.main_warehouse, + reference="Test", + responsible=self.main_warehouse, location=self.main_warehouse, - container_type=models.ContainerType.objects.all()[0] + container_type=models.ContainerType.objects.all()[0], ) container.save() container = models.Container.objects.get(pk=container.pk) container_2 = models.Container.objects.create( - reference="Test2", responsible=self.main_warehouse, + reference="Test2", + responsible=self.main_warehouse, location=self.main_warehouse, container_type=models.ContainerType.objects.all()[0], - parent=container + parent=container, ) self.assertIn(self.main_warehouse.name, container.cached_location) models.ContainerLocalisation.objects.create( - container=container, division=self.div_link, + container=container, + division=self.div_link, ) - self.assertTrue(models.ContainerLocalisation.objects.filter( - division__warehouse=self.main_warehouse).count()) + self.assertTrue( + models.ContainerLocalisation.objects.filter( + division__warehouse=self.main_warehouse + ).count() + ) # changing location remove irrelevant localisation other_warehouse = models.Warehouse.objects.create( - name="Other", - warehouse_type=models.WarehouseType.objects.all()[0] + name="Other", warehouse_type=models.WarehouseType.objects.all()[0] ) container.location = other_warehouse container.save() - self.assertFalse(models.ContainerLocalisation.objects.filter( - division__warehouse=self.main_warehouse).count()) + self.assertFalse( + models.ContainerLocalisation.objects.filter( + division__warehouse=self.main_warehouse + ).count() + ) container_2 = models.Container.objects.get(pk=container_2.pk) self.assertEqual(container_2.location, other_warehouse) @@ -710,24 +698,21 @@ class ContainerTest(FindInit, TestCase): def test_update_containers_on_warehouse_update(self): container = models.Container.objects.create( - reference="Test", responsible=self.main_warehouse, + reference="Test", + responsible=self.main_warehouse, location=self.main_warehouse, - container_type=models.ContainerType.objects.all()[0] + container_type=models.ContainerType.objects.all()[0], ) container.save() container = models.Container.objects.get(pk=container.pk) self.assertIn(self.main_warehouse.name, container.cached_location) self.main_warehouse.name = "New name" self.main_warehouse.save() + self.assertEqual(models.Container.objects.filter(need_update=True).count(), 1) self.assertEqual( - models.Container.objects.filter( - need_update=True - ).count(), 1) - self.assertEqual( - models.Container.objects.filter( - pk=container.pk, - need_update=True - ).count(), 1) + models.Container.objects.filter(pk=container.pk, need_update=True).count(), + 1, + ) container = models.Container.objects.get(pk=container.pk) # process pending update container.skip_history_when_saving = True @@ -738,15 +723,17 @@ class ContainerTest(FindInit, TestCase): def test_update_container_localisation_on_warehouse_update(self): profile, created = IshtarSiteProfile.objects.get_or_create( - slug='default', active=True) + slug="default", active=True + ) profile.mapping = True profile.locate_warehouses = True profile.save() wgs84 = SpatialReferenceSystem.objects.get(srid=4326) container = models.Container.objects.create( - reference="Test", responsible=self.main_warehouse, + reference="Test", + responsible=self.main_warehouse, location=self.main_warehouse, - container_type=models.ContainerType.objects.all()[0] + container_type=models.ContainerType.objects.all()[0], ) container.save() self.assertEqual(container.x, None) @@ -757,10 +744,9 @@ class ContainerTest(FindInit, TestCase): main_warehouse.save() # an update is pending self.assertEqual( - models.Container.objects.filter( - pk=container.pk, - need_update=True - ).count(), 1) + models.Container.objects.filter(pk=container.pk, need_update=True).count(), + 1, + ) # process pending update container = models.Container.objects.get(pk=container.pk) @@ -775,64 +761,70 @@ class ContainerTest(FindInit, TestCase): def test_external_id(self): ct = models.ContainerType.objects.all()[0] container_1 = models.Container.objects.create( - reference="Test", responsible=self.main_warehouse, + reference="Test", + responsible=self.main_warehouse, location=self.main_warehouse, - container_type=ct + container_type=ct, ) container_2 = models.Container.objects.create( - reference="Test 2", responsible=self.main_warehouse, + reference="Test 2", + responsible=self.main_warehouse, parent=container_1, location=self.main_warehouse, - container_type=ct + container_type=ct, ) container_3 = models.Container.objects.create( - reference="Test 3", responsible=self.main_warehouse, + reference="Test 3", + responsible=self.main_warehouse, parent=container_2, location=self.main_warehouse, - container_type=ct + container_type=ct, ) self.assertEqual( container_1.external_id, "{}-{}-{}".format( - self.main_warehouse.external_id, ct.txt_idx, - container_1.reference)) + self.main_warehouse.external_id, ct.txt_idx, container_1.reference + ), + ) self.assertEqual( container_2.external_id, "{}-{}-{}".format( - container_1.external_id, ct.txt_idx, - container_2.reference)) + container_1.external_id, ct.txt_idx, container_2.reference + ), + ) self.assertEqual( container_3.external_id, "{}-{}-{}".format( - container_2.external_id, ct.txt_idx, - container_3.reference)) + container_2.external_id, ct.txt_idx, container_3.reference + ), + ) def test_merge_candidate(self): ct = models.ContainerType.objects.all()[0] container_1 = models.Container.objects.create( - reference="Test", responsible=self.main_warehouse, + reference="Test", + responsible=self.main_warehouse, location=self.main_warehouse, - container_type=ct) + container_type=ct, + ) init_mc = container_1.merge_candidate.count() container_2 = models.Container.objects.create( - reference="TEST", responsible=self.main_warehouse, + reference="TEST", + responsible=self.main_warehouse, location=self.main_warehouse, - container_type=ct) - self.assertEqual(container_1.merge_candidate.count(), - init_mc + 1) + container_type=ct, + ) + self.assertEqual(container_1.merge_candidate.count(), init_mc + 1) container_1.archive() - self.assertEqual(container_1.merge_candidate.count(), - init_mc) + self.assertEqual(container_1.merge_candidate.count(), init_mc) container_1 = models.Container.objects.get(pk=container_1.pk) container_1.archived = False container_1.save() container_2 = models.Container.objects.get(pk=container_2.pk) - self.assertEqual(container_1.merge_candidate.count(), - init_mc + 1) + self.assertEqual(container_1.merge_candidate.count(), init_mc + 1) container_2.location = self.alt_warehouse container_2.save() - self.assertEqual(container_1.merge_candidate.count(), - init_mc) + self.assertEqual(container_1.merge_candidate.count(), init_mc) def test_merge_container(self): ct = models.ContainerType.objects.all()[0] @@ -845,9 +837,8 @@ class ContainerTest(FindInit, TestCase): find2 = self.finds[2] container_1 = models.Container.objects.create( - reference="Test 1", - location=self.main_warehouse, - container_type=ct) + reference="Test 1", location=self.main_warehouse, container_type=ct + ) find0.container = container_1 find0.container_ref = container_1 find0.save() @@ -856,20 +847,18 @@ class ContainerTest(FindInit, TestCase): find1.save() container_2 = models.Container.objects.create( - reference="Test 2", - location=self.alt_warehouse, - container_type=ct2) + reference="Test 2", location=self.alt_warehouse, container_type=ct2 + ) find2.container = container_2 find2.container_ref = container_2 find2.save() container_1.merge(container_2) container_1 = models.Container.objects.get(pk=container_1.pk) - self.assertEqual( - models.Container.objects.filter(pk=container_2.pk).count(), 0) + self.assertEqual(models.Container.objects.filter(pk=container_2.pk).count(), 0) # preserve existing fields - self.assertEqual(container_1.reference, 'Test 1') + self.assertEqual(container_1.reference, "Test 1") self.assertEqual(container_1.container_type, ct) find_lst = [f for f in container_1.finds.all()] for f in [find0, find1, find2]: @@ -889,17 +878,15 @@ class ContainerTest(FindInit, TestCase): find3 = self.finds[3] top_container_1 = models.Container.objects.create( - reference="Topref 1", - location=self.main_warehouse, - container_type=ct) + reference="Topref 1", location=self.main_warehouse, container_type=ct + ) find0.container = top_container_1 find0.container_ref = top_container_1 find0.save() top_container_2 = models.Container.objects.create( - reference="Topref 2", - location=self.alt_warehouse, - container_type=ct) + reference="Topref 2", location=self.alt_warehouse, container_type=ct + ) find1.container = top_container_2 find1.container_ref = top_container_2 find1.save() @@ -908,7 +895,8 @@ class ContainerTest(FindInit, TestCase): reference="Middle ref", location=self.main_warehouse, parent=top_container_1, - container_type=ct2) + container_type=ct2, + ) find2.container = middle_container_1 find2.container_ref = middle_container_1 find2.save() @@ -917,13 +905,15 @@ class ContainerTest(FindInit, TestCase): reference="Middle ref", location=self.alt_warehouse, parent=top_container_2, - container_type=ct2) + container_type=ct2, + ) bottom_container_3 = models.Container.objects.create( reference="Bottom ref", location=self.alt_warehouse, parent=middle_container_2, - container_type=ct3) + container_type=ct3, + ) find3.container = bottom_container_3 find3.container_ref = bottom_container_3 find3.save() @@ -956,8 +946,7 @@ class ContainerTest(FindInit, TestCase): def test_bulk_update(self): username, password, user = create_user() - user.user_permissions.add(Permission.objects.get( - codename='change_container')) + user.user_permissions.add(Permission.objects.get(codename="change_container")) client = Client() ct = models.ContainerType.objects.all()[0] @@ -966,34 +955,32 @@ class ContainerTest(FindInit, TestCase): container_parent = models.Container.objects.create( reference="Parent container", location=self.main_warehouse, - container_type=ct) + container_type=ct, + ) container_parent2 = models.Container.objects.create( reference="Parent container 2", location=self.alt_warehouse, - container_type=ct) + container_type=ct, + ) container = models.Container.objects.create( reference="Test", location=self.main_warehouse, parent=container_parent, - container_type=ct2) + container_type=ct2, + ) # base modification - url = reverse('container-qa-bulk-update', args=[container.pk]) - data = { - "qacontainer_type": ct.pk, - "qalocation": '', - "qaparent": '' - } + url = reverse("container-qa-bulk-update", args=[container.pk]) + data = {"qacontainer_type": ct.pk, "qalocation": "", "qaparent": ""} response = client.post(url, data) - self.assertRedirects(response, '/') + self.assertRedirects(response, "/") client.login(username=username, password=password) response = client.post(url, data) self.assertEqual(response.status_code, 200) - confirm_url = reverse( - 'container-qa-bulk-update-confirm', args=[container.pk]) + confirm_url = reverse("container-qa-bulk-update-confirm", args=[container.pk]) response = client.post(confirm_url, data) - self.assertRedirects(response, '/success/') + self.assertRedirects(response, "/success/") container = models.Container.objects.get(pk=container.pk) self.assertEqual(container.container_type_id, ct.pk) @@ -1002,12 +989,12 @@ class ContainerTest(FindInit, TestCase): container.save() data = { - "qacontainer_type": '', + "qacontainer_type": "", "qalocation": self.alt_warehouse.pk, - "qaparent": container_parent2.pk + "qaparent": container_parent2.pk, } response = client.post(confirm_url, data) - self.assertRedirects(response, '/success/') + self.assertRedirects(response, "/success/") container = models.Container.objects.get(pk=container.pk) self.assertEqual(container.location, self.alt_warehouse) @@ -1020,14 +1007,15 @@ class ContainerTest(FindInit, TestCase): # change location of children data = { - "qacontainer_type": '', + "qacontainer_type": "", "qalocation": self.alt_warehouse.pk, - "qaparent": '' + "qaparent": "", } confirm_parent_url = reverse( - 'container-qa-bulk-update-confirm', args=[container_parent.pk]) + "container-qa-bulk-update-confirm", args=[container_parent.pk] + ) response = client.post(confirm_parent_url, data) - self.assertRedirects(response, '/success/') + self.assertRedirects(response, "/success/") container_parent = models.Container.objects.get(pk=container_parent.pk) self.assertEqual(container_parent.location, self.alt_warehouse) @@ -1043,12 +1031,12 @@ class ContainerTest(FindInit, TestCase): # reinit parent when not provided and location changed data = { - "qacontainer_type": '', + "qacontainer_type": "", "qalocation": self.alt_warehouse.pk, - "qaparent": '' + "qaparent": "", } response = client.post(confirm_url, data) - self.assertRedirects(response, '/success/') + self.assertRedirects(response, "/success/") container = models.Container.objects.get(pk=container.pk) self.assertEqual(container.location, self.alt_warehouse) self.assertEqual(container.parent, None) @@ -1061,44 +1049,41 @@ class ContainerTest(FindInit, TestCase): ct2.stationary = True ct2.save() - q = models.Container.objects.filter( - location=self.main_warehouse).order_by("-index") + q = models.Container.objects.filter(location=self.main_warehouse).order_by( + "-index" + ) if q.count(): base_index = q.all()[0].index else: base_index = 0 container_1 = models.Container.objects.create( - reference="Ref 1", - location=self.main_warehouse, - container_type=ct) - self.assertEqual(models.Container.objects.get(pk=container_1.pk).index, - base_index + 1) + reference="Ref 1", location=self.main_warehouse, container_type=ct + ) + self.assertEqual( + models.Container.objects.get(pk=container_1.pk).index, base_index + 1 + ) container_2 = models.Container.objects.create( - reference="Ref 2", - location=self.main_warehouse, - container_type=ct) - self.assertEqual(models.Container.objects.get(pk=container_2.pk).index, - base_index + 2) + reference="Ref 2", location=self.main_warehouse, container_type=ct + ) + self.assertEqual( + models.Container.objects.get(pk=container_2.pk).index, base_index + 2 + ) container_3 = models.Container.objects.create( - reference="Ref 3", - location=self.main_warehouse, - container_type=ct2) + reference="Ref 3", location=self.main_warehouse, container_type=ct2 + ) self.assertEqual(container_3.index, None) - self.assertEqual(models.Container.objects.get(pk=container_3.pk).index, - None) + self.assertEqual(models.Container.objects.get(pk=container_3.pk).index, None) container_4 = models.Container.objects.create( - reference="Ref 4", - location=self.main_warehouse, - container_type=ct2) + reference="Ref 4", location=self.main_warehouse, container_type=ct2 + ) self.assertEqual(container_4.index, None) - self.assertEqual(models.Container.objects.get(pk=container_4.pk).index, - None) + self.assertEqual(models.Container.objects.get(pk=container_4.pk).index, None) container_5 = models.Container.objects.create( - reference="Ref 5", - location=self.main_warehouse, - container_type=ct) - self.assertEqual(models.Container.objects.get(pk=container_5.pk).index, - base_index + 3) + reference="Ref 5", location=self.main_warehouse, container_type=ct + ) + self.assertEqual( + models.Container.objects.get(pk=container_5.pk).index, base_index + 3 + ) def test_get_material_types(self): mat0 = MaterialType.objects.all()[0] @@ -1117,13 +1102,11 @@ class ContainerTest(FindInit, TestCase): find2 = self.finds[2] container_1 = models.Container.objects.create( - reference="Test 1", - location=self.main_warehouse, - container_type=ct) + reference="Test 1", location=self.main_warehouse, container_type=ct + ) container_2 = models.Container.objects.create( - reference="Test 2", - location=self.alt_warehouse, - container_type=ct) + reference="Test 2", location=self.alt_warehouse, container_type=ct + ) find0.container = container_1 find0.save() find1.container = container_1 @@ -1133,16 +1116,16 @@ class ContainerTest(FindInit, TestCase): find1.save() # no material inside this container - self.assertEqual( - container_2.get_material_types(), "") + self.assertEqual(container_2.get_material_types(), "") self.assertEqual( container_1.get_material_types(), - ", ".join(sorted([mat0.label, mat1.label, mat2.label])) + ", ".join(sorted([mat0.label, mat1.label, mat2.label])), ) self.assertEqual( container_1.get_material_types_code(), - "|".join(sorted([mat0.code, mat1.code, mat2.code]))) + "|".join(sorted([mat0.code, mat1.code, mat2.code])), + ) def test_calculated_weight(self): self.create_finds() @@ -1160,9 +1143,8 @@ class ContainerTest(FindInit, TestCase): ct.tare_weight = 200 ct.save() container_1 = models.Container.objects.create( - reference="Test 1", - location=self.main_warehouse, - container_type=ct) + reference="Test 1", location=self.main_warehouse, container_type=ct + ) container_1.save() self.assertEqual(container_1.calculated_weight, 200) self.assertEqual(container_1.cached_weight, 200) @@ -1188,7 +1170,8 @@ class ContainerTest(FindInit, TestCase): self.assertEqual(container_1.cached_weight, 1500) profile, created = IshtarSiteProfile.objects.get_or_create( - slug='default', active=True) + slug="default", active=True + ) profile.calculate_weight_on_full = True profile.save() @@ -1210,4 +1193,3 @@ class ContainerTest(FindInit, TestCase): container_1 = models.Container.objects.get(pk=container_1.pk) self.assertEqual(container_1.calculated_weight, None) self.assertEqual(container_1.cached_weight, None) - diff --git a/archaeological_warehouse/urls.py b/archaeological_warehouse/urls.py index 46d812def..4a7ee9d09 100644 --- a/archaeological_warehouse/urls.py +++ b/archaeological_warehouse/urls.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2010-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> @@ -28,112 +28,196 @@ from archaeological_warehouse import models # forms urlpatterns = [ - url(r'warehouse_packaging/(?P<step>.+)?$', # AFAC - check_rights(['change_find', 'change_own_find'])( - views.warehouse_packaging_wizard), name='warehouse_packaging'), - - url(r'new-warehouse/(?P<parent_name>.+)?/$', - views.new_warehouse, name='new-warehouse'), - url(r'^show-warehouse(?:/(?P<pk>.+))?/(?P<type>.+)?$', views.show_warehouse, - name=models.Warehouse.SHOW_URL), - url(r'^show-historized-warehouse/(?P<pk>.+)?/(?P<date>.+)?$', - views.show_warehouse, name='show-historized-warehouse'), - url(r'^revert-warehouse/(?P<pk>.+)/(?P<date>.+)$', - views.revert_warehouse, name='revert-warehouse'), - url(r'autocomplete-warehouse/$', views.autocomplete_warehouse, - name='autocomplete-warehouse'), - url(r'new-container/(?P<parent_name>.+)?/$', - views.new_container, name='new-container'), - url(r'get-container/(?P<type>.+)?$', views.get_container, - name='get-container'), - url(r'get-divisions-container/(?P<type>.+)?$', - views.get_divisions_container, name='get-divisions-container'), - url(r'get-non-divisions-container/(?P<type>.+)?$', - views.get_non_divisions_container, name='get-non-divisions-container'), - url(r'get-warehouse/(?P<type>.+)?$', views.get_warehouse, - name='get-warehouse'), - url(r'get-warehouse-shortcut/(?P<type>.+)?$', - views.get_warehouse, name='get-warehouse-shortcut', - kwargs={'full': 'shortcut'}), - url(r'autocomplete-container/(?P<warehouse_id>\d+)?(?:/)?$', - views.autocomplete_container, name='autocomplete-container'), - url(r'^show-container(?:/(?P<pk>.+))?/(?P<type>.+)?$', views.show_container, - name=models.Container.SHOW_URL), - url(r'^warehouse_search/(?P<step>.+)?$', - check_rights(['view_warehouse', 'view_own_warehouse'])( - views.warehouse_search_wizard), name='warehouse_search'), - url(r'^warehouse_creation/(?P<step>.+)?$', - check_rights(['add_warehouse'])( - views.warehouse_creation_wizard), name='warehouse_creation'), - url(r'^warehouse_modification/(?P<step>.+)?$', - check_rights(['change_warehouse'])( - views.warehouse_modification_wizard), - name='warehouse_modification'), - url(r'warehouse-modify/(?P<pk>.+)/$', - views.warehouse_modify, name='warehouse_modify'), - url(r'^warehouse_deletion/(?P<step>.+)?$', - check_rights(['change_warehouse'])( - views.warehouse_deletion_wizard), - name='warehouse_deletion'), - url(r'warehouse-delete/(?P<pk>.+)/$', - views.warehouse_delete, name='delete-warehouse'), - - url(r'^warehouse-qa-lock/(?P<pks>[0-9-]+)?/$', - views.QAWarehouseLockView.as_view(), name='warehouse-qa-lock', - kwargs={"model": models.Warehouse}), - - url(r'^container-add-treatment/(?P<pk>[0-9-]+)/$', - check_rights(['change_find', 'change_own_find'])( - views.container_treatment_add), - name='container-add-treatment'), - - url(r'^container_search/(?P<step>.+)?$', - check_rights(['view_container', 'view_own_container'])( - views.container_search_wizard), - name='container_search'), - url(r'^container_creation/(?P<step>.+)?$', - check_rights(['add_container', 'add_own_container'])( - views.container_creation_wizard), - name='container_creation'), - url(r'^container_modification/(?P<step>.+)?$', - check_rights(['change_container', 'change_own_container'])( - views.container_modification_wizard), - name='container_modification'), - url(r'container-modify/(?P<pk>.+)/$', - views.container_modify, name='container_modify'), - url(r'^container_deletion/(?P<step>.+)?$', - check_rights(['change_container', 'change_own_container'])( - views.container_deletion_wizard), - name='container_deletion'), - url(r'container-delete/(?P<pk>.+)/$', - views.container_delete, name='delete-container'), - - url(r'^container-qa-bulk-update/(?P<pks>[0-9-]+)?/$', - check_rights(['change_container', 'change_own_container'])( - views.QAContainerForm.as_view()), - name='container-qa-bulk-update'), - url(r'^container-qa-bulk-update/(?P<pks>[0-9-]+)?/confirm/$', - check_rights(['change_container', 'change_own_container'])( - views.QAContainerForm.as_view()), - name='container-qa-bulk-update-confirm', kwargs={"confirm": True}), - url(r'^container-qa-lock/(?P<pks>[0-9-]+)?/$', - views.QAContainerLockView.as_view(), name='container-qa-lock', - kwargs={"model": models.Container}), - - url(r'container-merge/(?:(?P<page>\d+)/)?$', views.container_merge, - name='container_merge'), - url(r'container-manual-merge/$', + url( + r"warehouse_packaging/(?P<step>.+)?$", # AFAC + check_rights(["change_find", "change_own_find"])( + views.warehouse_packaging_wizard + ), + name="warehouse_packaging", + ), + url( + r"new-warehouse/(?P<parent_name>.+)?/$", + views.new_warehouse, + name="new-warehouse", + ), + url( + r"^show-warehouse(?:/(?P<pk>.+))?/(?P<type>.+)?$", + views.show_warehouse, + name=models.Warehouse.SHOW_URL, + ), + url( + r"^show-historized-warehouse/(?P<pk>.+)?/(?P<date>.+)?$", + views.show_warehouse, + name="show-historized-warehouse", + ), + url( + r"^revert-warehouse/(?P<pk>.+)/(?P<date>.+)$", + views.revert_warehouse, + name="revert-warehouse", + ), + url( + r"autocomplete-warehouse/$", + views.autocomplete_warehouse, + name="autocomplete-warehouse", + ), + url( + r"new-container/(?P<parent_name>.+)?/$", + views.new_container, + name="new-container", + ), + url(r"get-container/(?P<type>.+)?$", views.get_container, name="get-container"), + url( + r"get-divisions-container/(?P<type>.+)?$", + views.get_divisions_container, + name="get-divisions-container", + ), + url( + r"get-non-divisions-container/(?P<type>.+)?$", + views.get_non_divisions_container, + name="get-non-divisions-container", + ), + url(r"get-warehouse/(?P<type>.+)?$", views.get_warehouse, name="get-warehouse"), + url( + r"get-warehouse-shortcut/(?P<type>.+)?$", + views.get_warehouse, + name="get-warehouse-shortcut", + kwargs={"full": "shortcut"}, + ), + url( + r"autocomplete-container/(?P<warehouse_id>\d+)?(?:/)?$", + views.autocomplete_container, + name="autocomplete-container", + ), + url( + r"^show-container(?:/(?P<pk>.+))?/(?P<type>.+)?$", + views.show_container, + name=models.Container.SHOW_URL, + ), + url( + r"^warehouse_search/(?P<step>.+)?$", + check_rights(["view_warehouse", "view_own_warehouse"])( + views.warehouse_search_wizard + ), + name="warehouse_search", + ), + url( + r"^warehouse_creation/(?P<step>.+)?$", + check_rights(["add_warehouse"])(views.warehouse_creation_wizard), + name="warehouse_creation", + ), + url( + r"^warehouse_modification/(?P<step>.+)?$", + check_rights(["change_warehouse"])(views.warehouse_modification_wizard), + name="warehouse_modification", + ), + url( + r"warehouse-modify/(?P<pk>.+)/$", + views.warehouse_modify, + name="warehouse_modify", + ), + url( + r"^warehouse_deletion/(?P<step>.+)?$", + check_rights(["change_warehouse"])(views.warehouse_deletion_wizard), + name="warehouse_deletion", + ), + url( + r"warehouse-delete/(?P<pk>.+)/$", + views.warehouse_delete, + name="delete-warehouse", + ), + url( + r"^warehouse-qa-lock/(?P<pks>[0-9-]+)?/$", + views.QAWarehouseLockView.as_view(), + name="warehouse-qa-lock", + kwargs={"model": models.Warehouse}, + ), + url( + r"^container-add-treatment/(?P<pk>[0-9-]+)/$", + check_rights(["change_find", "change_own_find"])(views.container_treatment_add), + name="container-add-treatment", + ), + url( + r"^container_search/(?P<step>.+)?$", + check_rights(["view_container", "view_own_container"])( + views.container_search_wizard + ), + name="container_search", + ), + url( + r"^container_creation/(?P<step>.+)?$", + check_rights(["add_container", "add_own_container"])( + views.container_creation_wizard + ), + name="container_creation", + ), + url( + r"^container_modification/(?P<step>.+)?$", + check_rights(["change_container", "change_own_container"])( + views.container_modification_wizard + ), + name="container_modification", + ), + url( + r"container-modify/(?P<pk>.+)/$", + views.container_modify, + name="container_modify", + ), + url( + r"^container_deletion/(?P<step>.+)?$", + check_rights(["change_container", "change_own_container"])( + views.container_deletion_wizard + ), + name="container_deletion", + ), + url( + r"container-delete/(?P<pk>.+)/$", + views.container_delete, + name="delete-container", + ), + url( + r"^container-qa-bulk-update/(?P<pks>[0-9-]+)?/$", + check_rights(["change_container", "change_own_container"])( + views.QAContainerForm.as_view() + ), + name="container-qa-bulk-update", + ), + url( + r"^container-qa-bulk-update/(?P<pks>[0-9-]+)?/confirm/$", + check_rights(["change_container", "change_own_container"])( + views.QAContainerForm.as_view() + ), + name="container-qa-bulk-update-confirm", + kwargs={"confirm": True}, + ), + url( + r"^container-qa-lock/(?P<pks>[0-9-]+)?/$", + views.QAContainerLockView.as_view(), + name="container-qa-lock", + kwargs={"model": models.Container}, + ), + url( + r"container-merge/(?:(?P<page>\d+)/)?$", + views.container_merge, + name="container_merge", + ), + url( + r"container-manual-merge/$", views.ContainerManualMerge.as_view(), - name='container_manual_merge'), - url(r'container-manual-merge-items/(?P<pks>[0-9_]+?)/$', + name="container_manual_merge", + ), + url( + r"container-manual-merge-items/(?P<pks>[0-9_]+?)/$", views.ContainerManualMergeItems.as_view(), - name='container_manual_merge_items'), - - url(r'generate-stats-container/(?P<pk>.+)/', + name="container_manual_merge_items", + ), + url( + r"generate-stats-container/(?P<pk>.+)/", views.GenerateStatsContainer.as_view(), - name='generate-stats-container'), - - url(r'generate-stats-warehouse/(?P<pk>.+)/', + name="generate-stats-container", + ), + url( + r"generate-stats-warehouse/(?P<pk>.+)/", views.GenerateStatsWarehouse.as_view(), - name='generate-stats-warehouse'), + name="generate-stats-warehouse", + ), ] diff --git a/archaeological_warehouse/views.py b/archaeological_warehouse/views.py index 2702e71c3..4fa60ff89 100644 --- a/archaeological_warehouse/views.py +++ b/archaeological_warehouse/views.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2010-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> @@ -32,72 +32,97 @@ from archaeological_warehouse import forms from ishtar_common.forms import FinalForm -from ishtar_common.views import QABaseLockView, wizard_is_available, \ - merge_action, ManualMergeMixin, ManualMergeItemsMixin, IshtarMixin, \ - LoginRequiredMixin, QAItemEditForm -from ishtar_common.views_item import get_item, show_item, new_qa_item, \ - revert_item +from ishtar_common.views import ( + QABaseLockView, + wizard_is_available, + merge_action, + ManualMergeMixin, + ManualMergeItemsMixin, + IshtarMixin, + LoginRequiredMixin, + QAItemEditForm, +) +from ishtar_common.views_item import get_item, show_item, new_qa_item, revert_item from archaeological_finds.views import treatment_add -from archaeological_warehouse.wizards import PackagingWizard, WarehouseSearch, \ - WarehouseWizard, WarehouseModificationWizard, WarehouseDeletionWizard, \ - ContainerSearch, ContainerWizard, ContainerModificationWizard, \ - ContainerDeletionWizard +from archaeological_warehouse.wizards import ( + PackagingWizard, + WarehouseSearch, + WarehouseWizard, + WarehouseModificationWizard, + WarehouseDeletionWizard, + ContainerSearch, + ContainerWizard, + ContainerModificationWizard, + ContainerDeletionWizard, +) -get_container = get_item(models.Container, 'get_container', 'container', - search_form=forms.ContainerSelect) +get_container = get_item( + models.Container, "get_container", "container", search_form=forms.ContainerSelect +) get_divisions_container = get_item( - models.Container, 'get_container', 'container', + models.Container, + "get_container", + "container", search_form=forms.ContainerSelect, - base_request={"container_type__stationary": 'True'}) + base_request={"container_type__stationary": "True"}, +) get_non_divisions_container = get_item( - models.Container, 'get_container', 'container', + models.Container, + "get_container", + "container", search_form=forms.ContainerSelect, - base_request={"container_type__stationary": 'False'}) -show_container = show_item(models.Container, 'container') + base_request={"container_type__stationary": "False"}, +) +show_container = show_item(models.Container, "container") -get_warehouse = get_item(models.Warehouse, 'get_warehouse', 'warehouse', - search_form=forms.WarehouseSelect) -show_warehouse = show_item(models.Warehouse, 'warehouse') +get_warehouse = get_item( + models.Warehouse, "get_warehouse", "warehouse", search_form=forms.WarehouseSelect +) +show_warehouse = show_item(models.Warehouse, "warehouse") revert_warehouse = revert_item(models.Warehouse) -new_warehouse = new_qa_item(models.Warehouse, forms.WarehouseForm, - page_name=_("New warehouse")) -new_container = new_qa_item(models.Container, forms.ContainerForm, - page_name=_("New container")) +new_warehouse = new_qa_item( + models.Warehouse, forms.WarehouseForm, page_name=_("New warehouse") +) +new_container = new_qa_item( + models.Container, forms.ContainerForm, page_name=_("New container") +) def autocomplete_warehouse(request): - if not request.user.has_perm('ishtar_common.view_warehouse', - models.Warehouse)\ - and not request.user.has_perm( - 'ishtar_common.view_own_warehouse', models.Warehouse): - return HttpResponse(content_type='text/plain') - if not request.GET.get('term'): - return HttpResponse(content_type='text/plain') - q = request.GET.get('term') + if not request.user.has_perm( + "ishtar_common.view_warehouse", models.Warehouse + ) and not request.user.has_perm( + "ishtar_common.view_own_warehouse", models.Warehouse + ): + return HttpResponse(content_type="text/plain") + if not request.GET.get("term"): + return HttpResponse(content_type="text/plain") + q = request.GET.get("term") query = Q() - for q in q.split(' '): - extra = Q(name__icontains=q) | \ - Q(warehouse_type__label__icontains=q) + for q in q.split(" "): + extra = Q(name__icontains=q) | Q(warehouse_type__label__icontains=q) query = query & extra limit = 15 warehouses = models.Warehouse.objects.filter(query)[:limit] - data = json.dumps([{'id': warehouse.pk, 'value': str(warehouse)} - for warehouse in warehouses]) - return HttpResponse(data, content_type='text/plain') + data = json.dumps( + [{"id": warehouse.pk, "value": str(warehouse)} for warehouse in warehouses] + ) + return HttpResponse(data, content_type="text/plain") def autocomplete_container(request, warehouse_id=None): - if not request.user.has_perm('ishtar_common.view_warehouse', - models.Warehouse)\ - and not request.user.has_perm( - 'ishtar_common.view_own_warehouse', models.Warehouse): - return HttpResponse(content_type='text/plain') - if not request.GET.get('term'): - return HttpResponse(content_type='text/plain') - term = request.GET.get('term').strip() + if not request.user.has_perm( + "ishtar_common.view_warehouse", models.Warehouse + ) and not request.user.has_perm( + "ishtar_common.view_own_warehouse", models.Warehouse + ): + return HttpResponse(content_type="text/plain") + if not request.GET.get("term"): + return HttpResponse(content_type="text/plain") + term = request.GET.get("term").strip() limit = 15 base_query = Q() if warehouse_id: @@ -106,16 +131,18 @@ def autocomplete_container(request, warehouse_id=None): # exact index try: query = query & Q(index=int(term)) - containers = list(models.Container.objects.filter( - query).values('id', 'cached_label')[:limit]) + containers = list( + models.Container.objects.filter(query).values("id", "cached_label")[:limit] + ) except ValueError: containers = [] # exact ref query = query & Q(reference__unaccent__iexact=term) - containers += list(models.Container.objects.filter( - query).values('id', 'cached_label')[:limit]) + containers += list( + models.Container.objects.filter(query).values("id", "cached_label")[:limit] + ) limit = 15 - len(containers) - splitted = [s.lower() for s in term.split(' ') if s and s != '|'] + splitted = [s.lower() for s in term.split(" ") if s and s != "|"] if limit > 0 and len(splitted) > 1: type_positions = [] # container_type ID, pos inf, pos sup @@ -147,7 +174,8 @@ def autocomplete_container(request, warehouse_id=None): index = None if index_is_ok: type_positions.append( - (container_type_id, index, index + len(values))) + (container_type_id, index, index + len(values)) + ) query = base_query if not warehouse_id and type_positions and type_positions[0][1] > 0: @@ -155,12 +183,11 @@ def autocomplete_container(request, warehouse_id=None): query &= Q(location__name__icontains=splitted[idx]) # group by container type, ref tuple groups = [] - for idx, (container_type_id, pos_inf, pos_sup) \ - in enumerate(type_positions): + for idx, (container_type_id, pos_inf, pos_sup) in enumerate(type_positions): if len(type_positions) == idx + 1: # last value = " ".join(splitted[pos_sup:]) else: - value = " ".join(splitted[pos_sup:type_positions[idx + 1][1]]) + value = " ".join(splitted[pos_sup : type_positions[idx + 1][1]]) if value: groups.append((container_type_id, value)) if groups: @@ -171,9 +198,11 @@ def autocomplete_container(request, warehouse_id=None): key2 = base_key + "reference__unaccent__iexact" query &= Q(**{key1: g[0], key2: g[1]}) ids = {c["id"] for c in containers} - containers += list(models.Container.objects.filter( - query).exclude(pk__in=ids).values('id', 'cached_label')[ - :limit]) + containers += list( + models.Container.objects.filter(query) + .exclude(pk__in=ids) + .values("id", "cached_label")[:limit] + ) if len(splitted) > 1 and len(containers) < 15: # group to do a "type" "reference" search @@ -182,12 +211,15 @@ def autocomplete_container(request, warehouse_id=None): group_2 = splitted[idx:] extra = Q( container_type__label__unaccent__iexact=" ".join(group_1), - reference__unaccent__iexact=" ".join(group_2)) + reference__unaccent__iexact=" ".join(group_2), + ) query = base_query & extra ids = {c["id"] for c in containers} - containers += list(models.Container.objects.filter( - query).exclude(pk__in=ids).values('id', 'cached_label')[ - :limit]) + containers += list( + models.Container.objects.filter(query) + .exclude(pk__in=ids) + .values("id", "cached_label")[:limit] + ) if len(containers) >= 15: break @@ -197,92 +229,114 @@ def autocomplete_container(request, warehouse_id=None): extra = Q(reference__unaccent__iexact=q) query = query & extra ids = {c["id"] for c in containers} - containers += list(models.Container.objects.filter( - query).exclude(pk__in=ids).values('id', 'cached_label')[:limit]) + containers += list( + models.Container.objects.filter(query) + .exclude(pk__in=ids) + .values("id", "cached_label")[:limit] + ) limit = 15 - len(containers) if limit > 0: query = base_query for q in splitted: - extra = Q(container_type__label__unaccent__icontains=q) | \ - Q(container_type__reference__unaccent__icontains=q) | \ - Q(reference__unaccent__icontains=q) | \ - Q(cached_label__unaccent__icontains=q) + extra = ( + Q(container_type__label__unaccent__icontains=q) + | Q(container_type__reference__unaccent__icontains=q) + | Q(reference__unaccent__icontains=q) + | Q(cached_label__unaccent__icontains=q) + ) if not warehouse_id: extra |= Q(location__name__unaccent=q) | Q( - location__town__unaccent=q) + location__town__unaccent=q + ) query = query & extra ids = {c["id"] for c in containers} containers += list( - models.Container.objects.filter(query).exclude( - pk__in=ids - ).values('id', 'cached_label')[:limit]) + models.Container.objects.filter(query) + .exclude(pk__in=ids) + .values("id", "cached_label")[:limit] + ) data = json.dumps( - [{'id': container['id'], 'value': container['cached_label']} - for container in containers]) - return HttpResponse(data, content_type='text/plain') - -warehouse_packaging_wizard = PackagingWizard.as_view([ # AFAC - ('seleccontainer-packaging', forms.ContainerFormSelection), - ('base-packaging', forms.BasePackagingForm), - ('final-packaging', FinalForm)], + [ + {"id": container["id"], "value": container["cached_label"]} + for container in containers + ] + ) + return HttpResponse(data, content_type="text/plain") + + +warehouse_packaging_wizard = PackagingWizard.as_view( + [ # AFAC + ("seleccontainer-packaging", forms.ContainerFormSelection), + ("base-packaging", forms.BasePackagingForm), + ("final-packaging", FinalForm), + ], label=_("Packaging"), - url_name='warehouse_packaging',) + url_name="warehouse_packaging", +) -warehouse_search_wizard = WarehouseSearch.as_view([ - ('selec-warehouse_search', forms.WarehouseFormSelection)], +warehouse_search_wizard = WarehouseSearch.as_view( + [("selec-warehouse_search", forms.WarehouseFormSelection)], label=_("Warehouse search"), - url_name='warehouse_search', + url_name="warehouse_search", ) warehouse_creation_steps = [ ("warehouse-warehouse_creation", forms.WarehouseForm), - ('divisions-warehouse_creation', forms.SelectedDivisionFormset), - ('final-warehouse_creation', FinalForm)] + ("divisions-warehouse_creation", forms.SelectedDivisionFormset), + ("final-warehouse_creation", FinalForm), +] warehouse_creation_wizard = WarehouseWizard.as_view( warehouse_creation_steps, label=_("Warehouse creation"), - url_name='warehouse_creation', + url_name="warehouse_creation", ) -warehouse_modification_wizard = WarehouseModificationWizard.as_view([ - ('selec-warehouse_modification', forms.WarehouseFormSelection), - ("warehouse-warehouse_modification", forms.WarehouseModifyForm), - ('divisions-warehouse_modification', forms.SelectedDivisionFormset), - ('final-warehouse_modification', FinalForm)], +warehouse_modification_wizard = WarehouseModificationWizard.as_view( + [ + ("selec-warehouse_modification", forms.WarehouseFormSelection), + ("warehouse-warehouse_modification", forms.WarehouseModifyForm), + ("divisions-warehouse_modification", forms.SelectedDivisionFormset), + ("final-warehouse_modification", FinalForm), + ], label=_("Warehouse modification"), - url_name='warehouse_modification', + url_name="warehouse_modification", ) def warehouse_modify(request, pk): - if not wizard_is_available(warehouse_modification_wizard, request, - models.Warehouse, pk): + if not wizard_is_available( + warehouse_modification_wizard, request, models.Warehouse, pk + ): return HttpResponseRedirect("/") - wizard_url = 'warehouse_modification' + wizard_url = "warehouse_modification" WarehouseModificationWizard.session_set_value( - request, 'selec-' + wizard_url, 'pk', pk, reset=True) - return redirect( - reverse(wizard_url, kwargs={'step': 'warehouse-' + wizard_url})) + request, "selec-" + wizard_url, "pk", pk, reset=True + ) + return redirect(reverse(wizard_url, kwargs={"step": "warehouse-" + wizard_url})) -warehouse_deletion_wizard = WarehouseDeletionWizard.as_view([ - ('selec-warehouse_deletion', forms.WarehouseFormMultiSelection), - ('final-warehouse_deletion', forms.WarehouseDeletionForm)], +warehouse_deletion_wizard = WarehouseDeletionWizard.as_view( + [ + ("selec-warehouse_deletion", forms.WarehouseFormMultiSelection), + ("final-warehouse_deletion", forms.WarehouseDeletionForm), + ], label=_("Warehouse deletion"), - url_name='warehouse_deletion',) + url_name="warehouse_deletion", +) def warehouse_delete(request, pk): - if not wizard_is_available(warehouse_deletion_wizard, request, - models.Warehouse, pk): + if not wizard_is_available( + warehouse_deletion_wizard, request, models.Warehouse, pk + ): return HttpResponseRedirect("/") - wizard_url = 'warehouse_deletion' + wizard_url = "warehouse_deletion" WarehouseDeletionWizard.session_set_value( - request, 'selec-' + wizard_url, 'pks', pk, reset=True) - return redirect( - reverse(wizard_url, kwargs={'step': 'final-' + wizard_url})) + request, "selec-" + wizard_url, "pks", pk, reset=True + ) + return redirect(reverse(wizard_url, kwargs={"step": "final-" + wizard_url})) class QAWarehouseLockView(QABaseLockView): @@ -290,58 +344,66 @@ class QAWarehouseLockView(QABaseLockView): base_url = "warehouse-qa-lock" -container_search_wizard = ContainerSearch.as_view([ - ('selec-container_search', forms.MainContainerFormSelection)], +container_search_wizard = ContainerSearch.as_view( + [("selec-container_search", forms.MainContainerFormSelection)], label=_("Container search"), - url_name='container_search', + url_name="container_search", ) container_creation_steps = [ - ('container-container_creation', forms.ContainerForm), - ('final-container_creation', FinalForm)] + ("container-container_creation", forms.ContainerForm), + ("final-container_creation", FinalForm), +] container_creation_wizard = ContainerWizard.as_view( container_creation_steps, label=_("Container creation"), - url_name='container_creation', + url_name="container_creation", ) -container_modification_wizard = ContainerModificationWizard.as_view([ - ('selec-container_modification', forms.MainContainerFormSelection), - ('container-container_modification', forms.ContainerModifyForm), - ('final-container_modification', FinalForm)], +container_modification_wizard = ContainerModificationWizard.as_view( + [ + ("selec-container_modification", forms.MainContainerFormSelection), + ("container-container_modification", forms.ContainerModifyForm), + ("final-container_modification", FinalForm), + ], label=_("Container modification"), - url_name='container_modification', + url_name="container_modification", ) def container_modify(request, pk): - if not wizard_is_available(container_modification_wizard, request, - models.Container, pk): + if not wizard_is_available( + container_modification_wizard, request, models.Container, pk + ): return HttpResponseRedirect("/") - wizard_url = 'container_modification' + wizard_url = "container_modification" ContainerModificationWizard.session_set_value( - request, 'selec-' + wizard_url, 'pk', pk, reset=True) - return redirect( - reverse(wizard_url, kwargs={'step': 'container-' + wizard_url})) + request, "selec-" + wizard_url, "pk", pk, reset=True + ) + return redirect(reverse(wizard_url, kwargs={"step": "container-" + wizard_url})) -container_deletion_wizard = ContainerDeletionWizard.as_view([ - ('selec-container_deletion', forms.MainContainerFormMultiSelection), - ('final-container_deletion', forms.ContainerDeletionForm)], +container_deletion_wizard = ContainerDeletionWizard.as_view( + [ + ("selec-container_deletion", forms.MainContainerFormMultiSelection), + ("final-container_deletion", forms.ContainerDeletionForm), + ], label=_("Container deletion"), - url_name='container_deletion',) + url_name="container_deletion", +) def container_delete(request, pk): - if not wizard_is_available(container_deletion_wizard, request, - models.Container, pk): + if not wizard_is_available( + container_deletion_wizard, request, models.Container, pk + ): return HttpResponseRedirect("/") - wizard_url = 'container_deletion' + wizard_url = "container_deletion" ContainerDeletionWizard.session_set_value( - request, 'selec-' + wizard_url, 'pks', pk, reset=True) - return redirect( - reverse(wizard_url, kwargs={'step': 'final-' + wizard_url})) + request, "selec-" + wizard_url, "pks", pk, reset=True + ) + return redirect(reverse(wizard_url, kwargs={"step": "final-" + wizard_url})) def container_treatment_add(request, pk, current_right=None): @@ -349,9 +411,8 @@ def container_treatment_add(request, pk, current_right=None): container = models.Container.objects.get(pk=pk) except models.Container.DoesNotExist: raise Http404() - return treatment_add( - request, ",".join(str(f.pk) for f in container.finds.all()) - ) + return treatment_add(request, ",".join(str(f.pk) for f in container.finds.all())) + """ warehouse_packaging_wizard = ItemSourceWizard.as_view([ @@ -361,26 +422,27 @@ warehouse_packaging_wizard = ItemSourceWizard.as_view([ """ -container_merge = merge_action(models.Container, forms.MergeContainerForm, - 'container', name_key="reference") +container_merge = merge_action( + models.Container, forms.MergeContainerForm, "container", name_key="reference" +) -class ContainerManualMerge(ManualMergeMixin, IshtarMixin, LoginRequiredMixin, - FormView): +class ContainerManualMerge(ManualMergeMixin, IshtarMixin, LoginRequiredMixin, FormView): form_class = forms.ContainerMergeFormSelection - template_name = 'ishtar/form.html' + template_name = "ishtar/form.html" page_name = _("Merge containers") - current_url = 'container-manual-merge' - redir_url = 'container_manual_merge_items' + current_url = "container-manual-merge" + redir_url = "container_manual_merge_items" -class ContainerManualMergeItems(ManualMergeItemsMixin, IshtarMixin, - LoginRequiredMixin, FormView): +class ContainerManualMergeItems( + ManualMergeItemsMixin, IshtarMixin, LoginRequiredMixin, FormView +): form_class = forms.ContainerMergeIntoForm - template_name = 'ishtar/form.html' + template_name = "ishtar/form.html" page_name = _("Select the main container") - current_url = 'container-manual-merge-items' - item_type = 'container' + current_url = "container-manual-merge-items" + item_type = "container" class QAContainerLockView(QABaseLockView): @@ -390,13 +452,13 @@ class QAContainerLockView(QABaseLockView): def reset_wizards(request): for wizard_class, url_name in ( - (PackagingWizard, 'warehouse_packaging'), - (WarehouseWizard, 'warehouse_creation'), - (WarehouseModificationWizard, 'warehouse_modification'), - (WarehouseDeletionWizard, 'warehouse_deletion'), - (ContainerWizard, 'container_creation'), - (ContainerModificationWizard, 'container_modification'), - (ContainerDeletionWizard, 'container_deletion'), + (PackagingWizard, "warehouse_packaging"), + (WarehouseWizard, "warehouse_creation"), + (WarehouseModificationWizard, "warehouse_modification"), + (WarehouseDeletionWizard, "warehouse_deletion"), + (ContainerWizard, "container_creation"), + (ContainerModificationWizard, "container_modification"), + (ContainerDeletionWizard, "container_deletion"), ): wizard_class.session_reset(request, url_name) @@ -408,7 +470,7 @@ class QAContainerForm(QAItemEditForm): def get_form_kwargs(self): kwargs = super(QAContainerForm, self).get_form_kwargs() # item list is necessary to verify uniqueness rules - kwargs['items'] = self.items + kwargs["items"] = self.items return kwargs @@ -416,15 +478,16 @@ class GenerateStats(IshtarMixin, LoginRequiredMixin, RedirectView): model = None def get_redirect_url(self, *args, **kwargs): - return reverse('display-item', - args=[self.model.SLUG, self.item.pk]) + "#stats" + return reverse("display-item", args=[self.model.SLUG, self.item.pk]) + "#stats" def get(self, request, *args, **kwargs): - self.item = self.model.objects.get(pk=kwargs['pk']) - self.item._get_or_set_stats('_number_of_finds_by_place', update=True, - expected_type=list) - self.item._get_or_set_stats('_number_of_containers_by_place', - update=True, expected_type=list) + self.item = self.model.objects.get(pk=kwargs["pk"]) + self.item._get_or_set_stats( + "_number_of_finds_by_place", update=True, expected_type=list + ) + self.item._get_or_set_stats( + "_number_of_containers_by_place", update=True, expected_type=list + ) return super(GenerateStats, self).get(request, *args, **kwargs) diff --git a/archaeological_warehouse/wizards.py b/archaeological_warehouse/wizards.py index 614e6e6be..66da94b86 100644 --- a/archaeological_warehouse/wizards.py +++ b/archaeological_warehouse/wizards.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2012-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> @@ -37,52 +37,54 @@ class ContainerSearch(SearchWizard): class PackagingWizard(TreatmentWizard): - basket_step = 'base-packaging' + basket_step = "base-packaging" def get_form_initial(self, step, data=None): initial = super(PackagingWizard, self).get_form_initial(step) user = self.request.user - if step != 'base-packaging' or not getattr(user, 'ishtaruser', None) \ - or not user.ishtaruser.person: + if ( + step != "base-packaging" + or not getattr(user, "ishtaruser", None) + or not user.ishtaruser.person + ): return initial - initial['person'] = user.ishtaruser.person.pk + initial["person"] = user.ishtaruser.person.pk return initial - def save_model(self, dct, m2m, whole_associated_models, form_list, - return_object): + def save_model(self, dct, m2m, whole_associated_models, form_list, return_object): dct = self.get_extra_model(dct, m2m, form_list) obj = self.get_current_saved_object() - dct['location'] = dct['container'].location + dct["location"] = dct["container"].location items = None - if 'items' in dct: - items = dct.pop('items') - if 'basket' in dct: + if "items" in dct: + items = dct.pop("items") + if "basket" in dct: if not items: - items = dct.pop('basket') + items = dct.pop("basket") else: - dct.pop('basket') - if 'treatment_type_list' in dct: - dct.pop('treatment_type_list') + dct.pop("basket") + if "treatment_type_list" in dct: + dct.pop("treatment_type_list") treatment = Treatment(**dct) - extra_args_for_new = {"container": dct['container']} - treatment.save(items=items, user=self.request.user, - extra_args_for_new=extra_args_for_new) - packaging = TreatmentType.objects.get(txt_idx='packaging') + extra_args_for_new = {"container": dct["container"]} + treatment.save( + items=items, user=self.request.user, extra_args_for_new=extra_args_for_new + ) + packaging = TreatmentType.objects.get(txt_idx="packaging") treatment.treatment_types.add(packaging) - res = render(self.request, 'ishtar/wizard/wizard_done.html', {}) + res = render(self.request, "ishtar/wizard/wizard_done.html", {}) return return_object and (obj, res) or res class WarehouseWizard(Wizard): model = models.Warehouse - wizard_done_window = reverse_lazy('show-warehouse') + wizard_done_window = reverse_lazy("show-warehouse") redirect_url = "warehouse_modification" - def save_model(self, dct, m2m, whole_associated_models, form_list, - return_object): + def save_model(self, dct, m2m, whole_associated_models, form_list, return_object): create_organization = False - if 'create_organization' in dct: - create_organization = dct.pop('create_organization') + if "create_organization" in dct: + create_organization = dct.pop("create_organization") obj, res = super(WarehouseWizard, self).save_model( dct, m2m, whole_associated_models, form_list, True ) @@ -95,10 +97,9 @@ class WarehouseWizard(Wizard): class WarehouseModificationWizard(Wizard): model = models.Warehouse modification = True - wizard_done_window = reverse_lazy('show-warehouse') + wizard_done_window = reverse_lazy("show-warehouse") wizard_templates = { - 'divisions-warehouse_modification': - 'ishtar/wizard/wizard_warehouse_divisions.html', + "divisions-warehouse_modification": "ishtar/wizard/wizard_warehouse_divisions.html", } redirect_url = "warehouse_modification" @@ -111,28 +112,26 @@ class WarehouseDeletionWizard(MultipleDeletionWizard): class ContainerWizard(Wizard): model = models.Container wizard_templates = { - 'container-container_creation': - 'ishtar/wizard/wizard_container.html', - 'container-container_modification': - 'ishtar/wizard/wizard_container.html', + "container-container_creation": "ishtar/wizard/wizard_container.html", + "container-container_modification": "ishtar/wizard/wizard_container.html", } - ignore_init_steps = ['localisation'] - wizard_done_window = reverse_lazy('show-container') + ignore_init_steps = ["localisation"] + wizard_done_window = reverse_lazy("show-container") redirect_url = "container_modification" def get_form_kwargs(self, step=None): kwargs = super(ContainerWizard, self).get_form_kwargs(step) - if step == 'localisation-' + self.url_name: - container_pk = self.session_get_value( - 'selec-' + self.url_name, 'pk') + if step == "localisation-" + self.url_name: + container_pk = self.session_get_value("selec-" + self.url_name, "pk") q = models.Container.objects.filter(pk=container_pk) if q.count(): - kwargs['container'] = q.all()[0] + kwargs["container"] = q.all()[0] warehouse_pk = self.session_get_value( - 'container-' + self.url_name, 'location') + "container-" + self.url_name, "location" + ) q = models.Warehouse.objects.filter(pk=warehouse_pk) if q.count(): - kwargs['warehouse'] = q.all()[0] + kwargs["warehouse"] = q.all()[0] return kwargs def done(self, form_list, **kwargs): @@ -144,22 +143,25 @@ class ContainerWizard(Wizard): for idx, form in enumerate(form_list): if not form.is_valid(): return self.render(form) - container = self.get_current_object() or \ - hasattr(self, 'current_object') and self.current_object - if container and form.prefix == 'localisation-' + self.url_name: + container = ( + self.get_current_object() + or hasattr(self, "current_object") + and self.current_object + ) + if container and form.prefix == "localisation-" + self.url_name: for div_name in form.cleaned_data: try: division = models.WarehouseDivisionLink.objects.get( - pk=div_name.split('_')[-1], - warehouse=container.location + pk=div_name.split("_")[-1], warehouse=container.location ) # check the localisation match with the container except models.WarehouseDivisionLink.DoesNotExist: return self.render(form) - localisation, created = \ - models.ContainerLocalisation.objects.get_or_create( - container=container, - division=division - ) + ( + localisation, + created, + ) = models.ContainerLocalisation.objects.get_or_create( + container=container, division=division + ) localisation.reference = form.cleaned_data[div_name] localisation.save() obj = container @@ -176,9 +178,15 @@ class ContainerModificationWizard(ContainerWizard): class ContainerDeletionWizard(MultipleDeletionWizard): model = models.Container - fields = ['container_type', 'reference', 'comment', 'location', 'index', - 'cached_label'] + fields = [ + "container_type", + "reference", + "comment", + "location", + "index", + "cached_label", + ] redirect_url = "container_deletion" wizard_templates = { - 'final-container_deletion': - 'ishtar/wizard/wizard_container_deletion.html'} + "final-container_deletion": "ishtar/wizard/wizard_container_deletion.html" + } |