-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactored the bulk gps check in order to call it inside the task. Fixed typo in HasCreateOrgUnitPermission.
- Loading branch information
Showing
9 changed files
with
662 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
from rest_framework import viewsets, permissions, status | ||
from rest_framework.response import Response | ||
|
||
from iaso.api.instances import HasInstanceBulkPermission | ||
from iaso.api.org_units import HasCreateOrgUnitPermission | ||
from iaso.api.tasks import TaskSerializer | ||
from iaso.tasks.instance_bulk_gps_push import instance_bulk_gps_push | ||
|
||
|
||
class InstanceBulkGpsPushViewSet(viewsets.ViewSet): | ||
"""Bulk push gps location from Instances to their related OrgUnit. | ||
This task will override existing location on OrgUnits and might set `None` if the Instance doesn't have any location. | ||
Calling this endpoint implies that the InstanceViewSet.check_bulk_gps_push() method has been called before and has returned no error. | ||
""" | ||
|
||
permission_classes = [permissions.IsAuthenticated, HasInstanceBulkPermission, HasCreateOrgUnitPermission] | ||
|
||
def create(self, request): | ||
raw_select_all = request.data.get("select_all", True) | ||
select_all = raw_select_all not in [False, "false", "False", "0", 0] | ||
selected_ids = request.data.get("selected_ids", []) | ||
unselected_ids = request.data.get("unselected_ids", []) | ||
|
||
user = self.request.user | ||
|
||
task = instance_bulk_gps_push( | ||
select_all=select_all, selected_ids=selected_ids, unselected_ids=unselected_ids, user=user | ||
) | ||
return Response( | ||
{"task": TaskSerializer(instance=task).data}, | ||
status=status.HTTP_201_CREATED, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
from copy import deepcopy | ||
from logging import getLogger | ||
from time import time | ||
from typing import Optional, List | ||
|
||
from django.contrib.auth.models import User | ||
from django.db import transaction | ||
|
||
from beanstalk_worker import task_decorator | ||
from hat.audit import models as audit_models | ||
from iaso.models import Task, Instance | ||
from iaso.utils.gis import convert_2d_point_to_3d | ||
from iaso.utils.models.common import check_instance_bulk_gps_push | ||
|
||
logger = getLogger(__name__) | ||
|
||
|
||
def push_single_instance_gps_to_org_unit(user: Optional[User], instance: Instance): | ||
org_unit = instance.org_unit | ||
original_copy = deepcopy(org_unit) | ||
org_unit.location = convert_2d_point_to_3d(instance.location) if instance.location else None | ||
org_unit.save() | ||
if not original_copy.location: | ||
logger.info(f"updating {org_unit.name} {org_unit.id} with {org_unit.location}") | ||
else: | ||
logger.info( | ||
f"updating {org_unit.name} {org_unit.id} - overwriting {original_copy.location} with {org_unit.location}" | ||
) | ||
audit_models.log_modification(original_copy, org_unit, source=audit_models.INSTANCE_API_BULK, user=user) | ||
|
||
|
||
@task_decorator(task_name="instance_bulk_gps_push") | ||
def instance_bulk_gps_push( | ||
select_all: bool, | ||
selected_ids: List[int], | ||
unselected_ids: List[int], | ||
task: Task, | ||
): | ||
"""Background Task to bulk push instance gps to org units. | ||
/!\ Danger: calling this task without having received a successful response from the check_bulk_gps_push | ||
endpoint will have unexpected results that might cause data loss. | ||
""" | ||
start = time() | ||
task.report_progress_and_stop_if_killed(progress_message="Searching for Instances for pushing gps data") | ||
|
||
user = task.launcher | ||
|
||
queryset = Instance.non_deleted_objects.get_queryset().filter_for_user(user) | ||
queryset = queryset.select_related("org_unit") | ||
|
||
if not select_all: | ||
queryset = queryset.filter(pk__in=selected_ids) | ||
else: | ||
queryset = queryset.exclude(pk__in=unselected_ids) | ||
|
||
if not queryset: | ||
raise Exception("No matching instances found") | ||
|
||
# Checking if any gps push can be performed with what was requested | ||
success, errors, _ = check_instance_bulk_gps_push(queryset) | ||
if not success: | ||
raise Exception("Cannot proceed with the gps push due to errors: %s" % errors) | ||
|
||
total = queryset.count() | ||
|
||
with transaction.atomic(): | ||
for index, instance in enumerate(queryset.iterator()): | ||
res_string = "%.2f sec, processed %i instances" % (time() - start, index) | ||
task.report_progress_and_stop_if_killed(progress_message=res_string, end_value=total, progress_value=index) | ||
push_single_instance_gps_to_org_unit( | ||
user, | ||
instance, | ||
) | ||
|
||
task.report_success(message="%d modified" % total) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.