написал обработку количества часов лекций лабораторных и практик по отдельности
This commit is contained in:
@@ -124,11 +124,9 @@ public class ScheduleRuleAdminController {
|
||||
if (request.semesterId() == null) {
|
||||
return "Семестр обязателен";
|
||||
}
|
||||
if (request.activeFromDate() == null) {
|
||||
return "Дата начала правила обязательна";
|
||||
}
|
||||
if (request.totalAcademicHours() == null || request.totalAcademicHours() <= 0) {
|
||||
return "Количество академических часов должно быть больше нуля";
|
||||
String hoursValidationError = validateTypeHours(request);
|
||||
if (hoursValidationError != null) {
|
||||
return hoursValidationError;
|
||||
}
|
||||
if (request.groupIds() == null || request.groupIds().isEmpty()) {
|
||||
return "Нужно выбрать хотя бы одну группу";
|
||||
@@ -151,15 +149,23 @@ public class ScheduleRuleAdminController {
|
||||
|
||||
rule.setSubject(subject);
|
||||
rule.setSemester(semester);
|
||||
rule.setActiveFromDate(request.activeFromDate());
|
||||
rule.setTotalAcademicHours(request.totalAcademicHours());
|
||||
rule.setLectureAcademicHours(request.lectureAcademicHours());
|
||||
rule.setLaboratoryAcademicHours(request.laboratoryAcademicHours());
|
||||
rule.setPracticeAcademicHours(request.practiceAcademicHours());
|
||||
rule.setLectureStartWeek(request.lectureStartWeek());
|
||||
rule.setLaboratoryStartWeek(request.laboratoryStartWeek());
|
||||
rule.setPracticeStartWeek(request.practiceStartWeek());
|
||||
rule.getGroups().clear();
|
||||
rule.getGroups().addAll(groups);
|
||||
|
||||
rule.getSlots().clear();
|
||||
List<ScheduleRuleSlot> slots = new ArrayList<>();
|
||||
for (ScheduleRuleSlotDto slotDto : request.slots()) {
|
||||
rule.getSlots().add(buildSlot(rule, slotDto));
|
||||
slots.add(buildSlot(rule, slotDto));
|
||||
}
|
||||
validateTypeCoverage(rule, slots);
|
||||
|
||||
rule.getSlots().clear();
|
||||
rule.getSlots().addAll(slots);
|
||||
}
|
||||
|
||||
private ScheduleRuleSlot buildSlot(ScheduleRule rule, ScheduleRuleSlotDto slotDto) {
|
||||
@@ -181,6 +187,7 @@ public class ScheduleRuleAdminController {
|
||||
.orElseThrow(() -> new IllegalArgumentException("Аудитория не найдена"));
|
||||
LessonType lessonType = lessonTypesRepository.findById(slotDto.lessonTypeId())
|
||||
.orElseThrow(() -> new IllegalArgumentException("Тип занятия не найден"));
|
||||
ScheduleLessonCategory.fromLessonType(lessonType);
|
||||
if (slotDto.lessonFormat() == null || slotDto.lessonFormat().isBlank()) {
|
||||
throw new IllegalArgumentException("Формат занятия обязателен");
|
||||
}
|
||||
@@ -198,6 +205,65 @@ public class ScheduleRuleAdminController {
|
||||
return slot;
|
||||
}
|
||||
|
||||
private String validateTypeHours(ScheduleRuleDto request) {
|
||||
if (isMissing(request.lectureAcademicHours())
|
||||
|| isMissing(request.laboratoryAcademicHours())
|
||||
|| isMissing(request.practiceAcademicHours())) {
|
||||
return "Укажите количество часов для всех типов занятий";
|
||||
}
|
||||
if (isNegative(request.lectureAcademicHours())
|
||||
|| isNegative(request.laboratoryAcademicHours())
|
||||
|| isNegative(request.practiceAcademicHours())) {
|
||||
return "Количество часов по типам занятий не может быть отрицательным";
|
||||
}
|
||||
if (isInvalidStartWeek(request.lectureStartWeek())
|
||||
|| isInvalidStartWeek(request.laboratoryStartWeek())
|
||||
|| isInvalidStartWeek(request.practiceStartWeek())) {
|
||||
return "Неделя начала занятий должна быть больше нуля";
|
||||
}
|
||||
int totalHours = valueOrZero(request.lectureAcademicHours())
|
||||
+ valueOrZero(request.laboratoryAcademicHours())
|
||||
+ valueOrZero(request.practiceAcademicHours());
|
||||
if (totalHours <= 0) {
|
||||
return "Укажите часы хотя бы для одного типа занятий";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void validateTypeCoverage(ScheduleRule rule, List<ScheduleRuleSlot> slots) {
|
||||
EnumSet<ScheduleLessonCategory> categoriesWithSlots = EnumSet.noneOf(ScheduleLessonCategory.class);
|
||||
for (ScheduleRuleSlot slot : slots) {
|
||||
categoriesWithSlots.add(ScheduleLessonCategory.fromLessonType(slot.getLessonType()));
|
||||
}
|
||||
|
||||
for (ScheduleLessonCategory category : ScheduleLessonCategory.values()) {
|
||||
int hours = rule.academicHoursFor(category);
|
||||
boolean hasSlots = categoriesWithSlots.contains(category);
|
||||
if (hours > 0 && !hasSlots) {
|
||||
throw new IllegalArgumentException("Для типа \"" + category.getDisplayName() + "\" добавьте хотя бы один слот");
|
||||
}
|
||||
if (hours == 0 && hasSlots) {
|
||||
throw new IllegalArgumentException("Для типа \"" + category.getDisplayName() + "\" укажите часы или удалите слоты этого типа");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMissing(Integer value) {
|
||||
return value == null;
|
||||
}
|
||||
|
||||
private boolean isNegative(Integer value) {
|
||||
return value < 0;
|
||||
}
|
||||
|
||||
private boolean isInvalidStartWeek(Integer value) {
|
||||
return value == null || value <= 0;
|
||||
}
|
||||
|
||||
private int valueOrZero(Integer value) {
|
||||
return value == null ? 0 : value;
|
||||
}
|
||||
|
||||
private ScheduleRuleDto toDto(ScheduleRule rule) {
|
||||
List<StudentGroup> groups = rule.getGroups().stream()
|
||||
.sorted(Comparator.comparing(StudentGroup::getName))
|
||||
@@ -217,8 +283,12 @@ public class ScheduleRuleAdminController {
|
||||
rule.getSemester().getId(),
|
||||
rule.getSemester().getAcademicYear().getTitle(),
|
||||
rule.getSemester().getSemesterType(),
|
||||
rule.getActiveFromDate(),
|
||||
rule.getTotalAcademicHours(),
|
||||
rule.getLectureAcademicHours(),
|
||||
rule.getLaboratoryAcademicHours(),
|
||||
rule.getPracticeAcademicHours(),
|
||||
rule.getLectureStartWeek(),
|
||||
rule.getLaboratoryStartWeek(),
|
||||
rule.getPracticeStartWeek(),
|
||||
groups.stream().map(StudentGroup::getId).toList(),
|
||||
groups.stream().map(StudentGroup::getName).toList(),
|
||||
slots
|
||||
|
||||
@@ -31,8 +31,8 @@ public record RenderedLessonDto(
|
||||
List<Long> groupIds,
|
||||
List<String> groupNames,
|
||||
String activityType,
|
||||
Integer totalAcademicHours,
|
||||
Integer consumedAcademicHoursBeforeLesson,
|
||||
Integer remainingAcademicHoursAfterLesson
|
||||
Integer lessonTypeAcademicHours,
|
||||
Integer consumedLessonTypeAcademicHoursBeforeLesson,
|
||||
Integer remainingLessonTypeAcademicHoursAfterLesson
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.magistr.app.dto;
|
||||
|
||||
import com.magistr.app.model.SemesterType;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
public record ScheduleRuleDto(
|
||||
@@ -12,8 +11,12 @@ public record ScheduleRuleDto(
|
||||
Long semesterId,
|
||||
String academicYearTitle,
|
||||
SemesterType semesterType,
|
||||
LocalDate activeFromDate,
|
||||
Integer totalAcademicHours,
|
||||
Integer lectureAcademicHours,
|
||||
Integer laboratoryAcademicHours,
|
||||
Integer practiceAcademicHours,
|
||||
Integer lectureStartWeek,
|
||||
Integer laboratoryStartWeek,
|
||||
Integer practiceStartWeek,
|
||||
List<Long> groupIds,
|
||||
List<String> groupNames,
|
||||
List<ScheduleRuleSlotDto> slots
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.magistr.app.model;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public enum ScheduleLessonCategory {
|
||||
LECTURE("Лекции"),
|
||||
LABORATORY("Лабораторные"),
|
||||
PRACTICE("Практики");
|
||||
|
||||
private final String displayName;
|
||||
|
||||
ScheduleLessonCategory(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public static ScheduleLessonCategory fromLessonType(LessonType lessonType) {
|
||||
if (lessonType == null || lessonType.getLessonType() == null) {
|
||||
throw new IllegalArgumentException("Тип занятия должен быть лекцией, практикой или лабораторной работой");
|
||||
}
|
||||
String name = lessonType.getLessonType().toLowerCase(Locale.forLanguageTag("ru-RU"));
|
||||
if (name.contains("лекц")) {
|
||||
return LECTURE;
|
||||
}
|
||||
if (name.contains("лаб")) {
|
||||
return LABORATORY;
|
||||
}
|
||||
if (name.contains("практ")) {
|
||||
return PRACTICE;
|
||||
}
|
||||
throw new IllegalArgumentException("Тип занятия должен быть лекцией, практикой или лабораторной работой");
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package com.magistr.app.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -22,11 +21,23 @@ public class ScheduleRule {
|
||||
@JoinColumn(name = "semester_id", nullable = false)
|
||||
private Semester semester;
|
||||
|
||||
@Column(name = "active_from_date", nullable = false)
|
||||
private LocalDate activeFromDate;
|
||||
@Column(name = "lecture_academic_hours", nullable = false)
|
||||
private Integer lectureAcademicHours = 0;
|
||||
|
||||
@Column(name = "total_academic_hours", nullable = false)
|
||||
private Integer totalAcademicHours;
|
||||
@Column(name = "laboratory_academic_hours", nullable = false)
|
||||
private Integer laboratoryAcademicHours = 0;
|
||||
|
||||
@Column(name = "practice_academic_hours", nullable = false)
|
||||
private Integer practiceAcademicHours = 0;
|
||||
|
||||
@Column(name = "lecture_start_week", nullable = false)
|
||||
private Integer lectureStartWeek = 1;
|
||||
|
||||
@Column(name = "laboratory_start_week", nullable = false)
|
||||
private Integer laboratoryStartWeek = 1;
|
||||
|
||||
@Column(name = "practice_start_week", nullable = false)
|
||||
private Integer practiceStartWeek = 1;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(
|
||||
@@ -63,20 +74,76 @@ public class ScheduleRule {
|
||||
this.semester = semester;
|
||||
}
|
||||
|
||||
public LocalDate getActiveFromDate() {
|
||||
return activeFromDate;
|
||||
public Integer getLectureAcademicHours() {
|
||||
return lectureAcademicHours;
|
||||
}
|
||||
|
||||
public void setActiveFromDate(LocalDate activeFromDate) {
|
||||
this.activeFromDate = activeFromDate;
|
||||
public void setLectureAcademicHours(Integer lectureAcademicHours) {
|
||||
this.lectureAcademicHours = lectureAcademicHours;
|
||||
}
|
||||
|
||||
public Integer getTotalAcademicHours() {
|
||||
return totalAcademicHours;
|
||||
public Integer getLaboratoryAcademicHours() {
|
||||
return laboratoryAcademicHours;
|
||||
}
|
||||
|
||||
public void setTotalAcademicHours(Integer totalAcademicHours) {
|
||||
this.totalAcademicHours = totalAcademicHours;
|
||||
public void setLaboratoryAcademicHours(Integer laboratoryAcademicHours) {
|
||||
this.laboratoryAcademicHours = laboratoryAcademicHours;
|
||||
}
|
||||
|
||||
public Integer getPracticeAcademicHours() {
|
||||
return practiceAcademicHours;
|
||||
}
|
||||
|
||||
public void setPracticeAcademicHours(Integer practiceAcademicHours) {
|
||||
this.practiceAcademicHours = practiceAcademicHours;
|
||||
}
|
||||
|
||||
public Integer getLectureStartWeek() {
|
||||
return lectureStartWeek;
|
||||
}
|
||||
|
||||
public void setLectureStartWeek(Integer lectureStartWeek) {
|
||||
this.lectureStartWeek = lectureStartWeek;
|
||||
}
|
||||
|
||||
public Integer getLaboratoryStartWeek() {
|
||||
return laboratoryStartWeek;
|
||||
}
|
||||
|
||||
public void setLaboratoryStartWeek(Integer laboratoryStartWeek) {
|
||||
this.laboratoryStartWeek = laboratoryStartWeek;
|
||||
}
|
||||
|
||||
public Integer getPracticeStartWeek() {
|
||||
return practiceStartWeek;
|
||||
}
|
||||
|
||||
public void setPracticeStartWeek(Integer practiceStartWeek) {
|
||||
this.practiceStartWeek = practiceStartWeek;
|
||||
}
|
||||
|
||||
public int academicHoursFor(ScheduleLessonCategory category) {
|
||||
return switch (category) {
|
||||
case LECTURE -> valueOrZero(lectureAcademicHours);
|
||||
case LABORATORY -> valueOrZero(laboratoryAcademicHours);
|
||||
case PRACTICE -> valueOrZero(practiceAcademicHours);
|
||||
};
|
||||
}
|
||||
|
||||
public int startWeekFor(ScheduleLessonCategory category) {
|
||||
return switch (category) {
|
||||
case LECTURE -> valueOrDefault(lectureStartWeek, 1);
|
||||
case LABORATORY -> valueOrDefault(laboratoryStartWeek, 1);
|
||||
case PRACTICE -> valueOrDefault(practiceStartWeek, 1);
|
||||
};
|
||||
}
|
||||
|
||||
private int valueOrZero(Integer value) {
|
||||
return valueOrDefault(value, 0);
|
||||
}
|
||||
|
||||
private int valueOrDefault(Integer value, int defaultValue) {
|
||||
return value == null ? defaultValue : value;
|
||||
}
|
||||
|
||||
public Set<StudentGroup> getGroups() {
|
||||
|
||||
@@ -157,10 +157,9 @@ public class ScheduleGeneratorService {
|
||||
StudentGroup targetGroup,
|
||||
Long targetTeacherId,
|
||||
List<RenderedLessonDto> result) {
|
||||
if (rule.getActiveFromDate() != null && date.isBefore(rule.getActiveFromDate())) {
|
||||
return;
|
||||
}
|
||||
if (rule.getTotalAcademicHours() == null || rule.getTotalAcademicHours() <= 0) {
|
||||
if (rule.getLectureAcademicHours() == null
|
||||
|| rule.getLaboratoryAcademicHours() == null
|
||||
|| rule.getPracticeAcademicHours() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -176,6 +175,7 @@ public class ScheduleGeneratorService {
|
||||
}
|
||||
|
||||
ScheduleParity dateParity = academicDateService.getParity(semester, date);
|
||||
int weekNumber = academicDateService.getWeekNumber(semester, date);
|
||||
int dayOfWeek = date.getDayOfWeek().getValue();
|
||||
List<ScheduleRuleSlot> slots = rule.getSlots().stream()
|
||||
.filter(slot -> Objects.equals(slot.getDayOfWeek(), dayOfWeek))
|
||||
@@ -190,16 +190,28 @@ public class ScheduleGeneratorService {
|
||||
return;
|
||||
}
|
||||
|
||||
int consumedHours = calculateConsumedHoursBeforeDate(rule, targetGroup, date);
|
||||
int weekNumber = academicDateService.getWeekNumber(semester, date);
|
||||
Map<ScheduleLessonCategory, Integer> consumedHoursByCategory = new EnumMap<>(ScheduleLessonCategory.class);
|
||||
|
||||
for (ScheduleRuleSlot slot : slots) {
|
||||
if (consumedHours >= rule.getTotalAcademicHours()) {
|
||||
break;
|
||||
ScheduleLessonCategory category = ScheduleLessonCategory.fromLessonType(slot.getLessonType());
|
||||
if (weekNumber < rule.startWeekFor(category)) {
|
||||
continue;
|
||||
}
|
||||
int remainingAfterLesson = Math.max(0, rule.getTotalAcademicHours() - consumedHours - ACADEMIC_HOURS_PER_SLOT);
|
||||
result.add(toRenderedLesson(rule, slot, date, weekNumber, dateParity, eligibleGroups, consumedHours, remainingAfterLesson));
|
||||
consumedHours += ACADEMIC_HOURS_PER_SLOT;
|
||||
int totalHours = rule.academicHoursFor(category);
|
||||
if (totalHours <= 0) {
|
||||
continue;
|
||||
}
|
||||
int consumedHours = consumedHoursByCategory.computeIfAbsent(
|
||||
category,
|
||||
key -> calculateConsumedHoursBeforeDate(rule, targetGroup, date, key)
|
||||
);
|
||||
if (consumedHours >= totalHours) {
|
||||
continue;
|
||||
}
|
||||
int remainingAfterLesson = Math.max(0, totalHours - consumedHours - ACADEMIC_HOURS_PER_SLOT);
|
||||
result.add(toRenderedLesson(rule, slot, date, weekNumber, dateParity, eligibleGroups,
|
||||
totalHours, consumedHours, remainingAfterLesson));
|
||||
consumedHoursByCategory.put(category, consumedHours + ACADEMIC_HOURS_PER_SLOT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,26 +226,30 @@ public class ScheduleGeneratorService {
|
||||
.toList();
|
||||
}
|
||||
|
||||
private int calculateConsumedHoursBeforeDate(ScheduleRule rule, StudentGroup targetGroup, LocalDate targetDate) {
|
||||
private int calculateConsumedHoursBeforeDate(ScheduleRule rule,
|
||||
StudentGroup targetGroup,
|
||||
LocalDate targetDate,
|
||||
ScheduleLessonCategory category) {
|
||||
Long groupId = targetGroup == null ? null : targetGroup.getId();
|
||||
String cacheKey = rule.getId() + ":" + (groupId == null ? "all" : groupId) + ":" + targetDate;
|
||||
return consumedHoursCache.computeIfAbsent(cacheKey, ignored -> calculateConsumedHours(rule, targetGroup, targetDate));
|
||||
String cacheKey = rule.getId() + ":" + category.name() + ":" + (groupId == null ? "all" : groupId) + ":" + targetDate;
|
||||
return consumedHoursCache.computeIfAbsent(cacheKey,
|
||||
ignored -> calculateConsumedHours(rule, targetGroup, targetDate, category));
|
||||
}
|
||||
|
||||
private int calculateConsumedHours(ScheduleRule rule, StudentGroup targetGroup, LocalDate targetDate) {
|
||||
LocalDate start = rule.getActiveFromDate() == null
|
||||
? rule.getSemester().getStartDate()
|
||||
: rule.getActiveFromDate();
|
||||
if (start.isBefore(rule.getSemester().getStartDate())) {
|
||||
start = rule.getSemester().getStartDate();
|
||||
}
|
||||
|
||||
private int calculateConsumedHours(ScheduleRule rule,
|
||||
StudentGroup targetGroup,
|
||||
LocalDate targetDate,
|
||||
ScheduleLessonCategory category) {
|
||||
int consumed = 0;
|
||||
for (LocalDate date = start; date.isBefore(targetDate); date = date.plusDays(1)) {
|
||||
for (LocalDate date = rule.getSemester().getStartDate(); date.isBefore(targetDate); date = date.plusDays(1)) {
|
||||
Semester semester = rule.getSemester();
|
||||
if (date.isBefore(semester.getStartDate()) || date.isAfter(semester.getEndDate())) {
|
||||
continue;
|
||||
}
|
||||
int weekNumber = academicDateService.getWeekNumber(semester, date);
|
||||
if (weekNumber < rule.startWeekFor(category)) {
|
||||
continue;
|
||||
}
|
||||
if (eligibleGroups(rule, targetGroup, semester, date).isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
@@ -243,9 +259,10 @@ public class ScheduleGeneratorService {
|
||||
long activeSlots = rule.getSlots().stream()
|
||||
.filter(slot -> Objects.equals(slot.getDayOfWeek(), dayOfWeek))
|
||||
.filter(slot -> slot.getParity() == ScheduleParity.BOTH || slot.getParity() == dateParity)
|
||||
.filter(slot -> ScheduleLessonCategory.fromLessonType(slot.getLessonType()) == category)
|
||||
.count();
|
||||
consumed += (int) activeSlots * ACADEMIC_HOURS_PER_SLOT;
|
||||
if (consumed >= rule.getTotalAcademicHours()) {
|
||||
if (consumed >= rule.academicHoursFor(category)) {
|
||||
return consumed;
|
||||
}
|
||||
}
|
||||
@@ -258,6 +275,7 @@ public class ScheduleGeneratorService {
|
||||
int weekNumber,
|
||||
ScheduleParity dateParity,
|
||||
List<StudentGroup> groups,
|
||||
int lessonTypeAcademicHours,
|
||||
int consumedBeforeLesson,
|
||||
int remainingAfterLesson) {
|
||||
TimeSlot timeSlot = resolveEffectiveTimeSlot(slot.getTimeSlot(), date);
|
||||
@@ -290,7 +308,7 @@ public class ScheduleGeneratorService {
|
||||
sortedGroups.stream().map(StudentGroup::getId).toList(),
|
||||
sortedGroups.stream().map(StudentGroup::getName).collect(Collectors.toList()),
|
||||
"Т",
|
||||
rule.getTotalAcademicHours(),
|
||||
lessonTypeAcademicHours,
|
||||
consumedBeforeLesson,
|
||||
remainingAfterLesson
|
||||
);
|
||||
|
||||
@@ -461,9 +461,25 @@ CREATE TABLE IF NOT EXISTS schedule_rules (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
subject_id BIGINT NOT NULL REFERENCES subjects(id),
|
||||
semester_id BIGINT NOT NULL REFERENCES semesters(id) ON DELETE CASCADE,
|
||||
active_from_date DATE NOT NULL,
|
||||
total_academic_hours INT NOT NULL,
|
||||
CONSTRAINT chk_schedule_rules_hours_positive CHECK (total_academic_hours > 0)
|
||||
lecture_academic_hours INT NOT NULL,
|
||||
laboratory_academic_hours INT NOT NULL,
|
||||
practice_academic_hours INT NOT NULL,
|
||||
lecture_start_week INT NOT NULL,
|
||||
laboratory_start_week INT NOT NULL,
|
||||
practice_start_week INT NOT NULL,
|
||||
CONSTRAINT chk_schedule_rules_type_hours_non_negative CHECK (
|
||||
lecture_academic_hours >= 0
|
||||
AND laboratory_academic_hours >= 0
|
||||
AND practice_academic_hours >= 0
|
||||
),
|
||||
CONSTRAINT chk_schedule_rules_has_type_hours CHECK (
|
||||
lecture_academic_hours + laboratory_academic_hours + practice_academic_hours > 0
|
||||
),
|
||||
CONSTRAINT chk_schedule_rules_start_weeks_positive CHECK (
|
||||
lecture_start_week > 0
|
||||
AND laboratory_start_week > 0
|
||||
AND practice_start_week > 0
|
||||
)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_schedule_rules_semester ON schedule_rules(semester_id);
|
||||
@@ -504,28 +520,66 @@ SELECT
|
||||
rule_key,
|
||||
subject_id,
|
||||
semester_id,
|
||||
active_from_date,
|
||||
total_academic_hours
|
||||
lecture_academic_hours,
|
||||
laboratory_academic_hours,
|
||||
practice_academic_hours,
|
||||
lecture_start_week,
|
||||
laboratory_start_week,
|
||||
practice_start_week
|
||||
FROM (
|
||||
SELECT
|
||||
data.rule_key,
|
||||
subj.id AS subject_id,
|
||||
sem.id AS semester_id,
|
||||
data.active_from_date,
|
||||
data.total_academic_hours
|
||||
data.lecture_academic_hours,
|
||||
data.laboratory_academic_hours,
|
||||
data.practice_academic_hours,
|
||||
data.lecture_start_week,
|
||||
data.laboratory_start_week,
|
||||
data.practice_start_week
|
||||
FROM (VALUES
|
||||
('stream_math', 'Высшая математика', '2025-2026', 'spring', DATE '2026-02-02', 72),
|
||||
('ivt_informatics_lab', 'Информатика', '2025-2026', 'spring', DATE '2026-02-02', 72),
|
||||
('ivt_databases_practice', 'Базы данных', '2025-2026', 'spring', DATE '2026-02-02', 72),
|
||||
('ib_philosophy', 'Философия', '2025-2026', 'spring', DATE '2026-02-02', 54)
|
||||
) AS data(rule_key, subject_name, year_title, semester_type, active_from_date, total_academic_hours)
|
||||
('stream_math', 'Высшая математика', '2025-2026', 'spring', 72, 0, 0, 1, 1, 1),
|
||||
('ivt_informatics_lab', 'Информатика', '2025-2026', 'spring', 0, 72, 0, 1, 1, 1),
|
||||
('ivt_databases_practice', 'Базы данных', '2025-2026', 'spring', 0, 0, 72, 1, 1, 1),
|
||||
('ib_philosophy', 'Философия', '2025-2026', 'spring', 54, 0, 0, 1, 1, 1)
|
||||
) AS data(
|
||||
rule_key,
|
||||
subject_name,
|
||||
year_title,
|
||||
semester_type,
|
||||
lecture_academic_hours,
|
||||
laboratory_academic_hours,
|
||||
practice_academic_hours,
|
||||
lecture_start_week,
|
||||
laboratory_start_week,
|
||||
practice_start_week
|
||||
)
|
||||
JOIN subjects subj ON subj.name = data.subject_name
|
||||
JOIN academic_years ay ON ay.title = data.year_title
|
||||
JOIN semesters sem ON sem.academic_year_id = ay.id AND sem.semester_type = data.semester_type
|
||||
) prepared_rules;
|
||||
|
||||
INSERT INTO schedule_rules (id, subject_id, semester_id, active_from_date, total_academic_hours)
|
||||
SELECT schedule_rule_id, subject_id, semester_id, active_from_date, total_academic_hours
|
||||
INSERT INTO schedule_rules (
|
||||
id,
|
||||
subject_id,
|
||||
semester_id,
|
||||
lecture_academic_hours,
|
||||
laboratory_academic_hours,
|
||||
practice_academic_hours,
|
||||
lecture_start_week,
|
||||
laboratory_start_week,
|
||||
practice_start_week
|
||||
)
|
||||
SELECT
|
||||
schedule_rule_id,
|
||||
subject_id,
|
||||
semester_id,
|
||||
lecture_academic_hours,
|
||||
laboratory_academic_hours,
|
||||
practice_academic_hours,
|
||||
lecture_start_week,
|
||||
laboratory_start_week,
|
||||
practice_start_week
|
||||
FROM tmp_default_rules;
|
||||
|
||||
INSERT INTO schedule_rule_groups (schedule_rule_id, group_id)
|
||||
@@ -615,6 +669,12 @@ COMMENT ON TABLE student_group_calendar_assignments IS 'Назначения к
|
||||
COMMENT ON TABLE schedule_rules IS 'Правила динамической генерации расписания';
|
||||
COMMENT ON TABLE schedule_rule_groups IS 'Привязка правил расписания к учебным группам';
|
||||
COMMENT ON TABLE schedule_rule_slots IS 'Слоты проведения занятий внутри правила расписания';
|
||||
COMMENT ON COLUMN schedule_rules.lecture_academic_hours IS 'Лимит академических часов лекций';
|
||||
COMMENT ON COLUMN schedule_rules.laboratory_academic_hours IS 'Лимит академических часов лабораторных работ';
|
||||
COMMENT ON COLUMN schedule_rules.practice_academic_hours IS 'Лимит академических часов практик';
|
||||
COMMENT ON COLUMN schedule_rules.lecture_start_week IS 'Неделя начала лекций в семестре';
|
||||
COMMENT ON COLUMN schedule_rules.laboratory_start_week IS 'Неделя начала лабораторных работ в семестре';
|
||||
COMMENT ON COLUMN schedule_rules.practice_start_week IS 'Неделя начала практик в семестре';
|
||||
|
||||
COMMENT ON TABLE education_forms IS 'Формы обучения';
|
||||
COMMENT ON TABLE subgroups IS 'Подгруппы';
|
||||
|
||||
Reference in New Issue
Block a user