package training import ( "context" "time" "github.com/google/uuid" ) // GetMatrixForRole returns all matrix entries for a given role func (s *Store) GetMatrixForRole(ctx context.Context, tenantID uuid.UUID, roleCode string) ([]TrainingMatrixEntry, error) { rows, err := s.pool.Query(ctx, ` SELECT tm.id, tm.tenant_id, tm.role_code, tm.module_id, tm.is_mandatory, tm.priority, tm.created_at, m.module_code, m.title FROM training_matrix tm JOIN training_modules m ON m.id = tm.module_id WHERE tm.tenant_id = $1 AND tm.role_code = $2 ORDER BY tm.priority ASC `, tenantID, roleCode) if err != nil { return nil, err } defer rows.Close() var entries []TrainingMatrixEntry for rows.Next() { var entry TrainingMatrixEntry err := rows.Scan( &entry.ID, &entry.TenantID, &entry.RoleCode, &entry.ModuleID, &entry.IsMandatory, &entry.Priority, &entry.CreatedAt, &entry.ModuleCode, &entry.ModuleTitle, ) if err != nil { return nil, err } entries = append(entries, entry) } if entries == nil { entries = []TrainingMatrixEntry{} } return entries, nil } // GetMatrixForTenant returns the full CTM for a tenant func (s *Store) GetMatrixForTenant(ctx context.Context, tenantID uuid.UUID) ([]TrainingMatrixEntry, error) { rows, err := s.pool.Query(ctx, ` SELECT tm.id, tm.tenant_id, tm.role_code, tm.module_id, tm.is_mandatory, tm.priority, tm.created_at, m.module_code, m.title FROM training_matrix tm JOIN training_modules m ON m.id = tm.module_id WHERE tm.tenant_id = $1 ORDER BY tm.role_code ASC, tm.priority ASC `, tenantID) if err != nil { return nil, err } defer rows.Close() var entries []TrainingMatrixEntry for rows.Next() { var entry TrainingMatrixEntry err := rows.Scan( &entry.ID, &entry.TenantID, &entry.RoleCode, &entry.ModuleID, &entry.IsMandatory, &entry.Priority, &entry.CreatedAt, &entry.ModuleCode, &entry.ModuleTitle, ) if err != nil { return nil, err } entries = append(entries, entry) } if entries == nil { entries = []TrainingMatrixEntry{} } return entries, nil } // SetMatrixEntry creates or updates a CTM entry func (s *Store) SetMatrixEntry(ctx context.Context, entry *TrainingMatrixEntry) error { entry.ID = uuid.New() entry.CreatedAt = time.Now().UTC() _, err := s.pool.Exec(ctx, ` INSERT INTO training_matrix ( id, tenant_id, role_code, module_id, is_mandatory, priority, created_at ) VALUES ($1, $2, $3, $4, $5, $6, $7) ON CONFLICT (tenant_id, role_code, module_id) DO UPDATE SET is_mandatory = EXCLUDED.is_mandatory, priority = EXCLUDED.priority `, entry.ID, entry.TenantID, entry.RoleCode, entry.ModuleID, entry.IsMandatory, entry.Priority, entry.CreatedAt, ) return err } // DeleteMatrixEntry removes a CTM entry func (s *Store) DeleteMatrixEntry(ctx context.Context, tenantID uuid.UUID, roleCode string, moduleID uuid.UUID) error { _, err := s.pool.Exec(ctx, "DELETE FROM training_matrix WHERE tenant_id = $1 AND role_code = $2 AND module_id = $3", tenantID, roleCode, moduleID, ) return err }