def stop_validating_tasks(
            stop_validating_dto: StopValidationDTO) -> TaskDTOs:
        """
        Unlocks supplied tasks after validation
        :raises ValidatatorServiceError
        """
        reset_tasks = stop_validating_dto.reset_tasks
        project_id = stop_validating_dto.project_id
        user_id = stop_validating_dto.user_id
        tasks_to_unlock = ValidatorService.get_tasks_locked_by_user(
            project_id, reset_tasks, user_id)

        dtos = []
        for task_to_unlock in tasks_to_unlock:
            task = task_to_unlock['task']

            if task_to_unlock['comment']:
                # Parses comment to see if any users have been @'d
                MessageService.send_message_after_comment(
                    user_id, task_to_unlock['comment'], task.id, project_id)

            task.reset_lock(user_id, task_to_unlock['comment'])
            dtos.append(task.as_dto())

        task_dtos = TaskDTOs()
        task_dtos.tasks = dtos

        return task_dtos
    def unlock_tasks_after_validation(
            validated_dto: UnlockAfterValidationDTO) -> TaskDTOs:
        """
        Unlocks supplied tasks after validation
        :raises ValidatatorServiceError
        """
        validated_tasks = validated_dto.validated_tasks
        project_id = validated_dto.project_id
        user_id = validated_dto.user_id
        tasks_to_unlock = ValidatorService.get_tasks_locked_by_user(
            project_id, validated_tasks, user_id)

        # Unlock all tasks
        dtos = []
        message_sent_to = []
        for task_to_unlock in tasks_to_unlock:
            task = task_to_unlock['task']

            if task_to_unlock['comment']:
                # Parses comment to see if any users have been @'d
                MessageService.send_message_after_comment(
                    validated_dto.user_id, task_to_unlock['comment'], task.id,
                    validated_dto.project_id)
            if task_to_unlock[
                    'new_state'] == TaskStatus.VALIDATED or task_to_unlock[
                        'new_state'] == TaskStatus.INVALIDATED:
                # All mappers get a notification if their task has been validated or invalidated.
                # Only once if multiple tasks mapped
                if task.mapped_by not in message_sent_to:
                    MessageService.send_message_after_validation(
                        task_to_unlock['new_state'], validated_dto.user_id,
                        task.mapped_by, task.id, validated_dto.project_id)
                    message_sent_to.append(task.mapped_by)

                if task_to_unlock['new_state'] == TaskStatus.VALIDATED:
                    # Set last_validation_date for the mapper to current date
                    task.mapper.last_validation_date = timestamp()

            # Update stats if user setting task to a different state from previous state
            prev_status = TaskHistory.get_last_status(project_id, task.id)
            if prev_status != task_to_unlock['new_state']:
                StatsService.update_stats_after_task_state_change(
                    validated_dto.project_id, validated_dto.user_id,
                    prev_status, task_to_unlock['new_state'])
            task_mapping_issues = ValidatorService.get_task_mapping_issues(
                task_to_unlock)
            task.unlock_task(validated_dto.user_id,
                             task_to_unlock['new_state'],
                             task_to_unlock['comment'],
                             issues=task_mapping_issues)
            dtos.append(
                task.as_dto_with_instructions(validated_dto.preferred_locale))

        task_dtos = TaskDTOs()
        task_dtos.tasks = dtos

        return task_dtos
Exemplo n.º 3
0
    def lock_tasks_for_validation(
            validation_dto: LockForValidationDTO) -> TaskDTOs:
        """
        Lock supplied tasks for validation
        :raises ValidatatorServiceError
        """
        # Loop supplied tasks to check they can all be locked for validation
        tasks_to_lock = []
        for task_id in validation_dto.task_ids:
            task = Task.get(task_id, validation_dto.project_id)

            if task is None:
                raise NotFound(f'Task {task_id} not found')

            if TaskStatus(task.task_status) not in [
                    TaskStatus.MAPPED, TaskStatus.VALIDATED,
                    TaskStatus.BADIMAGERY
            ]:
                raise ValidatatorServiceError(
                    f'Task {task_id} is not MAPPED, BADIMAGERY or VALIDATED')

            if not ValidatorService._user_can_validate_task(
                    validation_dto.user_id, task.mapped_by):
                raise ValidatatorServiceError(
                    f'Tasks cannot be validated by the same user who marked task as mapped or badimagery'
                )

            tasks_to_lock.append(task)

        user_can_validate, error_reason = ProjectService.is_user_permitted_to_validate(
            validation_dto.project_id, validation_dto.user_id)

        if not user_can_validate:
            if error_reason == ValidatingNotAllowed.USER_NOT_ACCEPTED_LICENSE:
                raise UserLicenseError(
                    'User must accept license to map this task')
            else:
                raise ValidatatorServiceError(
                    f'Mapping not allowed because: {error_reason.name}')

        # Lock all tasks for validation
        dtos = []
        for task in tasks_to_lock:
            task.lock_task_for_validating(validation_dto.user_id)
            dtos.append(
                task.as_dto_with_instructions(validation_dto.preferred_locale))

        task_dtos = TaskDTOs()
        task_dtos.tasks = dtos

        return task_dtos
    def get_task_details_for_logged_in_user(project_id: int, user_id: int, preferred_locale: str):
        """ if the user is working on a task in the project return it """
        project = ProjectService.get_project_by_id(project_id)

        tasks = project.get_locked_tasks_details_for_user(user_id)

        if len(tasks) == 0:
            raise NotFound()

        # TODO put the task details in to a DTO
        dtos = []
        for task in tasks:
            dtos.append(task.as_dto_with_instructions(preferred_locale))

        task_dtos = TaskDTOs()
        task_dtos.tasks = dtos

        return task_dtos
    def unlock_tasks_after_validation(
            validated_dto: UnlockAfterValidationDTO) -> TaskDTOs:
        """
        Unlocks supplied tasks after validation
        :raises ValidatatorServiceError
        """
        validated_tasks = validated_dto.validated_tasks
        project_id = validated_dto.project_id
        user_id = validated_dto.user_id
        tasks_to_unlock = ValidatorService.get_tasks_locked_by_user(
            project_id, validated_tasks, user_id)

        # Unlock all tasks
        dtos = []
        for task_to_unlock in tasks_to_unlock:
            task = task_to_unlock['task']

            if task_to_unlock['comment']:
                # Parses comment to see if any users have been @'d
                MessageService.send_message_after_comment(
                    validated_dto.user_id, task_to_unlock['comment'], task.id,
                    validated_dto.project_id)

            if task_to_unlock['new_state'] == TaskStatus.VALIDATED:
                # All mappers get a thankyou if their task has been validated :)
                MessageService.send_message_after_validation(
                    validated_dto.user_id, task.mapped_by, task.id,
                    validated_dto.project_id)

            StatsService.update_stats_after_task_state_change(
                validated_dto.project_id, validated_dto.user_id,
                task_to_unlock['new_state'], task.id)

            task.unlock_task(validated_dto.user_id,
                             task_to_unlock['new_state'],
                             task_to_unlock['comment'])

            dtos.append(task.as_dto())

        task_dtos = TaskDTOs()
        task_dtos.tasks = dtos

        return task_dtos
Exemplo n.º 6
0
    def split_task(split_task_dto: SplitTaskDTO) -> TaskDTOs:
        """
        Replaces a task square with 4 smaller tasks at the next OSM tile grid zoom level
        Validates that task is:
         - locked for mapping by current user
         - splittable (splittable property is True)
        :param split_task_dto:
        :return: new tasks in a DTO
        """
        # get the task to be split
        original_task = Task.get(split_task_dto.task_id,
                                 split_task_dto.project_id)
        if original_task is None:
            raise NotFound()

        # check it's splittable
        if not original_task.splittable:
            raise SplitServiceError('Task is not splittable')

        # check its locked for mapping by the current user
        if TaskStatus(
                original_task.task_status) != TaskStatus.LOCKED_FOR_MAPPING:
            raise SplitServiceError(
                'Status must be LOCKED_FOR_MAPPING to split')

        if original_task.locked_by != split_task_dto.user_id:
            raise SplitServiceError(
                'Attempting to split a task owned by another user')

        # create new geometries from the task geometry
        try:
            new_tasks_geojson = SplitService._create_split_tasks(
                original_task.x, original_task.y, original_task.zoom)
        except Exception as e:
            raise SplitServiceError(f'Error splitting task{str(e)}')

        # create new tasks from the new geojson
        i = Task.get_max_task_id_for_project(split_task_dto.project_id)
        new_tasks_dto = []
        for new_task_geojson in new_tasks_geojson:
            # insert new tasks into database
            i = i + 1
            new_task = Task.from_geojson_feature(i, new_task_geojson)
            new_task.project_id = split_task_dto.project_id
            new_task.task_status = TaskStatus.READY.value
            new_task.create()
            new_task.task_history.extend(original_task.copy_task_history())
            if new_task.task_history:
                new_task.clear_task_lock()  # since we just copied the lock
            new_task.set_task_history(TaskAction.STATE_CHANGE,
                                      split_task_dto.user_id, None,
                                      TaskStatus.SPLIT)
            new_task.set_task_history(TaskAction.STATE_CHANGE,
                                      split_task_dto.user_id, None,
                                      TaskStatus.READY)
            new_task.task_status = TaskStatus.READY.value
            new_task.update()
            new_tasks_dto.append(
                new_task.as_dto_with_instructions(
                    split_task_dto.preferred_locale))

        # delete original task from the database
        original_task.delete()

        # update project task counts
        project = Project.get(split_task_dto.project_id)
        project.total_tasks = project.tasks.count()
        # update bad imagery because we may have split a bad imagery tile
        project.tasks_bad_imagery = project.tasks.filter(
            Task.task_status == TaskStatus.BADIMAGERY.value).count()
        project.save()

        # return the new tasks in a DTO
        task_dtos = TaskDTOs()
        task_dtos.tasks = new_tasks_dto
        return task_dtos