|
@@ -0,0 +1,1354 @@
|
|
|
+Средства разработки
|
|
|
+ В современном мире разработки программного обеспечения создание удобных и эффективных пользовательских интерфейсов становится все более важной задачей. Разработка оконных приложений требует не только умения создавать функциональные возможности, но и обеспечения интуитивно понятного и привлекательного пользовательского опыта.
|
|
|
+ В данном проекте оконное приложение разрабатывается с использованием паттерна проектирования MVVM (Model-View-ViewModel) на языке программирования C# с использованием фреймворка Avalonia. Этот подход позволяет разделять логику приложения, его представление и управление пользовательским интерфейсом, что способствует легкости сопровождения кода, его тестирования и повторного использования, а также легкости работы с разными процессами параллельно группой разработчиков. Как хранилище данных для программы выбрана СУБД PostgreSQL.
|
|
|
+ Для полного понимания темы, давайте рассмотрим основные понятия:
|
|
|
+ MVVM (Model-View-ViewModel): Этот паттерн проектирования представляет собой разделение пользовательского интерфейса на три ключевых компонента: Модель (Model), Представление (View) и Модель представления (ViewModel). Модель представления служит связующим звеном между моделью данных и пользовательским интерфейсом, обеспечивая отделение логики представления от бизнес-логики.
|
|
|
+ Avalonia: Это кроссплатформенный фреймворк для разработки графических пользовательских интерфейсов (GUI) на языках программирования C# и XAML. Avalonia позволяет создавать красивые и отзывчивые приложения, которые могут работать на различных операционных системах, включая Windows, macOS и Linux.
|
|
|
+ PostgreSQL - мощная объектно-реляционная система управления базами данных (СУБД), которая обеспечивает надежное хранение и эффективное управление данными. Она широко используется в различных приложениях благодаря своей открытой природе, расширяемости и поддержке стандартов SQL. В нашей работе мы будем использовать PostgreSQL в качестве хранилища данных для наших приложений, чтобы обеспечить сохранность и доступность данных пользователя.
|
|
|
+Models
|
|
|
+ Модели в паттерне MVVM представляют собой компоненты, которые отвечают за представление бизнес-логики и управление данными. Они являются моделями данных приложения, которые предоставляют информацию и методы для их обработки и манипулирования.
|
|
|
+ Для ИС <<Учебный центр>> разработана 19 моделей, 14 из которых являются отражениями таблиц базы данных, а остальные необходимы для дополнительных целей. Программный код моделей представлен в листингах Приложения В. Опишем каждую из моделей подробнее.
|
|
|
+Таблица 1 - Модели ИС <<Учебная часть>>
|
|
|
+№
|
|
|
+Название
|
|
|
+Обозначение
|
|
|
+Назначение
|
|
|
+Дополнительные классы
|
|
|
+
|
|
|
+AttendanceInfo
|
|
|
+Информация о посещаемости
|
|
|
+Краткая информация об успеваемости для вывода данных в контроллер элемент в представлении
|
|
|
+
|
|
|
+Converter
|
|
|
+Конвертер
|
|
|
+Предоставляет статичные методы для чтения и записи csv-файлов
|
|
|
+
|
|
|
+MarksInfo
|
|
|
+Информация об оценках
|
|
|
+Краткая информация об оценках для вывода данных в контроллер элемент в представлении
|
|
|
+
|
|
|
+Schekaleva31pContext
|
|
|
+Контекст БД
|
|
|
+Класс, реализующий связь программы с базой данных
|
|
|
+Таблицы базы данных
|
|
|
+
|
|
|
+Attendance
|
|
|
+Посещаемость
|
|
|
+Хранение информации о студенте, расписании (дата, дисциплина, преподаватель) и пометка присутствовал/не присутствовал на занятии
|
|
|
+
|
|
|
+Building
|
|
|
+Корпус
|
|
|
+Хранение информации об адресе учебного корпуса, заведующем (навигация на таблицу пользователей) и ссылка на список расписания для данного корпуса
|
|
|
+
|
|
|
+Department
|
|
|
+Факультет
|
|
|
+Название факультета, ссылки на список специальностей факультета, дисциплин и преподавателей
|
|
|
+
|
|
|
+Discipline
|
|
|
+Дисциплина
|
|
|
+Название дисциплины, факультет, на котором она читается, количество уделяемых академических часов и ссылка на список <<Дисциплины преподавателей>>, определяющий, какие преподаватели ведут данную дисциплину
|
|
|
+
|
|
|
+Group
|
|
|
+Группа
|
|
|
+Название группы, специальность, дата основания группы (когда студенты начались учиться), ссылка на список дисциплин группы, список студентов группы
|
|
|
+
|
|
|
+Groupdiscipline
|
|
|
+Дисциплина группы
|
|
|
+Номер семестра, дисциплина преподавателя, группа, ссылка на список оценок (студент получил оценку за дисциплину, которая ведется в его группе), список расписаний (в сетке расписания для преподавателей и студентов указывается дисциплина и кто с кем ее проводит)
|
|
|
+
|
|
|
+Role
|
|
|
+Роль
|
|
|
+Название роли (преподаватель или студент) и ссылка на список всех пользователей по роли
|
|
|
+
|
|
|
+Specialty
|
|
|
+Специальность
|
|
|
+Название специальность, ее факультет и ссылка на список групп специальности
|
|
|
+
|
|
|
+Student
|
|
|
+Студент
|
|
|
+Информация о пользователе (личные данные), его группа, ссылки на список успеваемости студента и его оценок
|
|
|
+
|
|
|
+Studentgrade
|
|
|
+Оценка студента
|
|
|
+Информация о студенте, дисциплине группы, даты оценки, самой оценке и названии работы
|
|
|
+
|
|
|
+Teacher
|
|
|
+Преподаватель
|
|
|
+Информация о пользователе (личные данные), его факультет и ссылка на список дисциплин преподавателя
|
|
|
+
|
|
|
+Teachersdiscipline
|
|
|
+Дисциплина преподавателя
|
|
|
+Информация о преподавателе, его дисциплине и ссылка на список дисциплин группы, которым соответствует данный объект (какую дисциплину группы какой преподаватель ведет)
|
|
|
+
|
|
|
+Timetable
|
|
|
+Расписание
|
|
|
+Информация о дате занятия, номере занятия (паре), дисциплине группы, корпусе и ссылка на список посещаемости студентами этого занятия сетки расписания
|
|
|
+
|
|
|
+User
|
|
|
+Пользователь
|
|
|
+Личные данные о пользователе: ФИО, почта, номер телефона, дата рождения, пароль, роль пользователя в системе
|
|
|
+
|
|
|
+ViewModels
|
|
|
+ ViewModel (Модель представления) представляет собой прослойку между пользовательским интерфейсом (View) и моделью данных (Model). ViewModel обеспечивает связь между этими двумя компонентами, предоставляя данные и методы, необходимые для отображения информации на пользовательском интерфейсе и обработки пользовательских действий.
|
|
|
+ Для ИС <<Учебная часть>> разработано 7 моделей представления, одна из которых главная и содержит объекты остальных классов, отвечающих за функционал в рамках одной страницы. Программный код моделей представления изложен в листингах Приложения В. Опишем каждую из моделей представления подробнее:
|
|
|
+ MainWindowViewModel
|
|
|
+ Главная модель представление, которая вызывает все остальные при совершении команд перехода на другую страницу, при этом меняет пользовательский контроллер на контроллер нового представления и инициализирует соответствующую ему ViewModel.
|
|
|
+ Основные поля:
|
|
|
+ dbConnect - контекст соединения с базой данных, из которого можно получать информацию их хранилища, обновлять и добавлять новую
|
|
|
+ UserControl uc - пользовательский контроллер, который биндится к главному окну, и с помощью которого меняются страницы - после присваивания этой переменной нового значения отображается новое представление
|
|
|
+ User? user - текущий пользователь, который открыл сеанс работы с программой
|
|
|
+ string message - поле, использующееся для отображения сообщений пользователю в случае ошибок или пустой информации основного контента
|
|
|
+ Основные методы:
|
|
|
+ bool AuthorizationSuccess() - метод сверяет логин и пароль с данными бд, и если данный пользователь существует, возвращает значение True
|
|
|
+ void LoadHomePage() - если функция AuthorizationSuccess() возвратила успех, то выбирается и загружается новый пользовательский контроллер - в зависимости от роли пользователя загружается профиль либо студента, либо преподавателя. Данный метод загружает меню программы, из которого возможны переходы во все остальные окна
|
|
|
+ void LoadUserProfile() - метод перехода в личный кабинет пользователя
|
|
|
+ void LoadTimetablePage() - метод, который инициализирует новую ViewModel для расписания и загружает страницу расписания, переводя ее в uc
|
|
|
+ void LoadDisciplinePage() - метод, который инициализирует новую ViewModel для дисциплин и загружает страницу дисциплин, переводя ее в uc
|
|
|
+ void LoadAttendancePage() - метод, который инициализирует новую ViewModel для посещаемости и загружает страницу посещаемости, переводя ее в uc
|
|
|
+ void LoadEvaluationStudentPage() - метод, который инициализирует новую ViewModel для успеваемости студента и загружает страницу оценок, переводя ее в uc.
|
|
|
+ AuthorizationViewModel
|
|
|
+ Хранит два свойства: логин и пароль, которые при процессе авторизация сверяются с имеющимися в базе данных.
|
|
|
+ UserProfileViewModel
|
|
|
+ Хранит следующую информацию о личных данных авторизированного пользователя:
|
|
|
+ Connect - контекст соединения с базой данных, из которого можно получать информацию их хранилища, обновлять и добавлять новую
|
|
|
+ User User - текущий пользователь, который открыл сеанс работы с программой
|
|
|
+ string FirstName - имя пользователя
|
|
|
+ string LastName - фамилия пользователя
|
|
|
+ string DateBirht - дата рождения пользователя
|
|
|
+ string Group - группа пользователя, если он студент
|
|
|
+ List<string> Groups - список всех групп, отображаемых в comboBox в личном кабинете студента
|
|
|
+ List<string> Disciplines - список дисциплин пользователя, если он преподаватель
|
|
|
+ string Discipline - первая видимая дисциплина преподавателя
|
|
|
+ Имеет конструктор, который принимает аргументы: контекст базы данных, логин пользователя (почта).
|
|
|
+ TimetableViewModel
|
|
|
+ Хранит следующую информацию о расписании:
|
|
|
+ Connect - контекст соединения с базой данных, из которого можно получать информацию их хранилища, обновлять и добавлять новую
|
|
|
+ List<Timetable>? Timetable - список полученного расписания, после применения всех фильтров
|
|
|
+ List<string> TeachersList - список преподавателей, для выбора расписания
|
|
|
+ List<string> GroupsList - список групп, для выбора расписания
|
|
|
+ string ClassDate - дата занятий
|
|
|
+ List<string> Options - список опций (преподаватель или группа)
|
|
|
+ string SelectedOption - выбранная пользователем опция
|
|
|
+ string OptionValue - выбранное пользователем значение (конкретный преподаватель или группа)
|
|
|
+ List<string> Values - список значений, из которых пользователь выбирает
|
|
|
+ Методы:
|
|
|
+ void NewTimetable() - создание нового расписания по отмеченным пользователем фильтрам
|
|
|
+ List<string> NewValues(string selectedOption) - получение новых значений по выбранной опции (список преподавателей если выбран <<Преподаватель>>, список групп если выбрана <<Группа>>)
|
|
|
+ virtual void OnPropertyChanged(string propertyName) - сообщение о том, что некоторое свойство изменено, что изменяет значение зависимых полей и перерисовывает представление
|
|
|
+Данная модель представления имеет конструктор, который принимает контекст базы данных.
|
|
|
+ DisciplineViewModel
|
|
|
+ Хранит следующую информацию о дисциплинах:
|
|
|
+ Connect - контекст соединения с базой данных, из которого можно получать информацию их хранилища, обновлять и добавлять новую
|
|
|
+ List<Discipline>? Disciplines - список дисциплин, полученный после применения всех фильтров
|
|
|
+ List<string> Options - список опция (преподаватель и группа)
|
|
|
+ string SelectedOption - выбранная пользователем опция
|
|
|
+ string OptionValue - выбранное пользователем значение
|
|
|
+ List<string> Values - список значений, который определяется при изменение выбранной опции
|
|
|
+ Методы:
|
|
|
+ void OnPropertyChanged(string propertyName) - сообщение о том, что некоторое свойство изменено, что изменяет значение зависимых полей и перерисовывает представление
|
|
|
+ void NewDisciplines() - получение нового списка дисциплин по выбранных опции и значении
|
|
|
+ List<string> NewValues(string selectedOption) - получение списка новых значений при изменении опции
|
|
|
+Данная модель представления имеет конструктор, который принимает контекст базы данных.
|
|
|
+ AttendanceViewModel
|
|
|
+ Хранит информацию о посещаемости студентов, имеет конструктор, который принимает контекст базы данных, и имеет следующие поля и свойства:
|
|
|
+ Connect - контекст соединения с базой данных, из которого можно получать информацию их хранилища, обновлять и добавлять новую
|
|
|
+ List<string> Options - список опций для просмотра посещаемости (группа или дисциплина)
|
|
|
+ string SelectedOption - выбранная пользователем опция
|
|
|
+ List<string> secondOptions - второй список опций, в котором выбирается конкретные дисциплина или группа
|
|
|
+ string SecondSelectedOption - вторая выбранная пользователем опция
|
|
|
+ List<string> Values - список значений, который формируется при выборе второй опции: для группы - это список студентов, для дисциплин - список групп
|
|
|
+ string OptionValue - выбранное пользователем последнее значение
|
|
|
+ string ParameterName - название параметра - имя, которое указывается над столбцом значений в представлении посещаемости
|
|
|
+ List<AttendanceInfo> AttendanceTable - таблица посещаемости, сформированная после применения всех фильтров
|
|
|
+ Методы:
|
|
|
+ void OnPropertyChanged(string propertyName) - сообщение о том, что некоторое свойство изменено, что изменяет значение зависимых полей и перерисовывает представление
|
|
|
+ List<string> NewOption() - метол для получения вторых опций при изменении выбранной первой опции
|
|
|
+ List<string> NewValues() - метод для получения списка значений при изменения второй выбранной опции
|
|
|
+ void GetNewAttendance() - метод получения новой таблицы посещаемости, который ставит значение параметру и заполняет данные в соответствии с выбранными опциями.
|
|
|
+ EvaluationStudentViewModel
|
|
|
+ Данная модель представления имеет конструктор, который принимает контекст базы данных и ID пользователя, который вошел в систему, т.е. он сможет видеть только свои оценки.
|
|
|
+ Хранит информацию об оценках пользователя и имеет следующие свойства и поля:
|
|
|
+ Connect - контекст соединения с базой данных, из которого можно получать информацию их хранилища, обновлять и добавлять новую
|
|
|
+ Student student - студент, оценки которого показываются (открыт его аккаунт)
|
|
|
+ List<string> Options - список опций (дисциплины, по которым можно смотреть оценки)
|
|
|
+ string SelectedOption - выбранная пользователем опция
|
|
|
+ List<MarksInfo> MarksTable - таблица, которая хранит оценки и даты их получения за выбранную дисциплину у авторизовавшегося студента
|
|
|
+Методы:
|
|
|
+ void OnPropertyChanged(string propertyName) - сообщение о том, что некоторое свойство изменено, что изменяет значение зависимых полей и перерисовывает представление
|
|
|
+ List<string> StudentOptions() - получения дисциплин, в которых участвует данный студент
|
|
|
+ void GetMarks() - получение нового списка оценок по выбранной дисциплине
|
|
|
+ void WriteMarks() - вывод полученного списка MarksTable в csv-файл.
|
|
|
+Views
|
|
|
+ View (Представление) представляет собой пользовательский интерфейс приложения, который отображает данные и позволяет пользователю взаимодействовать с ними. View отвечает за отображение данных, реагирование на пользовательские действия и обновление интерфейса в соответствии с изменениями данных.
|
|
|
+ Для ИС <<Учебная часть>> разработано 9 представлений, одно из которых является главным и служит хранилищем контента остальных представлений. Одно представление является одной страницей, которая отображает блок действий и информации, логически относящейся к данному фрагменту программы. Опишем каждую из моделей подробнее:
|
|
|
+Таблица 2 - Представления ИС <<Учебная часть>>
|
|
|
+№
|
|
|
+Название
|
|
|
+Обозначение
|
|
|
+Действия и информация
|
|
|
+
|
|
|
+AttendancePage
|
|
|
+Страница посещаемости
|
|
|
+Имеет три фильтра:
|
|
|
+ "Группа"/"дисциплина"
|
|
|
+ Выбор группы/дисциплины
|
|
|
+ Выбор всей группы или студента/ всех группы на дисциплине или одной группы
|
|
|
+После чего пользователь нажимает кнопку <<Показать>> и получается фильтрованную посещаемость.
|
|
|
+Для перехода в главное меню нажать иконку приложения вверху слева
|
|
|
+
|
|
|
+AuthorizationPage
|
|
|
+Станица авторизации
|
|
|
+Имеется два поля для ввода: логин и пароль, пользователь нажимает на <<войти>> и переходит в свой профиль, если данные не корректны, выводится соответствующая ошибка
|
|
|
+
|
|
|
+DisciplinesPage
|
|
|
+Страница дисциплин
|
|
|
+Имеет два фильтра:
|
|
|
+ "Группа"/"преподаватель"
|
|
|
+ Выбор группы/преподавателя
|
|
|
+После чего пользователь нажимает кнопку <<Показать>> и получается фильтрованные дисциплины.
|
|
|
+Для перехода в главное меню нажать иконку приложения вверху слева
|
|
|
+
|
|
|
+EvaluationStudent
|
|
|
+Page
|
|
|
+Страница оценок пользователя
|
|
|
+Данная страница доступна в аккаунте пользователя и изначально показывает лишь те оценки, которые получал этот пользователь, имеет фильтрацию по дисциплинам, показывает оценки и дату, когда они были поставлены. Также есть кнопка <<печать>>, которая позволяет вывести список оценок в csv-файл.
|
|
|
+
|
|
|
+ProfileStudent
|
|
|
+Профиль студента
|
|
|
+Быстрый доступ к страницам: расписание, оценки, дисциплины. И редактирование информации о пользователе: ФИО, дата рождения. Группу пользователь сам себе изменять не может.
|
|
|
+Для перехода в главное меню нажать иконку приложения вверху слева
|
|
|
+
|
|
|
+ProfileTeacher
|
|
|
+Профиль преподавателя
|
|
|
+Быстрый доступ к страницам: расписание, оценки, дисциплины, посещаемость студентов. И редактирование информации о пользователе: ФИО, дата рождения. Дисциплины пользователь сам себе изменять не может.
|
|
|
+Для перехода в главное меню нажать иконку приложения вверху слева
|
|
|
+
|
|
|
+TimeTablePage
|
|
|
+Страница расписания
|
|
|
+Имеет три фильтра:
|
|
|
+ "Группа"/"преподаватель"
|
|
|
+ Выбор группы/преподавателя
|
|
|
+ Выбор даты
|
|
|
+После чего пользователь нажимает кнопку <<Показать>> и получается день расписания.
|
|
|
+Для перехода в главное меню нажать иконку приложения вверху слева
|
|
|
+
|
|
|
+Menu
|
|
|
+Меню
|
|
|
+Список всех страниц, на которые может переходить пользователь: профиль, дисциплины, оценки, посещаемость.
|
|
|
+
|
|
|
+MainWindow
|
|
|
+Главное окно
|
|
|
+С помощью контроллера контента хранит в себе каждую из страниц и переходит из одной на другую
|
|
|
+
|
|
|
+ПРИЛОЖЕНИЕ В. ПРОГРАММНЫЙ КОД МОДУЛЕЙ
|
|
|
+Листинг 1 - Модель <<Посещаемость>>
|
|
|
+namespace EducationDepartment.Models;
|
|
|
+
|
|
|
+public partial class Attendance
|
|
|
+{
|
|
|
+ public int Id { get; set; }
|
|
|
+
|
|
|
+ public int TimetableId { get; set; }
|
|
|
+
|
|
|
+ public int StudentId { get; set; }
|
|
|
+
|
|
|
+ public bool Attended { get; set; }
|
|
|
+
|
|
|
+ public virtual Student Student { get; set; } = null!;
|
|
|
+
|
|
|
+ public virtual Timetable Timetable { get; set; } = null!;
|
|
|
+}
|
|
|
+Листинг 2 - Модель <<Информация о посещаемости>>
|
|
|
+namespace EducationDepartment.Models
|
|
|
+{
|
|
|
+ public class AttendanceInfo
|
|
|
+ {
|
|
|
+ public AttendanceInfo(string value, double percentage)
|
|
|
+ {
|
|
|
+ Value = value;
|
|
|
+ Percentage = percentage;
|
|
|
+ }
|
|
|
+ //discipline, group, student
|
|
|
+ public string Value { get; set; }
|
|
|
+ //attendance %
|
|
|
+ public double Percentage { get; set; }
|
|
|
+ }
|
|
|
+}
|
|
|
+Листинг 3 - Модель <<Корпусы>>
|
|
|
+namespace EducationDepartment.Models;
|
|
|
+
|
|
|
+public partial class Building
|
|
|
+{
|
|
|
+ public int Id { get; set; }
|
|
|
+
|
|
|
+ public int Mgr { get; set; }
|
|
|
+
|
|
|
+ public string Address { get; set; } = null!;
|
|
|
+
|
|
|
+ public virtual User MgrNavigation { get; set; } = null!;
|
|
|
+
|
|
|
+ public virtual ICollection<Timetable> Timetables { get; set; } = new List<Timetable>();
|
|
|
+}
|
|
|
+Листинг 4 - Модель <<Конвертер>>
|
|
|
+namespace EducationDepartment.Models
|
|
|
+{
|
|
|
+ public class Converter
|
|
|
+ {
|
|
|
+ public static bool WriteCsv<T>(List<T> objects, string path)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ var config = new CsvConfiguration(CultureInfo.CurrentCulture)
|
|
|
+ {
|
|
|
+ HasHeaderRecord = true,
|
|
|
+ Delimiter = ";"
|
|
|
+ };
|
|
|
+
|
|
|
+ using (var writer = new StreamWriter(path))
|
|
|
+ using (var csv = new CsvWriter(writer, config))
|
|
|
+ {
|
|
|
+ csv.WriteHeader<T>();
|
|
|
+ csv.NextRecord();
|
|
|
+ foreach (var record in objects)
|
|
|
+ {
|
|
|
+ csv.WriteRecord(record);
|
|
|
+ csv.NextRecord();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ Console.WriteLine($"Исключение: {ex.Message}\n" +
|
|
|
+ $"Метод: {ex.TargetSite}\n" +
|
|
|
+ $"Трассировка стека: {ex.StackTrace}");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static List<T>? ReadCsv<T>(string path)
|
|
|
+ {
|
|
|
+ var config = new CsvConfiguration(CultureInfo.CurrentCulture)
|
|
|
+ {
|
|
|
+ HasHeaderRecord = true,
|
|
|
+ Delimiter = ";"
|
|
|
+ };
|
|
|
+ try
|
|
|
+ {
|
|
|
+ using (var reader = new StreamReader(path))
|
|
|
+ using (var csv = new CsvReader(reader, config))
|
|
|
+ {
|
|
|
+ return csv.GetRecords<T>().ToList();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ Console.WriteLine($"Исключение: {ex.Message}\n" +
|
|
|
+ $"Метод: {ex.TargetSite}\n" +
|
|
|
+ $"Трассировка стека: {ex.StackTrace}");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+Листинг 5 - Модель <<Факультет>>
|
|
|
+namespace EducationDepartment.Models;
|
|
|
+
|
|
|
+public partial class Department
|
|
|
+{
|
|
|
+ public int Id { get; set; }
|
|
|
+
|
|
|
+ public string Name { get; set; } = null!;
|
|
|
+
|
|
|
+ public virtual ICollection<Discipline> Disciplines { get; set; } = new List<Discipline>();
|
|
|
+
|
|
|
+ public virtual ICollection<Specialty> Specialties { get; set; } = new List<Specialty>();
|
|
|
+
|
|
|
+ public virtual ICollection<Teacher> Teachers { get; set; } = new List<Teacher>();
|
|
|
+}
|
|
|
+
|
|
|
+Листинг 6 - Модель <<Дисциплина>>
|
|
|
+namespace EducationDepartment.Models;
|
|
|
+
|
|
|
+public partial class Discipline
|
|
|
+{
|
|
|
+ public int Id { get; set; }
|
|
|
+
|
|
|
+ public string Name { get; set; } = null!;
|
|
|
+
|
|
|
+ public int DepartmentId { get; set; }
|
|
|
+
|
|
|
+ public int AcademicHours { get; set; }
|
|
|
+
|
|
|
+ public virtual Department Department { get; set; } = null!;
|
|
|
+
|
|
|
+ public virtual ICollection<Teachersdiscipline> Teachersdisciplines { get; set; } = new List<Teachersdiscipline>();
|
|
|
+}
|
|
|
+Листинг 7 - Модель <<Группа>>
|
|
|
+namespace EducationDepartment.Models;
|
|
|
+
|
|
|
+public partial class Group
|
|
|
+{
|
|
|
+ [Ignore]
|
|
|
+ public int Id { get; set; }
|
|
|
+ [Ignore]
|
|
|
+ public int IdSpecialty { get; set; }
|
|
|
+ [Ignore]
|
|
|
+ public DateOnly StartDate { get; set; }
|
|
|
+ [Name("Группа")]
|
|
|
+ public string Name { get; set; } = null!;
|
|
|
+ [Ignore]
|
|
|
+ public virtual ICollection<Groupdiscipline> Groupdisciplines { get; set; } = new List<Groupdiscipline>();
|
|
|
+ [Ignore]
|
|
|
+ public virtual Specialty IdSpecialtyNavigation { get; set; } = null!;
|
|
|
+ [Ignore]
|
|
|
+ public virtual ICollection<Student> Students { get; set; } = new List<Student>();
|
|
|
+}
|
|
|
+
|
|
|
+Листинг 8 - Модель <<Дисциплина группы>>
|
|
|
+namespace EducationDepartment.Models;
|
|
|
+
|
|
|
+public partial class Groupdiscipline
|
|
|
+{
|
|
|
+ public int Id { get; set; }
|
|
|
+
|
|
|
+ public int? Semester { get; set; }
|
|
|
+
|
|
|
+ public int TeacherDisciplineId { get; set; }
|
|
|
+
|
|
|
+ public int GroupId { get; set; }
|
|
|
+
|
|
|
+ public virtual Group Group { get; set; } = null!;
|
|
|
+
|
|
|
+ public virtual ICollection<Studentgrade> Studentgrades { get; set; } = new List<Studentgrade>();
|
|
|
+
|
|
|
+ public virtual Teachersdiscipline TeacherDiscipline { get; set; } = null!;
|
|
|
+
|
|
|
+ public virtual ICollection<Timetable> Timetables { get; set; } = new List<Timetable>();
|
|
|
+}
|
|
|
+Листинг 9 - Модель <<Информация об оценках>>
|
|
|
+namespace EducationDepartment.Models
|
|
|
+{
|
|
|
+ public class MarksInfo
|
|
|
+ {
|
|
|
+ public MarksInfo(string markDate, double markValue)
|
|
|
+ {
|
|
|
+ MarkDate = markDate;
|
|
|
+ MarkValue = markValue;
|
|
|
+ }
|
|
|
+ [Name("дата")]
|
|
|
+ public string MarkDate { get; set; }
|
|
|
+ [Name("оценка")]
|
|
|
+ public double MarkValue { get; set; }
|
|
|
+ }
|
|
|
+}
|
|
|
+Листинг 10 - Модель <<Роль>>
|
|
|
+namespace EducationDepartment.Models;
|
|
|
+
|
|
|
+public partial class Role
|
|
|
+{
|
|
|
+ public int Id { get; set; }
|
|
|
+
|
|
|
+ public string? Name { get; set; }
|
|
|
+
|
|
|
+ public virtual ICollection<User> Users { get; set; } = new List<User>();
|
|
|
+}
|
|
|
+Листинг 11 - Модель <<Контекст базы данных>>
|
|
|
+public partial class Schekaleva31pContext : DbContext
|
|
|
+{
|
|
|
+ public Schekaleva31pContext()
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ public Schekaleva31pContext(DbContextOptions<Schekaleva31pContext> options)
|
|
|
+ : base(options)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ public virtual DbSet<Attendance> Attendances { get; set; }
|
|
|
+
|
|
|
+ public virtual DbSet<Building> Buildings { get; set; }
|
|
|
+
|
|
|
+ public virtual DbSet<Department> Departments { get; set; }
|
|
|
+
|
|
|
+ public virtual DbSet<Discipline> Disciplines { get; set; }
|
|
|
+
|
|
|
+ public virtual DbSet<Group> Groups { get; set; }
|
|
|
+
|
|
|
+ public virtual DbSet<Groupdiscipline> Groupdisciplines { get; set; }
|
|
|
+
|
|
|
+ public virtual DbSet<Role> Roles { get; set; }
|
|
|
+
|
|
|
+ public virtual DbSet<Specialty> Specialties { get; set; }
|
|
|
+
|
|
|
+ public virtual DbSet<Student> Students { get; set; }
|
|
|
+
|
|
|
+ public virtual DbSet<Studentgrade> Studentgrades { get; set; }
|
|
|
+
|
|
|
+ public virtual DbSet<Teacher> Teachers { get; set; }
|
|
|
+
|
|
|
+ public virtual DbSet<Teachersdiscipline> Teachersdisciplines { get; set; }
|
|
|
+
|
|
|
+ public virtual DbSet<Timetable> Timetables { get; set; }
|
|
|
+
|
|
|
+ public virtual DbSet<User> Users { get; set; }
|
|
|
+
|
|
|
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
|
|
+ //local
|
|
|
+ //=> optionsBuilder.UseNpgsql("Host=edu.pg.ngknn.local;Port=5432;Database=schekaleva31p;Username=31P;Password=12345");
|
|
|
+ //global
|
|
|
+ => optionsBuilder.UseNpgsql("Host=ngknn.ru;Port=5442;Database=schekaleva31p;Username=31P;Password=12345");
|
|
|
+protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
|
+ {
|
|
|
+ modelBuilder.Entity<Attendance>(entity =>
|
|
|
+ {
|
|
|
+ entity.HasKey(e => e.Id).HasName("attendance_pkey");
|
|
|
+
|
|
|
+ entity.ToTable("attendance");
|
|
|
+
|
|
|
+ entity.Property(e => e.Id).HasColumnName("id");
|
|
|
+ entity.Property(e => e.Attended).HasColumnName("attended");
|
|
|
+ entity.Property(e => e.StudentId).HasColumnName("student_id");
|
|
|
+ entity.Property(e => e.TimetableId).HasColumnName("timetable_id");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.Student).WithMany(p => p.Attendances)
|
|
|
+ .HasForeignKey(d => d.StudentId)
|
|
|
+ .OnDelete(DeleteBehavior.ClientSetNull)
|
|
|
+ .HasConstraintName("attendance_student_id_fkey");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.Timetable).WithMany(p => p.Attendances)
|
|
|
+ .HasForeignKey(d => d.TimetableId)
|
|
|
+ .OnDelete(DeleteBehavior.ClientSetNull)
|
|
|
+ .HasConstraintName("attendance_timetable_id_fkey");
|
|
|
+ });
|
|
|
+
|
|
|
+ modelBuilder.Entity<Building>(entity =>
|
|
|
+ {
|
|
|
+ entity.HasKey(e => e.Id).HasName("buildings_pkey");
|
|
|
+
|
|
|
+ entity.ToTable("buildings");
|
|
|
+
|
|
|
+ entity.Property(e => e.Id).HasColumnName("id");
|
|
|
+ entity.Property(e => e.Address)
|
|
|
+ .HasMaxLength(70)
|
|
|
+ .HasColumnName("address");
|
|
|
+ entity.Property(e => e.Mgr).HasColumnName("mgr");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.MgrNavigation).WithMany(p => p.Buildings)
|
|
|
+ .HasForeignKey(d => d.Mgr)
|
|
|
+ .OnDelete(DeleteBehavior.ClientSetNull)
|
|
|
+ .HasConstraintName("buildings_mgr_fkey");
|
|
|
+ });
|
|
|
+
|
|
|
+ modelBuilder.Entity<Department>(entity =>
|
|
|
+ {
|
|
|
+ entity.HasKey(e => e.Id).HasName("departments_pkey");
|
|
|
+
|
|
|
+ entity.ToTable("departments");
|
|
|
+
|
|
|
+ entity.HasIndex(e => e.Name, "departments_name_key").IsUnique();
|
|
|
+
|
|
|
+ entity.Property(e => e.Id).HasColumnName("id");
|
|
|
+ entity.Property(e => e.Name)
|
|
|
+ .HasMaxLength(70)
|
|
|
+ .HasColumnName("name");
|
|
|
+ });
|
|
|
+
|
|
|
+ modelBuilder.Entity<Discipline>(entity =>
|
|
|
+ {
|
|
|
+ entity.HasKey(e => e.Id).HasName("disciplines_pkey");
|
|
|
+
|
|
|
+ entity.ToTable("disciplines");
|
|
|
+
|
|
|
+ entity.Property(e => e.Id).HasColumnName("id");
|
|
|
+ entity.Property(e => e.AcademicHours).HasColumnName("academic_hours");
|
|
|
+ entity.Property(e => e.DepartmentId).HasColumnName("department_id");
|
|
|
+ entity.Property(e => e.Name)
|
|
|
+ .HasMaxLength(60)
|
|
|
+ .HasColumnName("name");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.Department).WithMany(p => p.Disciplines)
|
|
|
+ .HasForeignKey(d => d.DepartmentId)
|
|
|
+ .OnDelete(DeleteBehavior.ClientSetNull)
|
|
|
+ .HasConstraintName("disciplines_department_id_fkey");
|
|
|
+ });
|
|
|
+
|
|
|
+ modelBuilder.Entity<Group>(entity =>
|
|
|
+ {
|
|
|
+ entity.HasKey(e => e.Id).HasName("Groups_pkey");
|
|
|
+
|
|
|
+ entity.Property(e => e.Id).HasColumnName("id");
|
|
|
+ entity.Property(e => e.IdSpecialty).HasColumnName("id_specialty");
|
|
|
+ entity.Property(e => e.Name)
|
|
|
+ .HasMaxLength(5)
|
|
|
+ .HasColumnName("name");
|
|
|
+ entity.Property(e => e.StartDate).HasColumnName("start_date");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.IdSpecialtyNavigation).WithMany(p => p.Groups)
|
|
|
+ .HasForeignKey(d => d.IdSpecialty)
|
|
|
+ .OnDelete(DeleteBehavior.ClientSetNull)
|
|
|
+ .HasConstraintName("Groups_id_specialty_fkey");
|
|
|
+ });
|
|
|
+
|
|
|
+ modelBuilder.Entity<Groupdiscipline>(entity =>
|
|
|
+ {
|
|
|
+ entity.HasKey(e => e.Id).HasName("groupdiscipline_pkey");
|
|
|
+
|
|
|
+ entity.ToTable("groupdiscipline");
|
|
|
+
|
|
|
+ entity.Property(e => e.Id).HasColumnName("id");
|
|
|
+ entity.Property(e => e.GroupId).HasColumnName("group_id");
|
|
|
+ entity.Property(e => e.Semester).HasColumnName("semester");
|
|
|
+ entity.Property(e => e.TeacherDisciplineId).HasColumnName("teacher_discipline_id");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.Group).WithMany(p => p.Groupdisciplines)
|
|
|
+ .HasForeignKey(d => d.GroupId)
|
|
|
+ .OnDelete(DeleteBehavior.ClientSetNull)
|
|
|
+ .HasConstraintName("groupdiscipline_group_id_fkey");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.TeacherDiscipline).WithMany(p => p.Groupdisciplines)
|
|
|
+ .HasForeignKey(d => d.TeacherDisciplineId)
|
|
|
+ .OnDelete(DeleteBehavior.ClientSetNull)
|
|
|
+ .HasConstraintName("groupdiscipline_teacher_discipline_id_fkey");
|
|
|
+ });
|
|
|
+
|
|
|
+ modelBuilder.Entity<Role>(entity =>
|
|
|
+ {
|
|
|
+ entity.HasKey(e => e.Id).HasName("roles_pkey");
|
|
|
+
|
|
|
+ entity.ToTable("roles");
|
|
|
+
|
|
|
+ entity.HasIndex(e => e.Name, "roles_name_key").IsUnique();
|
|
|
+
|
|
|
+ entity.Property(e => e.Id).HasColumnName("id");
|
|
|
+ entity.Property(e => e.Name)
|
|
|
+ .HasMaxLength(30)
|
|
|
+ .HasColumnName("name");
|
|
|
+ });
|
|
|
+ modelBuilder.Entity<Specialty>(entity =>
|
|
|
+ {
|
|
|
+ entity.HasKey(e => e.Id).HasName("specialties_pkey");
|
|
|
+
|
|
|
+ entity.ToTable("specialties");
|
|
|
+
|
|
|
+ entity.HasIndex(e => e.Name, "specialties_name_key").IsUnique();
|
|
|
+
|
|
|
+ entity.Property(e => e.Id).HasColumnName("id");
|
|
|
+ entity.Property(e => e.IdDepartment).HasColumnName("id_department");
|
|
|
+ entity.Property(e => e.Name)
|
|
|
+ .HasMaxLength(70)
|
|
|
+ .HasColumnName("name");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.IdDepartmentNavigation).WithMany(p => p.Specialties)
|
|
|
+ .HasForeignKey(d => d.IdDepartment)
|
|
|
+ .OnDelete(DeleteBehavior.ClientSetNull)
|
|
|
+ .HasConstraintName("specialties_id_department_fkey");
|
|
|
+ });
|
|
|
+
|
|
|
+ modelBuilder.Entity<Student>(entity =>
|
|
|
+ {
|
|
|
+ entity.HasKey(e => e.UserId).HasName("students_pkey");
|
|
|
+
|
|
|
+ entity.ToTable("students");
|
|
|
+
|
|
|
+ entity.Property(e => e.UserId)
|
|
|
+ .ValueGeneratedNever()
|
|
|
+ .HasColumnName("user_id");
|
|
|
+ entity.Property(e => e.GroupId).HasColumnName("group_id");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.Group).WithMany(p => p.Students)
|
|
|
+ .HasForeignKey(d => d.GroupId)
|
|
|
+ .OnDelete(DeleteBehavior.ClientSetNull)
|
|
|
+ .HasConstraintName("students_group_id_fkey");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.User).WithOne(p => p.Student)
|
|
|
+ .HasForeignKey<Student>(d => d.UserId)
|
|
|
+ .OnDelete(DeleteBehavior.ClientSetNull)
|
|
|
+ .HasConstraintName("students_user_id_fkey");
|
|
|
+ });
|
|
|
+
|
|
|
+ modelBuilder.Entity<Studentgrade>(entity =>
|
|
|
+ {
|
|
|
+ entity.HasKey(e => e.Id).HasName("studentgrades_pkey");
|
|
|
+
|
|
|
+ entity.ToTable("studentgrades");
|
|
|
+
|
|
|
+ entity.Property(e => e.Id).HasColumnName("id");
|
|
|
+ entity.Property(e => e.Grade).HasColumnName("grade");
|
|
|
+ entity.Property(e => e.GradedAt).HasColumnName("graded_at");
|
|
|
+ entity.Property(e => e.GroupDisciplineId).HasColumnName("group_discipline_id");
|
|
|
+ entity.Property(e => e.StudentId).HasColumnName("student_id");
|
|
|
+ entity.Property(e => e.WorkName)
|
|
|
+ .HasMaxLength(70)
|
|
|
+ .HasColumnName("work_name");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.GroupDiscipline).WithMany(p => p.Studentgrades)
|
|
|
+ .HasForeignKey(d => d.GroupDisciplineId)
|
|
|
+ .OnDelete(DeleteBehavior.ClientSetNull)
|
|
|
+ .HasConstraintName("studentgrades_group_discipline_id_fkey");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.Student).WithMany(p => p.Studentgrades)
|
|
|
+ .HasForeignKey(d => d.StudentId)
|
|
|
+ .OnDelete(DeleteBehavior.ClientSetNull)
|
|
|
+ .HasConstraintName("studentgrades_student_id_fkey");
|
|
|
+ });
|
|
|
+
|
|
|
+ modelBuilder.Entity<Teacher>(entity =>
|
|
|
+ {
|
|
|
+ entity.HasKey(e => e.UserId).HasName("teachers_pkey");
|
|
|
+
|
|
|
+ entity.ToTable("teachers");
|
|
|
+
|
|
|
+ entity.Property(e => e.UserId)
|
|
|
+ .ValueGeneratedNever()
|
|
|
+ .HasColumnName("user_id");
|
|
|
+ entity.Property(e => e.DepartmentId).HasColumnName("department_id");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.Department).WithMany(p => p.Teachers)
|
|
|
+ .HasForeignKey(d => d.DepartmentId)
|
|
|
+ .HasConstraintName("teachers_department_id_fkey");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.User).WithOne(p => p.Teacher)
|
|
|
+ .HasForeignKey<Teacher>(d => d.UserId)
|
|
|
+ .OnDelete(DeleteBehavior.ClientSetNull)
|
|
|
+ .HasConstraintName("teachers_user_id_fkey");
|
|
|
+ });
|
|
|
+
|
|
|
+ modelBuilder.Entity<Teachersdiscipline>(entity =>
|
|
|
+ {
|
|
|
+ entity.HasKey(e => e.Id).HasName("teachersdisciplines_pkey");
|
|
|
+
|
|
|
+ entity.ToTable("teachersdisciplines");
|
|
|
+
|
|
|
+ entity.Property(e => e.Id).HasColumnName("id");
|
|
|
+ entity.Property(e => e.DisciplineId).HasColumnName("discipline_id");
|
|
|
+ entity.Property(e => e.TeacherId).HasColumnName("teacher_id");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.Discipline).WithMany(p => p.Teachersdisciplines)
|
|
|
+ .HasForeignKey(d => d.DisciplineId)
|
|
|
+ .OnDelete(DeleteBehavior.ClientSetNull)
|
|
|
+ .HasConstraintName("teachersdisciplines_discipline_id_fkey");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.Teacher).WithMany(p => p.Teachersdisciplines)
|
|
|
+ .HasForeignKey(d => d.TeacherId)
|
|
|
+ .OnDelete(DeleteBehavior.ClientSetNull)
|
|
|
+ .HasConstraintName("teachersdisciplines_teacher_id_fkey");
|
|
|
+ });
|
|
|
+
|
|
|
+ modelBuilder.Entity<Timetable>(entity =>
|
|
|
+ {
|
|
|
+ entity.HasKey(e => e.Id).HasName("timetables_pkey");
|
|
|
+
|
|
|
+ entity.ToTable("timetables");
|
|
|
+
|
|
|
+ entity.Property(e => e.Id).HasColumnName("id");
|
|
|
+ entity.Property(e => e.BuildingId).HasColumnName("building_id");
|
|
|
+ entity.Property(e => e.ClassDate).HasColumnName("class_date");
|
|
|
+ entity.Property(e => e.ClassNumber).HasColumnName("class_number");
|
|
|
+ entity.Property(e => e.GroupDisciplineId).HasColumnName("group_discipline_id");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.Building).WithMany(p => p.Timetables)
|
|
|
+ .HasForeignKey(d => d.BuildingId)
|
|
|
+ .OnDelete(DeleteBehavior.ClientSetNull)
|
|
|
+ .HasConstraintName("timetables_buildind_id_fkey");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.GroupDiscipline).WithMany(p => p.Timetables)
|
|
|
+ .HasForeignKey(d => d.GroupDisciplineId)
|
|
|
+ .OnDelete(DeleteBehavior.ClientSetNull)
|
|
|
+ .HasConstraintName("timetables_group_discipline_id_fkey");
|
|
|
+ });
|
|
|
+
|
|
|
+ modelBuilder.Entity<User>(entity =>
|
|
|
+ {
|
|
|
+ entity.HasKey(e => e.Id).HasName("users_pkey");
|
|
|
+
|
|
|
+ entity.ToTable("users");
|
|
|
+
|
|
|
+ entity.HasIndex(e => e.Mail, "users_mail_key").IsUnique();
|
|
|
+
|
|
|
+ entity.HasIndex(e => e.PhoneNumber, "users_phone_number_key").IsUnique();
|
|
|
+
|
|
|
+ entity.Property(e => e.Id).HasColumnName("id");
|
|
|
+ entity.Property(e => e.DateBirth).HasColumnName("date_birth");
|
|
|
+ entity.Property(e => e.FirstName)
|
|
|
+ .HasMaxLength(30)
|
|
|
+ .HasColumnName("first_name");
|
|
|
+ entity.Property(e => e.IdRole).HasColumnName("id_role");
|
|
|
+ entity.Property(e => e.LastName)
|
|
|
+ .HasMaxLength(30)
|
|
|
+ .HasColumnName("last_name");
|
|
|
+ entity.Property(e => e.Mail)
|
|
|
+ .HasMaxLength(50)
|
|
|
+ .HasColumnName("mail");
|
|
|
+ entity.Property(e => e.MiddleName)
|
|
|
+ .HasMaxLength(30)
|
|
|
+ .HasColumnName("middle_name");
|
|
|
+ entity.Property(e => e.Password)
|
|
|
+ .HasMaxLength(30)
|
|
|
+ .HasColumnName("password");
|
|
|
+ entity.Property(e => e.PhoneNumber)
|
|
|
+ .HasMaxLength(20)
|
|
|
+ .HasColumnName("phone_number");
|
|
|
+
|
|
|
+ entity.HasOne(d => d.IdRoleNavigation).WithMany(p => p.Users)
|
|
|
+ .HasForeignKey(d => d.IdRole)
|
|
|
+ .OnDelete(DeleteBehavior.ClientSetNull)
|
|
|
+ .HasConstraintName("users_id_role_fkey");
|
|
|
+ });
|
|
|
+
|
|
|
+ OnModelCreatingPartial(modelBuilder);
|
|
|
+ }
|
|
|
+
|
|
|
+ partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
|
|
|
+}
|
|
|
+Листинг 12 - Модель <<Специальность>>
|
|
|
+namespace EducationDepartment.Models;
|
|
|
+
|
|
|
+public partial class Specialty
|
|
|
+{
|
|
|
+ public int Id { get; set; }
|
|
|
+
|
|
|
+ public string Name { get; set; } = null!;
|
|
|
+
|
|
|
+ public int IdDepartment { get; set; }
|
|
|
+
|
|
|
+ public virtual ICollection<Group> Groups { get; set; } = new List<Group>();
|
|
|
+
|
|
|
+ public virtual Department IdDepartmentNavigation { get; set; } = null!;
|
|
|
+}
|
|
|
+Листинг 13 - Модель <<Студент>>
|
|
|
+namespace EducationDepartment.Models;
|
|
|
+
|
|
|
+public partial class Student
|
|
|
+{
|
|
|
+ public int UserId { get; set; }
|
|
|
+ public int GroupId { get; set; }
|
|
|
+ public virtual ICollection<Attendance> Attendances { get; set; } = new List<Attendance>();
|
|
|
+ public virtual Group Group { get; set; } = null!;
|
|
|
+ public virtual ICollection<Studentgrade> Studentgrades { get; set; } = new List<Studentgrade>();
|
|
|
+ public virtual User User { get; set; } = null!;
|
|
|
+}
|
|
|
+Листинг 14 - Модель <<Оценка студента>>
|
|
|
+namespace EducationDepartment.Models;
|
|
|
+
|
|
|
+public partial class Studentgrade
|
|
|
+{
|
|
|
+ public int Id { get; set; }
|
|
|
+
|
|
|
+ public int StudentId { get; set; }
|
|
|
+
|
|
|
+ public int GroupDisciplineId { get; set; }
|
|
|
+
|
|
|
+ public DateOnly? GradedAt { get; set; }
|
|
|
+
|
|
|
+ public short Grade { get; set; }
|
|
|
+
|
|
|
+ public string? WorkName { get; set; }
|
|
|
+
|
|
|
+ public virtual Groupdiscipline GroupDiscipline { get; set; } = null!;
|
|
|
+
|
|
|
+ public virtual Student Student { get; set; } = null!;
|
|
|
+}
|
|
|
+Листинг 15 - Модель <<Преподаватель>>
|
|
|
+namespace EducationDepartment.Models;
|
|
|
+
|
|
|
+public partial class Teacher
|
|
|
+{
|
|
|
+ public int UserId { get; set; }
|
|
|
+
|
|
|
+ public int? DepartmentId { get; set; }
|
|
|
+
|
|
|
+ public virtual Department? Department { get; set; }
|
|
|
+
|
|
|
+ public virtual ICollection<Teachersdiscipline> Teachersdisciplines { get; set; } = new List<Teachersdiscipline>();
|
|
|
+
|
|
|
+ public virtual User User { get; set; } = null!;
|
|
|
+}
|
|
|
+Листинг 16 - Модель <<Дисциплина преподавателя>>
|
|
|
+namespace EducationDepartment.Models;
|
|
|
+
|
|
|
+public partial class Teachersdiscipline
|
|
|
+{
|
|
|
+ public int Id { get; set; }
|
|
|
+
|
|
|
+ public int TeacherId { get; set; }
|
|
|
+
|
|
|
+ public int DisciplineId { get; set; }
|
|
|
+
|
|
|
+ public virtual Discipline Discipline { get; set; } = null!;
|
|
|
+
|
|
|
+ public virtual ICollection<Groupdiscipline> Groupdisciplines { get; set; } = new List<Groupdiscipline>();
|
|
|
+
|
|
|
+ public virtual Teacher Teacher { get; set; } = null!;
|
|
|
+}
|
|
|
+Листинг 17 - Модель <<Расписание>>
|
|
|
+namespace EducationDepartment.Models;
|
|
|
+
|
|
|
+public partial class Timetable
|
|
|
+{
|
|
|
+ public int Id { get; set; }
|
|
|
+
|
|
|
+ public DateOnly ClassDate { get; set; }
|
|
|
+
|
|
|
+ public short? ClassNumber { get; set; }
|
|
|
+
|
|
|
+ public int GroupDisciplineId { get; set; }
|
|
|
+
|
|
|
+ public int BuildingId { get; set; }
|
|
|
+
|
|
|
+ public virtual ICollection<Attendance> Attendances { get; set; } = new List<Attendance>();
|
|
|
+
|
|
|
+ public virtual Building Building { get; set; } = null!;
|
|
|
+
|
|
|
+ public virtual Groupdiscipline GroupDiscipline { get; set; } = null!;
|
|
|
+}
|
|
|
+Листинг 18 - Модель <<Пользователь>>
|
|
|
+namespace EducationDepartment.Models;
|
|
|
+
|
|
|
+public partial class User
|
|
|
+{
|
|
|
+ public int Id { get; set; }
|
|
|
+ public string FirstName { get; set; } = null!;
|
|
|
+ public string LastName { get; set; } = null!;
|
|
|
+ public string? MiddleName { get; set; }
|
|
|
+ public string Mail { get; set; } = null!;
|
|
|
+ public string? PhoneNumber { get; set; }
|
|
|
+ public DateOnly? DateBirth { get; set; }
|
|
|
+ public int IdRole { get; set; }
|
|
|
+ public string Password { get; set; } = null!;
|
|
|
+ public virtual ICollection<Building> Buildings { get; set; } = new List<Building>();
|
|
|
+ public virtual Role IdRoleNavigation { get; set; } = null!;
|
|
|
+ public virtual Student? Student { get; set; }
|
|
|
+ public virtual Teacher? Teacher { get; set; }
|
|
|
+ public override string ToString()=>
|
|
|
+ $"{LastName} {FirstName[0]}.{(MiddleName!=null?MiddleName[0]+".":"")}";
|
|
|
+}
|
|
|
+Листинг 19 - Модель представления <<Посещаемость>>
|
|
|
+namespace EducationDepartment.ViewModels
|
|
|
+{
|
|
|
+ public class AttendanceViewModel : INotifyPropertyChanged
|
|
|
+ {
|
|
|
+ Schekaleva31pContext connect;
|
|
|
+ public AttendanceViewModel(Schekaleva31pContext dbConnect) => connect = dbConnect;
|
|
|
+ public event PropertyChangedEventHandler? PropertyChanged;
|
|
|
+ protected virtual void OnPropertyChanged(string propertyName)
|
|
|
+ {
|
|
|
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
|
+ if (propertyName == "SelectedOption")
|
|
|
+ SecondOptions = NewOption();
|
|
|
+ if(propertyName == "SecondSelectedOption")
|
|
|
+ Values = NewValues();
|
|
|
+ }
|
|
|
+ //1 filter
|
|
|
+ public List<string> Options => new List<string> { "Группа", "Дисциплина" };
|
|
|
+ string selectedOption;
|
|
|
+ public string SelectedOption { get => selectedOption; set { selectedOption = value; OnPropertyChanged(nameof(SelectedOption)); } }
|
|
|
+ //2 filter
|
|
|
+ List<string> secondOptions;//list group, list disciplines
|
|
|
+ public List<string> SecondOptions { get => NewOption(); set { secondOptions = value; OnPropertyChanged(nameof(SecondOptions)); } }
|
|
|
+ string secondSelectedOption;
|
|
|
+ public string SecondSelectedOption { get => secondSelectedOption; set { secondSelectedOption = value; OnPropertyChanged(nameof(SecondSelectedOption)); } }
|
|
|
+ public List<string> NewOption()
|
|
|
+ {
|
|
|
+ return selectedOption=="Группа"?
|
|
|
+ connect.Groups.Select(x=>x.Name).ToList() :
|
|
|
+ connect.Disciplines.Select(x=>x.Name).ToList();
|
|
|
+ }
|
|
|
+ //3 values
|
|
|
+ List<string> values;//all group, student| all groups, group
|
|
|
+ public List<string> Values { get => NewValues(); set { values = value; OnPropertyChanged(nameof(Values)); } }
|
|
|
+ List<string> NewValues()
|
|
|
+ {
|
|
|
+ if (selectedOption == "Группа")
|
|
|
+ return new List<string> { "Вся группа" }.Union(connect.Students.Include(x => x.User)
|
|
|
+ .Include(x => x.Group).Where(x => x.Group.Name == secondSelectedOption).Select(x => x.User.ToString()).ToList()).ToList();
|
|
|
+ else if (selectedOption == "Дисциплина")
|
|
|
+ return new List<string> { "Все группы" }.Union(connect.Groupdisciplines.Include(x => x.TeacherDiscipline.Discipline)
|
|
|
+ .Include(x => x.Group).ToList().Where(x => x.TeacherDiscipline.Discipline.Name == secondSelectedOption)
|
|
|
+ .Select(x => x.Group.Name).ToList()).ToList();
|
|
|
+ else return null;
|
|
|
+ }
|
|
|
+ string optionValue;
|
|
|
+ public string OptionValue { get => optionValue; set => optionValue = value; }
|
|
|
+ public string ParameterName { get => parameterName; set { parameterName = value; OnPropertyChanged(nameof(ParameterName)); } }
|
|
|
+ string parameterName;
|
|
|
+
|
|
|
+ List<AttendanceInfo> attendanceTable;
|
|
|
+ public List<AttendanceInfo> AttendanceTable { get => attendanceTable; set { attendanceTable = value; OnPropertyChanged(nameof(AttendanceTable)); } }
|
|
|
+ public void GetNewAttendance()
|
|
|
+ {
|
|
|
+ List<AttendanceInfo> newTable = new List<AttendanceInfo>();
|
|
|
+ if (selectedOption == "Группа")
|
|
|
+ {
|
|
|
+ if (OptionValue == "Вся группа")
|
|
|
+ {
|
|
|
+ ParameterName = $"Студенты группы {secondSelectedOption}";
|
|
|
+
|
|
|
+ foreach(var student in connect.Students.Include(x=>x.User).Include(x=>x.Group)
|
|
|
+ .Where(x=>x.Group.Name == secondSelectedOption).Select(x => x.User).ToList())
|
|
|
+ {
|
|
|
+ var data = connect.Attendances.Include(x => x.Student).Where(x => x.Student.User == student);
|
|
|
+ if (data.Count() == 0) newTable.Add(new AttendanceInfo(NewStr(student.ToString()), 100));
|
|
|
+ else newTable.Add(new AttendanceInfo(NewStr(student.ToString()),
|
|
|
+ Math.Round((double)(data.Count(x=>x.Attended))/data.Count()*100,2)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ParameterName = $"Дисциплины студента {optionValue}";
|
|
|
+ foreach (var studentDiscipline in connect.Groupdisciplines.Include(x => x.TeacherDiscipline.Discipline)
|
|
|
+ .Include(x => x.Group).Where(x => x.Group.Name == secondSelectedOption).Select(x => x.TeacherDiscipline.Discipline).ToList())
|
|
|
+ {
|
|
|
+ var data = connect.Attendances.Include(x => x.Student).Include(x => x.Timetable.GroupDiscipline.TeacherDiscipline.Discipline).ToList()
|
|
|
+ .Where(x => x.Student.User.ToString() == optionValue && x.Timetable.GroupDiscipline.TeacherDiscipline.Discipline == studentDiscipline).ToList();
|
|
|
+ if(data.Count==0) newTable.Add(new AttendanceInfo(NewStr(studentDiscipline.Name), 100));
|
|
|
+ else newTable.Add(new AttendanceInfo(NewStr(studentDiscipline.Name),
|
|
|
+ Math.Round((double)(data.Count(x => x.Attended)) / data.Count() * 100,2)
|
|
|
+ ));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (selectedOption == "Дисциплина")
|
|
|
+ {
|
|
|
+ if (OptionValue == "Все группы")
|
|
|
+ {
|
|
|
+ ParameterName = $"Группы на '{secondSelectedOption}'";
|
|
|
+ foreach (var group in connect.Groupdisciplines.Include(x => x.Group).Include(x => x.TeacherDiscipline.Discipline)
|
|
|
+ .Where(x => x.TeacherDiscipline.Discipline.Name == secondSelectedOption).Select(x => x.Group))
|
|
|
+ {
|
|
|
+ Schekaleva31pContext newConnect = new Schekaleva31pContext();
|
|
|
+ var data = newConnect.Attendances.Include(x => x.Timetable.GroupDiscipline.TeacherDiscipline.Discipline)
|
|
|
+ .Where(x => x.Timetable.GroupDiscipline.Group == group &&
|
|
|
+ x.Timetable.GroupDiscipline.TeacherDiscipline.Discipline.Name == secondSelectedOption).ToList();
|
|
|
+ if (data.Count() == 0) newTable.Add(new AttendanceInfo(NewStr(group.Name), 100));
|
|
|
+ else
|
|
|
+ newTable.Add(new AttendanceInfo(NewStr(group.Name),
|
|
|
+ Math.Round((double)(data.Count(x => x.Attended)) / data.Count()*100,2)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ParameterName = $"Студенты группы {optionValue}";
|
|
|
+ foreach(var studentOnDiscipline in connect.Students.Include(x=>x.Group).Where(x=>x.Group.Name == optionValue))
|
|
|
+ {
|
|
|
+ Schekaleva31pContext newConnect = new Schekaleva31pContext();
|
|
|
+ var data = newConnect.Attendances.Include(x => x.Student).Include(x => x.Timetable.GroupDiscipline.TeacherDiscipline.Discipline).ToList()
|
|
|
+ .Where(x => x.Student == studentOnDiscipline && x.Timetable.GroupDiscipline.TeacherDiscipline.Discipline.Name == secondSelectedOption);
|
|
|
+ if (data.Count() == 0) newTable.Add(new AttendanceInfo(NewStr(newConnect.Users.First(x => x.Student == studentOnDiscipline).ToString()), 100));
|
|
|
+ else
|
|
|
+ newTable.Add(new AttendanceInfo(NewStr(newConnect.Users.First(x => x.Student == studentOnDiscipline).ToString()),
|
|
|
+ Math.Round((double)(data.Count(x => x.Attended)) / data.Count()*100,2)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ AttendanceTable = newTable;
|
|
|
+ }
|
|
|
+ string NewStr(string oldStr)
|
|
|
+ {
|
|
|
+ int n = 16 - oldStr.Count()/4;
|
|
|
+ return oldStr + new string('\t', n);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+Листинг 20 - Модель представления <<Авторизация>>
|
|
|
+namespace EducationDepartment.ViewModels
|
|
|
+{
|
|
|
+ public class AuthorizationViewModel : ViewModelBase
|
|
|
+ {
|
|
|
+ string login = "";
|
|
|
+ string password = "";
|
|
|
+ public string Login { get => login; set => this.RaiseAndSetIfChanged(ref login, value); }
|
|
|
+ public string Password { get => password; set => this.RaiseAndSetIfChanged(ref password, value); }
|
|
|
+ }
|
|
|
+}
|
|
|
+Листинг 21 - Модель представления <<Дисциплины>>
|
|
|
+namespace EducationDepartment.ViewModels
|
|
|
+{
|
|
|
+ public class DisciplineViewModel : INotifyPropertyChanged
|
|
|
+ {
|
|
|
+ public event PropertyChangedEventHandler? PropertyChanged;
|
|
|
+ protected virtual void OnPropertyChanged(string propertyName)
|
|
|
+ {
|
|
|
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
|
+ if (propertyName == "SelectedOption")
|
|
|
+ Values = NewValues(SelectedOption);
|
|
|
+ }
|
|
|
+ Schekaleva31pContext connect;
|
|
|
+ List<Discipline>? disciplines;
|
|
|
+ public List<Discipline>? Disciplines { get => disciplines; set { disciplines = value; OnPropertyChanged(nameof(Disciplines)); } }
|
|
|
+ public DisciplineViewModel(Schekaleva31pContext dbConnect) => connect = dbConnect;
|
|
|
+ public void NewDisciplines()
|
|
|
+ {
|
|
|
+ if (selectedOption == "Преподаватель")
|
|
|
+ Disciplines = connect.Teachersdisciplines.Include(x => x.Teacher.User).Include(x => x.Discipline).ToList()
|
|
|
+ .Where(x => x.Teacher.User.ToString() == optionValue).Select(x => x.Discipline).ToList();
|
|
|
+ else if (selectedOption == "Группа")
|
|
|
+ Disciplines = connect.Groupdisciplines.Include(x => x.Group).Include(x => x.TeacherDiscipline.Discipline).ToList()
|
|
|
+ .Where(x => x.Group.Name == optionValue).Select(x => x.TeacherDiscipline.Discipline).ToList();
|
|
|
+ else Disciplines = null;
|
|
|
+ }
|
|
|
+ public List<string> Options => new List<string> { "Преподаватель", "Группа" };
|
|
|
+ string selectedOption;
|
|
|
+ public string SelectedOption
|
|
|
+ {
|
|
|
+ get { return selectedOption; }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ selectedOption = value;
|
|
|
+ OnPropertyChanged(nameof(SelectedOption));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ string optionValue;
|
|
|
+ public string OptionValue { get => optionValue; set => optionValue = value; }
|
|
|
+ List<string> values;
|
|
|
+ public List<string> Values { get => NewValues(selectedOption); set { values = value; OnPropertyChanged(nameof(Values)); } }
|
|
|
+ public List<string> NewValues(string selectedOption)
|
|
|
+ {
|
|
|
+ return selectedOption == "Преподаватель" ?
|
|
|
+ connect.Teachers.Include(x => x.User).Select(x => x.User.ToString()).ToList() :
|
|
|
+ connect.Groups.Select(x => x.Name).ToList();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+Листинг 22 - Модель представления <<Оценки студента>>
|
|
|
+namespace EducationDepartment.ViewModels
|
|
|
+{
|
|
|
+ public class EvaluationStudentViewModel: INotifyPropertyChanged
|
|
|
+ {
|
|
|
+ public event PropertyChangedEventHandler? PropertyChanged;
|
|
|
+ protected virtual void OnPropertyChanged(string propertyName)
|
|
|
+ {
|
|
|
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
|
+ }
|
|
|
+ Schekaleva31pContext connect;
|
|
|
+ Student student;
|
|
|
+ public EvaluationStudentViewModel(Schekaleva31pContext dbConnect, int UserId)
|
|
|
+ {
|
|
|
+ connect = dbConnect;
|
|
|
+ student = connect.Students.First(x=>x.UserId == UserId);
|
|
|
+ options = StudentOptions();
|
|
|
+ }
|
|
|
+ List<string> options;
|
|
|
+ public List<string> Options { get => options; set => options = value; }
|
|
|
+ string selectedOption = "";
|
|
|
+ public string SelectedOption
|
|
|
+ {
|
|
|
+ get { return selectedOption; }
|
|
|
+ set
|
|
|
+ { selectedOption = value;OnPropertyChanged(nameof(SelectedOption));}
|
|
|
+ }
|
|
|
+
|
|
|
+ List<string> StudentOptions()
|
|
|
+ {
|
|
|
+ return connect.Groupdisciplines.Include(x=>x.TeacherDiscipline.Discipline)
|
|
|
+ .Include(x=>x.Group).Where(x=>x.Group == student.Group).Select(x=>x.TeacherDiscipline.Discipline.Name).ToList();
|
|
|
+ }
|
|
|
+ List<MarksInfo> marksTable;
|
|
|
+ public List<MarksInfo> MarksTable { get => marksTable; set { marksTable = value; OnPropertyChanged(nameof(MarksTable)); } }
|
|
|
+ public void GetMarks()
|
|
|
+ {
|
|
|
+ List<MarksInfo> newTable = new List<MarksInfo>();
|
|
|
+ foreach(var studentGrade in connect.Studentgrades.Include(x=>x.GroupDiscipline.TeacherDiscipline.Discipline)
|
|
|
+ .Include(x=>x.Student).ToList().Where(x=>x.Student==student && x.GroupDiscipline.TeacherDiscipline.Discipline.Name == selectedOption)
|
|
|
+ .ToList())
|
|
|
+ {
|
|
|
+ newTable.Add(new MarksInfo(studentGrade.GradedAt.ToString()+new string(' ',80),
|
|
|
+ studentGrade.Grade
|
|
|
+ ));
|
|
|
+ }
|
|
|
+ MarksTable = newTable;
|
|
|
+ }
|
|
|
+ public void WriteMarks() => Converter.WriteCsv(MarksTable, "marks.csv");
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+Листинг 23 - Главная модель представления
|
|
|
+namespace EducationDepartment.ViewModels
|
|
|
+{
|
|
|
+ public class MainWindowViewModel : ViewModelBase
|
|
|
+ {
|
|
|
+ //general
|
|
|
+ public static Schekaleva31pContext dbConnect = new Schekaleva31pContext();
|
|
|
+ UserControl uc = new AuthorizationPage();
|
|
|
+ string option = "";
|
|
|
+ string optionValue = "";
|
|
|
+ User? user = null;
|
|
|
+ string message = "";
|
|
|
+ public string Message { get => message;set=>this.RaiseAndSetIfChanged(ref message, value); }
|
|
|
+ public UserControl UC { get => uc; set => this.RaiseAndSetIfChanged(ref uc, value); }
|
|
|
+ public string Option { get => option; set => option = value; }
|
|
|
+ public string OptionValue { get => optionValue; set => optionValue = value; }
|
|
|
+ public void SaveChanges()=> dbConnect.SaveChanges();
|
|
|
+ //authorization
|
|
|
+ AuthorizationViewModel authorizationVM = new AuthorizationViewModel();
|
|
|
+ public AuthorizationViewModel AuthorizationVM { get => authorizationVM; set => this.RaiseAndSetIfChanged(ref authorizationVM, value); }
|
|
|
+ public bool AuthorizationSuccess()
|
|
|
+ {
|
|
|
+ user = dbConnect.Users.FirstOrDefault(u => u.Mail == AuthorizationVM.Login && u.Password == AuthorizationVM.Password);
|
|
|
+ if (user == null) return false;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ public void LoadHomePage()
|
|
|
+ {
|
|
|
+ if (AuthorizationSuccess()) {
|
|
|
+ UC = new EducationDepartament.Views.Menu();
|
|
|
+ UserProfileVM = new UserProfileViewModel(dbConnect, user.Mail);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Message = "Ошибка авторизации";
|
|
|
+ AuthorizationVM.Login = "";
|
|
|
+ AuthorizationVM.Password = "";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //user profile
|
|
|
+ UserProfileViewModel userProfileVM;
|
|
|
+ public UserProfileViewModel UserProfileVM { get => userProfileVM; set => this.RaiseAndSetIfChanged(ref userProfileVM, value); }
|
|
|
+ public void LoadUserProfile()
|
|
|
+ {
|
|
|
+ if (user.IdRole == 2) UC = new ProfileStudent();
|
|
|
+ else if (user.IdRole == 1) UC = new ProfileTeacher();
|
|
|
+ }
|
|
|
+ //timetables
|
|
|
+ TimetableViewModel timetableVM;
|
|
|
+ public TimetableViewModel TimetableVM { get => timetableVM; set => this.RaiseAndSetIfChanged(ref timetableVM, value); }
|
|
|
+ public void LoadTimetablePage()
|
|
|
+ {
|
|
|
+ TimetableVM = new TimetableViewModel(dbConnect);
|
|
|
+ UC = new TimeTable();
|
|
|
+ }
|
|
|
+ //disciplines
|
|
|
+ DisciplineViewModel disciplineVM;
|
|
|
+ public DisciplineViewModel DisciplineVM { get => disciplineVM; set => this.RaiseAndSetIfChanged(ref disciplineVM, value); }
|
|
|
+ public void LoadDisciplinePage()
|
|
|
+ {
|
|
|
+ DisciplineVM = new DisciplineViewModel(dbConnect);
|
|
|
+ UC = new Disciplines();
|
|
|
+ }
|
|
|
+ //attendance
|
|
|
+ AttendanceViewModel attendanceVM;
|
|
|
+ public AttendanceViewModel AttendanceVM { get => attendanceVM; set => this.RaiseAndSetIfChanged(ref attendanceVM, value); }
|
|
|
+ public void LoadAttendancePage()
|
|
|
+ {
|
|
|
+ AttendanceVM = new AttendanceViewModel(dbConnect);
|
|
|
+ UC = new EducationDepartament.Views.Attendance();
|
|
|
+ }
|
|
|
+ //evalution
|
|
|
+ EvaluationStudentViewModel evaluationStudentVM;
|
|
|
+ public EvaluationStudentViewModel EvaluationStudentVM { get => evaluationStudentVM; set => this.RaiseAndSetIfChanged(ref evaluationStudentVM, value); }
|
|
|
+ public void LoadEvaluationStudentPage()
|
|
|
+ {
|
|
|
+ EvaluationStudentVM = new EvaluationStudentViewModel(dbConnect, user.Id);
|
|
|
+ UC = new EvaluationStudent();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+Листинг 24 - Модель представления <<Расписание>>
|
|
|
+namespace EducationDepartment.ViewModels
|
|
|
+{ public class TimetableViewModel : INotifyPropertyChanged
|
|
|
+ {
|
|
|
+ public event PropertyChangedEventHandler? PropertyChanged;
|
|
|
+ protected virtual void OnPropertyChanged(string propertyName)
|
|
|
+ {
|
|
|
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
|
+ if (propertyName == "Values" || propertyName == "Timetable" || propertyName=="ClassDate") return;
|
|
|
+ Values = NewValues(SelectedOption);
|
|
|
+ }
|
|
|
+
|
|
|
+ Schekaleva31pContext connect;
|
|
|
+ List<Timetable>? timetable;
|
|
|
+ public List<Timetable>? Timetable { get => timetable; set { timetable = value; OnPropertyChanged(nameof(Timetable)); } }
|
|
|
+ public List<string> TeachersList { get => connect.Teachers.Include(x => x.User).Select(x => x.User.ToString()).ToList(); }
|
|
|
+ public List<string> GroupsList { get => connect.Groups.Select(x => x.Name).ToList(); }
|
|
|
+ public TimetableViewModel(Schekaleva31pContext dbConnect) => connect = dbConnect;
|
|
|
+ private string classDate;
|
|
|
+ public string ClassDate { get => classDate; set { classDate = value; OnPropertyChanged(nameof(ClassDate)); } }
|
|
|
+ public void NewTimetable()
|
|
|
+ {
|
|
|
+ if (SelectedOption == "Преподаватель")
|
|
|
+ {
|
|
|
+ Timetable = connect.Timetables.Include(x => x.GroupDiscipline.TeacherDiscipline.Teacher.User)
|
|
|
+ .Include(x => x.GroupDiscipline.TeacherDiscipline.Discipline).Include(x => x.GroupDiscipline.Group).ToList()
|
|
|
+ .Where(x => x.GroupDiscipline.TeacherDiscipline.Teacher.User.ToString() == optionValue && x.ClassDate == DateOnly.FromDateTime(DateTime.Parse(ClassDate))).ToList();
|
|
|
+ }
|
|
|
+ else if (SelectedOption == "Группа")
|
|
|
+ Timetable = connect.Timetables.Include(x => x.GroupDiscipline.TeacherDiscipline.Teacher.User)
|
|
|
+ .Include(x => x.GroupDiscipline.TeacherDiscipline.Discipline).Include(x => x.GroupDiscipline.Group).ToList()
|
|
|
+ .Where(x => x.GroupDiscipline.Group.Name == optionValue && x.ClassDate == DateOnly.FromDateTime(DateTime.Parse(ClassDate))).ToList();
|
|
|
+ else Timetable = null;
|
|
|
+ }
|
|
|
+ //do parameter to date
|
|
|
+ public List<string> Options => new List<string> { "Преподаватель", "Группа" };
|
|
|
+ string selectedOption = "";
|
|
|
+ public string SelectedOption
|
|
|
+ {
|
|
|
+ get { return selectedOption; }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ selectedOption = value;
|
|
|
+ OnPropertyChanged(nameof(SelectedOption));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ string optionValue;
|
|
|
+ public string OptionValue { get=> optionValue; set => optionValue = value; }
|
|
|
+ List<string> values;
|
|
|
+ public List<string> Values { get => NewValues(selectedOption); set { values = value; OnPropertyChanged(nameof(Values)); } }
|
|
|
+
|
|
|
+ public List<string> NewValues(string selectedOption)
|
|
|
+ {
|
|
|
+ return selectedOption == "Преподаватель" ?
|
|
|
+ connect.Teachers.Include(x => x.User).Select(x => x.User.ToString()).ToList() :
|
|
|
+ connect.Groups.Select(x => x.Name).ToList();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+Листинг 25 - Модель представления <<Профиль пользователя>>
|
|
|
+namespace EducationDepartment.ViewModels
|
|
|
+{
|
|
|
+ public class UserProfileViewModel : ReactiveObject
|
|
|
+ {
|
|
|
+ Schekaleva31pContext connect;
|
|
|
+ User user;
|
|
|
+ public User User { get => user; set => this.RaiseAndSetIfChanged(ref user, value); }
|
|
|
+ public string FirstName { get => user.FirstName; set => user.FirstName = value; }
|
|
|
+ public string LastName { get => user.LastName; set => user.LastName = value; }
|
|
|
+ public string DateBirht { get => user.DateBirth.ToString();
|
|
|
+ set => user.DateBirth = DateOnly.FromDateTime(DateTime.Parse(value)); }
|
|
|
+ public UserProfileViewModel(Schekaleva31pContext dbConnect, string userMail)
|
|
|
+ {
|
|
|
+ connect = dbConnect;
|
|
|
+ user = connect.Users.Include(x => x.Student.Group).Include(x=>x.IdRoleNavigation).FirstOrDefault(user => user.Mail == userMail);
|
|
|
+ }
|
|
|
+ public string Group { get => user.Student.Group.Name; }
|
|
|
+ public List<string> Groups { get => connect.Groups.Select(x => x.Name).ToList(); }
|
|
|
+ public string Discipline { get => Disciplines.First(); }
|
|
|
+ public List<string> Disciplines { get => connect.Teachersdisciplines.Include(x => x.Teacher.User)
|
|
|
+ .Where(x => x.Teacher.User == user).Select(x => x.Discipline.Name).ToList();}
|
|
|
+ }
|
|
|
+}
|
|
|
+ПРИЛОЖЕНИЕ Г. СКРИНШОТЫ ПРОГРАММЫ
|
|
|
+
|
|
|
+Рисунок 1 - Страница авторизации пользователей
|
|
|
+
|
|
|
+Рисунок 2 - Меню ИС <<Учебная часть>>
|
|
|
+
|
|
|
+Рисунок 3 - Личный кабинет пользователя
|
|
|
+
|
|
|
+Рисунок 4 - Дисциплины преподавателя
|
|
|
+
|
|
|
+Рисунок 5 - Дисциплины группы
|
|
|
+
|
|
|
+Рисунок 6 - Расписание группы на день
|
|
|
+
|
|
|
+Рисунок 7 - Посещаемость студента группы по предметам
|
|
|
+
|
|
|
+Рисунок 8 - Общая посещаемость каждого студента группы
|
|
|
+
|
|
|
+Рисунок 9 - Посещаемость предмета по всем группам
|
|
|
+
|
|
|
+Рисунок 10 - Посещаемость предмета студентами группы
|
|
|
+
|
|
|
+Рисунок 11 - Оценки студента по предметам
|
|
|
+
|
|
|
+Рисунок 12 - Импорт оценок студента в csv-файл
|