/// <summary> /// Ensures that proper conditions exist for box creation. Returns false if boxes need not be created /// </summary> /// <returns></returns> private bool PreBoxCreation(PickslipGroup pickslipGroup, int pickslipId) { if (_bMinMaxPiecesRequired == null) { _bMinMaxPiecesRequired = RetrieveFromDataBase(_customerId); } //If Box minimum weight is greater than box maximum weight through the error if (this.BoxMinWeight > this.BoxMaxWeight) { Trace.TraceWarning("Box Minimum Weight {0} is more than Box Maximum Weight {1}. Treating min weight as max weight", this.BoxMinWeight, this.BoxMaxWeight); this.BoxMaxWeight = this.BoxMinWeight; this.BoxMinWeight = 0; } pickslipGroup.RetrieveFromDb(this, pickslipId, _bMinMaxPiecesRequired.Value); // 1. Should have some SKUs to put in boxes. // This can happen if boxes have already been created. if (pickslipGroup.AllSku.All(p => p.OrderedPieces <= 0)) { return(false); } return(true); }
/// <summary> /// Apply as many checks as we can think of to ensure that the created boxes meet all /// requirements. This amounts to debugging the algorithm. If the test passes, insert boxes in /// database. /// </summary> private void PostBoxCreation(PickslipGroup pickslipGroup) { // Ensure sanity // 1. If we do not have any boxes, it means that some SKU was too big for the box if (!pickslipGroup.Boxes.Any()) { throw new InvalidConstraintException("Some SKU too big for all SKU cases"); } // 5. Ensure that ordered SKUs and pieces exactly match SKU and pieces we have put in boxes bool b = (from sku in pickslipGroup.Boxes.SelectMany(p => p.AllSku) group sku by sku.UpcCode into grouping orderby grouping.Key select new { UpcCode = grouping.Key, TotalPieces = grouping.Sum(p => p.OrderedPieces) }).SequenceEqual( from sku in pickslipGroup.AllSku where sku.OrderedPieces > 0 group sku by sku.UpcCode into grouping orderby grouping.Key select new { UpcCode = grouping.Key, TotalPieces = grouping.Sum(p => p.OrderedPieces) }); if (!b) { throw new InvalidConstraintException("Some problem"); } // 3. Find most used and most unused boxes. Exception if there are no boxes var bestFillRatio = pickslipGroup.Boxes.Max(p => p.FillRatio); if (bestFillRatio > 1) { throw new InvalidConstraintException("Overfilling a box?"); } var worstFillRatio = pickslipGroup.Boxes.Min(p => p.FillRatio); if (worstFillRatio < 0.01m) { throw new InvalidConstraintException("Very underused box?"); } pickslipGroup.InsertBoxesInDb(this._ds); }
/// <summary> /// Creates boxes of pickslip using the passed case. The newly created boxes are accepted /// only if the number of boxes created is less than the existing number of boxes. /// Returns whether the boxes were accepted. /// </summary> /// <param name="boxCase"></param> /// <returns></returns> private bool CreateBoxesUsingBoxCase(PickslipGroup pickslipGroup, BoxCase boxCase) { // Remember the current solution List <Box> curBoxes = pickslipGroup.RelinquishBoxList(); // Create a new solution pickslipGroup.CreateBoxes(this, boxCase); if (curBoxes != null && pickslipGroup.Boxes.Count > curBoxes.Count) { // This solution is worse. Accept the previous solution as the final solution pickslipGroup.SetBoxList(curBoxes); return(false); } else { // The solution was accepted return(true); } }
///<summary> /// Pass a pickslip to create its boxes. /// </summary> /// <remarks> /// Algorithm: /// 1. Retrieve all candidate box cases. /// 2. Attempt to create boxes using the largest case first. /// 3. Stop as soon as the number of boxes created are more than the previous solution and /// accept the previous solution as the best solution. /// /// TODO: /// Handling for SLN (box creation on the basis of defined inner and outer pack /// <summary> /// </remarks> public void CreateBoxesForPickslipGroup(int pickslipId) { PickslipGroup pickslipGroup = new PickslipGroup(); bool b = PreBoxCreation(pickslipGroup, pickslipId); if (!b) { return; } // Try each case first, starting with the biggest. Stop when number of cases needed increases. foreach (BoxCase boxCase in this.BoxCases.OrderByDescending(p => p.Volume)) { if (!this.CreateBoxesUsingBoxCase(pickslipGroup, boxCase)) { // If this case is not accepted, we do not try any more break; } } //TODO: For each box, see whether it is possible to use a smaller SKU case // If we get here, we must have some boxes this.PostBoxCreation(pickslipGroup); }