admin
2024-11-11 83ec31b01a61d9a6bc74933572991469eeea4d44
包装计划优化
已添加4个文件
已修改2个文件
518 ■■■■■ 文件已修改
_Main/BL/Type_PackagingPlanCell/StaticMethod_CreateData.qbl 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
_Main/BL/Type_PackagingPlanCell/StaticMethod_GenerateReport.qbl 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
_Main/BL/Type_PackagingPlanCell/StaticMethod_SetPackage_Capacity.qbl 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
_Main/BL/Type_PackagingPlanCell/StaticMethod_SetPackage_Lotsize.qbl 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
_Main/BL/Type_PackagingPlanCell/StaticMethod_SetPackagingAndUnpackingValuesDL.qbl 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
_Main/BL/Type_PackagingPlanCell/StaticMethod_SetUnpackage_Lotsize.qbl 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
_Main/BL/Type_PackagingPlanCell/StaticMethod_CreateData.qbl
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,110 @@
Quintiq file version 2.0
#parent: #root
StaticMethod CreateData (
  MacroPlan macroPlan
)
{
  Description: '创建数据'
  TextBody:
  [*
    macroPlan.PackagingPlanRow( relflush );
    macroPlan.PackagingPlanColumn( relflush );
    // åˆ›å»ºè®¡åˆ’前一天列
    planPre     := macroPlan.PackagingPlanColumn( relnew, StartDate := macroPlan.StartOfPlanning().Date() - 1 );
    // ç”ŸæˆæŠ¥è¡¨
    traverse ( macroPlan, Product_MP.ProductInStockingPoint_MP, pisp, pisp.IsLeaf() and not pisp.IsSystem() and
               ( pisp.StockingPointID().Regex( "CC" ) or pisp.StockingPointID().Regex( "DL" ) or pisp.StockingPointID().Regex( "大连" ) or pisp.StockingPointID().Regex( "长春" ) ) ) {
      // å½“前pisp所处地点
      factory             := ifexpr( pisp.StockingPointID().Regex( "CC" ) or pisp.StockingPointID().Regex( "长春" ), "长春工厂", "大连工厂" );
      factoryAbbreviation := ifexpr( pisp.StockingPointID().Regex( "CC" ) or pisp.StockingPointID().Regex( "长春" ), "CC", "DL" );
      // åˆ›å»ºè¡Œ
      ppr := select( macroPlan, PackagingPlanRow, tempPPR, tempPPR.ProductID() = pisp.ProductID() and tempPPR.Factory() = factory );
      if ( isnull( ppr ) ) {
        ppr := macroPlan.PackagingPlanRow( relnew, ProductID := pisp.ProductID(), Factory := factory, Category := guard( pisp.Product_MP().ParentID(), "" ) );
      }
      // å¾ªçޝpispippl
      traverse ( pisp, ProductInStockingPointInPeriodPlanning.astype( ProductInStockingPointInPeriodPlanningLeaf ), pispipl, not pispipl.IsPeriodFrozen() ) {
        // åˆ›å»ºåˆ—
        ppc := select( macroPlan, PackagingPlanColumn, tempPPC, tempPPC.StartDate() = pispipl.Start().Date() );
        if ( isnull( ppc ) ) {
          ppc := macroPlan.PackagingPlanColumn( relnew, StartDate := pispipl.Start().Date() );
        }
        // åˆ›å»ºå•元格
        cell := select( ppr, PackagingPlanCell, tempPPCell, tempPPCell.PackagingPlanColumn() = ppc );
        if ( isnull( cell ) ) {
          cell := ppr.PackagingPlanCell( relnew );
          cell.PackagingPlanColumn( relset, ppc );
        }
        // è®¾ç½®è°ƒå‡º
        traverse ( pispipl, AsDeparturePISPIP, pit,
                   pit.Quantity()                > 0                                                                         and
                   pit.Trip().LaneLeg().AsOriginStockingPointLeg().StockingPoint_MP().ID().Regex( factoryAbbreviation )      and
                   TransferPlanRow::IdentifyTheFactory( pit.Trip().LaneLeg().AsOriginStockingPointLeg().StockingPoint_MP() ) <> TransferPlanRow::IdentifyTheFactory( pit.Trip().LaneLeg().AsDestinationStockingPointLeg().StockingPoint_MP() )
                  )
        {
          cell.Out( cell.Out() + pit.Quantity() );
        }
        // è®¾ç½®è°ƒè¿›
        traverse ( pispipl, AsArrivalPISPIP, pit,
                   pit.Quantity()              > 0                                                                           and
                   pit.Trip().LaneLeg().AsDestinationStockingPointLeg().StockingPoint_MP().ID().Regex( factoryAbbreviation ) and
                   TransferPlanRow::IdentifyTheFactory( pit.Trip().LaneLeg().AsOriginStockingPointLeg().StockingPoint_MP() ) <> TransferPlanRow::IdentifyTheFactory( pit.Trip().LaneLeg().AsDestinationStockingPointLeg().StockingPoint_MP() )
                  )
        {
          cell.TransferIn( cell.TransferIn() + pit.Quantity() );
        }
        // å¤§è¿žå·¥åŽ‚è®¾ç½®å€¼
        if ( factory = "大连工厂" ) {
          // å‡€éœ€æ±‚&剩余库存&供应量
          cell.NetDemand( cell.NetDemand() + pispipl.DependentDemandAndSalesDemandQuantity() );
          cell.EndingInventory( cell.EndingInventory() + pispipl.InventoryLevelEnd() );
        }
        // é•¿æ˜¥å·¥åŽ‚è®¾ç½®å€¼
        if ( factory = "长春工厂" ) {
          // å‰©ä½™åº“å­˜&供应量
          cell.EndingInventory( cell.EndingInventory() + pispipl.InventoryLevelEnd() );
          // å‡€éœ€æ±‚【只取线边库】&包装库存&非包装库存
          if ( pisp.StockingPointID().Regex( "外租库" ) ) {
            cell.CC_PackagingInventory( pispipl.InventoryLevelEnd() );
          } else if ( pisp.StockingPointID().Regex( "线边库" ) ) {
            cell.CC_UnpackagedInventory( pispipl.InventoryLevelEnd() );
            cell.NetDemand( cell.NetDemand() + pispipl.DependentDemandAndSalesDemandQuantity() );
          }
        }
        // è®¾ç½®New Supply,纯生产值
        traverse ( pispipl, NewSupply, ns, ns.PeriodTask_MP().istype( PeriodTaskOperation ) ) {
          cell.NewSupply( cell.NewSupply() + ns.Quantity() );
        }
        // è®¾ç½®å‰ä¸€å¤©åº“å­˜
        if ( pispipl.Start().Date() = macroPlan.StartOfPlanning().Date() ) {
          prePISPIPL  := pispipl.PreviousPlanningPISPIP().astype( ProductInStockingPointInPeriodPlanningLeaf ); // å‰ä¸€ä¸ªpispippl
          // åˆ›å»ºè®¡åˆ’前一天格子
          preCell := select( ppr, PackagingPlanCell, tempPPCell, tempPPCell.PackagingPlanColumn() = planPre );
          if ( isnull( preCell ) ) {
            preCell := ppr.PackagingPlanCell( relnew );
            preCell.EndingInventory( prePISPIPL.InventoryLevelEnd() );
            preCell.PackagingPlanColumn( relset, planPre );
          } else {
            preCell.EndingInventory( preCell.EndingInventory() + prePISPIPL.InventoryLevelEnd() );
          }
        }
      }
    }
    Transaction::Transaction().Propagate( attribute( PackagingPlanRow, FactoryAbbreviation ) );
    PackagingPlanCell::CalculationPackagingPlanProperties();
    Transaction::Transaction().Propagate( relation( PackagingPlanCell, Next ) );
  *]
}
_Main/BL/Type_PackagingPlanCell/StaticMethod_GenerateReport.qbl
@@ -6,110 +6,15 @@
{
  TextBody:
  [*
    macroPlan.PackagingPlanRow( relflush );
    macroPlan.PackagingPlanColumn( relflush );
    // åˆ›å»ºè®¡åˆ’前一天列
    planPre     := macroPlan.PackagingPlanColumn( relnew, StartDate := macroPlan.StartOfPlanning().Date() - 1 );
    // ç”ŸæˆæŠ¥è¡¨
    traverse ( macroPlan, Product_MP.ProductInStockingPoint_MP, pisp, pisp.IsLeaf() and not pisp.IsSystem() and
               ( pisp.StockingPointID().Regex( "CC" ) or pisp.StockingPointID().Regex( "DL" ) or pisp.StockingPointID().Regex( "大连" ) or pisp.StockingPointID().Regex( "长春" ) ) ) {
      // å½“前pisp所处地点
      factory             := ifexpr( pisp.StockingPointID().Regex( "CC" ) or pisp.StockingPointID().Regex( "长春" ), "长春工厂", "大连工厂" );
      factoryAbbreviation := ifexpr( pisp.StockingPointID().Regex( "CC" ) or pisp.StockingPointID().Regex( "长春" ), "CC", "DL" );
      // åˆ›å»ºè¡Œ
      ppr := select( macroPlan, PackagingPlanRow, tempPPR, tempPPR.ProductID() = pisp.ProductID() and tempPPR.Factory() = factory );
      if ( isnull( ppr ) ) {
        ppr := macroPlan.PackagingPlanRow( relnew, ProductID := pisp.ProductID(), Factory := factory, Category := guard( pisp.Product_MP().ParentID(), "" ) );
      }
      // å¾ªçޝpispippl
      traverse ( pisp, ProductInStockingPointInPeriodPlanning.astype( ProductInStockingPointInPeriodPlanningLeaf ), pispipl, not pispipl.IsPeriodFrozen() ) {
        // åˆ›å»ºåˆ—
        ppc := select( macroPlan, PackagingPlanColumn, tempPPC, tempPPC.StartDate() = pispipl.Start().Date() );
        if ( isnull( ppc ) ) {
          ppc := macroPlan.PackagingPlanColumn( relnew, StartDate := pispipl.Start().Date() );
        }
        // åˆ›å»ºå•元格
        cell := select( ppr, PackagingPlanCell, tempPPCell, tempPPCell.PackagingPlanColumn() = ppc );
        if ( isnull( cell ) ) {
          cell := ppr.PackagingPlanCell( relnew );
          cell.PackagingPlanColumn( relset, ppc );
        }
        // è®¾ç½®è°ƒå‡º
        traverse ( pispipl, AsDeparturePISPIP, pit,
                   pit.Quantity()                > 0                                                                         and
                   pit.Trip().LaneLeg().AsOriginStockingPointLeg().StockingPoint_MP().ID().Regex( factoryAbbreviation )      and
                   TransferPlanRow::IdentifyTheFactory( pit.Trip().LaneLeg().AsOriginStockingPointLeg().StockingPoint_MP() ) <> TransferPlanRow::IdentifyTheFactory( pit.Trip().LaneLeg().AsDestinationStockingPointLeg().StockingPoint_MP() )
                  )
        {
          cell.Out( cell.Out() + pit.Quantity() );
        }
        // è®¾ç½®è°ƒè¿›
        traverse ( pispipl, AsArrivalPISPIP, pit,
                   pit.Quantity()              > 0                                                                           and
                   pit.Trip().LaneLeg().AsDestinationStockingPointLeg().StockingPoint_MP().ID().Regex( factoryAbbreviation ) and
                   TransferPlanRow::IdentifyTheFactory( pit.Trip().LaneLeg().AsOriginStockingPointLeg().StockingPoint_MP() ) <> TransferPlanRow::IdentifyTheFactory( pit.Trip().LaneLeg().AsDestinationStockingPointLeg().StockingPoint_MP() )
                  )
        {
          cell.TransferIn( cell.TransferIn() + pit.Quantity() );
        }
        // å¤§è¿žå·¥åŽ‚è®¾ç½®å€¼
        if ( factory = "大连工厂" ) {
          // å‡€éœ€æ±‚&剩余库存&供应量
          cell.NetDemand( cell.NetDemand() + pispipl.DependentDemandAndSalesDemandQuantity() );
          cell.EndingInventory( cell.EndingInventory() + pispipl.InventoryLevelEnd() );
        }
        // é•¿æ˜¥å·¥åŽ‚è®¾ç½®å€¼
        if ( factory = "长春工厂" ) {
          // å‰©ä½™åº“å­˜&供应量
          cell.EndingInventory( cell.EndingInventory() + pispipl.InventoryLevelEnd() );
          // å‡€éœ€æ±‚【只取线边库】&包装库存&非包装库存
          if ( pisp.StockingPointID().Regex( "外租库" ) ) {
            cell.CC_PackagingInventory( pispipl.InventoryLevelEnd() );
          } else if ( pisp.StockingPointID().Regex( "线边库" ) ) {
            cell.CC_UnpackagedInventory( pispipl.InventoryLevelEnd() );
            cell.NetDemand( cell.NetDemand() + pispipl.DependentDemandAndSalesDemandQuantity() );
          }
        }
        // è®¾ç½®New Supply,纯生产值
        traverse ( pispipl, NewSupply, ns, ns.PeriodTask_MP().istype( PeriodTaskOperation ) ) {
          cell.NewSupply( cell.NewSupply() + ns.Quantity() );
        }
        // è®¾ç½®å‰ä¸€å¤©åº“å­˜
        if ( pispipl.Start().Date() = macroPlan.StartOfPlanning().Date() ) {
          prePISPIPL  := pispipl.PreviousPlanningPISPIP().astype( ProductInStockingPointInPeriodPlanningLeaf ); // å‰ä¸€ä¸ªpispippl
          // åˆ›å»ºè®¡åˆ’前一天格子
          preCell := select( ppr, PackagingPlanCell, tempPPCell, tempPPCell.PackagingPlanColumn() = planPre );
          if ( isnull( preCell ) ) {
            preCell := ppr.PackagingPlanCell( relnew );
            preCell.EndingInventory( prePISPIPL.InventoryLevelEnd() );
            preCell.PackagingPlanColumn( relset, planPre );
          } else {
            preCell.EndingInventory( preCell.EndingInventory() + prePISPIPL.InventoryLevelEnd() );
          }
        }
      }
    }
    Transaction::Transaction().Propagate( attribute( PackagingPlanRow, FactoryAbbreviation ) );
    PackagingPlanCell::CalculationPackagingPlanProperties();
    Transaction::Transaction().Propagate( relation( PackagingPlanCell, Next ) );
    // åˆ›å»ºæ•°æ®
    PackagingPlanCell::CreateData( macroPlan );
    
    // è®¾ç½®åŒ…装&拆包-数量(大连工厂)
    PackagingPlanCell::SetPackagingAndUnpackingValuesDL( macroPlan );
    // è®¾ç½®åŒ…装&拆包-数量(长春工厂)
    PackagingPlanCell::SetPackagingAndUnpackingValuesCC( macroPlan );
    //traverse ( macroPlan, PackagingPlanRow, ppr, ( ppr.ProductID() = "Windshield" and ppr.StockingPointID() = "Bosch" ) or ( ppr.ProductID() = "Windshield" and ppr.StockingPointID() = "Components (Spain)" ) ) {
    //  traverse ( ppr, PackagingPlanCell, ppc/*, ppc.StartDate() = Date::Construct( 2020, 4, 1 )*/ ) {
    //    // è®¾ç½®åŒ…装数量
_Main/BL/Type_PackagingPlanCell/StaticMethod_SetPackage_Capacity.qbl
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,44 @@
Quintiq file version 2.0
#parent: #root
StaticMethod SetPackage_Capacity (
  MacroPlan macroPlan
)
{
  TextBody:
  [*
    // è®¡åˆ’开始时间
    plannedStartDate := macroPlan.StartOfPlanning().Date();
    // è®¾ç½®åŒ…装值(符合大类下所有产品非包装量库存加和不能大于系统值)
    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 );
            }
          }
        }
      }
    }
  *]
}
_Main/BL/Type_PackagingPlanCell/StaticMethod_SetPackage_Lotsize.qbl
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,63 @@
Quintiq file version 2.0
#parent: #root
StaticMethod SetPackage_Lotsize (
  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();
          }
        }
      }
    }
  *]
}
_Main/BL/Type_PackagingPlanCell/StaticMethod_SetPackagingAndUnpackingValuesDL.qbl
@@ -6,141 +6,13 @@
{
  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();
          }
        }
      }
    }
    PackagingPlanCell::SetPackage_Lotsize( macroPlan );
    
    // è®¾ç½®åŒ…装值(符合大类下所有产品非包装量库存加和不能大于系统值)
    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 );
            }
          }
        }
      }
    }
    PackagingPlanCell::SetPackage_Capacity( macroPlan );
    
    // è®¾ç½®æ‹†åŒ…值(符合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();
          }
        }
      }
    }
    PackagingPlanCell::SetUnpackage_Lotsize( macroPlan );
  *]
}
_Main/BL/Type_PackagingPlanCell/StaticMethod_SetUnpackage_Lotsize.qbl
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,64 @@
Quintiq file version 2.0
#parent: #root
StaticMethod SetUnpackage_Lotsize (
  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() ) );
        // å½“前非包装库存 + ä¸‹ä¸€å¤©çš„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();
            canPackagingQuantity := minvalue( canPackagingQuantity, [Number]indexPPCell.PackagingInventory() );
    //        info( "开始包装的日期:", indexPPCell.StartDate().Format( "Y-M2-D2" ), "    èƒ½åŒ…装的数量:", canPackagingQuantity );
            indexPPCell.Next().Unpacking( canPackagingQuantity );
            Transaction::Transaction().Propagate( attribute( PackagingPlanCell, PackagingInventory ) );
            Transaction::Transaction().Propagate( attribute( PackagingPlanCell, UnpackagedInventory ) );
            needPackagingQuantity := needPackagingQuantity - canPackagingQuantity;
            indexPPCell           := indexPPCell.Previous();
          }
        }
      }
    }
  *]
}