public override MaintenanceObject GetEntity(IRepository repository) { MaintenanceObject replaceObject = null; if (ReplaceObjectId != null) { replaceObject = repository.Get <MaintenanceObject>(ReplaceObjectId.Value); } var newObject = new MaintenanceObject( repository.Get <ObjectGroup>(GroupId), TechIndex, StartOperating, Period == null? new Period(DateTime.Now):new Period(Period.Value), LastMaintenance == null? null: LastMaintenance.Select(x => x.GetEntity(repository)), replaceObject ); newObject.Plant = repository.Get <Plant>(PlantId.Value); newObject.Site = Site; if (ParentId != null) { var parent = repository.Get <MaintenanceObject>(ParentId.Value); parent.AddChild(newObject); repository.Save(parent); } return(newObject); }
/// <summary> /// Завершить неоконченное обслуживание /// </summary> /// <param name="end"></param> public void FinalizeMaintenance(DateTime end) { if (CurrentOperatingState == OperatingState.Maintenance) { //Сохраняем дату завершения обслуживания CurrentMaintenance.EndMaintenance = end; //Взять интересующий интервал по типу обслуживания var targetInterval = Intervals.SingleOrDefault(x => x.MaintenanceType == CurrentMaintenance.MaintenanceType); /* Выбрать интервалы для сброса. Сюда попадает интересующий нас интервал и более мелкие. * Т.е. Если проводится Средний ремонт, то сбрасываются Средний, Текущий и Обслуживание. */ //todo В данном случае выбираетя более мелкий интервал по минимальной наработке. var intervalsForReset = Intervals.Where( x => x.MinUsage <= targetInterval.MinUsage) .ToDictionary(i => i.MaintenanceType); //Если последнего обслуживания нет, то добавляем его if (lastMaintenance.All(x => x.MaintenanceType != CurrentMaintenance.MaintenanceType)) { var newLastMaintenance = new LastMaintenance( CurrentMaintenance.MaintenanceType, end, UsageFromStartup ); newLastMaintenance.Object = this; lastMaintenance.Add(newLastMaintenance); } //Сбрасываем данные по последнему обслуживанию lastMaintenance.ToList().ForEach(last => { if (intervalsForReset.ContainsKey(last.MaintenanceType)) { last.Reset(end); } }); //todo здесь нужно взять последнее состояние до ремонта и восстановить его ChangeOperatingState(OperatingState.Operating, end); CurrentMaintenance = null; } }
/// <summary> /// Удалить обслуживание /// </summary> /// <param name="entity"></param> public void RemoveMaintenance(MaintenanceActual entity) { var lastMaintenanceMap = LastMaintenance.ToDictionary(x => x.MaintenanceType.Id); //восстанавливаем данные из снимка entity.Snapshot.ToList().ForEach(x => { var last = lastMaintenanceMap[x.MaintenanceType.Id]; last.UsageFromLastMaintenance = x.UsageFromLastMaintenance; last.LastMaintenanceDate = x.LastMaintenanceDate; }); //если это текущее обслуживание, то сбрасываем его if (!entity.IsFinalized() && CurrentMaintenance == entity) { CurrentMaintenance = null; } maintenance.Remove(entity); }
/// <summary> /// Установка следующего обслуживания(данные для индикатора следующего ремонта) /// </summary> public void SetNextMaintenance() { //чтобы рассчитать следующее обслуживание нужно сравнить по всем обслуживаниям разницу наработки норма-факт и взять меньшую разницу var intervals = Intervals.ToList(); intervals.Sort(); var intervalsMap = intervals.ToDictionary(x => x.MaintenanceType.Id); var lastUsageMap = LastMaintenance.ToDictionary(x => x.MaintenanceType.Id, x => x.UsageFromLastMaintenance); MaintenanceType next = null; int? fact = 0; int? norm = 0; int? normMax = 0; intervals.ForEach(interval => { var usage = lastUsageMap[interval.MaintenanceType.Id]; if ( next == null || //сравниваем значения как по величине так и по модулю, на случай если ремонт пропущен и разница минусовая (interval.MinUsage - usage < norm - fact && Math.Abs(interval.MinUsage.Value - usage.Value) < Math.Abs(norm.Value - fact.Value)) ) { next = interval.MaintenanceType; norm = interval.MinUsage; normMax = interval.MaxUsage; fact = usage; } }); NextMaintenance = next; NextUsageFact = fact; NextUsageNorm = norm; NextUsageNormMax = normMax; }
/// <summary> /// Спланировать работы по обслуживанию /// </summary> /// <param name="period">Период планирования</param> /// <param name="offer">Предложение обслуживания</param> /// <param name="offerReason">Причина предложения</param> public void PlanningMaintenance(Period period, MaintenanceType offer = null, MaintenanceReason offerReason = null) { //если оборудование не эксплуатируется, то ничего не планируем if (CurrentOperatingState != OperatingState.Operating) { return; } //проверяем предыдущий период если план невыполнен то переносим в след период var prevPlan = plans.FirstOrDefault(x => x.MaintenanceDate >= period.Prev().Start() && x.MaintenanceDate <= period.Prev().End()); if (prevPlan != null && !maintenance.Any(x => x.StartMaintenance >= period.Prev().Start() && x.StartMaintenance <= period.Prev().End())) { plans.Add(new MaintenancePlan( this, prevPlan.MaintenanceType, period.Start(), true, false, prevPlan.OfferReason )); return; } ///сортируем интервалы по величине ремонта (самый крупный будет первым) var intervals = Intervals.ToList(); intervals.Sort(); var intervalsMap = intervals.ToDictionary(x => x.MaintenanceType.Id); var lastDateMap = LastMaintenance.ToDictionary(x => x.MaintenanceType.Id, x => x.LastMaintenanceDate); var lastUsageMap = LastMaintenance.ToDictionary(x => x.MaintenanceType.Id, x => x.UsageFromLastMaintenance); var hours = period.Hours(); intervals.Any(interval => { var type = interval.MaintenanceType.Id; if (!lastUsageMap.ContainsKey(type)) { var newLast = new LastMaintenance(interval.MaintenanceType, null, null) { Object = this }; lastMaintenance.Add(newLast); lastUsageMap.Add(type, 0); lastDateMap.Add(type, null); } //проверка по наработке if (interval.MinUsage != null) { var fork = interval.MaxUsage - interval.MinUsage; var targetUsage = fork >= 5000 ? interval.MinUsage.Value + fork / 2 : interval.MinUsage.Value; if (lastUsageMap[type].Value >= targetUsage) { //дата проведения обслуживания var date = period.Start().AddDays((interval.MinUsage.Value - lastUsageMap[type].Value) / 24); //если дата ремонта выходит за пределы периода, то устонавливаем её в пределы периода if (date > period.End()) { date = period.End(); } if (date < period.Start()) { date = period.Start(); } plans.Add(new MaintenancePlan(this, interval.MaintenanceType, date)); return(true); } } //проверка по времени if (interval.PeriodQuantity != null) { //todo сделать проверку интервалов по времени } //проверка по предложению if (offer != null && offer.Id == type) { plans.Add(new MaintenancePlan(this, interval.MaintenanceType, period.Start(), false, true, offerReason)); return(true); } return(false); }); }
/// <summary> /// Откатить отчёт /// </summary> public void DiscardReport() { //Если оборудование демонтировано, то отчёт не откатываем if (CurrentOperatingState == OperatingState.UnMounted) { return; } var CurrentPeriod = Report.Period; var PrevPeriod = CurrentPeriod.Prev(); Report.Period = PrevPeriod; //восстанавливаем план var plan = plans.FirstOrDefault(x => x.MaintenanceDate >= CurrentPeriod.Start() && x.MaintenanceDate <= CurrentPeriod.End()); if (plan != null) { //если было предложение то восстанавливаем его if (plan.IsOffer) { Report.OfferForPlan = plan.MaintenanceType; Report.ReasonForOffer = plan.OfferReason; } plans.Remove(plan); } //Востанавливаем наработку var prevUsageAfter = usage.Where(x => x.EndUsage == PrevPeriod.End() && x.StartUsage > PrevPeriod.Start()).FirstOrDefault(); if (prevUsageAfter != null) //наработка после ремонта { RemoveUsage(prevUsageAfter); } Report.UsageAfterMaintenance = prevUsageAfter?.Usage ?? 0; var prevMaintenance = maintenance.Where(x => x.StartMaintenance >= PrevPeriod.Start()).FirstOrDefault(); if (prevMaintenance != null) { Report.ActualMaintenanceType = prevMaintenance.MaintenanceType; Report.StartMaintenance = prevMaintenance.StartMaintenance; Report.EndMaintenance = prevMaintenance.EndMaintenance; RemoveMaintenance(prevMaintenance); } var notFinalized = maintenance.Where(x => x.EndMaintenance >= PrevPeriod.Start() && x.StartMaintenance < PrevPeriod.Start()).FirstOrDefault(); if (notFinalized != null) { var lastMaintenanceMap = LastMaintenance.ToDictionary(x => x.MaintenanceType.Id); notFinalized.Snapshot.ToList().ForEach(x => { var last = lastMaintenanceMap[x.MaintenanceType.Id]; last.UsageFromLastMaintenance = x.UsageFromLastMaintenance; last.LastMaintenanceDate = x.LastMaintenanceDate; }); Report.ActualMaintenanceType = notFinalized.MaintenanceType; Report.EndMaintenance = notFinalized.EndMaintenance; Report.StartMaintenance = notFinalized.StartMaintenance; notFinalized.EndMaintenance = null; CurrentMaintenance = notFinalized; } var prevUsageBefore = usage.Where(x => x.StartUsage == PrevPeriod.Start()).FirstOrDefault(); if (prevUsageBefore != null)//наработка до ремонта { RemoveUsage(prevUsageBefore); } Report.UsageBeforeMaintenance = prevUsageBefore?.Usage ?? 0; if (Parent != null) { var parentUsage = Parent.usage.Where(x => x.StartUsage >= PrevPeriod.Start() && x.EndUsage <= PrevPeriod.End()).Sum(x => x.Usage); Report.UsageParent = parentUsage; } else { Report.UsageParent = 0; } if (Children.Any()) { Children.ToList().ForEach(x => { if (x.Report.Period.period == CurrentPeriod.period) { x.Report.UsageParent = 0; } }); } //восстанавливаем состояние var lastState = operatingStates.FirstOrDefault(x => x.StartDate >= PrevPeriod.Start()); operatingStates.Where(x => x.StartDate >= PrevPeriod.Start()).ToList().ForEach(x => operatingStates.Remove(x)); if (CurrentMaintenance != null) { CurrentOperatingState = OperatingState.Maintenance; } else if (lastState != null && lastState.State == OperatingState.Reserve) { CurrentOperatingState = OperatingState.Reserve; } else { CurrentOperatingState = operatingStates.OrderBy(x => x.StartDate).LastOrDefault()?.State ?? OperatingState.Operating; } Report.State = CurrentOperatingState.Value; SetNextMaintenance(); }
/// <summary> /// Применить отчёт (добавить информацию о ремонтах и наработке в соответствующие журналы) и сформировать план на след. период /// </summary> public void ApplyReport() { //Если оборудование демонтировано, то отчёт не проводим if (CurrentOperatingState == OperatingState.UnMounted) { return; } if (CurrentOperatingState == null) { ChangeOperatingState(OperatingState.Operating, Report.Period.Start()); } if (!LastMaintenance.Any()) { Intervals.ToList().ForEach(x => { lastMaintenance.Add(new LastMaintenance( x.MaintenanceType, null, x.MinUsage != null ? (int?)0 : null ) { Object = this }); }); } var CurrentPeriod = Report.Period; var NextPeriod = CurrentPeriod.Next(); // 1 Добавить наработку до ремонта, а если его не было, то за весь период if (Report.UsageBeforeMaintenance != 0) { AddUsage(CurrentPeriod.Start(), Report.StartMaintenance ?? CurrentPeriod.End(), Report.UsageBeforeMaintenance); } //2 Добавить информацию о ремонте, если он был. // Если был неоконченный ремонт, то завершить его if (CurrentMaintenance != null) { //Бывает что начинают один вид ремонта, а по факту выполняется другой CurrentMaintenance.MaintenanceType = Report.ActualMaintenanceType; if (Report.EndMaintenance != null) { FinalizeMaintenance(Report.EndMaintenance.Value); } } // Если новый ремонт, то добавляем его в журнал ремонтов else if (Report.ActualMaintenanceType != null && Report.StartMaintenance != null) { AddMaintenance(Report.ActualMaintenanceType, Report.StartMaintenance.Value, Report.EndMaintenance, Report.UnplannedReason); } //3 если ремонт окончен и наработка после ремонта есть то добавляем её в журнал наработки if (Report.EndMaintenance != null && Report.UsageAfterMaintenance != 0) { AddUsage(Report.EndMaintenance.Value, CurrentPeriod.End(), Report.UsageAfterMaintenance); } /*Устанавливаем наработку для детей*/ if (Children.Any()) { Children.ToList().ForEach(child => { if (child.Report.Period.period == CurrentPeriod.period) { var allUsage = Report.UsageBeforeMaintenance + Report.UsageAfterMaintenance; child.Report.UsageParent = allUsage; child.Report.UsageBeforeMaintenance = allUsage; } }); } //Если состояние поменялось и это было не обслуживание, то меняем состояние if (Report.State != OperatingState.Maintenance && CurrentOperatingState != OperatingState.Maintenance && CurrentOperatingState != Report.State) { ChangeOperatingState(Report.State, CurrentPeriod.Start()); } //Планируем следующий период PlanningMaintenance(NextPeriod, Report.OfferForPlan, Report.ReasonForOffer); //Рассчитываем следующее обслуживание SetNextMaintenance(); /* Очищение информации в отчёте для следующего месяца */ // Если ремонт окончен, то обнуляем информацию по фактическому ремонту if (Report.EndMaintenance != null) { Report.ActualMaintenanceType = null; Report.UnplannedReason = null; Report.StartMaintenance = null; Report.EndMaintenance = null; } Report.OfferForPlan = null; Report.ReasonForOffer = null; //Устанавливаем состояние на следующий период. Если Текущее состояние резерв, то сбрасываем его на обслуживание, потому что механики вручную вносят резерв Report.State = CurrentOperatingState.Value == OperatingState.Reserve ? OperatingState.Operating : CurrentOperatingState.Value; if (Report.State == OperatingState.Operating) { Report.UsageBeforeMaintenance = NextPeriod.Hours(); } else { Report.UsageBeforeMaintenance = 0; } //Если есть родитель и у него проведена наработка, то устонавливаем её if (Parent != null && Parent.Report.Period.period > NextPeriod.period) { var parentUsage = Parent.usage.Where(x => x.StartUsage >= NextPeriod.Start() && x.EndUsage <= NextPeriod.End()).Sum(x => x.Usage); Report.UsageParent = parentUsage; Report.UsageBeforeMaintenance = parentUsage; } else { Report.UsageParent = 0; } Report.UsageAfterMaintenance = 0; //Переходим на следующий период Report.Period = NextPeriod; }
public override void Merge(MaintenanceObject entity, IRepository repository) { entity.TechIndex = TechIndex; entity.Plant = repository.Get <Plant>(PlantId.Value); entity.Site = Site; entity.Group = repository.Get <ObjectGroup>(GroupId); SetSpecifications(entity, repository); //Если введена дата ввода в эксплуатацию, то вводим в эксплуатацию if (entity.CurrentOperatingState == OperatingState.Mounted && StartOperating != null) { var period = Period == null ? new Period(DateTime.Now) : new Period(Period.Value); entity.PutIntoOperating(StartOperating.Value, period); } //Если родитель был if (entity.Parent != null) { //Если родитель получен if (ParentId != null) { //Если полученный родитель не равен тому, который был if (ParentId != entity.Parent.Id) { var newParent = repository.Get <MaintenanceObject>(ParentId.Value); entity.ClearParent(); newParent.AddChild(entity); repository.Save(newParent); } } //Если родитель был, но его убрали else { entity.ClearParent(); } } //Если родителя небыло else { //Если родитель был установлен if (ParentId != null) { var parent = repository.Get <MaintenanceObject>(ParentId.Value); parent.AddChild(entity); repository.Save(parent); } } var dtoMap = LastMaintenance.ToDictionary(x => x.MaintenanceTypeId); entity.LastMaintenance.ToList().ForEach(last => { if (dtoMap.ContainsKey(last.MaintenanceType.Id)) { var _dto = dtoMap[last.MaintenanceType.Id]; last.LastMaintenanceDate = _dto.LastMaintenanceDate; last.UsageFromLastMaintenance = _dto.UsageFromLastMaintenance; } }); entity.SetNextMaintenance(); }