summaryrefslogtreecommitdiff
path: root/archaeological_warehouse
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2020-09-30 17:56:39 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2021-02-28 12:15:20 +0100
commitcf38e81844d6828825c0cf5810cc9186b58174f9 (patch)
tree54ae0fb12f10f5106ccef9562a3235b3ab76e477 /archaeological_warehouse
parentd53b1af88aac5cf86b8acaab5e096d370d7fd0a4 (diff)
downloadIshtar-cf38e81844d6828825c0cf5810cc9186b58174f9.tar.bz2
Ishtar-cf38e81844d6828825c0cf5810cc9186b58174f9.zip
Sheet container: show statistics
Diffstat (limited to 'archaeological_warehouse')
-rw-r--r--archaeological_warehouse/models.py409
-rw-r--r--archaeological_warehouse/templates/ishtar/sheet_container.html119
-rw-r--r--archaeological_warehouse/templates/ishtar/sheet_warehouse.html34
3 files changed, 368 insertions, 194 deletions
diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py
index a8a38c34d..ffc491ddc 100644
--- a/archaeological_warehouse/models.py
+++ b/archaeological_warehouse/models.py
@@ -45,6 +45,201 @@ from ishtar_common.utils import cached_label_changed, \
cached_label_and_geo_changed
+class DivisionContainer(DashboardFormItem):
+ DIVISION_TEMPLATE = """<a class="display_details"
+ href="#" onclick="load_window('/show-container/{id}/')">
+ <i class="fa fa-info-circle" aria-hidden="true"></i>
+ </a> {container} {ref}"""
+ BASE_QUERY_LOCATION = "location"
+
+ @property
+ def pk(self):
+ # of course implemented by models.Model
+ raise NotImplemented
+
+ def get_max_division_number(self):
+ raise NotImplemented
+
+ @property
+ def start_division_number(self):
+ raise NotImplemented
+
+ @property
+ def division_labels(self):
+ if not self.get_max_division_number() + 1:
+ return []
+ start = self.start_division_number
+ return [
+ "{} {}".format(_("Division"), idx + start + 1)
+ for idx in range(self.get_max_division_number() + 1)
+ ]
+
+ @property
+ def number_divisions(self):
+ q = {
+ self.BASE_QUERY_LOCATION + "__id": self.pk,
+ "container_type__stationary": True
+ }
+ return Container.objects.filter(**q).count()
+
+ @property
+ def number_containers(self):
+ q = {
+ self.BASE_QUERY_LOCATION + "__id": self.pk,
+ "container_type__stationary": False
+ }
+ return Container.objects.filter(**q).count()
+
+ @property
+ def number_of_finds_hosted(self):
+ Find = apps.get_model("archaeological_finds", "Find")
+ q = {
+ "container__{}__id".format(self.BASE_QUERY_LOCATION): self.pk,
+ }
+ return Find.objects.filter(**q).count()
+
+ @property
+ def number_of_finds(self):
+ Find = apps.get_model("archaeological_finds", "Find")
+ q = {
+ "container_ref__{}__id".format(self.BASE_QUERY_LOCATION): self.pk,
+ }
+ return Find.objects.filter(**q).count()
+
+ @property
+ def number_of_containers(self):
+ 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__')
+
+ @property
+ def number_of_finds_by_place(self, update=False):
+ return self._get_or_set_stats('_number_of_finds_by_place', update)
+
+ def _number_of_containers_by_place(self):
+ return self._number_of_items_by_place(
+ 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)
+
+ def _get_divisions(self, current_path, remaining_division, depth=0):
+ if not remaining_division:
+ return [current_path]
+ remaining_division.pop(0)
+
+ query_location = self.BASE_QUERY_LOCATION
+ for __ in range(depth):
+ query_location = "parent__" + query_location
+ base_q = Container.objects.filter(**{query_location: self})
+
+ q = base_q
+ if self.BASE_QUERY_LOCATION == 'location':
+ exclude = "parent_"
+ for idx in range(depth):
+ exclude += "_parent_"
+ q = base_q.filter(**{exclude + "id": None})
+ elif not depth and not current_path:
+ q = base_q.filter(parent_id=self.pk)
+
+ for idx, p in enumerate(reversed(current_path)):
+ parent_id, __ = p
+ key = "parent__" * (idx + 1) + "id"
+ q = q.filter(**{key: parent_id})
+ res = []
+ old_ref, ct = None, None
+ if not q.count():
+ return [current_path]
+ q = q.values(
+ '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:
+ continue
+ 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'])
+ 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
+ }
+ remaining_division = list(
+ ContainerType.objects.filter(
+ **query).distinct())
+ for r in self._get_divisions(cpath, remaining_division[:],
+ depth + 1):
+ res.append(r)
+ return res
+
+ @property
+ def available_division_tuples(self):
+ """
+ :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__parent"] = None
+ top_divisions = list(
+ ContainerType.objects.filter(**q).distinct())
+ divisions = self._get_divisions([], top_divisions)
+ return divisions
+
+ def _number_of_items_by_place(self, model, division_key, count_filter=None):
+ res = {}
+ paths = self.available_division_tuples[:]
+ for path in paths:
+ cpath = []
+ for container_id, lbl in path:
+ cpath.append((container_id, lbl))
+ if tuple(cpath) in res:
+ continue
+ q = model.objects
+ for idx, p in enumerate(reversed(cpath)):
+ container_id, __ = p
+ div_key = division_key + "parent__" * idx
+ attrs = {
+ div_key + "id": container_id
+ }
+ q = q.filter(**attrs)
+ if count_filter:
+ q = q.filter(**{count_filter: None})
+ res[tuple(cpath)] = q.distinct().count()
+ res = [(k, res[k]) for k in res]
+ final_res, current_res, depth = [], [], 1
+
+ len_divisions = self.get_max_division_number() + 1
+ for path, nb in sorted(res, key=lambda x: (len(x[0]), x[0])):
+ if len(path) > len_divisions:
+ continue
+ if depth != len(path):
+ final_res.append(current_res[:])
+ current_res = []
+ depth = len(path)
+ if path[-1] == '-':
+ continue
+ path = [k[1] for k in path]
+ path = path + ['' for __ in range(len_divisions - len(path))]
+ current_res.append((path, nb))
+ final_res.append(current_res[:])
+ return final_res
+
+
class WarehouseType(GeneralType):
class Meta:
verbose_name = _("Warehouse type")
@@ -56,8 +251,8 @@ post_save.connect(post_save_cache, sender=WarehouseType)
post_delete.connect(post_save_cache, sender=WarehouseType)
-class Warehouse(Address, DocumentItem, GeoItem, QRCodeItem, DashboardFormItem,
- OwnPerms, MainItem):
+class Warehouse(Address, DocumentItem, GeoItem, QRCodeItem,
+ OwnPerms, MainItem, DivisionContainer):
SLUG = 'warehouse'
APP = "archaeological-warehouse"
MODEL = "warehouse"
@@ -156,28 +351,6 @@ class Warehouse(Address, DocumentItem, GeoItem, QRCodeItem, DashboardFormItem,
return self.name
@property
- def number_divisions(self):
- return Container.objects.filter(
- location=self.pk, container_type__stationary=True).count()
-
- @property
- def number_containers(self):
- return Container.objects.filter(
- location=self.pk, container_type__stationary=False).count()
-
- @property
- def number_finds(self):
- Find = apps.get_model("archaeological_finds", "Find")
- return Find.objects.filter(
- container__location_id=self.pk).count()
-
- @property
- def number_owned_finds(self):
- Find = apps.get_model("archaeological_finds", "Find")
- return Find.objects.filter(
- container_ref__location_id=self.pk).count()
-
- @property
def short_label(self):
return self.name
@@ -215,14 +388,12 @@ class Warehouse(Address, DocumentItem, GeoItem, QRCodeItem, DashboardFormItem,
setattr(self, k, None)
self.save()
+ def get_max_division_number(self):
+ return self.max_division_number
+
@property
- def division_labels(self):
- if not self.max_division_number:
- return []
- return [
- "{} {}".format(_("Division"), idx + 1)
- for idx in range(self.max_division_number)
- ]
+ def start_division_number(self):
+ return 0
@property
def default_location_types(self):
@@ -246,145 +417,6 @@ class Warehouse(Address, DocumentItem, GeoItem, QRCodeItem, DashboardFormItem,
def _get_query_owns_dicts(cls, ishtaruser):
return [{'person_in_charge__ishtaruser': ishtaruser}]
- @property
- def number_of_finds(self):
- from archaeological_finds.models import Find
- return Find.objects.filter(container_ref__location=self).count()
-
- @property
- def number_of_finds_hosted(self):
- from archaeological_finds.models import Find
- return Find.objects.filter(container__location=self).count()
-
- @property
- def number_of_containers(self):
- return Container.objects.filter(location=self).count()
-
- def _get_divisions(self, current_path, remaining_division, depth=0):
- if not remaining_division:
- return [current_path]
- remaining_division.pop(0)
-
- query_location = "location"
- for __ in range(depth):
- query_location = "parent__" + query_location
- base_q = Container.objects.filter(**{query_location: self})
-
- q = base_q.annotate(nb_children=Count("children__id")).exclude(
- nb_children=0)
-
- if not current_path:
- q = q.annotate(nb_parent=Count("parent__id")).filter(
- nb_parent=0)
-
- for idx, p in enumerate(reversed(current_path)):
- parent_id, __ = p
- key = "parent__" * (idx + 1) + "id"
- q = q.filter(**{key: parent_id})
- res = []
- old_ref, ct = None, None
- if not q.count():
- return [current_path]
- q = q.values(
- 'id', 'reference', 'container_type__label', 'container_type_id'
- ).order_by('container_type__label', 'reference')
-
- DIVISION_TEMPLATE = """<a class="display_details"
- href="#" onclick="load_window('/show-container/{id}/')">
- <i class="fa fa-info-circle" aria-hidden="true"></i></a>
- {container} {ref}"""
- for ref in q.all():
- if ref['reference'] == old_ref and \
- ref["container_type__label"] == ct:
- continue
- old_ref = ref['reference']
- ct = ref["container_type__label"]
- cpath = current_path[:]
- lbl = DIVISION_TEMPLATE.format(
- id=ref["id"], container=ref["container_type__label"],
- ref=ref['reference'])
- cpath.append((ref["id"], lbl))
- remaining_division = list(
- ContainerType.objects.filter(
- containers__parent__reference=ref['reference'],
- containers__parent__container_type_id=ref[
- "container_type_id"],
- containers__location=self).distinct())
- for r in self._get_divisions(cpath, remaining_division[:],
- depth + 1):
- res.append(r)
- return res
-
- @property
- def available_division_tuples(self):
- """
- :return: ordered list of available paths. Each path is a list of
- tuple with the container type and the full reference.
- """
- top_divisions = list(
- ContainerType.objects.filter(
- containers__parent=None,
- containers__location=self,
- stationary=True).distinct())
- divisions = self._get_divisions([], top_divisions)
- return divisions
-
- def _number_of_items_by_place(self, model, division_key, count_filter=None):
- res = {}
- paths = self.available_division_tuples[:]
- for path in paths:
- cpath = []
- for container_id, lbl in path:
- cpath.append((container_id, lbl))
- if tuple(cpath) in res:
- continue
- q = model.objects
- for idx, p in enumerate(reversed(cpath)):
- container_id, __ = p
- div_key = division_key + "parent__" * idx
- attrs = {
- div_key + "id": container_id
- }
- q = q.filter(**attrs)
- if count_filter:
- q = q.filter(**{count_filter: None})
- res[tuple(cpath)] = q.distinct().count()
- res = [(k, res[k]) for k in res]
- final_res, current_res, depth = [], [], 1
-
- len_divisions = self.max_division_number
- for path, nb in sorted(res, key=lambda x: (len(x[0]), x[0])):
- if len(path) > len_divisions:
- continue
- if depth != len(path):
- final_res.append(current_res[:])
- current_res = []
- depth = len(path)
- if path[-1] == '-':
- continue
- path = [k[1] for k in path]
- path = path + ['' for __ in range(len_divisions - len(path))]
- current_res.append((path, nb))
- final_res.append(current_res[:])
- return final_res
-
- def _number_of_finds_by_place(self):
- from archaeological_finds.models import Find
- return self._number_of_items_by_place(
- 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)
-
- def _number_of_containers_by_place(self):
- return self._number_of_items_by_place(
- 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)
-
def merge(self, item, keep_old=False):
# do not recreate missing divisions
available_divisions = [
@@ -569,7 +601,7 @@ class ContainerTree(models.Model):
class Container(DocumentItem, Merge, LightHistorizedItem, QRCodeItem, GeoItem,
- OwnPerms, MainItem):
+ OwnPerms, MainItem, DivisionContainer):
SLUG = 'container'
APP = "archaeological-warehouse"
MODEL = "container"
@@ -617,6 +649,10 @@ class Container(DocumentItem, Merge, LightHistorizedItem, QRCodeItem, GeoItem,
'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'
}
COL_LABELS = {
'cached_location': _("Location - index"),
@@ -788,6 +824,8 @@ class Container(DocumentItem, Merge, LightHistorizedItem, QRCodeItem, GeoItem,
)
QUICK_ACTIONS = [QA_EDIT, QA_LOCK]
+ BASE_QUERY_LOCATION = "container_tree_child__container_parent"
+
objects = UUIDModelManager()
# fields
@@ -853,6 +891,35 @@ class Container(DocumentItem, Merge, LightHistorizedItem, QRCodeItem, GeoItem,
return self.cached_label or ""
@property
+ def start_division_number(self):
+ depth = 1
+ parent = self.parent
+ parents = []
+ while parent and parent.pk not in parents:
+ parents.append(parent.pk)
+ depth += 1
+ parent = parent.parent
+ return depth
+
+ def get_max_division_number(self):
+ return self.location.get_max_division_number() \
+ - self.start_division_number
+
+ @property
+ def number_of_finds_hosted(self):
+ count = super(Container, self).number_of_finds_hosted
+ Find = apps.get_model("archaeological_finds", "Find")
+ count += Find.objects.filter(container_id=self.pk).count()
+ return count
+
+ @property
+ def number_of_finds(self):
+ count = super(Container, self).number_of_finds
+ Find = apps.get_model("archaeological_finds", "Find")
+ count += Find.objects.filter(container_ref_id=self.pk).count()
+ return count
+
+ @property
def name(self):
return "{} - {}".format(self.container_type.name, self.reference)
diff --git a/archaeological_warehouse/templates/ishtar/sheet_container.html b/archaeological_warehouse/templates/ishtar/sheet_container.html
index 5116820f0..336684bc8 100644
--- a/archaeological_warehouse/templates/ishtar/sheet_container.html
+++ b/archaeological_warehouse/templates/ishtar/sheet_container.html
@@ -27,6 +27,13 @@
{% trans "Content" %}
</a>
</li>
+ <li class="nav-item">
+ <a class="nav-link" id="{{window_id}}-stats-tab"
+ data-toggle="tab" href="#{{window_id}}-stats" role="tab"
+ aria-controls="{{window_id}}-stats" aria-selected="false">
+ {% trans "Statistics" %}
+ </a>
+ </li>
</ul>
{% endif %}
@@ -69,6 +76,22 @@
</nav>
</dd>
</dl>
+ <dl class="col-6 col-md-3 flex-wrap">
+ <dt>{% trans "Number of containers" %}</dt>
+ <dd>{{item.number_containers}}</dd>
+ </dl>
+ <dl class="col-6 col-md-3 flex-wrap">
+ <dt>{% trans "Number of divisions" %}</dt>
+ <dd>{{item.number_divisions}}</dd>
+ </dl>
+ <dl class="col-6 col-md-3 flex-wrap">
+ <dt>{% trans "Number of finds" %}</dt>
+ <dd>{{item.number_of_finds_hosted}}</dd>
+ </dl>
+ <dl class="col-6 col-md-3 flex-wrap">
+ <dt>{% trans "Number of owned finds" %}</dt>
+ <dd>{{item.number_of_finds}}</dd>
+ </dl>
{% include "ishtar/blocks/sheet_creation_section.html" %}
{% field_flex "Old reference" item.old_reference %}
{% field_flex_full "Comment" item.comment "<pre>" "</pre>" %}
@@ -107,24 +130,110 @@
{% if item.container_content.count or item.children.count %}
{% if item.children.count %}
- {% trans "Containers" as container_lbl %}
- {% dynamic_table_document container_lbl 'containers' 'parent' item.pk 'TABLE_COLS' output 'large' %}
+ <h4>{% trans "Divisions" %}</h4>
+ {% dynamic_table_document '' 'divisions' 'container_tree_child__container_parent__id' item.pk 'TABLE_COLS' output %}
+ <h4>{% trans "Containers" %}</h4>
+ {% dynamic_table_document '' 'non-divisions' 'container_tree_child__container_parent__id' item.pk 'TABLE_COLS' output %}
{% 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' %}
+ <h4>{% trans "Finds" %}</h4>
+ {% dynamic_table_document '' 'finds_inside_container' 'container' item.pk 'TABLE_COLS' output 'large' %}
{% endif %}
{% else %}
<div class="alert alert-info">
<i class="fa fa-exclamation-triangle"></i>
- <em>{% trans "Empty" %}</em>
+ &nbsp;<em>{% trans "Empty" %}</em>
+ </div>
+ {% endif %}
+
+ </div>
+
+ <div class="tab-pane fade" id="{{window_id}}-stats"
+ role="tabpanel" aria-labelledby="{{window_id}}-stats-tab">
+ <h3>{% trans "Statistics" %}</h3>
+
+ <small class="centered"><em>{% trans "These numbers are updated hourly" %}</em></small>
+
+ {% if not item.number_containers and not item.number_divisions %}
+ <div class="alert alert-info">
+ <i class="fa fa-exclamation-triangle"></i>
+ &nbsp;<em>{% trans "No container/division inside this container." %}</em>
</div>
+
+ {% else %}
+ <h4>{% trans "Finds" %}</h4>
+
+ <h4>{% trans "Finds by location" %}</h4>
+ {% for items in item.number_of_finds_by_place %}
+ {% if items %}
+ <table class='table table-striped datatables'
+ id="{{window_id}}-find-by-loca-{{forloop.counter}}">
+ <thead>
+ <tr>{% for location_type in item.division_labels %}
+ <th class="text-center">{{location_type|title}}</th>{% endfor %}
+ <th class="text-center">{% trans "Total" %}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for item in items %}
+ <tr>
+ {% for local in item.0 %}<td>{{local|safe}}</td>{% endfor %}
+ <td class="text-right">{{item.1}}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
{% endif %}
+ {% endfor %}
+
+ <h4>{% trans "Containers" %}</h4>
+ {% if item.number_of_containers_by_place %}
+ <h4>{% trans "Containers by location in the warehouse" %}</h4>
+ {% for items in item.number_of_containers_by_place %}
+ {% if items %}
+ <table class='table table-striped datatables'
+ id="{{window_id}}-container-by-loca-{{forloop.counter}}">
+ <thead>
+ <tr>{% for location_type in item.division_labels %}
+ <th class="text-center">{{location_type|title}}</th>{% endfor %}
+ <th class="text-center">{% trans "Total" %}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for item in items %}
+ <tr>
+ {% for local in item.0 %}<td>{{local|safe}}</td>{% endfor %}
+ <td class="text-right">{{item.1}}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% endif %}
+ {% endfor %}
+ {% endif %}
+ {% endif %}
</div>
</div>
+<script type="text/javascript">
+$(document).ready( function () {
+ datatable_options = {
+ "dom": 'ltip',
+ };
+ $.extend(datatable_options, datatables_static_default);
+ if (datatables_i18n) datatable_options['language'] = datatables_i18n;
+ $('.datatables').each(
+ function(){
+ var dt_id = "#" + $(this).attr('id');
+ if (! $.fn.DataTable.isDataTable(dt_id) ) {
+ $(dt_id).DataTable(datatable_options);
+ }
+ });
+} );
+</script>
+
{% endblock %}
diff --git a/archaeological_warehouse/templates/ishtar/sheet_warehouse.html b/archaeological_warehouse/templates/ishtar/sheet_warehouse.html
index 8e143aae9..e6717f230 100644
--- a/archaeological_warehouse/templates/ishtar/sheet_warehouse.html
+++ b/archaeological_warehouse/templates/ishtar/sheet_warehouse.html
@@ -61,7 +61,7 @@
<div class='row'>
<dl class="col-6 col-md-3 flex-wrap">
- <dt>{% trans "Number of container" %}</dt>
+ <dt>{% trans "Number of containers" %}</dt>
<dd>{{item.number_containers}}</dd>
</dl>
<dl class="col-6 col-md-3 flex-wrap">
@@ -70,11 +70,11 @@
</dl>
<dl class="col-6 col-md-3 flex-wrap">
<dt>{% trans "Number of finds" %}</dt>
- <dd>{{item.number_finds}}</dd>
+ <dd>{{item.number_of_finds_hosted}}</dd>
</dl>
<dl class="col-6 col-md-3 flex-wrap">
<dt>{% trans "Number of owned finds" %}</dt>
- <dd>{{item.number_owned_finds}}</dd>
+ <dd>{{item.number_of_finds}}</dd>
</dl>
{% field_flex_detail "Person in charge" item.person_in_charge %}
{% field_flex_detail "Organization" item.organization %}
@@ -138,15 +138,15 @@
<h3>{% trans "Statistics" %}</h3>
<small class="centered"><em>{% trans "These numbers are updated hourly" %}</em></small>
- <h4>{% trans "Finds" %}</h4>
- <div class='row'>
- {% trans "Number of attached finds" as number_of_attached_finds_label %}
- {% field_flex_2 number_of_attached_finds_label item.number_of_finds %}
- {% trans "Number of hosted finds" as number_of_hosted_finds_label %}
- {% field_flex_2 number_of_hosted_finds_label item.number_of_finds_hosted %}
+ {% if not item.number_containers and not item.number_divisions %}
+ <div class="alert alert-info">
+ <i class="fa fa-exclamation-triangle"></i>
+ &nbsp;<em>{% trans "No container/division inside this container" %}</em>
</div>
- {% if item.number_of_finds_by_place %}
+ {% else %}
+
+ <h4>{% trans "Finds" %}</h4>
<h4>{% trans "Finds by location in the warehouse" %}</h4>
{% for items in item.number_of_finds_by_place %}
{% if items %}
@@ -169,15 +169,9 @@
</table>
{% endif %}
{% endfor %}
- {% endif %}
<h4>{% trans "Containers" %}</h4>
- <div class='row'>
- {% trans "Number of containers" as number_of_containers_label %}
- {% field_flex_2 number_of_containers_label item.number_of_containers %}
- </div>
- {% if item.number_of_containers_by_place %}
<h4>{% trans "Containers by location in the warehouse" %}</h4>
{% for items in item.number_of_containers_by_place %}
{% if items %}
@@ -193,13 +187,14 @@
{% for item in items %}
<tr>
{% for local in item.0 %}<td>{{local|safe}}</td>{% endfor %}
- <td class="text-center">{{item.1}}</td>
+ <td class="text-right">{{item.1}}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% endfor %}
+
{% endif %}
</div>
</div>
@@ -213,7 +208,10 @@ $(document).ready( function () {
if (datatables_i18n) datatable_options['language'] = datatables_i18n;
$('.datatables').each(
function(){
- $("#" + $(this).attr('id')).DataTable(datatable_options);
+ var dt_id = "#" + $(this).attr('id');
+ if (! $.fn.DataTable.isDataTable(dt_id) ) {
+ $(dt_id).DataTable(datatable_options);
+ }
});
} );
</script>