def get_popular_projects() -> ProjectSearchResultsDTO: """ Get all projects ordered by task_history """ rate_func = func.count(TaskHistory.user_id) / extract( "epoch", func.sum(cast(TaskHistory.action_date, Time)) ) query = ( TaskHistory.query.with_entities( TaskHistory.project_id.label("id"), rate_func.label("rate") ) .filter(TaskHistory.action_date >= date.today() - timedelta(days=90)) .filter( or_( TaskHistory.action == TaskAction.LOCKED_FOR_MAPPING.name, TaskHistory.action == TaskAction.LOCKED_FOR_VALIDATION.name, ) ) .filter(TaskHistory.action_text is not None) .filter(TaskHistory.action_text != "") .group_by(TaskHistory.project_id) .order_by(desc("rate")) .limit(10) .subquery() ) projects_query = ProjectSearchService.create_search_query() projects = projects_query.filter(Project.id == query.c.id).all() # Get total contributors. contrib_counts = ProjectSearchService.get_total_contributions(projects) zip_items = zip(projects, contrib_counts) dto = ProjectSearchResultsDTO() dto.results = [ ProjectSearchService.create_result_dto(p, "en", t) for p, t in zip_items ] return dto
def test_get_area_from_3857_bbox(self): # polygon = ProjectSearchService._make_4326_polygon_from_bbox( # [3618104.193026841, -1413969.7644834695, 3861479.691086842, -1297785.4814900015], 3857) polygon = Polygon([ (34.68826225820438, -12.59912449955007), (34.68826225820438, -11.57858317689196), (32.50198296132938, -11.57858317689196), (32.50198296132938, -12.59912449955007), (34.68826225820438, -12.59912449955007), ]) # act expected = ProjectSearchService._get_area_sqm(polygon) # assert self.assertAlmostEqual(expected, 28276407740.2797, places=3)
def test_make_polygon_from_3857_bbox(self): # arrange expected = ( 32.50198296132938, -12.59912449955007, 34.68826225820438, -11.578583176891955, ) # act polygon = ProjectSearchService._make_4326_polygon_from_bbox( [ 3618104.193026841, -1413969.7644834695, 3861479.691086842, -1297785.4814900015, ], 3857, ) # assert for expected_val, actual_val in zip(expected, polygon.bounds): self.assertAlmostEqual(expected_val, actual_val, places=10)
def get_projects_for_admin(admin_id: int, preferred_locale: str, search_dto: ProjectSearchDTO): """ Get all projects for provided admin """ ProjectSearchService.create_search_query() return Project.get_projects_for_admin(admin_id, preferred_locale, search_dto)
def get(self): """ List and search projects by bounding box --- tags: - projects produces: - application/json parameters: - in: header name: Authorization description: Base64 encoded session token required: true type: string default: Token sessionTokenHere== - in: header name: Accept-Language description: Language user is requesting type: string default: en - in: query name: bbox description: comma separated list xmin, ymin, xmax, ymax type: string required: true default: 34.404,-1.034, 34.717,-0.624 - in: query name: srid description: srid of bbox coords type: integer default: 4326 - in: query name: createdByMe description: limit to projects created by authenticated user type: boolean required: true default: false responses: 200: description: ok 400: description: Client Error - Invalid Request 403: description: Forbidden 500: description: Internal Server Error """ try: authenticated_user_id = token_auth.current_user() orgs_dto = OrganisationService.get_organisations_managed_by_user_as_dto( authenticated_user_id ) if len(orgs_dto.organisations) < 1: raise ValueError("User not a project manager") except ValueError as e: error_msg = f"ProjectsQueriesBboxAPI GET: {str(e)}" return {"Error": error_msg}, 403 try: search_dto = ProjectSearchBBoxDTO() search_dto.bbox = map(float, request.args.get("bbox").split(",")) search_dto.input_srid = request.args.get("srid") search_dto.preferred_locale = request.environ.get("HTTP_ACCEPT_LANGUAGE") created_by_me = ( strtobool(request.args.get("createdByMe")) if request.args.get("createdByMe") else False ) if created_by_me: search_dto.project_author = authenticated_user_id search_dto.validate() except Exception as e: current_app.logger.error(f"Error validating request: {str(e)}") return {"Error": "Unable to fetch projects"}, 400 try: geojson = ProjectSearchService.get_projects_geojson(search_dto) return geojson, 200 except BBoxTooBigError: return {"Error": "Bounding Box too large"}, 403 except ProjectSearchServiceError: return {"Error": "Unable to fetch projects"}, 400 except Exception as e: error_msg = f"ProjectsQueriesBboxAPI GET - unhandled error: {str(e)}" current_app.logger.critical(error_msg) return {"Error": "Unable to fetch projects"}, 500
def get(self): """ List and search for projects --- tags: - projects produces: - application/json parameters: - in: header name: Authorization description: Base64 encoded session token type: string default: Token sessionTokenHere== - in: header name: Accept-Language description: Language user is requesting type: string required: true default: en - in: query name: mapperLevel type: string - in: query name: orderBy type: string default: priority enum: [id,mapper_level,priority,status,last_updated,due_date] - in: query name: orderByType type: string default: ASC enum: [ASC, DESC] - in: query name: mappingTypes type: string - in: query name: mappingTypesExact type: boolean default: false description: if true, limits projects to match the exact mapping types requested - in: query name: organisationName description: Organisation name to search for type: string - in: query name: organisationId description: Organisation ID to search for type: integer - in: query name: campaign description: Campaign name to search for type: string - in: query name: page description: Page of results user requested type: integer default: 1 - in: query name: textSearch description: Text to search type: string - in: query name: country description: Project country type: string - in: query name: action description: Filter projects by possible actions enum: [map, validate, any] type: string - in: query name: projectStatuses description: Authenticated PMs can search for archived or draft statuses type: string - in: query name: interests type: string description: Filter by interest on project default: null - in: query name: createdByMe description: Limit to projects created by the authenticated user type: boolean default: false - in: query name: mappedByMe description: Limit to projects mapped/validated by the authenticated user type: boolean default: false - in: query name: favoritedByMe description: Limit to projects favorited by the authenticated user type: boolean default: false - in: query name: managedByMe description: Limit to projects that can be managed by the authenticated user, excluding the ones created by them type: boolean default: false - in: query name: teamId type: string description: Filter by team on project default: null name: omitMapResults type: boolean description: If true, it will not return the project centroid's geometries. default: false responses: 200: description: Projects found 404: description: No projects found 500: description: Internal Server Error """ try: user = None user_id = token_auth.current_user() if user_id: user = UserService.get_user_by_id(user_id) search_dto = self.setup_search_dto() results_dto = ProjectSearchService.search_projects(search_dto, user) return results_dto.to_primitive(), 200 except NotFound: return {"mapResults": {}, "results": []}, 200 except Exception as e: error_msg = f"Project GET - unhandled error: {str(e)}" current_app.logger.critical(error_msg) return {"Error": "Unable to fetch projects"}, 500