diff options
Diffstat (limited to 'archaeological_warehouse/models.py')
| -rw-r--r-- | archaeological_warehouse/models.py | 102 | 
1 files changed, 68 insertions, 34 deletions
| diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py index 096ff0b6c..870f10d95 100644 --- a/archaeological_warehouse/models.py +++ b/archaeological_warehouse/models.py @@ -25,7 +25,7 @@ from django.conf import settings  from django.contrib.gis.db import models  from django.contrib.postgres.indexes import GinIndex  from django.core.urlresolvers import reverse -from django.db.models import Q, Max +from django.db.models import Q, Max, Count  from django.db.models.signals import post_save, post_delete, m2m_changed  from django.template.defaultfilters import slugify  from ishtar_common.utils import ugettext_lazy as _, pgettext_lazy @@ -131,6 +131,9 @@ class Warehouse(Address, DocumentItem, GeoItem, QRCodeItem, DashboardFormItem,      external_id = models.TextField(_("External ID"), blank=True, null=True)      auto_external_id = models.BooleanField(          _("External ID is set automatically"), default=False) +    max_division_number = models.IntegerField( +        _("Number maximum of division"), default=0, +        help_text=_("Automatically generated"))      SUB_ADDRESSES = ["organization", "person_in_charge"]      class Meta: @@ -190,10 +193,11 @@ class Warehouse(Address, DocumentItem, GeoItem, QRCodeItem, DashboardFormItem,      @property      def location_types(self): +        if not self.max_division_number: +            return []          return [ -            wd.container_type.label -            for wd in WarehouseDivisionLink.objects.filter( -                warehouse=self).order_by('order').all() if wd.container_type +            "{} {}".format(_("Division"), idx + 1) +            for idx in range(self.max_division_number)          ]      @property @@ -227,33 +231,53 @@ class Warehouse(Address, DocumentItem, GeoItem, QRCodeItem, DashboardFormItem,      def _get_divisions(self, current_path, remaining_division, depth=0):          if not remaining_division:              return [current_path] -        current_division = remaining_division.pop(0) +        remaining_division.pop(0) -        base_q = Container.objects.filter( -            container_type=current_division, -            location=self -        ) -        q = base_q -        for div, ref in current_path: -            q = base_q.filter( -                parent__container_type=div, -                parent__reference=ref) +        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 = None +        old_ref, ct = None, None          if not q.count():              return [current_path] -        for ref in q.values('reference').order_by('reference').all(): -            if ref['reference'] == old_ref: +        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[:] -            cpath.append((current_division, ref['reference'])) +            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=current_division, -                    containers__location=self, -                    stationary=True).distinct()) +                    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) @@ -263,7 +287,7 @@ class Warehouse(Address, DocumentItem, GeoItem, QRCodeItem, DashboardFormItem,      def available_division_tuples(self):          """          :return: ordered list of available paths. Each path is a list of -        tuple with the container type and the reference. +        tuple with the container type and the full reference.          """          top_divisions = list(              ContainerType.objects.filter( @@ -278,20 +302,16 @@ class Warehouse(Address, DocumentItem, GeoItem, QRCodeItem, DashboardFormItem,          paths = self.available_division_tuples[:]          for path in paths:              cpath = [] -            cdiv_path = [] -            for division, ref in path: -                cpath.append(ref) -                cdiv_path.append(division) +            for container_id, lbl in path: +                cpath.append((container_id, lbl))                  if tuple(cpath) in res:                      continue                  q = model.objects -                reversed_cdiv = list(reversed(cdiv_path)) -                for idx, new_ref in enumerate(reversed(cpath)): -                    division = reversed_cdiv[idx] +                for idx, p in enumerate(reversed(cpath)): +                    container_id, __ = p                      div_key = division_key + "parent__" * idx                      attrs = { -                        div_key + "container_type": division, -                        div_key + "reference": new_ref +                        div_key + "id": container_id                      }                      q = q.filter(**attrs)                  if count_filter: @@ -300,16 +320,18 @@ class Warehouse(Address, DocumentItem, GeoItem, QRCodeItem, DashboardFormItem,          res = [(k, res[k]) for k in res]          final_res, current_res, depth = [], [], 1 -        len_divisions = WarehouseDivisionLink.objects.filter( -            warehouse=self).count() +        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 = list(path) + ['' for __ in range(len_divisions - len(path))] +            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 @@ -1173,10 +1195,22 @@ class Container(DocumentItem, Merge, LightHistorizedItem, QRCodeItem, GeoItem,              else:                  self.index = 1 +    def _update_warehouse_max_division(self): +        number = 0 +        parent = self.parent_id +        while parent: +            number += 1 +            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() +      def save(self, *args, **kwargs):          self.pre_save()          super(Container, self).save(*args, **kwargs)          self._change_child_location(self) +        self._update_warehouse_max_division()          updated = False          if not self.index: | 
