Skip to content

Commit

Permalink
Remplement download CSV in a more optimal way
Browse files Browse the repository at this point in the history
  • Loading branch information
bshankar committed Sep 30, 2024
1 parent 0768c6d commit f43feab
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 37 deletions.
4 changes: 2 additions & 2 deletions backend/models/postgis/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,13 @@ class Project(db.Model):
def percent_mapped(self):
return (
(self.tasks_mapped + self.tasks_validated)
/ (self.total_tasks - self.tasks_bad_imagery)
* 100
// (self.total_tasks - self.tasks_bad_imagery)
)

@hybrid_property
def percent_validated(self):
return self.tasks_validated / (self.total_tasks - self.tasks_bad_imagery) * 100
return self.tasks_validated * 100 // (self.total_tasks - self.tasks_bad_imagery)

# Mapped Objects
tasks = db.relationship(
Expand Down
84 changes: 49 additions & 35 deletions backend/services/project_search_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def create_search_query(user=None):
query = (
db.session.query(
Project.id.label("id"),
ProjectInfo.name.label("project_name"),
Project.difficulty,
Project.priority,
Project.default_locale,
Expand All @@ -81,17 +82,23 @@ def create_search_query(user=None):
Project.tasks_bad_imagery,
Project.tasks_mapped,
Project.tasks_validated,
Project.percent_mapped,
Project.percent_validated,
Project.status,
Project.total_tasks,
Project.last_updated,
Project.due_date,
Project.country,
Organisation.name.label("organisation_name"),
Organisation.logo.label("organisation_logo"),
Project.created.label("creation_date"),
func.coalesce(
func.sum(func.ST_Area(Project.geometry, True) / 1000000)
).label("total_area"),
)
.filter(Project.geometry is not None)
.outerjoin(Organisation, Organisation.id == Project.organisation_id)
.group_by(Organisation.id, Project.id)
.group_by(Organisation.id, Project.id, ProjectInfo.name)
)

# Get public projects only for anonymous user.
Expand Down Expand Up @@ -203,52 +210,59 @@ def get_total_contributions(paginated_results):
@cached(csv_download_cache)
def search_projects_as_csv(search_dto: ProjectSearchDTO, user) -> str:
all_results, _ = ProjectSearchService._filter_projects(search_dto, user)
rows = [row._asdict() for row in all_results]
is_user_admin = user is not None and user.role == UserRole.ADMIN.value

project_ids = [p.id for p in all_results]
contributors_by_project_id = (
TaskHistory.query.with_entities(
TaskHistory.project_id, func.count(TaskHistory.user_id.distinct())
)
.filter(
TaskHistory.project_id.in_(project_ids), TaskHistory.action != "COMMENT"
)
.group_by(TaskHistory.project_id)
.all()
)

results_as_dto = [
ProjectSearchService.create_result_dto(
project,
search_dto.preferred_locale,
next(
filter(
lambda c, p=project: c[0] == p.id,
contributors_by_project_id,
for row in rows:
row["priority"] = ProjectPriority(row["priority"]).name
row["difficulty"] = ProjectDifficulty(row["difficulty"]).name
row["status"] = ProjectStatus(row["status"]).name
row["total_area"] = round(row["total_area"], 3)
row["total_contributors"] = Project.get_project_total_contributions(row["id"])

if is_user_admin:
partners_names = (
ProjectPartnership.query.with_entities(
ProjectPartnership.project_id, Partner.name
)
)[1],
with_partner_names=is_user_admin,
with_author_name=False,
).to_primitive()
for project in all_results
]
.join(Partner, ProjectPartnership.partner_id == Partner.id)
.filter(ProjectPartnership.project_id == row["id"])
.group_by(ProjectPartnership.project_id, Partner.name)
.all()
)
row["partner_names"] = [pn for (_, pn) in partners_names]

df = pd.json_normalize(results_as_dto)
df = pd.json_normalize(rows)
columns_to_drop = [
"locale",
"shortDescription",
"organisationLogo",
"campaigns",
"default_locale",
"organisation_id",
"organisation_logo",
"tasks_bad_imagery",
"tasks_mapped",
"tasks_validated",
"total_tasks",
"centroid",
]
if not is_user_admin:
columns_to_drop.append("partnerNames")

colummns_to_rename = {
"id": "projectId",
"organisation_name": "organisationName",
"last_updated": "lastUpdated",
"due_date": "dueDate",
"percent_mapped": "percentMapped",
"percent_validated": "percentValidated",
"total_area": "totalArea",
"total_contributors": "totalContributors",
"partner_names": "partnerNames",
"project_name": "name",
}

df.drop(
columns=columns_to_drop,
inplace=True,
axis=1,
)

df.rename(columns=colummns_to_rename, inplace=True)
return df.to_csv(index=False)

@staticmethod
Expand Down

0 comments on commit f43feab

Please sign in to comment.