/// <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> /// <param name="service"></param> /// <returns></returns> public Schedule GetServiceSchedule(Service service) { if (!serviceSchedule.ContainsKey(service)) { logger.Info("Загрузка расписания для услуги [{0}]", service); using (var session = SessionProvider.OpenSession()) using (var transaction = session.BeginTransaction()) { Schedule schedule = session.CreateCriteria<ServiceExceptionSchedule>() .Add(Restrictions.Eq("Service", service)) .Add(Restrictions.Eq("ScheduleDate", PlanDate)) .SetMaxResults(1) .UniqueResult<ServiceExceptionSchedule>(); if (schedule == null) { schedule = session.CreateCriteria<DefaultExceptionSchedule>() .Add(Restrictions.Eq("ScheduleDate", PlanDate)) .UniqueResult<DefaultExceptionSchedule>(); if (schedule == null) { var dayOfWeek = PlanDate.DayOfWeek; schedule = session.CreateCriteria<ServiceWeekdaySchedule>() .Add(Restrictions.Eq("Service", service)) .Add(Restrictions.Eq("DayOfWeek", dayOfWeek)) .SetMaxResults(1) .UniqueResult<ServiceWeekdaySchedule>(); if (schedule == null) { schedule = session.CreateCriteria<DefaultWeekdaySchedule>() .Add(Restrictions.Eq("DayOfWeek", dayOfWeek)) .UniqueResult<DefaultWeekdaySchedule>(); } } } if (schedule == null) { throw new Exception("Не удалось определить расписание для услуги"); } serviceSchedule.Add(service, schedule); transaction.Commit(); } } return serviceSchedule[service]; }
public async Task<DTO.Service> EditService(DTO.Service source) { return await Task.Run(() => { CheckPermission(UserRole.Administrator, AdministratorPermissions.Services); using (var session = SessionProvider.OpenSession()) using (var transaction = session.BeginTransaction()) { Service service; if (!source.Empty()) { var serviceId = source.Id; service = session.Get<Service>(serviceId); if (service == null) { throw new FaultException<ObjectNotFoundFault>(new ObjectNotFoundFault(serviceId), string.Format("Услуга [{0}] не найдена", serviceId)); } } else { service = new Service(); } service.IsActive = source.IsActive; service.Code = source.Code; service.Priority = source.Priority; service.Name = source.Name; service.Comment = source.Comment; service.Tags = source.Tags; service.Description = source.Description; service.Link = source.Link; service.MaxSubjects = source.MaxSubjects; service.MaxEarlyDays = source.MaxEarlyDays; service.MaxClientRecalls = source.MaxClientRecalls; service.IsPlanSubjects = source.IsPlanSubjects; service.ClientRequire = source.ClientRequire; service.ClientCallDelay = source.ClientCallDelay; service.TimeIntervalRounding = source.TimeIntervalRounding; service.IsUseType = source.IsUseType; service.LiveRegistrator = source.LiveRegistrator; service.EarlyRegistrator = source.EarlyRegistrator; service.Color = source.Color; service.FontSize = source.FontSize; if (source.ServiceGroup != null) { Guid serviceGroupId = source.ServiceGroup.Id; ServiceGroup serviceGroup = session.Get<ServiceGroup>(serviceGroupId); if (serviceGroup == null) { throw new FaultException<ObjectNotFoundFault>(new ObjectNotFoundFault(serviceGroupId), string.Format("Группа услуг [{0}] не найдена", serviceGroupId)); } service.ServiceGroup = serviceGroup; } else { service.ServiceGroup = null; } var errors = service.Validate(); if (errors.Length > 0) { throw new FaultException(errors.First().Message); } session.Save(service); var todayQueuePlan = QueueInstance.TodayQueuePlan; using (var locker = todayQueuePlan.WriteLock()) { transaction.Commit(); todayQueuePlan.Put(service); } return Mapper.Map<Service, DTO.Service>(service); } }); }