protected virtual void AssignInventoryBoxes(InventoryItemMaint graph, IEnumerable<INItemBoxEx> templateItemBoxes) { INItemBoxEx[] itemBoxes = graph.Boxes.Select().RowCast<INItemBoxEx>().ToArray(); foreach (INItemBoxEx templateItemBox in templateItemBoxes) { INItemBoxEx itemBox = itemBoxes.FirstOrDefault(ic => ic.BoxID == templateItemBox.BoxID) ?? graph.Boxes.Insert(new INItemBoxEx { BoxID = templateItemBox.BoxID }); var copy = (INItemBoxEx)graph.Boxes.Cache.CreateCopy(itemBox); graph.Boxes.Cache.RestoreCopy(copy, templateItemBox); var excludeFields = new Type[] { typeof(INItemBoxEx.inventoryID), typeof(INItemBoxEx.Tstamp), typeof(INItemBoxEx.createdByID), typeof(INItemBoxEx.createdByScreenID), typeof(INItemBoxEx.createdDateTime), typeof(INItemBoxEx.lastModifiedByID), typeof(INItemBoxEx.lastModifiedByScreenID), typeof(INItemBoxEx.lastModifiedDateTime), typeof(INItemBoxEx.noteID), }; foreach (Type excludeField in excludeFields) { graph.Boxes.Cache.SetValue(copy, excludeField.Name, graph.Boxes.Cache.GetValue(itemBox, excludeField.Name)); } itemBox = graph.Boxes.Update(copy); } }
public virtual List <BoxInfo> PackByWeight(List <INItemBoxEx> boxes, decimal baseWeight, decimal baseQty, int inventoryID) { boxes.Sort((INItemBoxEx x, INItemBoxEx y) => decimal.Compare(x.MaxWeight.GetValueOrDefault(), y.MaxWeight.GetValueOrDefault())); List <BoxInfo> list = new List <BoxInfo>(); if (baseQty == 0) { PXTrace.WriteWarning("Packing Engine failed to execute. BaseQty supplied is zero."); return(list); } decimal unitWeight = baseWeight / baseQty; if (baseWeight > 0 && boxes.Count > 0) { INItemBoxEx box = GetBoxThatCanFitWeight(boxes, baseWeight); if (box != null) { BoxInfo p = new BoxInfo(); p.Box = box; p.Value = baseWeight; list.Add(p); } else { //Distribute qty among Biggest boxes available: INItemBoxEx biggestBox = boxes[boxes.Count - 1]; if (biggestBox.MaxNetWeight > 0) { if (biggestBox.MaxNetWeight < unitWeight) { throw new PXException(Messages.PackagesRecalcErrorNoBoxesThatFitItem, InventoryItem.PK.Find(graph, (int?)inventoryID)?.InventoryCD); } int numberOfMaxBoxes = (int)Math.Floor(baseWeight / biggestBox.MaxNetWeight); int itemsPerBox = (int)Math.Floor(biggestBox.MaxNetWeight / unitWeight); for (int i = 0; i < numberOfMaxBoxes; i++) { BoxInfo p = new BoxInfo(); p.Box = biggestBox; p.Value = itemsPerBox * unitWeight; list.Add(p); baseWeight -= itemsPerBox * unitWeight; baseQty -= itemsPerBox; } //remainder list.AddRange(PackByWeight(boxes, baseWeight, baseQty, inventoryID)); } } } return(list); }
public virtual List <INItemBoxEx> GetBoxesByInventoryID(int inventoryID, string carrierID) { PXSelectBase <INItemBoxEx> select; if (string.IsNullOrEmpty(carrierID)) { select = new PXSelect <INItemBoxEx, Where <INItemBoxEx.inventoryID, Equal <Required <INItemBoxEx.inventoryID> > > >(graph); } else { select = new PXSelectJoin <INItemBoxEx, InnerJoin <CarrierPackage, On <INItemBoxEx.boxID, Equal <CarrierPackage.boxID> > >, Where <INItemBoxEx.inventoryID, Equal <Required <INItemBox.inventoryID> >, And <CarrierPackage.carrierID, Equal <Required <CarrierPackage.carrierID> > > > >(graph); } List <INItemBoxEx> list = new List <INItemBoxEx>(); foreach (INItemBoxEx box in select.Select(inventoryID, carrierID)) { list.Add(box); } if (list.Count == 0) { if (string.IsNullOrEmpty(carrierID)) { //there are no explicit boxes setup on the InventoryItem. This means that all system boxes are applicable: List <CSBox> allboxes = GetBoxesByCarrierID(carrierID); foreach (CSBox csBox in allboxes) { INItemBoxEx box = new INItemBoxEx(); box.BoxID = csBox.BoxID; box.BaseQty = null; box.BoxWeight = csBox.BoxWeight; box.CarrierBox = csBox.CarrierBox; box.Description = csBox.Description; box.InventoryID = inventoryID; box.MaxQty = null; box.MaxVolume = csBox.MaxVolume; box.MaxWeight = csBox.MaxWeight; box.Qty = null; box.UOM = null; list.Add(box); } } else { //There is no common box between boxes defined for the item and boxess defined for the carrier. throw new PXException(Messages.BoxesNotDefined); } } return(list); }
public virtual List <BoxInfo> PackByQty(List <INItemBoxEx> boxes, decimal baseQty) { boxes.Sort((INItemBoxEx x, INItemBoxEx y) => decimal.Compare(x.BaseQty.GetValueOrDefault(), y.BaseQty.GetValueOrDefault())); List <BoxInfo> list = new List <BoxInfo>(); if (baseQty > 0 && boxes.Count > 0) { INItemBoxEx box = GetBoxThatCanFitQty(boxes, baseQty); if (box != null) { BoxInfo p = new BoxInfo(); p.Box = box; p.Value = baseQty; list.Add(p); } else { //Distribute qty among Biggest boxes available: INItemBoxEx biggestBox = boxes[boxes.Count - 1]; if (biggestBox.BaseQty.Value > 0) { int numberOfMaxBoxes = (int)Math.Floor(baseQty / biggestBox.BaseQty.Value); for (int i = 0; i < numberOfMaxBoxes; i++) { BoxInfo p = new BoxInfo(); p.Box = biggestBox; p.Value = biggestBox.BaseQty.Value; list.Add(p); baseQty -= biggestBox.BaseQty.Value; } //remainder list.AddRange(PackByQty(boxes, baseQty)); } } } return(list); }
public virtual List <INItemBoxEx> GetBoxesByInventoryID(int inventoryID, string carrierID) { InventoryItem inventory = InventoryItem.PK.Find(graph, inventoryID); PXSelectBase <INItemBoxEx> select; if (string.IsNullOrEmpty(carrierID)) { select = new PXSelect <INItemBoxEx, Where <INItemBoxEx.inventoryID, Equal <Required <INItemBoxEx.inventoryID> > > >(graph); } else { select = new PXSelectJoin <INItemBoxEx, InnerJoin <CarrierPackage, On <INItemBoxEx.boxID, Equal <CarrierPackage.boxID> > >, Where <INItemBoxEx.inventoryID, Equal <Required <INItemBox.inventoryID> >, And <CarrierPackage.carrierID, Equal <Required <CarrierPackage.carrierID> > > > >(graph); } List <INItemBoxEx> list = new List <INItemBoxEx>(); foreach (INItemBoxEx box in select.Select(inventoryID, carrierID)) { list.Add(box); } if (list.Count == 0) { if (inventory.PackageOption == INPackageOption.Quantity) { if (string.IsNullOrEmpty(carrierID)) { throw new PXException(Messages.ItemBoxesAreNotSetup, inventory.InventoryCD); } else { throw new PXException(Messages.CarrierBoxesAreNotSetupForInventory, carrierID, inventory.InventoryCD); } } List <CSBox> allboxes = GetBoxesByCarrierID(carrierID); if (allboxes.Count == 0) { throw new PXException(Messages.CarrierBoxesAreNotSetup, carrierID); } foreach (CSBox csBox in allboxes) { INItemBoxEx box = new INItemBoxEx(); box.BoxID = csBox.BoxID; box.BaseQty = null; box.BoxWeight = csBox.BoxWeight; box.CarrierBox = csBox.CarrierBox; box.Description = csBox.Description; box.InventoryID = inventoryID; box.MaxQty = null; box.MaxVolume = csBox.MaxVolume; box.MaxWeight = csBox.MaxWeight; box.Qty = null; box.UOM = null; box.Length = csBox.Length; box.Width = csBox.Width; box.Height = csBox.Height; list.Add(box); } } return(list); }
public virtual List <SOPackageInfoEx> PackByWeightMixedItems(List <INItemBoxEx> boxes, List <ItemInfo> items, Dictionary <int, List <INItemBoxEx> > boxesByInventoryLookup, Dictionary <string, List <int> > boxItemsLookup, bool restrictByVolume, int?siteID, decimal?declaredValue) { HashSet <int> itemsWithRationalQunatities = new HashSet <int>(); //InventoryItem misses a property/attribute that describes whether an item qty is whole or can be a rational number. By judging the qty on the line we heuristicly deduce this property. foreach (ItemInfo item in items) { if ((item.Qty % 1) != 0) { itemsWithRationalQunatities.Add(item.InventoryID); } } // коробки c пустотой (могут быть и одинаковые, расширенный выходной массив) List <advancedINItemBoxEx> advancedboxes = new List <advancedINItemBoxEx>(); // упорядочим коробки для каждого айтема foreach (KeyValuePair <int, List <INItemBoxEx> > keyValuePair in boxesByInventoryLookup) { keyValuePair.Value.Sort((x, y) => { var weightCompare = (-1 * decimal.Compare(x.MaxNetWeight, y.MaxNetWeight)); return(weightCompare != 0 ? weightCompare : (-1 * decimal.Compare((x.MaxVolume ?? 0m), (y.MaxVolume ?? 0m)))); }); //DESC; } // упорядочим все айтемы по весу ОДНОЙ(НЕДЕЛИМОЙ) единицы items.Sort((x, y) => (-1 * decimal.Compare(x.UnitWeight.GetValueOrDefault(), y.UnitWeight.GetValueOrDefault()))); //DESC; // упорядочим все коробки для всех айтемов boxes.Sort((x, y) => { var weightCompare = (-1 * decimal.Compare(x.MaxNetWeight, y.MaxNetWeight)); return(weightCompare != 0 ? weightCompare : (-1 * decimal.Compare((x.MaxVolume ?? 0m), (y.MaxVolume ?? 0m)))); }); //DESC; // Перебираем все айтемы начиная с самого тяжелого (одного) if (restrictByVolume) { foreach (ItemInfo item in items) { // в такие коробки будем их класть INItemBoxEx currentbox = boxesByInventoryLookup[item.InventoryID].ToArray()[0]; decimal unpackedWeight = item.TotalWeight; decimal unpackedVolume = item.TotalVolume; if (item.UnitWeight > currentbox.MaxNetWeight || (item.UnitVolume > currentbox.MaxVolume && currentbox.MaxVolume > 0)) { InventoryItem inv = InventoryItem.PK.Find(graph, item.InventoryID); throw new PXException(Messages.NoBoxForItem, inv.InventoryCD.Trim()); } // может пустоты есть? foreach (advancedINItemBoxEx advancedbox in advancedboxes) { foreach (INItemBoxEx allcurrentbox in boxesByInventoryLookup[item.InventoryID].ToArray()) { if (advancedbox.BoxID == allcurrentbox.BoxID && unpackedWeight > 0) { if (advancedbox.EmptyBoxWeight >= item.UnitWeight && advancedbox.EmptyBoxVolume >= item.UnitVolume) { decimal numberofunitWeight; //qty that can fit in the box by weight decimal numberofunitVolume; //qty that can fit in the box by volume if (advancedbox.EmptyBoxWeight > unpackedWeight) { if (item.UnitWeight > 0) { numberofunitWeight = itemsWithRationalQunatities.Contains(item.InventoryID) ? unpackedWeight / item.UnitWeight.Value : Math.Floor(unpackedWeight / item.UnitWeight.Value); } else { numberofunitWeight = itemsWithRationalQunatities.Contains(item.InventoryID) ? item.Qty : Math.Floor(item.Qty); } } else { if (item.UnitWeight > 0) { numberofunitWeight = itemsWithRationalQunatities.Contains(item.InventoryID) ? advancedbox.EmptyBoxWeight / item.UnitWeight.Value : Math.Floor(advancedbox.EmptyBoxWeight / item.UnitWeight.Value); } else { numberofunitWeight = itemsWithRationalQunatities.Contains(item.InventoryID) ? item.Qty : Math.Floor(item.Qty); } } if (advancedbox.EmptyBoxVolume > unpackedVolume) { if (item.UnitVolume > 0) { numberofunitVolume = itemsWithRationalQunatities.Contains(item.InventoryID) ? unpackedVolume / item.UnitVolume.Value : Math.Floor(unpackedVolume / item.UnitVolume.Value); } else { numberofunitVolume = itemsWithRationalQunatities.Contains(item.InventoryID) ? item.Qty : Math.Floor(item.Qty); } } else { if (item.UnitVolume > 0) { numberofunitVolume = itemsWithRationalQunatities.Contains(item.InventoryID) ? advancedbox.EmptyBoxVolume / item.UnitVolume.Value : Math.Floor(advancedbox.EmptyBoxVolume / item.UnitVolume.Value); } else { numberofunitVolume = itemsWithRationalQunatities.Contains(item.InventoryID) ? item.Qty : Math.Floor(item.Qty); } } decimal numberofunit = numberofunitVolume < numberofunitWeight ? numberofunitVolume : numberofunitWeight; decimal actualweigth = numberofunit * item.UnitWeight.GetValueOrDefault(); decimal actualvolume = numberofunit * item.UnitVolume.GetValueOrDefault(); unpackedWeight = unpackedWeight - actualweigth; advancedbox.InvenoryList.Add(item.InventoryID); advancedbox.CurrentWeight = advancedbox.CurrentWeight + actualweigth; advancedbox.EmptyBoxWeight = advancedbox.MaxNetWeight - advancedbox.CurrentWeight; advancedbox.CurrentVolume = advancedbox.CurrentVolume + actualvolume; advancedbox.EmptyBoxVolume = advancedbox.MaxVolume.GetValueOrDefault() - advancedbox.CurrentVolume; } } } } if (unpackedWeight != 0) { // теперь в новые кидать будем while (unpackedWeight > currentbox.MaxNetWeight) { decimal numberofunitWeight; decimal numberofunitVolume; if (item.UnitWeight > 0) { numberofunitWeight = itemsWithRationalQunatities.Contains(item.InventoryID) ? currentbox.MaxNetWeight / item.UnitWeight.Value : Math.Floor(currentbox.MaxNetWeight / item.UnitWeight.Value); } else { numberofunitWeight = itemsWithRationalQunatities.Contains(item.InventoryID) ? item.Qty : Math.Floor(item.Qty); } if (item.UnitVolume > 0 && currentbox.MaxVolume > 0) { numberofunitVolume = itemsWithRationalQunatities.Contains(item.InventoryID) ? currentbox.MaxVolume.Value / item.UnitVolume.Value : Math.Floor(currentbox.MaxVolume.Value / item.UnitVolume.Value); } else { numberofunitVolume = itemsWithRationalQunatities.Contains(item.InventoryID) ? item.Qty : Math.Floor(item.Qty); } decimal numberofunit = numberofunitVolume < numberofunitWeight ? numberofunitVolume : numberofunitWeight; decimal actualweigth = numberofunit * item.UnitWeight.GetValueOrDefault(); decimal actualvolume = numberofunit * item.UnitVolume.GetValueOrDefault(); unpackedWeight = unpackedWeight - actualweigth; unpackedVolume = unpackedVolume - actualvolume; advancedINItemBoxEx advancedbox = new advancedINItemBoxEx(); advancedbox.InvenoryList = new List <int>(); advancedbox.BoxID = currentbox.BoxID; advancedbox.InvenoryList.Add(item.InventoryID); advancedbox.BoxWeight = currentbox.BoxWeight; advancedbox.MaxWeight = currentbox.MaxWeight; advancedbox.MaxVolume = currentbox.MaxVolume; advancedbox.EmptyBoxWeight = currentbox.MaxNetWeight - actualweigth; advancedbox.EmptyBoxVolume = currentbox.MaxVolume.GetValueOrDefault() - actualvolume; advancedbox.CurrentWeight = actualweigth; advancedbox.CurrentVolume = actualvolume; advancedbox.Length = currentbox.Length; advancedbox.Width = currentbox.Width; advancedbox.Height = currentbox.Height; advancedboxes.Add(advancedbox); } // последние ящики while (unpackedWeight != 0) { decimal numberofunitWeight; decimal numberofunitVolume; if (currentbox.MaxNetWeight > unpackedWeight) { if (item.UnitWeight > 0) { numberofunitWeight = itemsWithRationalQunatities.Contains(item.InventoryID) ? unpackedWeight / item.UnitWeight.Value : Math.Floor(unpackedWeight / item.UnitWeight.Value); } else { numberofunitWeight = itemsWithRationalQunatities.Contains(item.InventoryID) ? item.Qty : Math.Floor(item.Qty); } } else { if (item.UnitWeight > 0) { numberofunitWeight = itemsWithRationalQunatities.Contains(item.InventoryID) ? currentbox.MaxNetWeight / item.UnitWeight.Value : Math.Floor(currentbox.MaxNetWeight / item.UnitWeight.Value); } else { numberofunitWeight = itemsWithRationalQunatities.Contains(item.InventoryID) ? item.Qty : Math.Floor(item.Qty); } } if (currentbox.MaxVolume > unpackedVolume) { if (item.UnitVolume > 0) { numberofunitVolume = itemsWithRationalQunatities.Contains(item.InventoryID) ? unpackedVolume / item.UnitVolume.Value : Math.Floor(unpackedVolume / item.UnitVolume.Value); } else { numberofunitVolume = itemsWithRationalQunatities.Contains(item.InventoryID) ? item.Qty : Math.Floor(item.Qty); } } else { if (item.UnitVolume > 0 && currentbox.MaxVolume > 0) { numberofunitVolume = itemsWithRationalQunatities.Contains(item.InventoryID) ? currentbox.MaxVolume.Value / item.UnitVolume.Value : Math.Floor(currentbox.MaxVolume.Value / item.UnitVolume.Value); } else { numberofunitVolume = itemsWithRationalQunatities.Contains(item.InventoryID) ? item.Qty : Math.Floor(item.Qty); } } decimal numberofunit = numberofunitVolume < numberofunitWeight ? numberofunitVolume : numberofunitWeight; decimal actualweigth = numberofunit * item.UnitWeight.GetValueOrDefault(); decimal actualvolume = numberofunit * item.UnitVolume.GetValueOrDefault(); unpackedWeight = unpackedWeight - actualweigth; unpackedVolume = unpackedVolume - actualvolume; advancedINItemBoxEx advancedbox1 = new advancedINItemBoxEx(); advancedbox1.InvenoryList = new List <int>(); advancedbox1.BoxID = currentbox.BoxID; advancedbox1.InvenoryList.Add(item.InventoryID); advancedbox1.BoxWeight = currentbox.BoxWeight; advancedbox1.MaxWeight = currentbox.MaxWeight; advancedbox1.MaxVolume = currentbox.MaxVolume; advancedbox1.EmptyBoxWeight = currentbox.MaxNetWeight - actualweigth; advancedbox1.EmptyBoxVolume = currentbox.MaxVolume.GetValueOrDefault() - actualvolume; advancedbox1.CurrentWeight = actualweigth; advancedbox1.CurrentVolume = actualvolume; advancedbox1.Length = currentbox.Length; advancedbox1.Width = currentbox.Width; advancedbox1.Height = currentbox.Height; advancedboxes.Add(advancedbox1); } } } // Второй проход. Посмотрим не влезет ли товар в коробки поменьше foreach (advancedINItemBoxEx advancedbox in advancedboxes) { // пошли по всем коробкам foreach (INItemBoxEx box in boxes) { // если туда влезает именно этот товар (или товары) bool availablesmallpackage = true; foreach (int itemlist in advancedbox.InvenoryList) { if (!boxItemsLookup[box.BoxID].Contains(itemlist)) { availablesmallpackage = false; } } if (availablesmallpackage) { // и по весу проходим if (advancedbox.CurrentWeight < box.MaxNetWeight) { // и по объему if (advancedbox.CurrentVolume < box.MaxVolume) { advancedbox.BoxID = box.BoxID; advancedbox.Length = box.Length; advancedbox.Width = box.Width; advancedbox.Height = box.Height; advancedbox.BoxWeight = box.BoxWeight; } } } } } } else { foreach (ItemInfo item in items) { // в такие коробки будем их класть INItemBoxEx currentbox = boxesByInventoryLookup[item.InventoryID].ToArray()[0]; decimal unpackedWeight = item.TotalWeight; if (item.UnitWeight > currentbox.MaxNetWeight) { InventoryItem inv = InventoryItem.PK.Find(graph, item.InventoryID); throw new PXException(Messages.NoBoxForItem, inv.InventoryCD.Trim()); } // может пустоты есть? foreach (advancedINItemBoxEx advancedbox in advancedboxes) { foreach (INItemBoxEx allcurrentbox in boxesByInventoryLookup[item.InventoryID].ToArray()) { if (advancedbox.BoxID == allcurrentbox.BoxID && unpackedWeight > 0) { if (advancedbox.EmptyBoxWeight >= item.UnitWeight) { decimal numberofunit; if (advancedbox.EmptyBoxWeight > unpackedWeight) { if (item.UnitWeight > 0) { numberofunit = itemsWithRationalQunatities.Contains(item.InventoryID) ? unpackedWeight / item.UnitWeight.Value : Math.Floor(unpackedWeight / item.UnitWeight.Value); } else { numberofunit = itemsWithRationalQunatities.Contains(item.InventoryID) ? item.Qty : Math.Ceiling(item.Qty); } } else { if (item.UnitWeight > 0) { numberofunit = itemsWithRationalQunatities.Contains(item.InventoryID) ? advancedbox.EmptyBoxWeight / item.UnitWeight.Value : Math.Floor(advancedbox.EmptyBoxWeight / item.UnitWeight.Value); } else { numberofunit = itemsWithRationalQunatities.Contains(item.InventoryID) ? item.Qty : Math.Ceiling(item.Qty); } } decimal actualweigth = numberofunit * item.UnitWeight.GetValueOrDefault(); unpackedWeight = unpackedWeight - actualweigth; advancedbox.InvenoryList.Add(item.InventoryID); advancedbox.CurrentWeight = advancedbox.CurrentWeight + actualweigth; advancedbox.EmptyBoxWeight = advancedbox.MaxNetWeight - advancedbox.CurrentWeight; } } } } if (unpackedWeight != 0 && currentbox.MaxNetWeight > 0) { // теперь в новые кидать будем while (unpackedWeight > currentbox.MaxNetWeight) { decimal numberofunit; if (item.UnitWeight > 0) { numberofunit = itemsWithRationalQunatities.Contains(item.InventoryID) ? currentbox.MaxNetWeight / item.UnitWeight.Value : Math.Floor(currentbox.MaxNetWeight / item.UnitWeight.Value); } else { numberofunit = itemsWithRationalQunatities.Contains(item.InventoryID) ? item.Qty : Math.Ceiling(item.Qty); } decimal actualweigth = numberofunit * item.UnitWeight.GetValueOrDefault(); unpackedWeight = unpackedWeight - actualweigth; advancedINItemBoxEx advancedbox = new advancedINItemBoxEx(); advancedbox.InvenoryList = new List <int>(); advancedbox.BoxID = currentbox.BoxID; advancedbox.InvenoryList.Add(item.InventoryID); advancedbox.BoxWeight = currentbox.BoxWeight; advancedbox.MaxWeight = currentbox.MaxWeight; advancedbox.MaxVolume = currentbox.MaxVolume; advancedbox.EmptyBoxWeight = currentbox.MaxNetWeight - actualweigth; advancedbox.CurrentWeight = actualweigth; advancedbox.Length = currentbox.Length; advancedbox.Width = currentbox.Width; advancedbox.Height = currentbox.Height; advancedboxes.Add(advancedbox); } // и последний ящик advancedINItemBoxEx advancedbox1 = new advancedINItemBoxEx(); advancedbox1.InvenoryList = new List <int>(); advancedbox1.BoxID = currentbox.BoxID; advancedbox1.InvenoryList.Add(item.InventoryID); advancedbox1.BoxWeight = currentbox.BoxWeight; advancedbox1.MaxWeight = currentbox.MaxWeight; advancedbox1.MaxVolume = currentbox.MaxVolume; advancedbox1.EmptyBoxWeight = currentbox.MaxNetWeight - unpackedWeight; advancedbox1.CurrentWeight = unpackedWeight; advancedbox1.Length = currentbox.Length; advancedbox1.Width = currentbox.Width; advancedbox1.Height = currentbox.Height; advancedboxes.Add(advancedbox1); } } // Второй проход. Посмотрим не влезет ли товар в коробки поменьше foreach (advancedINItemBoxEx advancedbox in advancedboxes) { // пошли по всем коробкам foreach (INItemBoxEx box in boxes) { // если туда влезает именно этот товар (или товары) bool availablesmallpackage = true; foreach (int itemlist in advancedbox.InvenoryList) { if (!boxItemsLookup[box.BoxID].Contains(itemlist)) { availablesmallpackage = false; } } if (availablesmallpackage) { // и по весу проходим if (advancedbox.CurrentWeight < box.MaxNetWeight) { advancedbox.BoxID = box.BoxID; advancedbox.Length = box.Length; advancedbox.Width = box.Width; advancedbox.Height = box.Height; advancedbox.BoxWeight = box.BoxWeight; } } } } } List <SOPackageInfoEx> list = new List <SOPackageInfoEx>(); foreach (advancedINItemBoxEx advancedbox in advancedboxes) { SOPackageInfoEx temp = new SOPackageInfoEx(); temp.BoxID = advancedbox.BoxID; temp.SiteID = siteID; temp.DeclaredValue = declaredValue; temp.Length = advancedbox.Length; temp.Width = advancedbox.Width; temp.Height = advancedbox.Height; foreach (INItemBoxEx box in boxes) { if (box.BoxID == temp.BoxID) { temp.Weight = decimal.Round(advancedbox.CurrentWeight, SOPackageInfo.BoxWeightPrecision); temp.BoxWeight = decimal.Round(advancedbox.BoxWeight.GetValueOrDefault(), SOPackageInfo.BoxWeightPrecision); temp.GrossWeight = temp.Weight + temp.BoxWeight; } } list.Add(temp); } return(list); }
public virtual List <SOPackageInfoEx> PackByWeightMixedItems(List <INItemBoxEx> boxes, List <ItemInfo> items, Dictionary <int, List <INItemBoxEx> > boxesByInventoryLookup, Dictionary <string, List <int> > boxItemsLookup, bool restrictByVolume, int?siteID) { // коробки c пустотой (могут быть и одинаковые, расширенный выходной массив) List <advancedINItemBoxEx> advancedboxes = new List <advancedINItemBoxEx>(); // упорядочим коробки для каждого айтема foreach (KeyValuePair <int, List <INItemBoxEx> > keyValuePair in boxesByInventoryLookup) { keyValuePair.Value.Sort((x, y) => (-1 * decimal.Compare(x.MaxNetWeight, y.MaxNetWeight))); //DESC; } // упорядочим все айтемы по весу ОДНОЙ(НЕДЕЛИМОЙ) единицы items.Sort((x, y) => (-1 * decimal.Compare(x.UnitWeight.GetValueOrDefault(), y.UnitWeight.GetValueOrDefault()))); //DESC; // упорядочим все коробки для всех айтемов boxes.Sort((x, y) => (-1 * decimal.Compare(x.MaxNetWeight, y.MaxNetWeight))); //DESC; // Перебираем все айтемы начиная с самого тяжелого (одного) if (restrictByVolume) { foreach (ItemInfo item in items) { // в такие коробки будем их класть INItemBoxEx currentbox = boxesByInventoryLookup[item.InventoryID].ToArray()[0]; decimal unpackedWeight = item.TotalWeight; decimal unpackedVolume = item.TotalVolume; if (item.UnitWeight > currentbox.MaxWeight || (item.UnitVolume > currentbox.MaxVolume && currentbox.MaxVolume > 0)) { InventoryItem inv = PXSelect <InventoryItem, Where <InventoryItem.inventoryID, Equal <Required <InventoryItem.inventoryID> > > > .Select(graph, item.InventoryID); throw new PXException(Messages.NoBoxForItem, inv.InventoryCD.Trim()); } // может пустоты есть? foreach (advancedINItemBoxEx advancedbox in advancedboxes) { foreach (INItemBoxEx allcurrentbox in boxesByInventoryLookup[item.InventoryID].ToArray()) { if (advancedbox.BoxID == allcurrentbox.BoxID && unpackedWeight > 0) { if (advancedbox.EmptyBoxWeight >= item.UnitWeight && advancedbox.EmptyBoxVolume >= item.UnitVolume) { int numberofunitWeight; //qty that can fit in the box by weight int numberofunitVolume; //qty that can fit in the box by volume if (advancedbox.EmptyBoxWeight > unpackedWeight) { if (item.UnitWeight > 0) { numberofunitWeight = Convert.ToInt32(Math.Floor(unpackedWeight / item.UnitWeight.Value)); } else { numberofunitWeight = Convert.ToInt32(Math.Floor(item.Qty)); } } else { if (item.UnitWeight > 0) { numberofunitWeight = Convert.ToInt32(Math.Floor(advancedbox.EmptyBoxWeight / item.UnitWeight.Value)); } else { numberofunitWeight = Convert.ToInt32(Math.Floor(item.Qty)); } } if (advancedbox.EmptyBoxVolume > unpackedVolume) { if (item.UnitVolume > 0) { numberofunitVolume = Convert.ToInt32(Math.Floor(unpackedVolume / item.UnitVolume.Value)); } else { numberofunitVolume = Convert.ToInt32(Math.Floor(item.Qty)); } } else { if (item.UnitVolume > 0) { numberofunitVolume = Convert.ToInt32(Math.Floor(advancedbox.EmptyBoxVolume / item.UnitVolume.Value)); } else { numberofunitVolume = Convert.ToInt32(Math.Floor(item.Qty)); } } int numberofunit = numberofunitVolume < numberofunitWeight ? numberofunitVolume : numberofunitWeight; decimal actualweigth = numberofunit * item.UnitWeight.GetValueOrDefault(); decimal actualvolume = numberofunit * item.UnitVolume.GetValueOrDefault(); unpackedWeight = unpackedWeight - actualweigth; advancedbox.InvenoryList.Add(item.InventoryID); advancedbox.CurrentWeight = advancedbox.CurrentWeight + actualweigth; advancedbox.EmptyBoxWeight = advancedbox.MaxNetWeight - advancedbox.CurrentWeight; advancedbox.CurrentVolume = advancedbox.CurrentVolume + actualvolume; advancedbox.EmptyBoxVolume = advancedbox.MaxVolume.GetValueOrDefault() - advancedbox.CurrentVolume; } } } } if (unpackedWeight != 0) { // теперь в новые кидать будем while (unpackedWeight > currentbox.MaxNetWeight) { int numberofunitWeight; int numberofunitVolume; if (item.UnitWeight > 0) { numberofunitWeight = Convert.ToInt32(Math.Floor(currentbox.MaxNetWeight / item.UnitWeight.Value)); } else { numberofunitWeight = Convert.ToInt32(Math.Floor(item.Qty)); } if (item.UnitVolume > 0 && currentbox.MaxVolume > 0) { numberofunitVolume = Convert.ToInt32(Math.Floor(currentbox.MaxVolume.Value / item.UnitVolume.Value)); } else { numberofunitVolume = Convert.ToInt32(Math.Floor(item.Qty)); } int numberofunit = numberofunitVolume < numberofunitWeight ? numberofunitVolume : numberofunitWeight; decimal actualweigth = numberofunit * item.UnitWeight.GetValueOrDefault(); decimal actualvolume = numberofunit * item.UnitVolume.GetValueOrDefault(); unpackedWeight = unpackedWeight - actualweigth; unpackedVolume = unpackedVolume - actualvolume; advancedINItemBoxEx advancedbox = new advancedINItemBoxEx(); advancedbox.InvenoryList = new List <int>(); advancedbox.BoxID = currentbox.BoxID; advancedbox.InvenoryList.Add(item.InventoryID); advancedbox.BoxWeight = currentbox.BoxWeight; advancedbox.MaxWeight = currentbox.MaxWeight; advancedbox.EmptyBoxWeight = currentbox.MaxNetWeight - actualweigth; advancedbox.EmptyBoxVolume = currentbox.MaxVolume.GetValueOrDefault() - actualvolume; advancedbox.CurrentWeight = actualweigth; advancedbox.CurrentVolume = actualvolume; advancedboxes.Add(advancedbox); } // последние ящики while (unpackedWeight != 0) { int numberofunitWeight; int numberofunitVolume; if (currentbox.MaxNetWeight > unpackedWeight) { if (item.UnitWeight > 0) { numberofunitWeight = Convert.ToInt32(Math.Floor(unpackedWeight / item.UnitWeight.Value)); } else { numberofunitWeight = Convert.ToInt32(Math.Floor(item.Qty)); } } else { if (item.UnitWeight > 0) { numberofunitWeight = Convert.ToInt32(Math.Floor(currentbox.MaxNetWeight / item.UnitWeight.Value)); } else { numberofunitWeight = Convert.ToInt32(Math.Floor(item.Qty)); } } if (currentbox.MaxVolume > unpackedVolume) { if (item.UnitVolume > 0) { numberofunitVolume = Convert.ToInt32(Math.Floor(unpackedVolume / item.UnitVolume.Value)); } else { numberofunitVolume = Convert.ToInt32(Math.Floor(item.Qty)); } } else { if (item.UnitVolume > 0 && currentbox.MaxVolume > 0) { numberofunitVolume = Convert.ToInt32(Math.Floor(currentbox.MaxVolume.Value / item.UnitVolume.Value)); } else { numberofunitVolume = Convert.ToInt32(Math.Floor(item.Qty)); } } int numberofunit = numberofunitVolume < numberofunitWeight ? numberofunitVolume : numberofunitWeight; decimal actualweigth = numberofunit * item.UnitWeight.GetValueOrDefault(); decimal actualvolume = numberofunit * item.UnitVolume.GetValueOrDefault(); unpackedWeight = unpackedWeight - actualweigth; unpackedVolume = unpackedVolume - actualvolume; advancedINItemBoxEx advancedbox1 = new advancedINItemBoxEx(); advancedbox1.InvenoryList = new List <int>(); advancedbox1.BoxID = currentbox.BoxID; advancedbox1.InvenoryList.Add(item.InventoryID); advancedbox1.BoxWeight = currentbox.BoxWeight; advancedbox1.MaxWeight = currentbox.MaxWeight; advancedbox1.EmptyBoxWeight = currentbox.MaxNetWeight - actualweigth; advancedbox1.EmptyBoxVolume = currentbox.MaxVolume.GetValueOrDefault() - actualvolume; advancedbox1.CurrentWeight = actualweigth; advancedbox1.CurrentVolume = actualvolume; advancedboxes.Add(advancedbox1); } } } // Второй проход. Посмотрим не влезет ли товар в коробки поменьше foreach (advancedINItemBoxEx advancedbox in advancedboxes) { // пошли по всем коробкам foreach (INItemBoxEx box in boxes) { // если туда влезает именно этот товар (или товары) bool availablesmallpackage = true; foreach (int itemlist in advancedbox.InvenoryList) { if (!boxItemsLookup[box.BoxID].Contains(itemlist)) { availablesmallpackage = false; } } if (availablesmallpackage) { // и по весу проходим if (advancedbox.CurrentWeight < box.MaxNetWeight) { // и по объему if (advancedbox.CurrentVolume < box.MaxVolume) { advancedbox.BoxID = box.BoxID; } } } } } } else { foreach (ItemInfo item in items) { // в такие коробки будем их класть INItemBoxEx currentbox = boxesByInventoryLookup[item.InventoryID].ToArray()[0]; decimal unpackedWeight = item.TotalWeight; // может пустоты есть? foreach (advancedINItemBoxEx advancedbox in advancedboxes) { foreach (INItemBoxEx allcurrentbox in boxesByInventoryLookup[item.InventoryID].ToArray()) { if (advancedbox.BoxID == allcurrentbox.BoxID && unpackedWeight > 0) { if (advancedbox.EmptyBoxWeight >= item.UnitWeight) { int numberofunit; if (advancedbox.EmptyBoxWeight > unpackedWeight) { if (item.UnitWeight > 0) { numberofunit = Convert.ToInt32(Math.Ceiling(unpackedWeight / item.UnitWeight.Value)); } else { numberofunit = Convert.ToInt32(Math.Ceiling(item.Qty)); } } else { if (item.UnitWeight > 0) { numberofunit = Convert.ToInt32(Math.Ceiling(advancedbox.EmptyBoxWeight / item.UnitWeight.Value)); } else { numberofunit = Convert.ToInt32(Math.Ceiling(item.Qty)); } } decimal actualweigth = numberofunit * item.UnitWeight.GetValueOrDefault(); unpackedWeight = unpackedWeight - actualweigth; advancedbox.InvenoryList.Add(item.InventoryID); advancedbox.CurrentWeight = advancedbox.CurrentWeight + actualweigth; advancedbox.EmptyBoxWeight = advancedbox.MaxNetWeight - advancedbox.CurrentWeight; } } } } if (unpackedWeight != 0) { // теперь в новые кидать будем while (unpackedWeight > currentbox.MaxNetWeight) { int numberofunit; if (item.UnitWeight > 0) { numberofunit = Convert.ToInt32(Math.Ceiling(currentbox.MaxNetWeight / item.UnitWeight.Value)); } else { numberofunit = Convert.ToInt32(Math.Ceiling(item.Qty)); } decimal actualweigth = numberofunit * item.UnitWeight.GetValueOrDefault(); unpackedWeight = unpackedWeight - actualweigth; advancedINItemBoxEx advancedbox = new advancedINItemBoxEx(); advancedbox.InvenoryList = new List <int>(); advancedbox.BoxID = currentbox.BoxID; advancedbox.InvenoryList.Add(item.InventoryID); advancedbox.BoxWeight = currentbox.BoxWeight; advancedbox.MaxWeight = currentbox.MaxWeight; advancedbox.EmptyBoxWeight = currentbox.MaxNetWeight - actualweigth; advancedbox.CurrentWeight = actualweigth; advancedboxes.Add(advancedbox); } // и последний ящик advancedINItemBoxEx advancedbox1 = new advancedINItemBoxEx(); advancedbox1.InvenoryList = new List <int>(); advancedbox1.BoxID = currentbox.BoxID; advancedbox1.InvenoryList.Add(item.InventoryID); advancedbox1.BoxWeight = currentbox.BoxWeight; advancedbox1.MaxWeight = currentbox.MaxWeight; advancedbox1.EmptyBoxWeight = currentbox.MaxNetWeight - unpackedWeight; advancedbox1.CurrentWeight = unpackedWeight; advancedboxes.Add(advancedbox1); } } // Второй проход. Посмотрим не влезет ли товар в коробки поменьше foreach (advancedINItemBoxEx advancedbox in advancedboxes) { // пошли по всем коробкам foreach (INItemBoxEx box in boxes) { // если туда влезает именно этот товар (или товары) bool availablesmallpackage = true; foreach (int itemlist in advancedbox.InvenoryList) { if (!boxItemsLookup[box.BoxID].Contains(itemlist)) { availablesmallpackage = false; } } if (availablesmallpackage) { // и по весу проходим if (advancedbox.CurrentWeight < box.MaxNetWeight) { advancedbox.BoxID = box.BoxID; } } } } } List <SOPackageInfoEx> list = new List <SOPackageInfoEx>(); foreach (advancedINItemBoxEx advancedbox in advancedboxes) { SOPackageInfoEx temp = new SOPackageInfoEx(); temp.BoxID = advancedbox.BoxID; temp.SiteID = siteID; foreach (INItemBoxEx box in boxes) { if (box.BoxID == temp.BoxID) { temp.Weight = advancedbox.CurrentWeight + box.BoxWeight; } } list.Add(temp); } return(list); }