исправление хранения календаря
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
-- Инициализация расширений
|
||||
-- ==========================================
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
CREATE EXTENSION IF NOT EXISTS btree_gist;
|
||||
|
||||
-- ===============================
|
||||
-- Справочники высшего уровня
|
||||
@@ -714,22 +715,25 @@ JOIN specialty_profiles profile ON profile.specialty_id = specialty.id AND profi
|
||||
WHERE ay.title = '2025-2026'
|
||||
ON CONFLICT (academic_year_id, specialty_profile_id, study_form_id, title) DO NOTHING;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS academic_calendar_days (
|
||||
CREATE TABLE IF NOT EXISTS academic_calendar_periods (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
calendar_id BIGINT NOT NULL REFERENCES academic_calendars(id) ON DELETE CASCADE,
|
||||
course_number INT NOT NULL,
|
||||
date DATE NOT NULL,
|
||||
week_number INT NOT NULL,
|
||||
day_of_week INT NOT NULL,
|
||||
start_date DATE NOT NULL,
|
||||
end_date DATE NOT NULL,
|
||||
activity_type_id BIGINT NOT NULL REFERENCES academic_calendar_activity_types(id),
|
||||
CONSTRAINT chk_calendar_days_course_positive CHECK (course_number > 0),
|
||||
CONSTRAINT chk_calendar_days_week_positive CHECK (week_number > 0),
|
||||
CONSTRAINT chk_calendar_days_day CHECK (day_of_week BETWEEN 1 AND 7),
|
||||
CONSTRAINT uq_calendar_days UNIQUE (calendar_id, course_number, date)
|
||||
CONSTRAINT chk_calendar_periods_course_positive CHECK (course_number > 0),
|
||||
CONSTRAINT chk_calendar_periods_dates CHECK (end_date >= start_date),
|
||||
CONSTRAINT ex_calendar_periods_no_overlap
|
||||
EXCLUDE USING gist (
|
||||
calendar_id WITH =,
|
||||
course_number WITH =,
|
||||
(daterange(start_date, end_date, '[]')) WITH &&
|
||||
)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_calendar_days_lookup
|
||||
ON academic_calendar_days(calendar_id, course_number, date);
|
||||
CREATE INDEX IF NOT EXISTS idx_calendar_periods_schedule
|
||||
ON academic_calendar_periods(calendar_id, course_number, start_date, end_date);
|
||||
|
||||
CREATE OR REPLACE FUNCTION calculate_academic_calendar_week_number(
|
||||
academic_year_start DATE,
|
||||
@@ -750,20 +754,23 @@ AS $$
|
||||
) + 1
|
||||
$$;
|
||||
|
||||
INSERT INTO academic_calendar_days (calendar_id, course_number, date, week_number, day_of_week, activity_type_id)
|
||||
INSERT INTO academic_calendar_periods (
|
||||
calendar_id,
|
||||
course_number,
|
||||
start_date,
|
||||
end_date,
|
||||
activity_type_id
|
||||
)
|
||||
SELECT
|
||||
calendar.id,
|
||||
course.course_number,
|
||||
days.date::DATE,
|
||||
calculate_academic_calendar_week_number(ay.start_date, days.date::DATE),
|
||||
EXTRACT(ISODOW FROM days.date::DATE)::INT,
|
||||
ay.start_date,
|
||||
ay.end_date,
|
||||
activity.id
|
||||
FROM academic_calendars calendar
|
||||
JOIN academic_years ay ON ay.id = calendar.academic_year_id
|
||||
JOIN academic_calendar_activity_types activity ON activity.code = 'Т'
|
||||
CROSS JOIN GENERATE_SERIES(1, calendar.course_count) AS course(course_number)
|
||||
CROSS JOIN GENERATE_SERIES(ay.start_date, ay.end_date, INTERVAL '1 day') AS days(date)
|
||||
ON CONFLICT (calendar_id, course_number, date) DO NOTHING;
|
||||
CROSS JOIN GENERATE_SERIES(1, calendar.course_count) AS course(course_number);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS academic_calendar_subjects (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
@@ -1134,7 +1141,7 @@ COMMENT ON TABLE academic_years IS 'Учебные годы';
|
||||
COMMENT ON TABLE semesters IS 'Семестры учебного года';
|
||||
COMMENT ON TABLE academic_calendar_activity_types IS 'Коды активностей календарного учебного графика';
|
||||
COMMENT ON TABLE academic_calendars IS 'Календарные учебные графики по профилю, форме обучения и учебному году';
|
||||
COMMENT ON TABLE academic_calendar_days IS 'Дневные ячейки календарного учебного графика';
|
||||
COMMENT ON TABLE academic_calendar_periods IS 'Непересекающиеся периоды активности календарного учебного графика';
|
||||
COMMENT ON TABLE academic_calendar_subjects IS 'Привязка дисциплин к календарному учебному графику по номерам учебных семестров';
|
||||
COMMENT ON TABLE student_group_calendar_assignments IS 'Назначения календарных графиков учебным группам по учебному году';
|
||||
COMMENT ON TABLE schedule_rules IS 'Правила динамической генерации расписания';
|
||||
@@ -1275,12 +1282,11 @@ COMMENT ON COLUMN academic_calendars.specialty_profile_id IS 'ID профиля
|
||||
COMMENT ON COLUMN academic_calendars.study_form_id IS 'ID формы обучения из education_forms';
|
||||
COMMENT ON COLUMN academic_calendars.course_count IS 'Количество курсов в графике';
|
||||
|
||||
COMMENT ON COLUMN academic_calendar_days.calendar_id IS 'ID календарного учебного графика';
|
||||
COMMENT ON COLUMN academic_calendar_days.course_number IS 'Номер курса';
|
||||
COMMENT ON COLUMN academic_calendar_days.date IS 'Дата';
|
||||
COMMENT ON COLUMN academic_calendar_days.week_number IS 'Номер недели в учебном году';
|
||||
COMMENT ON COLUMN academic_calendar_days.day_of_week IS 'День недели ISO';
|
||||
COMMENT ON COLUMN academic_calendar_days.activity_type_id IS 'ID кода активности';
|
||||
COMMENT ON COLUMN academic_calendar_periods.calendar_id IS 'ID календарного учебного графика';
|
||||
COMMENT ON COLUMN academic_calendar_periods.course_number IS 'Номер курса';
|
||||
COMMENT ON COLUMN academic_calendar_periods.start_date IS 'Первая дата периода включительно';
|
||||
COMMENT ON COLUMN academic_calendar_periods.end_date IS 'Последняя дата периода включительно';
|
||||
COMMENT ON COLUMN academic_calendar_periods.activity_type_id IS 'ID кода активности';
|
||||
COMMENT ON FUNCTION calculate_academic_calendar_week_number(DATE, DATE)
|
||||
IS 'Номер недели календарного учебного графика по периодам понедельник–воскресенье';
|
||||
|
||||
@@ -1579,8 +1585,6 @@ BEGIN
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS btree_gist;
|
||||
|
||||
ALTER TABLE time_slots
|
||||
ADD CONSTRAINT chk_time_slots_duration_matches_range
|
||||
CHECK (
|
||||
@@ -1818,7 +1822,7 @@ CREATE TRIGGER trg_academic_years_include_semesters
|
||||
DO $$
|
||||
DECLARE
|
||||
assignment_violations BIGINT;
|
||||
calendar_day_violations BIGINT;
|
||||
calendar_period_violations BIGINT;
|
||||
calendar_subject_violations BIGINT;
|
||||
BEGIN
|
||||
SELECT count(*)
|
||||
@@ -1840,13 +1844,13 @@ BEGIN
|
||||
END NOT BETWEEN 1 AND calendar.course_count;
|
||||
|
||||
SELECT count(*)
|
||||
INTO calendar_day_violations
|
||||
FROM academic_calendar_days calendar_day
|
||||
JOIN academic_calendars calendar ON calendar.id = calendar_day.calendar_id
|
||||
INTO calendar_period_violations
|
||||
FROM academic_calendar_periods calendar_period
|
||||
JOIN academic_calendars calendar ON calendar.id = calendar_period.calendar_id
|
||||
JOIN academic_years academic_year ON academic_year.id = calendar.academic_year_id
|
||||
WHERE calendar_day.course_number > calendar.course_count
|
||||
OR calendar_day.date < academic_year.start_date
|
||||
OR calendar_day.date > academic_year.end_date;
|
||||
WHERE calendar_period.course_number > calendar.course_count
|
||||
OR calendar_period.start_date < academic_year.start_date
|
||||
OR calendar_period.end_date > academic_year.end_date;
|
||||
|
||||
SELECT count(*)
|
||||
INTO calendar_subject_violations
|
||||
@@ -1855,14 +1859,14 @@ BEGIN
|
||||
WHERE calendar_subject.semester_number > calendar.course_count * 2;
|
||||
|
||||
IF assignment_violations > 0
|
||||
OR calendar_day_violations > 0
|
||||
OR calendar_period_violations > 0
|
||||
OR calendar_subject_violations > 0 THEN
|
||||
RAISE EXCEPTION USING
|
||||
ERRCODE = '23514',
|
||||
MESSAGE = format(
|
||||
'Невозможно создать baseline: несовместимые назначения графиков=%s, строки сетки вне измерений=%s, дисциплины вне измерений=%s. Исправьте seed-данные V1 и повторите создание схемы.',
|
||||
'Невозможно создать baseline: несовместимые назначения графиков=%s, периоды активности вне измерений=%s, дисциплины вне измерений=%s. Исправьте seed-данные V1 и повторите создание схемы.',
|
||||
assignment_violations,
|
||||
calendar_day_violations,
|
||||
calendar_period_violations,
|
||||
calendar_subject_violations
|
||||
);
|
||||
END IF;
|
||||
@@ -1990,12 +1994,12 @@ BEGIN
|
||||
|
||||
IF EXISTS (
|
||||
SELECT 1
|
||||
FROM academic_calendar_days calendar_day
|
||||
WHERE calendar_day.calendar_id = OLD.id
|
||||
FROM academic_calendar_periods calendar_period
|
||||
WHERE calendar_period.calendar_id = OLD.id
|
||||
AND (
|
||||
calendar_day.course_number > NEW.course_count
|
||||
OR calendar_day.date < academic_year_start
|
||||
OR calendar_day.date > academic_year_end
|
||||
calendar_period.course_number > NEW.course_count
|
||||
OR calendar_period.start_date < academic_year_start
|
||||
OR calendar_period.end_date > academic_year_end
|
||||
)
|
||||
) THEN
|
||||
RAISE EXCEPTION USING
|
||||
@@ -2059,7 +2063,7 @@ CREATE TRIGGER trg_student_groups_protect_calendar_assignments
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION prevent_incompatible_student_group_change();
|
||||
|
||||
CREATE OR REPLACE FUNCTION enforce_calendar_day_dimensions()
|
||||
CREATE OR REPLACE FUNCTION enforce_calendar_period_dimensions()
|
||||
RETURNS TRIGGER
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
@@ -2078,22 +2082,22 @@ BEGIN
|
||||
IF calendar_course_count IS NOT NULL
|
||||
AND (
|
||||
NEW.course_number > calendar_course_count
|
||||
OR NEW.date < academic_year_start
|
||||
OR NEW.date > academic_year_end
|
||||
OR NEW.start_date < academic_year_start
|
||||
OR NEW.end_date > academic_year_end
|
||||
) THEN
|
||||
RAISE EXCEPTION USING
|
||||
ERRCODE = '23514',
|
||||
MESSAGE = 'Строка сетки выходит за измерения календарного графика';
|
||||
MESSAGE = 'Период активности выходит за измерения календарного графика';
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END $$;
|
||||
|
||||
CREATE TRIGGER trg_calendar_days_dimensions
|
||||
BEFORE INSERT OR UPDATE OF calendar_id, course_number, date
|
||||
ON academic_calendar_days
|
||||
CREATE TRIGGER trg_calendar_periods_dimensions
|
||||
BEFORE INSERT OR UPDATE OF calendar_id, course_number, start_date, end_date
|
||||
ON academic_calendar_periods
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION enforce_calendar_day_dimensions();
|
||||
EXECUTE FUNCTION enforce_calendar_period_dimensions();
|
||||
|
||||
CREATE OR REPLACE FUNCTION enforce_calendar_subject_dimensions()
|
||||
RETURNS TRIGGER
|
||||
@@ -2132,11 +2136,11 @@ BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1
|
||||
FROM academic_calendars calendar
|
||||
JOIN academic_calendar_days calendar_day ON calendar_day.calendar_id = calendar.id
|
||||
JOIN academic_calendar_periods calendar_period ON calendar_period.calendar_id = calendar.id
|
||||
WHERE calendar.academic_year_id = OLD.id
|
||||
AND (
|
||||
calendar_day.date < NEW.start_date
|
||||
OR calendar_day.date > NEW.end_date
|
||||
calendar_period.start_date < NEW.start_date
|
||||
OR calendar_period.end_date > NEW.end_date
|
||||
)
|
||||
) OR EXISTS (
|
||||
SELECT 1
|
||||
|
||||
Reference in New Issue
Block a user