Skip to content

Commit

Permalink
Merge pull request #359 from City-of-Turku/bugfix/import-traffic-situ…
Browse files Browse the repository at this point in the history
…ation-location-is-none

Bugfix/import traffic situation location is none
  • Loading branch information
juuso-j authored Jun 10, 2024
2 parents 0e269f4 + 1b6ada8 commit 3012793
Show file tree
Hide file tree
Showing 6 changed files with 486 additions and 64 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import logging

from django.core.management import BaseCommand

from exceptional_situations.models import (
Situation,
SituationAnnouncement,
SituationLocation,
)

logger = logging.getLogger(__name__)


class Command(BaseCommand):
def handle(self, *args, **options):
SituationLocation.objects.all().delete()
SituationAnnouncement.objects.all().delete()
Situation.objects.all().delete()
logger.info("Deleted all situations.")
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,19 @@
)


def get_or_create(model, filter):
obj = model.objects.filter(**filter).first()
if obj:
return obj
else:
return model.objects.create(**filter)


class Command(BaseCommand):
def get_geos_geometry(self, feature_data):
return GEOSGeometry(str(feature_data["geometry"]), srid=PROJECTION_SRID)

def create_location(self, geometry, announcement_data, announcement):
def create_location(self, geometry, announcement_data):
location = None
details = announcement_data["locationDetails"].get("roadAddressLocation", None)
if details:
Expand All @@ -54,12 +62,10 @@ def create_location(self, geometry, announcement_data, announcement):
"geometry": geometry,
"location": location,
"details": details,
"announcement": announcement,
}
situation_location = SituationLocation.objects.create(**filter)
return situation_location
return get_or_create(SituationLocation, filter)

def create_announcement(self, announcement_data):
def create_announcement(self, announcement_data, location):
title = announcement_data.get("title", "")
description = announcement_data["location"].get("description", "")
additional_info = {}
Expand Down Expand Up @@ -89,69 +95,82 @@ def create_announcement(self, announcement_data):
"additional_info": additional_info,
"start_time": start_time,
"end_time": end_time,
"location": location,
}
situation_announcement = SituationAnnouncement.objects.create(**filter)
return situation_announcement
return get_or_create(SituationAnnouncement, filter)

def handle(self, *args, **options):
def save_features(self, features):
num_imported = 0
for url in URLS:
try:
response = requests.get(url)
assert response.status_code == 200
except AssertionError:
for feature_data in features:
geometry = self.get_geos_geometry(feature_data)
if not SOUTHWEST_FINLAND_POLYGON.intersects(geometry):
continue
features = response.json()["features"]

for feature_data in features:
geometry = self.get_geos_geometry(feature_data)
if not SOUTHWEST_FINLAND_POLYGON.intersects(geometry):
continue

properties = feature_data.get("properties", None)
if not properties:
continue
situation_id = properties.get("situationId", None)
release_time_str = properties.get("releaseTime", None)
if release_time_str:
for format_str in DATETIME_FORMATS:
try:
release_time = datetime.strptime(
release_time_str, format_str
)
except ValueError:
pass
else:
break

if release_time.microsecond != 0:
release_time.replace(microsecond=0)
release_time = timezone.make_aware(release_time, timezone.utc)

type_name = properties.get("situationType", None)
sub_type_name = properties.get("trafficAnnouncementType", None)

situation_type, _ = SituationType.objects.get_or_create(
type_name=type_name, sub_type_name=sub_type_name
properties = feature_data.get("properties", None)
if not properties:
continue
situation_id = properties.get("situationId", None)
release_time_str = properties.get("releaseTime", None)
if release_time_str:
for format_str in DATETIME_FORMATS:
try:
release_time = datetime.strptime(release_time_str, format_str)
except ValueError:
pass
else:
break

if release_time.microsecond != 0:
release_time.replace(microsecond=0)
release_time = timezone.make_aware(release_time, timezone.utc)

type_name = properties.get("situationType", None)
sub_type_name = properties.get("trafficAnnouncementType", None)

situation_type, _ = SituationType.objects.get_or_create(
type_name=type_name, sub_type_name=sub_type_name
)

filter = {
"situation_id": situation_id,
"situation_type": situation_type,
}
situation, created = Situation.objects.get_or_create(**filter)
situation.release_time = release_time
situation.save()
if not created:
SituationAnnouncement.objects.filter(situation=situation).delete()
situation.announcements.clear()
for announcement_data in properties.get("announcements", []):
situation_location = self.create_location(geometry, announcement_data)
situation_announcement = self.create_announcement(
deepcopy(announcement_data), situation_location
)
situation.announcements.add(situation_announcement)
num_imported += 1
return num_imported

def add_arguments(self, parser):
parser.add_argument(
"--test-importer",
type=list,
default=[],
nargs="*",
help="Test importing of data.",
)

filter = {
"situation_id": situation_id,
"situation_type": situation_type,
}
situation, created = Situation.objects.get_or_create(**filter)
situation.release_time = release_time
situation.save()
if not created:
SituationAnnouncement.objects.filter(situation=situation).delete()
situation.announcements.clear()
for announcement_data in properties.get("announcements", []):
situation_announcement = self.create_announcement(
deepcopy(announcement_data)
)
self.create_location(
geometry, announcement_data, situation_announcement
)
situation.announcements.add(situation_announcement)
num_imported += 1
logger.info(f"Imported/updated {num_imported} traffic situations.")
def handle(self, *args, **options):
num_imported = 0
if options.get("test_importer", False):
features = [options["test_importer"][0]]
self.save_features(features)
else:
for url in URLS:
try:
response = requests.get(url)
assert response.status_code == 200
except AssertionError:
continue
features = response.json()["features"]
num_imported += self.save_features(features)
logger.info(f"Imported/updated {num_imported} traffic situations.")
5 changes: 5 additions & 0 deletions exceptional_situations/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,8 @@ def import_traffic_situations(name="import_traffic_situations"):
@shared_task_email
def delete_inactive_situations(name="delete_inactive_situations"):
management.call_command("delete_inactive_situations")


@shared_task_email
def delete_all_situations(name="delete_all_situations"):
management.call_command("delete_all_situations")
Loading

0 comments on commit 3012793

Please sign in to comment.