MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-999

2.9.9 Backend — split getDeletePreview into live vs archived descendant counts

Done
Description

Estimate: 40m · Type: code

Extend the delete-preview so the archived-item confirm modal (2.9.10) can warn about live (non-archived) descendants a cascade delete would also destroy. Motir's archive is single-node (workItemsService.ts:1469 — archiving a parent never archives its children), so an archived parent can still own non-archived LIVE descendants on the active boards/lists; deleteWorkItem cascades the whole subtree (workItemsService.ts:1560, findSubtree), permanently destroying those live items too. The preview must surface that live count.

Today getDeletePreview (lib/services/workItemsService.ts:1614) returns { totalCount, descendantCount, byKind } over the WHOLE subtree and does NOT split live vs archived (verified — lib/dto/workItems.ts:665). Add a live-(non-archived)-descendant count + per-kind breakdown (subtree rows where archivedAt IS NULL, EXCLUDING the root), leaving total/descendant/byKind unchanged (the total still counts every descendant — the design keeps the full cascade count and only ADDS the live split; do NOT filter the total).

  • DTO (lib/dto/workItems.ts WorkItemDeletePreviewDto): add liveDescendantCount: number + liveByKind: Partial<Record<WorkItemKindDto, number>>.
  • Repository (workItemRepository): a single-op read counting the subtree's non-archived descendants by kind (the archivedAt column carries archive state). Keep it one Prisma op (4-layer).
  • Service (getDeletePreview): compute the live split (root excluded), map into the DTO via the delete-preview mapper. Same assertCanManage gate (:1619).
  • Route app/api/work-items/[id]/delete-preview/route.ts returns the widened DTO (additive). Existing callers (fetchDeletePreview, DeleteWorkItemDialog) keep working.

Design: design/work-items/design-notes.md §2.9.7 ("Data note for 2.9.5") + delete-confirm.mock.html panels 6-7 (the warning the count drives). No UI in this subtask.

Acceptance criteria

  • WorkItemDeletePreviewDto carries liveDescendantCount + liveByKind; existing fields unchanged.
  • Archived parent with both live + archived descendants → correct live (non-archived) count + per-kind breakdown (root excluded); all-archived subtree → live count 0; leaf → 0.
  • Still assertCanManage-gated; one Prisma op per repo read. Service test covers live / all-archived / leaf; the workItemsService/workItemRepository ≥90% coverage gate holds.

Context refs

  • lib/services/workItemsService.ts:1614 getDeletePreview, :1560 deleteWorkItem/findSubtree, :1469 single-node archive
  • lib/dto/workItems.ts:665 WorkItemDeletePreviewDto; lib/mappers/* (delete-preview mapper); lib/repositories/workItemRepository.ts findSubtree
  • app/api/work-items/[id]/delete-preview/route.ts
  • design: design/work-items/design-notes.md §2.9.7, delete-confirm.mock.html panels 6-7