public async Task<DTO.ClientRequest> PostponeClientRequest(Guid clientRequestId, TimeSpan postponeTime) { return await Task.Run(() => { using (var session = SessionProvider.OpenSession()) using (var transaction = session.BeginTransaction()) { var clientRequest = session.Get<ClientRequest>(clientRequestId); if (clientRequest == null) { throw new FaultException<ObjectNotFoundFault>(new ObjectNotFoundFault(clientRequestId), string.Format("Запрос клиента [{0}] не найден", clientRequestId)); } try { clientRequest.Postpone(postponeTime); } catch (Exception exception) { throw new FaultException(exception.Message); } clientRequest.Version++; session.Save(clientRequest); var queueEvent = new ClientRequestEvent() { ClientRequest = clientRequest, Message = string.Format("[{0}] отложил на [{1} мин.] запрос клиента [{2}]", currentUser, postponeTime.TotalMinutes, clientRequest) }; session.Save(queueEvent); var todayQueuePlan = QueueInstance.TodayQueuePlan; using (var locker = todayQueuePlan.WriteLock()) { transaction.Commit(); todayQueuePlan.Put(clientRequest); todayQueuePlan.Build(DateTime.Now.TimeOfDay); } QueueInstance.Event(queueEvent); return Mapper.Map<ClientRequest, DTO.ClientRequest>(clientRequest); } }); }
public async Task<DTO.ClientRequest> AddLiveClientRequest(Guid clientId, Guid serviceId, bool isPriority, Dictionary<Guid, object> parameters, int subjects) { return await Task.Run(() => { CheckPermission(UserRole.Administrator, AdministratorPermissions.ClientsRequests); using (var session = SessionProvider.OpenSession()) using (var transaction = session.BeginTransaction()) { Client client = null; if (clientId != Guid.Empty) { client = session.Get<Client>(clientId); if (client == null) { throw new FaultException<ObjectNotFoundFault>(new ObjectNotFoundFault(clientId), string.Format("Клиент [{0}] не найден", clientId)); } } var service = session.Get<Service>(serviceId); if (service == null) { throw new FaultException<ObjectNotFoundFault>(new ObjectNotFoundFault(serviceId), string.Format("Услуга [{0}] не найдена", serviceId)); } if (!service.IsActive) { throw new FaultException("Выбранная услуга не активна"); } if (service.ClientRequire && client == null) { throw new FaultException("Выбранная услуга требует наличие клиента"); } var clientRequest = new ClientRequest() { Client = client, Service = service, ServiceStep = service.GetFirstStep(session), Subjects = subjects, IsPriority = client != null && client.VIP }; var currentTime = DateTime.Now.TimeOfDay; var todayQueuePlan = QueueInstance.TodayQueuePlan; using (var locker = todayQueuePlan.ReadLock()) { var schedule = todayQueuePlan.GetServiceSchedule(service); int count = session.CreateCriteria<ClientRequest>() .Add(Restrictions.Eq("RequestDate", DateTime.Today)) .Add(Restrictions.Eq("Client", client)) .Add(Restrictions.Eq("Service", service)) .SetProjection(Projections.RowCount()) .UniqueResult<int>(); if (count >= schedule.MaxClientRequests) { throw new FaultException("Достигнуто максимальное кол-во запрос на текущий день"); } #if !DEBUG if (currentTime < schedule.StartTime) { throw new FaultException(string.Format("Время начала оказания услуги наступит в {0}", schedule.StartTime)); } #endif try { var freeTime = todayQueuePlan.GetServiceFreeTime(service, clientRequest.ServiceStep, ClientRequestType.Live, service.IsPlanSubjects ? subjects : 1); var timeIntervals = freeTime.TimeIntervals; if (timeIntervals.Length == 0) { throw new FaultException("Нет свободного времени для оказания услуги"); } } catch (Exception exception) { throw new FaultException(exception.Message); } } logger.Info("Добавление нового запроса в план очереди"); using (var locker = todayQueuePlan.WriteLock()) { clientRequest.Number = ++todayQueuePlan.LastNumber; } clientRequest.RequestDate = DateTime.Today; clientRequest.RequestTime = currentTime.Add(service.ClientCallDelay); clientRequest.IsPriority = isPriority; clientRequest.Type = ClientRequestType.Live; var error = clientRequest.Validate().FirstOrDefault(); if (error != null) { throw new FaultException(error.Message); } session.Save(clientRequest); var queueEvent = new ClientRequestEvent() { ClientRequest = clientRequest, Message = string.Format("[{0}] добавил новый запрос клиента в живую очередь [{1}]", currentUser, clientRequest) }; session.Save(queueEvent); var defaultConfig = session.Get<DefaultConfig>(ConfigType.Default); if (defaultConfig.IsDebug) { session.Save(new QueuePlanReport() { ClientRequest = clientRequest, Report = string.Join(Environment.NewLine, todayQueuePlan.Report) }); } using (var locker = todayQueuePlan.WriteLock()) { transaction.Commit(); todayQueuePlan.AddClientRequest(clientRequest); todayQueuePlan.Build(currentTime); } QueueInstance.Event(queueEvent); logger.Info("Запрос добавлен в план очереди"); return Mapper.Map<ClientRequest, DTO.ClientRequest>(clientRequest); } }); }
public async Task<DTO.ClientRequest> CancelClientRequest(Guid clientRequestId) { return await Task.Run(() => { CheckPermission(UserRole.Administrator, AdministratorPermissions.ClientsRequests); using (var session = SessionProvider.OpenSession()) using (var transaction = session.BeginTransaction()) { var clientRequest = session.Get<ClientRequest>(clientRequestId); if (clientRequest == null) { throw new FaultException<ObjectNotFoundFault>(new ObjectNotFoundFault(clientRequestId), string.Format("Запрос клиента [{0}] не найден", clientRequestId)); } try { clientRequest.Cancel(); } catch (Exception exception) { throw new FaultException(exception.Message); } clientRequest.Version++; session.Save(clientRequest); var queueEvent = new ClientRequestEvent() { ClientRequest = clientRequest, Message = string.Format("[{0}] отмененил запрос клиента [{1}]", currentUser, clientRequest) }; session.Save(queueEvent); var todayQueuePlan = QueueInstance.TodayQueuePlan; using (var locker = todayQueuePlan.WriteLock()) { transaction.Commit(); todayQueuePlan.Put(clientRequest); todayQueuePlan.Build(DateTime.Now.TimeOfDay); } QueueInstance.Event(queueEvent); return Mapper.Map<ClientRequest, DTO.ClientRequest>(clientRequest); } }); }
public async Task PostponeCurrentClientRequest(TimeSpan postponeTime) { await Task.Run(() => { CheckPermission(UserRole.Operator); using (var session = SessionProvider.OpenSession()) using (var transaction = session.BeginTransaction()) { var queueOperator = (Operator)currentUser; try { ClientRequest clientRequest; var todayQueuePlan = QueueInstance.TodayQueuePlan; using (var locker = todayQueuePlan.ReadLock()) { clientRequest = session.Merge(todayQueuePlan.GetOperatorPlan(queueOperator) .CurrentClientRequestPlan.ClientRequest); } clientRequest.Postpone(postponeTime); clientRequest.Version++; session.Save(clientRequest); var queueEvent = new ClientRequestEvent() { ClientRequest = clientRequest, Message = string.Format("Запрос клиента был отложен оператором {0} на {1} мин.", queueOperator, postponeTime.TotalMinutes) }; session.Save(queueEvent); using (var locker = todayQueuePlan.WriteLock()) { transaction.Commit(); todayQueuePlan.Put(clientRequest); todayQueuePlan.Build(DateTime.Now.TimeOfDay); } QueueInstance.ClientRequestUpdated(clientRequest); QueueInstance.Event(queueEvent); } catch (Exception exception) { throw new FaultException(exception.Message); } } }); }
public async Task<DTO.ClientRequest> AddEarlyClientRequest(Guid clientId, Guid serviceId, DateTime requestDate, TimeSpan requestTime, Dictionary<Guid, object> parameters, int subjects) { return await Task.Run(() => { CheckPermission(UserRole.Administrator, AdministratorPermissions.ClientsRequests); using (var session = SessionProvider.OpenSession()) using (var transaction = session.BeginTransaction()) { Client client = null; if (clientId != Guid.Empty) { client = session.Get<Client>(clientId); if (client == null) { throw new FaultException<ObjectNotFoundFault>(new ObjectNotFoundFault(clientId), string.Format("Клиент [{0}] не найден", clientId)); } } var service = session.Get<Service>(serviceId); if (service == null) { throw new FaultException<ObjectNotFoundFault>(new ObjectNotFoundFault(serviceId), string.Format("Услуга [{0}] не найдена", serviceId)); } if (!service.IsActive) { throw new FaultException("Выбранная услуга не активна"); } if (service.ClientRequire && client == null) { throw new FaultException("Выбранная услуга требует наличие клиента"); } requestDate = requestDate.Date; var isRequestDateToday = requestDate == DateTime.Today; QueuePlan queuePlan; if (isRequestDateToday) { queuePlan = QueueInstance.TodayQueuePlan; } else { if (requestDate - DateTime.Today > TimeSpan.FromDays(service.MaxEarlyDays)) { throw new FaultException(string.Format("По указанной услуге запись возможна не более чем за {0} дней", service.MaxEarlyDays)); } queuePlan = new QueuePlan(); queuePlan.Load(requestDate); queuePlan.Build(); } var clientRequest = new ClientRequest() { Client = client, Service = service, ServiceStep = service.GetFirstStep(session), Subjects = subjects }; using (var locker = queuePlan.ReadLock()) { var schedule = queuePlan.GetServiceSchedule(service); int count = session.CreateCriteria<ClientRequest>() .Add(Restrictions.Eq("RequestDate", requestDate)) .Add(Restrictions.Eq("Client", client)) .Add(Restrictions.Eq("Service", service)) .SetProjection(Projections.RowCount()) .UniqueResult<int>(); if (count >= schedule.MaxClientRequests) { throw new FaultException("Достигнуто максимальное кол-во запрос на текущий день"); } try { var freeTime = queuePlan.GetServiceFreeTime(service, clientRequest.ServiceStep, ClientRequestType.Early, subjects); var timeIntervals = freeTime.TimeIntervals; if (timeIntervals.Length == 0) { throw new FaultException("Нет свободного времени для оказания услуги"); } if (!timeIntervals.Contains(requestTime)) { throw new FaultException("Выбрано недопустимое время"); } } catch (Exception exception) { throw new FaultException(exception.Message); } if (subjects < 1) { throw new FaultException("Количество объектов должно быть больше 0"); } } logger.Info("Добавление нового запроса в план очереди"); using (var locker = queuePlan.WriteLock()) { clientRequest.Number = ++queuePlan.LastNumber; } clientRequest.RequestDate = requestDate; clientRequest.RequestTime = requestTime; clientRequest.Type = ClientRequestType.Early; var error = clientRequest.Validate().FirstOrDefault(); if (error != null) { throw new FaultException(error.Message); } session.Save(clientRequest); var queueEvent = new ClientRequestEvent() { ClientRequest = clientRequest, Message = string.Format("[{0}] добавил новый запрос клиента по предварительной записи на дату [{1}] и время [{2}] [{3}]", currentUser, requestDate.ToShortDateString(), requestTime, clientRequest) }; session.Save(queueEvent); var defaultConfig = session.Get<DefaultConfig>(ConfigType.Default); if (defaultConfig.IsDebug) { session.Save(new QueuePlanReport() { ClientRequest = clientRequest, Report = string.Join(Environment.NewLine, queuePlan.Report) }); } if (isRequestDateToday) { using (var locker = queuePlan.WriteLock()) { transaction.Commit(); queuePlan.AddClientRequest(clientRequest); queuePlan.Build(DateTime.Now.TimeOfDay); } } else { transaction.Commit(); } QueueInstance.Event(queueEvent); logger.Info("Запрос добавлен в план очереди"); return Mapper.Map<ClientRequest, DTO.ClientRequest>(clientRequest); } }); }
public async Task ReturnCurrentClientRequest() { await Task.Run(() => { CheckPermission(UserRole.Operator); using (var session = SessionProvider.OpenSession()) using (var transaction = session.BeginTransaction()) { var queueOperator = (Operator)currentUser; try { var clientRequest = session.Merge(QueueInstance.TodayQueuePlan .GetOperatorPlan(queueOperator).CurrentClientRequestPlan.ClientRequest); clientRequest.Return(); clientRequest.Version++; session.Save(clientRequest); var queueEvent = new ClientRequestEvent() { ClientRequest = clientRequest, Message = string.Format("Запрос клиента был возвращен в очередь оператором {0}", queueOperator) }; session.Save(queueEvent); var todayQueuePlan = QueueInstance.TodayQueuePlan; using (var locker = todayQueuePlan.WriteLock()) { transaction.Commit(); todayQueuePlan.Put(clientRequest); todayQueuePlan.Build(DateTime.Now.TimeOfDay); } QueueInstance.ClientRequestUpdated(clientRequest); QueueInstance.Event(queueEvent); } catch (Exception exception) { throw new FaultException(exception.Message); } } }); }
public async Task CallClientByRequestNumber(int number) { await Task.Run(() => { CheckPermission(UserRole.Operator); using (var session = SessionProvider.OpenSession()) using (var transaction = session.BeginTransaction()) { var queueOperator = (Operator)currentUser; try { var events = new List<ClientRequestEvent>(); ClientRequest currentClientRequest = null; var currentClientRequestPlan = QueueInstance.TodayQueuePlan .GetOperatorPlan(queueOperator).CurrentClientRequestPlan; if (currentClientRequestPlan != null) { currentClientRequest = session.Merge(currentClientRequestPlan.ClientRequest); switch (currentClientRequest.State) { case ClientRequestState.Calling: currentClientRequest.Return(); currentClientRequest.Version++; session.Save(currentClientRequest); { var queueEvent = new ClientRequestEvent() { ClientRequest = currentClientRequest, Message = string.Format("Запрос клиента возвращен в очередь {0}", queueOperator) }; session.Save(queueEvent); events.Add(queueEvent); } break; case ClientRequestState.Rendering: if (!currentClientRequest.NextStep(session)) { if (currentClientRequest.Service.IsUseType && currentClientRequest.ServiceType == ServiceType.None) { throw new Exception("Укажите тип услуги перед окончанием обслуживания"); } currentClientRequest.Rendered(); currentClientRequest.Version++; session.Save(currentClientRequest); { var queueEvent = new ClientRequestEvent() { ClientRequest = currentClientRequest, Message = string.Format("Завершено обслуживание клиента [{0}] у оператора [{1}] с производительностью {2:00.00}%", currentClientRequest.Client, queueOperator, currentClientRequest.Productivity) }; session.Save(queueEvent); events.Add(queueEvent); } } else { var queueEvent = new ClientRequestEvent() { ClientRequest = currentClientRequest, Message = string.Format("Запросу установлен следующий этап оказания услуги [{0}]", currentClientRequest.ServiceStep) }; session.Save(queueEvent); events.Add(queueEvent); } break; } } var clientRequest = session.CreateCriteria<ClientRequest>() .Add(Restrictions.Eq("RequestDate", DateTime.Today)) .Add(Restrictions.Eq("Number", number)) .UniqueResult<ClientRequest>(); if (clientRequest == null) { throw new FaultException<ObjectNotFoundFault>(new ObjectNotFoundFault(number), string.Format("Запрос клиента [{0}] не найден", number)); } if (clientRequest.IsClosed) { clientRequest.Restore(); { var queueEvent = new ClientRequestEvent() { ClientRequest = currentClientRequest, Message = string.Format("Запрос клиента [{0}] восстановлен", clientRequest) }; session.Save(queueEvent); events.Add(queueEvent); } } clientRequest.Calling(queueOperator); { var queueEvent = new ClientRequestEvent() { ClientRequest = clientRequest, Message = string.Format("Запрос клиента вызван по номеру к оператору {0}", queueOperator) }; session.Save(queueEvent); QueueInstance.Event(queueEvent); } clientRequest.Version++; session.Save(clientRequest); var todayQueuePlan = QueueInstance.TodayQueuePlan; using (var locker = todayQueuePlan.WriteLock()) { transaction.Commit(); if (currentClientRequest != null) { todayQueuePlan.Put(currentClientRequest); QueueInstance.ClientRequestUpdated(currentClientRequest); } todayQueuePlan.AddClientRequest(clientRequest); todayQueuePlan.Build(DateTime.Now.TimeOfDay); QueueInstance.ClientRequestUpdated(clientRequest); QueueInstance.CallClient(clientRequest); } foreach (var e in events) { QueueInstance.Event(e); } } catch (Exception exception) { throw new FaultException(exception.Message); } } }); }
public async Task RedirectToOperator(Guid redirectOperatorId) { await Task.Run(() => { CheckPermission(UserRole.Operator); using (var session = SessionProvider.OpenSession()) using (var transaction = session.BeginTransaction()) { var queueOperator = (Operator)currentUser; try { var clientRequest = session.Merge(QueueInstance.TodayQueuePlan .GetOperatorPlan(queueOperator).CurrentClientRequestPlan.ClientRequest); var targetOperator = session.Get<Operator>(redirectOperatorId); if (targetOperator == null) { throw new FaultException<ObjectNotFoundFault>(new ObjectNotFoundFault(redirectOperatorId), string.Format("Оператор для передачи [{0}] не найден", redirectOperatorId)); } if (targetOperator.Equals(queueOperator)) { throw new FaultException("Не возможно передать запрос самому себе"); } clientRequest.Redirect(targetOperator); clientRequest.Version++; session.Save(clientRequest); var queueEvent = new ClientRequestEvent() { ClientRequest = clientRequest, Message = string.Format("Запрос клиента передан к оператору {0}", targetOperator) }; session.Save(queueEvent); var todayQueuePlan = QueueInstance.TodayQueuePlan; using (var locker = todayQueuePlan.WriteLock()) { transaction.Commit(); todayQueuePlan.Put(clientRequest); todayQueuePlan.Build(DateTime.Now.TimeOfDay); } QueueInstance.ClientRequestUpdated(clientRequest); QueueInstance.Event(queueEvent); } catch (Exception exception) { throw new FaultException(exception.Message); } } }); }
public async Task UpdateCurrentClientRequest(ClientRequestState state) { await Task.Run(() => { CheckPermission(UserRole.Operator); using (var session = SessionProvider.OpenSession()) using (var transaction = session.BeginTransaction()) { var queueOperator = (Operator)currentUser; ClientRequest clientRequest; var todayQueuePlan = QueueInstance.TodayQueuePlan; using (var locker = todayQueuePlan.ReadLock()) { var currentClientRequestPlan = todayQueuePlan.GetOperatorPlan(queueOperator) .CurrentClientRequestPlan; if (currentClientRequestPlan == null) { throw new FaultException<ObjectNotFoundFault>(new ObjectNotFoundFault(queueOperator.GetId()), string.Format("Текущий запрос клиента не найден у оператора [{0}]", queueOperator)); } clientRequest = session.Merge(currentClientRequestPlan.ClientRequest); } try { var service = clientRequest.Service; var client = clientRequest.Client; string message; switch (clientRequest.State) { case ClientRequestState.Waiting: case ClientRequestState.Redirected: case ClientRequestState.Postponed: switch (state) { case ClientRequestState.Calling: message = string.Format("Клиент [{0}] вызывается к оператору [{1}] на рабочее место [{2}]", client, queueOperator, queueOperator.Workplace); clientRequest.Calling(queueOperator); break; default: throw new Exception(string.Format("Изменение состояния с [{0}] на [{1}] заявки клиента [{2}] не допустимо", clientRequest.State, state, clientRequest)); } break; case ClientRequestState.Calling: switch (state) { case ClientRequestState.Absence: if (clientRequest.ClientRecalls >= service.MaxClientRecalls) { message = string.Format("Клиент [{0}] не подошел к оператору [{1}]", client, queueOperator); clientRequest.Absence(); } else { message = string.Format("Клиент [{0}] не подошел к оператору [{1}] вызов откладывается", client, queueOperator); clientRequest.Postpone(TimeSpan.FromMinutes(5)); clientRequest.ClientRecalls++; } break; case ClientRequestState.Rendering: message = string.Format("Начало обслуживания клиента [{0}] у оператора [{1}]", client, queueOperator); var schedule = todayQueuePlan.GetServiceSchedule(service); clientRequest.Rendering(schedule.LiveClientInterval); break; default: throw new Exception(string.Format("Изменение состояния с [{0}] на [{1}] заявки клиента [{2}] не допустимо", clientRequest.State, state, clientRequest)); } break; case ClientRequestState.Rendering: switch (state) { case ClientRequestState.Rendered: if (!clientRequest.NextStep(session)) { if (clientRequest.Service.IsUseType && clientRequest.ServiceType == ServiceType.None) { throw new Exception("Укажите тип услуги перед окончанием обслуживания"); } clientRequest.Rendered(); message = string.Format("Завершено обслуживание клиента [{0}] у оператора [{1}] с производительностью {2:00.00}%", client, queueOperator, clientRequest.Productivity); } else { message = string.Format("Запросу установлен следующий этап оказания услуги [{0}]", clientRequest.ServiceStep); } break; default: throw new Exception(string.Format("Изменение состояния с [{0}] на [{1}] заявки клиента [{2}] не допустимо", clientRequest.State, state, clientRequest)); } break; default: throw new Exception(string.Format("Заявка клиента [{0}] находиться в не допустимом состоянии [{1}]", clientRequest, clientRequest.State)); } clientRequest.Version++; session.Save(clientRequest); var queueEvent = new ClientRequestEvent() { ClientRequest = clientRequest, Message = message }; session.Save(queueEvent); using (var locker = todayQueuePlan.WriteLock()) { transaction.Commit(); todayQueuePlan.Put(clientRequest); todayQueuePlan.Build(DateTime.Now.TimeOfDay); } QueueInstance.ClientRequestUpdated(clientRequest); QueueInstance.Event(queueEvent); } catch (Exception exception) { throw new FaultException(exception.Message); } } }); }
public async Task CallCurrentClient() { await Task.Run(() => { CheckPermission(UserRole.Operator); using (var session = SessionProvider.OpenSession()) using (var transaction = session.BeginTransaction()) { var queueOperator = currentUser as Operator; ClientRequest clientRequest; try { var todayQueuePlan = QueueInstance.TodayQueuePlan; using (var locker = todayQueuePlan.ReadLock()) { var currentClientRequestPlan = todayQueuePlan.GetOperatorPlan(queueOperator).CurrentClientRequestPlan; if (currentClientRequestPlan == null) { throw new FaultException<ObjectNotFoundFault>(new ObjectNotFoundFault(queueOperator.GetId()), string.Format("Текущий запрос клиента не найден у оператора [{0}]", queueOperator)); } clientRequest = session.Merge(currentClientRequestPlan.ClientRequest); } clientRequest.CallingLastTime = DateTime.Now.TimeOfDay; session.Update(clientRequest); var queueEvent = new ClientRequestEvent() { ClientRequest = clientRequest, Message = string.Format("Оператор [{0}] вызывает клиента", clientRequest.Operator) }; session.Save(queueEvent); using (var locker = todayQueuePlan.WriteLock()) { transaction.Commit(); todayQueuePlan.Put(clientRequest); } QueueInstance.CallClient(clientRequest); } catch (Exception exception) { throw new FaultException(exception.Message); } } }); }