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' }
|
}
|