From d82e8729afbc33b5b955cb23121ff0b45966018e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=80=82?= Date: Wed, 8 Jul 2026 11:53:07 +0800 Subject: [PATCH] =?UTF-8?q?feat(v2.4):=20=E7=BB=9F=E4=B8=80=E9=A2=86?= =?UTF-8?q?=E5=9F=9F=E7=8A=B6=E6=80=81=E5=A5=91=E7=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migration.sql | 1 + apps/server/prisma/schema.prisma | 2 +- .../requirement/requirement.service.spec.ts | 48 +++- .../requirement/requirement.service.ts | 14 +- apps/web/lib/constants.ts | 22 +- apps/web/lib/domain-contract.test.ts | 48 ++++ .../2026-07-08-v24-domain-crud-migration.md | 236 ++++++++++++++++++ packages/shared/src/enums.ts | 52 +++- 8 files changed, 401 insertions(+), 22 deletions(-) create mode 100644 apps/server/prisma/migrations/20260708000000_v24_domain_contracts/migration.sql create mode 100644 apps/web/lib/domain-contract.test.ts create mode 100644 docs/superpowers/plans/2026-07-08-v24-domain-crud-migration.md diff --git a/apps/server/prisma/migrations/20260708000000_v24_domain_contracts/migration.sql b/apps/server/prisma/migrations/20260708000000_v24_domain_contracts/migration.sql new file mode 100644 index 0000000..b5cc3bf --- /dev/null +++ b/apps/server/prisma/migrations/20260708000000_v24_domain_contracts/migration.sql @@ -0,0 +1 @@ +ALTER TABLE "requirements" ALTER COLUMN "status" SET DEFAULT 'pending_review'; diff --git a/apps/server/prisma/schema.prisma b/apps/server/prisma/schema.prisma index c9060f0..a107578 100644 --- a/apps/server/prisma/schema.prisma +++ b/apps/server/prisma/schema.prisma @@ -95,7 +95,7 @@ model Requirement { code String title String description String @default("") - status String @default("draft") + status String @default("pending_review") priority Int @default(0) type String? sourceType String? @map("source_type") diff --git a/apps/server/src/modules/requirement/requirement.service.spec.ts b/apps/server/src/modules/requirement/requirement.service.spec.ts index ecd88c9..5a59e00 100644 --- a/apps/server/src/modules/requirement/requirement.service.spec.ts +++ b/apps/server/src/modules/requirement/requirement.service.spec.ts @@ -42,7 +42,7 @@ describe('RequirementService with V2.2 composite requirement key', () => { prisma.requirement.findFirst.mockResolvedValue({ id: 'req-1', productId: 'product-1', - status: 'draft', + status: 'pending_review', }); prisma.requirement.update.mockResolvedValue({ id: 'req-1', productId: 'product-1' }); @@ -59,7 +59,7 @@ describe('RequirementService with V2.2 composite requirement key', () => { prisma.requirement.findFirst.mockResolvedValue({ id: 'req-1', productId: 'product-1', - status: 'draft', + status: 'pending_review', }); prisma.requirement.delete.mockResolvedValue({ id: 'req-1', productId: 'product-1' }); @@ -69,4 +69,48 @@ describe('RequirementService with V2.2 composite requirement key', () => { where: { id_productId: { id: 'req-1', productId: 'product-1' } }, }); }); + + it.each([ + ['pending_review', 'adopted'], + ['pending_review', 'rejected'], + ['rejected', 'pending_review'], + ['adopted', 'planned'], + ['planned', 'developing'], + ['developing', 'testing'], + ['testing', 'released'], + ['released', 'closed'], + ])('allows current requirement workflow transition %s -> %s', async (fromStatus, toStatus) => { + const { prisma, service } = makeService(); + prisma.requirement.findFirst.mockResolvedValue({ + id: 'req-1', + productId: 'product-1', + status: fromStatus, + }); + prisma.requirement.update.mockResolvedValue({ + id: 'req-1', + productId: 'product-1', + status: toStatus, + }); + + await service.updateStatus('product-1', 'req-1', toStatus); + + expect(prisma.requirement.update).toHaveBeenCalledWith({ + where: { id_productId: { id: 'req-1', productId: 'product-1' } }, + data: { status: toStatus }, + }); + }); + + it('rejects skipping adopted requirements directly to development', async () => { + const { prisma, service } = makeService(); + prisma.requirement.findFirst.mockResolvedValue({ + id: 'req-1', + productId: 'product-1', + status: 'adopted', + }); + + await expect(service.updateStatus('product-1', 'req-1', 'developing')).rejects.toThrow( + '无法从 "adopted" 转换到 "developing"', + ); + expect(prisma.requirement.update).not.toHaveBeenCalled(); + }); }); diff --git a/apps/server/src/modules/requirement/requirement.service.ts b/apps/server/src/modules/requirement/requirement.service.ts index fbe65ab..f6e8b1c 100644 --- a/apps/server/src/modules/requirement/requirement.service.ts +++ b/apps/server/src/modules/requirement/requirement.service.ts @@ -5,11 +5,14 @@ import { CreateRequirementDto } from './dto/create-requirement.dto'; import { UpdateRequirementDto } from './dto/update-requirement.dto'; const VALID_TRANSITIONS: Record = { - [RequirementStatus.DRAFT]: [RequirementStatus.REVIEWING], - [RequirementStatus.REVIEWING]: [RequirementStatus.APPROVED, RequirementStatus.REJECTED], - [RequirementStatus.APPROVED]: [RequirementStatus.DELIVERED], - [RequirementStatus.REJECTED]: [RequirementStatus.DRAFT], - [RequirementStatus.DELIVERED]: [], + [RequirementStatus.PENDING_REVIEW]: [RequirementStatus.ADOPTED, RequirementStatus.REJECTED], + [RequirementStatus.REJECTED]: [RequirementStatus.PENDING_REVIEW], + [RequirementStatus.ADOPTED]: [RequirementStatus.PLANNED], + [RequirementStatus.PLANNED]: [RequirementStatus.DEVELOPING], + [RequirementStatus.DEVELOPING]: [RequirementStatus.TESTING], + [RequirementStatus.TESTING]: [RequirementStatus.RELEASED], + [RequirementStatus.RELEASED]: [RequirementStatus.CLOSED], + [RequirementStatus.CLOSED]: [], }; function createFallbackRequirementCode() { @@ -30,6 +33,7 @@ export class RequirementService { code: dto.code?.trim() || createFallbackRequirementCode(), title: dto.title, description: dto.description || '', + status: RequirementStatus.PENDING_REVIEW, priority: dto.priority ?? 0, creatorId: dto.creatorId, }, diff --git a/apps/web/lib/constants.ts b/apps/web/lib/constants.ts index 0cb74cc..d336a97 100644 --- a/apps/web/lib/constants.ts +++ b/apps/web/lib/constants.ts @@ -1,19 +1,25 @@ import { RequirementStatus } from '@ftb/shared'; export const REQUIREMENT_STATUS_LABEL: Record = { - [RequirementStatus.DRAFT]: '草稿', - [RequirementStatus.REVIEWING]: '评审中', - [RequirementStatus.APPROVED]: '已通过', + [RequirementStatus.PENDING_REVIEW]: '待评审', + [RequirementStatus.ADOPTED]: '已采纳', [RequirementStatus.REJECTED]: '已拒绝', - [RequirementStatus.DELIVERED]: '已交付', + [RequirementStatus.PLANNED]: '已规划', + [RequirementStatus.DEVELOPING]: '开发中', + [RequirementStatus.TESTING]: '测试中', + [RequirementStatus.RELEASED]: '已上线', + [RequirementStatus.CLOSED]: '已关闭', }; export const REQUIREMENT_STATUS_COLOR: Record = { - [RequirementStatus.DRAFT]: 'bg-gray-100 text-gray-700', - [RequirementStatus.REVIEWING]: 'bg-blue-100 text-blue-700', - [RequirementStatus.APPROVED]: 'bg-green-100 text-green-700', + [RequirementStatus.PENDING_REVIEW]: 'bg-zinc-100 text-zinc-700', + [RequirementStatus.ADOPTED]: 'bg-emerald-50 text-emerald-700', [RequirementStatus.REJECTED]: 'bg-red-100 text-red-700', - [RequirementStatus.DELIVERED]: 'bg-purple-100 text-purple-700', + [RequirementStatus.PLANNED]: 'bg-blue-50 text-blue-700', + [RequirementStatus.DEVELOPING]: 'bg-indigo-50 text-indigo-700', + [RequirementStatus.TESTING]: 'bg-purple-50 text-purple-700', + [RequirementStatus.RELEASED]: 'bg-emerald-50 text-emerald-700', + [RequirementStatus.CLOSED]: 'bg-zinc-50 text-zinc-500', }; export const PRIORITY_LABEL: Record = { diff --git a/apps/web/lib/domain-contract.test.ts b/apps/web/lib/domain-contract.test.ts new file mode 100644 index 0000000..37a5c6d --- /dev/null +++ b/apps/web/lib/domain-contract.test.ts @@ -0,0 +1,48 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; + +import { + BugStatus, + DevTaskStatus, + RequirementStatus, + TestCaseStatus, + VersionPlanStatus, + VersionStatus, +} from '@ftb/shared'; + +import type { BugStatus as WebBugStatus } from './bug'; +import type { DevTaskStatus as WebDevTaskStatus } from './dev-task'; +import type { RequirementStatus as WebRequirementStatus } from './requirement'; +import type { TestCaseStatus as WebTestCaseStatus } from './test-case'; +import type { PlanTaskStatus } from './version-plan'; +import type { VersionStatus as WebVersionStatus } from './version-status'; + +test('shared requirement statuses match the current requirement workflow', () => { + const shared = Object.values(RequirementStatus); + const expected: WebRequirementStatus[] = [ + 'pending_review', + 'adopted', + 'rejected', + 'planned', + 'developing', + 'testing', + 'released', + 'closed', + ]; + + assert.deepEqual(shared, expected); +}); + +test('shared execution entity statuses match frontend domain workflows', () => { + const planStatuses: PlanTaskStatus[] = ['pending', 'in_progress', 'completed']; + const devTaskStatuses: WebDevTaskStatus[] = ['todo', 'in_progress', 'testing', 'submitted']; + const testCaseStatuses: WebTestCaseStatus[] = ['pending', 'running', 'passed', 'failed', 'blocked']; + const bugStatuses: WebBugStatus[] = ['open', 'fixing', 'fixed', 'verifying', 'closed', 'rejected']; + const versionStatuses: WebVersionStatus[] = ['developing', 'planned', 'released', 'paused', 'closed']; + + assert.deepEqual(Object.values(VersionPlanStatus), planStatuses); + assert.deepEqual(Object.values(DevTaskStatus), devTaskStatuses); + assert.deepEqual(Object.values(TestCaseStatus), testCaseStatuses); + assert.deepEqual(Object.values(BugStatus), bugStatuses); + assert.deepEqual(Object.values(VersionStatus), versionStatuses); +}); diff --git a/docs/superpowers/plans/2026-07-08-v24-domain-crud-migration.md b/docs/superpowers/plans/2026-07-08-v24-domain-crud-migration.md new file mode 100644 index 0000000..15fb209 --- /dev/null +++ b/docs/superpowers/plans/2026-07-08-v24-domain-crud-migration.md @@ -0,0 +1,236 @@ +# V2.4 Domain CRUD Migration Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Move V2.4.0 through V2.4.5 from AppData-primary writes to domain CRUD primary writes backed by relation tables, while keeping AppData only as compatibility and migration fallback. + +**Architecture:** Keep V2.2 query APIs and V2.3 AppData sync as compatibility infrastructure, then add focused NestJS domain modules that write relation tables directly and reuse Xiaobao dirty marking plus work-activity evidence rules. Frontend stores switch one domain at a time to domain APIs with AppData fallback reads until each AppData document is no longer a source of truth. + +**Tech Stack:** Next.js 14 App Router, Zustand stores, NestJS, Prisma, PostgreSQL partitioned relation tables, Jest, node:test, TypeScript. + +## Global Constraints + +- Work only in `/Users/wanzi/Documents/xiaowanzi-claudecode/ftb-project-management-v24-worktree` on branch `codex/v2.4-domain-crud`. +- Do not edit the original dirty checkout. +- Do not push unless the user explicitly asks. +- Follow TDD: each behavior change starts with a failing test, then minimal implementation, then verification. +- Keep `/workspace` and `/xiaobao-warning` as relation-table read aggregations. +- Keep AppData as compatibility fallback only; do not introduce long-term dual-source writes. +- For partitioned tables, every lookup or mutation must carry the partition key: `productId` for requirements and `versionId` for version detail entities. +- `pnpm lint` is not a V2.4 gate until the baseline ESLint setup is fixed; current baseline fails because server/shared lint tooling is missing. + +--- + +### Task 1: V2.4.0 Domain Contract Unification + +**Files:** +- Modify: `packages/shared/src/enums.ts` +- Modify: `packages/shared/src/index.ts` +- Modify: `apps/server/src/modules/requirement/requirement.service.spec.ts` +- Modify: `apps/server/src/modules/requirement/requirement.service.ts` +- Modify: `apps/server/src/modules/requirement/dto/update-requirement-status.dto.ts` +- Modify: `apps/web/lib/requirement.ts` +- Modify: `apps/web/lib/dev-task.ts` +- Modify: `apps/web/lib/test-case.ts` +- Modify: `apps/web/lib/bug.ts` +- Modify: `apps/web/lib/version-plan.ts` + +**Interfaces:** +- Produces: shared status constants/enums for Requirement, VersionPlan, DevTask, TestCase, Bug, and Version. +- Consumes: current frontend status values documented in `docs/architecture.md`. + +- [x] Add failing shared contract tests proving shared statuses equal current frontend statuses. +- [x] Add failing backend tests proving Requirement transitions use `pending_review -> adopted/rejected`, `rejected -> pending_review`, and `adopted -> planned -> developing -> testing -> released -> closed`. +- [x] Replace old shared `draft/reviewing/approved/delivered` requirement status contract with current domain statuses. +- [x] Add shared contracts for `VersionPlanStatus`, `DevTaskStatus`, `TestCaseStatus`, `BugStatus`, and `VersionStatus`. +- [x] Update backend Requirement DTO validation and service transition table. +- [x] Run targeted tests: `pnpm --filter server test -- requirement.service.spec.ts` and shared/web tests added in this task. +- [x] Run gates: `pnpm type-check`, `pnpm test`, `pnpm build`, `DATABASE_URL=postgresql://postgres:postgres@localhost:5432/ftb_pm pnpm --filter server exec prisma validate --schema prisma/schema.prisma`, `pnpm deploy:verify`. +- [x] Commit: `feat(v2.4): 统一领域状态契约`. + +### Task 2: V2.4.1 Product / Project / Version Root Main Writes + +**Files:** +- Create: `apps/server/src/modules/project/project.module.ts` +- Create: `apps/server/src/modules/project/project.controller.ts` +- Create: `apps/server/src/modules/project/project.service.ts` +- Create: `apps/server/src/modules/project/dto/create-project.dto.ts` +- Create: `apps/server/src/modules/project/dto/update-project.dto.ts` +- Create: `apps/server/src/modules/project/project.service.spec.ts` +- Create: `apps/server/src/modules/version/version.module.ts` +- Create: `apps/server/src/modules/version/version.controller.ts` +- Create: `apps/server/src/modules/version/version.service.ts` +- Create: `apps/server/src/modules/version/dto/create-version.dto.ts` +- Create: `apps/server/src/modules/version/dto/update-version.dto.ts` +- Create: `apps/server/src/modules/version/version.service.spec.ts` +- Modify: `apps/server/src/modules/product/product.service.ts` +- Modify: `apps/server/src/app.module.ts` +- Create: `apps/web/lib/domain-api.ts` +- Modify: `apps/web/stores/useProductStore.ts` +- Modify: `apps/web/lib/product-overview-persistence.test.ts` +- Modify: `apps/web/lib/product-store-persistence-source.test.ts` + +**Interfaces:** +- Produces: `/api/v1/products`, `/api/v1/products/:productId/projects`, `/api/v1/products/:productId/versions`, and `/api/v1/products/:productId/projects/:projectId/versions`. +- Consumes: existing product/project/version tree shape from `products-overview`. + +- [ ] Add failing backend tests for project create/list/update/delete by `productId`. +- [ ] Add failing backend tests for version create/list/update/delete by `productId` and optional `projectId`. +- [ ] Add failing tests proving deleting a version releases linked requirements and deletes version-scoped plans/tasks/test cases/bugs. +- [ ] Add failing frontend tests proving `useProductStore` saves root mutations through domain APIs and falls back to `products-overview` when APIs are unavailable. +- [ ] Implement Project and Version modules with conservative DTO validation. +- [ ] Keep Product CRUD as the top-level root and add child include helpers only where needed. +- [ ] Switch Product store mutations to domain APIs while retaining AppData compatibility read. +- [ ] Run targeted backend and frontend tests. +- [ ] Run full gates and commit: `feat(v2.4): 切换根数据领域主写`. + +### Task 3: V2.4.2 Requirement Main Writes And Server Pagination + +**Files:** +- Modify: `apps/server/src/modules/requirement/requirement.controller.ts` +- Modify: `apps/server/src/modules/requirement/requirement.service.ts` +- Modify: `apps/server/src/modules/requirement/dto/create-requirement.dto.ts` +- Modify: `apps/server/src/modules/requirement/dto/update-requirement.dto.ts` +- Modify: `apps/server/src/modules/requirement/requirement.service.spec.ts` +- Modify: `apps/server/src/modules/v22-query/v22-query.service.ts` +- Modify: `apps/web/lib/requirement-v22-query.ts` +- Modify: `apps/web/stores/useRequirementStore.ts` +- Modify: `apps/web/lib/requirement-sort.test.ts` +- Modify: `apps/web/lib/requirement-v22-query.test.ts` + +**Interfaces:** +- Produces: requirement create/update/delete/status/link APIs that write `requirements` directly by `(id, productId)`. +- Produces: server-side list contract with `productId`, `projectId`, `versionId`, `status`, `priority`, `type`, `q`, `sort`, `cursor`, and `limit`. + +- [ ] Add failing backend tests for server pagination, search, filters, sort, cursor, and partition-key validation. +- [ ] Add failing tests for create/update fields currently present in frontend requirements: `projectId`, `versionId`, `type`, `sourceType`, `sourceTarget`, and `platform`. +- [ ] Add failing frontend tests proving requirement pool calls server pagination and does not require loading the full AppData document for list/search/filter/sort. +- [ ] Implement service-side query parsing and safe order fields. +- [ ] Switch `useRequirementStore` create/update/delete/status/link writes to Requirement APIs. +- [ ] Keep AppData read fallback only when relation API is unavailable. +- [ ] Run targeted tests and full gates. +- [ ] Commit: `feat(v2.4): 切换需求池领域主写`. + +### Task 4: V2.4.3 VersionPlan / DevTask Main Writes + +**Files:** +- Create: `apps/server/src/modules/version-plan/version-plan.module.ts` +- Create: `apps/server/src/modules/version-plan/version-plan.controller.ts` +- Create: `apps/server/src/modules/version-plan/version-plan.service.ts` +- Create: `apps/server/src/modules/version-plan/dto/create-version-plan.dto.ts` +- Create: `apps/server/src/modules/version-plan/dto/update-version-plan.dto.ts` +- Create: `apps/server/src/modules/version-plan/version-plan.service.spec.ts` +- Create: `apps/server/src/modules/dev-task/dev-task.module.ts` +- Create: `apps/server/src/modules/dev-task/dev-task.controller.ts` +- Create: `apps/server/src/modules/dev-task/dev-task.service.ts` +- Create: `apps/server/src/modules/dev-task/dto/create-dev-task.dto.ts` +- Create: `apps/server/src/modules/dev-task/dto/update-dev-task.dto.ts` +- Create: `apps/server/src/modules/dev-task/dev-task.service.spec.ts` +- Create: `apps/server/src/modules/work-activity/work-activity.module.ts` +- Create: `apps/server/src/modules/work-activity/work-activity.service.ts` +- Create: `apps/server/src/modules/work-activity/work-activity.service.spec.ts` +- Modify: `apps/server/src/modules/migration/app-data-v23-sync.service.ts` +- Modify: `apps/server/src/app.module.ts` +- Modify: `apps/web/stores/useVersionPlanStore.ts` +- Modify: `apps/web/stores/useDevTaskStore.ts` +- Modify: `apps/web/stores/useWorkActivityStore.ts` +- Modify: `apps/web/lib/version-plan.test.ts` +- Modify: `apps/web/lib/version-plan-workflow.test.ts` +- Modify: `apps/web/lib/dev-task.test.ts` +- Modify: `apps/web/lib/dev-task-transitions.test.ts` + +**Interfaces:** +- Produces: `/api/v1/versions/:versionId/plans` and `/api/v1/versions/:versionId/dev-tasks`. +- Produces: minimal relational `WorkActivityService.record()` for successful plan/task domain actions. + +- [ ] Add failing backend tests for VersionPlan create/update/status/complete writing `version_plans`. +- [ ] Add failing backend tests for DevTask create/update/status/block/unblock/transfer writing `dev_tasks` by `(id, versionId)`. +- [ ] Add failing backend tests proving status changes create `work_activities` records and mark Xiaobao summaries dirty. +- [ ] Add failing frontend tests proving plan/task stores write domain APIs and append activity evidence from API responses. +- [ ] Implement VersionPlan and DevTask modules using existing frontend workflow rules as the contract. +- [ ] Add minimal WorkActivity service and reuse V2.3 dirty-summary strategy. +- [ ] Switch version plan and dev task stores to domain writes with AppData fallback read only. +- [ ] Run targeted tests and full gates. +- [ ] Commit: `feat(v2.4): 切换计划与开发任务主写`. + +### Task 5: V2.4.4 TestCase / Bug Main Writes + +**Files:** +- Create: `apps/server/src/modules/test-case/test-case.module.ts` +- Create: `apps/server/src/modules/test-case/test-case.controller.ts` +- Create: `apps/server/src/modules/test-case/test-case.service.ts` +- Create: `apps/server/src/modules/test-case/dto/create-test-case.dto.ts` +- Create: `apps/server/src/modules/test-case/dto/update-test-case.dto.ts` +- Create: `apps/server/src/modules/test-case/test-case.service.spec.ts` +- Create: `apps/server/src/modules/bug/bug.module.ts` +- Create: `apps/server/src/modules/bug/bug.controller.ts` +- Create: `apps/server/src/modules/bug/bug.service.ts` +- Create: `apps/server/src/modules/bug/dto/create-bug.dto.ts` +- Create: `apps/server/src/modules/bug/dto/update-bug.dto.ts` +- Create: `apps/server/src/modules/bug/bug.service.spec.ts` +- Modify: `apps/server/src/modules/work-activity/work-activity.service.ts` +- Modify: `apps/server/src/app.module.ts` +- Modify: `apps/web/stores/useTestCaseStore.ts` +- Modify: `apps/web/stores/useBugStore.ts` +- Modify: `apps/web/lib/test-case.test.ts` +- Modify: `apps/web/lib/test-case-workflow.test.ts` +- Modify: `apps/web/lib/bug.test.ts` +- Modify: `apps/web/lib/bug-workflow.test.ts` + +**Interfaces:** +- Produces: `/api/v1/versions/:versionId/test-cases` and `/api/v1/versions/:versionId/bugs`. +- Consumes: TestCase round-copy workflow and Bug status workflow already defined in frontend helpers. + +- [ ] Add failing backend tests for TestCase create/update/status/round-copy by `(id, versionId)`. +- [ ] Add failing backend tests for Bug create/update/status/transfer/close by `(id, versionId)`. +- [ ] Add failing tests proving TestCase/Bug writes create activity evidence and mark Xiaobao dirty. +- [ ] Add failing frontend tests proving stores write domain APIs and preserve existing workflow outputs. +- [ ] Implement TestCase and Bug modules. +- [ ] Switch test case and bug stores to domain writes with AppData fallback read only. +- [ ] Run targeted tests and full gates. +- [ ] Commit: `feat(v2.4): 切换测试与缺陷主写`. + +### Task 6: V2.4.5 Dictionaries, Members, Worklogs, Overtime, Activity Evidence Consolidation + +**Files:** +- Create: `apps/server/src/modules/member/member.module.ts` +- Create: `apps/server/src/modules/member/member.controller.ts` +- Create: `apps/server/src/modules/member/member.service.ts` +- Create: `apps/server/src/modules/member/member.service.spec.ts` +- Create: `apps/server/src/modules/task-category/task-category.module.ts` +- Create: `apps/server/src/modules/task-category/task-category.controller.ts` +- Create: `apps/server/src/modules/task-category/task-category.service.ts` +- Create: `apps/server/src/modules/task-category/task-category.service.spec.ts` +- Create: `apps/server/src/modules/task-worklog/task-worklog.module.ts` +- Create: `apps/server/src/modules/task-worklog/task-worklog.controller.ts` +- Create: `apps/server/src/modules/task-worklog/task-worklog.service.ts` +- Create: `apps/server/src/modules/task-worklog/task-worklog.service.spec.ts` +- Create: `apps/server/src/modules/overtime/overtime.module.ts` +- Create: `apps/server/src/modules/overtime/overtime.controller.ts` +- Create: `apps/server/src/modules/overtime/overtime.service.ts` +- Create: `apps/server/src/modules/overtime/overtime.service.spec.ts` +- Modify: `apps/server/src/modules/work-activity/work-activity.service.ts` +- Modify: `apps/server/src/app.module.ts` +- Modify: `apps/web/stores/useMemberStore.ts` +- Modify: `apps/web/stores/useTaskCategoryStore.ts` +- Modify: `apps/web/stores/useTaskWorklogStore.ts` +- Modify: `apps/web/stores/useOvertimeStore.ts` +- Modify: `apps/web/stores/useWorkActivityStore.ts` +- Modify: `docs/architecture.md` +- Modify: `docs/decisions.md` +- Modify: `docs/roadmap.md` +- Modify: `docs/workflow.md` + +**Interfaces:** +- Produces: domain APIs for members, task categories, task worklogs, overtime records, and activity records. +- Consumes: existing AppData keys only for compatibility import/fallback during the transition. + +- [ ] Add failing backend tests for member CRUD, protected built-in admin behavior, and role/department fields used by the UI. +- [ ] Add failing backend tests for task category CRUD and uniqueness by `(group, name)`. +- [ ] Add failing backend tests for append-style TaskWorklog, OvertimeRecord, and WorkActivity writes. +- [ ] Add failing frontend tests proving dictionary/member/evidence stores no longer save AppData as the main write path. +- [ ] Implement the remaining domain modules. +- [ ] Switch stores to domain writes, preserving fallback reads and current UI data shapes. +- [ ] Update architecture, decisions, workflow, and roadmap to mark V2.4.0-V2.4.5 complete and clarify AppData is now compatibility/migration fallback. +- [ ] Run full gates: `pnpm type-check`, `pnpm test`, `pnpm build`, `DATABASE_URL=postgresql://postgres:postgres@localhost:5432/ftb_pm pnpm --filter server exec prisma validate --schema prisma/schema.prisma`, `pnpm deploy:verify`. +- [ ] Commit: `feat(v2.4): 完成领域主写迁移`. diff --git a/packages/shared/src/enums.ts b/packages/shared/src/enums.ts index a13c269..92af662 100644 --- a/packages/shared/src/enums.ts +++ b/packages/shared/src/enums.ts @@ -1,8 +1,45 @@ export enum TaskStatus { TODO = 'todo', IN_PROGRESS = 'in_progress', - IN_REVIEW = 'in_review', - DONE = 'done', + TESTING = 'testing', + SUBMITTED = 'submitted', +} + +export enum DevTaskStatus { + TODO = 'todo', + IN_PROGRESS = 'in_progress', + TESTING = 'testing', + SUBMITTED = 'submitted', +} + +export enum VersionPlanStatus { + PENDING = 'pending', + IN_PROGRESS = 'in_progress', + COMPLETED = 'completed', +} + +export enum TestCaseStatus { + PENDING = 'pending', + RUNNING = 'running', + PASSED = 'passed', + FAILED = 'failed', + BLOCKED = 'blocked', +} + +export enum BugStatus { + OPEN = 'open', + FIXING = 'fixing', + FIXED = 'fixed', + VERIFYING = 'verifying', + CLOSED = 'closed', + REJECTED = 'rejected', +} + +export enum VersionStatus { + DEVELOPING = 'developing', + PLANNED = 'planned', + RELEASED = 'released', + PAUSED = 'paused', CLOSED = 'closed', } @@ -14,9 +51,12 @@ export enum ProjectRole { } export enum RequirementStatus { - DRAFT = 'draft', - REVIEWING = 'reviewing', - APPROVED = 'approved', + PENDING_REVIEW = 'pending_review', + ADOPTED = 'adopted', REJECTED = 'rejected', - DELIVERED = 'delivered', + PLANNED = 'planned', + DEVELOPING = 'developing', + TESTING = 'testing', + RELEASED = 'released', + CLOSED = 'closed', }