public virtual List <SOPackageInfoEx> PackByWeight(List <INItemBoxEx> boxes, ItemStats stats) { List <SOPackageInfoEx> list = new List <SOPackageInfoEx>(); List <BoxInfo> boxList = PackByWeight(boxes, stats.BaseWeight, stats.BaseQty, stats.InventoryID.Value); foreach (BoxInfo box in boxList) { SOPackageInfoEx pack = new SOPackageInfoEx(); pack.SiteID = stats.SiteID; pack.BoxID = box.Box.BoxID; pack.CarrierBox = box.Box.CarrierBox; pack.InventoryID = stats.InventoryID; pack.DeclaredValue = (stats.DeclaredValue / stats.BaseWeight) * box.Value; pack.Weight = decimal.Round(box.Value, SOPackageInfo.BoxWeightPrecision); pack.Length = box.Box.Length; pack.Width = box.Box.Width; pack.Height = box.Box.Height; pack.BoxWeight = box.Box.BoxWeight; pack.GrossWeight = pack.Weight + pack.BoxWeight; list.Add(pack); } return(list); }
public virtual SOPackageInfoEx ToPackageInfo(int?siteID) { var info = new SOPackageInfoEx { BoxID = BoxID, Weight = NetWeight, GrossWeight = Weight, WeightUOM = WeightUOM, Qty = Qty, QtyUOM = QtyUOM, InventoryID = InventoryID, DeclaredValue = DeclaredValue, COD = COD > 0, SiteID = siteID, BoxWeight = BoxWeight, CarrierBox = CarrierBox, Description = BoxDescription, Height = Height, Length = Length, Width = Width, MaxWeight = MaxWeight }; return(info); }
public virtual List <SOPackageInfoEx> PackByWeight(List <INItemBoxEx> boxes, ItemStats stats) { List <SOPackageInfoEx> list = new List <SOPackageInfoEx>(); List <BoxInfo> boxList = PackByWeight(boxes, stats.BaseWeight); foreach (BoxInfo box in boxList) { SOPackageInfoEx pack = new SOPackageInfoEx(); pack.SiteID = stats.SiteID; pack.BoxID = box.Box.BoxID; pack.CarrierBox = box.Box.CarrierBox; pack.InventoryID = stats.InventoryID; pack.DeclaredValue = (stats.DeclaredValue / stats.BaseWeight) * box.Value; pack.Weight = box.Value + box.Box.BoxWeight.GetValueOrDefault(); pack.Length = box.Box.Length; pack.Width = box.Box.Width; pack.Height = box.Box.Height; list.Add(pack); } 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); }
public virtual List<SOPackageInfoEx> PackByQty(List<INItemBoxEx> boxes, ItemStats stats) { List<SOPackageInfoEx> list = new List<SOPackageInfoEx>(); List<BoxInfo> boxList = PackByQty(boxes, stats.BaseQty); foreach (BoxInfo box in boxList) { SOPackageInfoEx pack = new SOPackageInfoEx(); pack.SiteID = stats.SiteID; pack.BoxID = box.Box.BoxID; pack.CarrierBox = box.Box.CarrierBox; pack.InventoryID = stats.InventoryID; pack.DeclaredValue = (stats.DeclaredValue / stats.BaseQty) * box.Value; pack.Weight = (stats.BaseWeight / stats.BaseQty) * box.Value + box.Box.BoxWeight.GetValueOrDefault(); pack.Qty = box.Value; pack.Length = box.Box.Length; pack.Width = box.Box.Width; pack.Height = box.Box.Height; list.Add(pack); } 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; }