Task #1470
進行中Feature #1464: [M1] 垂直切片:HPICIOEB 散客線上報名端到端
[API] T01a 核心 schema ERD 設計
0%
概述
範圍
產出 docs/features/001-booking-platform/erd.md:Mermaid erDiagram、各表欄位與型別/nullable、索引清單、關鍵設計點說明(Session 補充屬性怎麼存、表單答案 JSON 欄位、金額明細快照)。
本票不寫任何 code。
依 D18/spec §4.5:關聯以邏輯關係標示,並註明「應用層維護,DB 無約束」;關聯欄位仍須列出索引。
驗收
ERD 文件完成並經使用者 review 核可
相依
無(M1 起點)
spec: docs/features/001-booking-platform/spec.md
tickets: docs/features/001-booking-platform/tickets.md
是由 鍾正剛 於 27 天 前更新
【T01a 完成,交付 ERD 待 review】
文件位置:docs/features/001-booking-platform/erd.md(836 行)
本票依定義只出設計文件、不寫 code、不建表。核可後由 #1485 T01b 依此文件建 schema 與 JPA entity。
一、關鍵設計判斷¶
-
PK 一律 bigint AUTO_INCREMENT,業務識別碼另立
code varchar(32)欄位。放棄舊系統 varchar PK + 自製 ID Generator,減輕 JPA 與跨表 join 負擔。 - 無 FK 但關聯欄位一律建索引(D18)。舊系統 13 張業務表除 PRIMARY 外零索引,這是本次重建的效能重點修補。共列 24 條非 PRIMARY 索引,依「關聯欄位/前台查詢/後台查詢/排程掃描」四類分組說明服務的查詢。
- 狀態欄位 varchar 存 enum name,狀態與取消原因分離兩欄(§5.3)。舊系統 int + Converter 導致 DB 側完全無法辨認,是明確的 anti-pattern。
-
三種預約型態單表實作(D10):
booking_type欄位 +session_id(前兩型必填)與apply_date_from/to(申請審核型必填)互斥為 NULL。無 DB CHECK,由 service 層保證。 -
Session 補充屬性採 JSON:
activity.session_extra_fields宣告欄位形狀、session.extra_attributes存值。避免舊h_tide.gather_time varchar(100)變成 1,519 筆自由格式的重演。取捨與 EAV 拆表方案列入待確認 Q4。 -
金額明細快照:
order.price_breakdown為結構化 JSON,含steps[](含 label/kind/amount)、priceTier快照、agreement、coupon、subtotal、total。文件中示範 M1(居民票 170×3)與 M2(含協議+coupon)兩種形狀,供客服逐行還原。 -
樂觀鎖 + 單一 UPDATE 原子扣減(§5.1):
session.version為 JPA@Version;名額扣減走UPDATE ... WHERE version=? AND (capacity IS NULL OR occupied_count+? <= capacity)一句 SQL。capacity IS NULL對應無上限場次(D17),仍記錄occupied_count但不做上限檢查。 -
表單版本快照為 int,不是 FK:
order.form_definition_version存整數,配合form_definition (code, version)唯一鍵解讀舊訂單答案。發布新版時舊版改 ARCHIVED、不刪。
二、對 spec 的補充(spec 未寫、本文件補)¶
- 主鍵型別、稽核欄位 4 欄、金額 int、狀態欄位型別、
price_breakdownJSON 結構、form_definition_version為快照非 FK、reserved_until單欄承載線上/線下兩種語意、activity_i18n表結構。
沒有偏離 spec 之處。假設 target env MySQL ≥ 8.0。
三、M1 vs M2 界線¶
-
M1 建 11 張表:
activity,activity_i18n,price_tier,session,order,booking,order_payment,order_invoice,form_definition,form_field,form_option_source。 -
M1 建欄位但暫不使用:在
order上預留customer_id、agreement_id、coupon_code、discount_amount4 欄(M2 用)。理由:M6 遷移後order將有數萬列,ALTER TABLE 代價高;四欄 nullable,M1 不用不會有副作用。 -
M2+ 才建的表:
customer,agreement,agreement_scope,coupon,coupon_redemption。M2 開工時再依 O-4(退款)等再定案,現在建大概率要改。 -
明確不建:舊
h_order_info_channel、h_order_detail、h_event系列。理由詳見文件 §6.4。
四、待使用者確認(8 項,見文件 §7)¶
-
Q1 主鍵:bigint +
code欄位(建議) vs 保留 varchar 業務碼 -
Q2
order是否改名為orders避開 MySQL 保留字(建議改名) -
Q3
activity_i18n是否 M1 就建(建議建,避免日後 ALTER) -
Q4
session.extra_attributes用 JSON(本設計) vs EAV 拆表 -
Q5
booking.booking_type冗餘存於 booking(建議保留) -
Q6 M1 是否建
form_option_source(建議建) -
Q7
order.reserved_until是否用 partial index(須確認正式環境 MySQL 版本) - Q8 補充屬性 JSON key 用英文 identifier(本設計) vs 中文
五、下一步¶
核可後 T01b(#1485)接手,依此 ERD 建 schema 與 entity。
若上述 Q1~Q8 有異議或補充,請直接在此票留 comment。
是由 鍾正剛 於 27 天 前更新
【T01a ERD Rev 2 — 依 review 修訂完成】
文件:docs/features/001-booking-platform/erd.md(898 行,頂部含修訂紀錄表)
一、實際改動的項目¶
Q1~Q8 裁示落實¶
-
Q1 依 spec D19/§4.6 重寫 §1.1 主鍵政策;
ordersPK 改為order_no varchar(14),取消order_id代理鍵與order_noUK;booking/order_payment/order_invoice的 FK 欄位改為order_no varchar(14);索引更名。移除初稿誤設計legacy_mid,並在文件中說明 M6 遷移舊mid原樣沿用即可。加入「對外只露業務碼」與「code→id 入口解析一次」兩條實作要求(避免逐號窮舉與 N+1)。 -
Q2 全文一致改為
orders(Mermaid、表定義、索引命名、prose 皆同步;`order`只剩兩處是刻意提到「MySQL 保留字/裁示紀錄」的敘述)。 -
Q3
activity_i18nM1 就建(原本即為此設計,無 code 變動)。 -
Q4
session.extra_attributes用 JSON(同上)。 -
Q5 §4.2 明確寫入 service 層約束:已存在 booking 的 activity 禁止變更
booking_type,並說明實作點(bookingRepository.existsByActivityId)。 -
Q6
form_option_sourceM1 就建(同上)。 -
Q7 §5.4 完全重寫:MySQL 無 partial index 是事實,改採複合索引
(payment_status, reserved_until);索引命名idx_orders_payment_status_reserved_until。§5.5 重新盤點索引總數。 - Q8 §4.1 加入「M3 前置需求」註記:活動設定介面與匯入對應介面須顯示中文 label,不露 identifier;系統內 key 為英文、UI 顯示為中文,這是分工的重點。
三項修正¶
-
修正一 §4.5 重寫。移除
AND version = :version;同時移除session.version欄位(於 §3.4 亦一併移除)。文件說明兩個原因(冗餘、與@Version衝突)與選擇「移除欄位」而非「保留但不標 @Version」的理由(Session 其他變更皆為低頻後台操作,無其他樂觀鎖需求)。T06 測試要求補入第二項「高競爭下的成功率」驗收條件(容量 100 / 20 併發全部成功)。 - 修正二 §6.1 標題「10 張」改為「11 張」,敘述同步。
- 修正三 §8 拆為 8.1~8.5,將「M4 兩型可能需要新的補充屬性型態」自「假設」升格為 §8.5 R-1「明確風險」,含衝擊時機(M4 開工時 booking 表已有正式訂單)、三種因應方向(加欄位/加子表/開新表)、責任歸屬(coordinator M4 spec 起草階段 review)。
環境事實¶
§8.3 將原「假設 MySQL ≥ 8.0」升格為已確認事實:local/staging 8.0.23、production 8.0.26(IP 亦收錄,供 T01b DDL 部署參考)。註明兩者皆無 partial index。
其他一致性修訂¶
- Mermaid ORDER→ORDERS、
order_id欄位屬性移除、child 表 FK 改為order_no varchar(14)、SESSION 移除bigint version欄位 - §5.3 移除
idx_order_no條目並加註「PK 直接服務,不需另建索引」 - §3.12 heading 由「M1 只在 Order 預留」改為「M1 只在
orders預留」 - prose 中所有
order.<field>全數改為orders.<field> - §1.3 敘述由「所有
<parent>_id欄位」擴充為「<parent>_idbigint 或<parent>_novarchar」以反映新現實
二、對裁示的異議¶
無。八項裁示與三項修正我全部同意,理由如下:
-
Q1 對不可變 key 加代理鍵確實是為不存在的問題付成本,且 D18 無 FK 的前提下 varchar PK 的效能顧慮已被舊系統的實測(
h_order_master.midPK 是 varchar(11))證偽。 -
Q7 MySQL 無 partial index 是事實,複合
(payment_status, reserved_until)是最左前綴等值 + 範圍,正好命中;我在 Rev 1 誤稱「partial」而非「functional」是名詞混淆。 -
修正一 版號檢查在此情境確實冗餘(capacity 條件本身即為原子);
@Version與原生 UPDATE 混用會導致 stale entity 拋假 exception 是常見坑,我在 Rev 1 沒發現這點。 -
修正三 M4 風險確實比「假設」嚴重 —— 尤其
APPLICATION_REVIEW型(租借申請)舊系統從未上線,屬全新設計,M4 才會發現真實需求,而屆時 booking 表已有正式訂單。
三、修訂後的待確認事項¶
無。Rev 1 的 Q1~Q8 全部關閉;Rev 2 沒有新增待確認項目。
§8.4 保留一項假設(M2 agreement.type 至少含 PERCENT 與 FIXED_UNIT_PRICE 兩種),但註明「不擋 M1」,M2 開工時再確認即可。
§8.5 R-1 是明確風險(不是待確認):責任歸屬 M4 spec 起草階段,M1 現在無法完全消除,也不需要在 M1 消除。
四、下一步¶
Rev 2 可交由 T01b(#1485)進場實作。若 coordinator 認為 Rev 2 仍有需修訂處,請在此票留 comment;否則我等 T01b 派工。
是由 鍾正剛 於 27 天 前更新
【T01a ERD Rev 3 — 依二輪 review 修訂完成】
文件:docs/features/001-booking-platform/erd.md(1041 行,頂部含三版修訂紀錄)
一、改動項目¶
修正一:form_definition_version 從 orders 搬到 booking
- Mermaid:ORDERS 移除、BOOKING 新增此欄位
- §3.5 移除;§3.6 新增(
int NOT NULL) - §4.6 解讀流程改寫:
(code, version)一組資料現在完全落在 booking 這一層,M1 1:1 與未來 1:N(購物車)皆自然運作
修正二:D20 多語一律走側表¶
新增/改造 4 張表:
-
form_definition_i18n:(form_definition_id, lang_code, title),UK(form_definition_id, lang_code) -
form_field_i18n:(form_field_id, lang_code, label, help_text),UK 同上 -
form_option(由form_option_source拆分主資料):(option_id PK, payload_key, value, sort_order, enabled),UK(payload_key, value) -
form_option_i18n:(option_id, lang_code, label),UK 同上
主表 form_definition.title、form_field.label、form_field.help_text 保留為 canonical zh_TW(比照既有 activity + activity_i18n 慣例);側表存其他語系。讀取策略:查當前語系側表,找不到回退主表 zh_TW。M1 只填 zh_TW,多語編輯介面 M3。
修正三:D21 可查詢的動態欄位¶
-
form_field.searchable bit(1) NOT NULL default b'0'新增旗標 -
booking_search_attribute側表:(bsa_id PK, booking_id, field_key, value_text varchar(200)) - 索引
idx_bsa_field_value(field_key, value_text)(後台篩選)+idx_bsa_booking(booking_id)(維護) - M1 寫入路徑就位;篩選介面 M3
- 文件明寫否決 generated column 的理由(每加可查欄位就 ALTER TABLE,與 M3 園方自主直接衝突)與 M1 就寫入的理由(避免 backfill;貴的是補資料不是寫程式)
連帶更新¶
- §5.5 新增「側表索引」小節;§5.6 重新盤點 —— 各表索引數含 5 張新/改側表;總計約 32 條非 PRIMARY 索引
- §5.1 移除
idx_activity_i18n_activity(UK 左前綴已服務)並補上一行說明 - §6.1 M1 建表 11→15;分為核心 8 + 多語側表 4 + 表單選項 1 + 搜尋側表 1,並註明各群組的裁示依據
- §7 拆為 §7.1 Rev 2 裁示、§7.2 Rev 3 裁示三項;Q6 說明加註「Rev 3 已改為 form_option + form_option_i18n」
- §8.1 更新
booking.form_definition_version補充敘述(原寫 orders);新增「i18n 側表結構統一」與booking_search_attribute的value_text型別選擇說明
二、對三項修正的異議¶
無。三項修正我全部同意,理由:
- 修正一 明顯是設計 bug —— 我沒把「M1 1:1、日後拆購物車 1:N」的意圖貫徹到欄位放置。感謝 coordinator 直接點名 D9 的原始意圖,這是我原本該想到的。
- 修正二 D20 消除了我在 Rev 1/2 混用兩慣例(activity_i18n 側表 vs form_option_source JSON 內嵌)的不一致。依 D14 表單引擎日後可能上收 ss3a-framework,慣例統一極重要。而且拆表後 M3 表單編輯器逐語系編輯的路徑會直觀許多。
-
修正三 D21 側表 +
searchable旗標是對舊系統病灶(h_order_master47 欄膨脹)最正確的回應。generated column 方案我原本 Rev 1/2 也沒考慮,coordinator 主動否決並註明理由(避免日後被再提議)是好判斷。M1 就寫入避免 backfill 的判斷也很紮實。
三、新增表之後的建表與索引數¶
M1 建表總數:15 張
- 核心 9:
activity,price_tier,session,orders,booking,order_payment,order_invoice,form_definition,form_field - 多語側表 4:
activity_i18n,form_definition_i18n,form_field_i18n,form_option_i18n - 表單選項 1:
form_option(原form_option_source拆分後主表) - 搜尋側表 1:
booking_search_attribute
(Rev 2 為 11 張。Rev 3 淨增 4:+form_definition_i18n、+form_field_i18n、+form_option_i18n、+booking_search_attribute;form_option 為 form_option_source 拆分後的主表,計為原地重命名)
索引總數:約 32 條非 PRIMARY
- 核心表(9 張):約 22 條(含 activity 的 UK code、booking 的 6 條、orders 的 4 條等)
- 多語側表(4 張):4 條 UK
- 表單選項(1 張):1 條 UK
- 搜尋側表(1 張):2 條(複合搜尋 + booking_id 反向)
- 部分索引因複合 UK 已服務左前綴而合併,實作階段可再收斂
(Rev 2 為約 24 條。Rev 3 淨增約 8 條)
四、待確認事項¶
無。Rev 3 沒有新的待確認項目。
§8.4 保留一項假設(M2 agreement.type 至少含兩種);§8.5 R-1 是 M4 明確風險(責任歸屬 M4 spec 起草階段)。兩者狀態不變。
五、下一步¶
Rev 3 可交由 T01b(#1485)進場實作。M1 建表擴為 15 張,比原估多 4 張與若干側表寫入路徑;T01b 工作量小幅增加但仍在可控範圍。
是由 鍾正剛 於 27 天 前更新
- 狀態 從 New 變更為 Resolved
【T01a 已核可】
ERD 經三輪 review 後核可,commit b14e7ce。
產出:docs/features/001-booking-platform/erd.md(Rev 3,1041 行)
- M1 建表 15 張、非 PRIMARY 索引約 32 條、FK 約束 0 個(D18)
三輪的主要修正
- Rev 2:8 項裁示(主鍵政策改為 D19「不可變自然鍵當主鍵」、表名 orders、排程索引改複合 (payment_status, reserved_until))+ 名額扣減移除樂觀鎖版號(冗餘且與 JPA @Version 混用會拋假的 OptimisticLockException)
- Rev 3:表單版本從 orders 移到 booking(D9 拆兩層為未來 1:N,orders 單一 int 無法表達多活動)、多語改側表(D20)、動態欄位可查詢(D21)
coordinator 補記:修訂紀錄索引數與 §5.6 對齊為 32;§5.1 補上 uk_activity_code。
後續由 #1485 T01b 依此 ERD 建表與 entity。