package repository import ( "context" "errors" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" "gorm.io/gorm" ) type ApprovalRepository interface { BaseRepository[entity.Approval] FindByTarget(ctx context.Context, workflow string, approvableID uint, modifier func(*gorm.DB) *gorm.DB) ([]entity.Approval, error) LatestByTarget(ctx context.Context, workflow string, approvableID uint, modifier func(*gorm.DB) *gorm.DB) (*entity.Approval, error) LatestByTargets(ctx context.Context, workflow string, approvableIDs []uint, modifier func(*gorm.DB) *gorm.DB) (map[uint]entity.Approval, error) DeleteByTarget(ctx context.Context, workflow string, approvableID uint) error } type approvalRepositoryImpl struct { *BaseRepositoryImpl[entity.Approval] } func NewApprovalRepository(db *gorm.DB) ApprovalRepository { return &approvalRepositoryImpl{ BaseRepositoryImpl: NewBaseRepository[entity.Approval](db), } } func (r *approvalRepositoryImpl) FindByTarget( ctx context.Context, workflow string, approvableID uint, modifier func(*gorm.DB) *gorm.DB, ) ([]entity.Approval, error) { var approvals []entity.Approval q := r.DB().WithContext(ctx).Where("approvable_type = ? AND approvable_id = ?", workflow, approvableID) if modifier != nil { q = modifier(q) } if err := q.Order("action_at ASC").Find(&approvals).Error; err != nil { return nil, err } return approvals, nil } func (r *approvalRepositoryImpl) LatestByTarget( ctx context.Context, workflow string, approvableID uint, modifier func(*gorm.DB) *gorm.DB, ) (*entity.Approval, error) { var approval entity.Approval q := r.DB().WithContext(ctx). Where("approvable_type = ? AND approvable_id = ?", workflow, approvableID). Order("action_at DESC") if modifier != nil { q = modifier(q) } if err := q.Limit(1).First(&approval).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil } return nil, err } return &approval, nil } func (r *approvalRepositoryImpl) LatestByTargets( ctx context.Context, workflow string, approvableIDs []uint, modifier func(*gorm.DB) *gorm.DB, ) (map[uint]entity.Approval, error) { if len(approvableIDs) == 0 { return nil, nil } result := make(map[uint]entity.Approval, len(approvableIDs)) q := r.DB().WithContext(ctx). Select("DISTINCT ON (approvable_id) *"). Where("approvable_type = ? AND approvable_id IN ?", workflow, approvableIDs). Order("approvable_id, action_at DESC") if modifier != nil { q = modifier(q) } var approvals []entity.Approval if err := q.Find(&approvals).Error; err != nil { return nil, err } for _, approval := range approvals { if _, exists := result[approval.ApprovableId]; exists { continue } result[approval.ApprovableId] = approval } return result, nil } func (r *approvalRepositoryImpl) DeleteByTarget( ctx context.Context, workflow string, approvableID uint, ) error { return r.DB().WithContext(ctx). Where("approvable_type = ? AND approvable_id = ?", workflow, approvableID). Delete(&entity.Approval{}).Error }