粗排引擎 Functional Spec ⇄ 舊版 ScheduleEngine_wo 比對報告

可讀性重排版:整篇套「白話上層 + 密表深究層」的架構,內容沿用原報告、未重新查證。原檔在 rough-cut-scheduler-spec-vs-legacy.md

產出日期:2026-06-08。性質:一次性比對,不改任何程式碼、不做裁定。 比對對象 A(基準):新版 functional spec functional-spec/rough-cut-scheduler.md(已簽核;2026-06-04 修正上游 JIT 拉動、廢棄 §RCS-FS-10)。 比對對象 B(現役實作):Lean-Scheduling/src/main/java/.../ScheduleEngine_wo.java(2350 行);佐證 LatestStartCalculator.javaVSMUtil.javaStdScheduleKanbanSorter.java


0. 大綱

排程分粗細兩層:

  • 粗排:先決定每張單「大概哪幾天做」。像排行事曆,只看哪天有空、趕不趕得上交期,不管細節。
  • 細排:再決定「哪台機台、幾點到幾點做」。

這份報告只比粗排,對象是兩支引擎:

  • A・新 spec:新訂的粗排引擎規格。定位是「純試算」:只算出每張單該落在哪幾天,不動真的產能、不寫回資料庫,算完就丟。處理單位是**投產單**(一筆「某產品、某數量、某交期」的生產要求)。
  • B・舊程式 ScheduleEngine_wo:現役那支 2350 行的引擎。它把粗排細排寫在一起,靠一個開關切換,而且會真的吃掉產能、把結果寫回去。

總結:兩者不是同一種東西。 新 spec 是「只算日期、不留痕跡」的輕量試算;舊程式是「算完就把產能佔掉」的重型引擎。

報告分兩個方向進行:一是新 spec 有沒有漏掉舊版該有的粗排能力,二是舊版有沒有多出 spec 沒提到的東西。重點是把查到的差異分成兩類:哪些是故意的、需要決議,哪些是真的對不上、得修正


1. 兩支引擎的根本定位

逐項比之前先對齊框架。新 spec 是「投產單級、純試算、只產日期」的獨立粗排引擎;舊程式是「工單級、會落地、粗細合一」的重型引擎。六個面向並排如下:

面向新 spec舊版 ScheduleEngine_wo
引擎範圍獨立粗排引擎(細排的 input 之一)細排粗排合一,isRoughSchedule() 切換
處理顆粒投產單({poNo, product, qty, dueDate, prioritySeq})工單(WorkOrder) 級,支援單投產單對多工單迭代
輸出模型每個 VSM 節點掛 {LSD, LeanPlay 交期, 投產順序}(純日期標記)KanBanProduce 生產看板 + KanBanMaterial 物料看板清單
產能語意純試算、不寫回/不鎖定實際消耗並 commit 產能表;非粗排模式另 saveSnapshot 落地
顆粒度到「天」到時間(時/分,含班制 WorkShift、時區位移)
到料/庫存不考慮(§RCS-FS-5,只保留「需要哪些料」)完整 WIP/庫存供需、未搓合工單搓合

定位不同,所以後面會看到「舊版功能多很多」。讀那部分時要分辨的不是數量,而是:哪些是 spec 故意排除,哪些是 spec 漏掉、得補進範圍說明。


2. 方向一:新 spec 有沒有漏掉舊版該有的粗排能力?

結論:沒有漏。 粗排的核心骨架(節拍點定錨、有限產能堆疊、上游拉動下游推動、最晚開工日反推)在舊版都找得到對應。但有幾處對不上,得照 spec 重做或補齊。

逐項對照如下。狀態欄:✅ 一致、⚠️ 有但語意有差、❌ 沒有或相反。

#Spec 項目舊版對應實作(檔:行)狀態說明
1LSD 反推(§RCS-FS-13:自交期反推、純 leadtime、不看產能)LatestStartCalculator.calculateNodeRecursive(LatestStartCalculator.java:91-153),排程後由 calculateLatestStart() 呼叫(ScheduleEngine_wo.java:2142-2174)⚠️核心一致(交期為錨、往前反推、不消耗產能)。兩點差異:(a) 逾期時 LSD clamp 到 nowDt(:117-118),spec §RCS-FS-3 是「保留過去值、視為無意義」;(b) leadtime 會除以開機數(:161-165),spec toy 假設單一資源、未涵蓋。
2LeanPlay:節拍點為錨(§RCS-FS-11 正推定錨求最早可開工日 → 有限產能堆疊 → 往前 JIT 拉上游、往後推下游)節拍點起排日(ScheduleEngine_wo.java:450-475)、有限產能 arrangeTimeWithProduceCapacity(:534)、pullScheduleProduceKanban(:850)、pushScheduleProduceKanban(:1435)⚠️結構對應。語意差異:spec 2026-06-04 已廢棄交期反推(§RCS-FS-10)改為自起排日正推 ASAP;舊版粗排仍保留「交期 JIT 反推」分支(:456-459)與「nowDt 正推 standardLeadTime」分支(:461-463)。錨點來源與新 spec 不一致,需以 spec 為準重做。
3有限產能堆疊、不足往後一天(§RCS-FS-2 排擠)arrangeTimeWithProduceCapacity 失敗→節拍點 +1 天(:538-547)機制一致。
4上游往前拉動 N-x(JIT、緊鄰、不留閒置)getPullNodeDt(:1371-1402)+ pullScheduleProduceKanban(:850)拉動以「緊鄰後站開工」反推,與不留閒置一致。
5下游往後推動 N+ygetPushNodeDt(:1328-1369)+ pushScheduleProduceKanban(:1435)機制一致。
6節拍點隨排擠後移、上游整段隨之後移(§RCS-FS-15)節拍點 +1 天後重排上游(:656-664)行為一致。
7節拍點→以最後一站為節拍點(§RCS-FS-1)VSMUtil.getTaktPoint 找不到回 null(VSMUtil.java:43-50);ScheduleEngine_wo.java:398 取得後無 fallback,後續會 NPE舊版未實作 §RCS-FS-1。spec 此處較嚴謹,屬新增需求。
8投產順序=LeanPlay 完工日全域排序、連續編號 1..NprocessAfterSchedule() 用可插拔 IScheduleKanbanSorter(:841-845);預設 StdScheduleKanbanSorter 依「MTO/MTS → 開工日 → manualSeq → 成品階 → processSeq」排(StdScheduleKanbanSorter.java:20-35)⚠️定義不同:spec 依「完工日」全域排;舊版依「開工日+業務分群」。需釐清採哪個。
9空批次 → 回傳空、不報錯(§RCS-FS-8)對空 productionOrderList 自然產生空輸出(:357);但 inputCheck() 對缺 VSM/產能會直接不跑(:189-243)⚠️空批次可達成空輸出;但 inputCheck 是另一層擋門,對「空輸入」的容忍邊界與 spec B8 略有出入,需確認。
10交期早於今日 → LeanPlay 落未來、LSD 落過去、引擎不判 overdue(§RCS-FS-3)LeanPlay nowDt 夾住、不排到過去(:419-421, 469-474)✅;LSD clamp 到 nowDt(:117-118)⚠️;overdue 見第 11 點 ❌⚠️LeanPlay 不落過去一致;LSD 落過去的處理不同(見第 1 點)。
11引擎只輸出日期、不比對交期、不判 overdue(§RCS-FS-7)舊版多處判逾期::530-531 log、:688-690 setOverdue:772-776 拋例外並 createScheduleAlarm:786-790 互動模式逾期停止與 spec 相反。舊版主動判逾期、產警報、甚至中斷;spec 明定引擎不判、交下游。
12純試算、不寫回/鎖定產能(UC A1 預期結果)粗排模式跳過 saveSnapshot(:765-767);但 arrangeTimeWithProduceCapacity 仍會消耗並 commitFinalProductivityCalculation(:700, :316-319)改寫記憶體產能表⚠️不落 DB 與「不寫回」相符;但引擎內部確實會佔用/commit 產能(為了多單排擠),是否算「鎖定」需對齊。

小結: 核心機制舊版都有。要對齊的是這四件:無節拍點的 fallback(舊版缺)、不判逾期(舊版相反)、LeanPlay 的錨點來源(舊版仍用交期反推、spec 已改正推),以及投產順序的排序依據。


3. 方向二:舊版多出哪些 spec 沒有的功能?

舊版多出不少功能,分三類看:

  • A 類:spec 已經明講「不做、或留到下一期」。這些是故意排除,不是缺口。
  • B 類:spec 完全沒提。這些是潛在缺口,要團隊決定「丟掉」還是「列為未來範圍」。
  • C 類:反過來,spec 有、舊版沒有(和 §2 呼應)。

3A. spec 已明講不做的——故意排除

這幾項舊版有、spec 沒有,而且 spec 有白紙黑字的排除依據。報告只是點名,確認「捨棄/延後」是有意識的決定。

舊版功能證據(檔:行)spec 排除依據
產銷協調互動入口/互動式模式(逾期單停止)isTurnOnInteractionMode:772-790概述「互動入口明確不做、留下一期」
逾期判定/排程警報(ScheduleAlarm)AlarmMgr.createScheduleAlarm:772-790§RCS-FS-7(引擎不判 overdue)
寫回/鎖定產能(Snapshot 落地)SnapshotDelegate.saveSnapshot:32-36, 765-767UC A1「純試算、不寫回/鎖定」(§Q4 待裁定是否落地)
到料/WIP/庫存供需協調checkSupplyDemand(:2021)、getWIPSupply/getInventorySupply(:975-984)§RCS-FS-5(不考慮到料,只保留「需要哪些料」)
集批控制getArrangeKanBan 已移除、恆回空(:2072-2074);getTaktTolerance 拆批(:548-571)§RCS-FS-14(集批不支援)

其中「集批」在舊版其實已被拔成空殼(getArrangeKanBan 恆空),與 spec 方向一致。

3B. spec 完全沒提的——潛在缺口,要裁定

這類最需要注意。多數是「工單級/細排」的機制,可能本來就該排除在粗排之外,但 spec 目前沒寫明,容易日後被誤判成「漏做」。

#舊版功能證據(檔:行)為何值得裁定
B1工單級處理:單投產單對多工單迭代、固定完工日:491-508, 590-606, 718-740spec 只到「投產單+qty」。粗排是否需感知工單/固定完工日?
B2計畫性訂單/共用件合併:未搓合工單搓合partUnfinishedWoMap(:949-1007)、:1819-1900投產單共用件邏輯,spec 未涵蓋。
B3採購件直接出貨isDirectSalecreateShipMaterialKanbanForBuy(:386-393)採購件不走製程樹,spec 未提。
B4物料看板生成(pull/store/ship/buy)KanbanEngine_new 系列(:578, 1028, 1607-1684)spec §RCS-FS-5 只要保留「需要哪些料」,未要求產各類物料看板。輸出模型差異核心。
B5移轉批量/拆批:容許天數控制:548-571, 1068-1073, 1242-1247比 spec 顆粒更細的批量控制,spec 未定義。
B6Lot 拆分assignLotsToKanbans(:797-824, 2198-2348)批次級拆分,spec 未涵蓋(spec 到「天」、到「節點」)。
B7瓶頸統計分析建議BottleneckStatEngine(:484-536)排單統計/瓶頸建議,spec 未提。
B8產能 Gap 掃描buildPoRecordGap/ScheduleGap(:1690-1775)不足量回報,spec 未提。
B9加班/特殊加班overTimeMapsalesOrderOvertimeMap(:73-76, 296-298)§RCS-FS-9 只說 Freeze 在引擎外;加班設定屬產能組成細節,spec 未展開。
B10資源數計算策略/模治具限制ResourcePlanCalculatormoldFixtureConstraintMap(:2151-2159)開機數會影響 leadtime(連帶 LSD);spec toy 假設單一資源。
B11齊料拉動(forerunner / kit pull)oidForerunnerFinishDtisForerunner(:367-384, 712-714)跨單齊料同步,spec 未涵蓋。
B12中斷機制/進度回報interrupt(:246-248)、getProgress(:250-255)執行控制,spec 未提(屬非功能性)。
B13時區位移zoneOffsetHours(:826-834)spec 到「天」、未談時區;若粗排也跨時區,需補。

B1~B6、B11 多屬細排/工單級,落在粗排投產單級、純試算」定位之外,建議在 spec 範圍說明補一句。B9(加班)、B10(資源數/模治具)與「可用產能leadtime」直接相關,最該先決定要不要納入。

3C. spec 有、舊版沒有——反向補記

項目說明
§RCS-FS-1節拍點 fallback(以最後一站為節拍點)舊版 getTaktPoint 回 null、無 fallback(會 NPE)。spec 較嚴謹。
§RCS-FS-7 明確「引擎不判 overdue」舊版相反(會判逾期+產警報)。spec 為刻意收斂。
LeanPlay 自起排日正推 ASAP 錨定(§RCS-FS-11,廢棄交期反推 §RCS-FS-10)舊版粗排仍用「交期 JIT 反推」或「nowDt 正推」分支,與 spec 新定義不一致。

4. 要團隊裁定的事項(依優先序)

把前面查到、需要人決定或修正的列出來。前四項是實作新粗排前一定要先定的。

  1. 逾期由誰判(衝突):spec 要引擎「只給日期、不判 overdue」,舊版會判逾期、產 ScheduleAlarm、互動模式還會中斷。實作新粗排時須移除逾期判定與警報,逾期比對交下游。(§RCS-FS-7)
  2. 節拍點 fallback(舊版缺):新引擎須補「無節拍點→以最後一站為節拍點」,避開舊版的 null/NPE 路徑。(§RCS-FS-1)
  3. LeanPlay 錨點來源(語意已改):採 spec 的正推 ASAP 定錨,不可沿用舊版的交期反推。(§RCS-FS-11)
  4. 投產順序定義(不一致):確認採 spec 的「完工日全域排序」,而非舊版的「開工日+MTO/MTS+manualSeq」。
  5. LSD 細節對齊:(a) 逾期時 LSD 要「保留過去值」(spec §RCS-FS-3)還是「clamp 到 nowDt」(舊版)?(b) LSDleadtime 要不要納入「開機數除 CT/CO」(舊版有、spec toy 無)?
  6. B 類功能範圍宣告:對 B1~B13 各項標記「本期捨棄」或「未來範圍」,補進 spec 範圍段,使「不做」是有意識的決定而非遺漏。其中 B9、B10 與「可用產能leadtime」直接相關,最需先決定。

附錄:關鍵證據索引

  • LSD(最晚開工日)計算:LatestStartCalculator.java:74-202;逾期 clamp :117-118;資源數除 CT/CO :161-165;填回看板 :207-218
  • LeanPlay 節拍點起排日策略:ScheduleEngine_wo.java:450-475(rough+JIT 交期反推 :456-459;nowDt 正推 :461-463)
  • 有限產能堆疊/排擠 +1 天::534-547
  • 上游拉動:pullScheduleProduceKanban :850-1326;getPullNodeDt :1371-1402
  • 下游推動:pushScheduleProduceKanban :1435-1688;getPushNodeDt :1328-1369
  • 逾期判定/警報::530-531, 688-690, 769-790
  • Snapshot 寫回(粗排跳過)::32-36, 765-767
  • WIP/庫存供需:checkSupplyDemand :2021-2040;updateOrderRequestQty :1954-2009
  • 集批已拔成空殼:getArrangeKanBan :2072-2074
  • Lot 拆分:assignLotsToKanbans :2198-2348
  • 投產順序 sorter:ScheduleEngine_wo.java:841-845;StdScheduleKanbanSorter.java:20-35
  • 節拍點查找(無 fallback):VSMUtil.java:43-50;呼叫點 ScheduleEngine_wo.java:398