feat: 完成 R13/R14/R15/R16 小团队管理核心能力
这个提交包含在:
@@ -0,0 +1,205 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "WorkspaceProfile" AS ENUM ('small_team_internal');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "WorkspaceOrgMode" AS ENUM ('single_company');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "WorkspacePrimaryEntryMode" AS ENUM ('password');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "WorkspaceNotificationStrategy" AS ENUM ('in_app');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "WorkspaceDevicePriority" AS ENUM ('desktop');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "EmploymentLifecycleStatus" AS ENUM ('onboarding', 'probation', 'active', 'offboarding', 'inactive');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "EmployeeLifecycleEventType" AS ENUM ('onboard', 'regularize', 'transfer', 'offboard');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "EmployeeChecklistScene" AS ENUM ('onboarding', 'offboarding', 'transfer');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "EmployeeChecklistTaskType" AS ENUM ('account_setup', 'asset_issue', 'policy_ack', 'asset_return', 'access_revoke', 'expense_clearance', 'handover_note');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "EmployeeChecklistTaskStatus" AS ENUM ('pending', 'completed', 'skipped');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "EmployeePresenceStatus" AS ENUM ('office', 'remote', 'out', 'travel', 'leave');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "EmployeePresenceTimeRange" AS ENUM ('full_day', 'morning', 'afternoon');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "EmployeePresenceSource" AS ENUM ('manual', 'leave_sync');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "WeeklyReportStatus" AS ENUM ('draft', 'submitted');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "TodoPriority" AS ENUM ('low', 'normal', 'high');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "TodoStatus" AS ENUM ('todo', 'doing', 'done', 'cancelled');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "TodoSource" AS ENUM ('manual', 'weekly_report');
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "employees" ADD COLUMN "emergency_contact_name" TEXT,
|
||||
ADD COLUMN "emergency_contact_phone" TEXT,
|
||||
ADD COLUMN "employment_status" "EmploymentLifecycleStatus" NOT NULL DEFAULT 'active',
|
||||
ADD COLUMN "last_working_date" DATE,
|
||||
ADD COLUMN "notes" TEXT,
|
||||
ADD COLUMN "probation_end_date" DATE,
|
||||
ADD COLUMN "work_location" TEXT;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "workspace_settings" (
|
||||
"id" UUID NOT NULL,
|
||||
"profile" "WorkspaceProfile" NOT NULL DEFAULT 'small_team_internal',
|
||||
"org_mode" "WorkspaceOrgMode" NOT NULL DEFAULT 'single_company',
|
||||
"primary_entry_mode" "WorkspacePrimaryEntryMode" NOT NULL DEFAULT 'password',
|
||||
"notification_strategy" "WorkspaceNotificationStrategy" NOT NULL DEFAULT 'in_app',
|
||||
"device_priority" "WorkspaceDevicePriority" NOT NULL DEFAULT 'desktop',
|
||||
"module_visibility_json" JSONB,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_by" UUID,
|
||||
|
||||
CONSTRAINT "workspace_settings_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "employee_lifecycle_events" (
|
||||
"id" UUID NOT NULL,
|
||||
"employee_id" UUID NOT NULL,
|
||||
"event_type" "EmployeeLifecycleEventType" NOT NULL,
|
||||
"effective_date" DATE NOT NULL,
|
||||
"payload_json" JSONB,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"created_by" UUID,
|
||||
|
||||
CONSTRAINT "employee_lifecycle_events_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "employee_checklist_tasks" (
|
||||
"id" UUID NOT NULL,
|
||||
"employee_id" UUID NOT NULL,
|
||||
"scene" "EmployeeChecklistScene" NOT NULL,
|
||||
"task_type" "EmployeeChecklistTaskType" NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"status" "EmployeeChecklistTaskStatus" NOT NULL DEFAULT 'pending',
|
||||
"due_date" DATE,
|
||||
"completed_at" TIMESTAMP(3),
|
||||
"completed_by" UUID,
|
||||
"payload_json" JSONB,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "employee_checklist_tasks_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "employee_presence" (
|
||||
"id" UUID NOT NULL,
|
||||
"employee_id" UUID NOT NULL,
|
||||
"date" DATE NOT NULL,
|
||||
"status" "EmployeePresenceStatus" NOT NULL,
|
||||
"time_range" "EmployeePresenceTimeRange" NOT NULL DEFAULT 'full_day',
|
||||
"note" TEXT,
|
||||
"source" "EmployeePresenceSource" NOT NULL DEFAULT 'manual',
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_by" UUID,
|
||||
|
||||
CONSTRAINT "employee_presence_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "weekly_reports" (
|
||||
"id" UUID NOT NULL,
|
||||
"employee_id" UUID NOT NULL,
|
||||
"week_start" DATE NOT NULL,
|
||||
"status" "WeeklyReportStatus" NOT NULL DEFAULT 'draft',
|
||||
"highlights_text" TEXT NOT NULL DEFAULT '',
|
||||
"blockers_text" TEXT NOT NULL DEFAULT '',
|
||||
"next_week_text" TEXT NOT NULL DEFAULT '',
|
||||
"needs_help" BOOLEAN NOT NULL DEFAULT false,
|
||||
"submitted_at" TIMESTAMP(3),
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "weekly_reports_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "todo_items" (
|
||||
"id" UUID NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"assignee_employee_id" UUID NOT NULL,
|
||||
"created_by" UUID NOT NULL,
|
||||
"due_date" DATE,
|
||||
"priority" "TodoPriority" NOT NULL DEFAULT 'normal',
|
||||
"status" "TodoStatus" NOT NULL DEFAULT 'todo',
|
||||
"source" "TodoSource" NOT NULL DEFAULT 'manual',
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"completed_at" TIMESTAMP(3),
|
||||
|
||||
CONSTRAINT "todo_items_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_employee_lifecycle_events_employee_date" ON "employee_lifecycle_events"("employee_id", "effective_date");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_employee_lifecycle_events_type_created" ON "employee_lifecycle_events"("event_type", "created_at");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_employee_checklist_tasks_employee_scene_status" ON "employee_checklist_tasks"("employee_id", "scene", "status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_employee_checklist_tasks_scene_due" ON "employee_checklist_tasks"("scene", "due_date");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_employee_presence_date_status" ON "employee_presence"("date", "status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "employee_presence_employee_date_ux" ON "employee_presence"("employee_id", "date");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_weekly_reports_week_status" ON "weekly_reports"("week_start", "status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "weekly_reports_employee_week_start_ux" ON "weekly_reports"("employee_id", "week_start");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_todo_items_assignee_status_due" ON "todo_items"("assignee_employee_id", "status", "due_date");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_todo_items_creator_created" ON "todo_items"("created_by", "created_at");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "employee_lifecycle_events" ADD CONSTRAINT "employee_lifecycle_events_employee_id_fkey" FOREIGN KEY ("employee_id") REFERENCES "employees"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "employee_checklist_tasks" ADD CONSTRAINT "employee_checklist_tasks_employee_id_fkey" FOREIGN KEY ("employee_id") REFERENCES "employees"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "employee_presence" ADD CONSTRAINT "employee_presence_employee_id_fkey" FOREIGN KEY ("employee_id") REFERENCES "employees"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "weekly_reports" ADD CONSTRAINT "weekly_reports_employee_id_fkey" FOREIGN KEY ("employee_id") REFERENCES "employees"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "todo_items" ADD CONSTRAINT "todo_items_assignee_employee_id_fkey" FOREIGN KEY ("assignee_employee_id") REFERENCES "employees"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "todo_items" ADD CONSTRAINT "todo_items_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "employees"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
+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)
|
||||
|
||||
在新工单中引用
屏蔽一个用户