Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /// <summary>
- /// Pobranie rekomendowanej lokalozacji
- /// </summary>
- /// <param name="article"></param>
- /// <param name="lot"></param>
- /// <param name="inboundMappingId"></param>
- /// <param name="suListUserInOrderByUser"></param>
- /// <param name="neededArticleVolume"></param>
- /// <param name="currentLoc"></param>
- /// <param name="locationType">Jeśli chcemy konkretny typ lokalizacji inny niz dtInboundMapping, jeśli nie wybieramy Undefined </param>
- /// <param name="confirmPickReason"></param>
- /// <returns></returns>
- public dtLocation GetRecommendedLocation(dtArticle article, dtLot lot, long inboundMappingId, long[] suListUserInOrderByUser, decimal? neededArticleVolume, dtLocation currentLoc, LocationType? locationType, ConfirmPickingReason? confirmPickReason = ConfirmPickingReason.OK)
- {
- dtLocation recommendedLocation = null;
- var mapping = Model.dtInboundMapping.FirstOrDefault(d => d.Id == inboundMappingId);
- //dla klienta Pneumat specjalna metoda szukania proponowanego miejsca - bez inbound mapping, z wieloma typami miejsc
- if (FormicaConfig.Common.ProductOwner == ProductOwner.PNE || FormicaConfig.Common.ProductOwner == ProductOwner.KON || FormicaConfig.Common.ProductOwner == ProductOwner.HTL || FormicaConfig.Common.ProductOwner == ProductOwner.JUM)
- {
- var articleVolume = neededArticleVolume ?? 0;
- //pula miejsc z wyliczoną dostępną objętością - niezablokowane, niepełne, niezarezerwowane, nieinwentaryzowane, określonych typów
- var locations = Model.dtLocation.Where(loc => loc.Blocked == LocationBlocked.No && !loc.IsFull
- && !loc.IsVirtual
- && loc.Status != LocationStatus.RESERVED
- && !loc.StocktakingPos.Any(
- x => x.Stocktaking.StocktakingType ==
- StocktakingType.Place
- && x.Stocktaking.Status != StocktakingStatus
- .Cancelled
- && x.Stocktaking.Status != StocktakingStatus
- .Finished)
- && ((locationType == LocationType.Undefined //dla przyjeć w HTL nie sprawdza tego warunku
- && FormicaConfig.Common.ProductOwner == ProductOwner.HTL)
- || loc.OwnerZone.TreeNames.Contains(dtOwnerZone.TREE_SEPARATOR +mapping.OwnerZone.Name + dtOwnerZone.TREE_SEPARATOR))
- && ((locationType == LocationType.Undefined && loc.LocationType ==
- mapping.LocationType) || loc.LocationType ==
- locationType)
- ).Select(loc =>
- //nowy obiekt - informacja o lokalizacji i dostępnej objętości
- new
- {
- location = loc,
- availableVolume =
- loc.Volume ??
- 0 //wyliczenie dostępnego miejsca z objętości lokalizacji i pozycji jednostek
- - (loc.Su.Any(
- su => su.SuPos.Any(
- sp => sp.Lot.Article.ArticleBarcode.Any(ac => ac.Volume.HasValue)))
- ? loc.Su.Sum(
- su => su.SuPos.Sum(
- sp => sp.Quantity *
- sp.Lot.Article.ArticleBarcode.FirstOrDefault(ac => ac.Volume.HasValue)
- .Volume)).Value
- : (decimal)0)
- }).ToList();
- //Dodatkowe warunki w przypadku ponownego wyszukiwania lokalizacji
- //1. Zaproponuj następną jednostkę (inną niż ostatnio)
- if (confirmPickReason == Wms.Common.Classes.Rpm.ConfirmPickingReason.NextLocation && currentLoc != null)
- {
- locations = locations.Except(locations.Where(x => x.location.Id == currentLoc.Id)).ToList();
- }
- //2. Zaproponuj większą jednostkę niż ostatnio wybrana
- if (confirmPickReason == Wms.Common.Classes.Rpm.ConfirmPickingReason.BiggerLocation)
- {
- locations = locations.Except(locations.Where(x => x.availableVolume <= currentLoc.Volume)).ToList();
- }
- //1. Miejsca z danym artykułem
- recommendedLocation = locations.Where(l => l.location.Su.Any(s => s.SuPos.Any(sp => sp.Lot.fkArticleId == article.Id))
- && l.availableVolume >= articleVolume)
- .OrderBy(l => l.availableVolume).ThenBy(l => l.location.PickPath).Select(l => l.location).FirstOrDefault();
- //2. Miejsce wolne
- if (recommendedLocation == null)
- recommendedLocation = locations.Where(l => !l.location.Su.Any(s => s.SuPos.Any()) && l.availableVolume >= articleVolume)
- .OrderBy(l => l.availableVolume).ThenBy(l => l.location.PickPath).Select(l => l.location).FirstOrDefault();
- //3. Miejsce z innym artykułem, pod warunkiem, że miejsce jest "wieloasortymentowe"
- if (recommendedLocation == null)
- recommendedLocation = locations.Where(l => l.location.MixOnLocation == MixOnLocation.MixedLotMixedArticle
- && l.availableVolume >= articleVolume)
- .OrderBy(l => l.availableVolume).ThenBy(l => l.location.PickPath).Select(l => l.location).FirstOrDefault();
- //4. Największe miejsce w magazynie
- if (recommendedLocation == null)
- {
- recommendedLocation = locations.Where(l => (!l.location.Su.Any(s => s.SuPos.Any()) ||
- l.location.MixOnLocation == MixOnLocation.MixedLotMixedArticle)
- && l.availableVolume >= articleVolume)
- .OrderByDescending(l => l.availableVolume).ThenBy(l => l.location.PickPath).Select(l => l.location).FirstOrDefault();
- }
- // 6. Jeśli nie znaleziono miejsca na przełożenie całej ilości to sprawdzamy czy możemy dołożyć coś do miejsca, na którym znajduje się artykuł bądź do miejsca
- // z największą dostępną pojemnością
- if (recommendedLocation == null)
- {
- //// 5.1 Najpierw dla tego samego artykułu
- //recommendedLocation = locations.Where(l => l.location.TD_SU.Any(s => s.TD_SU_POS.Any(sp => sp.TD_LOT.TD_ARTICLE_ID == article.TD_ARTICLE_ID)))
- // .OrderByDescending(l => l.availableVolume).ThenBy(l => l.location.PICK_PATH).Select(l => l.location).FirstOrDefault();
- //// 5.2 Jeśli nie było to największe dostępne
- //if (recommendedLocation == null)
- //{
- var allAvialabled = locations
- .Where(l => !l.location.Su.Any(s => s.SuPos.Any()) ||
- l.location.MixOnLocation == MixOnLocation.MixedLotMixedArticle)
- .OrderByDescending(l => l.availableVolume)
- .ThenBy(l => l.location.PickPath)
- .Select(l => l.location);
- recommendedLocation = allAvialabled.FirstOrDefault(d => d.PickPriority != 0);
- //jeśli nie znaleziono żadnego miejsca z PickPriority != 0
- if (recommendedLocation == null)
- {
- recommendedLocation = allAvialabled.FirstOrDefault();
- }
- }
- return recommendedLocation;
- }
- //pozostali klienci - dotychczasowe rozwiązanie
- else
- {
- bool newLot = lot == null;
- long? lotId = (newLot ? (long?)null : lot.Id);
- // var destLocationType = destLocationTypes.FirstOrDefault();
- // var inboundMapping = Model.dtInboundMapping.FirstOrDefault(x => x.LocationType == destLocationType);
- // var zoneId = inboundMapping != null ? inboundMapping.fkOwnerZoneId : -1;
- // Pula miejsc docelowych.
- var locations = (newLot ?
- //zapytanie dla nowotworzonej partii
- ((from loc in Model.dtLocation
- // Lokalizacja musi byc niezablokowana, niepelna, w dobrym statusie.
- where loc.Blocked == LocationBlocked.No
- where !loc.IsVirtual
- where !loc.IsFull
- where loc.Status != LocationStatus.RESERVED
- where loc.fkOwnerZoneId == mapping.fkOwnerZoneId
- where loc.LocationType != LocationType.ZoneOut
- // musi być zmapowana strefa
- where loc.fkOwnerZoneId != null && loc.OwnerZone.InboundMapping.Any(im => im.Id == inboundMappingId)
- // Lokalizacja nie jest inwentaryzowana
- where !Model.dtStocktakingPos.Any(x => x.Stocktaking.StocktakingType == StocktakingType.Place
- && x.Stocktaking.Status != StocktakingStatus.Cancelled
- && x.Stocktaking.Status != StocktakingStatus.Finished
- && x.fkLocationId == loc.Id)
- // Lista pozycji jednostek na tej lokalizacji.
- let suPosList = loc.Su.SelectMany(el => el.SuPos)
- // Nie mieszaj grup artykulowych.
- where suPosList.All(el => el.Lot.Article.fkOwnerWarehouseId == article.fkOwnerWarehouseId)
- // Nie mieszaj partii.
- where suPosList.All(el => el.Lot.fkArticleId != article.Id) // Nowa partia - nie moze byc takiego artykulu
- // Posortuj lokalizacje - zapelniaj zawsze w takim samym porzadku.
- //orderby loc.AISLE, loc.X, loc.Y, loc.Z
- select new
- {
- loc = loc,
- availableVolume = loc.Volume //wyliczenie dostępnego miejsca z objętości lokalizacji i pozycji jednostek
- - (loc.Su.Any(su => su.SuPos.Any(sp => sp.Lot.Article.ArticleBarcode.Any(ac => ac.Volume.HasValue))) ?
- loc.Su.Sum(su => su.SuPos.Sum(sp => sp.Quantity * sp.Lot.Article.ArticleBarcode.FirstOrDefault(ac => ac.Volume.HasValue).Volume)).Value
- : (decimal)0)
- }).Distinct())
- :
- //Zapytanie dla istniejącej partii
- ((from loc in Model.dtLocation
- // Znajdz strefe dla destLocationType
- // Lokalizacja musi byc niezablokowana, niepelna, w dobrym statusie.
- where loc.Blocked == LocationBlocked.No
- where !loc.IsVirtual
- where !loc.IsFull
- where loc.Status != LocationStatus.RESERVED
- where loc.fkOwnerZoneId == mapping.fkOwnerZoneId
- where loc.LocationType != LocationType.ZoneOut
- // musi być zmapowana strefa
- where loc.fkOwnerZoneId != null && loc.OwnerZone.InboundMapping.Any(im => im.Id == inboundMappingId)
- // Lokalizacja nie jest inwentaryzowana
- where !Model.dtStocktakingPos.Any(x => x.Stocktaking.StocktakingType == StocktakingType.Place
- && x.Stocktaking.Status != StocktakingStatus.Cancelled
- && x.Stocktaking.Status != StocktakingStatus.Finished
- && x.fkLocationId == loc.Id)
- // Lista pozycji jednostek na tej lokalizacji.
- let suPosList = loc.Su.SelectMany(el => el.SuPos)
- // Nie mieszaj grup artykulowych.
- where suPosList.All(el => el.Lot.Article.fkOwnerWarehouseId == article.fkOwnerWarehouseId)
- // Nie mieszaj partii.
- where suPosList.Where(el => el.Lot.fkArticleId == article.Id).All(el => el.fkLotId == lotId) // Partia ustalona - musi byc tylko taka partia
- // Posortuj lokalizacje - zapelniaj zawsze w takim samym porzadku.
- //orderby loc.AISLE, loc.X, loc.Y, loc.Z
- select new
- {
- loc = loc,
- availableVolume = loc.Volume //wyliczenie dostępnego miejsca z objętości lokalizacji i pozycji jednostek
- - (loc.Su.Any(su => su.SuPos.Any(sp => sp.Lot.Article.ArticleBarcode.Any(ac => ac.Volume.HasValue))) ?
- loc.Su.Sum(su => su.SuPos.Sum(sp => sp.Quantity * sp.Lot.Article.ArticleBarcode.FirstOrDefault(ac => ac.Volume.HasValue).Volume)).Value
- : (decimal)0)
- }).Distinct()));
- //Dodatkowe warunki w przypadku ponownego wyszukiwania lokalizacji
- //1. Zaproponuj następną jednostkę (inną niż ostatnio)
- if (confirmPickReason == Wms.Common.Classes.Rpm.ConfirmPickingReason.NextLocation && currentLoc != null)
- {
- locations = locations.Except(locations.Where(x => x.loc.Id == currentLoc.Id));
- }
- //2. Zaproponuj większą jednostkę niż ostatnio wybrana
- if (confirmPickReason == Wms.Common.Classes.Rpm.ConfirmPickingReason.BiggerLocation)
- {
- locations = locations.Except(locations.Where(x => x.availableVolume <= currentLoc.Volume));
- }
- // 1. Miejsce, które posiada wystarczającą ilość miejsca (objętości) do przyjęcia artykułu
- if (neededArticleVolume != null)
- {
- // bierzemy tylko miejsca, które mają możliwą do określenia pojemność
- var locs = locations.Where(d => d.loc.Container != null &&
- d.loc.Container.Height != null &&
- d.loc.Container.Width != null &&
- d.loc.Container.Length != null).ToList();
- var locationsWithVolume = locs.Select(y => y.loc).Select(loc =>
- {
- var totalVolume = loc.fkContainerId == null ? null : loc.Container.Height * loc.Container.Width * loc.Container.Length;
- var occupiedVolume = loc.Su.SelectMany(d => d.SuPos).Sum(d => GetArticleVolume(d.Lot.Article, d.Quantity)) ?? 0;
- return new
- {
- location = loc,
- totalVolume = totalVolume,
- occupiedVolume = occupiedVolume,
- freeVolume = totalVolume - occupiedVolume,
- enoughFreeSpace = (totalVolume - occupiedVolume) >= neededArticleVolume
- };
- }
- ).ToList();
- locationsWithVolume = (from l in locationsWithVolume
- orderby l.enoughFreeSpace ? 0 : 1, // sortujemy wedlug tego czy zmiesci sie tam nasz artykul
- l.location.Su.Any(su => suListUserInOrderByUser.Contains(su.Id)) ? 0 : 1, // czy aktywny uzytkownik juz przyjal taka partie na to miejsce
- l.location.Su.Any(su => su.SuPos.Any(el => el.fkLotId == lot.Id)) ? 0 : 1, // czy taka partia jest na tym miejscu
- l.freeVolume descending, // jesli nie ma lokalizacji gdzie sie zmiesci, to najpierw bierzemy te o najwiekszej ilosci miejsca
- l.location.PickPath, l.location.Aisle, l.location.X, l.location.Y, l.location.Z
- select l).Distinct().ToList();
- recommendedLocation = locationsWithVolume.Select(d => d.location).FirstOrDefault();
- }
- // 2. Miejsce na ktore uzytkownik juz przyjal taka partie w ramach tego zlecenia.
- if ((recommendedLocation == null) && (lot != null) && suListUserInOrderByUser.Any())
- {
- var recommendedLocations = (from location in locations.Select(x => x.loc)
- from su in location.Su
- where suListUserInOrderByUser.Contains(su.Id)
- where su.SuPos.Any(el => el.fkLotId == lot.Id)
- orderby location.PickPath, location.Aisle, location.X, location.Y, location.Z
- select location).Distinct().FirstOrDefault();
- recommendedLocation = recommendedLocations;
- }
- // 3. Miejsce z taka sama partia.
- if ((recommendedLocation == null) && (lot != null))
- {
- var recommendedLocations = (from location in locations.Select(x => x.loc)
- from su in location.Su
- where su.SuPos.Any(el => el.fkLotId == lot.Id)
- orderby location.PickPath, location.Aisle, location.X, location.Y, location.Z
- select location).Distinct().FirstOrDefault();
- recommendedLocation = recommendedLocations;
- }
- // 4. Miejsce puste.
- if (recommendedLocation == null)
- {
- var recommendedLocations = (from location in locations.Select(x => x.loc)
- where location.Status == LocationStatus.FREE
- orderby location.PickPath, location.Aisle, location.X, location.Y, location.Z
- select location).FirstOrDefault();
- recommendedLocation = recommendedLocations;
- }
- // 5. Miejsce pelne ale nie z tym artykulem (nie mieszamy partii).
- if (recommendedLocation == null)
- {
- var recommendedLocations = (from location in locations.Select(x => x.loc)
- from su in location.Su
- where su.SuPos.All(el => el.Lot.fkArticleId != article.Id)
- orderby location.PickPath, location.Aisle, location.X, location.Y, location.Z
- select location).Distinct().FirstOrDefault();
- recommendedLocation = recommendedLocations;
- }
- return recommendedLocation;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement