170 lines
5.7 KiB
JavaScript
170 lines
5.7 KiB
JavaScript
const Database = require('better-sqlite3');
|
||
const path = require('path');
|
||
const fs = require('fs');
|
||
|
||
const DATA_DIR = path.join(__dirname, '..', 'data');
|
||
if (!fs.existsSync(DATA_DIR)) fs.mkdirSync(DATA_DIR, { recursive: true });
|
||
|
||
const DB_PATH = path.join(DATA_DIR, 'journal.db');
|
||
const db = new Database(DB_PATH);
|
||
|
||
db.pragma('journal_mode = WAL');
|
||
db.pragma('foreign_keys = ON');
|
||
|
||
db.exec(`
|
||
CREATE TABLE IF NOT EXISTS classes (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
name TEXT UNIQUE NOT NULL
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS students (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
full_name TEXT NOT NULL,
|
||
class_id INTEGER NOT NULL,
|
||
UNIQUE(full_name, class_id),
|
||
FOREIGN KEY (class_id) REFERENCES classes(id)
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS subjects (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
name TEXT UNIQUE NOT NULL
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS teachers (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
name TEXT UNIQUE NOT NULL,
|
||
subject_id INTEGER,
|
||
FOREIGN KEY (subject_id) REFERENCES subjects(id)
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS grades (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
student_id INTEGER NOT NULL,
|
||
subject_id INTEGER NOT NULL,
|
||
teacher_id INTEGER,
|
||
quarter TEXT NOT NULL,
|
||
grade INTEGER,
|
||
UNIQUE(student_id, subject_id, quarter),
|
||
FOREIGN KEY (student_id) REFERENCES students(id),
|
||
FOREIGN KEY (subject_id) REFERENCES subjects(id),
|
||
FOREIGN KEY (teacher_id) REFERENCES teachers(id)
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS daily_grades (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
student_id INTEGER NOT NULL,
|
||
subject_id INTEGER NOT NULL,
|
||
teacher_id INTEGER,
|
||
grade_date TEXT NOT NULL,
|
||
grade INTEGER,
|
||
symbol TEXT,
|
||
FOREIGN KEY (student_id) REFERENCES students(id),
|
||
FOREIGN KEY (subject_id) REFERENCES subjects(id),
|
||
FOREIGN KEY (teacher_id) REFERENCES teachers(id)
|
||
);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_daily_student ON daily_grades(student_id);
|
||
CREATE INDEX IF NOT EXISTS idx_daily_subject ON daily_grades(subject_id);
|
||
CREATE INDEX IF NOT EXISTS idx_daily_teacher ON daily_grades(teacher_id);
|
||
CREATE INDEX IF NOT EXISTS idx_daily_date ON daily_grades(grade_date);
|
||
|
||
CREATE TABLE IF NOT EXISTS lesson_plans (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
subject_id INTEGER NOT NULL,
|
||
teacher_id INTEGER,
|
||
lesson_date TEXT NOT NULL,
|
||
topic TEXT,
|
||
homework TEXT,
|
||
UNIQUE(subject_id, lesson_date),
|
||
FOREIGN KEY (subject_id) REFERENCES subjects(id),
|
||
FOREIGN KEY (teacher_id) REFERENCES teachers(id)
|
||
);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_lp_subject ON lesson_plans(subject_id);
|
||
CREATE INDEX IF NOT EXISTS idx_lp_teacher ON lesson_plans(teacher_id);
|
||
CREATE INDEX IF NOT EXISTS idx_lp_date ON lesson_plans(lesson_date);
|
||
`);
|
||
|
||
const getClass = db.prepare(`SELECT id FROM classes WHERE name = ?`);
|
||
const insertClass = db.prepare(`INSERT OR IGNORE INTO classes (name) VALUES (?)`);
|
||
|
||
const getStudent = db.prepare(`SELECT id FROM students WHERE full_name = ? AND class_id = ?`);
|
||
const insertStudent = db.prepare(`INSERT OR IGNORE INTO students (full_name, class_id) VALUES (?, ?)`);
|
||
|
||
const getSubject = db.prepare(`SELECT id FROM subjects WHERE name = ?`);
|
||
const insertSubject = db.prepare(`INSERT OR IGNORE INTO subjects (name) VALUES (?)`);
|
||
|
||
const getTeacher = db.prepare(`SELECT id FROM teachers WHERE name = ? AND subject_id = ?`);
|
||
const getTeacherNull = db.prepare(`SELECT id FROM teachers WHERE name = ? AND subject_id IS NULL`);
|
||
const insertTeacher = db.prepare(`INSERT OR IGNORE INTO teachers (name, subject_id) VALUES (?, ?)`);
|
||
|
||
const upsertGrade = db.prepare(`
|
||
INSERT INTO grades (student_id, subject_id, teacher_id, quarter, grade)
|
||
VALUES (?, ?, ?, ?, ?)
|
||
ON CONFLICT(student_id, subject_id, quarter) DO UPDATE SET
|
||
teacher_id = excluded.teacher_id,
|
||
grade = excluded.grade
|
||
`);
|
||
|
||
function upsertClass(name) {
|
||
insertClass.run(name);
|
||
return getClass.get(name).id;
|
||
}
|
||
|
||
function upsertStudent(fullName, classId) {
|
||
insertStudent.run(fullName, classId);
|
||
return getStudent.get(fullName, classId).id;
|
||
}
|
||
|
||
function upsertSubject(name) {
|
||
insertSubject.run(name);
|
||
return getSubject.get(name).id;
|
||
}
|
||
|
||
function upsertTeacher(name, subjectId) {
|
||
insertTeacher.run(name, subjectId || null);
|
||
const row = subjectId ? getTeacher.get(name, subjectId) : getTeacherNull.get(name);
|
||
return row ? row.id : null;
|
||
}
|
||
|
||
function upsertGradeValue(studentId, subjectId, teacherId, quarter, grade) {
|
||
upsertGrade.run(studentId, subjectId, teacherId || null, quarter, grade === 'н/а' || grade === 'н' ? null : Number(grade) || null);
|
||
}
|
||
|
||
const insertDailyGrade = db.prepare(`
|
||
INSERT INTO daily_grades (student_id, subject_id, teacher_id, grade_date, grade, symbol)
|
||
VALUES (?, ?, ?, ?, ?, ?)
|
||
`);
|
||
|
||
function insertDailyGradeValue(studentId, subjectId, teacherId, gradeDate, gradeVal) {
|
||
const num = /^[2-5]$/.test(gradeVal) ? parseInt(gradeVal) : null;
|
||
const sym = /^[НБУнбу]$/.test(gradeVal) ? gradeVal.toUpperCase() : null;
|
||
insertDailyGrade.run(studentId, subjectId, teacherId || null, gradeDate, num, sym);
|
||
}
|
||
|
||
const insertLessonPlan = db.prepare(`
|
||
INSERT OR REPLACE INTO lesson_plans (subject_id, teacher_id, lesson_date, topic, homework)
|
||
VALUES (?, ?, ?, ?, ?)
|
||
`);
|
||
|
||
function insertLessonPlanValue(subjectId, teacherId, lessonDate, topic, homework) {
|
||
insertLessonPlan.run(subjectId, teacherId || null, lessonDate, topic || null, homework || null);
|
||
}
|
||
|
||
function clearAll() {
|
||
db.exec('DELETE FROM lesson_plans; DELETE FROM daily_grades; DELETE FROM grades; DELETE FROM teachers; DELETE FROM students; DELETE FROM subjects; DELETE FROM classes;');
|
||
}
|
||
|
||
module.exports = {
|
||
db,
|
||
upsertClass,
|
||
upsertStudent,
|
||
upsertSubject,
|
||
upsertTeacher,
|
||
upsertGradeValue,
|
||
insertDailyGradeValue,
|
||
insertLessonPlanValue,
|
||
clearAll,
|
||
DATA_DIR
|
||
};
|