Вы находитесь на странице: 1из 76

Частное учреждение образования

«Колледж бизнеса и права»

АВТОМАТИЗАЦИИ РАБОЧЕГО МЕСТА АДМИНИСТРАТОРА КАФЕ

ПОЯСНИТЕЛЬНАЯ ЗАПИСКА
к курсовому проекту по дисциплине
«Конструирование программ и языки программирования»

КП Т.795003.401

Руководитель проекта (В.Ю. Михалевич)

Учащейся (Е.Ю. Божкова)

2020
Содержание
Введение 4
1 Объектно-ориентированный анализ и проектирование системы 6
1.1 Сущность задачи 6
1.2 Проектирование модели 7
2 Вычислительная система 12
2.1 Требования к аппаратным и операционным ресурсам 12
2.2 Инструменты разработки 12
3 Проектирование задачи 14
3.1 Требования к приложению 14
3.2 Концептуальный прототип 14
3.3 Организация данных 16
3.4 Функции: логическая и физическая организация 20
3.5 Проектирование справочной системы приложения 21
4 Описание программного средства 22
4.1 Общие сведения 22
4.2 Функциональное назначение 22
4.3 Входные и выходные данные 22
5 Методика испытаний 27
5.1 Технические требования 27
5.2 Функциональное тестирование 27
6 Применение 34
6.1 Назначение программы 34
6.2 Условия применения 34
6.3 Справочная система 34
Заключение 36
Список информационных источников 37
Приложение А Текст программы 39
Приложение Б Формы выходных документов 71

КП Т.795003.401
Изм. Лист № докум. Подпись Дата
Разраб. Божкова Е. Ю. Лит.
Провер. Михалевич В.Ю. Программное средство для у
Реценз. автоматизации рабочего
Н. Контр. места администратора
Утверд. кафе

4
Введение

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


сферы промышленности и сферы услуг, не является исключением и сфера общественного
питания.
Последнее время, все больший интерес к автоматизации явно ощущается со стороны
активно развивающихся предприятий общественного питания, владеющих достаточным
количеством средств, желающих минимизировать потери рабочего времени персонала,
сэкономить на его численности и поднять уровень сервиса в заведениях, чему и способствует
разработанное программное средство.
Программное средство Cafe.sln предназначено для автоматизации рабочего места
администратора кафе. Благодаря гибкой системе настроек, оно позволит вести учет данных,
содержащих информацию о блюдах; списке официантов; складе и заказах. Также программное
средство будет осуществлять введение данных, содержащих информацию о блюдах и напитках;
работниках и складе. Реализовать следующие функции: редактирование меню, склад
продуктов, списка официантов, списка заказов. Обеспечивает возможность просмотра сведений
о наличии блюд и напитков, работниках данного кафе.
Пояснительная записка к курсовому проекту состоит из шести разделов, содержащих
необходимую информацию по организации эксплуатации программного приложения.
В первом разделе «Объектно-ориентированный анализ и проектирование системы»
раскрывается организационная сущность задачи, описывается предметная область и круг задач,
которые должны быть автоматизированы. Описываются новые возможности программы, а
также ее отличия от предыдущих версий, перечисляются основные функции программы.
Строится информационная модель, отражающая сущности задачи, их свойства и взаимосвязи.
Во втором разделе «Вычислительная система» перечисляются требования к аппаратному
обеспечению и конфигурации компьютера, проводится характеристика операционной системы,
обоснование выбранной среды для разработки приложения.
В третьем разделе «Проектирование задачи» перечисляются требования к программному
средству, концептуальный прототип, логическую и физическую структуры данных в контексте
среды разработки, структуру и описание функций пользователя в рамках среды
разрабатываемого программного средства, функции и элементы управления, проектирование
справочной системы программного средства.
В четвертом разделе «Описание программного средства» приводятся общие сведения о
программе, ее функциональное назначение, структура входных и выходных данных.
В пятом разделе «Методика испытаний» описываются требования к техническим
средствам для проведения испытаний, требования к характеристикам программы
применительно к условиям эксплуатации, требования к информационной и программной
совместимости. Представляются результаты функционального тестирования.
Шестой раздел «Применение» предназначен для описания сведений о назначении
программного средства и области его применения классе решаемых задач, ограничениях,
накладываемых на область применения, требования к техническим и программным ресурсам. В
этом разделе приводится структура справочной системы, а также методика ее использования.
В заключении подводятся итоги создания программного средства: перечисляются его
достоинства, проверяется корректное выполнение работы программного средства, его задач,
степень его соответствия проектным требованиям, работа всех функции, осуществляющих
определенные действия в данном программном обеспечении.
Приложение А содержит в себе код разрабатываемого программного средства.
Приложение Б содержит выходные документы программного средства.
Графическая часть содержит в себе всё необходимые диаграммы для проектирования
данного программного средства, такие как:
 диаграмма вариантов использования;
 диаграмма деятельности;
4
 диаграмма компонентов;
 диаграмма классов;
 диаграмма последовательности.

5
1 Объектно-ориентированный анализ и проектирование системы

1.1Сущность задачи

Предметной областью данного курсового проекта является администратор кафе.


Кафе – заведение общественного питания и отдыха, в котором можно сделать заказ еды
по имеющемуся меню [5].
В услуги кафе включаются:
 взаимодействия с меню;
 взаимодействие с заказом.
Каждое блюдо обладает следующими характеристиками:
 конкретное название;
 категорию;
 вес;
 себестоимость;
 наценку;
 цену.
В кафе будут присутствуют следующие должности: администратор, официант.
Официант – это человек, который обеспечивает обслуживание заведения. Основными
функциями официанта кафе являются: досконально знать меню; знать и качественно выполнять
все правила по обслуживанию гостей; выполнять распоряжения администратора или
вышестоящего руководства; корректно заполнять счёт и рассчитать гостя, знать и выполнять
правила техники безопасности [6].
Администратор – это человек, который управляет деятельностью заведения в целом.
Основными функциями администратора кафе являются: организует работу персонала (поваров,
официантов и т. д.), контролирует качество обслуживания, решает возможные конфликтные
ситуации и создает хорошее настроение посетителям [7].
Меню – это перечень блюд и напитков, подаваемых в кафе, ресторане или баре [8].
Меню включает в себя:
 список блюд;
 список напитков.
Заказ – поручение на изготовление чего-либо или оказание услуги. Заказ состоит из
блюд и напитков, заказанных заказчиком [9].
Учет заказов в кафе происходит следующим образом:
 заказ добавляет администратор;
 добавляется в базу заказов;
 исполняется или доставляется.
Склад – это территория, помещение, предназначенное для хранения материальных
ценностей и оказания складских услуг [10].
На складе находится сырье, поступающее на предприятие общественного питания,
хранят в складских помещениях.
Складское хозяйство в кафе выполняет следующие функции [11]:
 просмотр текущей насыщенности склада;
 добавление новых продуктов;
 редактирование ингредиентов, лежащих на складе;
 удаление израсходованных ингредиентов;

6
Таблица 1.1 – Сроки хранения продуктов
Наименование Срок хранения, сут Наименование Срок хранения, сут

Мясные 2–3 Овощи 5 – 10

Рыбные 1–2 Зелень 1

Молочно-жировые 1–3 Фрукты, ягоды 1–2

Гастрономические 2–5 Хлебобулочные изделия 1

Существует только одна роль  администратор.


Администратор приложения может:
 редактировать, добавлять, удалять, просматривать меню;
 редактировать, добавлять, удалять, просматривать ингредиенты на складе;
 добавлять, удалять, просматривать список обслуживающего персонала;
 производить поиск по названию и цене блюда или напитка.
На основе изученной предметной области приложение должно выполнять следующие
функции:
 ведение единой базы данных, содержащая такие сущности как: «Category», «Dish»,
«Drink», «Units», «Ingredient», «DishComposition», «Stock», «Waiter», «Order», «DishOrderInfo»,
«DrinkOrderInfo»;
 производить поиск по названиям блюд и напитков;
 производить сортировку по цене блюд и напитков;
 формирование выходного документа Excel, который будет содержать данные обо всех
оформленных заказах  Report.xlsx.
Данное приложение является небольшим аналогом приложения Caffesta [12], которое
также предназначено для автоматизации работы администратора кафе (ресторана). Но
приложение, разработанное в данном курсовом проекте, не только будет осуществлять учёт
работы администратора, но и возможность администратора изменять данные всех
составляющих кафе.

1.2Проектирование модели

При проектировании будет организован поэтапный план в виде основных аспектов


реализации: подготовки к проектированию и сбор необходимой информации, установка
используемого программного средства, создание и подключение библиотек для упрощения
реализации, проектирование базовой модели для первичного тестирования, обновление и
дополнение существующих компонентов, многоступенчатое тестирование продукта и его
оптимизация.
Наиболее распространенным средством моделирования данных являются диаграммы
«сущность-связь» (ERD). С их помощью определяются важные для предметной области
объекты (сущности), их свойства (атрибуты) и отношения друг с другом (связи). ERD
непосредственно используются для проектирования реляционных баз данных. Нотация ERD
была впервые введена П. Ченном и получила дальнейшее развитие в работах Баркера.
Для данного программного средства можно выделить следующие сущности: «Category»,
«Dish», «Drink», «Units», «Ingredient», «DishComposition», «Stock», «Waiter», «Order»,
«DishOrderInfo», «DrinkOrderInfo». Диаграмма «Сущность-связь» представлена на рисунке 1.1.

7
Рисунок 1.1 Диаграмма «Сущность-связь»

Для сущности «Category» атрибутом будет являться: name.


Для сущности «Dish» атрибутами будут являться:
 name;
 category;
 weight;
 first price;
 mark up;
 price.
Для сущности «Drink» атрибутами будут являться:
 name;
 category;
 volume;
 first price;
 mark up;
 price.
Для сущности «Units» атрибутом будет являться: name.
Для сущности «Ingredient» атрибутами будут являться:
 name;
 weight;
 units;
 first price.
Для сущности «DishComposition» атрибутами будут являться:
 number of dish;
 number of ingredient;
8
 amount.
Для сущности «Stock» атрибутами будут являться:
 number of ingredient;
 price.
Для сущности «Waiter» атрибутами будут являться:
 surname;
 name;
 patronymic.
Для сущности «Order» атрибутами будут являться:
 date;
 number of table;
 number of waiter;
 price.
Для сущности «DishOrderInfo» атрибутами будут являться:
 number of dish;
 number of order.
Для сущности «DrinkOrderInfo» атрибутами будут являться:
 number of drink;
 number of order.
Диаграмма вариантов использования в UML  диаграмма, отражающая отношения
между актерами и прецедентами и являющаяся составной частью модели прецедентов,
позволяющей описать систему на концептуальном уровне. Существуют два вида отношений в
данной диаграмме. Расширение (англ. Extend)  разновидность отношения зависимости между
базовым вариантом использования и его специальным случаем. Включение (англ. Include) 
определяет взаимосвязь базового варианта использования с другим вариантом использования,
функциональное поведение которого всегда задействуется базовым вариантом использования
[13]. На данной диаграмме имеется один «актёр»  администратор.
Администратор имеет такие варианты использования как:
 авторизация;
 редактирование;
 добавление;
 удаление;
 публикация;
 просмотр записей.
В основном при создании диаграммы рассматривались такие связи как «включение».
Данная диаграмма находится в графической части на листе 1.
В диаграмме классов схематически класс изображается в виде прямоугольника, который
дополнительно может быть разделен горизонтальными линиями на разделы. Верхний раздел
содержит название класса, в среднем указываются атрибуты класса (видимость, тип, название),
нижний содержит методы (видимость, тип и название). «+» – общедоступный атрибут –
доступен для чтения и модификации из объектов любого класса; «-» – закрытый атрибут –
доступен только объектам описываемого класса. Ассоциация  отношение между объектами-
экземплярами класса. Агрегация – ассоциация типа «целая часть». Композиция – это такая
агрегация, где объекты не могут существовать друг без друга. Данная диаграмма находится в
графической части на листе 2.
Таблица 1.2 хранит информацию о классах проекта, их полях и методах.

9
Таблица 1.2  Классы, поля и методы
Название класса Поля класса Методы класса

Dish - name: Varchar + Create(Dish dish): bool


- category: Category + Update(Dish dish): bool
- weight: Decimal(10,2) + GetById(int id): Dish
- firstPrice: Decimal(10,2) + Delete(int id): bool
- markUp: Decimal(10,2) + GetAll(): IList<Dish>
- price: Decimal(10,2)
DishComposition - dish: Dish
- ingredient[]: Ingredient
DishOrderInfo - dish[]: Dish
- orderNumber: int
Drink - name: Varchar + Create(Drink drink): bool
- category: Category + Update(Drink drink): bool
- volume: Decimal(10,2) + GetById(int id): Drink
- firstPrice: Decimal(10,2) + Delete(int id): bool
- markUp: Decimal(10,2) + GetAll(): IList<Drink>
- price: Decimal(10,2)
DrinkOrderInfo - drink[]: Drink
- orderNumber: int
Order - date: DateTime
- numberTable: int
- waiter: Waiter
- totalPrice: Decimal(10,2)
Ingredient - name: Varchar
- weight: Decimal(10,2)
- units: Decimal(10,2)
- firstPrice: Decimal(10,2)
Stock - ingredient[]: Ingredient + Create(Stock stock): bool
+ Update(Stock stock): bool
+ GetById(int id): Stock
+ Delete(int id): bool
+ GetAll(): IList<Dish>
Units - name: Varchar

Waiter - name: Varchar


- surname: Varchar
- patronymic: Varchar
Category - name: Varchar

Диаграмма деятельности – это технология, позволяющая описывать логику процедур,


бизнес-процессы и потоки работ. Ветвления означают, что есть один входной поток и
несколько параллельных потоков. Поток представляет собой самый общий вид перехода и
задает порядок выполнения операций. Эта диаграмма представляет собой блок-схему, которая
наглядно показывает, как поток управления переходит от одной деятельности к другой. Данная
диаграмма находится в графической части на листе 3.
Диаграмма последовательности  диаграмма, на которой для некоторого набора
объектов на единой временной оси показан жизненный цикл какого-либо определённого
объекта (создание-деятельность-уничтожение некой сущности) и взаимодействие актеров
(действующих лиц) ИС в рамках какого-либо определённого прецедента (отправка запросов и
получение ответов). Используется в языке UML. Данная диаграмма находится в графической
части на листе 4.
Диаграмма компонентов  элемент языка моделирования UML, статическая структурная
диаграмма, которая показывает разбиение программной системы на структурные компоненты и
связи (зависимости) между компонентами. В качестве физических компонентов могут

10
выступать файлы, библиотеки, модули, исполняемые файлы, пакеты и т. п. Для данного проекта
выделены такие компоненты, как:
 Controllers содержит такие контроллеры как:
 CategoryController;
 DishController;
 DrinkController;
 HomeController;
 IngredientController;
 OrderController;
 StockController;
 UnitController;
 WaiterController.
 Models содержит такие модели как:
 Category;
 Dish;
 DishComposition;
 DishOrderInfo;
 Drink;
 DrinkOrderInfo;
 Ingredient;
 Order;
 Stock;
 Units;
 Waiter.
Данная диаграмма находится в графической части на листе 5.

11
2 Вычислительная система

2.1Требования к аппаратным и операционным ресурсам

Данное программное средство не требовательно к ресурсам персонального компьютера.


Приведенных ниже системных требований будет более чем достаточно:
 процессор Intel Core i5 8250U 1600 МГц;
 операционная система Windows 7 64-bit и выше;
 оперативная память DDR4 16 ГБ;
 места на HDD 500 МБ;
 материнская плата Gigabyte G1.
Для работы с программой необходимо наличие монитора, клавиатуры и мыши.

2.2Инструменты разработки

Инструментами разработки будут являться:


 операционная система Windows 10 Корпоративная 2016;
 среда разработки Visual Studio 2019;
 среда разработки Visual Studio Code version 1.44;
 среда разработки Microsoft SQL Server Express version 18.4;
 программное средство для создания UML диаграмм StarUML version 3.1.0;
 язык программирования C#.
Данная программное средство будет разрабатываться в среде программирования Visual
Studio 2019. Данная среда содержит богатый набор различных типов данных и компонентов,
облегчающих создание программного продукта под ОС Windows.
Windows 10 – является наиболее популярной и удобной операционной системой.
Система призвана стать единой для разных устройств, таких как персональные компьютеры,
планшеты, смартфоны, консоли и т.д.
Язык программирования C# – объектно-ориентированный язык программирования.
Разработан в 1998-2001 годах группой инженеров компании Microsoft, как язык разработки
приложений для платформы Microsoft .NET Framework.
C# относится к семье языков с C-подобным синтаксисом, из них его синтаксис наиболее
близок к C++ и Java. Язык имеет статическую типизацию, поддерживает полиморфизм,
перегрузку операторов (в том числе операторов явного и неявного приведения типа), делегаты,
атрибуты, события, свойства, обобщённые типы и методы, итераторы, анонимные функции с
поддержкой замыканий, LINQ, исключения, комментарии в формате XML.
Переняв многое от своих предшественников  языков C++, Delphi, Модула, Smalltalk и, в
особенности, Java  С#, опираясь на практику их использования, исключает некоторые модели,
зарекомендовавшие себя как проблематичные при разработке программных систем, например,
C# в отличие от C++ не поддерживает множественное наследование классов (между тем
допускается множественное наследование интерфейсов).
Visual Studio 2019  полнофункциональная интегрированная среда разработки (IDE) для
приложений Android, iOS, Windows, веб- и облачных приложений. Написана на: C++ и C# [19].
Visual Studio Code  редактор исходного кода, разработанный Microsoft для Windows,
Linux и macOS. Позиционируется как «лёгкий» редактор кода для кроссплатформенной
разработки веб- и облачных приложений. Написана на: TypeScript и JavaScript [18].
Microsoft SQL Server Express  это версия системы управления реляционными базами
данных Microsoft SQL Server, которую можно бесплатно загружать, распространять и

12
использовать. Он содержит базу данных, специально предназначенную для встроенных и
небольших приложений.
StarUML  это сложный программный моделлер, предназначенный для поддержки
гибкого и лаконичного моделирования. Написан на Delphi [20].

13
3 Проектирование задачи

3.1 Требования к приложению

Согласно общим требованиям стандартный графический интерфейс разрабатываемого


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

Средства защиты у данного приложения существуют. При входе, если пользователь не


введёт валидные значения в поля «AdminName» и «Password» в форме для заполнения «Sign in»
вход в программу не произойдёт.

3.2Концептуальный прототип

Концептуальный прототип представляет собой описание внешнего пользовательского


интерфейса  системы меню, диалоговых окон и элементов управления.
При создании приложения важную роль играют формы, так как они являются основным
диалоговым средством работы пользователя. Разрабатываемое приложение будет
многооконное, то есть содержать несколько форм.
Для ввода и вывода данных будут использованы стандартные компоненты.
Основной интерфейс представлен стандартной формой, которая содержит стандартные
пользовательские элементы управления.
При запуске программы будет открываться форма «Sign in». После авторизации
запускается главная форма, на форме расположены кнопки для доступа к формам: «Home»,
«List of waiters», «Category», «Menu», «Stock», «Order», «References system».
Форма «Sign in» главная форма, которая предназначена для входа в систему. Имеет
кнопки, «Sign in».
Форма «Home» главная форма, которая приветствует пользователя приложения.
Форма «List of waiters» содержит информацию о рабочем персонале. Имеет кнопки,
«Add», «Delete».
Форма «Category» содержит информацию о категориях блюд и напитков. Имеет кнопки,
«Edit», «Add», «Delete».
Форма «Menu» содержит информацию о блюдах и напитках. Имеет кнопки, «Edit»,
«Add», «Delete».
Форма «Stock» содержит информацию об ингредиентах на складе. Имеет кнопки, «Edit»,
«Add», «Delete».
Форма «Order» содержит информацию о сделанных заказах. Имеет кнопки, «Edit»,
«Add», «Delete», «Export all to Excel».

Форма «Search and sort» будет осуществлять выборку элемента по определённым


критерия с базы данных.

14
Форма «References system» содержит справочную систему для данного приложения.
Кнопка «Edit» будет редактировать выбранный элемент в базе данных.
Кнопка «Add» будет добавлять новый элемент в базу данных.
Кнопка «Delete» будет удалять элементы с базы данных.

Макет формы «Home» представлен на рисунке 3.1.

Рисунок 3.1

Макет форм «List of waiters», «Category», «Menu», «Stock», «Order» представлен на


рисунке 3.2.

Рисунок 3.2

Макет формы «Search and sort» представлен на рисунке 3.3.

Рисунок 3.3
Макет формы «Sign in» представлен на рисунке 3.3.

15
Рисунок 3.3

3.3 Организация данных

Организация данных подразумевает создание модели данных, главными элементами


которой являются сущности и их связи.
Реляционная модель основана на математическом понятии отношения, представлением
которого является таблица. В реляционной модели отношения используются для хранения
информации об объектах, представленных в базе данных. Отношение имеет вид двухмерной
таблицы, в которой строки соответствуют записям, а столбцы – атрибутам. Каждая запись
должна однозначно характеризоваться в таблице. Для этого используют первичные и
вторичные ключи. Достоинством реляционной модели является простота и удобство
физической реализации.
Реляционная модель базы данных подразумевает нормализацию всех таблиц данных.
Нормализация – это формальный метод анализа отношений на основе их первичного ключа и
функциональных зависимостей, существующих между их атрибутами [21].

Таблица «Order» хранит информацию о заказах, структура которой приведена в таблице


3.1.

Таблица 3.1 – Структура таблицы «Order»


Имя поля Тип поля Размер поля, байт Описание поля

id INTEGER 4 Номер заказа

Date DATE 3 Дата заказа

numberTable INTEGER 4 Номер стола

Waiter INTEGER 4 Обслуживающей официант

totalPrice DECIMAL 12 Итоговая цена заказа

16
Таблица «Waiter» хранит информацию об официантах, структура которой приведена в
таблице 3.2.

Таблица 3.2 – Структура таблицы «Waiter»


Имя поля Тип поля Размер поля, байт Описание поля

id INTEGER 4 Номер официанта

name VARCHAR 255 Имя официанта

surname VARCHAR 255 Фамилия официанта

patronymic VARCHAR 255 Отчество официанта

Таблица «Drink» хранит информацию о напитках, структура которой приведена в


таблице 3.3.

Таблица 3.3 – Структура таблицы «Drink»


Имя поля Тип поля Размер поля, байт Описание поля

id INTEGER 4 Номер напитка

name VARCHAR 255 Название напитка

category INTEGER 4 Категории напитка

volume DECIMAL 12 Объём напитка

firstPrice DECIMAL 12 Себестоимость напитка

markUp DECIMAL 12 Надбавка

price DECIMAL 12 Отпускная цена

Таблица «Dish» хранит информацию о блюдах, структура которой приведена в таблице


3.4.

Таблица 3.4 – Структура таблицы «Dish»


Имя поля Тип поля Размер поля, байт Описание поля

id INTEGER 4 Номер блюда

name VARCHAR 255 Название блюда

category INTEGER 4 Категории блюда

Weight DECIMAL 12 Вес блюда

firstPrice DECIMAL 12 Себестоимость блюда

markUp DECIMAL 12 Надбавка

Price DECIMAL 12 Отпускная цена

Таблица «DishOrderInfo» хранит информацию о блюдах заказанные посетителем


(входящие в заказ), структура которой приведена в таблице 3.5.

Таблица 3.5 – Структура таблицы «DishOrderInfo»


17
Имя поля Тип поля Размер поля, байт Описание поля

id INTEGER 4 Номер блюда в заказе

dishId INTEGER 4 Номер блюда

orderId INTEGER 4 Номер заказа

Таблица «DrinkOrderInfo» хранит информацию о напитках заказанные посетителем


(входящие в заказ), структура которой приведена в таблице 3.6.

Таблица 3.6 – Структура таблицы «DrinkOrderInfo»


Имя поля Тип поля Размер поля, байт Описание поля

id INTEGER 4 Номер напитка в заказе

drinkId INTEGER 4 Номер напитка

orderId INTEGER 4 Номер заказа

Таблица «DishComposition» хранит информацию о составе блюда, структура которой


приведена в таблице 3.7.

Таблица 3.7 – Структура таблицы «DishComposition»


Имя поля Тип поля Размер поля, байт Описание поля

id INTEGER 4 Номер состава блюда

idDish INTEGER 4 Номер блюда

idIng INTEGER 4 Номер ингредиента

amount INTEGER 4 Количество


ингредиентов

Таблица «Category» хранит информацию о категориях блюд и напитков, структура


которой приведена в таблице 3.8.

Таблица 3.8 – Структура таблицы «Category»


Имя поля Тип поля Размер поля, байт Описание поля

id INTEGER 4 Номер категории

name VARCHAR 255 Название категории

Таблица «Ingredient» хранит информацию об ингредиентах, структура которой


приведена в таблице 3.9.

Таблица 3.9 – Структура таблицы «Ingredient»


Имя поля Тип поля Размер поля, байт Описание поля

id INTEGER 4 Номер ингредиента

name VARCHAR 255 Название ингредиента

Продолжение таблицы 3.9

18
Имя поля Тип поля Размер поля, байт Описание поля

weight DECIMAL 12 Вес блюда

units INTEGER 4 Единица измерение

firstPrice DECIMAL 12 Себестоимость блюда

Таблица «Stock» хранит информацию о хранящихся ингредиентах на складе, структура


которой приведена в таблице 3.10.

Таблица 3.10 – Структура таблицы «Stock»


Имя поля Тип поля Размер поля, байт Описание поля

id INTEGER 4 Номер склада

idIng INTEGER 4 Ингредиент

unitPrice DECIMAL 12 Цена за единицу


ингредиента

Таблица «Units» хранит информацию о единицах измерения, структура которой


приведена в таблице 3.11.

Таблица 3.11 – Структура таблицы «Units»


Имя поля Тип поля Размер поля, байт Описание поля

id INTEGER 4 Номер единицы


измерения
name VARCHAR 255 Наименование единицы
измерения

Схема базы данных представлена на рисунке 3.4.

Рисунок 3.4  Схема базы данных

19
3.4Функции: логическая и физическая организация

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


данных. Добавление и редактирование данных в базе производится нажатием по
соответственной кнопке и заполнение формы. Удаление из базы производится, также, нажатием
на кнопку соответствующего элемента.
Функции, которые будет выполнять программное средство  это ведение данных в базе
данных, добавление новых данных, их редактирование, удаление и просмотр данных.
Для добавления нового элемента в любую сущность данного приложения, необходимо
будет перейти на нужную модель сущности и нажать на кнопку «Add». После нажатия на
кнопку «Add» вызовется обработчик события handleSubmit, который обрабатывает заполненные
поля формы и отправит Http запрос. Код реализации данной функции представлен ниже.

handleSubmit=(event)=>{
event.preventDefault();
axios.post(`https://localhost:44399/api/Order/create?${qs.stringify({
Date: event.target.date.value,
NumberTable: event.target.numberTable.value,
WaiterId: event.target.waiter.value,
TotalPrice: event.target.totalPrice.value
})}`)
.then(res=> {
console.log(res.data);
this.setState({snackBaropen: true, snackBarMessage: 'Added successfully'});
})
.catch(error=> {
console.log(error);
this.setState({snackBaropen: true, snackBarMessage: 'Failed added'});
});
}

Для редактирования элемента в любую сущность данного приложения, кроме модели


«List of waiters», необходимо будет перейти на нужную модель сущности и нажать на кнопку
«Edit». После нажатия на кнопку «Edit» вызовется обработчик события handleSubmit, который
обрабатывает изменённые поля формы и отправляет Http запрос. Код реализации данной
функции представлен ниже.

handleSubmit(event){
event.preventDefault();
axios.put(`https://localhost:44399/api/Order/update?${qs.stringify({
Id: event.target.id.value,
Date: event.target.date.value,
NumberTable: event.target.numberTable.value,
WaiterId: event.target.waiter.value,
TotalPrice: event.target.totalPrice.value
})}`)
.then(res=> {
console.log(res.data);
this.setState({snackBaropen: true, snackBarMessage: 'Updated successfully'});
})
.catch(error=> {
console.log(error);

20
this.setState({snackBaropen: true, snackBarMessage: 'Failed to update'});
});
}

Для удаления элемента в любую сущность данного приложения, необходимо будет


перейти на нужную модель сущности и нажать на кнопку «Delete». После нажатия на кнопку
«Delete» вызовется обработчик события delete…, который отображает окно соглашения, после
соглашения которого отправляет Http запрос. Код реализации данной функции представлен
ниже.

deleteOrder(orderId){
if(window.confirm('Are you sure?')){
axios.delete(`https://localhost:44399/api/Order/delete/${orderId}`)
.then(res=> {
console.log(res.data);
})
.catch(error=> {
console.log(error);
});
}
}

Полный текст программы представлен в приложении А.

3.5 Проектирование справочной системы приложения

Справочная система в данном проекте будет реализована в правом верхнем углу панели
меню и содержать:
- основные цели данного приложения;
- описание кнопок и действий в данном приложении;
- список основных разделов приложения в панели меню:
- Home  главная страница приложения. Приветствует пользователя.
- List of waiters  страница для просмотра и работы со списком обслуживающего
персонала.
- Category  страница для просмотра и работы со списком существующих
категорий блюд и напитков.
- Menu/Dishes  страница для просмотра и работы со списком существующих
блюд.
- Menu/Drinks  страница для просмотра и работы со списком существующих
напитков.
- Stock  страница для просмотра и ведения учёта наличия ингредиентов.
- Order  страница для просмотра и ведения учёта сделанных заказов.
- ?  страница справочной системы.
Данная справочная система будет разработана средствами JavaScript-библиотеки  React.

21
4 Описание программного средства

4.1Общие сведения

Программное средство Cafe.sln предназначено для автоматизации работы


администратора кафе. Это приложение позволит уменьшить затраты времени, используемого
при учете работ, добавлении, изменении, удалении данных.
Данное программное средство было разработано на персональном компьютере со
следующей конфигурацией:
 процессор Intel Core i7 7700K 4.20 ГГц;
 оперативная память DDR4 16 ГБ;
Программное средство создано в среде разработки Visual Studio 2019 на языке
программирования C# в операционной системе Windows 10, а также в среде Visual Studio Code
на языке программирования JavaScript. Оно также может работать в средах операционных
систем семейства Microsoft Windows, начиная с Windows 7.
Для запуска данного программного средства следует запустить программное средство,
разработанную в Visual Studio 2019,  Cafe.sln, а затем графическую оболочку через терминал
редактора Visual Studio Code с помощью команды  npm start.

4.2Функциональное назначение

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


Целью программного средства является снижение бумажной работы, уменьшение количества
ошибок, быстрое использовать данных.
Программное средство использует стандартные элементы управления, такие как кнопки,
списки, таблицы, поля ввода и вывода, что обеспечивает удобство в использовании, понятный и
удобный интерфейс программного средства. Все данные хранятся в базе данных, созданная
средствами Microsoft SQL.
Таким образом, программное средство может применяться в реальных условиях,
представляя собой достаточно удобный помощник.
Средства защиты у данного приложения существуют. При входе, если пользователь не
введёт валидные значения в поля «AdminName» и «Password» в форме для заполнения «Sign in»
вход в программу не произойдёт.

4.3 Входные и выходные данные

Входными являются данные введёнными пользователем при добавлении новой


информации в базу.
Входными данными при добавлении новой информации в сущность «Category»
являются: name.
Форма «Adding category» представлен на рисунке 4.1.

22
Рисунок 4.1

Входными данными при добавлении новой информации в сущность «Dish» являются:


 name;
 category;
 weight;
 first price;
 mark up;
 price.
Форма «Adding dish» представлен на рисунке 4.2.

Рисунок 4.2

Входными данными при добавлении новой информации в сущность «Drink» являются:


 name;
 category;
23
 volume;
 first price;
 mark up;
 price.
Форма «Adding drink» представлен на рисунке 4.3.

Рисунок 4.3

Входными данными при добавлении новой информации в сущность «Units» являются:


 name.
Форма «Adding unit» представлен на рисунке 4.4.

Рисунок 4.4

Входными данными при добавлении новой информации в сущность «Ingredient»


являются:
 name;
24
 weight;
 units;
 first price.
Форма «Adding unit» представлен на рисунке 4.5.

Рисунок 4.5

Входными данными при добавлении новой информации в сущность «Waiter» являются:


 surname;
 name;
 patronymic.
Форма «Adding waiter» представлен на рисунке 4.6.

Рисунок 4.6
25
Входными данными при добавлении новой информации в сущность «Order» являются:
 date;
 number of table;
 number of waiter;
 price.
Форма «Adding order» представлен на рисунке 4.7.

Рисунок 4.7

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


данном курсовом проекте документ будет содержать данные обо всех оформленных заказах.
Форма выходного документа представлена в приложении Б рисунок Б.1.

26
5 Методика испытаний

5.1 Технические требования

Минимальные системные требования к приложению:


 процессор Intel Core i5 8250U 1600 МГц;
 операционная система Windows 7 64-bit и выше;
 оперативная память DDR4 16 ГБ;
 места на HDD 500 МБ;
 материнская плата Gigabyte G1.
Для удобного использования данного приложения, необходимо наличие мышки,
клавиатуры и монитора.
Компьютер должен работать под управлением операционной системы, начиная с
Windows 7 и выше. Наиболее удобной операционной системой для проведения испытаний
является Windows 10, так как она ориентирована на максимальное использование всех
возможностей ПК, сетевых ресурсов и обеспечение комфортных условий работы.

5.2 Функциональное тестирование

В процессе написания программного средства необходимо производить тестирование на


правильность работы приложения. Одной из основных задач тестирования является устранение
ошибок, происходящих при вводе данных.
Функциональное тестирование  это тестирование функций приложения на соответствие
требованиям. Оценка производится в соответствии с ожидаемыми и полученными результатами
(на основании функциональной спецификации), при условии, что функции отрабатывали на
различных значениях [22].

Тестирование всего программного средства происходит по средствам проверки всех


функций, представленных в программном средстве. Первый тест будет проведён в окне
авторизации программы, которое представлено на рисунке 5.1.

Рисунок 5.1  Окно авторизации  форма «Sign in»


27
Таблица 5.1  Тест-кейс функции авторизации
№ Функция Шаги выполнения Результат

Авторизация в 1. Заполнить требуемые поля Ожидаемый результат:


приложении данными: Произойдёт переход на страницу
- "AdminName"  admin Home
1 - "Password" – admin Фактический результат:
2. Нажать на кнопку «Sign in». Все поля заполнены
Результат: успешный переход на
страницу Home, представлен на
рисунке 5.2

Рисунок 5.2  Результат авторизации

Второй тест будет проведён в форме «Menu/Dish».

Рисунок 5.3  Форма «Menu/Dish»

Таблица 5.2  Тест функции добавления блюда


№ Функция Шаги выполнения Результат

Добавление блюда в 1. Нажать на пункт панели меню Ожидаемый результат:


меню в приложении «Menu/Dish»; Произойдёт добавление блюда в
2. Нажать на кнопку «Add dish»; базу
3. В открывшемся окне заполнить Фактический результат:
поля: Все поля заполнены,
2  «Dish name»  Salad Olivier представлено на рисунке 5.4
 «Dish category»  1 Результат: появление нового
 «Dish weight»  350 блюда в списке и отображение
 «Dish first price»  200 сообщения «Added successfully»,
 «Dish mark up»  9.3 представлен на рисунке 5.5
 «Dish price»  211.5
4. Нажать на кнопку «Add dish».

28
Рисунок 5.4  Окно добавления блюда

Рисунок 5.5  Результат добавления блюда

Третий тест будет проведён также в форме «Menu/Dish».

Рисунок 5.6  Форма «Menu/Dish»

29
Таблица 5.3  Тест функции изменение данных о блюде
№ Функция Шаги выполнения Результат

Редактирование 1. Нажать на пункт панели меню Ожидаемый результат:


блюда в меню в «Menu/Dish»; Произойдёт изменение данных о
приложении 2. Нажать на кнопку блюде и обновление их в базе
соответствующего блюда « »; Фактический результат:
3. В открывшемся окне заполнить Все поля заполнены,
поля: представлено на рисунке 5.7
3
 «Dish name»  French meat Результат: появление
 «Dish category»  3 изменённого блюда в списке и
 «Dish weight»  350 отображение сообщения «Updated
 «Dish first price»  250 successfully», представлен на
 «Dish mark up»  7.4 рисунке 5.8
 «Dish price»  270
4. Нажать на кнопку «Edit dish».

Рисунок 5.7  Окно изменений данных о блюде

Рисунок 5.8  Результат изменения данных о блюде

30
Четвёртый тест будет проведён также в форме «Menu/Dish».

Рисунок 5.9  Форма «Menu/Dish»

Таблица 5.4  Тест функции удаления блюда со списка


№ Функция Шаги выполнения Результат

Удаление блюда со 1. Нажать на пункт панели меню Ожидаемый результат:


списка меню в «Menu/Dish»; Произойдёт удаление блюда со
приложении 2. Нажать на кнопку списка и удаление его из базы
соответствующего блюда « »; Фактический результат:
4
3. В отобразившемся диалоговом Кнопка нажата, представлено на
окне нажать кнопку «ОК». рисунке 5.10
Результат: удаление блюда со
списка, представлено на рисунке
5.11

Рисунок 5.10  Диалоговой окно для удаления блюда

Рисунок 5.11  Результат удаления блюда

31
Пятый тест будет проведён также в форме «Menu/Dish».

Рисунок 5.12  Форма «Menu/Dish»

Таблица 5.5  Тест функции поиска блюда


№ Функция Шаги выполнения Результат

Поиск блюда по 1. Нажать на пункт панели меню Ожидаемый результат:


названию в списке «Menu/Dish»; Произойдёт отображение
меню в приложении 2. Ввести название в строку нужного блюда в списке
поиска: Фактический результат:
5
 «Search…»  Salad Название введено, представлено
на рисунке 5.13
Результат: отображение блюда в
списке, представлено на рисунке
5.13

Рисунок 5.13  Результат поиска блюда

Шестой тест будет проведён также в форме «Menu/Dish».

Рисунок 5.14  Форма «Menu/Dish»


32
№ Функция Шаги выполнения Результат

Сортировка блюд по 1. Нажать на пункт панели меню Ожидаемый результат:


итоговой цене в списке «Menu/Dish»; Произойдёт отображение
меню в приложении 2. Ввести цены в строки отсортированных блюд в списке
сортировок: Фактический результат:
6
 «Min price»  40 Цены введены, представлено на
 «Max price»  260 рисунке 5.15
Результат: отображение
отсортированных блюд в списке,
представлено на рисунке 5.15

Рисунок 5.15  Результат сортировки блюд

33
6 Применение

6.1 Назначение программы

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


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

6.2Условия применения

Для применения данного программного средства необходимы следующие технически


требования и инструменты:
 процессор Intel Core i5 8250U 1600 МГц;
 операционная система Windows 7 64-bit и выше;
 оперативная память DDR4 16 ГБ;
 места на HDD 500 МБ;
 материнская плата Gigabyte G1;
 клавиатура, мышь;
 среда разработки Visual Studio 2019;
 среда разработки Visual Studio Code version 1.44 и выше;
 среда разработки Microsoft SQL Server Express version 18.4 и выше.
Для запуска данного программного средства следует запустить программное средство,
разработанную в Visual Studio 2019,  Cafe.sln, а затем графическую оболочку через терминал
редактора Visual Studio Code с помощью команды  npm start. Microsoft SQL Server Express
требуется для того, чтобы создать и подключить базу данных.

6.3 Справочная система

Для корректной работы с приложением требуется обеспечить пользователя справочной


системой, в которой будут приведены действия работы с приложением, включающие данные о
том, что произойдёт после нажатия на определенную кнопку или при выборе пункта меню.
Существует страница справочной системы, на которой описаны основные цели данного
приложения, описание кнопок и действий в данном приложении, а также список основных
разделов приложения. Данная справочная система была разработана средствами JavaScript-
библиотеки  React. Форма «References system» представлен на рисунке 6.1.

34
Рисунок 6.1

35
Заключение

В рамках курсового проектирования на тему «Автоматизация рабочего места


администратора кафе» было разработано программное средство «Cafe.sln». Приложение
должно выполнять следующие функции:
 ведение единой базы данных, содержащая такие сущности как: «Category», «Dish»,
«Drink», «Units», «Ingredient», «DishComposition», «Stock», «Waiter», «Order», «DishOrderInfo»,
«DrinkOrderInfo»;
 производить поиск по названиям блюд и напитков;
 производить сортировку по цене блюд и напитков;
 формирование выходного документа Excel.
Для достижения цели курсового проектирования были решены следующие задачи:
- определена вычислительная система, необходимая для создания программного
средства;
- разработана физическая и логическая модель данных;
- по модели выполнено проектирование задачи;
- разработано программное средство;
- описано созданное программное средство;
- выбрана методика испытаний;
- описан процесс тестирования;
- приведены примеры области применения.
Проект был разработан в среде Visual Studio 2019 и Visual Studio Code на языке C# и
JavaScript-библиотеки  React. Пользовательский интерфейс разработан с помощью библиотеки
React.js. Для взаимодействия с базой данных для контекста данных должна быть определена
конфигурация подключения. Для ее установки было переопределение у класса контекста
данных метода OnConfiguring().
Программное средство имеет свои недостатки, такие как:
- нет нормальной выборки внешних ключей из базы данных;
- база данных создаётся пустая, так как её создание происходит через класс контекст,
без заполнения.
А также свои преимущества:
- удобный и понятный пользовательский интерфейс;
- минимальные системные требования.
Программное средство реализовано в полном объеме и в соответствии с заданными
требованиями, полностью отлажена и протестирована. Поставленные задачи выполнены.
Программное средство готово к практическому использованию и может быть дополнено
и модернизировано.

36
Список информационных источников

1. Михалевич В.Ю. Методические указания к курсовому проектированию для учащихся


специальности 2-40 01 01 «Программное обеспечение информационных технологий» /
В.Ю.Михалевич. – Минск: КБП, 2020

2. Багласова Т.Г. Методические указания по оформлению курсовых и дипломных


проектов / Т.Г.Багласова, К.О.Якимович. – Минск: КБП, 2013

3. Общие требования к тестовым документам: ГОСТ 2.105-95. – Введ. 01.01.1996. –


Минск: Межгос. совет по стандартизации, метрологии и сертификации, 1995.

4. Описание и текст программы. Требования к содержанию, оформлению и контролю


качества: ГОСТ 19.402-2000. – Введ. 01.09.2001. – Минск: Межгос. совет по стандартизации,
метрологии и сертификации, 2000.

5. Кафе [Электронный ресурс] – Wikipedia 2016 – Режим доступа:


https://ru.wikipedia.org/wiki/Кафе – Дата доступа: 11.05.2020

6. Основные должностные обязанности официанта в ресторане, кафе [Электронный


ресурс]  Заметки официанта 2020  Режим доступа: https://oficianty.com/obiazanosti-
oficianta.html  Дата доступа: 11.05.2020

7. Чем занимается администратор в кафе. Основные обязанности и должностная


инструкция администратора ресторана. Актуальность и необходимость профессии
[Электронный ресурс] – olimpikfood.ru 2020 – Режим доступа:
https://olimpikfood.ru/vypechka/chem-zanimaetsya-administrator-v-kafe-osnovnye-obyazannosti-i-
dolzhnostnaya/ – Дата доступа: 11.05.2020

8. Меню [Электронный ресурс] – Wikipedia 2018 – Режим доступа:


https://ru.wikipedia.org/wiki/Меню  Дата доступа: 11.05.2020

9. Заказ [Электронный ресурс] – Wikipedia 2020 – Режим доступа:


https://ru.wikipedia.org/wiki/Заказ  Дата доступа: 11.05.2020

10. Склад [Электронный ресурс] – Wikipedia 2020 – Режим доступа:


https://ru.wikipedia.org/wiki/Склад  Дата доступа: 11.05.2020

11. Структура управления кафе [Электронный ресурс]  StudFiles  Режим доступа:


https://studfile.net/preview/8109157/  Дата доступа: 11.05.2020

12. Автоматизация заказов, учет и контроль, отчеты в реальном времени из любой


точки мира [Электронный ресурс] – Caffesta 2017 – Режим доступа: https://caffesta.com/ru/ 
Дата доступа: 11.05.2020

13. Разница межу INCLUDE и EXTEND диаграмма вариантов использования (use


case) [Электронный ресурс]  fkn+antitotal  Режим доступа: http://fkn.ktu10.com/?q=node/2236 
Дата доступа: 11.05.2020

14. Понятие складов, их функции [Электронный ресурс] – Знайтовар.Ру - торговля,


бизнес, товароведение, экспертиза 2020– Режим доступа:
https://znaytovar.ru/s/Ponyatie_skladov_ix_funkcii.html  Дата доступа: 11.05.2020

37
15. Учебник. Создание веб-API с помощью ASP.NET Core [Электронный ресурс] –
Microsoft, 2019 – Режим доступа: https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-web-
api?view=aspnetcore-3.1&tabs=visual-studio  Дата доступа: 11.05.2020

16. Data Annotations - ForeignKey Attribute in EF 6 & EF Core [Электронный ресурс] –


Entity Framework Tutorial – Режим доступа: https://www.entityframeworktutorial.net/code-
first/foreignkey-dataannotations-attribute-in-code-first.aspx  Дата доступа: 11.05.2020

17. React JS. Подключение React в ASP.NET Core [Электронный ресурс] – Metanit –
Режим доступа: https://metanit.com/sharp/aspnet5/25.1.php  Дата доступа: 11.05.2020

18. Visual Studio Code [Электронный ресурс]  Wikipedia  Режим доступа:


https://ru.wikipedia.org/wiki/Visual_Studio_Code  Дата доступа: 29.05.2020

19. Visual Studio [Электронный ресурс]  Microsoft  Режим доступа:


https://visualstudio.microsoft.com/ru/downloads/  Дата доступа: 29.05.2020

20. StarUML [Электронный ресурс]  Wikipedia  Режим доступа:


https://en.wikipedia.org/wiki/StarUML  Дата доступа: 29.05.2020

21. Hормализация таблиц, ее цель. Первая нормальная форма. Вторая нормальная


форма. Третья нормальная форма. [Электронный ресурс]  StudFiles  Режим доступа:
https://studfile.net/preview/7003805/page:17/  Дата доступа: 29.05.2020

22. Тестирование клиентского приложения [Электронный ресурс]  Режим


доступа:http://lib.kstu.kz:8300/tb/books/2014/IS/Proektirovanie%20i%20razrabotka%20prilozheniy
%20BD/lab/lr6.htm  Дата доступа: 30.05.2020

38
Приложение А
(обязательное)
Текст программы

//Cafe.sln
//Models
//ApplicationContext.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Cafe.Models.DBModels;
using Microsoft.EntityFrameworkCore;

namespace Cafe.Models
{
public class ApplicationContext : DbContext
{
public ApplicationContext()
{
//this.Database.EnsureDeleted();
this.Database.EnsureCreated();
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Data Source=.\\SQLEXPRESS;Initial
Catalog=kursach_db;Trusted_connection=True");
}

public virtual DbSet<Category> Categories { get; set; }


public virtual DbSet<DishComposition> DishCompositions { get; set; }
public virtual DbSet<Dish> Dishes { get; set; }
public virtual DbSet<Drink> Drinks { get; set; }
public virtual DbSet<Ingredient> Ingredients { get; set; }

public virtual DbSet<DrinkOrderInfo> DrinkOrderInfos { get; set; }


public virtual DbSet<DishOrderInfo> DishOrderInfos { get; set; }
public virtual DbSet<Order> Orders { get; set; }
public virtual DbSet<Stock> Stocks { get; set; }
public virtual DbSet<Units> Units { get; set; }
public virtual DbSet<Waiter> Waiters { get; set; }
}
}

//ErrorViewModel.cs
using System;

namespace Cafe.Models
{
public class ErrorViewModel
{

39
public string RequestId { get; set; }

public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);


}
}

//Models/DBModels
//Category.cs
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;

namespace Cafe.Models.DBModels
{
public class Category
{
public int Id { get; set; }
[Required]
public string Name { get; set; }

[JsonIgnore]
public ICollection<Dish> Dishes { get; set; }
[JsonIgnore]
public ICollection<Drink> Drinks { get; set; }
}
}

//Dish.cs
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;

namespace Cafe.Models.DBModels
{
public class Dish
{
public int Id { get; set; }
public string Name { get; set; }
[ForeignKey("Category")]
public int CategoryId { get; set; }
public Category Category { get; set; }
public double Weight { get; set; }
public double FirstPrice { get; set; }
public double MarkUp { get; set; }
public double Price { get; set; }

[JsonIgnore]
40
public ICollection<DishComposition> DishCompositions { get; set; }
[JsonIgnore]
public ICollection<DishOrderInfo> DishOrderInfos { get; set; }
}
}

//DishComposition.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;

namespace Cafe.Models.DBModels
{
public class DishComposition
{
public int Id { get; set; }
[ForeignKey("Dish")]
public int DishId { get; set; }
public Dish Dish { get; set; }
[ForeignKey("Ingredient")]
public int IngredientId { get; set; }
public Ingredient Ingredient { get; set; }
public int Amount { get; set; }
}
}

//DishOrderInfo.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;

namespace Cafe.Models.DBModels
{
public class DishOrderInfo
{
public int Id { get; set; }
[ForeignKey("Dish")]
public int DishId { get; set; }
public Drink Drink { get; set; }
[ForeignKey("Order")]
public int OrderId { get; set; }
public Order Order { get; set; }
}
}

//Drink.cs
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
41
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;

namespace Cafe.Models.DBModels
{
public class Drink
{
public int Id { get; set; }
public string Name { get; set; }
[ForeignKey("Category")]
public int CategoryId { get; set; }
public Category Category { get; set; }
public double Volume { get; set; }
public double FirstPrice { get; set; }
public double MarkUp { get; set; }
public double Price { get; set; }

[JsonIgnore]
public ICollection<DrinkOrderInfo> DrinkOrderInfos { get; set; }
}
}

//DrinkOrderInfo.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;

namespace Cafe.Models.DBModels
{
public class DrinkOrderInfo
{
public int Id { get; set; }
[ForeignKey("Drink")]
public int DrinkId { get; set; }
public Drink Drink { get; set; }
[ForeignKey("Order")]
public int OrderId { get; set; }
public Order Order { get; set; }
}
}

//Ingredient.cs
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;

namespace Cafe.Models.DBModels
42
{
public class Ingredient
{
public int Id { get; set; }
public string Name { get; set; }
public double Amount { get; set; }
[ForeignKey("Units")]
public int UnitId { get; set; }
public Units Units { get; set; }
public double FirstPrice { get; set; }

[JsonIgnore]
public ICollection<DishComposition> DishCompositions { get; set; }
[JsonIgnore]
public ICollection<Stock> Stocks { get; set; }
}
}

//Order.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;

namespace Cafe.Models.DBModels
{
public class Order
{
public int Id { get; set; }
public DateTime? Date { get; set; }
public int NumberTable { get; set; }
[ForeignKey("Waiter")]
public int WaiterId { get; set; }
public Waiter Waiter { get; set; }
public double TotalPrice { get; set; }
}
}

//Stock.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;

namespace Cafe.Models.DBModels
{
public class Stock
{
public int Id { get; set; }
[ForeignKey("Ingredient")]
public int IngredientId { get; set; }
43
public Ingredient Ingredient { get; set; }
public double TotalPrice { get; set; }
}
}

//Units.cs
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Cafe.Models.DBModels
{
public class Units
{
public int Id { get; set; }
public string Name { get; set; }

[JsonIgnore]
public ICollection<Ingredient> Ingredients { get; set; }
}
}

//Waiter.cs
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Cafe.Models.DBModels
{
public class Waiter
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Patronymic { get; set; }

[JsonIgnore]
public ICollection<Order> Orders { get; set; }
}
}

//Services/DBServices
//IDBService.cs
using System.Collections.Generic;
using Cafe.Models.DBModels;

namespace Cafe.Services.DBServices
{
public interface IDBService<T>
44
{
bool Create(T entity);
IList<T> GetAll();
T GetById(int id);
bool Remove(int id);
bool Update(T newEntity);
}
}

//DBOrderService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Cafe.Models;
using Cafe.Models.DBModels;
using Microsoft.EntityFrameworkCore;

namespace Cafe.Services.DBServices
{
public class DBOrderService : IDBService<Order>
{
public bool Create(Order entity)
{
if (entity == null)
{
return false;
}
using (var context = new ApplicationContext())
{
var state = context.Add(entity).State;

if (state != EntityState.Added)
{
return false;
}

try
{
context.SaveChanges();

}
catch
{
return false;
}

return true;
}
}

public IList<Order> GetAll()


{
45
using (var context = new ApplicationContext())
{
return context.Orders.ToList();
}
}

public Order GetById(int id)


{
using (var context = new ApplicationContext())
{
return context.Orders.FirstOrDefault(x => x.Id == id);
}
}

public bool Remove(int id)


{
using (var context = new ApplicationContext())
{
var deleted = context.Orders.FirstOrDefault(x => x.Id == id);

if (deleted == null)
{
return false;
}

var result = context.Orders.Remove(deleted).State;

if (result != EntityState.Deleted)
{
return false;
}

try
{
context.SaveChanges();
}
catch
{
return false;
}

return true;
}
}

public bool Update(Order newEntity)


{
if (newEntity == null)
{
return false;
}
using (var context = new ApplicationContext())
{
46
var prevEntity = context.Orders.FirstOrDefault(x => x.Id == newEntity.Id);

if (prevEntity == null)
{
return false;
}

prevEntity.Date = newEntity.Date;
prevEntity.NumberTable = newEntity.NumberTable;
prevEntity.WaiterId = newEntity.WaiterId;
prevEntity.TotalPrice = newEntity.TotalPrice;

try
{
context.SaveChanges();
}
catch
{
return false;
}

return true;
}
}
}
}

//Controllers
//HomeController.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Cafe.Models;

namespace Cafe.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}

public IActionResult Privacy()


{
return View();
}

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore =


true)]
47
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ??
HttpContext.TraceIdentifier });
}
}
}

//OrderController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Cafe.Models.DBModels;
using Cafe.Services.DBServices;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Office.Interop.Excel;
using System.IO;

namespace Cafe.Controllers
{
[Route("api/[controller]")]
[EnableCors("AllowMyOrigin")]
public class OrderController : Controller
{
private readonly DBOrderService service;

public OrderController(DBOrderService service)


{
this.service = service;
}

[HttpPost("create")]
public bool Create(Order order)
{
return service.Create(order);
}

[HttpPut("update")]
//[FromBody]
public bool Update(Order order)
{
return service.Update(order);
}

[HttpGet("getById/{id}")]
public Order GetById(int id)
{
return service.GetById(id);
}

48
[HttpDelete("delete/{id}")]
public bool Delete(int id)
{
return service.Remove(id);
}

[HttpGet("getAll")]
public IList<Order> GetAll()
{
return service.GetAll();
}

private void CheckFile()


{
if (!System.IO.File.Exists("C:\\Report.xlsx"))
{
System.IO.File.Create("C:\\Report.xlsx");
}
}

[HttpGet("excelDoc")]
public void WriteDataToExcel()
{
//string sheetName = "";
List<Order> orders = GetAll().ToList();

Microsoft.Office.Interop.Excel.Application oXL = new


Microsoft.Office.Interop.Excel.Application();
//CheckFile();
//_Workbook oWB = oXL.Workbooks.Open("C:\\Report.xlsx");
oXL.Visible = false;
oXL.DisplayAlerts = false;
//_Worksheet oSheet = string.IsNullOrEmpty(sheetName) ?
(_Worksheet)oWB.ActiveSheet : (_Worksheet)oWB.Worksheets[sheetName];
var worKbooK = oXL.Workbooks.Add(Type.Missing);
var oSheet = (Microsoft.Office.Interop.Excel.Worksheet)worKbooK.ActiveSheet;

oSheet.Cells.ClearContents();

oSheet.Cells[1, 1] = "Order number";


oSheet.Cells[1, 2] = "Order date";
oSheet.Cells[1, 3] = "Number table";
oSheet.Cells[1, 4] = "Waiter Id";
oSheet.Cells[1, 5] = "Order total price";

int i = 2;
foreach (Order order in orders)
{
oSheet.Cells[i, 1] = order.Id.ToString();
oSheet.Cells[i, 2] = order.Date.ToString();
oSheet.Cells[i, 3] = order.NumberTable.ToString();
oSheet.Cells[i, 4] = order.WaiterId.ToString();
oSheet.Cells[i, 5] = order.TotalPrice.ToString();
49
++i;
}

worKbooK.SaveAs("C:\\Report.xlsx");
if (worKbooK != null)
{
worKbooK.Close();
}
}
}
}

//Program.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace Cafe
{
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>


WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}

//Startup.cs
using System;
using Cafe.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Cafe.Services.DBServices;
using Microsoft.AspNetCore.Mvc.Cors.Internal;

namespace Cafe
{
public class Startup
50
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed
for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddDbContext<ApplicationContext>();

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

services.AddSingleton(typeof(DBCategoryService));
services.AddSingleton(typeof(DBDishCompositionService));
services.AddSingleton(typeof(DBDishOrderInfoService));
services.AddSingleton(typeof(DBDishService));
services.AddSingleton(typeof(DBDrinkOrderInfoService));
services.AddSingleton(typeof(DBDrinkService));
services.AddSingleton(typeof(DBIngredientService));
services.AddSingleton(typeof(DBOrderService));
services.AddSingleton(typeof(DBStockService));
services.AddSingleton(typeof(DBUnitsService));
services.AddSingleton(typeof(DBWaiterService));

//add Core react


services.AddCors(options =>
{
options.AddPolicy("AllowMyOrigin",
builder =>
builder.WithOrigins("http://localhost:3000").WithMethods("*").WithHeaders("*"));
});
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new CorsAuthorizationFilterFactory("AllowMyOrigin"));
});
}

// This method gets called by the runtime. Use this method to configure the HTTP request
pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
51
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production
scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});

//use core react


app.UseCors("AllowMyOrigin");
}
}
}

//src
//index.css
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}

//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
52
    <App />,
  document.getElementById('root')
);

serviceWorker.unregister();

//App.js
import React from 'react';
import './App.css';
import Home from './components/Home';
import Categories from './components/Category/Categories';
import Dishes from './components/Dish/Dishes';
import Drinks from './components/Drink/Drinks';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
import Navigation from './components/Navigation';
import Waiters from './components/Waiter/Waiters';
import Reference from './components/ReferencesSystem/References';
import SignInModal from './components/SignInModal/SignInModal';
import Units from './components/Unit/Units';
import Stock from './components/Stock/Stock';
import Orders from './components/Order/Orders';

function App() {
  return (
    <BrowserRouter>
        <div className="container">

          <h1 className='m-3 d-flex justify-content-center'>Cafe</h1>
            <Navigation/>

            <Switch>
              <Route path='/' component={SignInModal} exact/>
              <Route path='/home' component={Home}/>
              <Route path='/waiters' component={Waiters}/>
              <Route path='/categories' component={Categories}/>
              <Route path='/menu/dishes' component={Dishes}/>
              <Route path='/menu/drinks' component={Drinks}/>
              <Route path='/units' component={Units}/>
              <Route path='/stock' component={Stock}/>
              <Route path='/orders' component={Orders}/>
              <Route path='/help' component={Reference}/>
            </Switch>
        </div>
    </BrowserRouter>
  );
}

export default App;

//App.css
.App {
  text-align: center;
}
53
.App-logo {
  height: 40vmin;
  pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  .App-logo {
    animation: App-logo-spin infinite 20s linear;
  }
}

.App-header {
  background-color: #282c34;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white;
}

.App-link {
  color: #61dafb;
}

@keyframes App-logo-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

//src/components
//Home.js
import React, {Component} from 'react';

export default class Home extends Component{

    render(){
        return(
            <div className='mt-5'>
                <h1>Home</h1>
                <h3>Welcome to the Cafe app</h3>
            </div>
        );
    };
};

//Navigation.js
54
import React, {Component} from 'react';
import {NavLink} from 'react-router-dom';
import {Navbar, Nav, NavDropdown} from 'react-bootstrap';
import HelpOutlineIcon from '@material-ui/icons/HelpOutline';

export default class Navigation extends Component{

    render(){
        return(
            <Navbar bg='dark' expand='sm'>
                <Navbar.Toggle aria-controls='basic-navbar-nav'/>
                <Navbar.Collapse id='basic-navbar-nav'>
                    <Nav className='col-sm-11'>
                        <NavLink className='d-inline p-2 bg-dark text-white badge-pill' to='/home'>
                            Home
                        </NavLink>
                        <NavLink className='d-inline p-2 bg-dark text-white badge-pill' to='/waiters'>
                            List of waiters
                        </NavLink>
                        <NavLink className='d-inline p-2 bg-dark text-white badge-pill' to='/categorie
s'>
                            Category
                        </NavLink>
                        <NavDropdown title="Menu" color='inherit'>
                            <NavDropdown.Item href='/menu/dishes'>Dishes</NavDropdown.Item>
                            <NavDropdown.Divider />
                            <NavDropdown.Item href='/menu/drinks'>Drinks</NavDropdown.Item>
                        </NavDropdown>
                        <NavLink className='d-inline p-2 bg-dark text-white badge-pill' to='/orders'>
                            List of orders
                        </NavLink>
                        <NavLink className='d-inline p-2 bg-dark text-white badge-pill' to='/units'>
                            Units
                        </NavLink>
                        <NavLink className='d-inline p-2 bg-dark text-white badge-pill' to='/stock'>
                            Stock
                        </NavLink>
                    </Nav>
                    <Nav>
                    <NavLink className='d-inline p-2 bg-dark text-white badge badge-secondary bad
ge-pill' to='/help'>
                            {<HelpOutlineIcon/>}
                        </NavLink>
                    </Nav>
                </Navbar.Collapse>
            </Navbar>
        );
    };
};

//src/components/Order
//AddOrderModal.js
import React, {Component} from 'react';
55
import {Modal, Row, Col, Form} from 'react-bootstrap';
import {Button} from 'react-bootstrap';
import SnackBar from '@material-ui/core/Snackbar';
import IconButton from "@material-ui/core/IconButton";
import Tooltip from '@material-ui/core/Tooltip';
import CloseIcon from '@material-ui/icons/Close';
import axios from 'axios';
import qs from 'querystring';

export default class AddOrderModal extends Component{

    constructor(props){
        super(props);
        this.state = {waiters:[], snackBaropen: false, snackBarMessage: '',
        number: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] };
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    componentDidMount(){
        axios.get(`https://localhost:44399/api/Waiter/getAll`)
        .then(res=> {
            this.setState({waiters: res.data})
        });
    }

    snackBarClose=(event)=>{
        this.setState({snackBaropen: false});
    }

    handleSubmit=(event)=>{
        event.preventDefault();
        axios.post(`https://localhost:44399/api/Order/create?${qs.stringify({
            Date: event.target.date.value,
            NumberTable: event.target.numberTable.value,
            WaiterId: event.target.waiter.value,
            TotalPrice: event.target.totalPrice.value
        })}`)
        .then(res=> {
            console.log(res.data);
            this.setState({snackBaropen: true, snackBarMessage: 'Added successfully'});
        })
        .catch(error=> {
            console.log(error);
            this.setState({snackBaropen: true, snackBarMessage: 'Failed added'});
        });
    }

    render(){
        return(
            <div className='container'>
                <SnackBar
                anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
                open={this.state.snackBaropen}
56
                autoHideDuration={1000}
                onClose={this.snackBarClose}
                message={<span id='message-id'>{this.state.snackBarMessage}</span>}
                action={[
                    <IconButton color="inherit" size="small"
                    onClick={this.snackBarClose}
                    ><CloseIcon/></IconButton>
                ]}/>

                <Modal
                    {...this.props}
                    size="lg"
                    aria-labelledby="contained-modal-title-vcenter"
                    centered>
                    <Modal.Header closeButton>
                        <Modal.Title id="contained-modal-title-vcenter">
                            Adding order
                        </Modal.Title>
                    </Modal.Header>
                    <Modal.Body>
                        <Row>
                            <Col sm={6}>
                                <Form onSubmit={this.handleSubmit}>
                                    <Form.Group controlId="date">
                                        <Form.Label>Order date</Form.Label>
                                        <Form.Control 
                                        type="date"
                                        name="date"
                                        required
                                        placeholder="Order date"/>
                                    </Form.Group>
                                    <Form.Group controlId="numberTable">
                                        <Form.Label>Number table</Form.Label>
                                        <Form.Control as="select">
                                            {this.state.number.map(num=>
                                                <option key={num}>{num}</option>
                                            )}
                                        </Form.Control>
                                    </Form.Group>
                                    <Form.Group controlId="waiter">
                                        <Form.Label>Number of waiter</Form.Label>
                                        <Form.Control as="select">
                                            {this.state.waiters.map(waiter=>
                                            <Tooltip key={waiter.id} title={waiter.name + ' ' + waiter.surname}
>
                                                <option key={waiter.id}>{waiter.id}</option>
                                            </Tooltip>
                                            )}
                                        </Form.Control>
                                    </Form.Group>
                                    <Form.Group controlId="totalPrice">
                                        <Form.Label>Order total price</Form.Label>
                                        <Form.Control 
57
                                        type="text"
                                        name="totalPrice"
                                        required
                                        placeholder="Order total price"/>
                                    </Form.Group>
                                    <Form.Group>
                                        <Button variant="primary" type="submit">
                                            Add order
                                        </Button>
                                    </Form.Group>
                                </Form>
                            </Col>
                        </Row>
                    </Modal.Body>
                    <Modal.Footer>
                        <Button variant="primary" onClick={this.props.onHide}>
                            Close
                        </Button>
                    </Modal.Footer>
                </Modal>
            </div>
        )
    }
}

//EditOrderModal.js
import React, {Component} from 'react';
import {Modal, Row, Col, Form} from 'react-bootstrap';
import {Button} from 'react-bootstrap';
import SnackBar from '@material-ui/core/Snackbar';
import IconButton from "@material-ui/core/IconButton";
import Tooltip from '@material-ui/core/Tooltip';
import CloseIcon from '@material-ui/icons/Close';
import axios from 'axios';
import qs from 'querystring';

export default class EditOrderModal extends Component{

    constructor(props){
        super(props);
        this.state = {waiters:[], snackBaropen: false, snackBarMessage: '',
        number: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] };
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    componentDidMount(){
        axios.get(`https://localhost:44399/api/Waiter/getAll`)
        .then(res=> {
            this.setState({waiters: res.data})
        });
    }

    snackBarClose=(event)=>{
58
        this.setState({snackBaropen: false});
    }

    handleSubmit(event){
        event.preventDefault();
        axios.put(`https://localhost:44399/api/Order/update?${qs.stringify({
            Id: event.target.id.value,
            Date: event.target.date.value,
            NumberTable: event.target.numberTable.value,
            WaiterId: event.target.waiter.value,
            TotalPrice: event.target.totalPrice.value
        })}`)
        .then(res=> {
            console.log(res.data);
            this.setState({snackBaropen: true, snackBarMessage: 'Updated successfully'});
        })
        .catch(error=> {
            console.log(error);
            this.setState({snackBaropen: true, snackBarMessage: 'Failed to update'});
        });
    }

    render(){
        return(
            <div className='container'>
                <SnackBar
                anchorOrigin={{vertical: 'bottom', horizontal: 'center'}}
                open={this.state.snackBaropen}
                autoHideDuration={1000}
                onClose={this.snackBarClose}
                message={<span id='message-id'>{this.state.snackBarMessage}</span>}
                action={[
                    <IconButton color="inherit" size="small"
                    onClick={this.snackBarClose}
                    ><CloseIcon/></IconButton>
                ]}/>

                <Modal
                {...this.props}
                size="lg"
                aria-labelledby="contained-modal-title-vcenter"
                centered>
                    <Modal.Header closeButton>
                        <Modal.Title id="contained-modal-title-vcenter">
                            Editing order
                        </Modal.Title>
                    </Modal.Header>
                    <Modal.Body>
                        <Row>
                            <Col sm={6}>
                                <Form onSubmit={this.handleSubmit}>
                                    <Form.Group controlId="id">
                                        <Form.Label>Order number</Form.Label>
59
                                            <Form.Control 
                                            type="text"
                                            name="id"
                                            required
                                            disabled
                                            defaultValue={this.props.orderid}
                                            placeholder="Order number"/>
                                    </Form.Group>
                                    <Form.Group controlId="date">
                                        <Form.Label>Order date</Form.Label>
                                            <Form.Control 
                                            type="date"
                                            name="date"
                                            required
                                            defaultValue={this.props.orderdate}
                                            placeholder="Order date"/>
                                    </Form.Group>
                                    <Form.Group controlId="numberTable">
                                        <Form.Label>Number table</Form.Label>
                                        <Form.Control as="select"
                                            defaultValue={this.props.ordernt}>
                                            {this.state.number.map(num=>
                                                <option key={num}>{num}</option>
                                            )}
                                        </Form.Control>
                                    </Form.Group>
                                    <Form.Group controlId="waiter">
                                        <Form.Label>Number of waiter</Form.Label>
                                        <Form.Control as="select"
                                            defaultValue={this.props.orderwaiter}>
                                            {this.state.waiters.map(waiter=>
                                            <Tooltip key={waiter.id} title={waiter.name + ' ' + waiter.surname}
>
                                                <option key={waiter.id}>{waiter.id}</option>
                                            </Tooltip>
                                            )}
                                        </Form.Control>
                                    </Form.Group>
                                    <Form.Group controlId="totalPrice">
                                        <Form.Label>Order total price</Form.Label>
                                            <Form.Control 
                                            type="text"
                                            name="totalPrice"
                                            required
                                            defaultValue={this.props.ordertp}
                                            placeholder="Order total price"/>
                                    </Form.Group>
                                    <Form.Group>
                                        <Button variant="primary" type="submit">
                                            Edit order
                                        </Button>
                                    </Form.Group>
                                </Form>
60
                            </Col>
                        </Row>
          
                    </Modal.Body>
                    <Modal.Footer>

                        <Button variant="primary" onClick={this.props.onHide}>
                            Close
                        </Button>

                    </Modal.Footer>
                </Modal>
            </div>
        )
    }
}

//Orders.js
import React, {Component} from 'react';
import {Table} from 'react-bootstrap';
import {Button, ButtonToolbar} from 'react-bootstrap';
import AddOrderModal from './AddOrderModal';
import EditOrderModal from './EditOrderModal';
import AddIcon from '@material-ui/icons/Add';
import EditIcon from '@material-ui/icons/Edit';
import DeleteIcon from '@material-ui/icons/Delete';
import ImportExportIcon from '@material-ui/icons/ImportExport';
import SnackBar from '@material-ui/core/Snackbar';
import CloseIcon from '@material-ui/icons/Close';
import IconButton from '@material-ui/core/IconButton';
import axios from 'axios';

export default class Orders extends Component{

    constructor(props){
        super(props);
        this.state = {orders: [], waiters: [], snackBaropen: false, snackBarMessage: '',
             addModalShow: false, editModalShow: false};
    }

    componentDidMount(){
        axios.get(`https://localhost:44399/api/Waiter/getAll`)
        .then(res=> {
            this.setState({waiters: res.data})
        });
        this.refreshList();
    }

    deleteOrder(orderId){
        if(window.confirm('Are you sure?')){
            axios.delete(`https://localhost:44399/api/Order/delete/${orderId}`)
            .then(res=> {
                console.log(res.data);
61
            })
            .catch(error=> {
                console.log(error);
            });
        }
    }

    refreshList(){
        axios.get(`https://localhost:44399/api/Order/getAll`)
        .then(res=> {
            console.log(res.data);
            this.setState({orders: res.data})
        });
    }

    snackBarClose=(event)=>{
        this.setState({snackBaropen: false});
    }

    export=(event)=>{
        event.preventDefault();
        axios.get(`https://localhost:44399/api/Order/excelDoc`)
        .then(res=>{
            this.setState({snackBaropen: true, snackBarMessage: `File is located ${res.data}`});
        })
        .catch(error=> {
            console.log(error);
            this.setState({snackBaropen: true, snackBarMessage: 'Failed export'});
        });
    }

    componentDidUpdate(){
        this.refreshList();
    }

    render(){
        const {orders, waiters, orderId, orderDate, orderNumberTable, orderWaiter, orderTotalPri
ce} = this.state;
        const addModalClose=()=>this.setState({addModalShow:false});
        const editModalClose=()=>this.setState({editModalShow:false});
        return(
            <div>
                <SnackBar
                anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
                open={this.state.snackBaropen}
                autoHideDuration={3000}
                onClose={this.snackBarClose}
                message={<span id='message-id'>{this.state.snackBarMessage}</span>}
                action={[
                    <IconButton
                    color="inherit"
                    size="small"
                    onClick={this.snackBarClose}
62
                    >
                      <CloseIcon />
                  </IconButton>
                ]}/>
            
                <Table className='mt-4' size='sm'>
                <thead>
                    <tr>
                        <th>Order number</th>
                        <th>Order date</th>
                        <th>Number table</th>
                        <th>Waiter</th>
                        <th>Order total price</th>
                        <th>Options</th>
                    </tr>
                </thead>
                <tbody>
                    {orders.map(order=>
                        <tr key={order.id}>
                            <td>{order.id}</td>
                            <td>{new Date(order.date).toLocaleDateString('en-GB')}</td>
                            <td>{order.numberTable}</td>
                            <td>{waiters.map(w=>{if(w.id === order.waiterId){return w.name +' '+ w.su
rname}})}</td>
                            <td>{order.totalPrice}</td>
                            <td>
                            <ButtonToolbar>
                                <Button 
                                variant="success" 
                                onClick={()=>this.setState({
                                    editModalShow: true, 
                                    orderId: order.id,
                                    orderDate: order.date,
                                    orderNumberTable: order.numberTable,
                                    orderWaiter: order.waiter,
                                    orderTotalPrice: order.totalPrice
                                    })}>
                                {<EditIcon/>}
                                </Button>

                                <div className="mr-2"></div>

                                <Button className="mr-2"
                                variant="secondary" 
                                onClick={()=>this.deleteOrder(order.id)}>
                                {<DeleteIcon/>}
                                </Button>

                                <EditOrderModal
                                show={this.state.editModalShow}
                                onHide={editModalClose}
                                orderid={orderId}
                                orderdate={orderDate}
63
                                ordernt={orderNumberTable}
                                orderwaiter={orderWaiter}
                                ordertp={orderTotalPrice}
                                />

                            </ButtonToolbar>
                            </td>
                        </tr>
                    )}
                </tbody>
            </Table>

            <ButtonToolbar>
                <Button 
                variant="danger" 
                onClick={()=>this.setState({addModalShow: true})}>
                    {<AddIcon/>}
                    Add order
                </Button>

                <div className="mr-2"/>

                <Button 
                className="mr-2" 
                variant='secondary'
                type='submit'
                onClick={this.export}>
                    {<ImportExportIcon/>}
                    Export all to Excel
                </Button>

                <AddOrderModal
                show={this.state.addModalShow}
                onHide={addModalClose}/>

            </ButtonToolbar>
            </div>
        )
    }
}

//src/components/ReferencesSystem
//references.css
.app-header {
    width: 100vw;
    margin-top: 3%;
}
h2 {
    font-size: 1.2rem;
    color: grey;
}
.span-style {
    margin-left: 3%;
64
    font-size: 1.2rem;
    color: grey;
}

li {
    margin-left: 3%;
    font-size: 1.2rem;
    color: grey;
}

//References.js
import React, {Component} from 'react';
import './references.css';
import AddIcon from '@material-ui/icons/Add';
import EditIcon from '@material-ui/icons/Edit';
import DeleteIcon from '@material-ui/icons/Delete';
import {Button, ButtonToolbar} from 'react-bootstrap';
import HelpOutlineIcon from '@material-ui/icons/HelpOutline';
import {Modal, Row, Col, Form} from 'react-bootstrap';

export default class References extends Component{

    constructor(props){
        super(props);
        this.state = {addModalShow: false, editModalShow: false, deleteModalShow: false};
    }

    render(){
        if(this.state.deleteModalShow){
            window.confirm('Are you sure?')
        }
        const {addModalShow, editModalShow} = this.state;
        const addModalClose=()=>this.setState({addModalShow:false});
        const editModalClose=()=>this.setState({editModalShow:false});
        return(
            <div>
                <h1>References system</h1>
                <h2>Данное приложение разработано для 
                автоматизации работы администратора кафе(рестона). С помощью данного при
ложения
                управляющий может с лёгкостью вести учёт своей работы.</h2>
                <div>
                <ButtonToolbar>
                    <div className='app-header'>
                    <Button onClick={()=>this.setState({addModalShow: true})}
                    variant="danger" >
                        {<AddIcon/>}
                        Add ...
                    </Button>
                    <span className='span-style'>Кнопка для функции добавления. 
                    Нажав на неё отобразиться модель для добавления нового элемента в список.
</span>
                    <div>
65
                    <Modal
        size="lg"
        show={addModalShow}
        onHide={addModalClose}
        aria-labelledby="contained-modal-title-vcenter"
      >
        <Modal.Header closeButton>
          <Modal.Title id="contained-modal-title-vcenter">
            Adding ...
          </Modal.Title>
        </Modal.Header>
        <Modal.Body>
                <Row>
                  <Col sm={6}>
                      <Form onSubmit={this.handleSubmit}>
                          <Form.Group controlId="name">
                              <Form.Label>Label</Form.Label>
                              <Form.Control 
                                type="text"
                                placeholder="Label"/>
                          </Form.Group>
                          <Form.Group>
                            <Button variant="primary">
                                Add ...
                            </Button>
                          </Form.Group>
                      </Form>
                  </Col>
              </Row>
        </Modal.Body>
        <Modal.Footer>

        <Button variant="primary" onClick={addModalClose}>
            Close
        </Button>

      </Modal.Footer>
      </Modal>
                    </div>
                    </div>
                    
                    <div className='app-header'>
                    <Button onClick={()=>this.setState({editModalShow: true})}
                    variant="success">
                    {<EditIcon/>}
                    </Button>
                    <span className='span-style'>Кнопка для функции редактирования. 
                    Нажав на неё отобразиться модель для редактирования выбраного элемента в 
списоке со старыми данными.</span>
                    <div>
                    <Modal
        size="lg"
        show={editModalShow}
66
        onHide={editModalClose}
        aria-labelledby="contained-modal-title-vcenter"
      >
        <Modal.Header closeButton>
          <Modal.Title id="contained-modal-title-vcenter">
            Editing ...
          </Modal.Title>
        </Modal.Header>
        <Modal.Body>
                <Row>
                  <Col sm={6}>
                      <Form onSubmit={this.handleSubmit}>
                          <Form.Group controlId="name">
                              <Form.Label>Label</Form.Label>
                              <Form.Control 
                                type="text"
                                placeholder="Label"/>
                          </Form.Group>
                          <Form.Group>
                            <Button variant="primary">
                                Edit ...
                            </Button>
                          </Form.Group>
                      </Form>
                  </Col>
              </Row>
        </Modal.Body>
        <Modal.Footer>

        <Button variant="primary" onClick={editModalClose}>
            Close
        </Button>

      </Modal.Footer>
      </Modal>
                    </div>
                    </div>
                    
                    <div className='app-header'>
                    <Button onClick={()=>this.setState({deleteModalShow: true})}
                    variant="secondary">
                    {<DeleteIcon/>}
                    </Button>
                    <span className='span-style'>Кнопка для функции удаления. 
                    Нажав на неё отобразиться окно соглашения на удаление выбраного элемент
а из списка.</span>
                    </div>
                </ButtonToolbar>
                <div className='app-header'>
                    <h2>Панель меню:</h2>
                    <li>Home - главная страница приложения. Приветствует пользователя.</li>
                    <li>List of waiters - страница для просмотра и работы со списком обслуживаю
щего персонала.</li>
67
                    <li>Category - страница для просмотра и работы со списком существующих к
атегорий блюд и напитков.</li>
                    <li>Menu/Dishes - страница для просмотра и работы со списком существующ
их блюд.</li>
                    <li>Menu/Drinks - страница для просмотра и работы со списком существующ
их напитков.</li>
                    <li>Stock - страница для просмотра и ведения учёта наличия ингредиентов.</
li>
                    <li>Order - страница для просмотра и ведения учёта сделанных заказов.</li>
                    <li>{<HelpOutlineIcon/>} - страница справочной системы.</li>
                </div>
                </div>
                
            </div>
        );
    }
};

//src/components/SearchPanel
//SearchPanel.js
import React, {Component} from 'react';

export default class SearchPanel extends Component{
    constructor(props){
        super(props);
        this.state = {search: ''};
    }

    onLabelSearch=(event)=>{
        const search = event.target.value;
        this.setState({search});
        this.props.onLabelSearch(search);
    };

    render(){
        const {search} = this.state;
        return(
            <div>
                <input type="text" className="form-control" placeholder='Search...' value={search} 
onChange={this.onLabelSearch}/>
            </div>
        )
    }
}

//src/components/SignInModal
//SignInModal.js
import React, {Component} from 'react';
import './signIn.css';
import {Modal, Row, Col, Form, Button} from 'react-bootstrap';
import { createBrowserHistory } from 'history';

export default class SignInModal extends Component{
68
    constructor(props){
        super(props);
        this.state = { show: true};
    }
    handleSubmit(event){
        event.preventDefault();
        const customHistory = createBrowserHistory();
        if((event.target.adminName.value === 'admin') && (event.target.password.value === 'ad
min')){
            return customHistory.go(customHistory.push('/home'));
        }
    }
    render(){
        const {show} = this.state;
        return(
            <div>
            <Modal show={show}
                size='sm'
                centered>
                    <Modal.Body>
                        <Row>
                            <Col>
                                <Form onSubmit={this.handleSubmit}>
                                    <Form.Label className='h2 mb-3 font-weight-normal d-flex justify-
content-center'>Please sign in</Form.Label>
                                    <Form.Group>
                                        <Form.Control
                                            type="text"
                                            size='lg'
                                            name='adminName'
                                            required
                                            autoFocus
                                            placeholder="AdminName"/>
                                        <Form.Control 
                                            type="text"
                                            size='lg'
                                            name="password"
                                            required
                                            placeholder="Password"/>
                                    </Form.Group>
                                    <Form.Group>
                                        <Button 
                                            className='btn-block mb-3'
                                            size='lg' 
                                            variant="primary" 
                                            type="submit">
                                            Sign in
                                        </Button>
                                    </Form.Group>
                                </Form>
                            </Col>
                        </Row>
                    </Modal.Body>
69
                    <Modal.Footer>
                        <Form.Label>AdminName: admin</Form.Label>
                        <Form.Label>Password: admin</Form.Label>
                    </Modal.Footer>
                </Modal>
        </div>
        )
    }
}

70
Приложение Б
(справочное)
Формы выходных документов

Данный проект создает выходной документ Excel содержащий все оформленные заказы
в кафе, данный документ представлен на рисунке Б.1.

Рисунок Б.1  Форма выходного документа

71
КП Т.795003 ГЧ

дл. Подп. и дата Взам.инв.№ Инв.№дубл. Подп. и дата


КП Т.795003.401 ГЧ
Лит.
Масса
Масштаб

Программное средство
для автоматизации
рабочего места
администратора кафе

Диаграмма вариантов 72
использования
КП Т.795003 ГЧ

дл. Подп. и дата Взам.инв.№ Инв.№дубл. Подп. и дата


КП Т.795003.401 ГЧ

Программное средство
для автоматизации
рабочего места
администратора кафе

Диаграмма классов
73
КП Т.795003 ГЧ

дл. Подп. и дата Взам.инв.№ Инв.№дубл. Подп. и дата


КП Т.795003.401 ГЧ
Лит.
Масса
Масштаб

Программное средство
для автоматизации
рабочего места
администратора кафе

74
КП Т.795003 ГЧ

дл. Подп. и дата Взам.инв.№ Инв.№дубл. Подп. и дата

Диаграмма деятельности
КП Т.795003.401 ГЧ
Лит.
Масса
Масштаб

Программное средство
для автоматизации
рабочего места
администратора кафе

Диаграмма 75
последовательности
КП Т.795003 ГЧ

дл. Подп. и дата Взам.инв.№ Инв.№дубл. Подп. и дата


КП Т.795003.401 ГЧ
Лит.
Масса
Масштаб

Программное средство
для автоматизации
рабочего места
администратора кафе

Диаграмма компонентов
76

Оценить