Files
SchoolVue/src/db.js
2026-06-19 20:15:20 +05:00

170 lines
5.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
};