def search_projects(
            search_dto: ProjectSearchDTO) -> ProjectSearchResultsDTO:
        """ Searches all projects for matches to the criteria provided by the user """

        all_results, paginated_results = ProjectSearchService._filter_projects(
            search_dto)

        if paginated_results.total == 0:
            raise NotFound()

        features = []
        for project in all_results:
            # This loop creates a geojson feature collection so you can see all active projects on the map
            properties = {
                "projectId": project.id,
                "priority": ProjectPriority(project.priority).name
            }
            centroid = project.centroid
            feature = geojson.Feature(geometry=geojson.loads(project.centroid),
                                      properties=properties)
            features.append(feature)
        feature_collection = geojson.FeatureCollection(features)
        dto = ProjectSearchResultsDTO()
        dto.map_results = feature_collection

        for project in paginated_results.items:
            # This loop loads the paginated text results
            # TODO would be nice to get this for an array rather than individually would be more efficient
            project_info_dto = ProjectInfo.get_dto_for_locale(
                project.id, search_dto.preferred_locale,
                project.default_locale)

            list_dto = ListSearchResultDTO()
            list_dto.project_id = project.id
            list_dto.locale = project_info_dto.locale
            list_dto.name = project_info_dto.name
            list_dto.priority = ProjectPriority(project.priority).name
            list_dto.mapper_level = MappingLevel(project.mapper_level).name
            list_dto.short_description = project_info_dto.short_description
            list_dto.organisation_tag = project.organisation_tag
            list_dto.campaign_tag = project.campaign_tag
            list_dto.percent_mapped = Project.calculate_tasks_percent(
                'mapped', project.total_tasks, project.tasks_mapped,
                project.tasks_validated, project.tasks_bad_imagery)
            list_dto.percent_validated = Project.calculate_tasks_percent(
                'validated', project.total_tasks, project.tasks_mapped,
                project.tasks_validated, project.tasks_bad_imagery)
            list_dto.status = ProjectStatus(project.status).name
            list_dto.active_mappers = Project.get_active_mappers(project.id)

            dto.results.append(list_dto)

        dto.pagination = Pagination(paginated_results)
        return dto
Пример #2
0
    def test_get_intersecting_projects(self, get_dto_for_locale,
                                       _get_intersecting_projects,
                                       get_user_by_username,
                                       validate_bbox_area,
                                       _make_4326_polygon_from_bbox):
        if self.skip_tests:
            return

        # arrange _make_4326_polygon_from_bbox mock
        _make_4326_polygon_from_bbox.return_value = Polygon([
            (34.68826225820438, -12.59912449955007),
            (34.68826225820438, -11.57858317689196),
            (32.50198296132938, -11.57858317689196),
            (32.50198296132938, -12.59912449955007),
            (34.68826225820438, -12.59912449955007)
        ])

        # arrange validate_bbox_area mock
        validate_bbox_area.return_value = True

        # arrange get_user_by_username mock
        get_user_by_username.return_value = User(id=3488526)

        # arrange _get_intersecting_projects mock
        polygon = json.dumps(get_canned_json('search_bbox_feature.json'))
        project = Project(id=2274,
                          status=0,
                          default_locale='en',
                          geometry=polygon)
        projects = [project]
        _get_intersecting_projects.return_value = projects

        # arrange get_dto_for_locale mock
        get_dto_for_locale.return_value = ProjectInfo(
            name='PEPFAR Kenya: Homa Bay')

        # arrange dto
        dto = ProjectSearchBBoxDTO()
        dto.bbox = map(float, '34.404,-1.034, 34.717,-0.624'.split(','))
        dto.preferred_locale = 'en'
        dto.input_srid = 4326
        dto.project_author = 3488526
        dto.validate()

        # arrange expected result
        expected = json.dumps(get_canned_json('search_bbox_result.json'))

        # act
        result = ProjectSearchService.get_projects_geojson(dto)

        # assert
        self.assertEqual(str(expected), str(expected))
    def get_projects_geojson(
            search_bbox_dto: ProjectSearchBBoxDTO
    ) -> geojson.FeatureCollection:
        """  search for projects meeting criteria provided return as a geojson feature collection"""

        # make a polygon from provided bounding box
        polygon = ProjectSearchService._make_4326_polygon_from_bbox(
            search_bbox_dto.bbox, search_bbox_dto.input_srid)

        # validate the bbox area is less than or equal to the max area allowed to prevent
        # abuse of the api or performance issues from large requests
        if not ProjectSearchService.validate_bbox_area(polygon):
            raise BBoxTooBigError('Requested bounding box is too large')

        # get projects intersecting the polygon for created by the author_id
        intersecting_projects = ProjectSearchService._get_intersecting_projects(
            polygon, search_bbox_dto.project_author)

        # allow an empty feature collection to be returned if no intersecting features found, since this is primarily
        # for returning data to show on a map
        features = []
        for project in intersecting_projects:
            try:
                localDTO = ProjectInfo.get_dto_for_locale(
                    project.id, search_bbox_dto.preferred_locale,
                    project.default_locale)
            except Exception as e:
                pass

            properties = {
                "projectId": project.id,
                "projectStatus": ProjectStatus(project.status).name,
                "projectName": localDTO.name
            }
            feature = geojson.Feature(geometry=geojson.loads(project.geometry),
                                      properties=properties)
            features.append(feature)

        return geojson.FeatureCollection(features)
Пример #4
0
    def search_projects(
            search_dto: ProjectSearchDTO) -> ProjectSearchResultsDTO:
        """ Searches all projects for matches to the criteria provided by the user """

        filtered_projects = ProjectSearchService._filter_projects(search_dto)

        if filtered_projects.total == 0:
            raise NotFound()

        dto = ProjectSearchResultsDTO()
        for project in filtered_projects.items:
            # TODO would be nice to get this for an array rather than individually would be more efficient
            project_info_dto = ProjectInfo.get_dto_for_locale(
                project.id, search_dto.preferred_locale,
                project.default_locale)

            result_dto = ProjectSearchResultDTO()
            result_dto.project_id = project.id
            result_dto.locale = project_info_dto.locale
            result_dto.name = project_info_dto.name
            result_dto.priority = ProjectPriority(project.priority).name
            result_dto.mapper_level = MappingLevel(project.mapper_level).name
            result_dto.short_description = project_info_dto.short_description
            result_dto.aoi_centroid = geojson.loads(project.centroid)
            result_dto.organisation_tag = project.organisation_tag
            result_dto.campaign_tag = project.campaign_tag
            result_dto.percent_mapped = round(
                (project.tasks_mapped /
                 (project.total_tasks - project.tasks_bad_imagery)) * 100, 0)
            result_dto.percent_validated = round(
                ((project.tasks_validated + project.tasks_bad_imagery) /
                 project.total_tasks) * 100, 0)

            dto.results.append(result_dto)

        dto.pagination = Pagination(filtered_projects)
        return dto