| Quintiq file version 2.0 | 
| #parent: #root | 
| Method GetInventoryRHSForShelfLifeSplitBalanceConstraint ( | 
|   const ProductInStockingPointInPeriodPlanning pispip, | 
|   const IncomingShelfLifeDay islday, | 
|   DateTime firstpispipforsplitbalancestart, | 
|   const RunContextForCapacityPlanning runcontext, | 
|   const LibOpt_Scope scope | 
| ) const as Real | 
| { | 
|   Description: 'Calculate and returns the rhs of the balance constraints (=starting inventory of a pispip considering all decisions outside the optimizer horizon)' | 
|   TextBody: | 
|   [* | 
|     // The RHS of this constraint is the initial inventory based on all decisions outside the scope of the optimizer, it includes: | 
|     // Inventory supply that is greater than 0. If the supply is less than 0, it will be treated as a "must be fulfilled" demands | 
|      | 
|     rhs := 0.0; | 
|     positiveinvsupply := sum( pispip, astype( ProductInStockingPointInPeriodPlanningLeaf ).InventorySupply, isup, isup.Quantity()  > 0.0, isup.Quantity() );  | 
|     supplyquantity := ifexpr( islday.ShelfLifeDays() = 0, positiveinvsupply, 0.0 ); // optimizer figures out itself how much expires, so give total inventory supply quantity | 
|      | 
|     // Inventory of the previous period if that period exists and is not part of the optimizer horizon | 
|     invstart := 0.0; | 
|     previouspispip := pispip.PreviousPlanningPISPIP(); | 
|     if( not isnull( previouspispip ) | 
|         and previouspispip.Start() < firstpispipforsplitbalancestart )  | 
|     { | 
|       if ( islday.ShelfLifeDays() =  0 ) // we put inventory start for first pispip in ShelfLifeDays = 0 pispip.Note we assume we have shelflife extra periods before optimizer scope  | 
|       { | 
|         invstart := pispip.InventoryLevelStart() // take start iventory of pispip to make sure expired qty is taken out (in this case previous pispip is completely outside of the optimizer so optimizer does not  | 
|                                                  // figure out itself what has expired.  | 
|       } | 
|     } | 
|      | 
|      | 
|     product := pispip.ProductInStockingPoint_MP().Product_MP(); | 
|      | 
|     // The sum of the new supply that starts outside the optimizer scope | 
|     sumnewsupply := 0.0; | 
|     // Add the new supply quantity if it has a dd on a pispip outside the optimizer scope | 
|     traverse( pispip, astype( ProductInStockingPointInPeriodPlanningLeaf ).NewSupply, newsupply, not newsupply.Quantity() = 0.0 )  | 
|                 | 
|     { | 
|       if ( newsupply.IsNewSupplyOfOperation()  | 
|           and ( isnull( newsupply.PeriodTaskOperation().UnitPeriodWhenInScope() )      // either the period task is not in scope | 
|                 or not newsupply.GetHasAllDDInOptimizerScope( runcontext, scope ) ) )                          // or if it is check whether some dependent demand is taking from a pispip not in scope | 
|       { | 
|         if ( islday.ShelfLifeDays() = 0 )  | 
|         { | 
|           sumnewsupply := sumnewsupply + newsupply.Quantity(); | 
|         } | 
|       } | 
|       else | 
|       { | 
|         traverse( newsupply, PeriodTask_MP.astype( PeriodTaskLaneLeg ).Trip.ProductInTrip, pit, | 
|                   pit.Product_MP() = product | 
|                   and not scope.Contains( pit.ProductInTripInOptimizerRun() )  | 
|                   and pit.Trip().GetShelfLifeAgeToAdd() = islday.ShelfLifeDays()  | 
|                  ) | 
|         { | 
|           sumnewsupply := sumnewsupply + pit.Quantity(); | 
|         } | 
|       } | 
|     } | 
|      | 
|     // If the user runs a downstream smart plan, then the user may specify a total available supply | 
|     // This total available supply will overrule the real total supply of the pispip | 
|     // Therefore, we will have to update the RHS of the balance constraint to account for the difference | 
|     magicalusersupply := 0.0; | 
|     if( pispip.GetHasMisMatchAvailableUserSupply() and islday.ShelfLifeDays() = 0 ) | 
|     { | 
|       magicalusersupply := pispip.TotalAvailableSupplyUser() - pispip.SupplyQuantity(); | 
|     } | 
|      | 
|     // Calculate the total RHS | 
|     rhs := -( supplyquantity + invstart + sumnewsupply + magicalusersupply ); | 
|      | 
|     return rhs | 
|   *] | 
|   InterfaceProperties { Accessibility: 'Module' } | 
| } |