| Quintiq file version 2.0 | 
| #parent: #root | 
| StaticMethod SetPackagingAndUnpackingValues ( | 
|   MacroPlan macroPlan | 
| ) | 
| { | 
|   TextBody: | 
|   [* | 
|     // 计划开始时间 | 
|     plannedStartDate := macroPlan.StartOfPlanning().Date(); | 
|      | 
|     // 设置包装值(符合lotsize和一日最大包装量) | 
|     traverse ( macroPlan, PackagingPlanRow, ppr/*, ppr.Factory() = "大连工厂" and ppr.ProductID() = "06K103011CM"*/ ) { | 
|       traverse ( ppr, PackagingPlanCell, ppcell/*, ppcell.StartDate() <= Date::Construct( 2025, 1, 4 )*/ ) { | 
|         // Product_MP | 
|         pmp                     := select( macroPlan, Product_MP, tempPMP, tempPMP.IsLeaf() and tempPMP.ID() = ppr.ProductID() ); | 
|         // 包装lotsize | 
|         ppls                    := select( macroPlan, PackagingPlanLotSize, tempPPLS, tempPPLS.Factory() = ppr.Factory() and  | 
|                                            tempPPLS.ProductID() = ifexpr( exists( macroPlan, PackagingPlanLotSize, tempPPLS1, tempPPLS1.ProductID() = pmp.ID() ), | 
|                                                                           pmp.ID(), | 
|                                                                           pmp.ParentID() ) ); | 
|         // 一日包装容量 | 
|         ppnc                    := select( macroPlan, PackagingPlanNewCapability, tempPPNC, tempPPNC.Factory() = ppr.Factory() and  | 
|                                            tempPPNC.ProductID() = ifexpr( exists( macroPlan, PackagingPlanNewCapability, tempPPNC1, tempPPNC1.ProductID() = pmp.ID() ), | 
|                                                                           pmp.ID(), | 
|                                                                           pmp.ParentID() ) ); | 
|         // Unit | 
|         us                      := selectset( macroPlan, Unit, tempU, tempU.ID().Regex( ppr.FactoryAbbreviation() + " " + ppr.Category() ) ); | 
|           | 
|         // 包装库存出现负值,需要设置包装量 | 
|         if ( ppcell.PackagingInventory() < 0 and not isnull( ppls ) and not isnull( ppnc ) ) { | 
|           // 需要包装的数量 | 
|           needPackagingQuantity := abs( ppcell.PackagingInventory() ).Round( 0 ); | 
|           // 包装开始的索引 | 
|           indexPPCell           := ppcell.Previous(); | 
|            | 
|     //      info( "产线个数:", us.Size(), "    开始时间:", ppcell.StartDate().Format( "Y-M2-D2" ), "    包装库存数量:", ppcell.PackagingInventory(), "    需要包装的数量:", needPackagingQuantity,  | 
|     //            "    包装lotsize:",guard( ppls.LotSize(), 0 ), "    最大包装容量:", ppnc.MaximumDailyPackagingQuantity() ); | 
|            | 
|           while ( not isnull( indexPPCell )                                                   and  | 
|                   indexPPCell.StartDate() >= plannedStartDate                                 and  | 
|                   exists( us, Elements.UnitPeriod.astype( UnitPeriodTime ).ShiftPlan, tempSP,  | 
|                           tempSP.UnitPeriodTime().StartDate() = indexPPCell.StartDate(), | 
|                           tempSP.Outcome() <> "" )                                            and | 
|                   needPackagingQuantity > 0 ) { | 
|             // 能包装的数量 | 
|             canPackagingQuantity  := ifexpr( ceil( needPackagingQuantity / ppls.LotSize() ) < floor( ppnc.MaximumDailyPackagingQuantity() / ppls.LotSize() ), | 
|                                              ceil( needPackagingQuantity / ppls.LotSize() ), | 
|                                              floor( ppnc.MaximumDailyPackagingQuantity() / ppls.LotSize() ) ) * ppls.LotSize(); | 
|     //        info( "开始包装的日期:", indexPPCell.StartDate().Format( "Y-M2-D2" ), "    能包装的数量:", canPackagingQuantity ); | 
|              | 
|             indexPPCell.Package( canPackagingQuantity ); | 
|             Transaction::Transaction().Propagate( attribute( PackagingPlanCell, PackagingInventory ) ); | 
|             Transaction::Transaction().Propagate( attribute( PackagingPlanCell, UnpackagedInventory ) ); | 
|              | 
|             needPackagingQuantity := needPackagingQuantity - canPackagingQuantity; | 
|             indexPPCell           := indexPPCell.Previous(); | 
|           } | 
|         } | 
|       } | 
|     } | 
|      | 
|     // 设置包装值(符合大类下所有产品非包装量库存加和不能大于系统值) | 
|     factorys               := selectuniquevalues( macroPlan, PackagingPlanRow, tempPPR, true, tempPPR.FactoryAbbreviation() ); | 
|     categorys              := selectuniquevalues( macroPlan, PackagingPlanRow, tempPPR, true, tempPPR.Category() ); | 
|     traverse ( factorys, Elements, f/*, f = "DL"*/ ) { | 
|       traverse ( categorys, Elements, c/*, c = "ZKG"*/ ) { | 
|         // 系统规定的最大非包装库存数量 | 
|         ppmqReflection     := Reflection::FindAttribute( "PackagingPlanMaximumQuantity", f + "_" + c ); | 
|         maxPackageQuantity := guard( ppmqReflection.GetNumber( macroPlan.PackagingPlanMaximumQuantity() ), 0 ); | 
|         // 当前工厂下一类产品行 | 
|         pprs               := selectset( macroPlan, PackagingPlanRow, tempPPR, tempPPR.FactoryAbbreviation() = f and tempPPR.Category() = c ); | 
|           | 
|     //    info( "当前工厂:", f, "    当前大类:", c, "    大类下的最大包装数量:", maxPackageQuantity ); | 
|         traverse ( macroPlan, PackagingPlanColumn, ppc, ppc.StartDate() > plannedStartDate and maxPackageQuantity > 0 ) { | 
|           sumUnpackagedInventoryQuantity := sum( pprs, Elements.PackagingPlanCell, tempPPCell, tempPPCell.PackagingPlanColumn() = ppc, tempPPCell.UnpackagedInventory() ).Round( 0 ); | 
|            | 
|           // 需要包装 | 
|           if ( sumUnpackagedInventoryQuantity > maxPackageQuantity ) { | 
|             // 需要包装的数量 | 
|             needPackagingQuantity := [Number] ( sumUnpackagedInventoryQuantity - maxPackageQuantity ); | 
|             // 按非包装库存排序后的行 | 
|             itemPPRs              := selectsortedset( pprs, Elements, tempPPR, true,  | 
|                                                       -select( tempPPR, PackagingPlanCell, tempPPCell, tempPPCell.PackagingPlanColumn() = ppc ).UnpackagedInventory() ); | 
|              | 
|     //        info( "需要包装时间:", ppc.StartDate().Format( "Y-M2-D2" ), "    需要包装的数量:", needPackagingQuantity ); | 
|             traverse ( itemPPRs, Elements, ppr, needPackagingQuantity > 0 ) { | 
|               PackagingPlanCell::Package( macroPlan, ppr, ppc, needPackagingQuantity ); | 
|             } | 
|           } | 
|         } | 
|       } | 
|     } | 
|      | 
|     // 设置拆包值(符合lotsize和一日最大包装量) | 
|     traverse ( macroPlan, PackagingPlanRow, ppr/*, ppr.Factory() = "大连工厂" and ppr.ProductID() = "06K103011CM"*/ ) { | 
|       traverse ( ppr, PackagingPlanCell, ppcell/*, ppcell.StartDate() <= Date::Construct( 2025, 1, 4 )*/ ) { | 
|         // Product_MP | 
|         pmp                     := select( macroPlan, Product_MP, tempPMP, tempPMP.IsLeaf() and tempPMP.ID() = ppr.ProductID() ); | 
|         // 包装lotsize | 
|         ppls                    := select( macroPlan, PackagingPlanLotSize, tempPPLS, tempPPLS.Factory() = ppr.Factory() and  | 
|                                            tempPPLS.ProductID() = ifexpr( exists( macroPlan, PackagingPlanLotSize, tempPPLS1, tempPPLS1.ProductID() = pmp.ID() ), | 
|                                                                           pmp.ID(), | 
|                                                                           pmp.ParentID() ) ); | 
|         // 一日包装容量 | 
|         ppnc                    := select( macroPlan, PackagingPlanNewCapability, tempPPNC, tempPPNC.Factory() = ppr.Factory() and  | 
|                                            tempPPNC.ProductID() = ifexpr( exists( macroPlan, PackagingPlanNewCapability, tempPPNC1, tempPPNC1.ProductID() = pmp.ID() ), | 
|                                                                           pmp.ID(), | 
|                                                                           pmp.ParentID() ) ); | 
|         // Unit | 
|         us                      := selectset( macroPlan, Unit, tempU, tempU.ID().Regex( ppr.FactoryAbbreviation() + " " + ppr.Category() ) ); | 
|           | 
|         // 当前非包装库存 + 下一天的NewSupply < 下一天的净需求 | 
|         if ( ppcell.UnpackagedInventory() < guard( ppcell.Next().NetDemand(), 0 ) and not isnull( ppls ) and not isnull( ppnc ) ) { | 
|           // 需要包装的数量 | 
|           needPackagingQuantity := abs( ppcell.PackagingInventory() ).Round( 0 ); | 
|           // 包装开始的索引 | 
|           indexPPCell           := ppcell.Previous(); | 
|            | 
|     //      info( "产线个数:", us.Size(), "    开始时间:", ppcell.StartDate().Format( "Y-M2-D2" ), "    包装库存数量:", ppcell.PackagingInventory(), "    需要包装的数量:", needPackagingQuantity,  | 
|     //            "    包装lotsize:",guard( ppls.LotSize(), 0 ), "    最大包装容量:", ppnc.MaximumDailyPackagingQuantity() ); | 
|            | 
|           while ( not isnull( indexPPCell )                                                   and  | 
|                   indexPPCell.StartDate() >= plannedStartDate                                 and  | 
|                   exists( us, Elements.UnitPeriod.astype( UnitPeriodTime ).ShiftPlan, tempSP,  | 
|                           tempSP.UnitPeriodTime().StartDate() = indexPPCell.StartDate(), | 
|                           tempSP.Outcome() <> "" )                                            and | 
|                   needPackagingQuantity > 0 ) { | 
|             // 能包装的数量 | 
|             canPackagingQuantity  := ifexpr( ceil( needPackagingQuantity / ppls.LotSize() ) < floor( ppnc.MaximumDailyPackagingQuantity() / ppls.LotSize() ), | 
|                                              ceil( needPackagingQuantity / ppls.LotSize() ), | 
|                                              floor( ppnc.MaximumDailyPackagingQuantity() / ppls.LotSize() ) ) * ppls.LotSize(); | 
|     //        info( "开始包装的日期:", indexPPCell.StartDate().Format( "Y-M2-D2" ), "    能包装的数量:", canPackagingQuantity ); | 
|              | 
|             indexPPCell.Package( canPackagingQuantity ); | 
|             Transaction::Transaction().Propagate( attribute( PackagingPlanCell, PackagingInventory ) ); | 
|             Transaction::Transaction().Propagate( attribute( PackagingPlanCell, UnpackagedInventory ) ); | 
|              | 
|             needPackagingQuantity := needPackagingQuantity - canPackagingQuantity; | 
|             indexPPCell           := indexPPCell.Previous(); | 
|           } | 
|         } | 
|       } | 
|     } | 
|   *] | 
| } |