package orm import ( "fmt" "net/http" "strings" "github.com/gobwas/glob" "github.com/jinzhu/gorm" "gogs.carduccidante.edu.it/karmen/core/renderer" ) type Group struct { gorm.Model Name string Query string TeacherIDs []uint `schema:"teacher_ids" gorm:"-"` Teachers []*Teacher `gorm:"many2many:group_teachers"` AllTeachers []*Teacher SelectedTeacher map[uint]string `gorm:"-"` } func (g *Group) GetID() uint { return g.ID } func (g *Group) String() string { return g.Name } func (g *Group) Create(args map[string]string, r *http.Request) (interface{}, error) { if r.Method == "GET" { group := new(Group) if err := DB().Find(&group.AllTeachers).Error; err != nil { return nil, err } return group, nil } else { group := new(Group) err := renderer.Decode(group, r) if err != nil { return nil, err } group, err = CreateGroup(group) if err != nil { return nil, err } return group, nil } } func (g *Group) Read(args map[string]string, r *http.Request) (interface{}, error) { var group Group id := args["id"] if err := DB().Preload("Teachers").Where("id = ?", id).Find(&group).Error; err != nil { return nil, err } if group.Query != "" { err := group.updateTeachersAssociation() if err != nil { return nil, err } } return &group, nil } func (g *Group) ReadAll(args map[string]string, r *http.Request) (interface{}, error) { var groups []*Group if err := DB().Preload("Teachers").Order("name").Find(&groups).Error; err != nil { return nil, err } for _, group := range groups { if group.Query != "" { err := group.updateTeachersAssociation() if err != nil { return nil, err } } } return groups, nil } func (g *Group) Update(args map[string]string, r *http.Request) (interface{}, error) { if r.Method == "GET" { result, err := g.Read(args, r) if err != nil { return nil, err } group := result.(*Group) if err := DB().Find(&group.AllTeachers).Error; err != nil { return nil, err } group.SelectedTeacher = make(map[uint]string) for _, t := range group.Teachers { group.SelectedTeacher[t.ID] = "selected" } return group, nil } else { group, err := g.Read(args, r) if err != nil { return nil, err } err = renderer.Decode(group, r) if err != nil { return nil, err } if err := DB().Where(group.(*Group).TeacherIDs).Find(&group.(*Group).Teachers).Error; err != nil { return nil, err } teachers, err := group.(*Group).executeTeacherQuery() group.(*Group).Teachers = append(group.(*Group).Teachers, teachers...) _, err = SaveGroup(group) if err != nil { return nil, err } if err := DB().Model(group).Association("Teachers").Replace(group.(*Group).Teachers).Error; err != nil { return nil, err } group, err = g.Read(args, r) if err != nil { return nil, err } return group.(*Group), nil } } func (g *Group) Delete(args map[string]string, r *http.Request) (interface{}, error) { group, err := g.Read(args, r) if err != nil { return nil, err } if err := DB().Unscoped().Delete(group.(*Group)).Error; err != nil { return nil, err } return group.(*Group), nil } func SaveGroup(group interface{}) (interface{}, error) { if err := DB().Save(group).Error; err != nil { return nil, err } return group, nil } func CreateGroup(group *Group) (*Group, error) { var groups []*Group if err := DB().Where("name=?", group.Name).Find(&groups).Error; err != nil { return nil, err } if len(groups) > 0 { return nil, fmt.Errorf("Group %s already exists!", group.Name) } if err := DB().Where(group.TeacherIDs).Find(&group.Teachers).Error; err != nil { return nil, err } teachers, err := group.executeTeacherQuery() if err != nil { return nil, err } group.Teachers = append(group.Teachers, teachers...) if err := DB().Create(group).Error; err != nil { return nil, err } return group, nil } func (group *Group) updateTeachersAssociation() error { teachers, err := group.executeTeacherQuery() if err != nil { return err } if err := DB().Model(group).Association("Teachers").Replace(teachers).Error; err != nil { return err } return nil } func (group *Group) executeTeacherQuery() ([]*Teacher, error) { var ( result []*Teacher allTeachers []*Teacher ) if group.Query != "" { fields := strings.Split(group.Query, " ") if err := DB().Find(&allTeachers).Error; err != nil { return nil, err } for _, field := range fields { nameValue := strings.Split(field, ":") if len(nameValue) < 2 { return nil, fmt.Errorf("Error parsing search query %s on field %s", group.Query, field) } name := nameValue[0] value := nameValue[1] switch name { case "surname": g, err := glob.Compile(value) if err != nil { return nil, err } for _, t := range allTeachers { if g.Match(t.Surname) { result = append(result, t) } } case "coordinator": for _, t := range allTeachers { c, err := t.CoordinatorClasses() if err != nil { return nil, err } if len(c) > 0 { result = append(result, t) } } } } } return result, nil }