/// <summary> /// Получить доступные временные интервалы /// </summary> public ServiceFreeTime GetServiceFreeTime(Service service, ServiceStep serviceStep, ClientRequestType requestType, int subjects = 1) { var schedule = GetServiceSchedule(service); if (schedule == null) { throw new Exception("Не удалось определить расписание для услуги"); } if (!schedule.IsWorked) { throw new Exception("На указанную дату услуга не оказывается"); } switch (requestType) { case ClientRequestType.Live: if (!schedule.RenderingMode.HasFlag(ServiceRenderingMode.LiveRequests)) { throw new Exception("Живая очередь для данной услуги на указанный день отключена"); } break; case ClientRequestType.Early: if (!schedule.RenderingMode.HasFlag(ServiceRenderingMode.EarlyRequests)) { throw new Exception("Предварительная запись для данной услуги на указанный день отключена"); } break; } var report = new List<string>() { string.Format("Поиск свободного времени на дату {0:dd.MM.yyyy} и время {1:hh\\:mm\\:ss}", PlanDate, PlanTime) }; // Только подходящие параметры обслуживания var serviceRenderingMode = requestType == ClientRequestType.Early ? ServiceRenderingMode.EarlyRequests : ServiceRenderingMode.LiveRequests; report.Add(string.Format("Выбран режим обслуживания [{0}]", serviceRenderingMode)); var renderings = GetServiceRenderings(schedule, serviceStep, serviceRenderingMode); var potentialOperatorsPlans = OperatorsPlans .Where(p => renderings.Any(r => r.Operator.IsActive && r.Operator.Equals(p.Operator))) .ToList(); if (potentialOperatorsPlans.Count == 0) { throw new Exception("В системе нет активных операторов способных оказать услугу"); } report.Add("Найдены следующие потенциальные планы операторов"); foreach (var o in potentialOperatorsPlans) { report.Add(o.ToString()); } if (PlanDate == DateTime.Today && schedule.OnlineOperatorsOnly) { potentialOperatorsPlans.RemoveAll(o => !o.Operator.Online); report.Add("Оставлены только операторы онлайн"); foreach (var o in potentialOperatorsPlans) { report.Add(o.ToString()); } } var timeIntervals = new List<TimeSpan>(); var startTime = schedule.StartTime; if (PlanTime > startTime) { startTime = PlanTime; } report.Add(string.Format("Поиск интервалов времени с {0:hh\\:mm\\:ss}", startTime)); var clientInterval = requestType == ClientRequestType.Live ? schedule.LiveClientInterval : schedule.EarlyClientInterval; int openedRequests = 0; foreach (var potentialOperatorPlan in potentialOperatorsPlans) { openedRequests += potentialOperatorPlan.ClientRequestPlans .Select(p => p.ClientRequest) .Count(r => r.Type == requestType); report.Add(string.Format("В плане оператора [{0}] {1} открытых запросов", potentialOperatorPlan, openedRequests)); var intervalTime = startTime; while (intervalTime < schedule.FinishTime) { intervalTime = potentialOperatorPlan.GetNearTimeInterval(intervalTime, schedule, requestType, subjects); report.Add(string.Format("Найден ближайший интвервал времени {0:hh\\:mm\\:ss}", intervalTime)); var timeIntervalRounding = service.TimeIntervalRounding; if (timeIntervalRounding != TimeSpan.Zero) { var rounding = new TimeSpan(intervalTime.Ticks % timeIntervalRounding.Ticks); if (rounding != TimeSpan.Zero) { report.Add(string.Format("Округление интервала {0:hh\\:mm\\:ss}", rounding)); intervalTime = intervalTime.Add(rounding <= schedule.Intersection ? -rounding : timeIntervalRounding.Subtract(rounding)); } } report.Add(string.Format("Найден интвервал времени {0:hh\\:mm\\:ss}", intervalTime)); timeIntervals.Add(intervalTime); intervalTime = intervalTime.Add(clientInterval); if (timeIntervals.Count() > 1000) { throw new OverflowException("Возможно переполнение памяти. Обратитесь к администратору."); } } } int freeTimeIntervals; if (PlanDate != DateTime.Today) { int maxOnlineOperators = schedule.MaxOnlineOperators > 0 ? schedule.MaxOnlineOperators : potentialOperatorsPlans.Count; int maxRequests = (int)((schedule.EarlyFinishTime - schedule.EarlyStartTime).Ticks / clientInterval.Ticks) * maxOnlineOperators; report.Add(string.Format("Максимальное кол-во запросов {0}", maxRequests)); int maxEarlyClientRequests = maxRequests * schedule.EarlyReservation / 100; report.Add(string.Format("Максимальное кол-во запросов с учетом резервирования {0}", maxEarlyClientRequests)); freeTimeIntervals = maxEarlyClientRequests - openedRequests; if (freeTimeIntervals <= 0) { throw new Exception("Возможности резервирования для данной услуги на указанный день исчерпаны"); } timeIntervals.RemoveAll(i => i < schedule.EarlyStartTime); timeIntervals.RemoveAll(i => i.Add(clientInterval - schedule.Intersection) > schedule.EarlyFinishTime); if (freeTimeIntervals > timeIntervals.Count) { freeTimeIntervals = timeIntervals.Count; } } else { timeIntervals.RemoveAll(i => i.Add(clientInterval - schedule.Intersection) > schedule.FinishTime); freeTimeIntervals = timeIntervals.Count; } return new ServiceFreeTime() { Service = service, Schedule = schedule, TimeIntervals = timeIntervals.ToArray(), FreeTimeIntervals = freeTimeIntervals, Report = report }; }
/// <summary> /// Получить параметры обслуживания /// </summary> public ServiceRendering[] GetServiceRenderings(Schedule schedule, ServiceStep serviceStep, ServiceRenderingMode serviceRenderingMode) { var key = new ServiceRenderingKey(schedule, serviceStep, serviceRenderingMode); if (!serviceRenderings.ContainsKey(key)) { logger.Info("Загрузка параметров оказания услуги для раписания [{0}]", schedule); using (var session = SessionProvider.OpenSession()) using (var transaction = session.BeginTransaction()) { serviceRenderings.Add(key, session.CreateCriteria<ServiceRendering>() .Add(Restrictions.Eq("Schedule", schedule)) .Add(serviceStep != null ? Restrictions.Eq("ServiceStep", serviceStep) : Restrictions.IsNull("ServiceStep")) .Add(new Disjunction() .Add(Restrictions.Eq("Mode", serviceRenderingMode)) .Add(Restrictions.Eq("Mode", ServiceRenderingMode.AllRequests))) .List<ServiceRendering>() .ToArray()); transaction.Commit(); } } return serviceRenderings[key]; }
public async Task<DTO.ServiceStep> EditServiceStep(DTO.ServiceStep source) { return await Task.Run(() => { CheckPermission(UserRole.Administrator, AdministratorPermissions.Services); using (var session = SessionProvider.OpenSession()) using (var transaction = session.BeginTransaction()) { ServiceStep serviceStep; if (!source.Empty()) { var serviceStepId = source.Id; serviceStep = session.Get<ServiceStep>(serviceStepId); if (serviceStep == null) { throw new FaultException<ObjectNotFoundFault>(new ObjectNotFoundFault(serviceStepId), string.Format("Этап услуги [{0}] не найден", serviceStepId)); } } else { serviceStep = new ServiceStep(); } if (source.Service != null) { var serviceId = source.Service.Id; var service = session.Get<Service>(serviceId); if (service == null) { throw new FaultException<ObjectNotFoundFault>(new ObjectNotFoundFault(serviceId), string.Format("Услуга [{0}] не найдена", serviceId)); } serviceStep.Service = service; } else { serviceStep.Service = null; } serviceStep.Name = source.Name; var errors = serviceStep.Validate(); if (errors.Length > 0) { throw new FaultException(errors.First().Message); } session.Save(serviceStep); transaction.Commit(); return Mapper.Map<ServiceStep, DTO.ServiceStep>(serviceStep); } }); }