def create_result_dto(project, preferred_locale, total_contributors):
        project_info_dto = ProjectInfo.get_dto_for_locale(
            project.id, 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.last_updated = project.last_updated
        list_dto.due_date = project.due_date
        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)
        list_dto.total_contributors = total_contributors
        list_dto.country = project.country
        list_dto.organisation_name = project.organisation_name
        list_dto.organisation_logo = project.organisation_logo
        list_dto.campaigns = Project.get_project_campaigns(project.id)

        return list_dto
    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:
                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)