Наше приложение будет задействовать несколько различных субстанций: пользователи, заявки, роли, аппаратные ресурсы и т.д. Каждая субстанция или сущность представляет собой какой-то объект, обладающий неким набором свойств, которые позволят нам эффективно им управлять. И на первом этапе, как мне кажется, было бы эффективнее не бросаться сразу в работу с контроллерами, представления, писать какую-то логику, а вначале выделить все сущности, которые будут использоваться в приложении. И затем создать БД и в ней определить таблицы для большинства сущностей.
Какие это будут сущности? Для нашего приложения я выделил следующие сущности: пользователь, роль пользователя, заявка, жизненный цикл заявки, категория возникшей проблемы, отдел (в котором работает пользователь), актив (департамент + кабинет).
Вроде все сущности перечислил. Но в зависимости от поставленной задачи, можно добавить и больше сущностей и классов, сделать программу побогаче, но мы остановимся на этом. И сейчас мы создадим для всех сущностей классы.
Итак, сущность Пользователь у нас будет обладать следующими свойствами:
Id
Имя пользователя
Логин, под которым пользователь будет входить в систему
Пароль для входа в систему
Должность
Отдел, в котором пользователь работает
Роль (администратор, модератор, исполнитель, простой пользователь)
Поэтому добавим в проект в папку Models первый класс - назовем его User:
using System; using System.ComponentModel.DataAnnotations; namespace HelpDeskTrain.Models { public class User { // ID public int Id { get; set; } // Фамилия Имя Отчество [Required] [Display(Name = "Фамилия Имя Отчество")] [MaxLength(50, ErrorMessage = "Превышена максимальная длина записи")] public string Name { get; set; } // Логин [Required] [Display(Name = "Логин")] [MaxLength(50, ErrorMessage = "Превышена максимальная длина записи")] public string Login { get; set; } // Пароль [Required] [Display(Name = "Пароль")] [MaxLength(50, ErrorMessage = "Превышена максимальная длина записи")] public string Password { get; set; } // Должность [Display(Name = "Должность")] [MaxLength(50, ErrorMessage = "Превышена максимальная длина записи")] public string Position { get; set; } // Отдел [Display(Name = "Отдел")] public int? DepartmentId { get; set; } public Department Department { get; set; } // Статус [Required] [Display(Name = "Статус")] public int RoleId { get; set; } public Role Role { get; set; } } }
Я думаю, по комментариям понятно предназначение свойств модели. На подчеркивание несуществующей модели можно не обращать внимание. Потом мы все их добавим.
Теперь добавим вторую модель Role, которая будет представлять статус пользователя:
public class Role { public int Id { get; set; } public string Name { get; set; } }
Класс заявки будет представлять класс ключевого объекта системы. В зависимости от того, насколько полную информацию предоставит пользователь в объекте заявки, настолько у него будут выше шансы, что его заявка будет быстро и без проблем выполнена. Для полноты информации снабдим класс свойствами, которые помогут понять заявку и также упростят ее управление.
Итак, добавим в папку Models следующий класс Request:
using System; using System.ComponentModel.DataAnnotations; namespace HelpDeskTrain.Models { // Модель Заявка public class Request { // ID public int Id { get; set; } // Наименование заявки [Required] [Display(Name = "Название заявки")] [MaxLength(50, ErrorMessage = "Превышена максимальная длина записи")] public string Name { get; set; } // Описание [Required] [Display(Name = "Описание")] [MaxLength(200, ErrorMessage = "Превышена максимальная длина записи")] public string Description { get; set; } // Комментарий к заявке [Display(Name = "Комментарий")] [MaxLength(200, ErrorMessage = "Превышена максимальная длина записи")] public string Comment { get; set; } // Статус заявки [Display(Name = "Статус")] public int Status { get; set; } // Приоритет заявки [Display(Name = "Приоритет")] public int Priority { get; set; } // Номер кабинета [Display(Name = "Кабинет")] public int? ActivId { get; set; } public Activ Activ { get; set; } // Файл ошибки [Display(Name = "Файл с ошибкой")] public string File { get; set; } // Внешний ключ Категория [Display(Name = "Категория")] public int? CategoryId { get; set; } public Category Category { get; set; } // Внешний ключ // ID Пользователя - обычное свойство public int? UserId { get; set; } // Пользователь - Навигационное свойство public User User { get; set; } // Внешний ключ // ID Исполнителя - обычное свойство public int? ExecutorId { get; set; } // Исполнитель - Навигационное свойство public User Executor { get; set; } // Внешний ключ // ID жизненного цикла заявки - обычное свойство public int LifecycleId { get; set; } // Ссылка на жизненный цикл заявки - Навигационное свойство public Lifecycle Lifecycle { get; set; } } }
Большинство свойств, я думаю, понятны, но все же несколько свойств я прокомментирую подробнее. public string File { get; set; }
-
данное свойство у нас буде хранить путь к файлу изображения с ошибкой (при наличии).
Теперь в файл с классом Request добавим класс Lifecycle, который будет отвечать за жизненный цикл заявки:
// Модель жизенного цикла заявки public class Lifecycle { // ID public int Id { get; set; } // Дата открытия [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy H:mm:ss}", ApplyFormatInEditMode = true)] [DataType(DataType.Date)] public DateTime Opened { get; set; } // Дата распределения [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy H:mm:ss}", ApplyFormatInEditMode = true)] [DataType(DataType.Date)] public DateTime? Distributed { get; set; } // Дата обработки [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy H:mm:ss}", ApplyFormatInEditMode = true)] [DataType(DataType.Date)] public DateTime? Proccesing { get; set; } // Дата проверки [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy H:mm:ss}", ApplyFormatInEditMode = true)] [DataType(DataType.Date)] public DateTime? Checking { get; set; } // Дата закрытия [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy H:mm:ss}", ApplyFormatInEditMode = true)] [DataType(DataType.Date)] public DateTime? Closed { get; set; } }
Деление на этапы жизненного цикла довольно условно. Ну вот я выделил такие этапы, и каждый этап увязан с датой перехода к данному этапу. Предполагается, что сначала при создании у заявки статус 'Открыто', затем ее модератор распределяет по исполнителям. Исполнители в свою очередь при начале выполнения устанавливают у заявки статус 'В процессе' (Proccesing), затем при окончании проверяют (статус Checking), и когда все уже сделано, закрывают ее.
Для свойств с типом DateTime
дополнительно атрибутом определяется формат даты, поскольку система может неправильно работать с датой.
А таким образом мы даем детальное указание, как дату надо интерпретировать.
Также в файл класса заявки добавим два вспомогательных перечисления:
// Перечисление для статуса заявки public enum RequestStatus { Open = 1, Distributed = 2, Proccesing = 3, Checking = 4, Closed = 5 } // Перечисление для приоритета заявки public enum RequestPriority { Low = 1, Medium = 2, High = 3, Critical = 4 }
Перечисление RequestStatus
содержи все статусы заявки. Оно увязывается со свойством Status
у класса Request
.
Перечисление RequestPriority
содержит все возможные приоритеты, которые пользователь может присвоить заявке: низкий, средний,
высокий, критический. Для установки приоритета в классе Request предназначено свойство Priority
.
Теперь добавим все остальные классы сущностей. Эти классы будут выглядеть намного проще. Итак, добавим в папку Models класс Category:
public class Category { public int Id { get; set; } [Required] [Display(Name = "Название категории")] [MaxLength(50, ErrorMessage = "Превышена максимальная длина записи")] public string Name { get; set; } }
Эта модель будет указывать на категорию проблемы, например, проблема с сетью, с оборудованием или проблема с программным обеспечением.
Теперь добавим модель отдела Department:
// модель отделы public class Department { public int Id { get; set; } [Required] [Display(Name = "Название отдела")] [MaxLength(50, ErrorMessage = "Превышена максимальная длина записи")] public string Name { get; set; } }
Тут же определим связанный с этим класс Activ:
// Модель Активы public class Activ { public int Id { get; set; } // номер кабинета [Required] [Display(Name = "Номер кабинета")] [MaxLength(50, ErrorMessage = "Превышена максимальная длина записи")] public string CabNumber { get; set; } // Внешний ключ // ID Отдела - обычное свойство [Required] [Display(Name = "Отдел")] public int? DepartmentId { get; set; } // Отдел - Навигационное свойство public Department Department { get; set; } }
Эта модель будет представлять актив - кабинет, принадлежащий определенному отделу. В процессе заполнения заявки пользователь сможет указать кабинет, в котором происходит проблема.
Таким образом, мы создали весь набор моделей, которые будут использоваться в приложении, и можем перейти к самому неинтересному этапу - созданию БД и таблиц.