对比新文件 |
| | |
| | | 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 ); |
| | | *] |
| | | } |