| Quintiq file version 2.0 | 
| #parent: #root | 
| Method InitConstraintsGoalsForDriverSales ( | 
|   CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program, | 
|   const LibOpt_Scope scope | 
| ) const | 
| { | 
|   Description: 'Init constraints goals for sales accounts' | 
|   TextBody: | 
|   [* | 
|     // Sales revenue accounts | 
|     salesdemandqty_varname := typeof( MPSalesDemandQtyVariable ); | 
|     driversales_varname := typeof( MPDriverSalesVariable ); | 
|     disaggregatedsalesdemandqty_varname := typeof( MPDisaggregatedSalesDemandQtyVariable ); | 
|     driversales_constname := typeof( MPDriverSalesConstraint ); | 
|     delayedsalesdemandqty_varname := typeof( MPDelayedSalesDemandQtyVariable ); | 
|     delayeddisaggregatedsalesdemandqty_varname := typeof( MPDelayedDisaggregatedSalesDemandQtyVariable ); | 
|      | 
|     scalefactor_driver_revconst := this.ScaleConstraintTerm( driversales_varname, driversales_constname ); | 
|     scalefactor_salesdemandqty_revconst := this.ScaleConstraintTerm( salesdemandqty_varname, driversales_constname ); | 
|     scalefactor_disaggregatedsalesdemandqty_revconst := this.ScaleConstraintTerm( disaggregatedsalesdemandqty_varname, driversales_constname ); | 
|     scalefactor_delayedsalesdemandqty_revconst := this.ScaleConstraintTerm( delayedsalesdemandqty_varname, driversales_constname ); | 
|     scalefactor_delayeddisaggregatedsalesdemandqty_revconst := this.ScaleConstraintTerm( delayeddisaggregatedsalesdemandqty_varname, driversales_constname ); | 
|      | 
|      | 
|     scalefactor_rhs_revconst := this.ScaleConstraintRHS( driversales_constname, 1.0 ); | 
|      | 
|     driver := select( this, MacroPlan.AccountCostDriver, driver, driver.Name() = Translations::MP_AccountAssignmentCostDriverSales() ); // unique | 
|     traverse( scope.GetAccountsInOptimizerRunConst(),Elements, account, account.HasSalesAssignment() ) // condition -=> not isnull( driver ) | 
|     { | 
|       // Sales of each account = sales demands & postponed sales demand fulfilled quantity in each assignment * revenue. | 
|       // revconst constraint uom: Monetary | 
|       revconst := program.DriverSalesConstraints().New( account, driver ); | 
|       revconst.Sense( '=' ); | 
|       revconst.RHSValue( 0.0 * scalefactor_rhs_revconst ); | 
|       // Term UoM: Monetary | 
|       revconst.NewTerm( 1.0 * scalefactor_driver_revconst, program.DriverSalesVariables().Get( account, driver ) ); | 
|      | 
|       traverse( account, AccountAssignment.astype( PISPAccount ), aa, aa.AccountCostDriver() = driver ) | 
|       { | 
|         // The pispip should only be considered if it is part of this optimizer run | 
|         pisp := aa.ProductInStockingPoint_MP(); | 
|         maxpostponementperiod := pisp.OptimizerMaxPostponementPeriod(); | 
|          | 
|         if ( guard( scope.Contains(  aa.ProductInStockingPoint_MP().PISPInOptimizerRun() ) and pisp.IsLeaf(), false ) ) | 
|         { | 
|           pispip := pisp.EarliestPISPIPInScope().astype( ProductInStockingPointInPeriodPlanningLeaf );  | 
|           lateststart := guard( pisp.LatestPISPIPInScope().Start(), DateTime::MinDateTime() );  | 
|           while ( not isnull( pispip ) and pispip.Start() <= lateststart )  | 
|           { | 
|             traverse( pispip, PlanningBaseSalesDemandInPeriodForOptimization.astype( LeafSalesDemandInPeriod ), sd ) // traverse LeafSalesDemandInPeriod | 
|             { | 
|               // Term: -revenueperquantity * SalesDemandQty variable | 
|               // UoM:     [Monetary/PISP]    *     [PISP] | 
|               revconst.NewTerm( -sd.BasePricePerQuantity() * scalefactor_salesdemandqty_revconst, program.SalesDemandQtyVariables().Get( sd ) ); | 
|             } //end of traverse LeafSalesDemandInPeriod | 
|        | 
|             // No need to create any term for driver constraint on AggregatedSalesDemandInPeriod, therefore traverse DisaggregatedSalesDemandInPeriod | 
|             traverse( pispip, PlanningBaseSalesDemandInPeriodForOptimization.astype( DisaggregatedSalesDemandInPeriod ), dasdip ) | 
|             { | 
|               revconst.NewTerm( -dasdip.BasePricePerQuantity() * scalefactor_disaggregatedsalesdemandqty_revconst, | 
|                                   program.DisaggregatedSalesDemandQtyVariables().Get( dasdip ) );                  | 
|             } // end of traverse DisaggregatedSalesDemandInPeriod | 
|              | 
|             // Add terms for postponed sales demands | 
|             previouspispip := pispip.PreviousPlanningPISPIP(); | 
|              | 
|             for( i := 1; | 
|                  i <= maxpostponementperiod         // within the maximum number of postponement periods | 
|                  and not isnull( previouspispip );  // the previous pispip exists | 
|                  i++ | 
|                ) | 
|             { | 
|               traverse( previouspispip, astype( ProductInStockingPointInPeriodPlanningLeaf ).PlanningBaseSalesDemandInPeriodForOptimizationPostponable, sd, | 
|                         not sd.MasterSalesDemand().IsExcludedFromFulfillmentKPI() ) | 
|               { | 
|                 isleafsalesdemandinperiod := sd.istype( LeafSalesDemandInPeriod ); | 
|                 coefficient := ifexpr( isleafsalesdemandinperiod, | 
|                                        -sd.BasePricePerQuantity(), | 
|                                        -sd.astype( DisaggregatedSalesDemandInPeriod ).AggregatedSalesDemandInPeriod().BasePricePerQuantity() ); | 
|                 scalefactor := ifexpr( isleafsalesdemandinperiod, | 
|                                        scalefactor_delayedsalesdemandqty_revconst, | 
|                                        scalefactor_delayeddisaggregatedsalesdemandqty_revconst ); | 
|                  | 
|                 coeffactor := coefficient * scalefactor; | 
|                  | 
|                 var := sd.GetDelayedSalesDemandQtyVariable( program, pispip.Period_MP() ); | 
|                  | 
|                 if( not isnull( var ) ) | 
|                 { | 
|                   revconst.NewTerm( coeffactor, var ); | 
|                 } | 
|               } | 
|                | 
|               previouspispip := previouspispip.PreviousPlanningPISPIP(); | 
|             } | 
|              | 
|             pispip := pispip.NextPlanningPISPIP().astype( ProductInStockingPointInPeriodPlanningLeaf ); | 
|           } // end of traverse pispip | 
|         } // endif pisp | 
|       } // end of traverse PISPAccount aa | 
|     } // end of traverse optimizer accounts | 
|   *] | 
|   InterfaceProperties { Accessibility: 'Module' } | 
| } |