Skip to content

Commit

Permalink
Add location model and location field to org
Browse files Browse the repository at this point in the history
  • Loading branch information
norkans7 committed Jan 10, 2025
1 parent fa247ba commit e54497c
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Generated by Django 5.1.4 on 2025-01-10 10:06

import mptt.fields

import django.db.models.deletion
import django.db.models.functions.text
import django.utils.timezone
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("locations", "0032_squashed"),
("orgs", "0164_remove_viewers"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name="Location",
fields=[
("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
("osm_id", models.CharField(max_length=15, unique=True)),
("name", models.CharField(max_length=128)),
("level", models.IntegerField()),
("path", models.CharField(max_length=768)),
("geometry", models.JSONField(null=True)),
("lft", models.PositiveIntegerField(editable=False)),
("rght", models.PositiveIntegerField(editable=False)),
("tree_id", models.PositiveIntegerField(db_index=True, editable=False)),
(
"parent",
mptt.fields.TreeForeignKey(
null=True,
on_delete=django.db.models.deletion.PROTECT,
related_name="children",
to="locations.location",
),
),
],
),
migrations.CreateModel(
name="LocationAlias",
fields=[
("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
(
"is_active",
models.BooleanField(
default=True, help_text="Whether this item is active, use this instead of deleting"
),
),
(
"created_on",
models.DateTimeField(
blank=True,
default=django.utils.timezone.now,
editable=False,
help_text="When this item was originally created",
),
),
(
"modified_on",
models.DateTimeField(
blank=True,
default=django.utils.timezone.now,
editable=False,
help_text="When this item was last modified",
),
),
("name", models.CharField(help_text="The name for our alias", max_length=128)),
(
"created_by",
models.ForeignKey(
help_text="The user which originally created this item",
on_delete=django.db.models.deletion.PROTECT,
related_name="%(app_label)s_%(class)s_creations",
to=settings.AUTH_USER_MODEL,
),
),
(
"location",
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT, related_name="aliases", to="locations.location"
),
),
(
"modified_by",
models.ForeignKey(
help_text="The user which last modified this item",
on_delete=django.db.models.deletion.PROTECT,
related_name="%(app_label)s_%(class)s_modifications",
to=settings.AUTH_USER_MODEL,
),
),
("org", models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to="orgs.org")),
],
),
migrations.AddIndex(
model_name="location",
index=models.Index(django.db.models.functions.text.Lower("name"), name="locations_by_name"),
),
migrations.AddIndex(
model_name="locationalias",
index=models.Index(django.db.models.functions.text.Lower("name"), name="locationaliases_by_name"),
),
]
43 changes: 42 additions & 1 deletion temba/locations/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from django.contrib.gis.db import models
from django.db.models import F, Value
from django.db.models.functions import Concat, Upper
from django.db.models.functions import Concat, Lower, Upper


# default manager for AdminBoundary, doesn't load geometries
Expand Down Expand Up @@ -178,3 +178,44 @@ def create(cls, org, user, boundary, name):

class Meta:
indexes = [models.Index(Upper("name"), name="boundaryaliases_by_name")]


class Location(MPTTModel, models.Model):
"""
Represents a single administrative locations (like a country, state or district)
"""

LEVEL_COUNTRY = 0
LEVEL_STATE = 1
LEVEL_DISTRICT = 2
LEVEL_WARD = 3

MAX_NAME_LEN = 128

# Used to separate segments in a hierarchy of locations. Has the advantage of being a character in GSM7 and
# being very unlikely to show up in an admin region name.
PATH_SEPARATOR = ">"
PADDED_PATH_SEPARATOR = " > "

osm_id = models.CharField(max_length=15, unique=True)
name = models.CharField(max_length=MAX_NAME_LEN)
level = models.IntegerField()
parent = TreeForeignKey("self", null=True, on_delete=models.PROTECT, related_name="children", db_index=True)
path = models.CharField(max_length=768) # e.g. Rwanda > Kigali
geometry = models.JSONField(null=True)

class Meta:
indexes = [models.Index(Lower("name"), name="locations_by_name")]


class LocationAlias(SmartModel):
"""
An org specific alias for a location name
"""

org = models.ForeignKey("orgs.Org", on_delete=models.PROTECT)
location = models.ForeignKey(Location, on_delete=models.PROTECT, related_name="aliases")
name = models.CharField(max_length=Location.MAX_NAME_LEN, help_text="The name for our alias")

class Meta:
indexes = [models.Index(Lower("name"), name="locationaliases_by_name")]
2 changes: 1 addition & 1 deletion temba/orgs/migrations/0164_remove_viewers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from django.db import migrations


def remove_viewers(apps, schema_editor):
def remove_viewers(apps, schema_editor): # pragma: no cover
OrgMembership = apps.get_model("orgs", "OrgMembership")
num_deleted = OrgMembership.objects.filter(role_code="V").delete()[0]
if num_deleted:
Expand Down
20 changes: 20 additions & 0 deletions temba/orgs/migrations/0165_org_location.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Generated by Django 5.1.4 on 2025-01-10 10:06

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("locations", "0033_location_locationalias_location_locations_by_name_and_more"),
("orgs", "0164_remove_viewers"),
]

operations = [
migrations.AddField(
model_name="org",
name="location",
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to="locations.location"),
),
]
1 change: 1 addition & 0 deletions temba/orgs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,7 @@ class Org(SmartModel):
help_text=_("Default formatting and parsing of dates in flows and messages."),
)
country = models.ForeignKey("locations.AdminBoundary", null=True, on_delete=models.PROTECT)
location = models.ForeignKey("locations.Location", null=True, on_delete=models.PROTECT)
flow_languages = ArrayField(models.CharField(max_length=3), default=list, validators=[ArrayMinLengthValidator(1)])
input_collation = models.CharField(max_length=32, choices=COLLATION_CHOICES, default=COLLATION_DEFAULT)
flow_smtp = models.CharField(null=True) # e.g. smtp://...
Expand Down
10 changes: 0 additions & 10 deletions temba/orgs/tests/test_migrations.py

This file was deleted.

0 comments on commit e54497c

Please sign in to comment.