public virtual BreachesInfo GetBreaches()
        {
            var eventMilestones =
                _eventMilestoneRepository.Get(
                    eventMilestone => eventMilestone.CompletedEvent.IsActive &&
                    eventMilestone.IsMandatory &&
                    eventMilestone.CompletedEvent.Period.ShouldCountForBreaches,
                    eventMilestone => eventMilestone.Name,
                    eventMilestone => eventMilestone.CompletedEvent.Period.CompletedEvents,
                    eventMilestone => eventMilestone.CompletedEvent.Period.Pathway.Patient).ToArray();
            var completedEvents = _completedEventRepository.Get(
                completedEvent => completedEvent.IsActive &&
                completedEvent.Period.ShouldCountForBreaches,
                completedEvent => completedEvent.Name,
                completedEvent => completedEvent.Period.CompletedEvents,
                completedEvent => completedEvent.Period.Pathway.Patient).ToArray();

            var eventBreachesInfo = GetEventBreachesInfo(eventMilestones, 0)
                                    .Concat(GetEventBreachesInfo(eventMilestones, 1))
                                    .Concat(GetEventBreachesInfo(eventMilestones, 2))
                                    .Concat(GetEventBreachesInfo(eventMilestones, 3))
                                    .Concat(GetEventBreachesInfo(eventMilestones, -1))
                                    .ToArray();
            var periodBreachedInfo = GetPeriodBreachesInfo(completedEvents, 0)
                                     .Concat(GetPeriodBreachesInfo(completedEvents, 1))
                                     .Concat(GetPeriodBreachesInfo(completedEvents, 2))
                                     .Concat(GetPeriodBreachesInfo(completedEvents, 3))
                                     .ToArray();

            return(new BreachesInfo
            {
                EventsBreaches = eventBreachesInfo,
                PeriodsBreaches = periodBreachedInfo
            });
        }
        public virtual IEnumerable <LiteEventBreachInfo> GetLiteEventBreaches(int periodId)
        {
            var allEventMilestones = _eventMilestoneRepository
                                     .Get(GetCriteriaForPeriodEventMilestones(periodId),
                                          e => e.CompletedEvent.Period,
                                          e => e.Name)
                                     .Where(eventMilestone => eventMilestone.BreachDate != null)
                                     .ToArray();

            var allCompletedEvents = _completedEventRepository.Get(GetCriteriaForPeriodCompletedEvents(periodId), null, null, e => e.Name).ToArray();

            return(allEventMilestones
                   .Where(eventMilestone =>
                          eventMilestone.GetDaysToBreachAt(_clock.TodayDate) != null &&
                          eventMilestone.GetDaysToBreachAt(_clock.TodayDate) <= ThreeDaysToBreach)
                   .Select(eventMilestone =>
            {
                var daysToBreachAt = eventMilestone.GetDaysToBreachAt(_clock.TodayDate);
                var eventBreachStatus = eventMilestone.BreachStatusAt(_clock.TodayDate);
                if (daysToBreachAt != null && eventBreachStatus != null)
                {
                    return new LiteEventBreachInfo
                    {
                        EventDescription = eventMilestone.Name.Description,
                        DaysForStatus = Math.Abs(daysToBreachAt.Value),
                        Status = eventBreachStatus.Value
                    };
                }
                return null;
            })
                   .Concat(allCompletedEvents.Select(completedEvent =>
                                                     new LiteEventBreachInfo
            {
                EventDescription = completedEvent.Name.Description,
                DaysForStatus = (int)completedEvent.PostBreachDays,
                Status = EventBreachStatus.Breached
            }))
                   .ToArray());
        }
        public IEnumerable <FuturePeriodBreachesInfo> GetFuturePeriodBreachesReport(int weeksToBreach, int hospitalId,
                                                                                    string specialtyCode, int clinicianId, Granularity granularity)
        {
            var fromDate        = _clock.Today.AddDays(-weeksToBreach * OneWeek);
            var completedEvents = _completedEventRepository.Get(completedEvent => completedEvent.IsActive &&
                                                                (clinicianId == 0 || completedEvent.Clinician.Id == clinicianId) &&
                                                                (string.IsNullOrEmpty(specialtyCode) || completedEvent.Clinician.Specialty.Code == specialtyCode) &&
                                                                (hospitalId == 0 || completedEvent.Clinician.Hospital.Id == hospitalId) &&
                                                                completedEvent.Period.ShouldCountForBreaches,
                                                                null,
                                                                fromDate,
                                                                e => e.Period.CompletedEvents.Select(completedEvent => completedEvent.Name),
                                                                e => e.Clinician.Specialty,
                                                                e => e.Clinician.Hospital)
                                  .Where(completedEvent =>
                                         completedEvent.Period.GetDaysRemainingAt(_clock.Today) > 0 &&
                                         completedEvent.Period.GetDaysRemainingAt(_clock.Today) <= weeksToBreach * OneWeek)
                                  .ToArray();

            var groupedEventsByGranularity = (from completedEvent in completedEvents
                                              group completedEvent by(granularity == Granularity.Specialty ? completedEvent.Clinician.Specialty.Name :
                                                                      (granularity == Granularity.Clinician ? completedEvent.Clinician.Name :
                                                                       completedEvent.Clinician.Hospital.Name))
                                              into groupedEvents
                                              select new { groupedEvents.Key, Events = groupedEvents.ToList() })
                                             .ToDictionary(e => e.Key, e => e.Events);

            var futurePeriodBreachesReport = new List <FuturePeriodBreachesInfo>();

            foreach (var groupedEvents in groupedEventsByGranularity)
            {
                for (var weekToBreach = 1; weekToBreach <= weeksToBreach; weekToBreach++)
                {
                    var filteredEvents = groupedEvents.Value.Where(e =>
                                                                   e.Period.GetDaysRemainingAt(_clock.Today) > (weekToBreach - 1) * OneWeek &&
                                                                   e.Period.GetDaysRemainingAt(_clock.Today) <= weekToBreach * OneWeek).ToList();

                    var completedEvent = filteredEvents.Any() ? filteredEvents.FirstOrDefault() : groupedEvents.Value.FirstOrDefault();
                    if (completedEvent != null)
                    {
                        futurePeriodBreachesReport.Add(new FuturePeriodBreachesInfo
                        {
                            Clinician        = granularity == Granularity.Clinician ? completedEvent.Clinician.Name : string.Empty,
                            Hospital         = completedEvent.Clinician.Hospital.Name,
                            Specialty        = granularity == Granularity.Clinician || granularity == Granularity.Specialty ? completedEvent.Clinician.Specialty.Name : string.Empty,
                            WeeksToBreach    = weekToBreach,
                            NumberOfBreaches = filteredEvents.Any() ? filteredEvents.Count() : 0
                        });
                    }
                }
            }

            return(futurePeriodBreachesReport);
        }