Skip to content

feat: 成員/訂閱/方案/渠道 刪除(補齊 CRUD)#4

Merged
poterpan merged 9 commits into
mainfrom
feat/crud-delete
Jun 7, 2026
Merged

feat: 成員/訂閱/方案/渠道 刪除(補齊 CRUD)#4
poterpan merged 9 commits into
mainfrom
feat/crud-delete

Conversation

@poterpan

@poterpan poterpan commented Jun 7, 2026

Copy link
Copy Markdown
Owner

背景

後台原本只能新增/編輯成員與訂閱,無法刪除——嚴重的 CRUD 缺口。本 PR 補上四個實體的刪除能力。

CRUD 缺口 review(feature 2(b) 交付):掃過所有 admin 路由,缺 DELETE 的為 users / subscriptions / plans / channel_tags(payments 是交易紀錄,走狀態轉換不硬刪,刻意保留)。本 PR 對四者都補上。

  • 設計 spec:docs/superpowers/specs/2026-06-07-crud-delete-design.md
  • 實作計畫:docs/superpowers/plans/2026-06-07-crud-delete.md

刪除語意

實體 方式
成員 / 訂閱 cascade 硬刪:連帶刪除 payments + upload_tokens + R2 截圖物件;child→parent 順序、D1 batch() 原子化、workspace 限定、writeAudit、回傳刪除計數
方案 / 渠道 guarded 硬刪:仍被訂閱/付款參照時回 409(仍可用 active=0 停用);未參照才刪
  • 訂閱的「取消」(status='cancelled') 保留給「停收但留歷史」的情境。
  • list 端點新增依賴計數(subscription_count/payment_count/usage_count,皆 workspace 關聯)→ 驅動前端確認框顯示「將刪除 N 筆」與 guarded 防呆(使用中則 disable)。
  • 前端每列加刪除鈕 + 紅色確認 Modal;cascade 顯示連帶數量,guarded 被參照時 disable + tooltip。

驗證(CI 條件,無 .dev.vars)

  • pnpm -r typecheck
  • pnpm -r test177 passed (31 files) ✅(新增 cascade 計數、R2 有/無清理、guarded 409/放行、audit、list 計數等測試)
  • pnpm -r build(web+admin)✅

流程

每個 Task 經 implementer → spec 合規審查 → 程式品質審查(含修正迴圈:cascade 改 D1 batch() 原子化、deleteSubscription 補 workspace scoping、plan-delete 409 訊息清晰化、count 子查詢 workspace 關聯、補 R2-present cascade 測試),最後整體 review(Ready to merge)。

🤖 Generated with Claude Code

poterpan added 9 commits June 7, 2026 22:21
Add hard-delete for users/subscriptions (cascade: payments + upload_tokens + R2
objects, with confirmation + audit) and guarded hard-delete for plans/channel_tags
(409 when still referenced; soft-deactivate via active stays). List endpoints gain
counts to drive the confirmation dialog + guarded front-end disable. Decisions from
brainstorming.
4 tasks (TDD): cascade delete (users/subscriptions, +payments/upload_tokens/R2),
guarded delete (plans/channel_tags, 409 when referenced), list dependency counts,
and the front-end delete buttons + confirmation. Per the CRUD-delete spec.
DELETE /admin/users/:id and /admin/subscriptions/:id remove the entity plus its
payments, upload_tokens, and R2 proof objects (child→parent; R2 cleanup guarded by
env.BUCKET). Returns deletion counts and writes an audit log.
…eSubscription

Wrap the multi-table cascade DELETEs in env.DB.batch() so a mid-sequence failure
can't leave partial state; add workspace_id scoping to deleteSubscription's payment/
upload_token statements for defence-in-depth; tighten the test payment-count assertions.
DELETE /admin/plans/:id and /admin/channel-tags/:id hard-delete only when nothing
references them (a subscription / a payment), else 409. Soft-deactivate via active
remains. Writes an audit log.
users gain subscription_count + payment_count; subscriptions gain payment_count;
plans gain subscription_count; channel_tags gain usage_count. Drives the delete
confirmation dialog and the guarded-delete front-end disable.
Each Manage list row gets a delete action. Members/subscriptions show a cascade
confirmation with affected counts; plans/channel-tags disable delete while still
referenced (guarded). Adds the api delete methods + count fields to the types.
… cascade

Scope the dependency-count subqueries by workspace so the front-end disable parity
matches the workspace-scoped delete guards (multi-workspace-safe). Add a cascade-
delete test that verifies the R2 proof object is removed when R2 is configured.
@poterpan poterpan merged commit 6581ad7 into main Jun 7, 2026
2 checks passed
@poterpan poterpan deleted the feat/crud-delete branch June 7, 2026 16:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant