Разработка программного продукта для составления расписания репетитора

Анализ существующих решений для составления расписания репетитора. Разработка архитектуры программного продукта. Выбор инструментальных средств. Проектирование реляционной базы данных. Определение методики тестирования. Реализация интерфейса пользователя.

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 22.03.2018
Размер файла 411,7 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Для некоторых данных не предполагается дополнительной обработки, и в таких случаях достаточно в сервисе вызвать соответствующий метод репозитория и преобразовать данные к DTO. С другой стороны, для сущности «Событие» (Event) необходимо особое преобразование из модели, которая хранится в БД, к данным, которые будут переданы интерфейсу пользователя. Это связано с тем, что в БД хранится одна запись для повторяющегося события, тогда как в интерфейсе может понадобиться вывести несколько событий одной серии. Всего заведено пять типов повторяющихся событий: никогда (NEVER), каждый день (DAILY), каждую неделю (WEEKLY), каждый месяц (MONTHLY) и каждый год (YEAR). В связи с этим в коде Java создан перечисляемый тип (enum) RepeatCode с соответствующими значениями.

Сущность, полученная из базы, хранит в себе временной интервал в виде дат начала и окончания серии событий - dateStart и dateEnd. При этом дата окончания может быть не определена, что означает, что событие будет повторяться сколько угодно раз. Метод, который будет возвращать данные для интерфейса пользователя, принимает на вход две даты - начала и окончания периода, для которого надо получить список событий (from и to соответственно).

В первую очередь требуется получить записи из таблицы EVENT, учитывая даты события и даты периода. Для этого в соответствующем SQL запросе указано, что нужно выбрать такие записи, у которых дата начала меньше либо равна дате окончания искомого периода (dateStart <= to) и дата окончания не определена или меньше либо равна дате начала искомого периода (dateEnd >= from). Полученный в результате запроса список передается из репозитория в сервис.

В сервисе для каждого события из базы нужно создать один или несколько объектов DTO. Логика преобразования вынесена из сервиса в утилитный класс EventUtil для лучшей читаемости кода сервиса. Способ преобразования сильно зависит от типа повторения события, поэтому реализация разбита на несколько блоков через оператор switch. Для неповторяющихся событий (NEVER) достаточно проверить, что дата начала попадает в нужный промежуток, после чего преобразовать эту запись в DTO и добавить в результирующий список. В случае повторяющихся событий реализация разбита на две части. В первую очередь определяется дата первого события серии, попадающего в нужный диапазон дат. При этом не обязательно, что существует такое событие - достаточно определить первую дату, соответствующую серии событий, которая больше начала диапазона. Начиная с этой даты, в цикле добавим события в виде DTO в результирующий список, увеличивая дату при каждой итерации, до тех пор, пока она не превышает дату окончания серии событий (dateEnd) или диапазона (to). Увеличение даты зависит от типа повторяющегося события - на одну неделю, на один год и т.п.

В текущей реализации метод поиска событий работает для любого диапазона дат. Также для сокращения кода отдельные методы работы с датами были вынесены в утилитный класс DateUtil.

Классы, в которых описаны методы, формирующие ответ на REST запросы, называются контроллерами и имеют аннотацию @RestController. Эта аннотация сообщает о том, что данный класс является контроллером (по паттерну MVC), но возвращает не представление (View), а только набор данных в формате JSON или XML. Также в этих классах описано соответствие (маппинг) его методов и URL, по которым предполагается получать данные через REST; указан метод HTTP, который может быть использован для получения, параметры запроса (прописываются в URL через символы «?», «&»), заголовки и т.п.

В соответствии с соглашениями REST, URL могут выглядеть следующим образом (на примере сущности Event - «Событие») (табл.11).

Таблица 11 - Конечные точки REST

URL

Метод HTTP

Описание

/rest/event

GET

Получение всех событий

POST

Создание нового события (в теле запроса должно быть передано новое событие)

/rest/event?from=…&to=…

GET

Получение событий с параметрами from и to (в текущей реализации принимаются две даты)

/rest/event/{id}

GET

Получение события по его id (вместо id указывается конкретное число)

PUT

Изменение события по id (в теле запроса должно быть передано новое событие)

DELETE

Удаление события по id

Аналогично описывается доступ к любым другим типам данных. Тем самым создается унифицированный протокол взаимодействия клиентской и серверной частей приложения.

В качестве входных параметров каждого метода могут быть заголовки, параметры из URL (как перечисленные через «&», так и содержащиеся, например, в {id}), объект из тела запроса (RequestBody).

В ответ на запрос метод формирует объект ResponseEntity, который может включать в себя HTTP статус (например, 200 ОК), тело запроса, список HTTP заголовков.

Преобразование данных из объектов-сущностей в объекты DTO может происходить на уровне сервисов или REST контроллеров.

Стоит отметить, что серверная часть приложения представляет собой stateless реализацию, или реализацию «без сохранения состояния». Другими словами, любые данные, полученные в методах REST контроллеров, не сохраняются после обработки, система не «запоминает» предыдущие вызовы, сессии пользователей и т.п. Такой подход позволяет избежать сложностей синхронизации состояний и данных, не может привести к неожиданной потере данных сервером (в связи с удалением объекта, который хранил состояние) и соответствует принципам REST.

Исходный код приведен в приложении 2.

3.3 Реализация интерфейса пользователя

В интерфейсе пользователя можно выделить несколько блоков, каждый из которых соответствует функционалу для работы со связанными сущностями:

· работа с расписанием

· работа с журналом

· карточки студентов

· дерево тем занятий

· страница с информацией про ресурс

Для разделения логических блоков каждый из них был вынесен в отдельный файл HTML, а также было создано навигационное меню для переключения между содержимым этих файлов [6]. Поскольку навигационное меню не меняется для всех блоков, оно было вынесено в основной файл main.html, в котором также выделено пространство для импорта других файлов посредством HTML5 Imports. Помимо этого, стили и скрипты по мере разработки подключались в основной файл. Таким образом, с точки зрения пользователя, существует всего одна страница приложения, наполнение которой динамически подгружается при переходе между пунктами меню [7].

Навигационное меню представляет собой список (<ul>) с классами Bootstrap nav, navbar-nav. Каждый элемент списка (<li>) содержит внутри себя ссылку для подключения .html файла. За счет класса стилей active добавляется подсветка выбранного пункта меню. Обработка нажатия пунктов навигационного меню происходит в файле default.js через определение обработчика события onClick.

Авторизация пользователей осуществляется с помощью хранения идентификатора репетитора в cookie. Для авторизации пользователь вводит свой идентификатор в форму, после чего он записывается в cookie и отправляется на сервер в виде заголовка запросов на получение какой-либо информации. Если идентификатор не введен, ссылки в меню блокируются, и пользователь не имеет возможности видеть содержимое сайта. Идентификатор пользователя выводится в навигационном меню справа сверху, рядом с кнопкой «Выход». При нажатии на кнопку «Выход» значение cookie стирается.

Все CSS стили проекта хранятся в файле main.css, который подключается в основном файле HTML. Там же подключаются файлы скриптов с расширением .js.

Работа с расписанием.

Блок для работы с расписанием включает в себя таблицу-разметку, в которой столбцы соответствуют дням недели, а строки - часам от 0 до 24. Под каждым названием дня недели выводится его дата. По умолчанию первая неделя, которая показывается пользователю, - это неделя, в которую попадает текущая дата. Поверх разметки отрисовываются прямоугольники, соответствующие событиям, запланированным в этот промежуток времени. Событие занимает по ширине один столбец таблицы, а по высоте - несколько ячеек подряд, соответствующих промежутку времени события.

Структура таблицы описана в файле schedule.html, который импортируется в основную часть страницы при выборе пункта меню «Расписание». Обработчики событий, загрузка динамического содержимого, вызов и скрытие модальных окон на странице описаны в файле schedule.js.

В блоке «Расписание» пользователь имеет возможность просматривать события за неделю, добавлять новые события, редактировать уже созданное событие, сдвигать период, за который отображаются события, на неделю вперед или назад.

При загрузке страницы происходит Ajax_запрос на получение списка событий за неделю. После получения ответа, для каждого события создается элемент, который затем выводится на экран. При этом расположение элемента определяется датой события из списка, временем его начала и окончания. Для изменения периода отображения событий добавлены кнопки «Следующая неделя» и «Предыдущая неделя» над таблицей-разметкой. При нажатии на кнопку происходит новый Ajax_запрос на получение списка событий.

Такой запрос осуществляется с помощью метода ajax библиотеки JQuery. В запросе указывается тип данных (JSON), URL для вызова REST, метод HTTP GET, по которому будут получены данные, параметры запроса (значения дат from и to). Также в заголовке передается идентификатор пользователя idTutor, полученный из cookie. В ответе на запрос с сервера приходит массив событий в формате JSON.

Для просмотра информации о событии и создания нового события добавлено модальное окно. HTML разметка, описывающая модальное окно, добавлена в файл schedule.html и по умолчанию скрыта. Вызов окна происходит при нажатии на событие в календаре или при выборе нескольких ячеек в таблице-разметке. При этом, пользователь может выбрать несколько последовательных ячеек только в одном из столбцов таблицы. При нажатии левой кнопки мыши на ячейке таблицы она закрашивается, а при передвижении курсора мыши вниз также закрашиваются ячейки, от той, на которой был клик, до текущего положения курсора. Таким образом, пользователь «растягивает» прямоугольник закрашенных ячеек таблицы в одном столбце. Для реализации этой возможности были созданы обработчики событий mousedown, mouseup и mousemove для ячеек таблицы. При нажатии кнопки мыши включается обработчик, считывающий текущее положение курсора, по которому вычисляется, сколько ячеек таблицы должно быть закрашено.

Когда пользователь отпускает кнопку мыши, вызывается обработчик mouseup, который отображает модальное окно с формой создания нового события. То же модальное окно вызывается при клике по событию в расписании.

Форма модального окна включает в себя следующие поля:

· Название. Здесь можно увидеть название события, ввести новое.

· Дата. Фиксированное значение даты текущего события без возможности изменения.

· Время начала и время окончания. Поля формы типа time.

· Комментарий. Произвольный комментарий пользователя для события.

· Блок «Повторяющееся событие». Активен, если сохраненное событие имеет период повторения. При создании нового события блок скрыт, но доступен checkbox, при нажатии на который блок становится видимым. Селектор повторения события включает значения «Каждый день», «Каждую неделю» и т.д. Также доступны поля ввода типа date для старта и окончания серии событий. В случае «бесконечного» события, созданного ранее, вместо даты в поле «Окончание серии» отображается надпись «Бесконечно».

· Блок «Сделать занятием». Включает в себя дополнительную информацию о занятии: выбор из выпадающего списка предмета и студента; поле ввода стоимости занятия. В случае, если событие и связанное с ним занятие уже были созданы, данный блок будет виден сразу с сохраненной информацией о занятии.

· Внизу формы отображаются кнопки «Удалить», «Сохранить» и «Закрыть».

Поля ввода типа date доступны в HTML5 и позволяют выбрать дату из выпадающего календаря на месяц.

Закрытие модального окна возможно при нажатии левой кнопки мыши на кнопке «Закрыть», по крестику в углу формы и за пределами окна. Сохранение изменений в этих случаях не происходит.

При нажатии кнопки «Сохранить» формируется Ajax_запрос с данными формы и HTTP методом POST. Данные, которые не выводятся в расписании, но нужны для корректной работы (например, id события), хранятся в data_атрибутах элемента страницы, соответствующего каждому событию.

В режиме редактирования информации о событии доступна кнопка «Добавить в журнал», при нажатии на которую посредством Ajax_запроса происходит добавление записи в журнал о текущем событии. В записи указываются дата занятия, идентификатор и студент. Остальные поля можно заполнить на вкладке «Журнал».

Работа с журналом.

При выборе вкладки «Журнал» в основную часть страницы загружается файл journal.html. Журнал представляет собой таблицу со следующими столбцами:

· дата

· студент

· тема занятия

· домашнее задание

· оценка

· оценка за домашнее задание

· комментарий

По умолчанию выводятся последние 10 записей журнала. Также возможно пролистывание страниц журнала с помощью кнопок «Предыдущая страница» и «Следующая страница» над таблицей. Обработка событий описана в файле journal.js.

При загрузке страницы таблица наполняется данными, полученными по Ajax_запросу. В запросе в качестве параметров указываются limit и offset - количество записей журнала и порядковый номер, с которого нужно получить записи, соответственно. В ответ с сервера приходит массив записей, отсортированный по дате.

Также в журнале возможно редактирование записи через модальное окно, которое вызывается при нажатии левой кнопки мыши на строке таблицы. В форме модального окна содержатся те же поля, которые есть в таблице. Дату и студента изменить нельзя, т.к. это атрибуты сущности «Занятие». Тему занятия можно выбрать из выпадающего списка, который формируется в ответ на еще один запрос на сервер - в запросе указывается название дисциплины, по которой проводится занятие, в ответ приходит список всех тем занятий по данной дисциплине. Домашнее задание, оценки и комментарий заполняются пользователем в произвольной форме.

Карточки студентов.

Для перехода к карточкам студентов необходимо выбрать вкладку «Студенты». Карточки оформлены с помощью панелей Bootstrap и выводятся на экран в виде списка. В заголовке карточки указаны имя и фамилия ученика, а в теле карточки - его адрес и контактные данные. Панели можно сворачивать и раскрывать по клику на заголовок. Внизу каждой карточки есть кнопки «Редактировать» и «Удалить». Также над списком добавлены кнопки «Свернуть все», «Раскрыть все» и «Добавить студента».

При нажатии на кнопку «Добавить студента» или «Редактировать» выводится модальное окно. В случае редактирования карточки студента поля формы в модальном окне заполнены, для нового студента - нет. На форме выводятся поля ввода: имя, фамилия, адрес и список контактов. Каждый контакт состоит в свою очередь из двух полей: название контакта и его значение, например, телефон - номер. Строки в списке контактов можно удалять и добавлять. В поле названия контакта есть автодополнение ввода, а также можно выбрать значение из выпадающего списка. В модальном окне есть кнопки «Сохранить» и «Закрыть». При нажатии на кнопку «Сохранить» на сервер отправляется запрос с данными из формы. При этом если создается новая карточка студента, то отправляется HTTP запрос POST, а в случае редактирования - PUT.

Дерево тем занятий.

На вкладке «Темы занятий» пользователь может просматривать дисциплины и относящиеся к ним темы занятий в виде дерева. Дерево строится через вложенные HTML списки динамически после Ajax_запроса с параметром равным null (нет родительской темы занятия). При этом с сервера данные приходят в виде вложенных массивов элементов.

Для создания новой дисциплины и, соответственно, нового корня дерева, существует кнопка «Добавить дисциплину». Помимо этого, в каждой строке рядом с темой занятия есть кнопки «Создать» и «Удалить». При нажатии кнопки «Создать» под элементом, в строке которого была нажата кнопка, создается вложенный список с одним элементом-формой. Если такой список уже есть, то дополнительный элемент появляется в конце списка. В форме достаточно указать название темы занятия и комментарий. Новую строку можно сохранить или удалить. При сохранении данные отправляются на сервер, форма удаляется, а новая тема дописывается на свое место в списке. Перезагрузка данных при этом не происходит.

Листинги документов HTML, CSS и скриптов JavaScript приведены в приложении 3.

4. ТЕСТИРОВАНИЕ ПРИЛОЖЕНИЯ

Тестирование - это процесс проверки работоспособности и соответствия поставленной задаче частей приложения, отдельных блоков кода или всего приложения в целом.

Цели тестирования:

· выявить ошибки для дальнейшей их ликвидации;

· убедиться, что приложение или его часть выполняет поставленную задачу.

4.1 Определение методики тестирования

Тестирование программного продукта начинается как можно раньше - после реализации самой минимальной части приложения. По уровню автоматизации различают ручное и автоматизированное тестирование.

По уровню тестирования также можно выделить:

· Модульное тестирование. Тестируются отдельные компоненты.

· Интеграционное тестирование. Проверяется взаимодействие компонентов друг с другом.

· Системное тестирование. Тестирование системы в целом.

· Приемочное тестирование. Формальное тестирование по отношению к потребностям.

· Альфа-тестирование. Тестирование потенциальными пользователями системы или сторонней командой тестировщиков.

· Бета-тестирование. Тестирование пользователями системы с целью проверки, действительно ли система удовлетворяет требованиям заказчика.

Для каждого уровня создается набор сценариев, позволяющих оценить работу приложения в разных условиях. Каждый сценарий имеет входные данные и планируемый результат. Для фиксации результата, в зависимости от уровня, применяются различные инструменты. Также стоит учитывать разделение проекта на бэкенд и фронтенд - обе части должны быть протестированы в отдельности, затем проверена их интеграция.

Модульное тестирование классов и методов Java возможно с написанием Unit тестов непосредственно в серверной части проекта. Unit тесты позволяют проверить работоспособность минимальных логических составляющих программного продукта. Такие тесты особенно полезны, если происходят изменения в реализации работы методов без изменения входных и выходных значений. С другой стороны, написание Unit тестов предполагается на основе утвержденной иерархии классов и разделения «обязанностей» между ними, а также зачастую требует большого количества времени. Если после реализации метода (и первичной проверки его работоспособности) не предполагается изменять логику его работы, эффективность Unit тестов сильно снижается.

В связи с этим модульное тестирование осуществлялось в ручном режиме с помощью средств отладки в среде разработки, консольного вывода (в том числе сообщений от фреймворков) по мере реализации отдельных частей приложения. Аналогично отладка фронтенда возможна с помощью консоли разработчика в браузере и установки точек останова там же, либо в среде разработки WebStorm. В ходе интеграционного тестирования оценивается взаимодействие отдельных частей приложения: компоненты Java друг с другом, REST взаимодействие двух частей приложения. Для оценки работы REST API удобно использовать Postman.

Системное тестирование заключается в проверке соответствия исходных требований и полученного результата. Тестирование проводится через интерфейс пользователя, соответственно, для системного тестирования необходимы все интеграции проекта. Приемочное тестирование, альфа- и бета-тестирование не проводились. Помимо тестирования работоспособности отдельных частей и всего приложения в целом (тесты функциональности) также проверяется сборка приложения, отсутствие ошибок компиляции, развертывание на серверы, подключение к БД и т.п. Подобные тесты относятся к «дымовому» тестирование (Smoke Test).

4.2 Результаты тестирования

Результаты тестирования приведены в таблицах 12-15.

Таблица 12 - Дымовое тестирование

Тест

Ожидаемый результат

Результат прохождения теста

Компиляция бэкенда (Java)

Отсутствие ошибок компиляции

+

Инициализация контекста приложения, бинов

Вызов метода getClass() для контекста и бинов возвращает значение

+

Есть подключение к БД

При запуске приложения отсутствует ошибка HibernateException

+

Приложение развернуто на встроенном Tomcat

При запросе к http://localhost:8080 попадаем на страницу ошибки Whitelabel Error Page

+

Компиляция фронтенда (JavaScript)

Отсутствие ошибок компиляции

+

Фронтенд развернут на встроенном сервере (запуск из среды разработки)

Интерфейс пользователя отображается по адресу http://localhost:63342

+

Есть подключение к бэкенду

В консоли браузера отсутствуют ошибки ERR_CONNECTION_REFUSED

+

Таблица 13 - Модульное тестирование

Тест

Ожидаемый результат

Результат прохождения теста

Добавление новой записи в таблицы TUTOR, CONTACT_NAME, редактирование записи, нахождение записи по id, удаление (CRUD операции для TutorRepository, ContactNameRepository)

Запись добавляется, редактируется, находится и удаляется, проверяется SQL запросами к БД и выводом в консоль

+

Добавление двух записей в таблицу CONTACT_NAME с одинаковым полем NAME

Для второго добавления ошибка ConstraintViolationException

+

Добавление записи в таблицы EVENT, SUBJECT для существующего id пользователя (посредством EventRepository, SubjectRepository)

Происходит добавление

+

Добавление записи в таблицы EVENT, SUBJECT для не зарегистрированного id пользователя (посредством EventRepository, SubjectRepository)

Ошибка SQLException

+

Поиск заведомо существующей записи по id в любой из таблиц

Запись найдена

+

Поиск заведомо не существующей записи по id в любой из таблиц

Запись не найдена

+

Запись объекта с null полем при условии nullable=false

Ошибка SQLException

+

Поиск заведомо существующей записи ContactName по полю name

Запись найдена

+

Поиск всех Event, попадающих в выбранный промежуток дат

Записи найдены, даты dateStart, dateEnd соответствуют заданному диапазону

+

Пограничные случаи поиска Event, попадающих в выбранный промежуток дат

+

Поиск списка Contact по полю idStudent

Записи найдены, список полностью соответствует данным в базе

+

Поиск всех Event по полю idTutor

+

Поиск всех Journal по полю idTutor и параметрам limit и offset

+

Поиск Journal по idLesson и date

+

Поиск всех Student по idTutor

+

Поиск всех Student по idTutor и firstName

+

Поиск всех Subject по idTutor

+

Поиск всех Theme по idSubject

+

Поиск всех Theme по idParentTheme

+

Поиск всех Tutor по name и address

+

Составление списка EventDTO для повторяющихся событий (EventUtil)

Для всех типов повторяющихся событий возвращается список объектов EventDTO, попадающих в выбранный диапазон дат

+

Сохранение Student совместно со списком Contact

Список Contact перезаписывается при сохранении записи Student, не возникает ошибок SQLException

+

Получение дерева объектов Theme в рекурсивном методе

Дерево объетов Theme соответствует записям БД в части связей idTheme и idParentTheme, не возникает ошибки StackOverflow

+

Чтение и запись cookie

Полученные и записанные значения совпадают со значениями cookie в консоли браузера

+

Идентификация и авторизация по id

Запись cookie при авторизации

+

Доступность пунктов навигационного меню при наличии cookie

Навигационное меню разблокировано

+

Доступность пунктов навигационного меню при отсутствии cookie

Навигационное меню заблокировано

+

Переходы между вкладками навигационного меню

Загружается соответствующий файл html

+

Подключение библиотек

Методы JQuery доступны, стили Bootstrap присутствуют в интерфейсе

+

Отображение разметки для расписания

Разметка отображается корректно

+

Таблица 14 - Интеграционное тестирование

Тест

Ожидаемый результат

Результат прохождения теста

REST запросы к бэкенду для CRUD операций, метод GET

Получение данных в ответ на REST-запрос, соответствующих данным в БД

+

REST запросы к бэкенду для CRUD операций, метод POST

Сохранение новой записи в БД

+

REST запросы к бэкенду для CRUD операций, метод PUT

Изменение существующей записи в БД

+

REST запросы к бэкенду для CRUD операций, метод DELETE

Удаление записи в БД

Частичная реализация

Получение списка событий через REST с передачей параметров в виде даты начала и даты окончания периода

Получен список событий для выбранного периода

+

REST запрос с методом POST для сохранения объекта Student

Сохранен объект Student, обновлены контакты

+

REST запрос на получение дерева тем занятий, метод GET

Получен JSON массив с вложенными дочерними элементами

+

REST запрос на удаление части дерева из произвольного узла

Удаление всех соответствующих записей в БД

Частичная реализация

Таблица 15 - Системное тестирование

Тест

Ожидаемый результат

Результат прохождения теста

Отображение разметки для расписания

Разметка отображается корректно

+

Вывод на экран событий расписания

События выводятся за указанный период

+

Перелистывание страниц расписания

Сдвиг на одну неделю вперед или назад

+

Выделение цветом ячеек таблицы при создании нового события

Выделение цветом есть, не выходит за пределы одного столбца, без пропусков ячеек

+

Форма для ввода информации о новом событии при выборе диапазона времени в таблице-разметке

Появление модального окна с формой

+

Сохранение нового события по кнопке «Сохранить»

Новое событие сохраняется в БД и появляется в расписании

Возникают ошибки из-за отсутствия валидации полей

Закрытие модального окна без сохранения

Запрос на сохранение не отправляется, новое событие не появляется в расписании, модальное окно закрывается, форма очищается

+

Детальная информация при клике по событию

Появление модального окна с информацией о событии и возможностью редактировать

+

Сохранение изменений в событии по кнопке «Сохранить»

Событие редактируется в БД

Возникают ошибки из-за отсутствия валидации полей

Удаление события по кнопке «Удалить»

Удаление события из БД

Не реализовано

Вывод в интерфейс дерева тем занятий

Иерархия записей корректно отображается

+

Создание новой дисциплины

Новая дисциплина и корневая тема занятия создаются через форму модального окна и выводятся в интерфейс

+

Кнопки «Свернуть все» и «Раскрыть все» для тем занятий

Все узлы дерева сворачиваются до корневых элементов

Не реализовано

Создание новой записи в дереве тем занятий

Появление формы создания новой темы, добавление в интерфейс и сохранение в БД

+

Удаление произвольного узла дерева

Удаляется узел и все дочерние элементы

Ошибки при попытке удаления записей, использующихся другими сущностями

Отображение журнала

В журнале выводятся последние 10 записей

+

Перелистывание страниц журнала кнопками «Следующая страница» и «Предыдущая страница»

Отображение следующей или предыдущей страницы журнала, если имеется

+

Просмотр и редактирование записи журнала

Отображение формы в модальном окне с возможностью сохранения изменений

+

Выбор темы занятия для записи журнала из выпадающего списка

Отображение выпадающего списка для дисциплины занятия

+

Выбор студента для записи журнала из выпадающего списка

Отображение списка студентов

+

Просмотр карточек студентов

Отображение списка карточек студентов

+

Кнопки «Свернуть все» и «Раскрыть все» для карточек студентов

Все панели карточек сворачиваются и раскрываются

+

Кнопка «Добавить студента»

Отображение формы в модальном окне с сохранением новой карточки студента

+

Редактирование карточки студента

Сохранение изменений, внесенных в карточку

+

Редактирование списка контактов студента

Список контактов перезаписан в БД

+

Автодополнение в названии контакта

Автодополнение по введенным ранее названиям контакта, выбор из списка

+

Кнопка «Удалить» в карточке студента

Удаление записи студента и всех его контактов из БД

Не реализовано

5. РАЗРАБОТКА ДОКУМЕНТАЦИИ

Документация к проекту включает в себя:

· документацию пользователя - описание возможностей приложения при работе через интерфейс, для пользователей системы,

· документацию разработчика - описание бэкенда и фронтенда проекта, их установки и запуска, для разработчиков, желающих внести изменения в проект или подготовить дистрибутивы для развертывания на серверах,

· документацию администратора - для поддержки пользователей системы, поддержки и настройки серверов.

5.1 Документация разработчика

Для работы с исходным кодом проекта достаточно клонировать репозиторий с GitHub: часть приложения на Java (бэкенд) - HTML, CSS, JavaScript (фронтенд).

За счет разделения есть возможность создать еще один вариант фронтенда, который сможет подключиться к тем же REST контроллерам, без замены бэкенда.

1. Бэкенд.

Для работы приложения предполагается установка Maven (обязательно) и Git (опционально, для клонирования и работы с удаленным репозиторием).

Запуск проекта происходит из класса Application, метод main. При старте приложения Spring Boot по умолчанию запускает jetty и контекст приложения, инициализирует бины (компоненты). Все настройки компонентов и контекста определяются через аннотации (нет xml файлов настроек). Параметры подключения к базе данных описаны в файле application.properties (табл. 16).

Для создания базы данных заново можно использовать значение create-drop параметра spring.jpa.hibernate.ddl-auto. DML команды для наполнения таблиц тестовыми данными записаны в файле data.sql. Структура базы данных формируется за счет аннотаций в классах-сущностях (Entity). Описание идентификаторов для всех таблиц вынесены в класс BaseEntity.

При необходимости подключения к другой базе данных необходимо переопределить значение параметра spring.datasource.url.

Запросы в БД описаны в интерфейсах Repository. CRUD_операции, которые по умолчанию есть для этих интерфейсов, не переопределены. Используется модуль Spring Data JPA и Hibernate.

Таблица 16 - Описание содержания файла application.properties

Параметр

Значение

Описание

spring.jpa.hibernate.ddl-auto

update

Обновление структуры БД при старте приложения в соответствии со структурой Entity классов

spring.jpa.generate-ddl

true

Генерация DDL скриптов при старте приложения для создания/обновления схемы

spring.jpa.show-sql

true

Включено логгирование SQL запросов

spring.datasource.url

jdbc:mysql://localhost:3306/testing_db

URL для подключения к БД: драйвер - JDBC, СУБД - MySQL, локальный сервер, порт 3306, название базы testing_db

spring.datasource.username

admin

Логин пользователя в MySQL

spring.datasource.password

1234

Пароль пользователя в MySQL

На уровне сервисов реализована бизнес_логика приложения. Методы сервисов должны возвращать объекты DTO, либо списки таких объектов.

В классах REST контроллеров создаются только конечные точки приложения (endpoints), без бизнес-логики. Каждый метод контроллера должен возвращать объект ResponseEntity, параметризованный соответствующим DTO. Для сохранения обратной совместимости рекомендуется не переопределять маппинг конечных точек без согласования со всеми фронтенд-системами, использующими данное API. Маппинг описан в соответствии с принципами REST. Все URL доступа по REST, их связь с сущностями и HTTP методы запросов приведены в таблице 17.

Для точек доступа REST использовалась аннотация @CrossOrigin, которая отменяет необходимость настройки CORS.

Создание дистрибутива возможно двумя способами. Во-первых, можно переопределить параметр packaging в файле pom.xml на jar и выполнить команду maven clean install в директории проекта. Полученный jar включает в себя Apache Tomcat, который будет развернут при запуске. Запуск можно выполнить из консоли командой java -jar schedule.jar. Для создания дистрибутива в случае развертывания на стороннем веб-сервере необходимо настроить сборку на war, закомментировать плагин spring-boot-maven-plugin в pom.xml, а также внести небольшие изменения в класс Application: класс должен наследоваться от SpringBootServletInitializer и переопределять метод configure(). Метод должен возвращать application.sources(ApplicationContext).

Таблица 17 - Все конечные точки REST приложения

Entity

URL

GET

POST

PUT

DELETE

Contact

/rest/student/{idStudent}/contact

+

+

/rest/student/{idStudent}/contact/{id}

+

+

+

ContactName

/rest/contactname

+

+

/rest/contactname/{id}

+

+

+

Event

/rest/event

+

+

/rest/event, params = from, to

+

/rest/event/{id}

+

+

+

Journal

/rest/journal

+

/rest/journal/{id}

+

+

/rest/journal/idLesson/{idLesson}, params = date

+

/rest/journal, params = limit, offset

+

Student

/rest/student

+

+

/rest/student, params = firstName

+

/rest/student/{id}

+

+

+

Subject, Theme

/rest/subject

+

/rest/subject/{idSubject}/theme

+

/rest/theme

+

/rest/theme/{id}

+

/rest/theme/parent, params = idParent

+

/rest/theme/tree/parent, params = idParent

+

Tutor

/rest/tutor

+

+

/rest/tutor/{id}

+

+

+

2. Фронтенд.

Запуск фронтенда возможен из среды разработки WebStorm. Для этого требуется открыть в браузере файл main.html (Run main.html). Для загрузки данных по Ajax необходим предварительный запуск бэкенда.

Файлы HTML, CSS и JavaScript находятся в папках html, css и js соответственно. Библиотеки JavaScript, в том числе для корректной работы Bootstrap, находятся в папке js-libs - это jquery, jquery-ui и cookie.js. Файлы html не рекомендуется переименовывать, поскольку их названия используются для импорта в main.html. Все скрипты js подключаются в основной файл - main.html. Общие функции вынесены в файл default.js - проверка cookie и переключение вкладок по пунктам меню.

Файлы html соответствуют вкладкам в навигационном меню:

· home.html - вкладка с «домиком»

· schedule.html - «Расписание»

· subjects.html - «Темы занятий»

· journal.html - «Журнал»

· students.html - «Студенты»

· tutor.html - «Ваш ID на сайте»

Каждому файлу html соответствует свой файл js с тем же названием, в котором содержится код обработчиков событий, запросов к бэкенду и динамического наполнения страницы. При изменении локализации бэкенда необходимо переопределить все строки, содержащие «localhost:8080» на другой сервер и порт. Настройки CORS при этом не требуется.

Все доступные URL запросов по REST описаны в таблице 17.

5.2 Документация администратора

Развертывание приложения предполагается с использованием трех серверов: MySQL, веб-сервер для бэкенда, веб-сервер для фронтенда.

Сервер СУБД необходимо установить с помощью дистрибутива с официального сайта MySQL.

Проект разрабатывался и тестировался под версию MySQL Server 5.7.

Доступ к БД можно осуществить через консоль или MySQL Workbench. Создание базы данных и наполнение ее тестовыми данными происходит после первого запуска бэкенда с соответствующими параметрами (см. «Документация разработчика»). БД может быть создана на локальном сервере, порт по умолчанию 3306. Также для создания БД можно воспользоваться скриптами SQL (приложение 1).

Локальные веб-серверы для бэкенда и фронтенда запускаются автоматически из сред разработки Intellij IDEA и WebStorm соответственно. Помимо этого, war файл, полученный при сборке бэкенда с помощью Maven, может быть развернут в контейнере сервлетов Tomcat. Порт по умолчанию для запросов REST - 8080.

При запуске фронтенда через WebStorm порт по умолчанию - 63342. Перед запуском необходимо убедиться, что указанные порты не заняты другими приложениями. Также фронтенд можно развернуть на веб-сервере. При проверке данной возможности использовался сервер Apache в составе Denwer. Рекомендованный локальный адрес для доступа к приложению - schedule.com.

Идентификаторы пользователей заводятся в таблице TUTOR. Другие поля таблицы необязательны для заполнения.

5.3 Документация пользователя

Пользователю не требуется установки специальных программ, помимо браузера. Сайт доступен локально по адресу schedule.com.

Для входа на сайт необходимо ввести идентификатор. После ввода идентификатора будет разблокировано навигационное меню и открыт доступ ко всем вкладкам сайта. Чтобы выйти из аккаунта можно нажать кнопку «Выйти» в правом верхнем углу экрана. В текущей реализации получить идентификатор можно только через администратора системы.

В навигационном меню можно увидеть четыре основные вкладки для работы на странице: Расписание, Темы занятий, Журнал и Студенты.

1. Расписание.

При первом обращении к вкладке отображается текущая неделя. Можно перелистывать расписание с помощью кнопок «Следующая страница» и «Предыдущая страница» в верхней части экрана.

Для добавления нового события в расписание необходимо выбрать несколько ячеек в одной из колонок, «растянув» закрашенную область на нужное количество строк. После этого появится форма для создания события. По умолчанию создается однократное событие. Чтобы сделать событие повторяющимся, нужно поставить галочку «Повторяющееся событие», после чего указать период (каждый день, неделю и т.п.), а также старт и окончание серии - даты, в пределах которых событие будет выводиться в расписании. Если не указывать дату окончания серии, событие будет повторяться «бесконечно». Если событие является занятием, необходимо выбрать «Сделать занятием», после чего появятся поля ввода для предмета занятия, студента, с которым проводится занятие, и стоимости. Не рекомендуется создавать занятие, если еще не заведены карточки студентов и список дисциплин - это можно сделать позднее. Для сохранения нового события нужно нажать на кнопку «Сохранить». Также можно закрыть окно формы без сохранения информации.

События в расписании отображаются со своими названиями. Для просмотра и редактирования подробной информации о событии достаточно нажать левой кнопкой мыши на одно из них. При этом отображается форма, похожая на создание нового события, но на ней также появляется кнопка «Добавить запись в журнал», при клике по которой запись об открытом событии будет добавлена в журнал с минимальными данными: датой занятия и именем ученика.

2. Темы занятий.

На вкладке «Темы занятий» есть возможность добавлять новые дисциплины и темы, относящиеся к ним. Для создания новой дисциплины необходимо воспользоваться кнопкой «Добавить дисциплину», после чего в открывшейся форме ввести ее наименование. После появления дисциплины на странице можно добавить к ней темы занятия с помощью кнопки «Создать». В форме для новой темы занятия необходимо указать ее название и комментарий, после чего нажать на кнопку «Сохранить». Для удаления тем занятий есть кнопка «Удалить» в каждой строке с темой. Стоит учитывать, что в случае, если у темы есть дочерние элементы, они также будут удалены.

3. Журнал.

Работа с журналом доступна на вкладке «Журнал». Если в журнал уже были добавлены записи (с вкладки «Расписание»), они будут выведены в таблице. Перелистывание страниц журнала происходит при нажатии на кнопки «Предыдущая страница» и «Следующая страница». Записи журнала отсортированы по дате занятия. Для редактирования записи нужно нажать на строку таблицы, а в открывшейся форме ввести необходимую информацию и сохранить. Оценки за занятие и домашнее задание вводятся в произвольной форме без какой-либо шкалы.

4. Студенты.

Просмотр карточек студента доступен на вкладке «Студенты». При необходимости каждую карточку можно свернуть. Для сворачивания всех карточек можно воспользоваться кнопкой «Свернуть все». Добавление нового студента в список осуществляется так же через форму, которая появляется после нажатия кнопки «Добавить студента». Для студента можно указать его имя, фамилию, адрес и список контактов. Информацию о студенте можно изменить, нажав на кнопку «Редактировать» в карточке студента.

ЗАКЛЮЧЕНИЕ

В процессе выполнения дипломной работы было разработано веб-приложение, позволяющее планировать расписание занятий, работать с информацией о занятиях, учениках и их успеваемости.

Был проведен анализ существующих решений, выявлены их основные положительные и отрицательные стороны, на основании которых сформулированы функциональные требования к проекту.

В части проектирования была разработана архитектура приложения, описана схема базы данных, а также были выбраны подходящие инструментальные средства.

В ходе разработки приложения были реализованы части, отвечающие за взаимодействие с базой данных, бизнес-логику; разработан графический интерфейс пользователя.

Отдельные части программного продукта были протестированы по мере добавления нового функционала, также было проведено системное тестирование продукта в целом. Разработана документация к приложению.

Разделение проекта на две логические части позволило добиться хорошей масштабируемости, что дает возможность развивать проект в дальнейшем, добавлять новые и расширять уже существующие функции.

Помимо этого, использование широко распространенных в настоящее время интеграционных решений может позволить разработать несколько вариантов графического интерфейса пользователя для использования в разных системах - например, на мобильных устройствах.

ПРИЛОЖЕНИЕ 1

Листинг SQL-запроса для создания базы данных

-- MySQL Script generated by MySQL Workbench

-- 02/21/18 00:29:03

-- Model: New Model Version: 1.0

-- MySQL Workbench Forward Engineering

SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;

SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;

SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';

-- -----------------------------------------------------

-- Schema mydb

-- -----------------------------------------------------

-- -----------------------------------------------------

-- Schema TESTING_DB

-- -----------------------------------------------------

-- -----------------------------------------------------

-- Schema TESTING_DB

-- -----------------------------------------------------

CREATE SCHEMA IF NOT EXISTS `TESTING_DB` DEFAULT CHARACTER SET utf8 ;

USE `TESTING_DB` ;

-- -----------------------------------------------------

-- Table `TESTING_DB`.`STUDENT`

-- -----------------------------------------------------

CREATE TABLE IF NOT EXISTS `TESTING_DB`.`STUDENT` (

`ID` BIGINT(20) NOT NULL AUTO_INCREMENT,

`FIRST_NAME` VARCHAR(45) NOT NULL,

`LAST_NAME` VARCHAR(45) NULL DEFAULT NULL,

`ADDRESS` VARCHAR(255) NULL DEFAULT NULL,

`ID_TUTOR` BIGINT(20) NOT NULL,

PRIMARY KEY (`ID`))

ENGINE = InnoDB

AUTO_INCREMENT = 3

DEFAULT CHARACTER SET = utf8;

-- -----------------------------------------------------

-- Table `TESTING_DB`.`CONTACT_NAME`

-- -----------------------------------------------------

CREATE TABLE IF NOT EXISTS `TESTING_DB`.`CONTACT_NAME` (

`ID` BIGINT(20) NOT NULL AUTO_INCREMENT,

`NAME` VARCHAR(100) NOT NULL,

PRIMARY KEY (`ID`),

UNIQUE INDEX `UK_CONTACT_NAME_NAME` (`NAME` ASC))

ENGINE = InnoDB

AUTO_INCREMENT = 4

DEFAULT CHARACTER SET = utf8;

-- -----------------------------------------------------

-- Table `TESTING_DB`.`CONTACT`

-- -----------------------------------------------------

CREATE TABLE IF NOT EXISTS `TESTING_DB`.`CONTACT` (

`ID` BIGINT(20) NOT NULL AUTO_INCREMENT,

`ID_CONTACT_NAME` BIGINT(20) NOT NULL,

`VALUE` VARCHAR(100) NOT NULL,

`ID_STUDENT` BIGINT(20) NOT NULL,

PRIMARY KEY (`ID`),

INDEX `FK_CONTACT_CONTACT_NAME` (`ID_CONTACT_NAME` ASC),

INDEX `FK_CONTACT_STUDENT` (`ID_STUDENT` ASC),

CONSTRAINT `FK_CONTACT_STUDENT`

FOREIGN KEY (`ID_STUDENT`)

REFERENCES `TESTING_DB`.`STUDENT` (`ID`),

CONSTRAINT `FK_CONTACT_CONTACT_NAME`

FOREIGN KEY (`ID_CONTACT_NAME`)

REFERENCES `TESTING_DB`.`CONTACT_NAME` (`ID`))

ENGINE = InnoDB

AUTO_INCREMENT = 5

DEFAULT CHARACTER SET = utf8;

-- -----------------------------------------------------

-- Table `TESTING_DB`.`TUTOR`

-- -----------------------------------------------------

CREATE TABLE IF NOT EXISTS `TESTING_DB`.`TUTOR` (

`ID` BIGINT(20) NOT NULL AUTO_INCREMENT,

`NAME` VARCHAR(255) NULL DEFAULT NULL,

`ADDRESS` VARCHAR(255) NULL DEFAULT NULL,

PRIMARY KEY (`ID`))

ENGINE = InnoDB

AUTO_INCREMENT = 2

DEFAULT CHARACTER SET = utf8;

-- -----------------------------------------------------

-- Table `TESTING_DB`.`EVENT`

-- -----------------------------------------------------

CREATE TABLE IF NOT EXISTS `TESTING_DB`.`EVENT` (

`ID` BIGINT(20) NOT NULL AUTO_INCREMENT,

`NAME` VARCHAR(255) NOT NULL,

`COMMENT` VARCHAR(255) NULL DEFAULT NULL,

`DATE_START` DATE NOT NULL,

`DATE_END` DATE NULL DEFAULT NULL,

`TIME_START` TIME NULL DEFAULT NULL,

`TIME_END` TIME NULL DEFAULT NULL,

`CODE` ENUM('DAILY', 'WEEKLY', 'YEARLY', 'MONTHLY', 'NEVER') NOT NULL,

`ID_TUTOR` BIGINT(20) NOT NULL,

PRIMARY KEY (`ID`),

INDEX `FK_EVENT_TUTOR` (`ID_TUTOR` ASC),

CONSTRAINT `FK_EVENT_TUTOR`

FOREIGN KEY (`ID_TUTOR`)

REFERENCES `TESTING_DB`.`TUTOR` (`ID`)

ON DELETE NO ACTION

ON UPDATE NO ACTION)

ENGINE = InnoDB

AUTO_INCREMENT = 9

DEFAULT CHARACTER SET = utf8;

-- -----------------------------------------------------

-- Table `TESTING_DB`.`SUBJECT`

-- -----------------------------------------------------

CREATE TABLE IF NOT EXISTS `TESTING_DB`.`SUBJECT` (

`ID` BIGINT(20) NOT NULL AUTO_INCREMENT,

`NAME` VARCHAR(100) NOT NULL,

`ID_TUTOR` BIGINT(20) NOT NULL,

UNIQUE INDEX `UK_SUBJECT_ID_TUTOR_NAME` (`ID_TUTOR` ASC, `NAME` ASC),

CONSTRAINT `FK_SUBJECT_TUTOR`

FOREIGN KEY (`ID_TUTOR`)

REFERENCES `TESTING_DB`.`TUTOR` (`ID`)

ON DELETE NO ACTION

ON UPDATE NO ACTION)

ENGINE = InnoDB

AUTO_INCREMENT = 3

DEFAULT CHARACTER SET = utf8;

-- -----------------------------------------------------

-- Table `TESTING_DB`.`LESSON`

-- -----------------------------------------------------

CREATE TABLE IF NOT EXISTS `TESTING_DB`.`LESSON` (

`ID` BIGINT(20) NOT NULL AUTO_INCREMENT,

`ID_EVENT` BIGINT(20) NOT NULL,

`ID_STUDENT` BIGINT(20) NOT NULL,

`ID_SUBJECT` BIGINT(20) NOT NULL,

`PRICE` DECIMAL(19,2) NOT NULL,

PRIMARY KEY (`ID`),

INDEX `FK_LESSON_EVENT` (`ID_EVENT` ASC),

INDEX `FK_LESSON_STUDENT` (`ID_STUDENT` ASC),

INDEX `FK_LESSON_SUBJECT` (`ID_SUBJECT` ASC),

CONSTRAINT `fk_lesson_event`

FOREIGN KEY (`ID_EVENT`)

REFERENCES `TESTING_DB`.`EVENT` (`ID`),

CONSTRAINT `fk_lesson_student`

FOREIGN KEY (`ID_STUDENT`)

REFERENCES `TESTING_DB`.`STUDENT` (`ID`),

CONSTRAINT `fk_lesson_subject`

FOREIGN KEY (`ID_SUBJECT`)

REFERENCES `TESTING_DB`.`SUBJECT` (`ID`))

ENGINE = InnoDB

AUTO_INCREMENT = 5

DEFAULT CHARACTER SET = utf8;

-- -----------------------------------------------------

-- Table `TESTING_DB`.`THEME`

-- -----------------------------------------------------

CREATE TABLE IF NOT EXISTS `TESTING_DB`.`THEME` (

`ID` BIGINT(20) NOT NULL AUTO_INCREMENT,

`ID_PARENT_THEME` BIGINT(20) NULL DEFAULT NULL,

`NAME` VARCHAR(255) NOT NULL,

`COMMENT` VARCHAR(255) NULL DEFAULT NULL,

`ID_SUBJECT` BIGINT(20) NOT NULL,

PRIMARY KEY (`ID`),

INDEX `FK_THEME_SUBJECT` (`ID_SUBJECT` ASC),

CONSTRAINT `FK_THEME_SUBJECT`

FOREIGN KEY (`ID_SUBJECT`)

REFERENCES `TESTING_DB`.`SUBJECT` (`ID`))

ENGINE = InnoDB

AUTO_INCREMENT = 45

DEFAULT CHARACTER SET = utf8;

-- -----------------------------------------------------

-- Table `TESTING_DB`.`JOURNAL`

-- -----------------------------------------------------

CREATE TABLE IF NOT EXISTS `TESTING_DB`.`JOURNAL` (

`ID` BIGINT(20) NOT NULL AUTO_INCREMENT,

`ID_LESSON` BIGINT(20) NOT NULL,

`ID_THEME` BIGINT(20) NULL DEFAULT NULL,

`DATE` DATE NOT NULL,

`HOMETASK` VARCHAR(255) NULL DEFAULT NULL,

`LESSON_MARK` VARCHAR(255) NULL DEFAULT NULL,

`HOMETASK_MARK` VARCHAR(255) NULL DEFAULT NULL,

`COMMENT` VARCHAR(255) NULL DEFAULT NULL,

PRIMARY KEY (`ID`),

INDEX `FK_JOURNAL_LESSON` (`ID_LESSON` ASC),

INDEX `FK_JOURNAL_THEME` (`ID_THEME` ASC),

CONSTRAINT `FK_JOURNAL_LESSON`

FOREIGN KEY (`ID_LESSON`)

REFERENCES `TESTING_DB`.`LESSON` (`ID`),

CONSTRAINT `FK_JOURNAL_THEME`

FOREIGN KEY (`ID_THEME`)

REFERENCES `TESTING_DB`.`THEME` (`ID`))

ENGINE = InnoDB

AUTO_INCREMENT = 28

DEFAULT CHARACTER SET = utf8;

SET SQL_MODE=@OLD_SQL_MODE;

SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;

SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;

ПРИЛОЖЕНИЕ 2

Листинги классов и интерфейсов Java

Листинг класса BaseEntity

package com.rep.db.domain;

import javax.persistence.*;

@MappedSuperclass
public class BaseEntity {

@Id

@Column(name = "ID")

@GeneratedValue(strategy = GenerationType.IDENTITY)

private Long id;

public Long getId() {

return id;

}

public void setId(Long id) {

this.id = id;

}

}

Листинг класса Contact

package com.rep.db.domain;

import com.fasterxml.jackson.annotation.JsonIgnore;

import javax.persistence.*;

@Entity

@Table(name = "CONTACT")

public class Contact extends BaseEntity {

@JsonIgnore

@Column(name = "ID_STUDENT",

nullable = false)

private Long idStudent;

@ManyToOne

@JoinColumn(name = "ID_CONTACTNAME",

nullable = false,

foreignKey = @ForeignKey(

name = "FK_CONTACT_CONTACT_NAME"))

private ContactName contactName;

@Column(name = "VALUE",

nullable = false,

length = 100)

private String value;

public Long getIdStudent() {

return idStudent;

}

public void setIdStudent(Long idStudent) {

this.idStudent = idStudent;

}

public ContactName getContactName() {

return contactName;

}

public void setContactName(ContactName contactName) {

his.contactName = contactName;

}

public String getValue() {

return value;

}

public void setValue(String value) {

this.value = value;

}

@Override

public String toString() {

return "Contact{" +

"contactName=" + contactName +

", value='" + value + '\'' +

'}';

}

public Contact() {

}

}

Листинг класса ContactName

package com.rep.db.domain;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.Table;

@Entity

@Table(name = "CONTACT_NAME")

public class ContactName extends BaseEntity {

@Column(name = "NAME",

nullable = false,

unique = true)

private String name;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

@Override

public String toString() {

return "ContactName{" +

"name='" + name + '\'' +

'}';

}

public ContactName() {

}

}

Листинг класса Event

package com.rep.db.domain;

import com.fasterxml.jackson.annotation.JsonFormat;

import com.fasterxml.jackson.annotation.

import javax.persistence.*;

import java.util.Date;

@Entity

@Table(name = "EVENT")

ublic class Event extends BaseEntity {

@JsonIgnore

@Column(name = "ID_TUTOR",

nullable = false)

private Long idTutor;

@Column(name = "NAME",

nullable = false)

private String name;

@Enumerated(EnumType.STRING)

@Column(name = "CODE",

columnDefinition = "ENUM('DAILY', 'WEEKLY', 'YEARLY', 'MONTHLY', 'NEVER')",

nullable = false)

private RepeatCode repeatCode;

@Temporal(value = TemporalType.DATE)

@Column(name = "DATE_START",

nullable = false)

@JsonFormat(shape = JsonFormat.Shape.STRING,

pattern="yyyy-MM-dd")

private Date dateStart;

@Temporal(value = TemporalType.DATE)

@Column(name = "DATE_END")

@JsonFormat(shape = JsonFormat.Shape.STRING,

pattern="yyyy-MM-dd")

private Date dateEnd;

@Temporal(value = TemporalType.TIME)

@Column(name = "TIME_END")

@JsonFormat(shape = JsonFormat.Shape.STRING,

pattern="HH:mm:ss",

timezone = "Europe/Moscow")

private Date timeEnd;

@Temporal(value = TemporalType.TIME)

@Column(name = "TIME_START")

@JsonFormat(shape = JsonFormat.Shape.STRING,

pattern="HH:mm:ss",

timezone = "Europe/Moscow")

private Date timeStart;

@Column(name = "COMMENT")

private String comment;

@OneToOne(mappedBy = "event")

private Lesson lesson;

public Long getIdTutor() {

return idTutor;

}

public void setIdTutor(Long idTutor) {

this.idTutor = idTutor;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public RepeatCode getRepeatCode() {

return repeatCode;

}

public void setRepeatCode(RepeatCode repeatCode) {

this.repeatCode = repeatCode;

}

public Date getDateStart() {

return dateStart;

}

public void setDateStart(Date dateStart) {

this.dateStart = dateStart;

}

public Date getDateEnd() {


Подобные документы

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.