admin
2025-01-22 7e31442f0e9b07764e9c6a9680d3d4aeba5fe1de
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
Quintiq file version 2.0
#parent: #root
StaticMethod RefreshOfflinePlan (
  MacroPlan macroPlan
)
{
  TextBody:
  [*
    macroPlan.NewOfflinePlanTable( relflush );
    
    nopt         := macroPlan.NewOfflinePlanTable( relnew, SaveDateTime := DateTime::ActualTime() );
    
    // 计划开始时间
    planningDate := macroPlan.StartOfPlanning().Date() 
    
    // 初始化下线计划列
    traverse ( macroPlan, Period_MP, pmp, pmp.IsPlanning() and not pmp.IsHistorical() ) {
      nopt.NewOfflinePlanColumn( relnew, StartDate := pmp.StartDate(), EndDate := pmp.EndDate() );
    }
    
    // 生成下线计划表【一条产线在同一天不会产生两次相同产品的周期任务】
    traverse ( macroPlan, Unit, u, u.HasCapacityTypeTime() 
    //           and u.Name() = "eMotor Assy (France)" // 测试本地场景时可以过滤
    //           and u.Name() = "DL-MoMo"              // 测试实际场景时可以过滤
              ) 
    {
      // 循环遍历周期任务的NewSupply【生成明细下线计划】
      traverse ( u, Operation, o ) {
        traverse ( o, PeriodTaskOperation.NewSupply, ns ) {
          // ProductInStockingPoint_MP
          pisp     := ns.AsProductionSupply().ProductInStockingPoint_MP();
          // ProductInStockingPointInPeriodPlanningLeaf
          pispippl := ns.ProductInStockingPointInPeriodPlanningLeaf();
          // Period_MP
          pmp      := pispippl.Period_MP();
          // ShiftPattern
          sp       := ns.PeriodTask_MP().UnitPeriod().astype( UnitPeriodTimeBase ).ShiftPattern();
          // ShiftDayTime
          sdt      := select( sp, ShiftDayTime, tempSDT, tempSDT.Name() = tempSDT.ShiftPattern().Name() );
          
          // 生成下线计划【产线明细】行
          detailedNOPR   := select( nopt, NewOfflinePlanRow, tempNOPR, tempNOPR.ProductionLine() = u.ID() and tempNOPR.ProductID() = pisp.ProductID() and tempNOPR.StockingPointID() = pisp.StockingPointID() and tempNOPR.Type() = "1" );
          if ( isnull( detailedNOPR ) ) {
            detailedNOPR := nopt.NewOfflinePlanRow( relnew, ProductionLine := u.ID(), ProductID := pisp.ProductID(),StockingPointID := pisp.StockingPointID(), Type := "1", OperationID := o.ID() );
          }
          
          // 生成下线计划列
          nopc   := select( nopt, NewOfflinePlanColumn, tempNOPC, tempNOPC.StartDate() = pmp.StartDate() and tempNOPC.EndDate() = pmp.EndDate() );
          if ( isnull( nopc ) ) {
            nopc := nopt.NewOfflinePlanColumn( relnew, StartDate := pmp.StartDate(), EndDate := pmp.EndDate() );
          }
          
          // 生成下线计划【产线明细】单元格
          detaileNOPCell := select( detailedNOPR, NewOfflinePlanCell, tempNOPCell, tempNOPCell.NewOfflinePlanColumn() = nopc );
          if ( isnull ( detaileNOPCell ) ) {
            detaileNOPCell := detailedNOPR.NewOfflinePlanCell( relnew, 
                                                               Quantity          := ns.Quantity().Round( 0 ), 
                                                               InventoryWeight   := pispippl.InventoryLevelEnd() - pispippl.MinInventoryLevel(),
                                                               ShiftPatternName  := guard( sp.Name(), "" ),
                                                               ShiftPatternStart := guard( sdt.StartDateTime().Format( "H:m" ), "" ),
                                                               ShiftPatternEnd   := guard( sdt.EndDateTIme().Format( "H:m" ), "" ) );
            detaileNOPCell.NewOfflinePlanColumn( relset, nopc );
          }
        }
      }
      
      // 补齐空格子
      traverse ( nopt, NewOfflinePlanRow, nopr ) {
        traverse ( nopt, NewOfflinePlanColumn, nopc ) {
          cell   := select( nopr, NewOfflinePlanCell, tempNOPCell, tempNOPCell.NewOfflinePlanColumn() = nopc );
          if ( isnull( cell ) ) {
            uptb := select( macroPlan, Unit.UnitPeriod.astype( UnitPeriodTimeBase ), tempUPTB, 
                            tempUPTB.UnitID() = nopr.ProductionLine() and tempUPTB.StartDate() = nopc.StartDate() and tempUPTB.End().Date() = nopc.EndDate() );
            // ShiftPattern
            sp   := uptb.ShiftPattern();
            // ShiftDayTime
            sdt  := select( sp, ShiftDayTime, tempSDT, tempSDT.Name() = tempSDT.ShiftPattern().Name() );
            cell := nopr.NewOfflinePlanCell( relnew, 
                                             ShiftPatternName  := guard( sp.Name(), "" ), 
                                             ShiftPatternStart := guard( sdt.StartDateTime().Format( "H:m" ), "" ),
                                             ShiftPatternEnd   := guard( sdt.EndDateTIme().Format( "H:m" ), "" ) );
            cell.NewOfflinePlanColumn( relset, nopc );
          }
        }
      }
      
      // 【生成合计下线计划】
      totalNOPR   := nopt.NewOfflinePlanRow( relnew, ProductID := "All", ProductionLine := u.ID(), Type := "2" );
      detailNOPRs := selectset( nopt, NewOfflinePlanRow, tempNOPR, tempNOPR.ProductionLine() = u.ID() and tempNOPR.Type() = "1" );
      traverse ( detailNOPRs, Elements, detailNOPR ) {
        traverse ( detailNOPR, NewOfflinePlanCell, detailNOPCell ) {
          // 生产下线计划【产线合计】单元格
          totalNOPRCell   := select( totalNOPR, NewOfflinePlanCell, tempNOPCell, tempNOPCell.NewOfflinePlanColumn() = detailNOPCell.NewOfflinePlanColumn() );
          if ( isnull( totalNOPRCell ) ) {
            totalNOPRCell := totalNOPR.NewOfflinePlanCell( relnew, 
                                                           ShiftPatternName  := detailNOPCell.ShiftPatternName(),
                                                           ShiftPatternStart := detailNOPCell.ShiftPatternStart(),
                                                           ShiftPatternEnd   := detailNOPCell.ShiftPatternEnd() );
            totalNOPRCell.NewOfflinePlanColumn( relset, detailNOPCell.NewOfflinePlanColumn() ); // 设置列
            // 将明细单元格关联到合计单元格
            totalNOPRCell.Detailed( relinsert, detailNOPCell );
          } else {
            // 将明细单元格关联到合计单元格
            totalNOPRCell.Detailed( relinsert, detailNOPCell );
          }
        }
      }
      
      // 设置生产顺序【对下线计划明细生效】
      indexColumn    := select( nopt, NewOfflinePlanColumn, tempNOPC, tempNOPC.StartDate() = planningDate );
      previousColumn := indexColumn.PreviousNOPColumn();
      nextColumn     := indexColumn.NextNOPColumn();
      while ( not isnull( indexColumn.NextNOPColumn() )
    //          and indexColumn.ColumnDate() <= Date::Construct( 2020, 4, 1 ) // 测试实际场景时可以过滤
             ) 
      {
        orderNr     := 1;
        nopcells    := selectsortedset( indexColumn, NewOfflinePlanCell, tempNOPCell, tempNOPCell.FindProductionLineAndType( u.ID(), "1" ), tempNOPCell.InventoryWeight() );
        initialSize := nopcells.Size();
    //    info( "计划开始时间:", planningDate.Format( "Y-M2-D2" ), "    索引时间:", indexColumn.StartDate().Format( "Y-M2-D2" ), "    个数:", nopcells.Size() );
        
        if ( nopcells.Size() > 0 ) {
        
          // 判定1
          previousOPCell := maxselect( previousColumn, NewOfflinePlanCell, tempNOPCell, tempNOPCell.FindProductionLineAndType( u.ID(), "1" ), tempNOPCell.OrderNr() );
          if ( isnull( previousOPCell ) or indexColumn.StartDate() = planningDate ) {
            nopcell := nopcells.Element( 0 );
            nopcell.Order( "#" + orderNr.Format( "N(LPad0(2))" ) );
            nopcell.OrderNr( orderNr );
            orderNr++;
            nopcells.Remove( nopcell );
          } else {
            nopcell := select( nopcells, Elements, tempNOPCell, tempNOPCell.NewOfflinePlanRow().ProductID() =  previousOPCell.NewOfflinePlanRow().ProductID() );
            if ( not isnull( nopcell ) ) {
              nopcell.Order( "#" + orderNr.Format( "N(LPad0(2))" ) );
              nopcell.OrderNr( orderNr );
              orderNr++;
              nopcells.Remove( nopcell );
            }
          }
          
          // 判定2
          nextNOPCells := selectset( nopcells, Elements, tempOPC,
                                     exists( nextColumn, NewOfflinePlanCell, nextOPCell, nextOPCell.FindProductionLineAndType( u.ID(), "1" ) and 
                                             nextOPCell.NewOfflinePlanRow().ProductID() = tempOPC.NewOfflinePlanRow().ProductID() ) ); // 找下一列是否有当前列生产的产品
          if ( nextNOPCells.Size() = 1 ) {
            nopcell := nextNOPCells.Element( 0 );
            nopcell.Order( "#" + initialSize.Format( "N(LPad0(2))" ) );
            nopcell.OrderNr( initialSize );
            nopcells.Remove( nopcell );
          }
          
          // 判定3
          traverse ( nopcells, Elements, opcell ) {
            opcell.Order( "#" + orderNr.Format( "N(LPad0(2))" ) );
            opcell.OrderNr( orderNr );
            orderNr++;
            nopcells.Remove( opcell );
          }
        }
        
        indexColumn    := indexColumn.NextNOPColumn();
        previousColumn := indexColumn.PreviousNOPColumn();
        nextColumn     := indexColumn.NextNOPColumn();
      }
    }
  *]
}