public OrderManagementService(IPreactor preactor)
 {
     _preactor  = preactor;
     shtRepo    = new ShortagesRepo(_preactor);
     ignShtRepo = new IgnoreShortagesRepo(_preactor);
     ordRepo    = new OrderRepo(_preactor);
     prdRepo    = new ProductRepo(_preactor);
     resSqlRepo = new ResourceRepoSql(_preactor);
     resList    = resSqlRepo.getAll();
 }
        public IEnumerable <IGrouping <dynamic, OrderDTO> > SetOperationsStartTimeByLast2(IEnumerable <IGrouping <dynamic, OrderDTO> > list)
        {
            //обход по подгруппам (resource-rank)
            DateTime               tTime            = _preactor.PlanningBoard.TerminatorTime;
            DateTime               prevMaxEndDate   = default(DateTime);
            ResourceRepoSql        resSqlRepo       = new ResourceRepoSql(_preactor);
            int                    resId            = -1;
            IEnumerable <OrderDTO> opListTemp       = new List <OrderDTO>();
            IEnumerable <OrderDTO> opListTempBuffer = new List <OrderDTO>();
            PlannerService         _plannerService  = new PlannerService(_preactor);

            foreach (var gr in list)
            {
                //Если меняется ранк, то идет вычисление предыдущей макс даты
                //Если меняется ресурс, макс дата сбрасывается.
                DateTime st1 = default(DateTime);
                DateTime et1 = default(DateTime);

                OrderDTO lastOp = getLastOperationOnResource(gr.ToList());
                if (lastOp != null)
                {
                    st1 = lastOp.SetupStart;
                    et1 = lastOp.EndTime;
                }

                if (gr.Select(x => x.ResourceId).First() != resId)
                {
                    _plannerService.UnallocateOpOnResources(gr.Select(x => x.ResourceId).First(), true);
                    if (lastOp != null)
                    {
                        prevMaxEndDate = st1;
                    }
                    else
                    {
                        prevMaxEndDate = tTime;
                    }
                    opListTempBuffer = new List <OrderDTO>();//обнуляем буфер уже запланированых операций на ресурсе
                }
                else
                {
                    if (opListTempBuffer.Count() > 0)
                    {
                        List <OrderDTO> testIntervalList = opListTempBuffer.Where(x => {
                            return(IsDayIntervalIntersected(st1, et1, x.SetupStart, x.EndTime));
                        }).ToList();
                        if (testIntervalList.Count() == 0)
                        {
                            prevMaxEndDate = st1;
                        }
                        else
                        {
                            prevMaxEndDate = opListTempBuffer.Max(x => x.EndTime);
                        }
                    }
                }


                opListTemp = gr.ToList();



                resId = gr.Select(x => x.ResourceId).First();
                int resNumber = _preactor.GetRecordNumber("Resources", new PrimaryKey(resId));

                while (opListTemp.Count() > 0)
                {
                    lastOp = getLastOperationOnResource(opListTemp);
                    if (lastOp == null)
                    {
                        //оставшееся подмножество операций больше не удовлетворяет условиям
                        break;
                    }

                    DateTime setupStart = lastOp.SetupStart;
                    DateTime startTime  = lastOp.StartTime;
                    DateTime endTime    = lastOp.EndTime;

                    int opNumber = _preactor.GetRecordNumber("Orders", new PrimaryKey(lastOp.Id));

                    prevMaxEndDate = tTime;

                    //Проверяем на пересечение текущего штабеля операций  с уже запланироваными
                    if (opListTempBuffer.Count() > 0)
                    {
                        List <OrderDTO> testIntervalList = opListTempBuffer.Where(x => {
                            return(IsDayIntervalIntersected(lastOp.SetupStart, lastOp.EndTime, x.SetupStart, x.EndTime));
                        }).ToList();
                        if (testIntervalList.Count() == 0)
                        {
                            prevMaxEndDate = lastOp.SetupStart;
                        }
                        else
                        {
                            //если текущий штабель пересекает запланированые, выясняем время тестированием от терминатора
                            prevMaxEndDate = tTime;
                            OperationTimes?times1 = _preactor.PlanningBoard.TestOperationOnResource(opNumber, resNumber, prevMaxEndDate);
                            if (times1 != null)
                            {
                                testIntervalList = opListTempBuffer.Where(x => {
                                    return(IsDayIntervalIntersected(times1.Value.ChangeStart, times1.Value.ProcessEnd, x.SetupStart, x.EndTime));
                                }).ToList();
                            }


                            if (testIntervalList.Count() == 0)
                            {
                                prevMaxEndDate = times1.Value.ChangeStart;
                            }
                            else
                            {
                                prevMaxEndDate = opListTempBuffer.Max(x => x.EndTime);//как последний вариант ставим в конец всех операций
                            }
                        }
                    }
                    //-------------------------------------

                    OperationTimes?times = _preactor.PlanningBoard.TestOperationOnResource(opNumber, resNumber, prevMaxEndDate);
                    //При подсчете разницы, учитываем на тестовое время,что есть периоды недоступности ресурсов
                    if (times.HasValue)
                    {
                        DateTime testTimeStart = times.Value.ProcessStart;
                        DateTime testTimeSetup = times.Value.ChangeStart;
                        DateTime testTimeEnd   = times.Value.ProcessEnd;
                        startTime  = testTimeStart;
                        setupStart = testTimeSetup;
                        endTime    = testTimeEnd;
                    }
                    else
                    {
                        times = _preactor.PlanningBoard.QueryOperationOnResource(opNumber, resNumber, prevMaxEndDate);

                        DateTime testTimeStart = times.Value.ProcessStart;
                        DateTime testTimeSetup = times.Value.ChangeStart;
                        DateTime testTimeEnd   = times.Value.ProcessEnd;
                        startTime  = testTimeStart;
                        setupStart = testTimeSetup;
                        endTime    = testTimeEnd;
                    }


                    var subListOp = opListTemp.Where(x => x.StartTime <= lastOp.StartTime).ToList();
                    opListTemp = opListTemp.Except(subListOp).ToList();


                    foreach (var el in subListOp)
                    {
                        if (el.SetupStart < tTime)
                        {
                            continue;
                        }

                        el.SetupStart = setupStart;
                        el.StartTime  = startTime;
                        TimeSpan tsStart = endTime - el.StartTime;
                        TimeSpan tsSetup = endTime - el.SetupStart;
                        el.EndTime   = el.StartTime.Add(tsStart);
                        el.Scheduled = true;
                    }
                    prevMaxEndDate   = subListOp.Max(x => x.EndTime);
                    opListTempBuffer = opListTempBuffer.Concat(subListOp);//постепенно заполняем буфер запланированых операций
                }//while
            }//foreach


            return(list);
        }