99from core .utils import build_xlsx_download_response , sanitize_excel_value
1010from courses .models import (
1111 Course ,
12+ CourseLesson ,
1213 CourseLessonContentStatus ,
1314 CourseModuleContentStatus ,
1415 CourseTask ,
@@ -105,6 +106,24 @@ def _lesson_progresses_by_user(user_ids: list[int], course: Course) -> dict[int,
105106 return progress_map
106107
107108
109+ def _published_lessons_with_tasks (course : Course ) -> list [CourseLesson ]:
110+ published_tasks_qs = CourseTask .objects .filter (
111+ status = CourseTaskContentStatus .PUBLISHED ,
112+ ).order_by ("order" , "id" )
113+ return list (
114+ CourseLesson .objects .filter (
115+ module__course = course ,
116+ module__status = CourseModuleContentStatus .PUBLISHED ,
117+ status = CourseLessonContentStatus .PUBLISHED ,
118+ )
119+ .select_related ("module" )
120+ .prefetch_related (
121+ Prefetch ("tasks" , queryset = published_tasks_qs , to_attr = "_published_tasks" )
122+ )
123+ .order_by ("module__order" , "module__id" , "order" , "id" )
124+ )
125+
126+
108127def _answers_by_user_and_task (
109128 user_ids : list [int ],
110129 task_ids : list [int ],
@@ -143,34 +162,55 @@ def _task_header(task: CourseTask) -> str:
143162 )
144163
145164
165+ def _lesson_stage_header (lesson : CourseLesson ) -> str :
166+ return (
167+ f"Модуль { lesson .module .order } : { lesson .module .title } / "
168+ f"Урок { lesson .order } : { lesson .title } "
169+ )
170+
171+
146172def _format_stage (
147173 course_progress : UserCourseProgress ,
148174 lesson_progresses : list [UserLessonProgress ],
175+ published_lessons : list [CourseLesson ],
149176) -> str :
150177 if course_progress .status == ProgressStatus .COMPLETED :
151178 return "Курс завершён"
152179
180+ lesson_progress_by_lesson_id = {
181+ progress .lesson_id : progress for progress in lesson_progresses
182+ }
183+
153184 current_progress = next (
154- (progress for progress in lesson_progresses if progress .current_task_id ),
185+ (
186+ progress
187+ for progress in lesson_progresses
188+ if progress .current_task_id
189+ and progress .current_task is not None
190+ and progress .current_task .status == CourseTaskContentStatus .PUBLISHED
191+ ),
155192 None ,
156193 )
157194 if current_progress is not None :
158195 current_task = current_progress .current_task
159- return (
160- f"Модуль { current_progress .lesson .module .order } : { current_progress .lesson .module .title } / "
161- f"Урок { current_progress .lesson .order } : { current_progress .lesson .title } / "
162- f"Задание { current_task .order } : { current_task .title } "
163- )
196+ return _task_header (current_task )
164197
165198 in_progress_lesson = next (
166199 (progress for progress in lesson_progresses if progress .status == ProgressStatus .IN_PROGRESS ),
167200 None ,
168201 )
169202 if in_progress_lesson is not None :
170- return (
171- f"Модуль { in_progress_lesson .lesson .module .order } : { in_progress_lesson .lesson .module .title } / "
172- f"Урок { in_progress_lesson .lesson .order } : { in_progress_lesson .lesson .title } "
173- )
203+ return _lesson_stage_header (in_progress_lesson .lesson )
204+
205+ for lesson in published_lessons :
206+ lesson_progress = lesson_progress_by_lesson_id .get (lesson .id )
207+ if lesson_progress and lesson_progress .status == ProgressStatus .COMPLETED :
208+ continue
209+
210+ published_tasks = getattr (lesson , "_published_tasks" , [])
211+ if published_tasks :
212+ return _task_header (published_tasks [0 ])
213+ return _lesson_stage_header (lesson )
174214
175215 return "Этап не определён"
176216
@@ -204,6 +244,7 @@ def _build_headers(tasks: list[CourseTask]) -> list[str]:
204244
205245def build_course_results_workbook_bytes (course : Course ) -> bytes :
206246 tasks = _export_tasks (course )
247+ published_lessons = _published_lessons_with_tasks (course )
207248 course_progresses = _started_course_progresses (course )
208249 user_ids = [progress .user_id for progress in course_progresses ]
209250 task_ids = [task .id for task in tasks ]
@@ -223,7 +264,7 @@ def build_course_results_workbook_bytes(course: Course) -> bytes:
223264 course_progress .percent ,
224265 _format_msk_datetime (course_progress .started_at ),
225266 course .title ,
226- _format_stage (course_progress , lesson_progresses ),
267+ _format_stage (course_progress , lesson_progresses , published_lessons ),
227268 ]
228269 for task in tasks :
229270 row .append (
0 commit comments