[feature] 訂閱可綁定合約,訂閱表與合約列可互相看到 - #64
Merged
Merged
Conversation
❌ SonarQube Quality Gate ERROR — pathorsAI_internal
1 open issue on this PR:
|
This was referenced Sep 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
為什麼
subscriptions(週期性月費)與contracts是兩張各自獨立的表,訂閱只掛得到專案(project_id),掛不到合約。但週期性費用多半是合約裡談好的條件 —— 合約寫「每月維運費 30,000」,系統裡卻只有一張孤兒訂閱,回頭要問「這筆月費是哪張合約來的」沒有任何欄位答得出來,只能靠方案名稱猜。請款看板上的訂閱期別也因此永遠是contractId: null,跟billing_items那側的合約欄位對不起來。一次性分期走
billing_items.contract_id,週期性月費走新的subscriptions.contract_id,兩邊語意一致。刻意維持選填 —— 既有訂閱不見得對得到合約,也有純口頭約定的月費。改了什麼
Schema:
subscriptions.contract_id(選填,FK →contracts.id)+idx_subscriptions_contract。Queries(
src/db/queries.ts)listSubscriptions/getSubscriptionleftJoincontracts,多回contractId/contractTitle。listBillingBoard的訂閱列不再硬寫contractId: null/contractTitle: null,改由訂閱綁定的合約帶出來。listSubscriptionsByContract(orgId):一次查完再依合約分組(合約頁每張合約各查一次就是 N+1)。Mutations(
src/db/mutations.ts)subscriptionValues/subscriptionColumns收contractId;createSubscription/updateSubscription的unownedRefError一併檢查合約歸屬,別的 org 的合約 id 塞不進來。optRefNum():Radix Select 不接受空字串當值,「不綁定」那一項送的是"none"(比照 employees 的userId),用num()解會變成NaN。Web UI
合約標題 — 客戶名,因為同一客戶常有多張標題相近的約。可清空(「不綁定合約」)。MCP
create_subscription/update_subscription收選填contractId,以assertInOrg驗歸屬;update_subscription明確傳contractId: null可解除綁定(optNumber會把 null 與「沒帶」都收斂成undefined,所以另外判一次)。list_subscriptions多回contractId/contractTitle;SUBSCRIPTION_ROW/SUBSCRIPTION_LIST_ROW兩個 outputSchema 同步補欄位,structured output 驗證才過得了。docs/mcp.md補一行。i18n:
subscriptions.list.columns.contract、subscriptions.newDialog.contract.*、contracts.linkedSubscriptions.*(zh-TW / en 各一份)。Schema change
migrations/0022_subscription_contract.sqlmerge 後要手動套到 prod。db:pull/db:push,也沒對任何資料庫套用過。驗證
bun run lint通過(無輸出)。bunx tsc --noEmit:src/零錯誤。bun run build通過。