完整性更新
现在已经实现了大部分基础功能
This commit is contained in:
183
src/modules/school/data-access.ts
Normal file
183
src/modules/school/data-access.ts
Normal file
@@ -0,0 +1,183 @@
|
||||
import "server-only"
|
||||
|
||||
import { cache } from "react"
|
||||
import { asc, eq, inArray, or } from "drizzle-orm"
|
||||
|
||||
import { db } from "@/shared/db"
|
||||
import { academicYears, departments, grades, schools, users } from "@/shared/db/schema"
|
||||
import type { AcademicYearListItem, DepartmentListItem, GradeListItem, SchoolListItem, StaffOption } from "./types"
|
||||
|
||||
const toIso = (d: Date) => d.toISOString()
|
||||
|
||||
export const getDepartments = cache(async (): Promise<DepartmentListItem[]> => {
|
||||
try {
|
||||
const rows = await db.select().from(departments).orderBy(asc(departments.name))
|
||||
return rows.map((r) => ({
|
||||
id: r.id,
|
||||
name: r.name,
|
||||
description: r.description ?? null,
|
||||
createdAt: toIso(r.createdAt),
|
||||
updatedAt: toIso(r.updatedAt),
|
||||
}))
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
})
|
||||
|
||||
export const getAcademicYears = cache(async (): Promise<AcademicYearListItem[]> => {
|
||||
try {
|
||||
const rows = await db.select().from(academicYears).orderBy(asc(academicYears.startDate))
|
||||
return rows.map((r) => ({
|
||||
id: r.id,
|
||||
name: r.name,
|
||||
startDate: toIso(r.startDate),
|
||||
endDate: toIso(r.endDate),
|
||||
isActive: Boolean(r.isActive),
|
||||
createdAt: toIso(r.createdAt),
|
||||
updatedAt: toIso(r.updatedAt),
|
||||
}))
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
})
|
||||
|
||||
export const getSchools = cache(async (): Promise<SchoolListItem[]> => {
|
||||
try {
|
||||
const rows = await db.select().from(schools).orderBy(asc(schools.name))
|
||||
return rows.map((r) => ({
|
||||
id: r.id,
|
||||
name: r.name,
|
||||
code: r.code ?? null,
|
||||
createdAt: toIso(r.createdAt),
|
||||
updatedAt: toIso(r.updatedAt),
|
||||
}))
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
})
|
||||
|
||||
export const getGrades = cache(async (): Promise<GradeListItem[]> => {
|
||||
try {
|
||||
const rows = await db
|
||||
.select({
|
||||
id: grades.id,
|
||||
name: grades.name,
|
||||
order: grades.order,
|
||||
schoolId: schools.id,
|
||||
schoolName: schools.name,
|
||||
gradeHeadId: grades.gradeHeadId,
|
||||
teachingHeadId: grades.teachingHeadId,
|
||||
createdAt: grades.createdAt,
|
||||
updatedAt: grades.updatedAt,
|
||||
})
|
||||
.from(grades)
|
||||
.innerJoin(schools, eq(schools.id, grades.schoolId))
|
||||
.orderBy(asc(schools.name), asc(grades.order), asc(grades.name))
|
||||
|
||||
const headIds = Array.from(
|
||||
new Set(
|
||||
rows
|
||||
.flatMap((r) => [r.gradeHeadId, r.teachingHeadId])
|
||||
.filter((v): v is string => typeof v === "string" && v.length > 0)
|
||||
)
|
||||
)
|
||||
|
||||
const heads = headIds.length
|
||||
? await db
|
||||
.select({ id: users.id, name: users.name, email: users.email })
|
||||
.from(users)
|
||||
.where(inArray(users.id, headIds))
|
||||
: []
|
||||
|
||||
const headById = new Map<string, StaffOption>()
|
||||
for (const u of heads) {
|
||||
headById.set(u.id, { id: u.id, name: u.name ?? "Unnamed", email: u.email })
|
||||
}
|
||||
|
||||
return rows.map((r) => ({
|
||||
id: r.id,
|
||||
school: { id: r.schoolId, name: r.schoolName },
|
||||
name: r.name,
|
||||
order: Number(r.order ?? 0),
|
||||
gradeHead: r.gradeHeadId ? headById.get(r.gradeHeadId) ?? null : null,
|
||||
teachingHead: r.teachingHeadId ? headById.get(r.teachingHeadId) ?? null : null,
|
||||
createdAt: toIso(r.createdAt),
|
||||
updatedAt: toIso(r.updatedAt),
|
||||
}))
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
})
|
||||
|
||||
export const getStaffOptions = cache(async (): Promise<StaffOption[]> => {
|
||||
try {
|
||||
const rows = await db
|
||||
.select({ id: users.id, name: users.name, email: users.email })
|
||||
.from(users)
|
||||
.where(inArray(users.role, ["teacher", "admin"]))
|
||||
.orderBy(asc(users.name), asc(users.email))
|
||||
|
||||
return rows.map((r) => ({
|
||||
id: r.id,
|
||||
name: r.name ?? "Unnamed",
|
||||
email: r.email,
|
||||
}))
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
})
|
||||
|
||||
export const getGradesForStaff = cache(async (staffId: string): Promise<GradeListItem[]> => {
|
||||
const id = staffId.trim()
|
||||
if (!id) return []
|
||||
|
||||
try {
|
||||
const rows = await db
|
||||
.select({
|
||||
id: grades.id,
|
||||
name: grades.name,
|
||||
order: grades.order,
|
||||
schoolId: schools.id,
|
||||
schoolName: schools.name,
|
||||
gradeHeadId: grades.gradeHeadId,
|
||||
teachingHeadId: grades.teachingHeadId,
|
||||
createdAt: grades.createdAt,
|
||||
updatedAt: grades.updatedAt,
|
||||
})
|
||||
.from(grades)
|
||||
.innerJoin(schools, eq(schools.id, grades.schoolId))
|
||||
.where(or(eq(grades.gradeHeadId, id), eq(grades.teachingHeadId, id)))
|
||||
.orderBy(asc(schools.name), asc(grades.order), asc(grades.name))
|
||||
|
||||
const headIds = Array.from(
|
||||
new Set(
|
||||
rows
|
||||
.flatMap((r) => [r.gradeHeadId, r.teachingHeadId])
|
||||
.filter((v): v is string => typeof v === "string" && v.length > 0)
|
||||
)
|
||||
)
|
||||
|
||||
const heads = headIds.length
|
||||
? await db
|
||||
.select({ id: users.id, name: users.name, email: users.email })
|
||||
.from(users)
|
||||
.where(inArray(users.id, headIds))
|
||||
: []
|
||||
|
||||
const headById = new Map<string, StaffOption>()
|
||||
for (const u of heads) headById.set(u.id, { id: u.id, name: u.name ?? "Unnamed", email: u.email })
|
||||
|
||||
return rows.map((r) => ({
|
||||
id: r.id,
|
||||
school: { id: r.schoolId, name: r.schoolName },
|
||||
name: r.name,
|
||||
order: Number(r.order ?? 0),
|
||||
gradeHead: r.gradeHeadId ? headById.get(r.gradeHeadId) ?? null : null,
|
||||
teachingHead: r.teachingHeadId ? headById.get(r.teachingHeadId) ?? null : null,
|
||||
createdAt: toIso(r.createdAt),
|
||||
updatedAt: toIso(r.updatedAt),
|
||||
}))
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user