diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2017-04-05 11:33:54 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2017-04-05 11:33:54 +0200 |
commit | 2e512bc9dffca5624342aa75ca01b3ff7f390141 (patch) | |
tree | 21976a27b67c98aa1a79a63f190d06dd489b89ec /archaeological_warehouse | |
parent | 3a5dbf688d058bd39aaae308cd7224ddd42c7890 (diff) | |
download | Ishtar-2e512bc9dffca5624342aa75ca01b3ff7f390141.tar.bz2 Ishtar-2e512bc9dffca5624342aa75ca01b3ff7f390141.zip |
Warehouse sheet: provide statistics (refs #3398)
- Number of finds (total and by places)
- Number of container (total and by places)
Diffstat (limited to 'archaeological_warehouse')
-rw-r--r-- | archaeological_warehouse/models.py | 103 | ||||
-rw-r--r-- | archaeological_warehouse/templates/ishtar/sheet_warehouse.html | 44 |
2 files changed, 143 insertions, 4 deletions
diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py index fe054a37b..2851e1df0 100644 --- a/archaeological_warehouse/models.py +++ b/archaeological_warehouse/models.py @@ -21,7 +21,7 @@ import datetime from django.conf import settings from django.contrib.gis.db import models -from django.db.models import Q +from django.db.models import Q, Count from django.db.models.signals import post_save, post_delete from django.template.defaultfilters import slugify from django.utils.translation import ugettext_lazy as _, ugettext @@ -29,7 +29,9 @@ from django.utils.translation import ugettext_lazy as _, ugettext from ishtar_common.utils import cached_label_changed from ishtar_common.models import GeneralType, get_external_id, \ - LightHistorizedItem, OwnPerms, Address, Person, post_save_cache, ImageModel + LightHistorizedItem, OwnPerms, Address, Person, post_save_cache, \ + ImageModel, DashboardFormItem +from archaeological_finds.models import Find class WarehouseType(GeneralType): @@ -41,7 +43,7 @@ post_save.connect(post_save_cache, sender=WarehouseType) post_delete.connect(post_save_cache, sender=WarehouseType) -class Warehouse(Address, OwnPerms): +class Warehouse(Address, DashboardFormItem, OwnPerms): SHOW_URL = 'show-warehouse' name = models.CharField(_(u"Name"), max_length=200) warehouse_type = models.ForeignKey(WarehouseType, @@ -83,6 +85,98 @@ class Warehouse(Address, OwnPerms): def get_query_owns(cls, user): return Q(person_in_charge__ishtaruser=user.ishtaruser) + @property + def number_of_finds(self): + return Find.objects.filter(container__responsible=self).count() + + @property + def number_of_finds_hosted(self): + 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] + current_division = remaining_division.pop(0) + q = ContainerLocalisation.objects.filter( + division=current_division, + ) + for div, ref in current_path: + q = q.filter( + container__division__division=div, + container__division__reference=ref + ) + res = [] + old_ref = None + for ref in q.values('reference').order_by('reference').all(): + if ref['reference'] == old_ref: + continue + old_ref = ref['reference'] + cpath = current_path[:] + cpath.append((current_division, ref['reference'])) + 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 WarehouseDivisionLink and the reference. + """ + divisions = list( + WarehouseDivisionLink.objects.filter(warehouse=self + ).order_by('order').all()) + return self._get_divisions([], divisions) + + def _number_of_items_by_place(self, model, division_key='division'): + res = {} + paths = self.available_division_tuples[:] + for path in paths: + q = model.objects + cpath = [] + for division, ref in path: + lbl = u"{} {}".format(division.division, ref) + cpath.append(lbl) + attrs = { + division_key + "__division": division, + division_key + "__reference": ref + } + q = q.filter(**attrs) + if tuple(cpath) not in res: + res[tuple(cpath)] = q.count() + res = [(k, res[k]) for k in res] + final_res, current_res, depth = [], [], 1 + for path, nb in sorted(res, key=lambda x: (len(x[0]), x[0])): + if depth != len(path): + final_res.append(current_res[:]) + current_res = [] + depth = len(path) + current_res.append((u" | ".join(path), nb)) + final_res.append(current_res[:]) + return final_res + + def _number_of_finds_by_place(self): + return self._number_of_items_by_place( + Find, division_key='container__division') + + @property + def number_of_finds_by_place(self, update=False): + return self._get_or_set_stats('_number_of_finds_by_place', update, + settings.CACHE_SMALLTIMEOUT) + + def _number_of_containers_by_place(self): + return self._number_of_items_by_place(Container) + + @property + def number_of_containers_by_place(self, update=False): + return self._get_or_set_stats('_number_of_containers_by_place', update, + settings.CACHE_SMALLTIMEOUT) + def save(self, *args, **kwargs): super(Warehouse, self).save(*args, **kwargs) for container in self.containers.all(): @@ -287,7 +381,8 @@ post_save.connect(cached_label_changed, sender=Container) class ContainerLocalisation(models.Model): - container = models.ForeignKey(Container, verbose_name=_(u"Container")) + container = models.ForeignKey(Container, verbose_name=_(u"Container"), + related_name='division') division = models.ForeignKey(WarehouseDivisionLink, verbose_name=_(u"Division")) reference = models.CharField(_(u"Reference"), max_length=200, default='') diff --git a/archaeological_warehouse/templates/ishtar/sheet_warehouse.html b/archaeological_warehouse/templates/ishtar/sheet_warehouse.html index c31fc93b4..17a2c6c2b 100644 --- a/archaeological_warehouse/templates/ishtar/sheet_warehouse.html +++ b/archaeological_warehouse/templates/ishtar/sheet_warehouse.html @@ -26,4 +26,48 @@ {% dynamic_table_document '' 'containers' 'responsible' item.pk 'TABLE_COLS' output %} {% endif %} +<h3>{% trans "Statistics" %}</h3> +<small class="centered"><em>{% trans "Theses number are updated hourly" %}</em></small> + +<h4>{% trans "Finds" %}</h4> +<ul class='form-flex'> + {% field_li "Number of attached finds" item.number_of_finds %} + {% field_li "Number of hosted finds" item.number_of_finds_hosted %} +</ul> + +{% if item.number_of_finds_by_place %} +<h4>{% trans "Finds by location in the warehouse" %}</h4> +<ul class='form-flex'> + {% for items in item.number_of_finds_by_place %} + <li> + <table class='clean-table small'> + {% for item in items %} + <tr><th>{{item.0}}</th><td>{{item.1}}</td></tr> + {% endfor %} + </table> + </li> + {% endfor %} +</ul> +{% endif %} + +<h4>{% trans "Containers" %}</h4> +<ul class='form-flex'> + {% field_li "Number of containers" item.number_of_containers %} +</ul> + +{% if item.number_of_containers_by_place %} +<h4>{% trans "Containers by location in the warehouse" %}</h4> +<ul class='form-flex'> + {% for items in item.number_of_containers_by_place %} + <li> + <table class='clean-table small'> + {% for item in items %} + <tr><th>{{item.0}}</th><td>{{item.1}}</td></tr> + {% endfor %} + </table> + </li> + {% endfor %} +</ul> +{% endif %} + {% endblock %} |