Автоматизация работы техподдержки пользователей

Тип работы:
Курсовая
Предмет:
Программирование


Узнать стоимость

Детальная информация о работе

Выдержка из работы

Оглавление

  • Характеристика объекта автоматизации
  • Краткое техническое задание на разработку автоматизированной системы
  • Функциональная модель системы обработки заявок
  • Модель базы данных системы обработки заявок
  • Проектирование интерфейса
  • Разработка системы. Выбор средств реализации
  • Реализация
  • Листинг основных классов программы
  • Глоссарий
  • Заключение
  • Список использованных источников

Характеристика объекта автоматизации

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

· К кому обращаться?

· Сколько времени департамент ИТ будет обрабатывать мой вопрос?

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

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

· Как организовать работу департамента ИТ в преддверии предстоящего роста компании?

И так далее.

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

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

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

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

Предположим:

Штат ИТ-службы компании 30 человек

Средняя заработная плата ИТ-специалиста 21 000 рублей

Количество пользовательских рабочих мест в компании 1500

Среднее количество заявок по инцидентам 760

Среднее время, затрачиваемое инженером на закрытие одного инцидента — 4 часа

Тогда:

Стоимость обслуживания 1 рабочего места в месяц: (30×21 000)/1500=420 рублей

Количество заявок, требующих выхода на место инцидента: 760×0,45=342

Экономия времени при внедрении Service Desk на решение одного инцидента: 4×0,25=1 час

Экономия времени по всем инцидентам за месяц: 342×1=342 часа

Час работы специалиста стоит: 21 000/22/8=120 рублей

Экономия времени за месяц 120*342=41 040 рублей, за год 41 040×12=492 480 рублей.

С другой стороны, сокращается время простоев пользователей. При средней заработной плате сотрудников компании 15 000 рублей 342 часа экономии в месяц на простоях выражаются суммой в (15 000/22/8)х342×12=349 773 рубля в год.

Суммарный эффект 842 253 рубля в год

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

В частности, полномасштабный запуск системы создаёт постоянно накапливаемую информационную основу для совершенствования регламентов и методик, применяемых для повышения качества предоставляемых пользователям услуг (базу знаний по возникающим решениям). Такое совершенствование также значительно снижает время обработки инцидентов и простоев по их вине. По данным известного независимого аналитического агентства Giga Information Group время разрешения инцидентов на рабочих местах сокращается при этом на 30−40%

Краткое техническое задание на разработку автоматизированной системы

В соответствии с ГОСТ 34. 601−90, настоящий стандарт распространяется на автоматизированные системы (АС), используемые в различных видах деятельности (исследование, проектирование, управление и т. п.), включая их сочетания, создаваемые в организациях, объединениях и на предприятиях (далее — организациях).

Стандарт устанавливает стадии и этапы создания АС.

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

Назначение и цели создания системы:

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

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

Система должна автоматизировано накапливать заявки пользователей в IT-отдел, автоматически сортировать их по проектам и исполнителям.

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

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

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

Требования к видам обеспечения — информационному, техническому, программному, организационному:

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

Требования к персоналу:

Минимальные требования к знанию интерфейса Windows, умение пользоваться браузером, начальные навыки обращения с ПК.

Состав и содержание работ по созданию системы:

1. Моделирование системы

2. Проектирование системы

3. Разработка интерфейса

4. Реализация логики на языке программирования

Порядок контроля и приемки системы:

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

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

Рис. 1 Модель IDEF0 системы обработки заявок

Рис. 2 Процесс обработки заявок пользователей (разделение на АРМы)

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

Рис. 3 ER-диаграмма базы данных для системы обработки заявок

Проектирование интерфейса

Когда говорят о научных основах проектирования пользовательских интерфейсов, в первую очередь упоминают термин HCI. HCI -- это аббревиатура английского Human-Computer Interaction, что переводится как «взаимодействие человека и компьютера». На Западе HCI -- это целая профессия, ей обучают в университетах, выдавая дипломы «Специалист по HCI». Издается много журналов по этой теме, существует большое количество Web-сайтов. В России, к сожалению, эта наука не пользуется особой популярностью, например, у нас настоящих специалистов по HCI можно буквально пересчитать по пальцам одной руки.

Как легко догадаться по названию, составными частями HCI являются:

· · человек (пользователь)

· · компьютер

· · их взаимодействие.

Пользовательский интерфейс (англ. user interface, UI) является своеобразным коммуникационным каналом, по которому осуществляется взаимодействие пользователя и компьютера.

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

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

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

Рис 4 Схема проекта основного интерфейса программы

Разработка системы. Выбор средств реализации

ASP. NET MVC — это платформа для разработки веб-приложений от Microsoft, которая сочетает в себе эффективность и аккуратность архитектуры «модель-представление-контроллер», новейшие идеи и приемы гибкой разработки, а также все лучшее из существующей платформы ASP. NET. Она представляет собой полномасштабную альтернативу традиционной технологии ASP. NET Web Forms, предоставляя существенные преимущества для всех проектов веб-разработки, кроме наиболее тривиальных. Новая платформа ASP. NET MVC обеспечила радикальный сдвиг в разработке веб — приложений на платформе Microsoft. В ней делается упор на ясную архитектуру, шаблоны проектирования и тестируемость, и не предпринимается попыток сокрытия того, как работает веб-среда.

Термин модель — представление — контроллер (model — view — controller) используется с конца 70-х гг. прошлого столетия. Эта модель явилась результатом проекта Smalltalk в компании Xerox, где она была задумана как способ организации некоторых из ранних приложений графического пользовательского интерфейса. Некоторые из нюансов первоначальной модели MVC были связаны с концепциями, специфичными для Smalltalk, такими как экраны и инструменты, но более глобальные понятия все еще применимы к приложениям, и особенно хорошо они подходят для веб-приложений [5, с. 63].

Если оперировать понятиями высокого уровня, архитектурный шаблон MVC означает, что приложение MVC будет разделено, по крайней мере, на три части (рисунок 5).

интерфейс автоматизированный программный заявка

Рисунок 5 — Структурные части архитектурного шаблона MVC

Модели, содержащие или представляющие данные, с которыми работают пользователи. Они могут быть простыми моделями представлений, которые только представляют данные, передаваемые между представлениями и контроллерами; или же они могут быть моделями предметной области, которые содержат бизнес — данные, а также операции, преобразования и правила для манипулирования этими данными.

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

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

В MVC контроллеры являются классами, обычно производными от класса System. Web. Mvc. Controller. Каждый метод public в классе, унаследованном от класса Controller, называется методом действия и посредством системы маршрутизации ASP. NET связан с конфигурируемым URL. Когда запрос отправляется URL, связанному с методом действия, операторы в классе контроллера выполняются, чтобы провести некоторую операцию по отношению к модели предметной области и затем выбрать представление для отображения клиенту. Взаимодействия между контроллером, моделью и представлением показаны на рисунке 6

Рисунок 6 — Взаимодействия между контроллером, моделью и представлением

Для разработки программного продукта была выбрана технология ASP. NET MVC 3 и язык C#, являющийся самым популярным языком для написания бизнес логики на платформе. NET, основные преимущества технологии ASP. NET MVC 3:

— Использование встроенного архитектурного шаблона MVC.

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

— Жесткий контроль над HTML и HTTP. В платформе ASP. NET MVC учтена важность генерации ясного и соответствующего стандартам кода разметки. Ее встроенные вспомогательные методы HTML создают соответствующий стандартам вывод, но в ней реализовано и гораздо более значимое философское изменение по сравнению с Web Forms. Вместо громадного объема, трудно поддающегося управлению HTML-кода, платформа MVC стимулирует создание простых и элегантных, стилизованных с помощью CSS компонентов.

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

В качестве IDE была выбрана Visual Studio 2010 — это интегрированная среда разработки Microsoft (IDE), являющейся самой функциональной IDE для разработки на платформе. NET.

Для модульного тестирования была выбрана встроенная поддержка в Visual Studio 2010 так как в настоящий момент функциональность встроенной поддержки ничуть не хуже, чем у конкурентов, а тесная интеграция с IDE ставит её на первое место.

Для хранения данных был выбрана СУБД SQL Server 2008 R2 от Microsoft. Из наиболее распространенных СУБД для создания базы данных выбрана СУБД MS SQL Server, так как она обладает всеми необходимыми средствами для создания и обеспечения работоспособности базы данных, поддерживает визуальную технологию создания объектов базы данных, стандарт языка SQL.

Реализация

Рис. 7 Основной интерфейс программы

Рис. 8 Форма для подачи заявки

Листинг основных классов программы

using System;

using System. Collections. Generic;

using System. Linq;

using System. Runtime. Serialization;

using System. ServiceModel;

using System. ServiceModel. Web;

using System. Text;

using System. Timers;

using PlanningService. DataClasses;

using System. Diagnostics;

namespace PlanningService

{

public class RequestComparer: IComparer< Request>

{

public int Compare (Request x, Request y)

{

if (x. CurrentStatus < y. CurrentStatus)

{

return -1;

}

else if (x. CurrentStatus > y. CurrentStatus)

{

return 1;

}

else

{

if (x. CurrentStatus == Status. WaitingOpen_StatusCode & & y. CurrentStatus == Status. WaitingOpen_StatusCode & & x. Type == y. Type & & x. PlanningTime < 10 & & y. PlanningTime < 10)

{

return 0;

}

else

{

if (y. Priority==1)

{

return 1;

}

else if (x. Priority==1)

{

return -1;

}

else

{

if (x. PlanningOnDate < y. PlanningOnDate)

{

return -1;

}

else if (x. PlanningOnDate > y. PlanningOnDate)

{

return 1;

}

else

{

return 0;

}

}

}

}

}

}

public class UserRequestComparer: IEqualityComparer< Request>

{

#region IEqualityComparer< Request> Members

public bool Equals (Request x, Request y)

{

if (x. ReqID == y. ReqID)

{

if (x. CurrentStatus == y. CurrentStatus & & x. ExecutorID == y. ExecutorID & & x. PlanningOnDate == y. PlanningOnDate & & x. PlanningCompleteDate==y. PlanningCompleteDate)

{

return true;

}

else

{

return false;

}

}

else

{

return false;

}

}

public int GetHashCode (Request obj)

{

return obj. GetHashCode ();

}

#endregion

}

[ServiceBehavior (InstanceContextMode=InstanceContextMode. Single)]

public class PlanningService: IService1

{

private ServiceResponse Response =null;

private List< UserContainer> UserList = null;

private static linqDataContext dc = null;

private static ViolationsDataContext vdc= null;

private RequestComparer ReqComparer = null;

public PlanningService ()

{

Response = new ServiceResponse (false, ««);

UserList = new List< UserContainer>();

dc = new linqDataContext ();

vdc = new ViolationsDataContext ();

ReqComparer = new RequestComparer ();

SOTRUD user = null;

foreach (Sessions session in dc. Sessions)

{

user = dc. SOTRUD. SingleOrDefault (s => s. ID == session. EmployeeID);

if (user ≠ null)

{

if (user. ID_SOTRUD_DOLG. HasValue)

{

SetWorkDay (user. ID, user. ID_SOTRUD_DOLG. Value, false, session. DuringTime);

}

private static UsersList ContainerToUser (UserContainer uc)

{

SOTRUD CurrentSotr = dc. SOTRUD. Single (s=>s. ID==uc. UserID);

return new UsersList { ID = CurrentSotr. ID, name = CurrentSotr. FIO, position = CurrentSotr. SOTRUD_DOLG. SOTRUD_DOLG1, BeginTime = uc. ComeTime. ToString (@"hh:mm:ss") };

}

private void AddViolation (Guid ReqID, string Type)

{

Violations V = new Violations{ Data=DateTime. Now, Request=ReqID, Type=Type };

vdc. Violations. InsertOnSubmit (V);

vdc. SubmitChanges ();

}

public bool SetWorkDay (int id, int posID, bool itIsEnd, int minutes = 0)

{

if (!itIsEnd)

UserContainer CurrentContainer = UserList. SingleOrDefault (s => s. UserID == id);

if (CurrentContainer == null)

{

UserContainer NewContainer = new UserContainer (id, posID, dc);

NewContainer. ComeTime = NewContainer. ComeTime. Subtract (new TimeSpan (0, minutes, 0));

try

{

foreach (Request r in NewContainer. ReqList. FindAll (r=>r. CurrentStatus>Status. Opened_StatusCode & & r. PlanningOnDate. Date<=DateTime. Now. Date & & !r. PlannedRequest))

{

int ind = NewContainer. ReqList. IndexOf®;

if (ind == 0)

{

r. PlanningOnDate = DateTime. Parse (GetPlanningTime (r. CreatorID, r. IsCycle, r. Type, r. Executor. LocationID. Value, false, r. ExecutorID));

}

else

{

r. PlanningOnDate = NewContainer. ReqList[ind — 1]. PlanningCompleteDate. Value. AddMinutes (5);

}

r. PlanningCompleteDate = r. PlanningOnDate. AddMinutes (r. PlanningTime);

}

dc. SubmitChanges ();

UserList. Capacity++;

UserList. Add (NewContainer);

CheckForCyclicRequests ();

return true;

}

catch

{

return false;

}

}

else

{

return false;

}

}

else

{

UserContainer Current = UserList. Single (s=>s. UserID==id);

int DepID = dc. SOTRUD. Single (s=>s. ID==id). ID_OTD;

Current. ReqList. ForEach (ListRequestHandlers. SetMinutesLeft);

dc. SubmitChanges ();

List< Request> lreq = dc. Request. Where (r=>r. PlanningOnDate. Date==DateTime. Now. Date & & r. ExecutorID==Current. UserID). ToList ();

TimeSpan WorkedTime = DateTime. Now. TimeOfDay. Subtract (Current. ComeTime);

int RequestsPlanning = lreq. Count;

int RequestsExecuted = lreq. Where (r=>r. CurrentStatus>=Status. Completed_StatusCode). Count ();

List< Request> forgrade = lreq. Where (r=>r. grade. HasValue). ToList ();

int ViolCount = vdc. Violations. Where (r => r. Re. PlanningOnDate. Date == DateTime. Now. Date & & r. Re. ExecutorID == Current. UserID). Count ();

double AvgGrade = 0;

if (forgrade. Count > 0)

{

AvgGrade = forgrade. Average (a => a. grade. Value);

}

Tabel tab = new Tabel

{

BeginWorkTime = DateTime. Now. Subtract (WorkedTime),

EndWorkTime = DateTime. Now,

ExecutorID = Current. UserID,

TimeOnBreak = Current. TimeInBreak,

RequestsAssigned = RequestsPlanning,

RequestsExecuted = RequestsExecuted,

AverageGrade = Convert. ToDecimal (AvgGrade),

ViolationsCount = ViolCount,

ViolationsPercent = RequestsExecuted ≠ 0? ViolCount / RequestsExecuted: 0,

DepID= DepID

};

vdc. Tabel. InsertOnSubmit (tab);

vdc. SubmitChanges ();

bool Deleted = UserList. Remove (Current);

return false;

}

}

private void DeleteSession (int uid)

{

try

{

Sessions session = dc. Sessions. SingleOrDefault (s => s. EmployeeID == uid);

if (session ≠ null)

{

dc. Sessions. DeleteOnSubmit (session);

dc. SubmitChanges ();

}

}

catch

{

}

}

private void WriteSession (int uid, int minutes)

{

try

{

Sessions session = dc. Sessions. SingleOrDefault (s => s. EmployeeID == uid);

if (session == null)

{

session = new Sessions { DuringTime = minutes, ID = Guid. NewGuid (), EmployeeID = uid };

dc. Sessions. InsertOnSubmit (session);

}

else

{

session. DuringTime = minutes;

}

dc. SubmitChanges ();

}

catch

{

}

}

public bool ToggleBreak (int UID)

{

UserContainer Current = UserList. SingleOrDefault (s => s. UserID == UID);

if (Current ≠ null)

{

int index = UserList. IndexOf (Current);

UserList[index]. IsOnBreak = !Current. IsOnBreak;

if (UserList[index]. IsOnBreak)

{

UserList[index]. TimeInLastBreak = 0;

UserList[index]. BreakTimer. Start ();

UserList[index]. PauseTimer. Stop ();

}

else

{

UserList[index]. BreakTimer. Stop ();

UserList[index]. MovePlanningCompleteTime (0, Convert. ToDouble (UserList[index]. TimeInLastBreak));

}

}

return true;

}

public Request GetRequest (int userID, string reqID)

{

Guid outGID;

Request req = null;

if (Guid. TryParse (reqID, out outGID))

{

req = dc. Request. SingleOrDefault (r => r. ReqID == outGID);

}

return req;

}

public void ResetReplannedFlag (int id)

{

UserContainer uc = GetUserContainer (id);

if (uc≠null)UserList[UserList. IndexOf (uc)]. IsReplanned=false;

}

public void SetPlannedFlag (Guid RID, bool value)

{

Request r = dc. Request. SingleOrDefault (s => s. ReqID == RID);

if (r ≠ null)

{

UserContainer ul = UserList. SingleOrDefault (a => a. UserID == r. ExecutorID);

if (ul ≠ null) ul. IsReplanned = true;

r. PlannedRequest = value;

dc. SubmitChanges ();

}

}

public void SetPlanningTime (Guid RID, DateTime On, DateTime Complete)

{

Request r = dc. Request. SingleOrDefault (s => s. ReqID == RID);

if (r ≠ null)

{

UserContainer ul = UserList. SingleOrDefault (a => a. UserID == r. ExecutorID);

if (ul ≠ null) ul. IsReplanned = true;

r. PlanningOnDate = On;

r. PlanningCompleteDate = Complete;

dc. SubmitChanges ();

}

}

public bool CheckForListEquality (IEnumerable< Request> OldList, int UID)

{

IEnumerable< Request> newList = GetUserRequests (UID);

return OldList. SequenceEqual (newList, new UserRequestComparer ());

}

private void AddCommentToRequest (Guid RID, int CommentType, string comment, int CreatorID)

{

if (comment. Trim ()≠string. Empty)

{

if (comment. Length > 998)

{

comment = «Комментарий, который хотел добавить пользователь был слишком большим по объему»;

}

try

{

ReqComment rc = new ReqComment { CommentID = Guid. NewGuid (), UID = CreatorID, EnterDate = DateTime. Now, CommentType = CommentType, Comment = comment, ReqID = RID };

dc. ReqComment. InsertOnSubmit (rc);

dc. SubmitChanges ();

}

catch (Exception ex)

{

Trace. Write («Ошибка в функции AddCommentToRequest «+ ex. Message);

}

}

}

private ServiceResponse SetErrorMessage (string message)

{

Response. IsError = true;

Response. ErrorMessage = message;

return Response;

}

public ServiceResponse CreateRequest (string intCreatorUID, string gidReqType, string dtmPlanningOnDate, string strcomment, string intCount, string LocationID, bool Cyclic, bool HighestPriority, string HostName, bool NeedReconcile, int? ExecutorID)

{

byte StatusID = NeedReconcile? Status. Reconciling_StatusCode: Status. WaitingOpen_StatusCode;

return this. CreateRequestWithCurrentStatus (intCreatorUID, gidReqType, dtmPlanningOnDate, strcomment, intCount, LocationID, Cyclic, HighestPriority, HostName, StatusID, ExecutorID);

}

public ServiceResponse CreateRequestWithCurrentStatus (string intCreatorUID, string gidReqType, string dtmPlanningOnDate, string strcomment, string intCount, string LocationID, bool Cyclic, bool HighestPriority, string HostName, byte StatusID, int? ExecutorID)

{

int CreatorUID;

if (!int. TryParse (intCreatorUID, out CreatorUID))

{

return SetErrorMessage («Ошибка Не получен ID инициатора»);

}

int locationID;

if (!int. TryParse (LocationID, out locationID))

{

locationID = GetLocID (CreatorUID);

}

Guid ReqType;

if (!Guid. TryParse (gidReqType, out ReqType))

{

return SetErrorMessage («Ошибка Не получен тип заявки»);

}

DateTime PlanningOnDate;

if (!DateTime. TryParse (dtmPlanningOnDate, out PlanningOnDate))

{

return SetErrorMessage («Ошибка Не получена дата начала действия заявки, формат даты должен соответствовать: дд мм гггг чч: мм»);

}

int Count;

if (!int. TryParse (intCount, out Count))

{

return SetErrorMessage («Ошибка Не получено количество заявок»);

}

//Если планнинг день не сегодня тогда пишем заявку в базу, и не пишем в юзерлист

if (PlanningOnDate. DayOfYear < DateTime. Now. DayOfYear)

{

return SetErrorMessage («Ошибка Планируемая дата заявки меньше сегодняшней»);

}

try

{

WorkClassificator wclass = dc. WorkClassificator. SingleOrDefault (s => s. ID == ReqType);

if (wclass ≠ null) dc. Refresh (System. Data. Linq. RefreshMode. OverwriteCurrentValues, wclass);

}

catch

{

Trace. TraceWarning («An error in function CreateRequest, workcls refresh»);

}

UserContainer ExecutorContainer = null;

if (ExecutorID. HasValue)

{

ExecutorContainer = UserList. SingleOrDefault (s => s. UserID == ExecutorID. Value);

}

else

{

ExecutorContainer = FindUser (ReqType, CreatorUID, locationID);

ExecutorID = ExecutorContainer ≠ null? ExecutorContainer. UserID: FindExecutorByReqType (ReqType, CreatorUID, locationID);

}

if (ExecutorID < 0 || !ExecutorID. HasValue)

{

return SetErrorMessage («Ошибка Не удалось найти ни одного исполнителя»);

Request NewReq = new Request { ReqID = Guid. NewGuid (), CreationDate = DateTime. Now, PlanningOnDate = PlanningOnDate, CreatorID = CreatorUID, ExecutorID = ExecutorID. Value, CurrentStatus = StatusID, Type = ReqType, IsCycle = Cyclic };

if (HostName is string)

{

if (HostName. Length > 1) NewReq. HostName = HostName;

}

NewReq. Priorities = SetRequestPriority (NewReq. IsCycle, CreatorUID, HighestPriority);

try

{

dc. Request. InsertOnSubmit (NewReq);

dc. SubmitChanges ();

}

catch (Exception ex)

{

return SetErrorMessage («Ошибка при записи заявки «+ ex. Message);

}

NewReq. PlanningTime = NewReq. WorkClassificator. PlanningTime. HasValue? NewReq. WorkClassificator. PlanningTime. Value * Count: 0;

NewReq. PlanningCompleteDate = NewReq. PlanningOnDate. AddMinutes (Convert. ToDouble (NewReq. PlanningTime));

dc. SubmitChanges ();

AddCommentToRequest (NewReq. ReqID, ReqCommentTypes. Open_CommentType, strcomment, CreatorUID);

if (ExecutorContainer ≠ null & & NewReq. PlanningOnDate. Date >= DateTime. Now. Date & & NewReq. PlanningOnDate. Date <= DateTime. Now. Date. AddDays (5) & & StatusID ≠ Status. Reconciling_StatusCode)

{

int indexContainer = UserList. IndexOf (ExecutorContainer);

UserList[indexContainer]. IsReplanned = true;

UserList[indexContainer]. ReqList. Add (NewReq);

UserList[indexContainer]. ReqList. Sort (ReqComparer);

double minInterval = NewReq. PlanningOnDate. Subtract (DateTime. Now). TotalMinutes;

if (UserList[indexContainer]. ReqList. Count == 1 & & minInterval < 10) UserList[indexContainer]. StartRequest ();

}

if (StatusID ≠ Status. Reconciling_StatusCode)

{

OTD Department = dc. OTD. SingleOrDefault (s => s. ID == NewReq. WorkClassificator. DepartmentID);

long? AccEmailId = null;

if (Department ≠ null)

{

AccEmailId = Department. ID_EmailAccount;

}

UserContainer. NotificateUser (ExecutorID. Value, CreatorUID, «Оповещение о регистрации заявки», «Ваша заявка «+ NewReq. WorkClassificator. TitleRow + «зарегистрирована. Ваш исполнитель «+ NewReq. Executor. FIO + «. Планируемое время закрытия — «+ NewReq. PlanningCompleteDate. Value. ToString (), AccEmailId);

UserContainer. NotificateUser (ExecutorID. Value, ExecutorID. Value, «Оповещение о новой заявке», «Вам назначена новая заявка: «+ NewReq. WorkClassificator. TitleRow + «от пользователя «+ NewReq. Creator. FIO, AccEmailId);

}

Response. IsError = false;

Response. ReturnObject = NewReq. ReqID. ToString ();

return Response;

}

public int GetCurrentRequestTime (UserContainer Container)

{

Request CurrentReq = Container. ReqList. FirstOrDefault (s => s. CurrentStatus == Status. Opened_StatusCode);

int CurrentRequestRemaining = 0;

if (CurrentReq ≠ null)

{

CurrentRequestRemaining = Convert. ToInt32(CurrentReq. PlanningCompleteDate. Value. Subtract (DateTime. Now). TotalMinutes);

}

return CurrentRequestRemaining;

}

public void CreateGroupRequest (string intCreatorUID, string gidReqType, string dtmPlanningOnDate, string strcomment, string intCount, string LocationID, bool Cyclic, bool Highest, int? ExecutorID)

{

int countReq = int. Parse (intCount);

for (int i = 0; i < countReq; i++)

{

string planDate = GetPlanningTime (int. Parse (intCreatorUID), false, Guid. Parse (gidReqType), int. Parse (LocationID), Highest, null);

CreateRequest (intCreatorUID, gidReqType, planDate, strcomment, «1», LocationID, false, Highest, null, false, ExecutorID);

public string GetPlanningTime (int CreatorID, bool ReqIsCycle, Guid ReqType, int LocationID, bool HighestPriority, int? ExecutorID)

{

Priorities PriorityEntity = SetRequestPriority (ReqIsCycle, CreatorID, HighestPriority);

int Priority = PriorityEntity. ID;

dc. Refresh (System. Data. Linq. RefreshMode. OverwriteCurrentValues, dc. WorkClassificator);

WorkClassificator Class = dc. WorkClassificator. Single (s => s. ID == ReqType);

int pause = 5;

int CurrentExecutor;

int TimeNeedToRequest = Class. PlanningTime. Value + (pause * 2);

UserContainer ExecutorContainer = !ExecutorID. HasValue? FindUser (ReqType, CreatorID, LocationID): UserList. SingleOrDefault (s => s. UserID == ExecutorID. Value);

List< Request> reversed;

if (ExecutorContainer ≠ null)

{

reversed = ExecutorContainer. ReqList. Where (r=>r. Priority<=Priority & & r. CurrentStatus<Status. Excluded_StatusCode & & r. PlanningOnDate. Date==DateTime. Now. Date). OrderBy (r => r. PlanningOnDate). ToList ();

CurrentExecutor = ExecutorContainer. UserID;

}

else

{

int OfflineExecutor = !ExecutorID. HasValue? FindExecutorByReqType (ReqType, CreatorID, LocationID): ExecutorID. Value;

reversed = (from r in dc. Request where r. PlanningOnDate. Date == DateTime. Now. Date & & r. ExecutorID == OfflineExecutor & & r. Priority <= Priority & & r. CurrentStatus < Status. Excluded_StatusCode orderby r. PlanningOnDate select r). ToList ();

CurrentExecutor = OfflineExecutor;

}

int currentIndex=-1;

Request Next;

foreach (Request req in reversed)

{

currentIndex = reversed. IndexOf (req);

Next = reversed. ElementAtOrDefault (currentIndex + 1);

if (Next ≠ null)

{

if (Next. PlanningOnDate. TimeOfDay. Subtract (req. PlanningCompleteDate. Value. TimeOfDay). TotalMinutes >= TimeNeedToRequest)

{

//если нашли окно то втыкаем сюда.

if (DateTime. Now. CompareTo (req. PlanningCompleteDate. Value) > 0) continue;

return req. PlanningCompleteDate. Value. AddMinutes (Convert. ToDouble (pause)). ToString («dd MM yyyy HH: mm: ss»);

}

}

else

{

if (DateTime. Now. CompareTo (req. PlanningCompleteDate. Value) > 0)

{

return DateTime. Now. ToString («dd MM yyyy HH: mm: ss»);

}

else

{

return req. PlanningCompleteDate. Value. AddMinutes (Convert. ToDouble (pause)). ToString («dd MM yyyy HH: mm: ss»);

}

}

}

Request LastOpenedReq = dc. Request. Where (r => r. CurrentStatus <= Status. Opened_StatusCode & & r. PlanningCompleteDate. HasValue & & r. ExecutorID==CurrentExecutor). OrderByDescending (r=>r. PlanningCompleteDate). FirstOrDefault ();

if (LastOpenedReq ≠ null & & DateTime. Now. CompareTo (LastOpenedReq. PlanningCompleteDate. Value) < 0)

{

return LastOpenedReq. PlanningCompleteDate. Value. AddMinutes (Convert. ToDouble (pause)). ToString («dd MM yyyy HH: mm: ss»);

}

else

{

return DateTime. Now. ToString («dd MM yyyy HH: mm: ss»);

}

}

//Этот блок инициирует пользователь, поэтому нужно искать в листе, потом, если не найдено — в базе

public bool ReopenRequest (int UID, Guid ReqID, string comment)

{

UserContainer Current = UserList. SingleOrDefault (s => s. UserID == UID);

Request ReqObj = dc. Request. Single (s => s. ReqID == ReqID);

ReqObj. Status = dc. Status. Single (s => s. ID == Status. WaitForResponse_StatusCode);

if (Current≠null)

{

ReqObj. PlanningOnDate = DateTime. Parse (GetPlanningTime (UID, ReqObj. IsCycle, ReqObj. Type, ReqObj. Executor. LocationID. Value, false, ReqObj. ExecutorID));

ReqObj. PlanningCompleteDate = ReqObj. PlanningOnDate. AddMinutes (Convert. ToDouble (ReqObj. PlanningTime));

int index = UserList. IndexOf (Current);

UserList[index]. ReqList. Sort (new RequestComparer ());

UserList[index]. IsReplanned= true;

}

try

{

dc. SubmitChanges ();

AddCommentToRequest (ReqID, ReqCommentTypes. Reopen_CommentType, comment, ReqObj. CreatorID);

return true;

}

catch

{

return false;

}

}

public bool CloseRequest (int UID, Guid ReqID, string comment="", int grade=0)

{

UserContainer Current = UserList. SingleOrDefault (s => s. UserID == UID);

Request ReqObj = dc. Request. Single (s => s. ReqID == ReqID);

ReqObj. CloseDate = DateTime. Now;

ReqObj. Status = dc. Status. Single (s => s. ID == Status. Closed_StatusCode);

ReqObj. grade = grade;

if (grade > 0 & & grade < 3)

{

AddViolation (ReqObj. ReqID, Violations. BadGradeViolation);

}

try

{

dc. SubmitChanges ();

if (Current ≠ null)

{

int currindex = UserList. IndexOf (Current);

UserList[currindex]. IsReplanned = true;

UserList[currindex]. ReqList. Remove (ReqObj);

}

if (!string. IsNullOrEmpty (comment))

{

this. AddCommentToRequest (ReqObj. ReqID, ReqCommentTypes. UserClose_CommentType, comment, ReqObj. ExecutorID);

}

return true;

}

catch

{

return false;

}

}

public bool CancelRequest (int UID, Guid ReqID, string comment = ««, int grade = 0)

{

UserContainer Current = UserList. SingleOrDefault (s => s. UserID == UID);

Request ReqObj = dc. Request. Single (s => s. ReqID == ReqID);

ReqObj. CloseDate = DateTime. Now;

ReqObj. Status = dc. Status. Single (s => s. ID == Status. Cancelled_StatusCode);

ReqObj. grade = grade;

if (grade > 0 & & grade < 3)

{

AddViolation (ReqObj. ReqID, Violations. BadGradeViolation);

}

try

{

dc. SubmitChanges ();

if (Current ≠ null)

{

int currindex = UserList. IndexOf (Current);

UserList[currindex]. IsReplanned = true;

UserList[currindex]. ReqList. Remove (ReqObj);

}

if (!string. IsNullOrEmpty (comment))

{

this. AddCommentToRequest (ReqObj. ReqID, ReqCommentTypes. UserClose_CommentType, comment, ReqObj. ExecutorID);

}

return true;

}

catch

{

return false;

}

private void CheckForCyclicRequests ()

{

DateTime Now = DateTime. Now;

IEnumerable< CyclicRequests> CRList = (from creq in dc. CyclicRequests

join req in dc. Request

on new { creq. CreatorID, creq. Type }

equals

new { req. CreatorID, req. Type }

where creq. BeginDateTime <= Now

& & creq. EndDate > Now

& & creq. BeginDateTime. TimeOfDay <= Now. TimeOfDay

& & creq. isActive==true

& & req. IsCycle==true

& & req. PlanningOnDate. Date == Now. Date

select creq);

List< CyclicRequests> CycleList = (from c in dc. CyclicRequests where c. BeginDateTime <= Now & & c. EndDate > Now & & c. isActive == true select c). ToList ();

CycleList. RemoveAll (c => CRList. Contains (c));

bool AddToRequests;

string CombinedTime;

foreach (CyclicRequests CycleReq in CycleList)

{

AddToRequests=false;

switch (CycleReq. ScheduleType)

{

case Schedule. DailyScheduleType:

AddToRequests = true;

break;

case Schedule. WeeklyScheduleType:

if (CycleReq. RunDays. Contains (DateTime. Now. DayOfWeek. ToString ()))

{

AddToRequests = true;

}

break;

case Schedule. MonthlyScheduleType:

if (CycleReq. RunWeeks. Contains (Service. GetWeekOfMonth (DateTime. Now). ToString ()) & & CycleReq. RunDays. Contains (DateTime. Now. DayOfWeek. ToString ()))

{

AddToRequests = true;

}

break;

}

if (AddToRequests)

{

string LocID = GetLocID (CycleReq. CreatorID). ToString ();

CombinedTime = DateTime. Now. ToString («dd MM yyyy «)+CycleReq. Time;

CreateRequest (CycleReq. CreatorID. ToString (), CycleReq. Type. ToString (), CombinedTime, CycleReq. comment, «1», LocID, true, false, null, false, null);

}

}

return;

public string Validate (string[] str)

{

return ««;

public string CreateCycleRequest (string dtBeginDT, string dtEndDT, string intCrID, string comment, string gdType, string SchedType, string ReqTime, string RunDays=null, string RunWeeks=null)

{

int CreatorUID;

if (!int. TryParse (intCrID, out CreatorUID))

{

return «Ошибка Не получен ID инициатора»;

}

Guid ReqType;

if (!Guid. TryParse (gdType, out ReqType))

{

return «Ошибка Не получен тип заявки»;

}

if (ReqTime. Trim () == String. Empty)

{

return «Ошибка Время должно быть заполнено»;

}

DateTime BeginDate;

if (!DateTime. TryParse (dtBeginDT, out BeginDate))

{

return «Ошибка Не получена дата начала действия заявки, формат даты должен соответствовать: дд мм гггг чч: мм»;

DateTime EndDate;

if (!DateTime. TryParse (dtEndDT, out EndDate))

{

return «Ошибка Не получена дата окончания действия заявки, формат даты должен соответствовать: дд мм гггг чч: мм»;

CyclicRequests CReq = new CyclicRequests { BeginDateTime = BeginDate, EndDate = EndDate, ID = Guid. NewGuid (), isActive = true, CreatorID = CreatorUID, RunDays = RunDays, Type = ReqType, comment = comment, Time=ReqTime, ScheduleType=SchedType, RunWeeks=RunWeeks };

try

{

dc. CyclicRequests. InsertOnSubmit (CReq);

dc. SubmitChanges ();

return ««;

}

catch (Exception ex)

{

return «Ошибка не удалось записать заявку «+ex. Message;

}

}

public bool SetRequestCompleted (int Uid, Guid ReqID)

{

UserContainer Current = UserList. SingleOrDefault (c => c. UserID == Uid);

if (Current ≠ null)

{

int CurrIndex = UserList. IndexOf (Current);

Request RObj = dc. Request. SingleOrDefault (c => c. ReqID == ReqID);

if (RObj ≠ null)

{

RObj. Status = dc. Status. First (s => s. ID == Status. Completed_StatusCode);

RObj. CompleteDate = DateTime. Now;

if (RObj. PlanningCompleteDate. Value. CompareTo (RObj. CompleteDate) < 0)

{

AddViolation (RObj. ReqID, Violations. BreakTimeViolation);

}

try

{

dc. SubmitChanges ();//При закрытии заявки удалять ее из листа и записывать в базу (сначала в базу потом удалять)

UserList[CurrIndex]. IsReplanned = true;

UserList[CurrIndex]. PauseTimer. Start ();

CheckForCyclicRequests ();

UserList[CurrIndex]. ReqList. Sort (ReqComparer);

OTD Department = dc. OTD. SingleOrDefault (s => s. ID == RObj. WorkClassificator. DepartmentID);

long? AccEmailId = null;

if (Department ≠ null)

{

AccEmailId = Department. ID_EmailAccount;

}

UserContainer. NotificateUser (RObj. ExecutorID, RObj. CreatorID, «Оповещение о закрытии заявки», «Ваша заявка «+ RObj. WorkClassificator. TitleRow + «завершена исполнителем «+ RObj. Executor. FIO + «. Подтвердите ее завершение в интерфейсе пользователя», AccEmailId);

UserList[CurrIndex]. ReqList. Remove (RObj);

return true;

}

catch

{

return false;

}

}

}

return false;

}

public void StartFirst (int id)

{

UserContainer Current = UserList. SingleOrDefault (c => c. UserID == id);

if (Current ≠ null)

{

int CurrIndex = UserList. IndexOf (Current);

UserList[CurrIndex]. PauseTimer. Stop ();

UserList[CurrIndex]. StartRequest ();

}

}

public IEnumerable< Request> GetUserRequests (int CreatorID)

{

List< Request> IReq = (from cr in dc. Request where cr. CreatorID == CreatorID & & cr. CurrentStatus ≠ Status. Closed_StatusCode select cr). ToList ();

IReq. Sort (new RequestComparer ());

return IReq. AsEnumerable ();

}

private Priorities SetRequestPriority (bool isCycle, int CreatorID, bool HighestPriority)

{

if (!HighestPriority)

{

SOTRUD Creator = dc. SOTRUD. Single (s => s. ID == CreatorID);

dc. Refresh (System. Data. Linq. RefreshMode. OverwriteCurrentValues, Creator);

return Creator. Priorities;

}

else

{

return dc. Priorities. Single (e => e. ID == 1);

}

public void TransmitRequest (string RID, int FromUID, int ToUID, string comment, bool isOffline)

{

Request Current = dc. Request. SingleOrDefault (s => s. ReqID == Guid. Parse (RID));

if (Current ≠ null)

{

if (this. UserIsHere (FromUID))

{

int indexFrom = UserList. IndexOf (UserList. Single (u => u. UserID == FromUID));

UserContainer uc = UserList[indexFrom];

if (Current ≠ null & & uc. ReqList. Contains (Current))

{

UserList[indexFrom]. ReqList. Remove (Current);

UserList[indexFrom]. ReqList. Sort (new RequestComparer ());

UserList[indexFrom]. IsReplanned = true;

}

}

AddCommentToRequest (Guid. Parse (RID), ReqCommentTypes. Redirect_CommentType, comment, FromUID);

if (Current. CurrentStatus ≠ Status. onRegistration_StatusCode)

{

Current. Status = dc. Status. Single (i => i. ID == Status. WaitingOpen_StatusCode);

Current. Executor = dc. SOTRUD. Single (s => s. ID == ToUID);

Current. PlanningOnDate = DateTime. Parse (GetPlanningTime (Current. CreatorID, Current. IsCycle, Current. Type, Current. Executor. LocationID. Value, false, ToUID));

dc. SubmitChanges ();

OTD Department = dc. OTD. SingleOrDefault (s => s. ID == Current. WorkClassificator. DepartmentID);

long? AccEmailId = null;

if (Department ≠ null)

{

AccEmailId = Department. ID_EmailAccount;

}

UserContainer. NotificateUser (Current. ExecutorID, Current. CreatorID, «Оповещение о передаче заявки», «Ваша заявка «+ Current. WorkClassificator. TitleRow + «передана другому исполнителю. Ваш новый исполнитель «+ Current. Executor. FIO + «. Планируемое время закрытия — «+ Current. PlanningCompleteDate. Value. ToString (), AccEmailId);

UserContainer. NotificateUser (Current. CreatorID, Current. ExecutorID, «Оповещение о передаче заявки», «Вам была передана заявка «+ Current. WorkClassificator. TitleRow + «. Инициатор заявки «+ Current. Creator. FIO + «. Планируемое время закрытия — «+ Current. PlanningCompleteDate. Value. ToString (), AccEmailId);

if (!isOffline)

{

int indexTo = UserList. IndexOf (UserList. Single (u => u. UserID == ToUID));

UserList[indexTo]. ReqList. Add (Current);

UserList[indexTo]. ReqList. Sort (new RequestComparer ());

UserList[indexTo]. IsReplanned = true;

}

}

}

public void EditPlanningTime (string RID, int UID, string NewTime, string comment)

{

int index = UserList. IndexOf (UserList. Single (u => u. UserID == UID));

DateTime NewT = DateTime. Parse (NewTime);

double MinutesToMove=0;

Request Current = UserList[index]. ReqList. Single (r => r. ReqID == Guid. Parse (RID));

int ReqIndex = UserList[index]. ReqList. IndexOf (Current);

AddCommentToRequest (Guid. Parse (RID), ReqCommentTypes. ChangeData_CommentType, comment, UID);

if (NewT. Date==DateTime. Now. Date)

{

MinutesToMove= NewT. Subtract (UserList[index]. ReqList[ReqIndex]. PlanningCompleteDate. Value). TotalMinutes;

}

UserList[index]. ReqList[ReqIndex]. PlanningCompleteDate = NewT;

UserList[index]. ReqList[ReqIndex]. PlanningOnDate = UserList[index]. ReqList[ReqIndex]. PlanningCompleteDate. Value. Subtract (new TimeSpan (0, Current. PlanningTime, 0));

//}

if (UserList[index]. ReqList[ReqIndex]. CurrentStatus<=Status. Opened_StatusCode)

{

UserList[index]. ReqList[ReqIndex]. Status = dc. Status. Single (s => s. ID == Status. WaitingOpen_StatusCode);

UserList[index]. ReqList. Sort (new RequestComparer ());

dc. SubmitChanges ();

ReqIndex = UserList[index]. ReqList. IndexOf (Current);

UserList[index]. MovePlanningCompleteTime (ReqIndex, MinutesToMove);

UserList[index]. IsReplanned = true;

AddViolation (Current. ReqID, Violations. ChangeTimeViolation);

private UserContainer FindUser (Guid TypeReq, int creatorID, int CreatorLocationID)

{

/*Если юзер не найден — найти заместителя, если заместитель не найден идем на уровень выше по классификтору

Если никто не найден = возврат -1*/

WorkClassificator ClassObj = dc. WorkClassificator. SingleOrDefault (r => r. ID == TypeReq & & r. responsibleDolgID. HasValue);

UserContainer User = UserList. Find (r => (r. PositionID == ClassObj. responsibleDolgID. Value || ClassObj. SOTRUD_DOLG. MainPost. Count (a=>a. ID==r. PositionID)>0) & & GetLocID (r. UserID)==CreatorLocationID);

if (User ≠ null)

{

return User;

}

else

User = UserList. Find (r => (r. PositionID == ClassObj. AssistantDolgID. Value

if (User ≠ null)

{

return User;

}

else

{

if (ClassObj. ParentUID. HasValue)

{

FindUser (ClassObj. ParentUID. Value, creatorID, CreatorLocationID);

}

}

if (User == null)

{

return UserList. SingleOrDefault (s => s. UserID == 104);

}

return User;

}

private int GetLocID (int id)

{

SOTRUD sotr = dc. SOTRUD. Single (s => s. ID == id);

if (sotr. LocationID. HasValue)

{

return sotr. LocationID. Value;

}

else

{

return 1;

}

}

public int FindExecutorByReqType (Guid TypeReq, int CreatorID, int CreatorLocationID)

{

WorkClassificator ClassObj = dc. WorkClassificator. Single (r => r. ID == TypeReq);

SOTRUD User = dc. SOTRUD. FirstOrDefault (r => (r. SOTRUD_DOLG. ID == ClassObj. responsibleDolgID. Value || ClassObj. SOTRUD_DOLG. MainPost. Contains (r. SOTRUD_DOLG)) & & r. LocationID == CreatorLocationID & & r. DATA_YVOL. HasValue == false);

if (User == null)

{

User = dc. SOTRUD. FirstOrDefault (r => (r. SOTRUD_DOLG. ID == ClassObj. AssistantDolgID. Value || ClassObj. SOTRUD_DOLG1. MainPost. Contains (r. SOTRUD_DOLG)) & & r. LocationID == CreatorLocationID & & r. DATA_YVOL. HasValue == false);

if (User == null)

{

return ClassObj. ParentUID. HasValue== true? FindExecutorByReqType (ClassObj. ParentUID. Value, CreatorID, CreatorLocationID): 104;

return User. ID;

public UserContainer GetUserContainer (int id)

{

UserContainer uc = UserList. SingleOrDefault (u => u. UserID == id);

if (uc ≠ null)

{

uc. ReqList. Sort (ReqComparer);

}

return uc;

}

public bool UserIsHere (int id)

{

return (UserList. Find (f => f. UserID == id) ≠ null);

}

public List< UsersList> GetActiveUsers ()

{

try

List< UsersList> ul = UserList. ConvertAll (new Converter< UserContainer, UsersList> (ContainerToUser));

return ul;

}

catch

{

List< UsersList> ul = UserList. ConvertAll (new Converter< UserContainer, UsersList> (ContainerToUser));

return ul;

}

private void SetHighestPriority (Request Req, UserContainer user)

{

//Установить высший приоритет == 1

if (user. ReqList. Contains (Req) & & !Req. PlannedRequest)

{

Req. Priorities = dc. Priorities. SingleOrDefault (p => p. ID == 1);

Request LastOpen = user. ReqList. FindLast (e=>e. CurrentStatus==Status. Opened_StatusCode);

if (LastOpen ≠ null)

{

Req. PlanningOnDate = LastOpen. PlanningCompleteDate. Value;

}

else

{

Req. PlanningOnDate = DateTime. Now;

}

Req. PlanningCompleteDate = Req. PlanningOnDate. AddMinutes (Req. PlanningTime);

dc. SubmitChanges ();

user. ReqList. Sort (ReqComparer);

user. ReplanAll (user. ReqList. IndexOf (Req) + 1, Req. PlanningCompleteDate. Value);

}

//Перепланировать время в соответствии с приоритетом

}

private void MoveUp (Request Req, UserContainer user)

{

if (user. ReqList. Contains (Req) & & !Req. PlannedRequest)

{

int CurrentIndex = user. ReqList. IndexOf (Req);

if (CurrentIndex > 0)

{

Req. PlanningOnDate = user. ReqList[CurrentIndex — 1]. PlanningOnDate;

Req. PlanningCompleteDate = Req. PlanningOnDate. AddMinutes (Req. PlanningTime);

user. ReqList[CurrentIndex — 1]. PlanningOnDate = Req. PlanningCompleteDate. Value. AddMinutes (5);

user. ReqList[CurrentIndex — 1]. PlanningCompleteDate=user. ReqList[CurrentIndex — 1]. PlanningOnDate. AddMinutes (user. ReqList[CurrentIndex — 1]. PlanningTime);

}

private void MoveDown (Request Req, UserContainer user)

{

if (user. ReqList. Contains (Req) & & !Req. PlannedRequest)

int CurrentIndex = user. ReqList. IndexOf (Req);

if (CurrentIndex < user. ReqList. Count-1)

{

Req. PlanningOnDate = user. ReqList[CurrentIndex + 1]. PlanningOnDate;

Req. PlanningCompleteDate = Req. PlanningOnDate. AddMinutes (Req. PlanningTime);

user. ReqList[CurrentIndex + 1]. PlanningCompleteDate = Req. PlanningOnDate. AddMinutes (-5);

user. ReqList[CurrentIndex + 1]. PlanningOnDate = user. ReqList[CurrentIndex + 1]. PlanningCompleteDate. Value. AddMinutes (user. ReqList[CurrentIndex + 1]. PlanningTime * -1);

public void ManagerContextAction (string ActCode, string ReqID)

{

Guid gReqID;

if (Guid. TryParse (ReqID, out gReqID))

{

Request Req = dc. Request. SingleOrDefault (s => s. ReqID == gReqID);

if (Req ≠ null)

{

UserContainer container = UserList. SingleOrDefault (s => s. UserID == Req. ExecutorID);

if ((Req. CurrentStatus < Status. Completed_StatusCode) & & container≠null)

{

switch (ActCode)

{

case ContextAction. SetHighestPriority:

SetHighestPriority (Req, container);

break;

case ContextAction. MoveUp:

MoveUp (Req, container);

break;

case ContextAction. MoveDown:

MoveDown (Req, container);

break;

case ContextAction. IncludeToQueue:

IncludeToQueue (Req, container);

break;

case ContextAction. ExcludeFromQueue:

ExcludeFromQueue (Req, container);

break;

case ContextAction. CloseRequest:

SetRequestCompleted (container. UserID, Req. ReqID);

break;

default:

break;

}

try

{

dc. SubmitChanges ();

container. IsReplanned = true;

container. ReqList. Sort (ReqComparer);

}

catch

{

}

}

}

}

}

private void ExcludeFromQueue (Request Req, UserContainer container)

{

Req. Status = dc. Status. Single (s => s. ID == Status. Excluded_StatusCode);

ПоказатьСвернуть
Заполнить форму текущей работой