diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2020-04-06 12:31:38 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2021-02-28 12:15:20 +0100 |
commit | 0f96790ca2866d205b262c96ddb1b155abb80ef6 (patch) | |
tree | 1ac684557b5b6d2b7457b80040f8955e0db19d07 /archaeological_warehouse | |
parent | 8b69114b1932329283f3563077a3cb53149af7c8 (diff) | |
download | Ishtar-0f96790ca2866d205b262c96ddb1b155abb80ef6.tar.bz2 Ishtar-0f96790ca2866d205b262c96ddb1b155abb80ef6.zip |
New container localisation - adapt sheets, imports
Diffstat (limited to 'archaeological_warehouse')
6 files changed, 346 insertions, 96 deletions
diff --git a/archaeological_warehouse/forms.py b/archaeological_warehouse/forms.py index e03918965..a7390a890 100644 --- a/archaeological_warehouse/forms.py +++ b/archaeological_warehouse/forms.py @@ -372,15 +372,14 @@ class ContainerSelect(DocumentItemSelect): label=_(u"Full text search"), widget=widgets.SearchWidget( 'archaeological-warehouse', 'container' )) - location_name = get_warehouse_field( - label=_(u"Current location (warehouse)")) - responsible_name = get_warehouse_field(label=_(u"Responsible warehouse")) - container_type = forms.ChoiceField(label=_(u"Container type"), choices=[]) - reference = forms.CharField(label=_(u"Ref.")) - old_reference = forms.CharField(label=_(u"Old reference")) + location_name = get_warehouse_field(label=_("Warehouse")) + container_type = forms.ChoiceField(label=_("Container type"), choices=[]) + reference = forms.CharField(label=_("Ref.")) + old_reference = forms.CharField(label=_("Old reference")) comment = forms.CharField(label=_(u"Comment")) - no_finds = forms.NullBooleanField(label=_(u"No associated finds")) - empty = forms.NullBooleanField(label=_(u"Currently empty")) + contain_containers = forms.NullBooleanField(label=_("Contain containers")) + empty = forms.NullBooleanField(label=_("Currently empty")) + is_stationary = forms.NullBooleanField(label=_("Is stationary")) archaeological_sites = forms.IntegerField( label=_("Archaeological site (attached to the operation)"), diff --git a/archaeological_warehouse/management/commands/migrate_to_new_container_management.py b/archaeological_warehouse/management/commands/migrate_to_new_container_management.py index b5885cbf0..d8f701793 100644 --- a/archaeological_warehouse/management/commands/migrate_to_new_container_management.py +++ b/archaeological_warehouse/management/commands/migrate_to_new_container_management.py @@ -30,18 +30,23 @@ class Command(BaseCommand): def handle(self, *args, **options): to_update = models.Container.objects.filter( - division__pk__isnull=False) + division__pk__isnull=False, parent__isnull=True) container_types = {} created_nb = 0 for div_type in models.WarehouseDivision.objects.all(): container_type, c = models.ContainerType.objects.get_or_create( txt_idx=slugify(div_type.label), - defaults={"label": div_type.label}) + defaults={"label": div_type.label, + "stationary": True}) if c: created_nb += 1 sys.stdout.write("-> {} created\n".format( div_type.label)) container_types[div_type.pk] = container_type + for wdl in models.WarehouseDivisionLink.objects.all(): + wdl.container_type = container_types[wdl.division_id] + wdl.save() + if created_nb: sys.stdout.write("* {} container types created\n".format( created_nb)) @@ -50,10 +55,10 @@ class Command(BaseCommand): potential_duplicate = {} data = [("id", "warehouse", "reference", "old cached division", "new cached division")] - for idx, container in enumerate(models.Container.objects.filter( - division__pk__isnull=False).all()): + for idx, container in enumerate(to_update.values("id").all()): sys.stdout.write("* Updating: {}/{}\r".format(idx + 1, to_be_done)) sys.stdout.flush() + container = models.Container.objects.get(pk=container["id"]) if container.responsible_id not in potential_duplicate: potential_duplicate[container.responsible_id] = {} parent = None diff --git a/archaeological_warehouse/migrations/0103_auto_20200403_1638.py b/archaeological_warehouse/migrations/0103_auto_20200403_1638.py new file mode 100644 index 000000000..d7bd5320b --- /dev/null +++ b/archaeological_warehouse/migrations/0103_auto_20200403_1638.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.27 on 2020-04-03 16:38 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_warehouse', '0102_auto_20200324_1142'), + ] + + operations = [ + migrations.AddField( + model_name='containertype', + name='stationary', + field=models.BooleanField(default=False, help_text='Container that usually will not be moved. Ex: building, room.', verbose_name='Stationary'), + ), + migrations.AddField( + model_name='warehousedivisionlink', + name='container_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='archaeological_warehouse.ContainerType'), + ), + migrations.AlterField( + model_name='container', + name='parent', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='children', to='archaeological_warehouse.Container', verbose_name='Parent container'), + ), + migrations.AlterField( + model_name='container', + name='responsible', + field=models.ForeignKey(blank=True, help_text='Deprecated - do not use', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='owned_containers', to='archaeological_warehouse.Warehouse', verbose_name='Responsible warehouse'), + ), + migrations.AlterField( + model_name='warehousedivisionlink', + name='division', + field=models.ForeignKey(blank=True, help_text='Deprecated - do not use', null=True, on_delete=django.db.models.deletion.CASCADE, to='archaeological_warehouse.WarehouseDivision'), + ), + ] diff --git a/archaeological_warehouse/migrations/0104_auto_container_views.py b/archaeological_warehouse/migrations/0104_auto_container_views.py new file mode 100644 index 000000000..4f707c8d7 --- /dev/null +++ b/archaeological_warehouse/migrations/0104_auto_container_views.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.27 on 2020-04-03 16:47 +from __future__ import unicode_literals + +from django.db import migrations + +import archaeological_warehouse.models +import archaeological_finds.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_warehouse', '0103_auto_20200403_1638'), + ] + + operations = [ + migrations.RunSQL( + archaeological_warehouse.models.ContainerTree.DELETE_SQL), + migrations.RunSQL( + archaeological_warehouse.models.ContainerTree.CREATE_SQL), + migrations.RunSQL( + archaeological_finds.models.FindInsideContainer.DELETE_SQL), + migrations.RunSQL( + archaeological_finds.models.FindInsideContainer.CREATE_SQL), + ] diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py index 839ca1a6e..c4b26e3d1 100644 --- a/archaeological_warehouse/models.py +++ b/archaeological_warehouse/models.py @@ -393,12 +393,37 @@ class WarehouseDivisionLinkManager(models.Manager): division__txt_idx=division) +class ContainerType(GeneralType): + stationary = models.BooleanField( + _("Stationary"), default=False, + help_text=_("Container that usually will not be moved. Ex: building, " + "room.")) + length = models.IntegerField(_(u"Length (mm)"), blank=True, null=True) + width = models.IntegerField(_(u"Width (mm)"), blank=True, null=True) + height = models.IntegerField(_(u"Height (mm)"), blank=True, null=True) + volume = models.FloatField(_(u"Volume (l)"), blank=True, null=True) + reference = models.CharField(_(u"Ref."), max_length=300, blank=True, + null=True) + + class Meta: + verbose_name = _(u"Container type") + verbose_name_plural = _(u"Container types") + ordering = ('label',) + + +post_save.connect(post_save_cache, sender=ContainerType) +post_delete.connect(post_save_cache, sender=ContainerType) + + class WarehouseDivisionLink(models.Model): RELATED_SET_NAME = "divisions" RELATED_ATTRS = ["order"] RELATIVE_MODELS = {Warehouse: 'warehouse'} warehouse = models.ForeignKey(Warehouse, related_name='divisions') - division = models.ForeignKey(WarehouseDivision) + container_type = models.ForeignKey(ContainerType, blank=True, null=True) + division = models.ForeignKey( + WarehouseDivision, help_text=_("Deprecated - do not use"), + blank=True, null=True) order = models.IntegerField(_("Order"), default=10) objects = WarehouseDivisionLinkManager() @@ -413,22 +438,43 @@ class WarehouseDivisionLink(models.Model): return self.warehouse.uuid, self.division.txt_idx -class ContainerType(GeneralType): - length = models.IntegerField(_(u"Length (mm)"), blank=True, null=True) - width = models.IntegerField(_(u"Width (mm)"), blank=True, null=True) - height = models.IntegerField(_(u"Height (mm)"), blank=True, null=True) - volume = models.FloatField(_(u"Volume (l)"), blank=True, null=True) - reference = models.CharField(_(u"Ref."), max_length=300, blank=True, - null=True) - - class Meta: - verbose_name = _(u"Container type") - verbose_name_plural = _(u"Container types") - ordering = ('label',) - - -post_save.connect(post_save_cache, sender=ContainerType) -post_delete.connect(post_save_cache, sender=ContainerType) +class ContainerTree: + CREATE_SQL = """ + CREATE VIEW containers_tree AS + WITH RECURSIVE rel_tree AS ( + SELECT c.id AS container_id, c.parent_id AS container_parent_id, + 1 AS level + FROM archaeological_warehouse_container c + WHERE c.parent_id is NOT NULL + UNION ALL + SELECT p.container_id AS container_id, + c.parent_id as container_parent_id, + p.level + 1 + FROM archaeological_warehouse_container c, rel_tree p + WHERE c.id = p.container_parent_id + AND c.parent_id is NOT NULL + AND p.level < 10 -- prevent recursive... + ) + SELECT DISTINCT container_id, container_parent_id, level + FROM rel_tree; + + CREATE VIEW container_tree AS + SELECT DISTINCT y.container_id, y.container_parent_id + FROM (SELECT * FROM containers_tree) y + ORDER BY y.container_id, y.container_parent_id; + + -- deactivate deletion + CREATE RULE container_tree_del AS + ON DELETE TO container_tree + DO INSTEAD DELETE FROM archaeological_warehouse_container where id=NULL; + CREATE RULE containers_tree_del AS + ON DELETE TO container_tree + DO INSTEAD DELETE FROM archaeological_warehouse_container where id=NULL; + """ + DELETE_SQL = """ + DROP VIEW IF EXISTS container_tree; + DROP VIEW IF EXISTS containers_tree; + """ class Container(DocumentItem, LightHistorizedItem, QRCodeItem, GeoItem, @@ -439,7 +485,8 @@ class Container(DocumentItem, LightHistorizedItem, QRCodeItem, GeoItem, SHOW_URL = 'show-container' DELETE_URL = 'delete-container' NEW_QUERY_ENGINE = True - TABLE_COLS = ['reference', 'container_type__label', 'cached_location', + TABLE_COLS = ['container_type__label', 'reference', + 'location__name', 'cached_division', 'old_reference'] IMAGE_PREFIX = 'containers/' BASE_SEARCH_VECTORS = [ @@ -457,6 +504,7 @@ class Container(DocumentItem, LightHistorizedItem, QRCodeItem, GeoItem, # search parameters EXTRA_REQUEST_KEYS = { 'location': 'location__pk', + 'location__name': "location__name", 'location_id': 'location__pk', 'responsible_id': 'responsible__pk', 'container_type': 'container_type__pk', @@ -470,9 +518,10 @@ class Container(DocumentItem, LightHistorizedItem, QRCodeItem, GeoItem, 'container_type__label': 'container_type__label', } COL_LABELS = { - 'cached_location': _(u"Location - index"), - 'cached_division': _(u"Precise localisation"), - 'container_type__label': _(u"Type") + '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', ] @@ -483,10 +532,6 @@ class Container(DocumentItem, LightHistorizedItem, QRCodeItem, GeoItem, pgettext_lazy("key for text search", "location"), 'location__name__iexact' ), - 'responsible_name': SearchAltName( - pgettext_lazy("key for text search", "responsible-warehouse"), - 'responsible__name__iexact' - ), 'container_type': SearchAltName( pgettext_lazy("key for text search", "type"), 'container_type__label__iexact' @@ -595,20 +640,25 @@ class Container(DocumentItem, LightHistorizedItem, QRCodeItem, GeoItem, pgettext_lazy("key for text search", "find-description"), 'finds__description__iexact'), 'empty': SearchAltName( - pgettext_lazy("key for text search", u"empty"), + pgettext_lazy("key for text search", "empty"), 'finds' ), - 'no_finds': SearchAltName( - pgettext_lazy("key for text search", u"no-associated-finds"), - 'finds_ref' + 'contain_containers': SearchAltName( + pgettext_lazy("key for text search", "contain-containers"), + 'children__isnull' ), - + 'is_stationary': SearchAltName( + pgettext_lazy("key for text search", "is-stationary"), + 'container_type__stationary' + ) } REVERSED_BOOL_FIELDS = [ + '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'] ALT_NAMES.update(LightHistorizedItem.ALT_NAMES) @@ -638,11 +688,13 @@ class Container(DocumentItem, LightHistorizedItem, QRCodeItem, GeoItem, # fields uuid = models.UUIDField(default=uuid.uuid4) location = models.ForeignKey( - Warehouse, verbose_name=_(u"Location (warehouse)"), + Warehouse, verbose_name=_("Location (warehouse)"), related_name='containers') responsible = models.ForeignKey( - Warehouse, verbose_name=_(u"Responsible warehouse"), - related_name='owned_containers') + Warehouse, verbose_name=_("Responsible warehouse"), + related_name='owned_containers', blank=True, null=True, + help_text=_("Deprecated - do not use") + ) container_type = models.ForeignKey(ContainerType, verbose_name=_("Container type")) reference = models.TextField(_(u"Container ref.")) @@ -655,19 +707,21 @@ class Container(DocumentItem, LightHistorizedItem, QRCodeItem, GeoItem, null=True, blank=True, db_index=True) parent = models.ForeignKey("Container", verbose_name=_("Parent container"), on_delete=models.SET_NULL, - blank=True, null=True) - index = models.IntegerField(u"Container ID", default=0) - old_reference = models.TextField(_(u"Old reference"), blank=True, null=True) - external_id = models.TextField(_(u"External ID"), blank=True, null=True) + related_name="children", blank=True, null=True) + index = models.IntegerField(_("Container ID"), default=0) + old_reference = models.TextField(_("Old reference"), blank=True, null=True) + external_id = models.TextField(_("External ID"), blank=True, null=True) auto_external_id = models.BooleanField( - _(u"External ID is set automatically"), default=False) + _("External ID is set automatically"), default=False) documents = models.ManyToManyField( - Document, related_name='containers', verbose_name=_(u"Documents"), + Document, related_name='containers', verbose_name=_("Documents"), blank=True) main_image = models.ForeignKey( Document, related_name='main_image_containers', on_delete=models.SET_NULL, - verbose_name=_(u"Main image"), blank=True, null=True) + verbose_name=_("Main image"), blank=True, null=True) + + DISABLE_POLYGONS = False class Meta: verbose_name = _(u"Container") @@ -688,13 +742,15 @@ class Container(DocumentItem, LightHistorizedItem, QRCodeItem, GeoItem, def __str__(self): return self.cached_label or "" + @property + def short_label(self): + return "{} {}".format(self.container_type.label, self.reference) + def natural_key(self): return (self.uuid, ) def _generate_cached_label(self): - items = [self.reference, self.precise_location] - cached_label = u" | ".join(items) - return cached_label + return self.precise_location def _generate_cached_location(self): items = [self.location.name, str(self.index)] @@ -715,10 +771,11 @@ class Container(DocumentItem, LightHistorizedItem, QRCodeItem, GeoItem, "{} {}".format(loca.container_type.name, loca.reference) for loca in reversed(parents) ] + locas.append("{} {}".format(self.container_type.name, self.reference)) return " | ".join(locas) def _get_base_image_path(self): - return self.responsible._get_base_image_path() + u"/" + self.external_id + return self.location._get_base_image_path() + "/" + self.external_id def merge(self, item, keep_old=False): locas = [ @@ -754,21 +811,21 @@ class Container(DocumentItem, LightHistorizedItem, QRCodeItem, GeoItem, @property def associated_filename(self): filename = datetime.date.today().strftime('%Y-%m-%d') - filename += u'-' + self.reference - filename += u"-" + self.location.name - filename += u"-" + str(self.index) + filename += "-" + self.reference + filename += "-" + self.location.name + filename += "-" + str(self.index) if self.cached_division is None: self.skip_history_when_saving = True self.save() if self.cached_division: - filename += u"-" + self.cached_division + filename += "-" + self.cached_division return slugify(filename) @property def precise_location(self): location = self.location.name if self.cached_division: - location += u" " + self.cached_division + location += " " + self.cached_division return location def get_localisations(self): @@ -777,11 +834,12 @@ class Container(DocumentItem, LightHistorizedItem, QRCodeItem, GeoItem, :return: tuple of strings with localisations """ - return tuple(( - loca.reference - for loca in ContainerLocalisation.objects.filter( - container=self).order_by('division__order') - )) + localisations = [] + parent = self.parent + while parent: + localisations.append(parent) + parent = parent.parent + return reversed(localisations) def get_localisation(self, place): locas = self.get_localisations() @@ -825,30 +883,83 @@ class Container(DocumentItem, LightHistorizedItem, QRCodeItem, GeoItem, def localisation_9(self): return self.get_localisation(8) - def set_localisation(self, place, value): + def set_localisation(self, place, value, static=False, return_errors=False): """ Set the reference for the localisation number "place" (starting from 0) :param place: the number of the localisation :param value: the reference to be set + :param static: do not create new containers + :param return_errors: return error message :return: the container location object or None if the place does not - exist + exist - return also error message if return_errors set to True """ + value = value.strip() + if not value or value == "-": + if return_errors: + return None, _("No value") + return q = WarehouseDivisionLink.objects.filter( warehouse=self.location).order_by('order') + + current_container_type = None + error_msg = str( + _("The division number {} have not been set for the warehouse {}.") + ).format(place + 1, self.location) + previous_container_types = [] for idx, division_link in enumerate(q.all()): if idx == place: + current_container_type = division_link.container_type break + previous_container_types.append(division_link.container_type_id) else: + if return_errors: + return None, error_msg return - dct = {'container': self, 'division': division_link} - if not value: - if ContainerLocalisation.objects.filter(**dct).count(): - c = ContainerLocalisation.objects.filter(**dct).all()[0] - c.delete() + if not current_container_type: + # no division link set at this place + if return_errors: + return None, error_msg return - dct['defaults'] = {'reference': value} - obj, created = ContainerLocalisation.objects.update_or_create(**dct) - return obj + + # modify existing + current_localisations = self.get_localisations() + current_localisation, current_parent = None, None + for loca in current_localisations: + if loca.container_type == current_container_type: + if loca.reference == value: + current_localisation = loca + break + elif loca.container_type_id in previous_container_types: + current_parent = loca + + if not current_localisation: + dct = { + "reference": value, + "container_type": current_container_type, + "parent": current_parent, + "location": self.location + } + q = Container.objects.filter(**dct) + if q.count(): + current_localisation = q.all()[0] + else: + if static: + if return_errors: + error_msg = str( + _("The division {} {} do not exist for the " + "location {}.") + ).format(current_container_type, value, self.location) + return None, error_msg + return + current_localisation = Container.objects.create(**dct) + self.parent = current_localisation + self.save() + if return_errors: + return current_localisation, None + return current_localisation + + def set_static_localisation(self, place, value): + return self.set_localisation(place, value, static=True) @post_importer_action def set_localisation_1(self, context, value): @@ -895,6 +1006,51 @@ class Container(DocumentItem, LightHistorizedItem, QRCodeItem, GeoItem, 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 + def get_extra_actions(self, request): """ extra actions for the sheet template diff --git a/archaeological_warehouse/templates/ishtar/sheet_container.html b/archaeological_warehouse/templates/ishtar/sheet_container.html index ffc533513..1bb004071 100644 --- a/archaeological_warehouse/templates/ishtar/sheet_container.html +++ b/archaeological_warehouse/templates/ishtar/sheet_container.html @@ -1,7 +1,10 @@ {% extends "ishtar/sheet.html" %} -{% load i18n window_header window_field window_tables %} +{% load i18n window_header window_field window_tables link_to_window %} -{% block head_title %}<strong>{% trans "Container" %}</strong> - {{ item.reference|default:"" }} ({{ item.container_type|default:"" }}){% endblock %} +{% block head_title %}<strong>{% trans "Container" %}</strong> - +{{ item.container_type|default:"" }} {{ item.reference|default:"" }} - +{{ item.location.name|default:"" }} +{% endblock %} {% block toolbar %} {% window_nav item window_id 'show-container' 'container_modify' '' '' previous next 1 %} @@ -19,9 +22,8 @@ {% else %} <div class="float-left col-6 col-md-3 text-center"> {% endif %} - <p class="window-refs">{{ item.reference|default:"" }}</p> - <p class="window-refs">{{ item.container_type|default:"" }}</p> - <p class="window-refs">{{ item.responsible.name }} - {{ item.index }}</p> + <p class="window-refs">{{ item.container_type|default:"" }} {{ item.reference|default:"" }}</p> + <p class="window-refs">{{ item.location.name }} - {{ item.index }}</p> <p class="window-refs">{{ item.old_reference|default:"" }}</p> {% include "ishtar/blocks/sheet_external_id.html" %} </div> @@ -30,36 +32,57 @@ {% else %} <div class="float-left row col-6 col-md-8"> {% endif %} - {% field_flex_detail "Responsible warehouse" item.responsible %} - {% field_flex_detail "Location (warehouse)" item.location %} + {% field_flex_detail "Warehouse" item.location %} + {% if item.parent %} + <dl class="col-12 col-md-6 flex-wrap"> + <dt>{% trans "Location" %}</dt> + <dd> + <nav aria-label="breadcrumb"> + <ol class="breadcrumb"> + {% for loca in item.get_localisations %} + <li class="breadcrumb-item"> + {{loca.short_label}} {{loca|simple_link_to_window}} + </li> + {% endfor %} + </ol> + </nav> + </dd> + </dl> + {% endif %} {% include "ishtar/blocks/sheet_creation_section.html" %} - {% field_flex "Location" item.precise_location %} {% field_flex_full "Comment" item.comment "<pre>" "</pre>" %} {% include "ishtar/blocks/sheet_json.html" %} </div> </div> +{% if item.container_content.count or item.children.count %} +<h4>{% trans "Content" %}</h4> + +{% if item.children.count %} +{% trans "Containers" as container_lbl %} +{% dynamic_table_document container_lbl 'containers' 'parent' item.pk 'TABLE_COLS' output 'large' %} +{% endif %} + +{% if item.container_content.count %} +{% trans "Finds" as finds_lbl %} +{% dynamic_table_document finds_lbl 'finds_inside_container' 'container' item.pk 'TABLE_COLS' output 'large' %} +{% endif %} + +{% endif %} + +{% if PROFILE.locate_warehouses %} {% if item.point_2d or item.multi_polygon %} <h3>{% trans "Localisation"%}</h3> <div class='row'> + {{item.point_2d}} {% with geo_item=item %} - {% if PROFILE.locate_warehouses %}{% include "ishtar/blocks/sheet_simple_map.html"%}{% endif %} + {% include "ishtar/blocks/sheet_simple_map.html" %} <div class="col-12 col-lg-6 flex-wrap"> - {% if PROFILE.locate_warehouses %}{% include "ishtar/blocks/sheet_coordinates.html"%}{% endif %} + {% include "ishtar/blocks/sheet_coordinates.html" %} </div> {% endwith %} </div> {% endif %} - - -{% if item.finds.count %} -<h4>{% trans "Content" %}</h4> -{% dynamic_table_document finds 'finds' 'container' item.pk 'TABLE_COLS' output 'large' %} -{% endif %} - -{% if item.finds_ref.count %} -<h4>{% trans "Reference content" %}</h4> -{% dynamic_table_document finds 'finds' 'container_ref' item.pk 'TABLE_COLS' output 'large' %} {% endif %} {% endblock %} |