R18-1/R18-3: 接入企业微信入口绑定与免登回退
这个提交包含在:
@@ -0,0 +1,357 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ProjectStatus" AS ENUM ('draft', 'active', 'paused', 'completed', 'archived');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ProjectRole" AS ENUM ('owner', 'manager', 'member', 'observer');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ProjectMilestoneStatus" AS ENUM ('pending', 'in_progress', 'done', 'delayed', 'cancelled');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ProjectTaskStatus" AS ENUM ('todo', 'doing', 'blocked', 'done', 'cancelled');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ProjectTaskPriority" AS ENUM ('low', 'normal', 'high', 'urgent');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ProjectRiskLevel" AS ENUM ('low', 'medium', 'high');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ProjectDeliveryRecordType" AS ENUM ('kickoff', 'onsite', 'stage_acceptance', 'final_acceptance', 'handover');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ConfidentialityLevel" AS ENUM ('public', 'internal', 'confidential', 'restricted');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "DocumentStorageType" AS ENUM ('oa_link', 'nas', 'internal_share', 'offline_archive');
|
||||
|
||||
-- AlterEnum
|
||||
ALTER TYPE "WorkspacePrimaryEntryMode" ADD VALUE 'wecom';
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "reimbursement_forms" ADD COLUMN "project_id" UUID;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "todo_items" ADD COLUMN "project_id" UUID;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "travel_requests" ADD COLUMN "project_id" UUID;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "wecom_identity_bindings" (
|
||||
"id" UUID NOT NULL,
|
||||
"employee_id" UUID NOT NULL,
|
||||
"external_user_id" VARCHAR(128) NOT NULL,
|
||||
"external_open_user_id" VARCHAR(128),
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"created_by" UUID,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_by" UUID,
|
||||
|
||||
CONSTRAINT "wecom_identity_bindings_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "projects" (
|
||||
"id" UUID NOT NULL,
|
||||
"project_no" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"client_name" TEXT NOT NULL,
|
||||
"client_alias" TEXT,
|
||||
"owner_employee_id" UUID NOT NULL,
|
||||
"manager_employee_id" UUID,
|
||||
"status" "ProjectStatus" NOT NULL DEFAULT 'draft',
|
||||
"starts_at" DATE,
|
||||
"target_end_at" DATE,
|
||||
"actual_end_at" DATE,
|
||||
"summary" TEXT,
|
||||
"is_confidential" BOOLEAN NOT NULL DEFAULT false,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "projects_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "project_members" (
|
||||
"id" UUID NOT NULL,
|
||||
"project_id" UUID NOT NULL,
|
||||
"employee_id" UUID NOT NULL,
|
||||
"role" "ProjectRole" NOT NULL DEFAULT 'member',
|
||||
"joined_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"left_at" TIMESTAMP(3),
|
||||
|
||||
CONSTRAINT "project_members_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "project_milestones" (
|
||||
"id" UUID NOT NULL,
|
||||
"project_id" UUID NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"status" "ProjectMilestoneStatus" NOT NULL DEFAULT 'pending',
|
||||
"due_date" DATE,
|
||||
"completed_at" TIMESTAMP(3),
|
||||
"owner_employee_id" UUID,
|
||||
"sort_order" INTEGER NOT NULL DEFAULT 100,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "project_milestones_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "project_tasks" (
|
||||
"id" UUID NOT NULL,
|
||||
"project_id" UUID NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"status" "ProjectTaskStatus" NOT NULL DEFAULT 'todo',
|
||||
"priority" "ProjectTaskPriority" NOT NULL DEFAULT 'normal',
|
||||
"assignee_employee_id" UUID,
|
||||
"due_date" DATE,
|
||||
"blocked_reason" TEXT,
|
||||
"created_by" UUID NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "project_tasks_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "project_risks" (
|
||||
"id" UUID NOT NULL,
|
||||
"project_id" UUID NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"detail" TEXT NOT NULL,
|
||||
"level" "ProjectRiskLevel" NOT NULL DEFAULT 'medium',
|
||||
"status" VARCHAR(32) NOT NULL DEFAULT 'open',
|
||||
"owner_employee_id" UUID,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "project_risks_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "weekly_report_project_links" (
|
||||
"id" UUID NOT NULL,
|
||||
"weekly_report_id" UUID NOT NULL,
|
||||
"project_id" UUID NOT NULL,
|
||||
"progress_text" TEXT NOT NULL DEFAULT '',
|
||||
"risk_text" TEXT NOT NULL DEFAULT '',
|
||||
"next_step_text" TEXT NOT NULL DEFAULT '',
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "weekly_report_project_links_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "contract_registry" (
|
||||
"id" UUID NOT NULL,
|
||||
"contract_no" TEXT NOT NULL,
|
||||
"project_id" UUID,
|
||||
"counterparty_name" TEXT NOT NULL,
|
||||
"summary" TEXT NOT NULL,
|
||||
"confidentiality_level" "ConfidentialityLevel" NOT NULL DEFAULT 'internal',
|
||||
"archive_location" TEXT NOT NULL,
|
||||
"offline_archive_no" TEXT,
|
||||
"owner_employee_id" UUID NOT NULL,
|
||||
"status" VARCHAR(32) NOT NULL DEFAULT 'active',
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "contract_registry_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "project_delivery_records" (
|
||||
"id" UUID NOT NULL,
|
||||
"project_id" UUID NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"record_type" "ProjectDeliveryRecordType" NOT NULL,
|
||||
"summary" TEXT NOT NULL,
|
||||
"occurred_at" TIMESTAMP(3) NOT NULL,
|
||||
"owner_employee_id" UUID NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "project_delivery_records_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "confidential_document_refs" (
|
||||
"id" UUID NOT NULL,
|
||||
"project_id" UUID,
|
||||
"contract_registry_id" UUID,
|
||||
"title" TEXT NOT NULL,
|
||||
"document_no" TEXT,
|
||||
"confidentiality_level" "ConfidentialityLevel" NOT NULL DEFAULT 'internal',
|
||||
"storage_type" "DocumentStorageType" NOT NULL,
|
||||
"storage_path" TEXT NOT NULL,
|
||||
"offline_archive_no" TEXT,
|
||||
"owner_employee_id" UUID NOT NULL,
|
||||
"access_rule_json" JSONB,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "confidential_document_refs_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "wecom_identity_bindings_employee_id_key" ON "wecom_identity_bindings"("employee_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "wecom_identity_bindings_external_user_id_key" ON "wecom_identity_bindings"("external_user_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_wecom_identity_bindings_external_user" ON "wecom_identity_bindings"("external_user_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "projects_project_no_key" ON "projects"("project_no");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_projects_owner_status" ON "projects"("owner_employee_id", "status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_projects_manager_status" ON "projects"("manager_employee_id", "status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_projects_status_target_end" ON "projects"("status", "target_end_at");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_projects_client_name" ON "projects"("client_name", "name");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_project_members_employee_open" ON "project_members"("employee_id", "left_at");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "project_members_project_employee_ux" ON "project_members"("project_id", "employee_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_project_milestones_project_sort" ON "project_milestones"("project_id", "sort_order");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_project_milestones_owner_due" ON "project_milestones"("owner_employee_id", "due_date");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_project_tasks_project_status_priority" ON "project_tasks"("project_id", "status", "priority");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_project_tasks_assignee_status" ON "project_tasks"("assignee_employee_id", "status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_project_risks_project_status_level" ON "project_risks"("project_id", "status", "level");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_project_risks_owner_status" ON "project_risks"("owner_employee_id", "status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_weekly_report_project_links_project_updated" ON "weekly_report_project_links"("project_id", "updated_at");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "weekly_report_project_links_report_project_ux" ON "weekly_report_project_links"("weekly_report_id", "project_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "contract_registry_contract_no_key" ON "contract_registry"("contract_no");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_contract_registry_project_status" ON "contract_registry"("project_id", "status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_contract_registry_owner_created" ON "contract_registry"("owner_employee_id", "created_at");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_project_delivery_records_project_occurred" ON "project_delivery_records"("project_id", "occurred_at");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_confidential_doc_refs_project_level" ON "confidential_document_refs"("project_id", "confidentiality_level");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_confidential_doc_refs_contract" ON "confidential_document_refs"("contract_registry_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_confidential_doc_refs_owner_created" ON "confidential_document_refs"("owner_employee_id", "created_at");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_reimbursement_forms_project" ON "reimbursement_forms"("project_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_todo_items_project_status" ON "todo_items"("project_id", "status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_travel_requests_project" ON "travel_requests"("project_id");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "reimbursement_forms" ADD CONSTRAINT "reimbursement_forms_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "todo_items" ADD CONSTRAINT "todo_items_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "wecom_identity_bindings" ADD CONSTRAINT "wecom_identity_bindings_employee_id_fkey" FOREIGN KEY ("employee_id") REFERENCES "employees"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "projects" ADD CONSTRAINT "projects_owner_employee_id_fkey" FOREIGN KEY ("owner_employee_id") REFERENCES "employees"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "projects" ADD CONSTRAINT "projects_manager_employee_id_fkey" FOREIGN KEY ("manager_employee_id") REFERENCES "employees"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "project_members" ADD CONSTRAINT "project_members_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "project_members" ADD CONSTRAINT "project_members_employee_id_fkey" FOREIGN KEY ("employee_id") REFERENCES "employees"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "project_milestones" ADD CONSTRAINT "project_milestones_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "project_milestones" ADD CONSTRAINT "project_milestones_owner_employee_id_fkey" FOREIGN KEY ("owner_employee_id") REFERENCES "employees"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "project_tasks" ADD CONSTRAINT "project_tasks_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "project_tasks" ADD CONSTRAINT "project_tasks_assignee_employee_id_fkey" FOREIGN KEY ("assignee_employee_id") REFERENCES "employees"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "project_tasks" ADD CONSTRAINT "project_tasks_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "employees"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "project_risks" ADD CONSTRAINT "project_risks_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "project_risks" ADD CONSTRAINT "project_risks_owner_employee_id_fkey" FOREIGN KEY ("owner_employee_id") REFERENCES "employees"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "weekly_report_project_links" ADD CONSTRAINT "weekly_report_project_links_weekly_report_id_fkey" FOREIGN KEY ("weekly_report_id") REFERENCES "weekly_reports"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "weekly_report_project_links" ADD CONSTRAINT "weekly_report_project_links_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "contract_registry" ADD CONSTRAINT "contract_registry_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "contract_registry" ADD CONSTRAINT "contract_registry_owner_employee_id_fkey" FOREIGN KEY ("owner_employee_id") REFERENCES "employees"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "project_delivery_records" ADD CONSTRAINT "project_delivery_records_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "project_delivery_records" ADD CONSTRAINT "project_delivery_records_owner_employee_id_fkey" FOREIGN KEY ("owner_employee_id") REFERENCES "employees"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "confidential_document_refs" ADD CONSTRAINT "confidential_document_refs_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "confidential_document_refs" ADD CONSTRAINT "confidential_document_refs_contract_registry_id_fkey" FOREIGN KEY ("contract_registry_id") REFERENCES "contract_registry"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "confidential_document_refs" ADD CONSTRAINT "confidential_document_refs_owner_employee_id_fkey" FOREIGN KEY ("owner_employee_id") REFERENCES "employees"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "travel_requests" ADD CONSTRAINT "travel_requests_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
+323
-10
@@ -275,6 +275,7 @@ enum WorkspaceOrgMode {
|
||||
|
||||
enum WorkspacePrimaryEntryMode {
|
||||
password
|
||||
wecom
|
||||
}
|
||||
|
||||
enum WorkspaceNotificationStrategy {
|
||||
@@ -364,6 +365,72 @@ enum TodoSource {
|
||||
weekly_report
|
||||
}
|
||||
|
||||
enum ProjectStatus {
|
||||
draft
|
||||
active
|
||||
paused
|
||||
completed
|
||||
archived
|
||||
}
|
||||
|
||||
enum ProjectRole {
|
||||
owner
|
||||
manager
|
||||
member
|
||||
observer
|
||||
}
|
||||
|
||||
enum ProjectMilestoneStatus {
|
||||
pending
|
||||
in_progress
|
||||
done
|
||||
delayed
|
||||
cancelled
|
||||
}
|
||||
|
||||
enum ProjectTaskStatus {
|
||||
todo
|
||||
doing
|
||||
blocked
|
||||
done
|
||||
cancelled
|
||||
}
|
||||
|
||||
enum ProjectTaskPriority {
|
||||
low
|
||||
normal
|
||||
high
|
||||
urgent
|
||||
}
|
||||
|
||||
enum ProjectRiskLevel {
|
||||
low
|
||||
medium
|
||||
high
|
||||
}
|
||||
|
||||
enum ProjectDeliveryRecordType {
|
||||
kickoff
|
||||
onsite
|
||||
stage_acceptance
|
||||
final_acceptance
|
||||
handover
|
||||
}
|
||||
|
||||
enum ConfidentialityLevel {
|
||||
public
|
||||
internal
|
||||
confidential
|
||||
restricted
|
||||
}
|
||||
|
||||
enum DocumentStorageType {
|
||||
oa_link
|
||||
nas
|
||||
internal_share
|
||||
offline_archive
|
||||
}
|
||||
|
||||
model Department {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
name String
|
||||
@@ -479,15 +546,26 @@ 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")
|
||||
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")
|
||||
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")
|
||||
wecom_identity_binding WecomIdentityBinding?
|
||||
owned_projects Project[] @relation("ProjectOwner")
|
||||
managed_projects Project[] @relation("ProjectManager")
|
||||
project_memberships ProjectMember[]
|
||||
owned_project_milestones ProjectMilestone[] @relation("ProjectMilestoneOwner")
|
||||
assigned_project_tasks ProjectTask[] @relation("ProjectTaskAssignee")
|
||||
created_project_tasks ProjectTask[] @relation("ProjectTaskCreator")
|
||||
owned_project_risks ProjectRisk[] @relation("ProjectRiskOwner")
|
||||
owned_project_delivery_records ProjectDeliveryRecord[] @relation("ProjectDeliveryRecordOwner")
|
||||
owned_contract_registries ContractRegistry[] @relation("ContractRegistryOwner")
|
||||
owned_confidential_document_refs ConfidentialDocumentRef[] @relation("ConfidentialDocumentRefOwner")
|
||||
|
||||
@@index([department_id])
|
||||
@@index([legal_entity_id], map: "idx_employees_legal_entity")
|
||||
@@ -1052,6 +1130,7 @@ model ReimbursementForm {
|
||||
payment_channel String? @db.VarChar(20)
|
||||
paid_at DateTime?
|
||||
paid_by String? @db.Uuid
|
||||
project_id String? @db.Uuid
|
||||
|
||||
created_at DateTime @default(now())
|
||||
created_by String? @db.Uuid
|
||||
@@ -1062,6 +1141,7 @@ model ReimbursementForm {
|
||||
owner Employee @relation("ReimbursementOwner", fields: [owner_id], references: [id], onDelete: Restrict)
|
||||
paid_by_employee Employee? @relation("ReimbursementPaidBy", fields: [paid_by], references: [id], onDelete: SetNull)
|
||||
department Department @relation(fields: [department_id], references: [id], onDelete: Restrict)
|
||||
project Project? @relation(fields: [project_id], references: [id], onDelete: SetNull)
|
||||
|
||||
items ReimbursementItem[]
|
||||
invoice_pool_items InvoicePool[]
|
||||
@@ -1074,6 +1154,7 @@ model ReimbursementForm {
|
||||
@@index([submitter_id])
|
||||
@@index([department_id])
|
||||
@@index([paid_by])
|
||||
@@index([project_id], map: "idx_reimbursement_forms_project")
|
||||
@@index([status])
|
||||
@@index([reimbursement_date])
|
||||
@@index([owner_id, status, updated_at], map: "idx_reimbursement_owner_status_updated_at")
|
||||
@@ -1608,7 +1689,8 @@ model WeeklyReport {
|
||||
created_at DateTime @default(now())
|
||||
updated_at DateTime @default(now()) @updatedAt
|
||||
|
||||
employee Employee @relation(fields: [employee_id], references: [id], onDelete: Cascade)
|
||||
employee Employee @relation(fields: [employee_id], references: [id], onDelete: Cascade)
|
||||
project_links ProjectLinkOnWeeklyReport[]
|
||||
|
||||
@@unique([employee_id, week_start], map: "weekly_reports_employee_week_start_ux")
|
||||
@@index([week_start, status], map: "idx_weekly_reports_week_status")
|
||||
@@ -1625,6 +1707,7 @@ model TodoItem {
|
||||
priority TodoPriority @default(normal)
|
||||
status TodoStatus @default(todo)
|
||||
source TodoSource @default(manual)
|
||||
project_id String? @db.Uuid
|
||||
|
||||
created_at DateTime @default(now())
|
||||
updated_at DateTime @default(now()) @updatedAt
|
||||
@@ -1632,12 +1715,239 @@ model TodoItem {
|
||||
|
||||
assignee Employee @relation("TodoAssignee", fields: [assignee_employee_id], references: [id], onDelete: Restrict)
|
||||
creator Employee @relation("TodoCreator", fields: [created_by], references: [id], onDelete: Restrict)
|
||||
project Project? @relation(fields: [project_id], references: [id], onDelete: SetNull)
|
||||
|
||||
@@index([assignee_employee_id, status, due_date], map: "idx_todo_items_assignee_status_due")
|
||||
@@index([project_id, status], map: "idx_todo_items_project_status")
|
||||
@@index([created_by, created_at], map: "idx_todo_items_creator_created")
|
||||
@@map("todo_items")
|
||||
}
|
||||
|
||||
model WecomIdentityBinding {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
employee_id String @unique @db.Uuid
|
||||
external_user_id String @unique @db.VarChar(128)
|
||||
external_open_user_id String? @db.VarChar(128)
|
||||
|
||||
created_at DateTime @default(now())
|
||||
created_by String? @db.Uuid
|
||||
updated_at DateTime @default(now()) @updatedAt
|
||||
updated_by String? @db.Uuid
|
||||
|
||||
employee Employee @relation(fields: [employee_id], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([external_user_id], map: "idx_wecom_identity_bindings_external_user")
|
||||
@@map("wecom_identity_bindings")
|
||||
}
|
||||
|
||||
model Project {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
project_no String @unique
|
||||
name String
|
||||
client_name String
|
||||
client_alias String?
|
||||
owner_employee_id String @db.Uuid
|
||||
manager_employee_id String? @db.Uuid
|
||||
status ProjectStatus @default(draft)
|
||||
starts_at DateTime? @db.Date
|
||||
target_end_at DateTime? @db.Date
|
||||
actual_end_at DateTime? @db.Date
|
||||
summary String?
|
||||
is_confidential Boolean @default(false)
|
||||
|
||||
created_at DateTime @default(now())
|
||||
updated_at DateTime @default(now()) @updatedAt
|
||||
|
||||
owner Employee @relation("ProjectOwner", fields: [owner_employee_id], references: [id], onDelete: Restrict)
|
||||
manager Employee? @relation("ProjectManager", fields: [manager_employee_id], references: [id], onDelete: SetNull)
|
||||
members ProjectMember[]
|
||||
milestones ProjectMilestone[]
|
||||
tasks ProjectTask[]
|
||||
risks ProjectRisk[]
|
||||
reimbursements ReimbursementForm[]
|
||||
travel_requests TravelRequest[]
|
||||
todo_items TodoItem[]
|
||||
weekly_reports ProjectLinkOnWeeklyReport[]
|
||||
contracts ContractRegistry[]
|
||||
deliveries ProjectDeliveryRecord[]
|
||||
document_refs ConfidentialDocumentRef[]
|
||||
|
||||
@@index([owner_employee_id, status], map: "idx_projects_owner_status")
|
||||
@@index([manager_employee_id, status], map: "idx_projects_manager_status")
|
||||
@@index([status, target_end_at], map: "idx_projects_status_target_end")
|
||||
@@index([client_name, name], map: "idx_projects_client_name")
|
||||
@@map("projects")
|
||||
}
|
||||
|
||||
model ProjectMember {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
project_id String @db.Uuid
|
||||
employee_id String @db.Uuid
|
||||
role ProjectRole @default(member)
|
||||
joined_at DateTime @default(now())
|
||||
left_at DateTime?
|
||||
|
||||
project Project @relation(fields: [project_id], references: [id], onDelete: Cascade)
|
||||
employee Employee @relation(fields: [employee_id], references: [id], onDelete: Restrict)
|
||||
|
||||
@@unique([project_id, employee_id], map: "project_members_project_employee_ux")
|
||||
@@index([employee_id, left_at], map: "idx_project_members_employee_open")
|
||||
@@map("project_members")
|
||||
}
|
||||
|
||||
model ProjectMilestone {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
project_id String @db.Uuid
|
||||
title String
|
||||
description String?
|
||||
status ProjectMilestoneStatus @default(pending)
|
||||
due_date DateTime? @db.Date
|
||||
completed_at DateTime?
|
||||
owner_employee_id String? @db.Uuid
|
||||
sort_order Int @default(100)
|
||||
|
||||
created_at DateTime @default(now())
|
||||
updated_at DateTime @default(now()) @updatedAt
|
||||
|
||||
project Project @relation(fields: [project_id], references: [id], onDelete: Cascade)
|
||||
owner Employee? @relation("ProjectMilestoneOwner", fields: [owner_employee_id], references: [id], onDelete: SetNull)
|
||||
|
||||
@@index([project_id, sort_order], map: "idx_project_milestones_project_sort")
|
||||
@@index([owner_employee_id, due_date], map: "idx_project_milestones_owner_due")
|
||||
@@map("project_milestones")
|
||||
}
|
||||
|
||||
model ProjectTask {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
project_id String @db.Uuid
|
||||
title String
|
||||
description String?
|
||||
status ProjectTaskStatus @default(todo)
|
||||
priority ProjectTaskPriority @default(normal)
|
||||
assignee_employee_id String? @db.Uuid
|
||||
due_date DateTime? @db.Date
|
||||
blocked_reason String?
|
||||
created_by String @db.Uuid
|
||||
|
||||
created_at DateTime @default(now())
|
||||
updated_at DateTime @default(now()) @updatedAt
|
||||
|
||||
project Project @relation(fields: [project_id], references: [id], onDelete: Cascade)
|
||||
assignee Employee? @relation("ProjectTaskAssignee", fields: [assignee_employee_id], references: [id], onDelete: SetNull)
|
||||
creator Employee @relation("ProjectTaskCreator", fields: [created_by], references: [id], onDelete: Restrict)
|
||||
|
||||
@@index([project_id, status, priority], map: "idx_project_tasks_project_status_priority")
|
||||
@@index([assignee_employee_id, status], map: "idx_project_tasks_assignee_status")
|
||||
@@map("project_tasks")
|
||||
}
|
||||
|
||||
model ProjectRisk {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
project_id String @db.Uuid
|
||||
title String
|
||||
detail String
|
||||
level ProjectRiskLevel @default(medium)
|
||||
status String @default("open") @db.VarChar(32)
|
||||
owner_employee_id String? @db.Uuid
|
||||
|
||||
created_at DateTime @default(now())
|
||||
updated_at DateTime @default(now()) @updatedAt
|
||||
|
||||
project Project @relation(fields: [project_id], references: [id], onDelete: Cascade)
|
||||
owner Employee? @relation("ProjectRiskOwner", fields: [owner_employee_id], references: [id], onDelete: SetNull)
|
||||
|
||||
@@index([project_id, status, level], map: "idx_project_risks_project_status_level")
|
||||
@@index([owner_employee_id, status], map: "idx_project_risks_owner_status")
|
||||
@@map("project_risks")
|
||||
}
|
||||
|
||||
model ProjectLinkOnWeeklyReport {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
weekly_report_id String @db.Uuid
|
||||
project_id String @db.Uuid
|
||||
progress_text String @default("")
|
||||
risk_text String @default("")
|
||||
next_step_text String @default("")
|
||||
|
||||
created_at DateTime @default(now())
|
||||
updated_at DateTime @default(now()) @updatedAt
|
||||
|
||||
weekly_report WeeklyReport @relation(fields: [weekly_report_id], references: [id], onDelete: Cascade)
|
||||
project Project @relation(fields: [project_id], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([weekly_report_id, project_id], map: "weekly_report_project_links_report_project_ux")
|
||||
@@index([project_id, updated_at], map: "idx_weekly_report_project_links_project_updated")
|
||||
@@map("weekly_report_project_links")
|
||||
}
|
||||
|
||||
model ContractRegistry {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
contract_no String @unique
|
||||
project_id String? @db.Uuid
|
||||
counterparty_name String
|
||||
summary String
|
||||
confidentiality_level ConfidentialityLevel @default(internal)
|
||||
archive_location String
|
||||
offline_archive_no String?
|
||||
owner_employee_id String @db.Uuid
|
||||
status String @default("active") @db.VarChar(32)
|
||||
|
||||
created_at DateTime @default(now())
|
||||
updated_at DateTime @default(now()) @updatedAt
|
||||
|
||||
project Project? @relation(fields: [project_id], references: [id], onDelete: SetNull)
|
||||
owner Employee @relation("ContractRegistryOwner", fields: [owner_employee_id], references: [id], onDelete: Restrict)
|
||||
document_refs ConfidentialDocumentRef[]
|
||||
|
||||
@@index([project_id, status], map: "idx_contract_registry_project_status")
|
||||
@@index([owner_employee_id, created_at], map: "idx_contract_registry_owner_created")
|
||||
@@map("contract_registry")
|
||||
}
|
||||
|
||||
model ProjectDeliveryRecord {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
project_id String @db.Uuid
|
||||
title String
|
||||
record_type ProjectDeliveryRecordType
|
||||
summary String
|
||||
occurred_at DateTime
|
||||
owner_employee_id String @db.Uuid
|
||||
|
||||
created_at DateTime @default(now())
|
||||
|
||||
project Project @relation(fields: [project_id], references: [id], onDelete: Cascade)
|
||||
owner Employee @relation("ProjectDeliveryRecordOwner", fields: [owner_employee_id], references: [id], onDelete: Restrict)
|
||||
|
||||
@@index([project_id, occurred_at], map: "idx_project_delivery_records_project_occurred")
|
||||
@@map("project_delivery_records")
|
||||
}
|
||||
|
||||
model ConfidentialDocumentRef {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
project_id String? @db.Uuid
|
||||
contract_registry_id String? @db.Uuid
|
||||
title String
|
||||
document_no String?
|
||||
confidentiality_level ConfidentialityLevel @default(internal)
|
||||
storage_type DocumentStorageType
|
||||
storage_path String
|
||||
offline_archive_no String?
|
||||
owner_employee_id String @db.Uuid
|
||||
access_rule_json Json?
|
||||
|
||||
created_at DateTime @default(now())
|
||||
updated_at DateTime @default(now()) @updatedAt
|
||||
|
||||
project Project? @relation(fields: [project_id], references: [id], onDelete: SetNull)
|
||||
contract_registry ContractRegistry? @relation(fields: [contract_registry_id], references: [id], onDelete: SetNull)
|
||||
owner Employee @relation("ConfidentialDocumentRefOwner", fields: [owner_employee_id], references: [id], onDelete: Restrict)
|
||||
|
||||
@@index([project_id, confidentiality_level], map: "idx_confidential_doc_refs_project_level")
|
||||
@@index([contract_registry_id], map: "idx_confidential_doc_refs_contract")
|
||||
@@index([owner_employee_id, created_at], map: "idx_confidential_doc_refs_owner_created")
|
||||
@@map("confidential_document_refs")
|
||||
}
|
||||
|
||||
model MigrationRun {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
run_type String @db.VarChar(32)
|
||||
@@ -1744,6 +2054,7 @@ model TravelRequest {
|
||||
legal_entity_id String @db.Uuid
|
||||
cost_center_id String @db.Uuid
|
||||
budget_pool_id String? @db.Uuid
|
||||
project_id String? @db.Uuid
|
||||
purpose String
|
||||
trip_type TravelTripType
|
||||
start_date DateTime @db.Date
|
||||
@@ -1762,6 +2073,7 @@ model TravelRequest {
|
||||
legal_entity LegalEntity @relation(fields: [legal_entity_id], references: [id], onDelete: Restrict)
|
||||
cost_center CostCenter @relation(fields: [cost_center_id], references: [id], onDelete: Restrict)
|
||||
budget_pool BudgetPool? @relation(fields: [budget_pool_id], references: [id], onDelete: SetNull)
|
||||
project Project? @relation(fields: [project_id], references: [id], onDelete: SetNull)
|
||||
|
||||
segments TravelRequestSegment[]
|
||||
travel_orders TravelOrder[]
|
||||
@@ -1772,6 +2084,7 @@ model TravelRequest {
|
||||
|
||||
@@index([applicant_employee_id, start_date], map: "idx_travel_requests_applicant_start")
|
||||
@@index([submitter_id], map: "idx_travel_requests_submitter")
|
||||
@@index([project_id], map: "idx_travel_requests_project")
|
||||
@@index([department_id, status], map: "idx_travel_requests_department_status")
|
||||
@@index([legal_entity_id, cost_center_id], map: "idx_travel_requests_legal_cost_center")
|
||||
@@index([budget_pool_id], map: "idx_travel_requests_budget_pool")
|
||||
|
||||
在新工单中引用
屏蔽一个用户