216 lines
5.7 KiB
Go
216 lines
5.7 KiB
Go
package directory
|
|
|
|
import (
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"heliosian/internal/data"
|
|
)
|
|
|
|
const appName = "directory"
|
|
|
|
func LoadModel(source data.Source) (*Model, error) {
|
|
tables := map[string][]map[string]string{}
|
|
for _, name := range []string{"Basic Directory", "Staff Details", "Classrooms", "Schedules", "Grade Lookup", "Room Parents", "Departments"} {
|
|
rows, err := source.Table(appName, name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
tables[name] = rows
|
|
}
|
|
|
|
model := &Model{Families: map[string]Family{}, RoomParents: map[string][]string{}}
|
|
|
|
staffByEmail := map[string]map[string]string{}
|
|
for _, row := range tables["Staff Details"] {
|
|
email := strings.ToLower(row["Email Lower"])
|
|
if email != "" {
|
|
staffByEmail[email] = row
|
|
}
|
|
}
|
|
|
|
type familyAcc struct {
|
|
family Family
|
|
hasParent bool
|
|
hasStudent bool
|
|
}
|
|
families := map[string]*familyAcc{}
|
|
byEmail := map[string]Person{}
|
|
for _, row := range tables["Basic Directory"] {
|
|
email := strings.ToLower(row["Email Lower"])
|
|
if email == "" {
|
|
continue
|
|
}
|
|
p := Person{
|
|
Email: email,
|
|
FullName: row["Full Name"],
|
|
LegalName: row["Legal Name"],
|
|
PreferredName: row["Preferred Name"],
|
|
IsStaff: row["Is Staff?"] == "TRUE",
|
|
IsParent: row["Is Parent?"] == "TRUE",
|
|
IsStudent: row["Is Student?"] == "TRUE",
|
|
Pronouns: row["Pronouns"],
|
|
Facts: row["Facts"],
|
|
PronunciationURL: row["Pronunciation"],
|
|
PhotoURL: row["Primary Photo"],
|
|
Grade: row["Grade"],
|
|
Classroom: row["Class"],
|
|
Section: row["Section"],
|
|
Phone: row["Phone Number"],
|
|
FamilyKey: strings.ToLower(row["Family Key"]),
|
|
}
|
|
for _, contact := range strings.Split(row["Parent Contact Emails"], ",") {
|
|
if contact = strings.ToLower(strings.TrimSpace(contact)); contact != "" {
|
|
p.ParentContactEmails = append(p.ParentContactEmails, contact)
|
|
}
|
|
}
|
|
if details, ok := staffByEmail[email]; ok {
|
|
p.JobTitle = details["Job Title"]
|
|
p.Department = details["Department"]
|
|
p.GradeBand = details["Grade Band"]
|
|
}
|
|
model.People = append(model.People, p)
|
|
byEmail[email] = p
|
|
|
|
if p.FamilyKey == "" {
|
|
continue
|
|
}
|
|
acc, ok := families[p.FamilyKey]
|
|
if !ok {
|
|
acc = &familyAcc{family: Family{Key: p.FamilyKey}}
|
|
families[p.FamilyKey] = acc
|
|
}
|
|
if acc.family.Address == "" && row["Address 1"] != "" {
|
|
acc.family.Address = row["Address 1"]
|
|
if row["Address 2"] != "" {
|
|
acc.family.Address += ", " + row["Address 2"]
|
|
}
|
|
}
|
|
if acc.family.PhotoURL == "" {
|
|
acc.family.PhotoURL = row["Family Photo"]
|
|
}
|
|
if acc.family.PhotoCaption == "" {
|
|
acc.family.PhotoCaption = row["Family Photo Description"]
|
|
}
|
|
if acc.family.PronunciationURL == "" {
|
|
acc.family.PronunciationURL = row["Family Pronunciation"]
|
|
}
|
|
if p.IsParent {
|
|
acc.hasParent = true
|
|
acc.family.AdultEmails = append(acc.family.AdultEmails, email)
|
|
}
|
|
if p.IsStudent {
|
|
acc.hasStudent = true
|
|
acc.family.KidEmails = append(acc.family.KidEmails, email)
|
|
}
|
|
}
|
|
for key, acc := range families {
|
|
if !acc.hasParent && !acc.hasStudent {
|
|
continue
|
|
}
|
|
acc.family.Name = familyName(acc.family, byEmail)
|
|
model.Families[key] = acc.family
|
|
}
|
|
|
|
sort.Slice(model.People, func(i, j int) bool {
|
|
si, sj := surname(model.People[i].FullName), surname(model.People[j].FullName)
|
|
if si != sj {
|
|
return si < sj
|
|
}
|
|
return model.People[i].FullName < model.People[j].FullName
|
|
})
|
|
|
|
for _, row := range tables["Classrooms"] {
|
|
if row["Class"] == "" {
|
|
continue
|
|
}
|
|
model.Classrooms = append(model.Classrooms, Classroom{
|
|
Name: row["Class"],
|
|
ImageURL: row["Classroom Image"],
|
|
HasSections: row["Has Sections"] == "TRUE",
|
|
})
|
|
}
|
|
|
|
for _, row := range tables["Schedules"] {
|
|
if row["Classroom"] == "" {
|
|
continue
|
|
}
|
|
section := Section{Classroom: row["Classroom"], Name: row["Section"], GradeBand: row["Grade Band"]}
|
|
for _, column := range []string{"Teacher 1", "Teacher 2", "Teacher 3"} {
|
|
if row[column] != "" {
|
|
section.Teachers = append(section.Teachers, row[column])
|
|
}
|
|
}
|
|
model.Sections = append(model.Sections, section)
|
|
}
|
|
|
|
for _, row := range tables["Grade Lookup"] {
|
|
if row["Current Grade"] == "" {
|
|
continue
|
|
}
|
|
model.Grades = append(model.Grades, Grade{
|
|
Name: row["Current Grade"],
|
|
NextName: row["Next Grade"],
|
|
Band: row["Current Gradeband"],
|
|
NextBand: row["Next Gradeband"],
|
|
})
|
|
}
|
|
|
|
for _, row := range tables["Room Parents"] {
|
|
band, email := row["Gradeband"], strings.ToLower(row["Email Address"])
|
|
if band == "" || email == "" {
|
|
continue
|
|
}
|
|
model.RoomParents[band] = append(model.RoomParents[band], email)
|
|
}
|
|
|
|
type department struct {
|
|
name string
|
|
order float64
|
|
}
|
|
departments := []department{}
|
|
for _, row := range tables["Departments"] {
|
|
if row["Department"] == "" {
|
|
continue
|
|
}
|
|
order, err := strconv.ParseFloat(row["Order"], 64)
|
|
if err != nil {
|
|
order = float64(len(departments))
|
|
}
|
|
departments = append(departments, department{name: row["Department"], order: order})
|
|
}
|
|
sort.SliceStable(departments, func(i, j int) bool { return departments[i].order < departments[j].order })
|
|
for _, d := range departments {
|
|
model.Departments = append(model.Departments, d.name)
|
|
}
|
|
|
|
return model, nil
|
|
}
|
|
|
|
func surname(fullName string) string {
|
|
fields := strings.Fields(fullName)
|
|
if len(fields) == 0 {
|
|
return ""
|
|
}
|
|
return fields[len(fields)-1]
|
|
}
|
|
|
|
func familyName(f Family, byEmail map[string]Person) string {
|
|
members := append(append([]string{}, f.KidEmails...), f.AdultEmails...)
|
|
seen := map[string]bool{}
|
|
names := []string{}
|
|
for _, email := range members {
|
|
s := surname(byEmail[email].FullName)
|
|
if s == "" || seen[s] {
|
|
continue
|
|
}
|
|
seen[s] = true
|
|
names = append(names, s)
|
|
}
|
|
if len(names) == 0 {
|
|
return ""
|
|
}
|
|
return strings.Join(names, " & ") + " Family"
|
|
}
|