diff options
Diffstat (limited to 'ishtar_common/models.py')
| -rw-r--r-- | ishtar_common/models.py | 65 | 
1 files changed, 63 insertions, 2 deletions
| diff --git a/ishtar_common/models.py b/ishtar_common/models.py index a03b90434..a1f91282e 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -52,6 +52,7 @@ from django.contrib.auth.models import User, Group  from django.contrib.contenttypes.fields import GenericForeignKey  from django.contrib.contenttypes.models import ContentType  from django.contrib.gis.db import models +from django.contrib.gis.db.models.aggregates import Union  from django.contrib.postgres.fields import JSONField  from django.contrib.postgres.indexes import GinIndex  from django.contrib.sites.models import Site @@ -141,6 +142,8 @@ from ishtar_common.models_common import (      SearchAltName,      DynamicRequest,      GeoItem, +    GeoDataType, +    GeoVectorData,      CompleteIdentifierItem,      SearchVectorConfig,      DocumentItem, @@ -2251,8 +2254,8 @@ class Area(HierarchicalType):      )      class Meta: -        verbose_name = _("Area") -        verbose_name_plural = _("Areas") +        verbose_name = _("Town - Area") +        verbose_name_plural = _("Town - Areas")          ordering = ("label",)      def __str__(self): @@ -2260,6 +2263,64 @@ class Area(HierarchicalType):              return self.label          return "{} ({})".format(self.label, self.reference) +    @classmethod +    def get_or_create_by_towns(cls, towns, get_geo=False): +        if hasattr(towns, "all"):  # queryset +            if not towns.count(): +                return +            towns = towns.all() +        elif not len(towns): +            return +        name = [] +        reference = [] +        for town in sorted(towns, key=lambda x: (x.numero_insee, x.name)): +            name.append(town._generate_cached_label()) +            reference.append(town.numero_insee or slugify(town.name)) +        name = " / ".join(name) +        reference = f"{_('area')}-{'/'.join(reference)}" +        area, created = cls.objects.get_or_create( +            reference=reference, +            defaults={"label": name} +        ) + +        area_content_type = ContentType.objects.get(app_label="ishtar_common", +                                                    model="area") +        attrs = { +            "source_content_type": area_content_type, +            "source_id": area.pk, +        } +        q = GeoVectorData.objects.filter(**attrs) +        if created or not q.count(): +            data_type, __ = GeoDataType.objects.get_or_create( +                txt_idx="area-limit", +                defaults={"label": str(_("Communal area boundaries"))} +            ) +            attrs["data_type"] = data_type +            geo = GeoVectorData.objects.create(**attrs) +        else: +            geo = q.all()[0] + +        q_poly_towns = GeoVectorData.objects.filter( +            source_content_type__app_label="ishtar_common", +            source_content_type__model="town", +            source_id__in=[t.pk for t in towns]) +        q_poly = q_poly_towns.annotate(poly=Union("multi_polygon")) +        poly = q_poly.all()[0].poly +        if not geo.multi_polygon or not geo.multi_polygon.equals_exact(poly, 0.001): +            origins, providers = [], [] +            for g in q_poly_towns: +                origins.append(g.origin) +                providers.append(g.provider) +            if len(set(origins)) == 1:  # no ambiguous origin +                geo.origin = origins[0] +            if len(set(providers)) == 1:  # no ambiguous provider +                geo.provider = providers[0] +            geo.multi_polygon = poly +            geo.save() +        if get_geo: +            return geo +        return area +      @property      def full_label(self):          label = [str(self)] | 
