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);
			}
		}
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
        }