package repository import ( "context" "fmt" dbgen "Yimaru-Backend/gen/db" ) // CompleteLessonForUser records lesson completion and cascades to module, course, and program when the user // has fully completed the preceding scope. Runs in a single transaction. func (s *Store) CompleteLessonForUser(ctx context.Context, userID, lessonID int64) error { q, tx, err := s.BeginTx(ctx) if err != nil { return fmt.Errorf("begin tx: %w", err) } defer func() { _ = tx.Rollback(ctx) }() if err := q.InsertUserLessonProgress(ctx, dbgen.InsertUserLessonProgressParams{UserID: userID, LessonID: lessonID}); err != nil { return err } lesson, err := q.GetLessonByID(ctx, lessonID) if err != nil { return err } mod, err := q.GetModuleByID(ctx, lesson.ModuleID) if err != nil { return err } crs, err := q.GetCourseByID(ctx, mod.CourseID) if err != nil { return err } nLess, err := q.CountLessonsInModule(ctx, lesson.ModuleID) if err != nil { return err } nDoneLess, err := q.CountUserCompletedLessonsInModule(ctx, dbgen.CountUserCompletedLessonsInModuleParams{ ModuleID: lesson.ModuleID, UserID: userID, }) if err != nil { return err } if nLess > 0 && nDoneLess >= nLess { if err := q.InsertUserModuleProgress(ctx, dbgen.InsertUserModuleProgressParams{UserID: userID, ModuleID: mod.ID}); err != nil { return err } nMods, err := q.CountModulesInCourse(ctx, mod.CourseID) if err != nil { return err } nDoneMods, err := q.CountUserCompletedModulesInCourse(ctx, dbgen.CountUserCompletedModulesInCourseParams{ CourseID: mod.CourseID, UserID: userID, }) if err != nil { return err } if nMods > 0 && nDoneMods >= nMods { if err := q.InsertUserCourseProgress(ctx, dbgen.InsertUserCourseProgressParams{UserID: userID, CourseID: crs.ID}); err != nil { return err } nCr, err := q.CountCoursesInProgram(ctx, crs.ProgramID) if err != nil { return err } nCrDone, err := q.CountUserCompletedCoursesInProgram(ctx, dbgen.CountUserCompletedCoursesInProgramParams{ ProgramID: crs.ProgramID, UserID: userID, }) if err != nil { return err } if nCr > 0 && nCrDone >= nCr { if err := q.InsertUserProgramProgress(ctx, dbgen.InsertUserProgramProgressParams{UserID: userID, ProgramID: crs.ProgramID}); err != nil { return err } } } } if err := tx.Commit(ctx); err != nil { return fmt.Errorf("commit: %w", err) } return nil }