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 | 75e4fda871103f74e2aaad5ad663a3a734108a80 (patch) | |
| tree | 21976a27b67c98aa1a79a63f190d06dd489b89ec /archaeological_warehouse/models.py | |
| parent | 00d53a94deb9e7bcd232ef481fdac30269fc76d7 (diff) | |
| download | Ishtar-75e4fda871103f74e2aaad5ad663a3a734108a80.tar.bz2 Ishtar-75e4fda871103f74e2aaad5ad663a3a734108a80.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/models.py')
| -rw-r--r-- | archaeological_warehouse/models.py | 103 | 
1 files changed, 99 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='') | 
