出貨前處理:賣的是承諾,出的是現實
· tech
#war-story#live-commerce#fulfillment
📑 目錄
錢收完了,該出貨了。這章是系統與實體世界的交界——留言、庫存、金流都活在資料庫裡,但貨是真的紙箱、真的倉庫、真的宅配司機。也因此,這是全系列「系統邊界」劃得最有意識的一章:哪些歸系統管、哪些交給人,當年的答案比我記憶中更聰明。
兩本庫存:賣的是承諾,到的是現實
先把時序擺正:主播直播時跟廠商談好「有多少貨」——這個數字進了庫存章的上限,系統拿它守住不能超賣。但下播之後,採購流程才真正開始;採購本身不在系統內,系統看到的下一個事實,是營運把實際到貨填成入庫單——一筆一筆 append 的紀錄,庫存的每次調整都有 log 可看。
所以這個系統其實有兩本庫存,庫存表上就是分開的兩個欄位、各司其職:
- 銷售庫存(承諾):主播喊的量。它的工作是在下單瞬間守住「賣出 ≤ 上限」,活在毫秒級的交易裡。
- 實體庫存(現實):入庫單累積的量。它的工作是誠實記錄倉庫裡真的有什麼,活在天級的物流節奏裡。
兩本帳天生會歪——談好 100 件、廠商到貨 80 件(短交),或貨損、或規格不符。這不是 bug,是代購這門生意的常態。問題只有一個:歪了之後,誰的單有貨、誰的單要等?
配貨:把承諾對到現實
當年的答案是一套配貨系統:把實際到的庫存,分配給承諾過的訂單。
配貨系統有三個設計,每個都值得停一下:
- 配貨紀錄表是 append 的——庫存變動可以用全部事件重建。 入庫是事件、配貨是事件,事實的全集隨時可以重放出當下狀態:帳歪了有地方對、客訴有據可查、盤點有底可回。這張紀錄表是實體側的定海神針。
- 機制歸系統,政策歸人。 配貨系統提供的是「怎麼分都行」的機制,加上每次分配的紀錄;至於怎麼分——短交時犧牲誰、誰先出——是營運的商業判斷。系統不越權替人做政策,但把每個政策決定都記成可追溯的事實。這跟狀態機被拔掉、退款走銀行是同一個哲學的第三次落地。
- 規則簡單到不會錯:order 全部配齊,才產生出貨單,items 一起出。 不拆件,所以沒有「拆到一半」的中間態;出貨時機大部分由營運依配貨情況決定,客人急了找客服——又是機制與政策的分工。
系統的邊界:管到出貨單為止
這章最值得學的,其實是系統選擇不做什麼:實際上有很多個倉,系統不管;揀貨怎麼撿、有沒有條碼、短少怎麼辦,系統都不管。系統的責任在「訂單變出貨單」畫上句點,之後——7-11 走 API(客人在網頁選店號)、宅配靠人工匯出 CSV 交給貨運——剩下是營運的世界。運費和條件則設定在檔期層,跟優惠券、結算同一個範疇,檔期第三次證明自己是這個系統天然的設定邊界。
這條線劃的位置有邏輯:它恰好是資訊流和實體流的分界。資訊錯了會超賣、會收錯錢——違約成本高、人眼看不見,系統必須守;實體錯了(撿錯貨、少一箱)現場看得到、當場能修——人比系統更適合守。六個工程師的複雜度預算,再一次花在刀口上。
重來:三步把履約拆出去
當年的形狀能跑,但有一個結構性的彆扭:購物車章說 order 按檔期切、是履約單位——於是payment 已經跨檔期了,出貨卻還被檔期綁著。客人買了三個檔期的貨,想一箱寄來?結構不順。重來版分三步,一步比一步深:
- 履約單位下放到 order item。 配齊哪個 item,哪個就具備出貨資格——「等貨齊」從結構限制變成營運政策:想等齊再出、想到貨先出,都只是聚合時收不收這個 item 的決定。order 退回純帳務分組(檔期優惠、對帳照舊),會計完全不動——order item 本來就是定格金額的會計單位,履約下放後「履約-會計」反而同粒度了。
- shipment(出貨單)升為一級實體,以「收件人+地址」聚合。 跨檔期合併出貨自然發生、部分到貨自然拆件,不需要任何特殊邏輯。代價有三,寫下來才誠實:運費政策要重定義(檔期層留規則、shipment 層做計算——包裹才是實際產生運費的東西);地址是聚合鍵,所以聚合那一刻要定格地址——承諾點原則的第二次出現(第一次是成交定格價格);客人的查詢單位從 order 變成 shipment,前台和客服的敘事要跟著改。
- 履約整段獨立成「貨運系統」。 電商系統的終點=匯出可履約訂單;貨運系統吃訂單,管入庫、配貨、出貨單、物流介接的全部,出貨與退回以事件回流電商——電商照老規矩事實落地、狀態派生。代價同樣要寫下來:兩本庫存從此正式分家——銷售庫存留在電商守超賣,實體庫存跟著貨運系統走,兩邊靠回流的事件對帳。這一步聽起來激進,其實有兩個當年的伏筆撐著:人工匯出 CSV 給貨運,就是這個介面的人力版雛形——這個邊界已經靠人力跑了好幾年;而專案終局把 monolith 拆成電商、選標、採購三個服務,用的正是同一種邊界直覺,貨運完全有資格當第四個。真正的回報在最後:介面一旦是「訂單匯入」,貨運系統就是可替換的消費者——自己養、換 3PL 第三方倉配、或混用,電商一行不動。好邊界的複利,是連「要不要自己做」都變成可以隨時反悔的決定。
反思
系統的邊界,劃在你能負責的地方為止
當年不做倉儲管理、不做揀貨系統、出貨靠人工 CSV——年輕時我大概會把這些列成「技術債清單」。現在我認為它們是自知:系統守資訊流(錯了會超賣、會錯錢、人看不見),人守實體流(錯了看得見、修得快)。把系統硬伸進倉庫,要處理的是條碼設備、盤點差異、人員操作習慣——每一項都是新的複雜度來源,而它們換來的正確性,人力本來就守得住。邊界不是能力的極限,是責任的極限:劃在你能為錯誤負責的地方,而不是技術能延伸到的地方。
機制歸系統,政策歸人——這是第三次了
狀態機被主播拔掉、退款讓營運去銀行按、配貨「按他們想要的方式」——同一個哲學在這個系統落地三次,沒有一次是妥協,每一次都是正確的分工:系統擅長記錄與守不變量,人擅長判斷與扛例外。配貨系統最聰明的地方,是它不試圖演算法化「短交時犧牲誰」這種商業判斷,但把每個判斷都變成配貨紀錄表裡可追溯的事件——人自由,帳清楚。這比「全自動配貨引擎」誠實,也比「Excel 裡自己喬」可靠,它站在兩者中間的甜蜜點上。
最好的架構演進,是把已經存在的縫變成介面
「履約拆成貨運系統」聽起來像大重構,但仔細看:那個介面(一批可履約的訂單)當年就以人工 CSV 的形式存在,而且一直跑得穩——重來只是把這條人力跑出來的斷面正式化。這是我對架構演進最相信的一件事:好邊界不是設計出來的,是觀察出來的。 系統裡那些「long-lived 的人工流程」——每週固定匯出的報表、營運固定貼給誰的檔案——都是還沒被承認的介面。想知道系統該從哪裡拆,別開白板會議,去看人們已經在哪裡交接。