feat: 完成 R13/R14/R15/R16 小团队管理核心能力

这个提交包含在:
2026-03-21 20:31:34 +08:00
父节点 0826693a8f
当前提交 1e52f1c225
共修改 47 个文件,包含 4298 行新增和 306 行删除
+243 -13
查看文件
@@ -265,6 +265,105 @@ enum BudgetControlRuleEntityType {
travel_request
}
enum WorkspaceProfile {
small_team_internal
}
enum WorkspaceOrgMode {
single_company
}
enum WorkspacePrimaryEntryMode {
password
}
enum WorkspaceNotificationStrategy {
in_app
}
enum WorkspaceDevicePriority {
desktop
}
enum EmploymentLifecycleStatus {
onboarding
probation
active
offboarding
inactive
}
enum EmployeeLifecycleEventType {
onboard
regularize
transfer
offboard
}
enum EmployeeChecklistScene {
onboarding
offboarding
transfer
}
enum EmployeeChecklistTaskType {
account_setup
asset_issue
policy_ack
asset_return
access_revoke
expense_clearance
handover_note
}
enum EmployeeChecklistTaskStatus {
pending
completed
skipped
}
enum EmployeePresenceStatus {
office
remote
out
travel
leave
}
enum EmployeePresenceTimeRange {
full_day
morning
afternoon
}
enum EmployeePresenceSource {
manual
leave_sync
}
enum WeeklyReportStatus {
draft
submitted
}
enum TodoPriority {
low
normal
high
}
enum TodoStatus {
todo
doing
done
cancelled
}
enum TodoSource {
manual
weekly_report
}
model Department {
id String @id @default(uuid()) @db.Uuid
name String
@@ -296,17 +395,24 @@ model Department {
}
model Employee {
id String @id @default(uuid()) @db.Uuid
employee_no String @unique
name String
phone String @unique
email String @unique
department_id String @db.Uuid
legal_entity_id String? @db.Uuid
title String
direct_manager_id String? @db.Uuid
hire_date DateTime @db.Date
status EmployeeStatus @default(active)
id String @id @default(uuid()) @db.Uuid
employee_no String @unique
name String
phone String @unique
email String @unique
department_id String @db.Uuid
legal_entity_id String? @db.Uuid
title String
direct_manager_id String? @db.Uuid
hire_date DateTime @db.Date
status EmployeeStatus @default(active)
employment_status EmploymentLifecycleStatus @default(active)
probation_end_date DateTime? @db.Date
last_working_date DateTime? @db.Date
work_location String?
emergency_contact_name String?
emergency_contact_phone String?
notes String?
bank_account_encrypted String
bank_name String
@@ -373,9 +479,15 @@ model Employee {
workflow_tasks_assigned WorkflowTask[] @relation("WorkflowTaskAssignee")
workflow_tasks_completed WorkflowTask[] @relation("WorkflowTaskCompleter")
approval_transfers_from ApprovalTransfer[] @relation("TransferFrom")
approval_transfers_to ApprovalTransfer[] @relation("TransferTo")
approval_transfers_from ApprovalTransfer[] @relation("TransferFrom")
approval_transfers_to ApprovalTransfer[] @relation("TransferTo")
password_reset_codes PasswordResetCode[]
lifecycle_events EmployeeLifecycleEvent[]
checklist_tasks EmployeeChecklistTask[]
presence_records EmployeePresence[]
weekly_reports WeeklyReport[]
todo_items_assigned TodoItem[] @relation("TodoAssignee")
todo_items_created TodoItem[] @relation("TodoCreator")
@@index([department_id])
@@index([legal_entity_id], map: "idx_employees_legal_entity")
@@ -1408,6 +1520,124 @@ model PortalAnnouncement {
@@map("portal_announcements")
}
model WorkspaceSetting {
id String @id @default(uuid()) @db.Uuid
profile WorkspaceProfile @default(small_team_internal)
org_mode WorkspaceOrgMode @default(single_company)
primary_entry_mode WorkspacePrimaryEntryMode @default(password)
notification_strategy WorkspaceNotificationStrategy @default(in_app)
device_priority WorkspaceDevicePriority @default(desktop)
module_visibility_json Json?
created_at DateTime @default(now())
updated_at DateTime @default(now()) @updatedAt
updated_by String? @db.Uuid
@@map("workspace_settings")
}
model EmployeeLifecycleEvent {
id String @id @default(uuid()) @db.Uuid
employee_id String @db.Uuid
event_type EmployeeLifecycleEventType
effective_date DateTime @db.Date
payload_json Json?
created_at DateTime @default(now())
created_by String? @db.Uuid
employee Employee @relation(fields: [employee_id], references: [id], onDelete: Cascade)
@@index([employee_id, effective_date], map: "idx_employee_lifecycle_events_employee_date")
@@index([event_type, created_at], map: "idx_employee_lifecycle_events_type_created")
@@map("employee_lifecycle_events")
}
model EmployeeChecklistTask {
id String @id @default(uuid()) @db.Uuid
employee_id String @db.Uuid
scene EmployeeChecklistScene
task_type EmployeeChecklistTaskType
title String
status EmployeeChecklistTaskStatus @default(pending)
due_date DateTime? @db.Date
completed_at DateTime?
completed_by String? @db.Uuid
payload_json Json?
created_at DateTime @default(now())
employee Employee @relation(fields: [employee_id], references: [id], onDelete: Cascade)
@@index([employee_id, scene, status], map: "idx_employee_checklist_tasks_employee_scene_status")
@@index([scene, due_date], map: "idx_employee_checklist_tasks_scene_due")
@@map("employee_checklist_tasks")
}
model EmployeePresence {
id String @id @default(uuid()) @db.Uuid
employee_id String @db.Uuid
date DateTime @db.Date
status EmployeePresenceStatus
time_range EmployeePresenceTimeRange @default(full_day)
note String?
source EmployeePresenceSource @default(manual)
created_at DateTime @default(now())
updated_at DateTime @default(now()) @updatedAt
updated_by String? @db.Uuid
employee Employee @relation(fields: [employee_id], references: [id], onDelete: Cascade)
@@unique([employee_id, date], map: "employee_presence_employee_date_ux")
@@index([date, status], map: "idx_employee_presence_date_status")
@@map("employee_presence")
}
model WeeklyReport {
id String @id @default(uuid()) @db.Uuid
employee_id String @db.Uuid
week_start DateTime @db.Date
status WeeklyReportStatus @default(draft)
highlights_text String @default("")
blockers_text String @default("")
next_week_text String @default("")
needs_help Boolean @default(false)
submitted_at DateTime?
created_at DateTime @default(now())
updated_at DateTime @default(now()) @updatedAt
employee Employee @relation(fields: [employee_id], references: [id], onDelete: Cascade)
@@unique([employee_id, week_start], map: "weekly_reports_employee_week_start_ux")
@@index([week_start, status], map: "idx_weekly_reports_week_status")
@@map("weekly_reports")
}
model TodoItem {
id String @id @default(uuid()) @db.Uuid
title String
description String?
assignee_employee_id String @db.Uuid
created_by String @db.Uuid
due_date DateTime? @db.Date
priority TodoPriority @default(normal)
status TodoStatus @default(todo)
source TodoSource @default(manual)
created_at DateTime @default(now())
updated_at DateTime @default(now()) @updatedAt
completed_at DateTime?
assignee Employee @relation("TodoAssignee", fields: [assignee_employee_id], references: [id], onDelete: Restrict)
creator Employee @relation("TodoCreator", fields: [created_by], references: [id], onDelete: Restrict)
@@index([assignee_employee_id, status, due_date], map: "idx_todo_items_assignee_status_due")
@@index([created_by, created_at], map: "idx_todo_items_creator_created")
@@map("todo_items")
}
model MigrationRun {
id String @id @default(uuid()) @db.Uuid
run_type String @db.VarChar(32)