From 25bd6b91e3aa2b97bbd55f972e69fd72cd1a38df Mon Sep 17 00:00:00 2001 From: hongji.li <hongji.a.li@capgemini.com> Date: 星期二, 26 九月 2023 19:18:05 +0800 Subject: [PATCH] Merge branch 'dev_Kevin' into dev --- _Main/BL/Type_ProductInStockingPointInPeriodPlanningLeaf/_ROOT_Type_ProductInStockingPointInPeriodPlanningLeaf.qbl | 6 +++ LibMacroPlanner/BL/Type_UnitPeriodTimeBase/Function_CalcTotalAvailableCapacity.qbl | 3 + _Main/BL/Type_ProductInStockingPointInPeriodPlanningLeaf/FunctionOverride_CalcStockLevelInDays.qbl | 79 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletions(-) diff --git a/LibMacroPlanner/BL/Type_UnitPeriodTimeBase/Function_CalcTotalAvailableCapacity.qbl b/LibMacroPlanner/BL/Type_UnitPeriodTimeBase/Function_CalcTotalAvailableCapacity.qbl index 7b7de81..704abc5 100644 --- a/LibMacroPlanner/BL/Type_UnitPeriodTimeBase/Function_CalcTotalAvailableCapacity.qbl +++ b/LibMacroPlanner/BL/Type_UnitPeriodTimeBase/Function_CalcTotalAvailableCapacity.qbl @@ -16,7 +16,8 @@ if( not isnull( planningup ) ) { - value := planningup.BaseAvailableCapacity().HoursAsReal() * planningup.MaximumLoadPercentage() / 100; + value := planningup.BaseAvailableCapacity().HoursAsReal() * planningup.MaximumLoadPercentage() / 100 + * this.PlanningSystemRatio(); // Tianma fix 20230926 } } else diff --git a/_Main/BL/Type_ProductInStockingPointInPeriodPlanningLeaf/FunctionOverride_CalcStockLevelInDays.qbl b/_Main/BL/Type_ProductInStockingPointInPeriodPlanningLeaf/FunctionOverride_CalcStockLevelInDays.qbl new file mode 100644 index 0000000..bd5d786 --- /dev/null +++ b/_Main/BL/Type_ProductInStockingPointInPeriodPlanningLeaf/FunctionOverride_CalcStockLevelInDays.qbl @@ -0,0 +1,79 @@ +Quintiq file version 2.0 +#parent: #root +FunctionOverride CalcStockLevelInDays #extension +{ + TextBody: + [* + totalDays := 0.0; + + if( not this.Period_MP().MacroPlan().IsMetaOptimizerRunning() ) + { + balanceInv := this.InventoryLevelEnd(); + + if( balanceInv > 0 ) + { + // Calculate stock level in days + futureperiods := selectsortedset( this, ProductInStockingPoint_MP.ProductInStockingPointInPeriodPlanning.astype( ProductInStockingPointInPeriodPlanningLeaf ), p, + p.Start() >= this.End(), p.Start() ); + product := this.ProductInStockingPoint_MP().Product_MP(); + shelflife := this.ShelfLife(); + hasshelflife := product.HasShelfLife() and not isnull( shelflife ); + agevector := RealVector::Construct(); + quantityvector := RealVector::Construct(); + + // Modified logic to consider shelf-life for stock level in days + if( hasshelflife ) + { + // Get the age and quantity vector of remaining product stock at the end of period + agevector := RealVector::Construct( shelflife.ShelfLifeEndAgeVectorAsBinaryValue() ); + quantityvector := RealVector::Construct( shelflife.ShelfLifeEndQuantityVectorAsBinaryValue() ); + } + + /* + Track if consecutive future periods has 0 demand (although we have balance supply, but if remaining future periods has 0 demand not consider as coverable). + Accumulate the coverable days and only add to total days if manage to find a subsequent period with demand. + */ + traverse( futureperiods, Elements, pispip, + // Terminate calculation once remaining supply is 0 + balanceInv > 0 ) + { + if( balanceInv > 0 ) + { + demandQty := pispip.DependentDemandAndSalesDemandQuantity(); + + // Include expired quantity as demand to determine stock level in days + if( hasshelflife ) + { + isexpiredinperiodvector := BooleanVector::Construct(); + + traverse( agevector.AsValues(), Elements, age ) + { + isexpiredinperiod := not product.GetIsUsableInTargetPeriod( [Real] age, pispip.Start(), pispip.Period_MP() ); + isexpiredinperiodvector.Append( isexpiredinperiod ); + agevector.Add( pispip.Period_MP().GetDurationInDaysForShelfLife(), false ); + } + + // Sum of all elements in the quantity vector that corresponds to element = true in the boolean vector + expiredinventoryqty := quantityvector.GetSelection( isexpiredinperiodvector ).Sum(); + demandQty := demandQty + expiredinventoryqty; // Reduce inventory as expired + } + + if( balanceInv > demandQty ) // Remaining supply can cover demand in period + { + totalDays := totalDays + pispip.Period_MP().DurationInDays(); + balanceInv := balanceInv - demandQty; + } + else // Remaining supply partially cover the demand in period + { + // Main calc logic + totalDays := totalDays + ( balanceInv / demandQty * pispip.Period_MP().DurationInDays() ); + balanceInv := 0.0; + } + } + } + } + } + + this.StockLevelInDays( totalDays ); + *] +} diff --git a/_Main/BL/Type_ProductInStockingPointInPeriodPlanningLeaf/_ROOT_Type_ProductInStockingPointInPeriodPlanningLeaf.qbl b/_Main/BL/Type_ProductInStockingPointInPeriodPlanningLeaf/_ROOT_Type_ProductInStockingPointInPeriodPlanningLeaf.qbl new file mode 100644 index 0000000..8c6a2c8 --- /dev/null +++ b/_Main/BL/Type_ProductInStockingPointInPeriodPlanningLeaf/_ROOT_Type_ProductInStockingPointInPeriodPlanningLeaf.qbl @@ -0,0 +1,6 @@ +Quintiq file version 2.0 +#root +#parent: #DomainModel +TypeSpecialization ProductInStockingPointInPeriodPlanningLeaf #extension +{ +} -- Gitblit v1.9.3