Skip to content

Commit 08c7a19

Browse files
committed
Изменены поля в табилце excel при Выгрузцке оценок программ
1 parent 95b9b37 commit 08c7a19

1 file changed

Lines changed: 96 additions & 32 deletions

File tree

partner_programs/admin.py

Lines changed: 96 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import tablib
55
from django import forms
66
from django.contrib import admin
7-
from django.db.models import QuerySet
7+
from django.db.models import Prefetch, QuerySet
88
from django.http import HttpRequest, HttpResponse
99
from django.urls import path
1010
from django.utils import timezone
@@ -19,9 +19,7 @@
1919
PartnerProgramProject,
2020
PartnerProgramUserProfile,
2121
)
22-
from partner_programs.services import ProjectScoreDataPreparer
2322
from project_rates.models import Criteria, ProjectScore
24-
from projects.models import Project
2523

2624

2725
class PartnerProgramMaterialInline(admin.StackedInline):
@@ -247,46 +245,112 @@ def get_export_rates_view(self, request, object_id):
247245

248246
def _get_prepared_rates_data_for_export(self, program_id: int) -> list[dict]:
249247
"""
250-
Prepares info (list if dicts) for export about prjects_rates by experts.
251-
Columns example:
252-
ФИО|Email|Регион_РФ|Учебное_заведение|Название_учебного_заведения|Класс_курс|Фамилия эксперта|**criteria
248+
Готовит данные для выгрузки оценок проектов.
249+
Порядок колонок: название проекта → фамилия эксперта → доп. поля программы →
250+
критерии → комментарий.
251+
Если у проекта несколько экспертов, на каждый проект-эксперт создаётся отдельная строка.
253252
"""
254-
criterias = Criteria.objects.filter(
255-
partner_program__id=program_id
256-
).select_related("partner_program")
253+
criterias = list(
254+
Criteria.objects.filter(partner_program__id=program_id)
255+
.select_related("partner_program")
256+
.order_by("id")
257+
)
258+
if not criterias:
259+
return []
260+
261+
comment_criteria = next(
262+
(criteria for criteria in criterias if criteria.name == "Комментарий"),
263+
None,
264+
)
265+
criterias_without_comment = [
266+
criteria for criteria in criterias if criteria != comment_criteria
267+
]
268+
269+
program_fields = list(
270+
PartnerProgramField.objects.filter(partner_program_id=program_id).order_by(
271+
"id"
272+
)
273+
)
274+
257275
scores = (
258276
ProjectScore.objects.filter(criteria__in=criterias)
259277
.select_related("user", "criteria", "project")
260-
.order_by("project", "criteria")
261-
)
262-
user_programm_profiles = PartnerProgramUserProfile.objects.filter(
263-
partner_program__id=program_id
264-
).select_related("user")
265-
projects = (
266-
Project.objects.filter(scores__in=scores)
267-
.select_related("leader")
268-
.distinct()
278+
.order_by("project_id", "criteria_id", "id")
269279
)
270-
271-
# To reduce the number of DB requests.
272-
user_profiles_dict: dict[int, PartnerProgramUserProfile] = {
273-
profile.project_id: profile for profile in user_programm_profiles
274-
}
275280
scores_dict: dict[int, list[ProjectScore]] = {}
276281
for score in scores:
277282
scores_dict.setdefault(score.project_id, []).append(score)
278283

284+
if not scores_dict:
285+
return []
286+
287+
project_ids = list(scores_dict.keys())
288+
289+
field_values_prefetch = Prefetch(
290+
"field_values",
291+
queryset=PartnerProgramFieldValue.objects.select_related("field").filter(
292+
program_project__partner_program_id=program_id,
293+
program_project__project_id__in=project_ids,
294+
),
295+
to_attr="_prefetched_field_values",
296+
)
297+
program_projects = (
298+
PartnerProgramProject.objects.filter(
299+
partner_program_id=program_id, project_id__in=project_ids
300+
)
301+
.select_related("project")
302+
.prefetch_related(field_values_prefetch)
303+
)
304+
program_project_by_project_id: dict[int, PartnerProgramProject] = {
305+
link.project_id: link for link in program_projects
306+
}
307+
279308
prepared_projects_rates_data: list[dict] = []
280-
for project in projects:
281-
project_data_preparer = ProjectScoreDataPreparer(
282-
user_profiles_dict, scores_dict, project.id, program_id
309+
for project_id, project_scores in scores_dict.items():
310+
project_link = program_project_by_project_id.get(project_id)
311+
project = (
312+
project_link.project
313+
if project_link
314+
else (project_scores[0].project if project_scores else None)
283315
)
284-
full_project_rates_data: dict = {
285-
**project_data_preparer.get_project_user_info(),
286-
**project_data_preparer.get_project_expert_info(),
287-
**project_data_preparer.get_project_scores_info(),
288-
}
289-
prepared_projects_rates_data.append(full_project_rates_data)
316+
317+
field_values_map: dict[int, str] = {}
318+
field_values = (
319+
getattr(project_link, "_prefetched_field_values", None)
320+
if project_link
321+
else None
322+
)
323+
if field_values:
324+
for field_value in field_values:
325+
field_values_map[field_value.field_id] = field_value.get_value()
326+
327+
scores_by_expert: dict[int, list[ProjectScore]] = {}
328+
for score in project_scores:
329+
scores_by_expert.setdefault(score.user_id, []).append(score)
330+
331+
for _, expert_scores in scores_by_expert.items():
332+
row_data: dict[str, str] = {}
333+
row_data["Название проекта"] = (
334+
getattr(project, "name", "") if project else ""
335+
)
336+
row_data["Фамилия эксперта"] = (
337+
expert_scores[0].user.last_name if expert_scores else ""
338+
)
339+
340+
for field in program_fields:
341+
row_data[field.label] = field_values_map.get(field.id, "")
342+
343+
scores_map: dict[int, str] = {
344+
score.criteria_id: score.value for score in expert_scores
345+
}
346+
347+
for criteria in criterias_without_comment:
348+
row_data[criteria.name] = scores_map.get(criteria.id, "")
349+
350+
if comment_criteria:
351+
row_data["Комментарий"] = scores_map.get(comment_criteria.id, "")
352+
353+
prepared_projects_rates_data.append(row_data)
290354

291355
return prepared_projects_rates_data
292356

0 commit comments

Comments
 (0)