diff --git a/apps/api/src/services/courses/chapters.py b/apps/api/src/services/courses/chapters.py index 5bc3e9bb..97afcf92 100644 --- a/apps/api/src/services/courses/chapters.py +++ b/apps/api/src/services/courses/chapters.py @@ -366,182 +366,97 @@ async def reorder_chapters_and_activities( # Chapters ########### - # Delete CourseChapters that are not linked to chapter_id and activity_id and org_id and course_id - statement = ( - select(CourseChapter) - .where( - CourseChapter.course_id == course.id, CourseChapter.org_id == course.org_id - ) - .order_by(CourseChapter.order) + # Get all existing course chapters + statement = select(CourseChapter).where( + CourseChapter.course_id == course.id, + CourseChapter.org_id == course.org_id ) - course_chapters = db_session.exec(statement).all() + existing_course_chapters = db_session.exec(statement).all() - chapter_ids_to_keep = [ - chapter_order.chapter_id - for chapter_order in chapters_order.chapter_order_by_ids - ] - for course_chapter in course_chapters: - if course_chapter.chapter_id not in chapter_ids_to_keep: - db_session.delete(course_chapter) - db_session.commit() + # Create a map of existing chapters for faster lookup + existing_chapter_map = {cc.chapter_id: cc for cc in existing_course_chapters} - # Delete Chapters that are not in the list of chapters_order - statement = select(Chapter).where(Chapter.course_id == course.id) - chapters = db_session.exec(statement).all() - - chapter_ids_to_keep = [ - chapter_order.chapter_id - for chapter_order in chapters_order.chapter_order_by_ids - ] - - for chapter in chapters: - if chapter.id not in chapter_ids_to_keep: - db_session.delete(chapter) - db_session.commit() - - # If links do not exists, create them - for chapter_order in chapters_order.chapter_order_by_ids: - statement = ( - select(CourseChapter) - .where( - CourseChapter.chapter_id == chapter_order.chapter_id, - CourseChapter.course_id == course.id, - ) - .order_by(CourseChapter.order) - ) - course_chapter = db_session.exec(statement).first() - - if not course_chapter: - # Add CourseChapter link + # Update or create course chapters based on new order + for index, chapter_order in enumerate(chapters_order.chapter_order_by_ids): + if chapter_order.chapter_id in existing_chapter_map: + # Update existing chapter order + course_chapter = existing_chapter_map[chapter_order.chapter_id] + course_chapter.order = index + db_session.add(course_chapter) + else: + # Create new course chapter course_chapter = CourseChapter( chapter_id=chapter_order.chapter_id, - course_id=course.id, # type: ignore + course_id=course.id, # type: ignore org_id=course.org_id, creation_date=str(datetime.now()), update_date=str(datetime.now()), - order=chapter_order.chapter_id, + order=index, ) - - # Insert CourseChapter link in DB db_session.add(course_chapter) - db_session.commit() + + db_session.commit() - # Update order of chapters - for chapter_order in chapters_order.chapter_order_by_ids: - statement = ( - select(CourseChapter) - .where( - CourseChapter.chapter_id == chapter_order.chapter_id, - CourseChapter.course_id == course.id, - ) - .order_by(CourseChapter.order) - ) - course_chapter = db_session.exec(statement).first() - - if course_chapter: - # Get the order from the index of the chapter_order_by_ids list - course_chapter.order = chapters_order.chapter_order_by_ids.index( - chapter_order - ) - db_session.commit() + # Remove chapters that are no longer in the order + chapter_ids_to_keep = {co.chapter_id for co in chapters_order.chapter_order_by_ids} + for cc in existing_course_chapters: + if cc.chapter_id not in chapter_ids_to_keep: + db_session.delete(cc) + db_session.commit() ########### # Activities ########### - # Delete ChapterActivities that are no longer part of the new order - statement = ( - select(ChapterActivity) - .where( - ChapterActivity.course_id == course.id, - ChapterActivity.org_id == course.org_id, - ) - .order_by(ChapterActivity.order) + # Get all existing chapter activities + statement = select(ChapterActivity).where( + ChapterActivity.course_id == course.id, + ChapterActivity.org_id == course.org_id ) - chapter_activities = db_session.exec(statement).all() + existing_chapter_activities = db_session.exec(statement).all() - activity_ids_to_delete = [] - for chapter_activity in chapter_activities: - if ( - chapter_activity.chapter_id not in chapter_ids_to_keep - or chapter_activity.activity_id not in activity_ids_to_delete - ): - activity_ids_to_delete.append(chapter_activity.activity_id) + # Create a map for faster lookup + existing_activity_map = { + (ca.chapter_id, ca.activity_id): ca + for ca in existing_chapter_activities + } - for activity_id in activity_ids_to_delete: - statement = ( - select(ChapterActivity) - .where( - ChapterActivity.activity_id == activity_id, - ChapterActivity.course_id == course.id, - ) - .order_by(ChapterActivity.order) - ) - chapter_activity = db_session.exec(statement).first() + # Track which activities we want to keep + activities_to_keep = set() - db_session.delete(chapter_activity) - db_session.commit() - - # If links do not exist, create them - chapter_activity_map = {} + # Update or create chapter activities based on new order for chapter_order in chapters_order.chapter_order_by_ids: - for activity_order in chapter_order.activities_order_by_ids: - if ( - activity_order.activity_id in chapter_activity_map - and chapter_activity_map[activity_order.activity_id] - != chapter_order.chapter_id - ): - continue + for index, activity_order in enumerate(chapter_order.activities_order_by_ids): + activity_key = (chapter_order.chapter_id, activity_order.activity_id) + activities_to_keep.add(activity_key) - statement = ( - select(ChapterActivity) - .where( - ChapterActivity.chapter_id == chapter_order.chapter_id, - ChapterActivity.activity_id == activity_order.activity_id, - ) - .order_by(ChapterActivity.order) - ) - chapter_activity = db_session.exec(statement).first() - - if not chapter_activity: - # Add ChapterActivity link + if activity_key in existing_activity_map: + # Update existing activity order + chapter_activity = existing_activity_map[activity_key] + chapter_activity.order = index + db_session.add(chapter_activity) + else: + # Create new chapter activity chapter_activity = ChapterActivity( chapter_id=chapter_order.chapter_id, activity_id=activity_order.activity_id, org_id=course.org_id, - course_id=course.id, # type: ignore + course_id=course.id, # type: ignore creation_date=str(datetime.now()), update_date=str(datetime.now()), - order=activity_order.activity_id, + order=index, ) - - # Insert ChapterActivity link in DB db_session.add(chapter_activity) - db_session.commit() + + db_session.commit() - chapter_activity_map[activity_order.activity_id] = chapter_order.chapter_id + # Remove activities that are no longer in any chapter + for ca in existing_chapter_activities: + if (ca.chapter_id, ca.activity_id) not in activities_to_keep: + db_session.delete(ca) + db_session.commit() - # Update order of activities - for chapter_order in chapters_order.chapter_order_by_ids: - for activity_order in chapter_order.activities_order_by_ids: - statement = ( - select(ChapterActivity) - .where( - ChapterActivity.chapter_id == chapter_order.chapter_id, - ChapterActivity.activity_id == activity_order.activity_id, - ) - .order_by(ChapterActivity.order) - ) - chapter_activity = db_session.exec(statement).first() - - if chapter_activity: - # Get the order from the index of the chapter_order_by_ids list - chapter_activity.order = chapter_order.activities_order_by_ids.index( - activity_order - ) - db_session.commit() - - return {"detail": "Chapters reordered"} + return {"detail": "Chapters and activities reordered successfully"} ## 🔒 RBAC Utils ##