9.4 KiB
9.4 KiB
PMFlow Dev Plan — User / Skill / Workload Modules
Stack: FastAPI + React + shadcn/ui + Tailwind | Timeline: ~11 days, 1 dev
Phase 1 — Core Foundation (Day 1–3)
Day 1 — DB Migration + User CRUD
DB
ALTER TABLE users ADD COLUMN is_active BOOLEAN NOT NULL DEFAULT TRUE;
CREATE TABLE user_projects (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL DEFAULT 1,
user_id BIGINT NOT NULL,
project_id BIGINT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES tenants(id),
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (project_id) REFERENCES projects(id),
UNIQUE(tenant_id, user_id, project_id)
);
Backend
- Update ORM:
User.is_active, newUserProjectmodel GET /api/users— paginated list with filters (role/status/project/workload/skill)POST /api/users— create user (bcrypt password, auto-inituser_workloadsrow with 40h/week)PUT /api/users/{id}— update userDELETE /api/users/{id}— block if user has incomplete tasksPOST /api/users/{id}/reset-passwordPATCH /api/users/{id}/status— disable: cleartasks.assignee_id, zero out workloadPOST /api/users/import— bulk import via Excel (max 50 rows, return per-row result)- Transaction: delete user → cascade delete
user_skill_bindings+user_workloads - Log all mutations (actor, time, diff)
Frontend
- Routes:
/users,/skills,/workloads,/workloads/:id /userspage: top bar (title + New/Import/Bulk-delete buttons + search)- Right filter panel (280px, collapsible): role / status / project / workload-state / skill multi-select
- Table: avatar+name / email / role badge / linked projects / top-3 skill tags / workload% / status / actions
- New/Edit user modal (form validation, edit pre-fills data)
- Reset password modal
- Bulk import modal (preview first 10 rows, highlight errors, show import result summary)
- Workload% color: green <70%, yellow 70–100%, red >100%
Day 2 — Skill & Workload APIs
Backend — Skills
- Seed system skill tags on startup (Python, FastAPI, LangChain, React, Prompt Eng, etc.)
GET /api/skill-tags— list with category filterPOST /api/skill-tags— admin onlyPUT /api/skill-tags/{id}— system tags: category only; custom: name + categoryDELETE /api/skill-tags/{id}— block ifis_system=true; cascade deleteuser_skill_bindingsGET /api/users/{id}/skills— user skill bindingsPOST /api/users/{id}/skills— bind skill (default: beginner, scores 0.0)PUT /api/users/{id}/skills/{skill_id}— update proficiency / scoresDELETE /api/users/{id}/skills/{skill_id}— unbind (block system-auto-bound skills)
Backend — Workload
- Workload calc util:
ratio = assigned_hours / ((max_weekly_hours / 5) * remaining_workdays) GET /api/workloads— team list with project/date filtersGET /api/workloads/{user_id}— personal detailPUT /api/workloads/{user_id}— update max weekly hours (triggers ratio recalc)GET /api/workloads/{user_id}/tasks— assigned task listGET /api/workloads/{user_id}/trend— daily ratio for last 7/30 days- Cron job at 00:00 daily: recalc ratio for all users based on updated remaining workdays
- Auto-trigger ratio recalc on: task assign / estimate change / task complete / task delete
Day 3 — Skill & Workload Frontend
Frontend — Skill Tags (/skills)
- Table: name / category badge / linked-user count / actions
- System tags: show "System" label, disable delete, disable name edit
- New/Edit skill tag modal
- Category badge colors: dev=blue / algorithm=purple / product=orange / pm=green / qa=gray
Frontend — User Skill Detail (/users/:id/skills)
- Top bar: avatar / name / role / linked projects / "Batch Edit" + "Refresh Scores" buttons
- Left 60%: skills grouped by category (collapsible), each row: name / proficiency dropdown / quality score / efficiency score / last used (read-only)
- "Remove" button per row (disabled for system-bound skills)
- "Add Skill" button → modal to select skill tags
- Right 40%: recharts
RadarChart— weighted score per skill, filter by category, hover shows detail - "Export Chart" button (save as image)
Frontend — Team Workload (/workloads)
- Filter bar: project select + date range (this week / this month / custom)
- 3 stat cards: avg team ratio / headcount by state (idle/normal/overloaded) / AI alert summary
- Table: member info / projects / assigned hours / max weekly hours / ratio% / remaining hours / actions
- Overloaded rows: red highlight + warning icon
Frontend — Personal Workload (/workloads/:id)
- Header: ratio% / remaining hours / "Adjust Hours" button
- recharts
LineChart: daily ratio trend (7d/30d toggle), 70% + 100% reference lines, overloaded segments in red - Task list table: title / project / priority / est. hours / due date / status / view link
- Task list filters: status / priority / due date
Phase 2 — Sync Logic + AI (Day 4–8)
Day 4–5 — Cross-module Sync
Backend
- User create → init empty
user_skill_bindings, inituser_workloads - User delete → transaction: delete bindings + workload record
- User disable → zero
current_assigned_hours+workload_ratio, clear task assignments - Skill score update → recalc top-3 skills for user, sync to user list response
- Workload ratio change → sync to user list
workload_ratiofield - Skill proficiency level → pass to task estimation: expert → lower est. hours → lower ratio
Frontend
- User list table: workload% and top-3 skill tags update without page reload (TanStack Query invalidation)
- Skill detail page: manual score edit shows warning "AI will overwrite on next update"
- Workload team table: ratio column updates in real-time after task changes
Day 6–7 — SSTC Kanban Integration
Backend
- Task assign endpoint: filter candidates to current-project users only, exclude disabled users
GET /api/tasks/recommend-assignees?task_id=— rank users by skill match + proficiency + ratio (<70% preferred)- Task status →
done: trigger async job to updatecurrent_assigned_hours(subtract est. hours) and recalc ratio GET /api/workloads/summary— team health card data for kanban top bar
Frontend
- SSTC kanban top bar: "Team Workload Health" card (avg ratio + overload count), click →
/workloads - Task breakdown panel: recommended assignees list shows name / role / top skills / ratio badge
- Assignee dropdown: disabled users grayed out and unselectable
- Task status change → trigger workload refetch (TanStack Query)
Day 8 — AI Features
Backend
- New LangChain prompt: skill score update — input: task quality_score + (est_hours / actual_hours), output: quality/efficiency score delta per skill tag
- Trigger on
tasks.status = done: async call above prompt, apply weighted update (higher priority task = higher weight) - New LangChain prompt: workload optimization — input: all members' skills + ratios, output: suggested task reassignments
POST /api/workloads/ai-optimize— run optimization, return preview plan (no auto-apply)POST /api/workloads/ai-optimize/apply— apply approved plan (batch updatetasks.assignee_id)- Overload alert: ratio >100% → send notification (Feishu/email); if unresolved 24h → auto-generate transfer suggestion
Frontend
- "AI Optimize Assignments" button → show optimization preview modal (old vs new assignee per task)
- Confirm → apply; Cancel → discard
- Overload alert banner on team workload page when any member >100%
Phase 3 — Polish (Day 9–11)
Day 9 — Filters / Export / Bulk Actions
- Verify all filter combinations work correctly across all 3 pages
- Export workload report (Excel/PDF)
- Export skill radar chart (PNG)
- Bulk delete users (with incomplete-task guard)
- Bulk assign project / role to selected users
Day 10 — Permissions
| Role | Users | Skills | Workload |
|---|---|---|---|
| admin | Full | Full | Full |
| manager | Own project users (no delete) | Bind/edit scores for own project | View + optimize own project |
| member | View all + edit own profile | View own + edit own proficiency | View own + edit own weekly hours |
- Backend: permission middleware on all mutation endpoints
- Frontend: route guards + button-level permission checks
Day 11 — Final QA
- Dark mode audit across all new pages
- Empty state / loading state / error state for all tables and cards
- Toast notifications for all CRUD operations
- End-to-end flow test: create user → bind skills → assign task → complete task → verify score + workload update
- Fix bugs, merge
Reference
Workload ratio formula:
ratio = current_assigned_hours / ((max_weekly_hours / 5) * remaining_workdays_this_week)
Ratio recalc triggers: task assign · est hours change · task complete · task delete · weekly hours update · daily cron
API response format:
{ "code": 200, "message": "ok", "data": {} }