我是 Kota,宇鯨智能的創辦人,從 2021 年開始了一人公司,協助中小企業透過 Data / AI 技術進行數位轉型。
我特別關注想要建立新的服務模式、獲取營收的製造業。這背後需要進行大量的流程再造和數位管理,也需要藉由 AI 技術自動化瓶頸的步驟,這些是我特別擅長的領域。
上一篇提到,當我們把商品規格、合作條件與每筆訂單的客製內容拆開之後,系統開始需要保存不同通路之間反覆使用的價格、交期與其他合作條件。這些資訊不適合每一張訂單重新輸入,也不能直接固定在商品本身,因此後來抽象化出「合約」的概念。
解決了「空間」問題,下個問題則是「時間」,一筆交易到底在什麼時間點成立。如果合作條件之後會修改,已經成立的訂單要不要跟著變;如果一張訂單裡有一個品項不符合規則,其他正常的品項能不能先成立;就算平台已經確認訂單沒有問題,後面的 ERP 建單失敗時,又應該把這張訂單當成什麼狀態。
最直接的例子是價格。假設某個合作通路原本談好的商品價格是 100 元,後來雙方重新議價,從 10 月開始改成 110 元。10 月之後的新訂單直接使用 110 元沒有太大問題,但如果 9 月底已經成立一張訂單,而且當時就是按照 100 元成交,這張訂單之後再被打開時,仍然需要保留原本的交易內容。
如果系統裡只有一份「目前有效的合作條件」,每次改價就直接把 100 元覆蓋成 110 元,那麼過去已經成立的交易就可能跟著被修改。問題不只出現在畫面顯示,後面還可能牽涉報價、對帳、客服與 ERP。幾個月後如果有人回頭問這一張訂單為什麼是這個價格,系統必須有辦法回答當時真正適用的是哪一組條件。
交期也有相同的情況。假設原本約定七天交貨,後來因為產能或合作方式調整成五天,這個變化應該影響新的訂單,但不能因此把過去已經承諾七天的交易全部改寫。
所以當合作條件開始進入系統後,我們很快就碰到一個時間上的問題:系統不只需要知道「現在有效的是什麼」,還需要知道「某一段時間內有效的是什麼」。
原本如果只有一份合作條件,修改價格或交期時可以直接更新資料;但開始需要回頭追溯之後,比較適合的做法是保留舊的條件,再建立新的版本,並記錄新的條件從什麼時間開始生效。這樣系統才有辦法知道某一天建立的訂單,當時應該使用哪一組價格、交期與商品條件。
不過,如果一張已經成立的訂單,每次被打開時仍然重新去查某個合約版本,訂單本身其實仍然依賴外部資料。合約後續如果發生調整、資料被修正,或版本規則發生變化,歷史訂單的內容仍然可能受到影響。
因此在訂單成立時,系統還需要留下這一次交易實際使用的條件。例如這一張訂單當時使用的價格、交期,以及其他會影響交易結果的內容,都應該跟著訂單一起被保存。後來即使合作條件繼續改版,這張訂單仍然可以保留成立當下的狀態。
技術上可以把這種做法理解成 Snapshot,但在這個案子裡,它的目的很實際:當一張訂單已經被雙方視為一筆正式交易,系統就需要保留當時用來成立這筆交易的資訊,避免後面的改版回頭改寫過去。
處理完版本問題後,另一個情境也開始出現。外部通路一次送進來的訂單,可能不只有一個品項。如果一張訂單有十個品項,其中九個都符合目前的合作條件,但其中一個品項找不到對應的製造規格,或不符合目前允許的條件,系統應該怎麼處理?
如果只從單一品項來看,讓九個正常的先成立、一個錯誤的退回,看起來可以減少重工。但把整個流程往後看,就會出現很多新的狀態。
對外部通路來說,它原本送出的是一張完整訂單;到了製造商這裡,卻只成立其中九個品項。對方修正第十個品項後如果重新把整張訂單送一次,系統還需要辨認前九個已經處理過,避免重複建立。客服查看這張訂單時,也需要知道哪些已成立、哪些還在等待修正,ERP 端最後可能又需要處理部分訂單或拆單。
雖然這些情況技術上都可以處理,但「部分成功」會讓狀態非常複雜。所以我們後來比較決定把訂單視為一個完整的交易單位。在進入後面的流程以前,所有品項先一起完成驗證;只要其中一項不符合條件,整筆訂單就先不成立,由外部通路修正後重新送入。
這個做法當然也有代價。如果十個品項裡只有一個有問題,另外九個明明沒有錯,還是得等那一個品項被修正之後整張重新處理。從單次操作來看,這確實沒有部分成功那麼有彈性。
如果系統允許部分成功,那麼從 API 回傳、訂單狀態、重新送單、ERP 建單到客服查詢,後面每一個環節都要理解「這張訂單只有部分成立」。對一個正在建立中的新流程來說,這會讓上下游很容易對同一張訂單產生不同認知。
整筆驗證的做法讓規則相對明確:在所有必要資料與品項都符合條件之前,這張訂單還沒有正式進入後面的製造流程。外部通路也可以把修正看成對同一筆資料的重新提交,而不需要追蹤哪些品項已經成功、哪些尚未成功。
這個方向其實和前面的 Snapshot 有關。因為只有在系統確定整筆訂單可以成立之後,才適合把當下的合作條件保存成一筆正式交易。如果驗證還沒完成,就先留下交易快照,系統裡很容易累積一些最後根本沒有成立的資料。
這套接單平台後面還需要把資料送進製造商既有 ERP,所以即使平台已經完成驗證,也保存了訂單與合作條件,整個流程仍然沒有真正結束。
例如平台已經確認所有品項都符合條件,訂單也成功建立,接著呼叫 ERP 建單,但 ERP 在這個時間點 timeout。這時候平台裡已經存在一筆合法訂單,工廠 ERP 裡卻不一定有對應資料。
更麻煩的情況是,平台看到的是 timeout,但 ERP 其實已經成功建立訂單,只是回應沒有正常傳回。平台如果直接重新送一次,就可能在 ERP 裡產生兩張相同訂單。
這類問題和前面的整筆 Validation 不太一樣。前面的驗證都發生在平台可以控制的範圍內,系統知道哪些資料成功、哪些資料失敗;一旦跨到另一套系統,平台就可能遇到「不知道對方到底有沒有完成」的狀態。
因此,原本很簡單的「訂單成立」開始需要再拆開看。平台可以確認這張訂單在自己的規則裡是合法的,但後續 ERP 是否已經接收成功,是另一個狀態。
如果所有資料都在同一個系統裡,建立訂單、保存 Snapshot 與其他必要資料可以使用資料庫 Transaction 保持一致。但平台與 ERP 是兩套獨立系統,無法簡單用同一個資料庫交易包在一起。平台成功、ERP 失敗,或 ERP 成功但平台沒有收到結果,都是實際可能出現的情況。
這也讓工程師開始需要考慮後續的重送與狀態確認。例如同一筆訂單重新送進 ERP 時,有沒有辦法讓對方辨認這其實是同一筆交易,而不是再建立一張新的訂單;如果平台與 ERP 的狀態一段時間後仍然不一致,有沒有方式重新確認兩邊的資料。
這些問題往技術架構繼續走,會碰到 Idempotency、Reconciliation 等做法。不過在這個專案的這個階段,更重要的是先把狀態拆清楚:平台能確認的是什麼,ERP 回覆之後又多確認了什麼,以及兩套系統中間出現不一致時,需要由哪一邊繼續處理。
這和前面的合約版本、Snapshot、整筆驗證其實是同一條線。系統一路都在處理同一件事情:什麼資訊已經足夠確定,可以被後面的流程當成事實使用。
總結一下,這段系統設計是在處理:
外部資料剛送進來時,只能說系統收到了一份訂單內容;完成所有品項驗證之後,平台可以把它建立成一筆正式訂單,並保存當時使用的合作條件;後續 ERP 建單成功,又代表工廠既有系統已經接收到這筆交易。這幾個狀態原本很容易全部用「成功」來描述,但實際運作後,它們背後的意義並不完全相同。
這個區分也會影響後續錯誤怎麼處理。資料本身不符合條件,可以直接退回給合作通路修正;平台確認沒有問題,但 ERP 暫時無法處理,則可能需要重試或由內部人員確認;有些情況系統甚至可能無法判斷 ERP 到底有沒有成功,需要另外處理例外。
釐清完「這張訂單能不能成立」,下一個問題是「成立後如果自動化流程沒有照預期走,誰要接手」。有些錯誤適合直接 Reject,有些可以 Retry,也可能有現場人員明知道系統檢查沒有通過,仍然需要讓訂單繼續往下走的情況。下一篇會接著這些例外,談自動化流程失敗時,我們怎麼處理 Retry、Force Send,以及人工介入應該留下哪些界線。
有興趣知道更多的,也歡迎和我聯繫交流( kota@yujing.io )!