diff options
| -rw-r--r-- | archaeological_warehouse/tests.py | 9 | ||||
| -rw-r--r-- | archaeological_warehouse/views.py | 136 | 
2 files changed, 94 insertions, 51 deletions
| diff --git a/archaeological_warehouse/tests.py b/archaeological_warehouse/tests.py index f6d877ec4..21833a08f 100644 --- a/archaeological_warehouse/tests.py +++ b/archaeological_warehouse/tests.py @@ -514,8 +514,8 @@ class ContainerTest(FindInit, TestCase):          )      def test_container_search(self): -        ct = models.ContainerType.objects.all()[0] -        ct2 = models.ContainerType.objects.all()[0] +        ct = models.ContainerType.objects.order_by("id").all()[0] +        ct2 = models.ContainerType.objects.order_by("id").all()[1]          container_1 = models.Container.objects.create(              reference="Test", responsible=self.main_warehouse,              location=self.main_warehouse, @@ -547,9 +547,8 @@ class ContainerTest(FindInit, TestCase):          self.assertEqual(response.status_code, 200)          c = json.loads(response.content.decode())          self.assertEqual(len(c), 1) -        response = client.get( -            url, -            {"term": "{} Test {} Test 35000".format(ct.label, ct2.label)}) +        full_path = "{} Test {} 35000".format(ct.label, ct2.label) +        response = client.get(url, {"term": full_path})          self.assertEqual(response.status_code, 200)          c = json.loads(response.content.decode())          self.assertEqual(len(c), 1) diff --git a/archaeological_warehouse/views.py b/archaeological_warehouse/views.py index efa5bdf19..a9d1bf409 100644 --- a/archaeological_warehouse/views.py +++ b/archaeological_warehouse/views.py @@ -113,63 +113,106 @@ def autocomplete_container(request, warehouse_id=None):      containers += list(models.Container.objects.filter(          query).values('id', 'cached_label')[:limit])      limit = 15 - len(containers) -    splitted = [s for s in term.split(' ') if s] -    if limit > 0: -        if len(splitted) > 1 and not len(splitted) % 2: -            # group by container type, ref tuple -            groups = [(splitted[idx * 2], splitted[idx * 2 + 1]) -                      for idx in range(int(len(splitted) / 2))] +    splitted = [s.lower() for s in term.split(' ') if s] + +    if limit > 0 and len(splitted) > 1: +        type_positions = []  # container_type ID, pos inf, pos sup +        container_types = [ +            (c[0], c[1]) +            for c in models.ContainerType.objects.values_list("id", "label") +        ] +        for container_type_id, value in container_types: +            if value.lower() in term.lower():  # container_type is in search q +                values = [v.lower() for v in value.split(" ") if v] + +                # verify that all term match in splitted +                try: +                    index = splitted.index(values[0].lower()) +                except ValueError: +                    index = None +                index_is_ok = False +                while not index_is_ok and index is not None: +                    for idx, v in enumerate(values): +                        try: +                            assert splitted[index + idx] == v +                        except (ValueError, AssertionError): +                            break +                        index_is_ok = True +                    if not index_is_ok: +                        try: +                            index = splitted.index(values[0].lower(), index + 1) +                        except ValueError: +                            index = None +                if index_is_ok: +                    type_positions.append( +                        (container_type_id, index, index + len(values))) + +        query = base_query +        if not warehouse_id and type_positions and type_positions[0][1] > 0: +            for idx in range(type_positions[0][1]): +                query &= Q(location__name__icontains=splitted[idx]) +        # group by container type, ref tuple +        groups = [] +        for idx, (container_type_id, pos_inf, pos_sup) \ +                in enumerate(type_positions): +            if len(type_positions) == idx + 1:  # last +                value = " ".join(splitted[pos_sup:]) +            else: +                value = " ".join(splitted[pos_sup:type_positions[idx + 1][1]]) +            groups.append((container_type_id, value)) +        if groups:              query = base_query              for idx, g in enumerate(reversed(groups)):                  base_key = "parent__" * idx -                key1 = base_key + "container_type__label__unaccent__iexact" +                key1 = base_key + "container_type_id"                  key2 = base_key + "reference__unaccent__iexact"                  query &= Q(**{key1: g[0], key2: g[1]}) -            ids = set([c["id"] for c in containers]) +            ids = {c["id"] for c in containers}              containers += list(models.Container.objects.filter(                  query).exclude(pk__in=ids).values('id', 'cached_label')[                                 :limit]) -        if len(splitted) > 1 and (15 - len(containers)) > 0: -            # group to do a "type" "reference" search -            for idx in range(1, len(splitted)): -                group_1 = splitted[:idx] -                group_2 = splitted[idx:] -                extra = Q( -                    container_type__label__unaccent__iexact=" ".join(group_1), -                    reference__unaccent__iexact=" ".join(group_2)) -                query = base_query & extra -                ids = set([c["id"] for c in containers]) -                containers += list(models.Container.objects.filter( -                    query).exclude(pk__in=ids).values('id', 'cached_label')[ -                                   :limit]) -                if (15 - len(containers)) <= 0: -                    break -        if (15 - len(containers)) > 0: +    if len(splitted) > 1 and len(containers) < 15: +        # group to do a "type" "reference" search +        for idx in range(1, len(splitted)): +            group_1 = splitted[:idx] +            group_2 = splitted[idx:] +            extra = Q( +                container_type__label__unaccent__iexact=" ".join(group_1), +                reference__unaccent__iexact=" ".join(group_2)) +            query = base_query & extra +            ids = {c["id"] for c in containers} +            containers += list(models.Container.objects.filter( +                query).exclude(pk__in=ids).values('id', 'cached_label')[ +                               :limit]) +            if len(containers) >= 15: +                break + +    if len(containers) < 15: +        query = base_query +        for q in splitted: +            extra = Q(reference__unaccent__iexact=q) +            query = query & extra +        ids = {c["id"] for c in containers} +        containers += list(models.Container.objects.filter( +            query).exclude(pk__in=ids).values('id', 'cached_label')[:limit]) +        limit = 15 - len(containers) +        if limit > 0:              query = base_query              for q in splitted: -                extra = Q(reference__unaccent__iexact=q) +                extra = Q(container_type__label__unaccent__icontains=q) | \ +                    Q(container_type__reference__unaccent__icontains=q) | \ +                    Q(reference__unaccent__icontains=q) | \ +                    Q(cached_label__unaccent__icontains=q) +                if not warehouse_id: +                    extra |= Q(location__name__unaccent=q) | Q( +                        location__town__unaccent=q)                  query = query & extra -            ids = set([c["id"] for c in containers]) -            containers += list(models.Container.objects.filter( -                query).exclude(pk__in=ids).values('id', 'cached_label')[:limit]) -            limit = 15 - len(containers) -            if limit > 0: -                query = base_query -                for q in splitted: -                    extra = Q(container_type__label__unaccent__icontains=q) | \ -                        Q(container_type__reference__unaccent__icontains=q) | \ -                        Q(reference__unaccent__icontains=q) | \ -                        Q(cached_label__unaccent__icontains=q) -                    if not warehouse_id: -                        extra |= Q(location__name__unaccent=q) | Q( -                            location__town__unaccent=q) -                    query = query & extra -                ids = set([c["id"] for c in containers]) -                containers += list( -                    models.Container.objects.filter(query).exclude( -                        pk__in=ids -                    ).values('id', 'cached_label')[:limit]) +            ids = {c["id"] for c in containers} +            containers += list( +                models.Container.objects.filter(query).exclude( +                    pk__in=ids +                ).values('id', 'cached_label')[:limit])      data = json.dumps(          [{'id': container['id'], 'value': container['cached_label']}           for container in containers]) @@ -304,7 +347,8 @@ def container_treatment_add(request, pk, current_right=None):      except models.Container.DoesNotExist:          raise Http404()      return treatment_add( -        request, ",".join([str(f.pk) for f in container.finds.all()])) +        request, ",".join(str(f.pk) for f in container.finds.all()) +    )  """  warehouse_packaging_wizard = ItemSourceWizard.as_view([ | 
