public IList <GoodsInRouteListResultToDivide> AllGoodsLoadedDivided(IUnitOfWork uow, RouteList routeList, CarLoadDocument excludeDoc = null) { CarLoadDocument docAlias = null; CarLoadDocumentItem docItemsAlias = null; GoodsInRouteListResultToDivide inCarLoads = null; var loadedQuery = uow.Session.QueryOver <CarLoadDocument>(() => docAlias) .Where(d => d.RouteList.Id == routeList.Id); if (excludeDoc != null) { loadedQuery.Where(d => d.Id != excludeDoc.Id); } var loadedlist = loadedQuery .JoinAlias(d => d.Items, () => docItemsAlias) .SelectList(list => list .SelectGroup(() => docItemsAlias.Nomenclature.Id).WithAlias(() => inCarLoads.NomenclatureId) .SelectSum(() => docItemsAlias.Amount).WithAlias(() => inCarLoads.Amount) .SelectGroup(() => docItemsAlias.ExpireDatePercent).WithAlias(() => inCarLoads.ExpireDatePercent) .SelectGroup(() => docItemsAlias.OwnType).WithAlias(() => inCarLoads.OwnType) ).TransformUsing(Transformers.AliasToBean <GoodsInRouteListResultToDivide>()) .List <GoodsInRouteListResultToDivide>(); return(loadedlist); }
public decimal LoadedTerminalAmount(IUnitOfWork uow, int routelistId, int terminalId) { CarLoadDocument carLoadDocumentAlias = null; CarLoadDocumentItem carLoadDocumentItemAlias = null; var query = uow.Session.QueryOver(() => carLoadDocumentAlias) .JoinAlias(c => c.Items, () => carLoadDocumentItemAlias) .Where(() => carLoadDocumentAlias.RouteList.Id == routelistId) .And(() => carLoadDocumentItemAlias.Nomenclature.Id == terminalId) .Select(Projections.Sum(() => carLoadDocumentItemAlias.Amount)) .SingleOrDefault <decimal>(); return(query); }
public GoodsInRouteListResultWithSpecialRequirements GetTerminalInRLWithSpecialRequirements(IUnitOfWork uow, RouteList routeList, Warehouse warehouse = null) { CarLoadDocumentItem carLoadDocumentItemAlias = null; if (GetLastTerminalDocumentForEmployee(uow, routeList.Driver) is DriverAttachedTerminalGiveoutDocument giveoutDoc) { //если водителю был привязан терминал, то ему не надо его грузить return(null); } var transferedCount = TerminalTransferedCountToRouteList(uow, routeList); var terminalId = _terminalNomenclatureProvider.GetNomenclatureIdForTerminal; var needTerminal = routeList.Addresses.Any(x => x.Order.PaymentType == PaymentType.Terminal) && transferedCount == 0; var loadedTerminal = uow.Session.QueryOver <CarLoadDocument>() .JoinAlias(x => x.Items, () => carLoadDocumentItemAlias) .Where(() => carLoadDocumentItemAlias.Nomenclature.Id == terminalId) .And(x => x.RouteList.Id == routeList.Id) .List(); if (needTerminal || loadedTerminal.Any()) { var terminal = uow.GetById <Nomenclature>(terminalId); int amount = 1; if (warehouse == null) { return(new GoodsInRouteListResultWithSpecialRequirements { NomenclatureName = terminal.Name, NomenclatureId = terminalId, Amount = amount }); } if (_stockRepository.NomenclatureInStock(uow, warehouse.Id, new int[] { terminal.Id }).Any()) { return(new GoodsInRouteListResultWithSpecialRequirements { NomenclatureName = terminal.Name, NomenclatureId = terminalId, Amount = amount }); } } return(null); }
string CalculateAmountAndColor(CarLoadDocumentItem item) { if (item.Nomenclature.OfficialName == "Терминал для оплаты" && item.Amount > 1) { item.Amount = decimal.One; } if (item.Amount > item.AmountInStock) { return("red"); } if (item.Equipment == null) { if (item.AmountInRouteList < item.AmountLoaded + item.Amount) { return("orange"); } if (item.AmountInRouteList == item.AmountLoaded + item.Amount) { return("green"); } if (item.AmountInRouteList > item.AmountLoaded + item.Amount) { return("blue"); } } else { if (1 < item.AmountLoaded + item.Amount) { return("orange"); } if (1 == item.AmountLoaded + item.Amount) { return("green"); } if (1 > item.AmountLoaded + item.Amount) { return("blue"); } } return("black"); }
public bool IsTerminalRequired(IUnitOfWork uow, int routeListId) { CarLoadDocumentItem carLoadDocumentItemAlias = null; var terminalId = new BaseParametersProvider().GetNomenclatureIdForTerminal; var routeList = uow.Query <RouteList>().Where(x => x.Id == routeListId).SingleOrDefault(); var anyAddressesRequireTermanal = routeList.Addresses.Any(x => x.Order.PaymentType == PaymentType.Terminal); var loadedTerminal = uow.Session.QueryOver <CarLoadDocument>() .JoinAlias(x => x.Items, () => carLoadDocumentItemAlias) .Where(() => carLoadDocumentItemAlias.Nomenclature.Id == terminalId) .And(() => carLoadDocumentItemAlias.Amount > 0) .And(x => x.RouteList.Id == routeList.Id) .List(); return(anyAddressesRequireTermanal && !loadedTerminal.Any()); }
public bool IsTerminalRequired(IUnitOfWork uow, int routeListId) { CarLoadDocumentItem carLoadDocumentItemAlias = null; var terminalId = _terminalNomenclatureProvider.GetNomenclatureIdForTerminal; var routeList = uow.Query <RouteList>().Where(x => x.Id == routeListId).SingleOrDefault(); var anyAddressesRequireTerminal = routeList.Addresses.Any(x => x.Order.PaymentType == PaymentType.Terminal); var giveoutDoc = GetLastTerminalDocumentForEmployee(uow, routeList.Driver) as DriverAttachedTerminalGiveoutDocument; var loadedTerminal = uow.Session.QueryOver <CarLoadDocument>() .JoinAlias(x => x.Items, () => carLoadDocumentItemAlias) .Where(() => carLoadDocumentItemAlias.Nomenclature.Id == terminalId) .And(() => carLoadDocumentItemAlias.Amount > 0) .And(x => x.RouteList.Id == routeList.Id) .List(); return(anyAddressesRequireTerminal && !loadedTerminal.Any() && giveoutDoc == null); }
public GoodsInRouteListResultWithSpecialRequirements GetTerminalInRLWithSpecialRequirements(IUnitOfWork uow, RouteList routeList, Warehouse warehouse = null) { CarLoadDocumentItem carLoadDocumentItemAlias = null; var terminalId = new BaseParametersProvider().GetNomenclatureIdForTerminal; var needTerminal = routeList.Addresses.Any(x => x.Order.PaymentType == PaymentType.Terminal); var loadedTerminal = uow.Session.QueryOver <CarLoadDocument>() .JoinAlias(x => x.Items, () => carLoadDocumentItemAlias) .Where(() => carLoadDocumentItemAlias.Nomenclature.Id == terminalId) .And(x => x.RouteList.Id == routeList.Id) .List(); if (needTerminal || loadedTerminal.Any()) { var terminal = uow.GetById <Nomenclature>(terminalId); int amount = 1; if (warehouse == null) { return(new GoodsInRouteListResultWithSpecialRequirements { NomenclatureName = terminal.Name, NomenclatureId = terminalId, Amount = amount }); } if (StockRepository.NomenclatureInStock(uow, warehouse.Id, new int[] { terminal.Id }).Any()) { return(new GoodsInRouteListResultWithSpecialRequirements { NomenclatureName = terminal.Name, NomenclatureId = terminalId, Amount = amount }); } } return(null); }
public GoodsInRouteListResult GetTerminalInRL(IUnitOfWork uow, RouteList routeList, Warehouse warehouse = null) { CarLoadDocumentItem carLoadDocumentItemAlias = null; var terminalId = _terminalNomenclatureProvider.GetNomenclatureIdForTerminal; var needTerminal = routeList.Addresses.Any(x => x.Order.PaymentType == PaymentType.Terminal); var loadedTerminal = uow.Session.QueryOver <CarLoadDocument>() .JoinAlias(x => x.Items, () => carLoadDocumentItemAlias) .Where(() => carLoadDocumentItemAlias.Nomenclature.Id == terminalId) .And(x => x.RouteList.Id == routeList.Id) .List(); if (GetLastTerminalDocumentForEmployee(uow, routeList.Driver) is DriverAttachedTerminalGiveoutDocument) { return(null); } if (needTerminal || loadedTerminal.Any()) { var terminal = uow.GetById <Nomenclature>(terminalId); int amount = 1; if (warehouse == null) { return(new GoodsInRouteListResult { NomenclatureId = terminalId, Amount = amount }); } if (_stockRepository.NomenclatureInStock(uow, warehouse.Id, new int[] { terminal.Id }).Any()) { return(new GoodsInRouteListResult { NomenclatureId = terminalId, Amount = amount }); } } return(null); }
string CalculateAmountColor(CarLoadDocumentItem item) { if (item.Amount > item.AmountInStock) { return("red"); } if (item.Equipment == null) { if (item.AmountInRouteList < item.AmountLoaded + item.Amount) { return("orange"); } if (item.AmountInRouteList == item.AmountLoaded + item.Amount) { return("green"); } if (item.AmountInRouteList > item.AmountLoaded + item.Amount) { return("blue"); } } else { if (1 < item.AmountLoaded + item.Amount) { return("orange"); } if (1 == item.AmountLoaded + item.Amount) { return("green"); } if (1 > item.AmountLoaded + item.Amount) { return("blue"); } } return("black"); }
public bool HasEnoughQuantityForFastDelivery(IUnitOfWork uow, RouteListItem routeListItemFrom, RouteList routeListTo) { RouteListItem routeListItemAlias = null; RouteListItem routeListItemTransferedAlias = null; OrderItem orderItemAlias = null; NomenclatureAmountNode nomenclatureAmountAlias = null; Order orderAlias = null; OrderEquipment orderEquipmentAlias = null; CarLoadDocument carLoadDocumentAlias = null; CarLoadDocumentItem carLoadDocumentItemAlias = null; var nomenclaturesToDeliver = routeListItemFrom.Order.GetAllGoodsToDeliver(); var neededIds = nomenclaturesToDeliver.Select(x => x.NomenclatureId).ToArray(); var orderItemsToDeliver = uow.Session.QueryOver <RouteListItem>(() => routeListItemAlias) .Inner.JoinAlias(() => routeListItemAlias.Order, () => orderAlias) .Inner.JoinAlias(() => orderAlias.OrderItems, () => orderItemAlias) .Left.JoinAlias(() => routeListItemAlias.TransferedTo, () => routeListItemTransferedAlias) .Where(() => routeListItemAlias.RouteList.Id == routeListTo.Id) .WhereRestrictionOn(() => orderItemAlias.Nomenclature.Id).IsIn(neededIds) .Where(() => //не отменённые и не недовозы routeListItemAlias.Status != RouteListItemStatus.Canceled && routeListItemAlias.Status != RouteListItemStatus.Overdue // и не перенесённые к водителю; либо перенесённые с погрузкой; либо перенесённые и это экспресс-доставка (всегда без погрузки) && (!routeListItemAlias.WasTransfered || routeListItemAlias.NeedToReload || orderAlias.IsFastDelivery) // и не перенесённые от водителя; либо перенесённые и не нужна погрузка и не экспресс-доставка (остатки по экспресс-доставке не переносятся) && (routeListItemAlias.Status != RouteListItemStatus.Transfered || (!routeListItemTransferedAlias.NeedToReload && !orderAlias.IsFastDelivery))) .SelectList(list => list .SelectGroup(() => orderItemAlias.Nomenclature.Id).WithAlias(() => nomenclatureAmountAlias.NomenclatureId) .SelectSum(() => orderItemAlias.Count).WithAlias(() => nomenclatureAmountAlias.Amount) ).TransformUsing(Transformers.AliasToBean <NomenclatureAmountNode>()) .Future <NomenclatureAmountNode>(); var orderEquipmentsToDeliver = uow.Session.QueryOver <RouteListItem>(() => routeListItemAlias) .Inner.JoinAlias(() => routeListItemAlias.Order, () => orderAlias) .Inner.JoinAlias(() => orderAlias.OrderEquipments, () => orderEquipmentAlias) .Left.JoinAlias(() => routeListItemAlias.TransferedTo, () => routeListItemTransferedAlias) .Where(() => routeListItemAlias.RouteList.Id == routeListTo.Id) .WhereRestrictionOn(() => orderEquipmentAlias.Nomenclature.Id).IsIn(neededIds) .Where(() => //не отменённые и не недовозы routeListItemAlias.Status != RouteListItemStatus.Canceled && routeListItemAlias.Status != RouteListItemStatus.Overdue // и не перенесённые к водителю; либо перенесённые с погрузкой; либо перенесённые и это экспресс-доставка (всегда без погрузки) && (!routeListItemAlias.WasTransfered || routeListItemAlias.NeedToReload || orderAlias.IsFastDelivery) // и не перенесённые от водителя; либо перенесённые и не нужна погрузка и не экспресс-доставка (остатки по экспресс-доставке не переносятся) && (routeListItemAlias.Status != RouteListItemStatus.Transfered || (!routeListItemTransferedAlias.NeedToReload && !orderAlias.IsFastDelivery))) .And(() => orderEquipmentAlias.Direction == Domain.Orders.Direction.Deliver) .SelectList(list => list .SelectGroup(() => orderEquipmentAlias.Nomenclature.Id).WithAlias(() => nomenclatureAmountAlias.NomenclatureId) .Select(Projections.Cast(NHibernateUtil.Decimal, Projections.Sum(Projections.Property(() => orderEquipmentAlias.Count)))).WithAlias(() => nomenclatureAmountAlias.Amount) ).TransformUsing(Transformers.AliasToBean <NomenclatureAmountNode>()) .Future <NomenclatureAmountNode>(); var allToDeliver = orderItemsToDeliver .Union(orderEquipmentsToDeliver) .GroupBy(x => new { x.NomenclatureId }) .Select(group => new NomenclatureAmountNode() { NomenclatureId = group.Key.NomenclatureId, Amount = group.Sum(x => x.Amount) }) .ToList(); var allLoaded = uow.Session.QueryOver <CarLoadDocument>(() => carLoadDocumentAlias) .Inner.JoinAlias(() => carLoadDocumentAlias.Items, () => carLoadDocumentItemAlias) .Where(() => carLoadDocumentAlias.RouteList.Id == routeListTo.Id) .WhereRestrictionOn(() => carLoadDocumentItemAlias.Nomenclature.Id).IsIn(neededIds) .SelectList(list => list .SelectGroup(() => carLoadDocumentItemAlias.Nomenclature.Id).WithAlias(() => nomenclatureAmountAlias.NomenclatureId) .SelectSum(() => carLoadDocumentItemAlias.Amount).WithAlias(() => nomenclatureAmountAlias.Amount) ).TransformUsing(Transformers.AliasToBean <NomenclatureAmountNode>()) .List <NomenclatureAmountNode>(); foreach (var need in nomenclaturesToDeliver) { var toDeliver = allToDeliver.FirstOrDefault(x => x.NomenclatureId == need.NomenclatureId)?.Amount ?? 0; var loaded = allLoaded.FirstOrDefault(x => x.NomenclatureId == need.NomenclatureId)?.Amount ?? 0; if (loaded - toDeliver < need.Amount) { return(false); } } return(true); }
public FastDeliveryAvailabilityHistory GetRouteListsForFastDelivery( IUnitOfWork uow, double latitude, double longitude, bool isGetClosestByRoute, IDeliveryRulesParametersProvider deliveryRulesParametersProvider, IEnumerable <NomenclatureAmountNode> nomenclatureNodes, Order fastDeliveryOrder = null) { var maxDistanceToTrackPoint = deliveryRulesParametersProvider.MaxDistanceToLatestTrackPointKm; var driverGoodWeightLiftPerHand = deliveryRulesParametersProvider.DriverGoodWeightLiftPerHandInKg; var maxFastOrdersPerSpecificTime = deliveryRulesParametersProvider.MaxFastOrdersPerSpecificTime; var maxTimeForFastDeliveryTimespan = deliveryRulesParametersProvider.MaxTimeForFastDelivery; //Переводим всё в минуты var trackPointTimeOffset = (int)deliveryRulesParametersProvider.MaxTimeOffsetForLatestTrackPoint.TotalMinutes; var maxTimeForFastDelivery = (int)maxTimeForFastDeliveryTimespan.TotalMinutes; var minTimeForNewOrder = (int)deliveryRulesParametersProvider.MinTimeForNewFastDeliveryOrder.TotalMinutes; var driverUnloadTime = (int)deliveryRulesParametersProvider.DriverUnloadTime.TotalMinutes; var specificTimeForFastOrdersCount = (int)deliveryRulesParametersProvider.SpecificTimeForMaxFastOrdersCount.TotalMinutes; var fastDeliveryAvailabilityHistory = new FastDeliveryAvailabilityHistory { IsGetClosestByRoute = isGetClosestByRoute, Order = fastDeliveryOrder, MaxDistanceToLatestTrackPointKm = maxDistanceToTrackPoint, DriverGoodWeightLiftPerHandInKg = driverGoodWeightLiftPerHand, MaxFastOrdersPerSpecificTime = maxFastOrdersPerSpecificTime, MaxTimeForFastDelivery = maxTimeForFastDeliveryTimespan, MinTimeForNewFastDeliveryOrder = deliveryRulesParametersProvider.MinTimeForNewFastDeliveryOrder, DriverUnloadTime = deliveryRulesParametersProvider.DriverUnloadTime, SpecificTimeForMaxFastOrdersCount = deliveryRulesParametersProvider.SpecificTimeForMaxFastOrdersCount, }; var order = fastDeliveryAvailabilityHistory.Order; if (order != null) { fastDeliveryAvailabilityHistory.Order = order.Id == 0 ? null : order; fastDeliveryAvailabilityHistory.Author = order.Author; fastDeliveryAvailabilityHistory.DeliveryPoint = order.DeliveryPoint; fastDeliveryAvailabilityHistory.District = order.DeliveryPoint.District; fastDeliveryAvailabilityHistory.Counterparty = order.Client; } var fastDeliveryHistoryConverter = new FastDeliveryHistoryConverter(); if (nomenclatureNodes != null) { fastDeliveryAvailabilityHistory.OrderItemsHistory = fastDeliveryHistoryConverter.ConvertNomenclatureAmountNodesToOrderItemsHistory(nomenclatureNodes, fastDeliveryAvailabilityHistory); } var distributions = uow.GetAll <AdditionalLoadingNomenclatureDistribution>(); fastDeliveryAvailabilityHistory.NomenclatureDistributionHistoryItems = fastDeliveryHistoryConverter.ConvertNomenclatureDistributionToDistributionHistory(distributions, fastDeliveryAvailabilityHistory); var district = GetDistrict(uow, (decimal)latitude, (decimal)longitude); if (district?.TariffZone == null || !district.TariffZone.IsFastDeliveryAvailableAtCurrentTime) { fastDeliveryAvailabilityHistory.AdditionalInformation = new List <string> { "Не найден район, у района отсутствует тарифная зона, либо недоступна экспресс-доставка в текущее время." }; return(fastDeliveryAvailabilityHistory); } var neededNomenclatures = nomenclatureNodes.ToDictionary(x => x.NomenclatureId, x => x.Amount); Track t = null; TrackPoint tp = null; RouteList rl = null; TrackPoint tpInner = null; FastDeliveryVerificationDetailsNode result = null; Employee e = null; RouteListItem rla = null; RouteListItem rlaTransfered = null; Order o = null; OrderItem oi = null; OrderEquipment oe = null; CarLoadDocument scld = null; CarLoadDocumentItem scldi = null; CountUnclosedFastDeliveryAddressesNode countUnclosedFastDeliveryAddressesAlias = null; RouteListNomenclatureAmount ordersAmountAlias = null; RouteListNomenclatureAmount loadDocumentsAmountAlias = null; var lastTimeTrackQuery = QueryOver.Of(() => tpInner) .Where(() => tpInner.Track.Id == t.Id) .Select(Projections.Max(() => tpInner.TimeStamp)); //МЛ только в пути и с погруженным запасом var routeListNodes = uow.Session.QueryOver(() => rl) .JoinEntityAlias(() => t, () => t.RouteList.Id == rl.Id) .Inner.JoinAlias(() => t.TrackPoints, () => tp) .Inner.JoinAlias(() => rl.Driver, () => e) .WithSubquery.WhereProperty(() => tp.TimeStamp).Eq(lastTimeTrackQuery) .And(() => rl.Status == RouteListStatus.EnRoute) .And(() => rl.AdditionalLoadingDocument.Id != null) // только с погруженным запасом .SelectList(list => list .Select(() => tp.TimeStamp).WithAlias(() => result.TimeStamp) .Select(() => tp.Latitude).WithAlias(() => result.Latitude) .Select(() => tp.Longitude).WithAlias(() => result.Longitude) .Select(Projections.Entity(() => rl)).WithAlias(() => result.RouteList)) .TransformUsing(Transformers.AliasToBean <FastDeliveryVerificationDetailsNode>()) .List <FastDeliveryVerificationDetailsNode>(); //Последняя координата в указанном радиусе foreach (var node in routeListNodes) { var distance = DistanceHelper.GetDistanceKm(node.Latitude, node.Longitude, latitude, longitude); var deliveryPoint = new PointOnEarth(latitude, longitude); var proposedRoute = OsrmClientFactory.Instance .GetRoute(new List <PointOnEarth> { new PointOnEarth(node.Latitude, node.Longitude), deliveryPoint }, false, GeometryOverview.False, _globalSettings.ExcludeToll)?.Routes? .FirstOrDefault(); node.DistanceByLineToClient.ParameterValue = (decimal)distance; node.DistanceByRoadToClient.ParameterValue = decimal.Round((decimal)(proposedRoute?.TotalDistance ?? int.MaxValue) / 1000, 2); if (distance < maxDistanceToTrackPoint) { node.DistanceByLineToClient.IsValidParameter = node.DistanceByRoadToClient.IsValidParameter = true; } else { node.DistanceByLineToClient.IsValidParameter = node.DistanceByRoadToClient.IsValidParameter = false; node.IsValidRLToFastDelivery = false; } //Выставляем время последней координаты var timeSpan = DateTime.Now - node.TimeStamp; node.LastCoordinateTime.ParameterValue = timeSpan.TotalHours > 838 ? new TimeSpan(838, 0, 0) : timeSpan; if (node.LastCoordinateTime.ParameterValue.TotalMinutes <= trackPointTimeOffset) { node.LastCoordinateTime.IsValidParameter = true; } else { node.LastCoordinateTime.IsValidParameter = false; node.IsValidRLToFastDelivery = false; } } routeListNodes = routeListNodes .OrderBy(x => isGetClosestByRoute ? x.DistanceByRoadToClient.ParameterValue : x.DistanceByLineToClient.ParameterValue) .ToList(); //Не более определённого кол-ва заказов с быстрой доставкой в определённый промежуток времени var addressCountSubquery = QueryOver.Of(() => rla) .Inner.JoinAlias(() => rla.Order, () => o) .Where(() => rla.RouteList.Id == rl.Id) .And(() => rla.Status == RouteListItemStatus.EnRoute) .And(() => o.IsFastDelivery) .And(Restrictions.GtProperty( Projections.Property(() => rla.CreationDate), Projections.SqlFunction( new SQLFunctionTemplate(NHibernateUtil.DateTime, $"TIMESTAMPADD(MINUTE, -{specificTimeForFastOrdersCount}, CURRENT_TIMESTAMP)"), NHibernateUtil.DateTime))) .Select(Projections.Count(() => rla.Id)); var routeListsWithCountUnclosedFastDeliveries = uow.Session.QueryOver(() => rl) .WhereRestrictionOn(() => rl.Id).IsInG(routeListNodes.Select(x => x.RouteList.Id)) .SelectList(list => list .Select(() => rl.Id).WithAlias(() => countUnclosedFastDeliveryAddressesAlias.RouteListId) .SelectSubQuery(addressCountSubquery).WithAlias(() => countUnclosedFastDeliveryAddressesAlias.UnclosedFastDeliveryAddresses)) .TransformUsing(Transformers.AliasToBean <CountUnclosedFastDeliveryAddressesNode>()) .List <CountUnclosedFastDeliveryAddressesNode>(); var rlsWithCountUnclosedFastDeliveries = routeListsWithCountUnclosedFastDeliveries.ToDictionary(x => x.RouteListId, x => x.UnclosedFastDeliveryAddresses); foreach (var node in routeListNodes) { var countUnclosedFastDeliveryAddresses = rlsWithCountUnclosedFastDeliveries[node.RouteList.Id]; node.UnClosedFastDeliveries.ParameterValue = countUnclosedFastDeliveryAddresses; if (countUnclosedFastDeliveryAddresses < maxFastOrdersPerSpecificTime) { node.UnClosedFastDeliveries.IsValidParameter = true; } else { node.UnClosedFastDeliveries.IsValidParameter = false; node.IsValidRLToFastDelivery = false; } } //Время доставки следующего (текущего) заказа позволяет взять быструю доставку foreach (var routeListNode in routeListNodes) { RouteListItem latestAddress = null; var orderedEnRouteAddresses = routeListNode.RouteList.Addresses .Where(x => x.Status == RouteListItemStatus.EnRoute).OrderBy(x => x.IndexInRoute).ToList(); var orderedCompletedAddresses = routeListNode.RouteList.Addresses .Where(x => x.Status == RouteListItemStatus.Completed).OrderBy(x => x.IndexInRoute).ToList(); var latestCompletedAddress = orderedCompletedAddresses.OrderByDescending(x => x.StatusLastUpdate).FirstOrDefault(); if (latestCompletedAddress != null) { latestAddress = orderedEnRouteAddresses.FirstOrDefault(x => x.IndexInRoute > latestCompletedAddress.IndexInRoute); } if (latestAddress == null) { latestAddress = orderedEnRouteAddresses.FirstOrDefault(); } if (latestAddress != null) { var neededTime1 = maxTimeForFastDelivery - latestAddress.Order.DeliveryPoint.MinutesToUnload; if (neededTime1 < minTimeForNewOrder) { routeListNode.RemainingTimeForShipmentNewOrder.ParameterValue = new TimeSpan(0, neededTime1, 0); routeListNode.RemainingTimeForShipmentNewOrder.IsValidParameter = false; routeListNode.IsValidRLToFastDelivery = false; continue; } var water19Count = latestAddress.Order.OrderItems .Where(x => x.Nomenclature.TareVolume == TareVolume.Vol19L && x.Nomenclature.Category == NomenclatureCategory.water) .Sum(x => x.Count); var orderItemsSummaryWeight = latestAddress.Order.OrderItems .Where(x => x.Nomenclature.TareVolume != TareVolume.Vol19L || x.Nomenclature.Category != NomenclatureCategory.water) .Sum(x => x.Nomenclature.Weight * x.Count); var orderEquipmentsSummaryWeight = latestAddress.Order.OrderEquipments .Where(x => x.Direction == Direction.Deliver) .Sum(x => x.Nomenclature.Weight * x.Count); var goodsSummaryWeight = orderItemsSummaryWeight + orderEquipmentsSummaryWeight; //Время выгрузки след. заказа: //(Суммарный вес прочих товаров / кол-во кг, которое водитель может унести в одной руке + кол-во 19л) / 2 руки * время выгрузки в 2 руках 2 бутылей или товара var unloadTime = (goodsSummaryWeight / driverGoodWeightLiftPerHand + water19Count) / 2 * driverUnloadTime; var neededTime2 = maxTimeForFastDelivery - (int)unloadTime; if (neededTime2 < minTimeForNewOrder) { routeListNode.RemainingTimeForShipmentNewOrder.ParameterValue = new TimeSpan(0, neededTime2, 0); routeListNode.RemainingTimeForShipmentNewOrder.IsValidParameter = false; routeListNode.IsValidRLToFastDelivery = false; } else { routeListNode.RemainingTimeForShipmentNewOrder.ParameterValue = new TimeSpan(0, neededTime2, 0); routeListNode.RemainingTimeForShipmentNewOrder.IsValidParameter = true; } } else { routeListNode.RemainingTimeForShipmentNewOrder.ParameterValue = maxTimeForFastDeliveryTimespan; routeListNode.RemainingTimeForShipmentNewOrder.IsValidParameter = true; } } var rlIds = routeListNodes.Select(x => x.RouteList.Id).ToArray(); //OrderItems var orderItemsToDeliver = uow.Session.QueryOver <RouteListItem>(() => rla) .Inner.JoinAlias(() => rla.Order, () => o) .Inner.JoinAlias(() => o.OrderItems, () => oi) .Left.JoinAlias(() => rla.TransferedTo, () => rlaTransfered) .WhereRestrictionOn(() => rla.RouteList.Id).IsIn(rlIds) .WhereRestrictionOn(() => oi.Nomenclature.Id).IsIn(neededNomenclatures.Keys) .Where(() => //не отменённые и не недовозы rla.Status != RouteListItemStatus.Canceled && rla.Status != RouteListItemStatus.Overdue // и не перенесённые к водителю; либо перенесённые с погрузкой; либо перенесённые и это экспресс-доставка (всегда без погрузки) && (!rla.WasTransfered || rla.NeedToReload || o.IsFastDelivery) // и не перенесённые от водителя; либо перенесённые и не нужна погрузка и не экспресс-доставка (остатки по экспресс-доставке не переносятся) && (rla.Status != RouteListItemStatus.Transfered || (!rlaTransfered.NeedToReload && !o.IsFastDelivery))) .SelectList(list => list .SelectGroup(() => rla.RouteList.Id).WithAlias(() => ordersAmountAlias.RouteListId) .SelectGroup(() => oi.Nomenclature.Id).WithAlias(() => ordersAmountAlias.NomenclatureId) .SelectSum(() => oi.Count).WithAlias(() => ordersAmountAlias.Amount)) .TransformUsing(Transformers.AliasToBean <RouteListNomenclatureAmount>()) .Future <RouteListNomenclatureAmount>(); //OrderEquipments var orderEquipmentsToDeliver = uow.Session.QueryOver <RouteListItem>(() => rla) .Inner.JoinAlias(() => rla.Order, () => o) .Inner.JoinAlias(() => o.OrderEquipments, () => oe) .Left.JoinAlias(() => rla.TransferedTo, () => rlaTransfered) .WhereRestrictionOn(() => rla.RouteList.Id).IsIn(rlIds) .WhereRestrictionOn(() => oe.Nomenclature.Id).IsIn(neededNomenclatures.Keys) .Where(() => //не отменённые и не недовозы rla.Status != RouteListItemStatus.Canceled && rla.Status != RouteListItemStatus.Overdue // и не перенесённые к водителю; либо перенесённые с погрузкой; либо перенесённые и это экспресс-доставка (всегда без погрузки) && (!rla.WasTransfered || rla.NeedToReload || o.IsFastDelivery) // и не перенесённые от водителя; либо перенесённые и не нужна погрузка и не экспресс-доставка (остатки по экспресс-доставке не переносятся) && (rla.Status != RouteListItemStatus.Transfered || (!rlaTransfered.NeedToReload && !o.IsFastDelivery))) .And(() => oe.Direction == Direction.Deliver) .SelectList(list => list .SelectGroup(() => rla.RouteList.Id).WithAlias(() => ordersAmountAlias.RouteListId) .SelectGroup(() => oe.Nomenclature.Id).WithAlias(() => ordersAmountAlias.NomenclatureId) .Select(Projections.Sum(Projections.Cast(NHibernateUtil.Decimal, Projections.Property(() => oe.Count))) ).WithAlias(() => ordersAmountAlias.Amount)) .TransformUsing(Transformers.AliasToBean <RouteListNomenclatureAmount>()) .Future <RouteListNomenclatureAmount>(); //CarLoadDocuments var allLoaded = uow.Session.QueryOver <CarLoadDocument>(() => scld) .Inner.JoinAlias(() => scld.Items, () => scldi) .WhereRestrictionOn(() => scld.RouteList.Id).IsIn(rlIds) .WhereRestrictionOn(() => scldi.Nomenclature.Id).IsIn(neededNomenclatures.Keys) .SelectList(list => list .SelectGroup(() => scld.RouteList.Id).WithAlias(() => loadDocumentsAmountAlias.RouteListId) .SelectGroup(() => scldi.Nomenclature.Id).WithAlias(() => loadDocumentsAmountAlias.NomenclatureId) .SelectSum(() => scldi.Amount).WithAlias(() => loadDocumentsAmountAlias.Amount)) .TransformUsing(Transformers.AliasToBean <RouteListNomenclatureAmount>()) .Future <RouteListNomenclatureAmount>(); var allToDeliver = orderItemsToDeliver .Union(orderEquipmentsToDeliver) .GroupBy(x => new { x.RouteListId, x.NomenclatureId }) .Select(group => new RouteListNomenclatureAmount { RouteListId = group.Key.RouteListId, NomenclatureId = group.Key.NomenclatureId, Amount = group.Sum(x => x.Amount) }) .ToList(); //Выбираем МЛ, в котором хватает запаса номенклатур на поступивший быстрый заказ foreach (var routeListNode in routeListNodes) { var toDeliverForRL = allToDeliver.Where(x => x.RouteListId == routeListNode.RouteList.Id).ToList(); var loadedForRL = allLoaded.Where(x => x.RouteListId == routeListNode.RouteList.Id).ToList(); foreach (var need in neededNomenclatures) { var toDeliver = toDeliverForRL.FirstOrDefault(x => x.NomenclatureId == need.Key)?.Amount ?? 0; var loaded = loadedForRL.FirstOrDefault(x => x.NomenclatureId == need.Key)?.Amount ?? 0; var onBoard = loaded - toDeliver; if (onBoard < need.Value) { routeListNode.IsGoodsEnough.ParameterValue = false; routeListNode.IsGoodsEnough.IsValidParameter = false; routeListNode.IsValidRLToFastDelivery = false; break; } } } if (routeListNodes != null) { fastDeliveryAvailabilityHistory.Items = fastDeliveryHistoryConverter .ConvertVerificationDetailsNodesToAvailabilityHistoryItems(routeListNodes, fastDeliveryAvailabilityHistory); } return(fastDeliveryAvailabilityHistory); }