Quintiq file version 2.0 
 | 
#parent: #root 
 | 
Method CapacityRounding ( 
 | 
  MacroPlan macroPlan, 
 | 
  Real timeDifference, 
 | 
  UnitPeriodTimeBase uptb, 
 | 
  UnitPeriodTimeBases uptbs 
 | 
) 
 | 
{ 
 | 
  TextBody: 
 | 
  [* 
 | 
    debuginfo( "需要圆整的时间(单位:小时)", timeDifference, "    Free capacity(单位:小时)", uptb.FreeCapacity().HoursAsReal(), "    ChangeoverDuration(单位:小时)", uptb.ChangeoverDuration().HoursAsReal(), "    需要圆整的产能周期的开始时间:", uptb.StartDate().Format( "Y-M2-D2" ) ); 
 | 
    //timeDifference         := uptb.FreeCapacity().HoursAsReal() - uptb.ChangeoverDuration().HoursAsReal(); 
 | 
    nextUnitPeriodTimeBase := ifexpr( isnull( uptb.Next().astype( UnitPeriodTimeBase ) ), select( uptbs, Elements, tempUPTB, tempUPTB.Start() = uptb.End() ), uptb.Next().astype( UnitPeriodTimeBase ) ); 
 | 
    //debuginfo( "考虑库存和lotsize" ); 
 | 
    //while ( timeDifference > 0 and not isnull( nextUnitPeriodTimeBase ) ) { 
 | 
    //  debuginfo( "开始向时间为:", nextUnitPeriodTimeBase.StartDate().Format( "Y-M2-D2" ), "的产能周期借" ); 
 | 
    //       
 | 
    //  traverse ( nextUnitPeriodTimeBase, PeriodTaskOperation, pto, guard( pto.Operation().RoutingStep().Routing().Start(), uptb.StartDate() ) <= uptb.StartDate() and 
 | 
    //                                                               guard( pto.Operation().RoutingStep().Routing().End(), uptb.End().Date() ) >= uptb.End().Date() and 
 | 
    //                                                               timeDifference > 0 ) {          
 | 
    //    minimumQuantityThatCanBeBorrowed := Real::MaxReal(); 
 | 
    //    minimumCapacityThatCanBeBorrowed := Real::MaxReal(); 
 | 
    //    traverse ( pto, NewSupply, ns, true ) { 
 | 
    //      targetBorrowSplitShiftLotsizeLimit := select( scenarioManager, SplitShiftLotsizeLimit, tempSSLL, tempSSLL.unitID() = unitPeriodTimeBase.UnitID() and 
 | 
    //                                                                                                       tempSSLL.productID() = ns.ProductInStockingPointInPeriodPlanningLeaf().ProductInStockingPoint_MP().ProductID() and 
 | 
    //                                                                                                       tempSSLL.startTime() <= ns.Start().Date() and 
 | 
    //                                                                                                       tempSSLL.endTime() >= ns.End().Date() ); 
 | 
    //      minimumQuantityThatCanBeBorrowed := minvalue(  
 | 
    //                                                    minvalue( ifexpr( not isnull( targetBorrowSplitShiftLotsizeLimit ) and targetBorrowSplitShiftLotsizeLimit.lotsize() < ns.Quantity(),  
 | 
    //                                                                      ns.Quantity() - targetBorrowSplitShiftLotsizeLimit.lotsize(),  
 | 
    //                                                                      Real::MaxReal() ), 
 | 
    //                                                              minvalue(  
 | 
    //                                                                        ifexpr( ( ns.ProductInStockingPointInPeriodPlanningLeaf().InventoryLevelEnd() - ns.ProductInStockingPointInPeriodPlanningLeaf().MinInventoryLevel() ) > 0,  
 | 
    //                                                                                  ns.ProductInStockingPointInPeriodPlanningLeaf().InventoryLevelEnd() - ns.ProductInStockingPointInPeriodPlanningLeaf().MinInventoryLevel(),  
 | 
    //                                                                                  0.0  
 | 
    //                                                                               ),  
 | 
    //                                                                        ns.Quantity()     
 | 
    //                                                                       )  
 | 
    //                                                             ), 
 | 
    //                                                    minimumCapacityThatCanBeBorrowed  
 | 
    //                                                   ); 
 | 
    //      debuginfo( "nextUnitPeriodTimeBase的当前周期任务供应的产品名:", ns.ProductInStockingPointInPeriodPlanningLeaf().ProductInStockingPoint_MP().ProductID(), String::Tab(), 
 | 
    //                 "最小库存:", ns.ProductInStockingPointInPeriodPlanningLeaf().MinInventoryLevel(), String::Tab(), 
 | 
    //                 "现有库存:", ns.ProductInStockingPointInPeriodPlanningLeaf().InventoryLevelEnd(), String::Tab(), 
 | 
    //                 "供应数量:", ns.Quantity(), String::Tab(), 
 | 
    //                 "是否存在lotsize:", ifexpr( isnull( targetBorrowSplitShiftLotsizeLimit ), "不存在", "存在" ), String::Tab(), 
 | 
    //                 "lotsize数量:", ifexpr( isnull( targetBorrowSplitShiftLotsizeLimit ), -1, targetBorrowSplitShiftLotsizeLimit.lotsize() ) 
 | 
    //                ); 
 | 
    //                     
 | 
    //      sourceProductInStockingPointInPeriodPlanningLeaf := select( ns, ProductInStockingPointInPeriodPlanningLeaf.ProductInStockingPoint_MP.ProductInStockingPointInPeriodPlanning.astype( ProductInStockingPointInPeriodPlanningLeaf ), tempPISPIPPL, tempPISPIPPL.Start() = unitPeriodTimeBase.Start() ); 
 | 
    //      sourceNewSupply := select( sourceProductInStockingPointInPeriodPlanningLeaf, NewSupply, tempNS, tempNS.Process_MP().AsProcess_MP().ID() = unitPeriodTimeBase.UnitID() ); 
 | 
    //      targetReturnSplitShiftLotsizeLimit := select( scenarioManager, SplitShiftLotsizeLimit, tempSSLL, tempSSLL.unitID() = unitPeriodTimeBase.UnitID() and 
 | 
    //                                                                                                       tempSSLL.productID() = sourceProductInStockingPointInPeriodPlanningLeaf.ProductInStockingPoint_MP().ProductID() and 
 | 
    //                                                                                                       tempSSLL.startTime() <= sourceProductInStockingPointInPeriodPlanningLeaf.Start().Date() and 
 | 
    //                                                                                                       tempSSLL.endTime() >= sourceProductInStockingPointInPeriodPlanningLeaf.End().Date() ); 
 | 
    //      minimumAcceptableQuantity := minvalue( ifexpr( not isnull( targetReturnSplitShiftLotsizeLimit ) and not isnull( sourceNewSupply ) and targetReturnSplitShiftLotsizeLimit.lotsize() > sourceNewSupply.Quantity(),  
 | 
    //                                                     targetReturnSplitShiftLotsizeLimit.lotsize() - sourceNewSupply.Quantity(),  
 | 
    //                                                     Real::MaxReal()  
 | 
    //                                                    ), 
 | 
    //                                             ifexpr( ( sourceProductInStockingPointInPeriodPlanningLeaf.MaxInventoryLevel() - sourceProductInStockingPointInPeriodPlanningLeaf.InventoryLevelEnd() ) > 0,  
 | 
    //                                                       sourceProductInStockingPointInPeriodPlanningLeaf.MaxInventoryLevel() - sourceProductInStockingPointInPeriodPlanningLeaf.InventoryLevelEnd(),  
 | 
    //                                                       0.0  
 | 
    //                                                    ) 
 | 
    //                                            );                                             
 | 
    //      debuginfo( "要圆整的时间:", sourceProductInStockingPointInPeriodPlanningLeaf.Start().Date().Format( "Y-M2-D2" ), String::Tab(), 
 | 
    //                 "要圆整的最大库存:", sourceProductInStockingPointInPeriodPlanningLeaf.MaxInventoryLevel(), String::Tab(), 
 | 
    //                 "要圆整的现有库存:", sourceProductInStockingPointInPeriodPlanningLeaf.InventoryLevelEnd(), String::Tab(), 
 | 
    //                 "要圆整的供应数量:", guard( sourceNewSupply.Quantity(), 0 ), String::Tab(), 
 | 
    //                 "是否存在lotsize:", ifexpr( isnull( targetReturnSplitShiftLotsizeLimit ), "不存在", "存在" ), String::Tab(), 
 | 
    //                 "lotsize数量:", ifexpr( isnull( targetReturnSplitShiftLotsizeLimit ), -1, targetReturnSplitShiftLotsizeLimit.lotsize() ), String::Tab(), 
 | 
    //                 "要圆整的最小接纳数量:", minimumAcceptableQuantity 
 | 
    //                ); 
 | 
    //         
 | 
    //      minimumQuantityThatCanBeBorrowed := minvalue( minimumQuantityThatCanBeBorrowed, minimumAcceptableQuantity ); 
 | 
    //    } 
 | 
    //    debuginfo( "nextUnitPeriodTimeBase的当前周期任务供应数量:", pto.Quantity(), "    周期任务能借的最低数量:", minimumQuantityThatCanBeBorrowed );                                                      
 | 
    //       
 | 
    //    minimumCapacityThatCanBeBorrowed := minimumQuantityThatCanBeBorrowed / pto.Operation().Throughput(); 
 | 
    //    unifiedProcessingTimeOfRounding := minvalue( timeDifference, minimumCapacityThatCanBeBorrowed );  
 | 
    //    debuginfo( "剩余圆整的产能:", timeDifference, "    nextUnitPeriodTimeBase的当前周期任务供应数量:", pto.Quantity(), "    能借的产能:", minimumCapacityThatCanBeBorrowed, " 统一借的产能:", unifiedProcessingTimeOfRounding );  
 | 
    //    this.A_unifiedProcessingOfRoundingLogic( unifiedProcessingTimeOfRounding, unitPeriodTimeBase, pto, macroPlan );   
 | 
    //    timeDifference := timeDifference - unifiedProcessingTimeOfRounding;   
 | 
    //  } 
 | 
    //      
 | 
    //  if ( isnull( nextUnitPeriodTimeBase.Next() ) ) { 
 | 
    //    nextUnitPeriodTimeBase := select( unitPeriodTimeBases, Elements, tempUPTB, tempUPTB.Start() = nextUnitPeriodTimeBase.End() ); 
 | 
    //  } else { 
 | 
    //    nextUnitPeriodTimeBase := nextUnitPeriodTimeBase.Next().astype( UnitPeriodTimeBase ); 
 | 
    //  } 
 | 
    //  debuginfo( "。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。" ); 
 | 
    //} 
 | 
     
 | 
    sourceChangeover := uptb.ChangeoverDuration(); 
 | 
    targetChangeover := Duration::Zero(); 
 | 
     
 | 
    debuginfo( "需要圆整的时间(单位:小时)", timeDifference, "    考虑ChangeOver条件圆整使其达到整班" ); 
 | 
    nextUnitPeriodTimeBase := ifexpr( isnull( uptb.Next().astype( UnitPeriodTimeBase ) ), select( uptbs, Elements, tempUPTB, tempUPTB.Start() = uptb.End() ), uptb.Next().astype( UnitPeriodTimeBase ) ); 
 | 
    while ( timeDifference > 0 and not isnull( nextUnitPeriodTimeBase ) ) { 
 | 
      debuginfo( "开始向时间为:", nextUnitPeriodTimeBase.StartDate().Format( "Y-M2-D2" ), "的产能周期借" ); 
 | 
      traverse ( nextUnitPeriodTimeBase, PeriodTaskOperation, pto, guard( pto.Operation().RoutingStep().Routing().Start(), uptb.StartDate() ) <= uptb.StartDate() and 
 | 
                                                                   guard( pto.Operation().RoutingStep().Routing().End(), uptb.End().Date() ) >= uptb.End().Date() and 
 | 
                                                                   exists( uptb, PeriodTaskOperation.Operation, tempO, tempO = pto.Operation() )                  and 
 | 
                                                                   timeDifference > 0 ) { 
 | 
        minimumCapacityThatCanBeBorrowed := pto.Quantity() / pto.Operation().Throughput(); 
 | 
        unifiedProcessingTimeOfRounding := minvalue( timeDifference, minimumCapacityThatCanBeBorrowed );  
 | 
        debuginfo( "剩余圆整的产能:", timeDifference, "    nextUnitPeriodTimeBase的当前周期任务供应数量:", pto.Quantity(), "    能借的产能:", minimumCapacityThatCanBeBorrowed, " 统一借的产能:", unifiedProcessingTimeOfRounding, "    借之前changeover时间:", uptb.ChangeoverDuration() );  
 | 
        this.UnifiedProcessingOfRoundingLogic( unifiedProcessingTimeOfRounding, uptb, pto, macroPlan );  
 | 
        targetChangeover := uptb.ChangeoverDuration(); 
 | 
        timeDifference   := timeDifference - unifiedProcessingTimeOfRounding;                                                  
 | 
      } 
 | 
          
 | 
      if ( isnull( nextUnitPeriodTimeBase.Next() ) ) { 
 | 
        nextUnitPeriodTimeBase := select( uptbs, Elements, tempUPTB, tempUPTB.Start() = nextUnitPeriodTimeBase.End() ); 
 | 
      } else { 
 | 
        nextUnitPeriodTimeBase := nextUnitPeriodTimeBase.Next().astype( UnitPeriodTimeBase ); 
 | 
      } 
 | 
    } 
 | 
         
 | 
    debuginfo( "需要圆整的时间(单位:小时)", timeDifference, "    不考虑任何条件圆整使其到达整班" ); 
 | 
    nextUnitPeriodTimeBase := ifexpr( isnull( uptb.Next().astype( UnitPeriodTimeBase ) ), select( uptbs, Elements, tempUPTB, tempUPTB.Start() = uptb.End() ), uptb.Next().astype( UnitPeriodTimeBase ) ); 
 | 
    while ( timeDifference > 0 and not isnull( nextUnitPeriodTimeBase ) ) { 
 | 
      debuginfo( "开始向时间为:", nextUnitPeriodTimeBase.StartDate().Format( "Y-M2-D2" ), "的产能周期借" ); 
 | 
      traverse ( nextUnitPeriodTimeBase, PeriodTaskOperation, pto, guard( pto.Operation().RoutingStep().Routing().Start(), uptb.StartDate() ) <= uptb.StartDate() and 
 | 
                                                                   guard( pto.Operation().RoutingStep().Routing().End(), uptb.End().Date() ) >= uptb.End().Date() and 
 | 
                                                                   timeDifference > 0 ) { 
 | 
        minimumCapacityThatCanBeBorrowed := pto.Quantity() / pto.Operation().Throughput(); 
 | 
        unifiedProcessingTimeOfRounding := minvalue( timeDifference, minimumCapacityThatCanBeBorrowed );  
 | 
        debuginfo( "剩余圆整的产能:", timeDifference, "    nextUnitPeriodTimeBase的当前周期任务供应数量:", pto.Quantity(), "    能借的产能:", minimumCapacityThatCanBeBorrowed, " 统一借的产能:", unifiedProcessingTimeOfRounding, "    当前changeover时间:", uptb.ChangeoverDuration().HoursAsReal() );  
 | 
        this.UnifiedProcessingOfRoundingLogic( unifiedProcessingTimeOfRounding, uptb, pto, macroPlan );   
 | 
        timeDifference := timeDifference - unifiedProcessingTimeOfRounding;                                                  
 | 
      } 
 | 
          
 | 
      if ( isnull( nextUnitPeriodTimeBase.Next() ) ) { 
 | 
        nextUnitPeriodTimeBase := select( uptbs, Elements, tempUPTB, tempUPTB.Start() = nextUnitPeriodTimeBase.End() ); 
 | 
      } else { 
 | 
        nextUnitPeriodTimeBase := nextUnitPeriodTimeBase.Next().astype( UnitPeriodTimeBase ); 
 | 
      } 
 | 
    } 
 | 
     
 | 
    if ( ( targetChangeover - sourceChangeover ).HoursAsReal() > 0.0 ) { 
 | 
      this.ZeroCapacityReplenishment( macroPlan, ( targetChangeover - sourceChangeover ).HoursAsReal(), uptb, uptbs ); 
 | 
    } 
 | 
  *] 
 | 
} 
 |