Yimaru-BackEnd/internal/repository/lms_progress_tx.go

87 lines
2.4 KiB
Go

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
}