feat(G1,P16A,P16B): 收口主数据核心与节假日日历增强

这个提交包含在:
2026-03-07 17:29:03 +08:00
父节点 32a3d3724d
当前提交 195f46a2e3
共修改 35 个文件,包含 4556 行新增和 27 行删除
@@ -0,0 +1,91 @@
-- CreateEnum
CREATE TYPE "DocumentCategoryEntityType" AS ENUM ('reimbursement', 'leave', 'purchase_request', 'asset_card', 'general');
-- CreateTable
CREATE TABLE "legal_entities" (
"id" UUID NOT NULL,
"code" TEXT NOT NULL,
"name" TEXT NOT NULL,
"short_name" TEXT,
"currency_code" VARCHAR(8) NOT NULL DEFAULT 'CNY',
"tax_no" TEXT,
"enabled" BOOLEAN NOT NULL DEFAULT true,
"archived_at" TIMESTAMP(3),
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"created_by" UUID,
"updated_at" TIMESTAMP(3) NOT NULL,
"updated_by" UUID,
CONSTRAINT "legal_entities_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "cost_centers" (
"id" UUID NOT NULL,
"legal_entity_id" UUID NOT NULL,
"code" TEXT NOT NULL,
"name" TEXT NOT NULL,
"parent_id" UUID,
"owner_employee_id" UUID,
"enabled" BOOLEAN NOT NULL DEFAULT true,
"archived_at" TIMESTAMP(3),
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"created_by" UUID,
"updated_at" TIMESTAMP(3) NOT NULL,
"updated_by" UUID,
CONSTRAINT "cost_centers_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "document_categories" (
"id" UUID NOT NULL,
"code" TEXT NOT NULL,
"name" TEXT NOT NULL,
"entity_type" "DocumentCategoryEntityType" NOT NULL,
"sequence_prefix" TEXT NOT NULL,
"number_length" INTEGER NOT NULL DEFAULT 4,
"reset_period" "DocumentResetPeriod" NOT NULL,
"default_workflow_key" TEXT,
"enabled" BOOLEAN NOT NULL DEFAULT true,
"archived_at" TIMESTAMP(3),
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"created_by" UUID,
"updated_at" TIMESTAMP(3) NOT NULL,
"updated_by" UUID,
CONSTRAINT "document_categories_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "legal_entities_code_key" ON "legal_entities"("code");
-- CreateIndex
CREATE INDEX "idx_legal_entities_status" ON "legal_entities"("enabled", "archived_at");
-- CreateIndex
CREATE INDEX "idx_cost_centers_legal_entity_status" ON "cost_centers"("legal_entity_id", "enabled", "archived_at");
-- CreateIndex
CREATE INDEX "idx_cost_centers_parent" ON "cost_centers"("parent_id");
-- CreateIndex
CREATE INDEX "idx_cost_centers_owner" ON "cost_centers"("owner_employee_id");
-- CreateIndex
CREATE UNIQUE INDEX "legal_entity_cost_center_code_ux" ON "cost_centers"("legal_entity_id", "code");
-- CreateIndex
CREATE UNIQUE INDEX "document_categories_code_key" ON "document_categories"("code");
-- CreateIndex
CREATE INDEX "idx_document_categories_entity_status" ON "document_categories"("entity_type", "enabled", "archived_at");
-- AddForeignKey
ALTER TABLE "cost_centers" ADD CONSTRAINT "cost_centers_legal_entity_id_fkey" FOREIGN KEY ("legal_entity_id") REFERENCES "legal_entities"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "cost_centers" ADD CONSTRAINT "cost_centers_parent_id_fkey" FOREIGN KEY ("parent_id") REFERENCES "cost_centers"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "cost_centers" ADD CONSTRAINT "cost_centers_owner_employee_id_fkey" FOREIGN KEY ("owner_employee_id") REFERENCES "employees"("id") ON DELETE SET NULL ON UPDATE CASCADE;
@@ -0,0 +1,71 @@
-- CreateEnum
CREATE TYPE "HolidayCalendarDayType" AS ENUM ('holiday', 'workday', 'adjusted_workday');
-- AlterTable
ALTER TABLE "employees" ADD COLUMN "legal_entity_id" UUID;
-- AlterTable
ALTER TABLE "legal_entities" ADD COLUMN "default_holiday_calendar_id" UUID;
-- CreateTable
CREATE TABLE "holiday_calendars" (
"id" UUID NOT NULL,
"code" TEXT NOT NULL,
"name" TEXT NOT NULL,
"timezone" VARCHAR(64) NOT NULL DEFAULT 'Asia/Shanghai',
"legal_entity_id" UUID,
"enabled" BOOLEAN NOT NULL DEFAULT true,
"archived_at" TIMESTAMP(3),
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"created_by" UUID,
"updated_at" TIMESTAMP(3) NOT NULL,
"updated_by" UUID,
CONSTRAINT "holiday_calendars_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "holiday_calendar_days" (
"id" UUID NOT NULL,
"calendar_id" UUID NOT NULL,
"date" DATE NOT NULL,
"day_type" "HolidayCalendarDayType" NOT NULL,
"name" TEXT NOT NULL,
"note" TEXT,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"created_by" UUID,
"updated_at" TIMESTAMP(3) NOT NULL,
"updated_by" UUID,
CONSTRAINT "holiday_calendar_days_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "holiday_calendars_code_key" ON "holiday_calendars"("code");
-- CreateIndex
CREATE INDEX "idx_holiday_calendars_legal_entity_status" ON "holiday_calendars"("legal_entity_id", "enabled", "archived_at");
-- CreateIndex
CREATE INDEX "idx_holiday_calendar_days_calendar_date" ON "holiday_calendar_days"("calendar_id", "date");
-- CreateIndex
CREATE UNIQUE INDEX "holiday_calendar_day_ux" ON "holiday_calendar_days"("calendar_id", "date");
-- CreateIndex
CREATE INDEX "idx_employees_legal_entity" ON "employees"("legal_entity_id");
-- CreateIndex
CREATE INDEX "idx_legal_entities_default_calendar" ON "legal_entities"("default_holiday_calendar_id");
-- AddForeignKey
ALTER TABLE "employees" ADD CONSTRAINT "employees_legal_entity_id_fkey" FOREIGN KEY ("legal_entity_id") REFERENCES "legal_entities"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "legal_entities" ADD CONSTRAINT "legal_entities_default_holiday_calendar_id_fkey" FOREIGN KEY ("default_holiday_calendar_id") REFERENCES "holiday_calendars"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "holiday_calendars" ADD CONSTRAINT "holiday_calendars_legal_entity_id_fkey" FOREIGN KEY ("legal_entity_id") REFERENCES "legal_entities"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "holiday_calendar_days" ADD CONSTRAINT "holiday_calendar_days_calendar_id_fkey" FOREIGN KEY ("calendar_id") REFERENCES "holiday_calendars"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+137 -3
查看文件
@@ -90,6 +90,20 @@ enum DocumentResetPeriod {
yearly
}
enum DocumentCategoryEntityType {
reimbursement
leave
purchase_request
asset_card
general
}
enum HolidayCalendarDayType {
holiday
workday
adjusted_workday
}
enum WorkflowInstanceStatus {
pending
approved
@@ -163,6 +177,7 @@ model Employee {
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
@@ -185,9 +200,10 @@ model Employee {
updated_at DateTime @updatedAt
updated_by String? @db.Uuid
department Department @relation(fields: [department_id], references: [id], onDelete: Restrict)
direct_manager Employee? @relation("EmployeeToManager", fields: [direct_manager_id], references: [id], onDelete: Restrict)
subordinates Employee[] @relation("EmployeeToManager")
department Department @relation(fields: [department_id], references: [id], onDelete: Restrict)
legal_entity LegalEntity? @relation(fields: [legal_entity_id], references: [id], onDelete: SetNull)
direct_manager Employee? @relation("EmployeeToManager", fields: [direct_manager_id], references: [id], onDelete: Restrict)
subordinates Employee[] @relation("EmployeeToManager")
roles EmployeeRole[]
@@ -203,6 +219,7 @@ model Employee {
paid_reimbursements ReimbursementForm[] @relation("ReimbursementPaidBy")
leave_requests LeaveRequest[]
leave_ledgers LeaveLedger[]
owned_cost_centers CostCenter[] @relation("CostCenterOwner")
owned_invoices InvoicePool[] @relation("InvoiceOwner")
uploaded_invoices InvoicePool[] @relation("InvoiceUploader")
@@ -220,6 +237,7 @@ model Employee {
password_reset_codes PasswordResetCode[]
@@index([department_id])
@@index([legal_entity_id], map: "idx_employees_legal_entity")
@@index([direct_manager_id])
@@map("employees")
}
@@ -371,6 +389,122 @@ model DocumentSequence {
@@map("document_sequences")
}
model LegalEntity {
id String @id @default(uuid()) @db.Uuid
code String @unique
name String
short_name String?
currency_code String @default("CNY") @db.VarChar(8)
tax_no String?
default_holiday_calendar_id String? @db.Uuid
enabled Boolean @default(true)
archived_at DateTime?
created_at DateTime @default(now())
created_by String? @db.Uuid
updated_at DateTime @updatedAt
updated_by String? @db.Uuid
default_holiday_calendar HolidayCalendar? @relation("LegalEntityDefaultHolidayCalendar", fields: [default_holiday_calendar_id], references: [id], onDelete: SetNull)
cost_centers CostCenter[]
employees Employee[]
holiday_calendars HolidayCalendar[] @relation("HolidayCalendarLegalEntity")
@@index([enabled, archived_at], map: "idx_legal_entities_status")
@@index([default_holiday_calendar_id], map: "idx_legal_entities_default_calendar")
@@map("legal_entities")
}
model CostCenter {
id String @id @default(uuid()) @db.Uuid
legal_entity_id String @db.Uuid
code String
name String
parent_id String? @db.Uuid
owner_employee_id String? @db.Uuid
enabled Boolean @default(true)
archived_at DateTime?
created_at DateTime @default(now())
created_by String? @db.Uuid
updated_at DateTime @updatedAt
updated_by String? @db.Uuid
legal_entity LegalEntity @relation(fields: [legal_entity_id], references: [id], onDelete: Restrict)
parent CostCenter? @relation("CostCenterToParent", fields: [parent_id], references: [id], onDelete: Restrict)
children CostCenter[] @relation("CostCenterToParent")
owner_employee Employee? @relation("CostCenterOwner", fields: [owner_employee_id], references: [id], onDelete: SetNull)
@@unique([legal_entity_id, code], map: "legal_entity_cost_center_code_ux")
@@index([legal_entity_id, enabled, archived_at], map: "idx_cost_centers_legal_entity_status")
@@index([parent_id], map: "idx_cost_centers_parent")
@@index([owner_employee_id], map: "idx_cost_centers_owner")
@@map("cost_centers")
}
model DocumentCategory {
id String @id @default(uuid()) @db.Uuid
code String @unique
name String
entity_type DocumentCategoryEntityType
sequence_prefix String
number_length Int @default(4)
reset_period DocumentResetPeriod
default_workflow_key String?
enabled Boolean @default(true)
archived_at DateTime?
created_at DateTime @default(now())
created_by String? @db.Uuid
updated_at DateTime @updatedAt
updated_by String? @db.Uuid
@@index([entity_type, enabled, archived_at], map: "idx_document_categories_entity_status")
@@map("document_categories")
}
model HolidayCalendar {
id String @id @default(uuid()) @db.Uuid
code String @unique
name String
timezone String @default("Asia/Shanghai") @db.VarChar(64)
legal_entity_id String? @db.Uuid
enabled Boolean @default(true)
archived_at DateTime?
created_at DateTime @default(now())
created_by String? @db.Uuid
updated_at DateTime @updatedAt
updated_by String? @db.Uuid
legal_entity LegalEntity? @relation("HolidayCalendarLegalEntity", fields: [legal_entity_id], references: [id], onDelete: SetNull)
days HolidayCalendarDay[]
default_for_legal_entities LegalEntity[] @relation("LegalEntityDefaultHolidayCalendar")
@@index([legal_entity_id, enabled, archived_at], map: "idx_holiday_calendars_legal_entity_status")
@@map("holiday_calendars")
}
model HolidayCalendarDay {
id String @id @default(uuid()) @db.Uuid
calendar_id String @db.Uuid
date DateTime @db.Date
day_type HolidayCalendarDayType
name String
note String?
created_at DateTime @default(now())
created_by String? @db.Uuid
updated_at DateTime @updatedAt
updated_by String? @db.Uuid
calendar HolidayCalendar @relation(fields: [calendar_id], references: [id], onDelete: Cascade)
@@unique([calendar_id, date], map: "holiday_calendar_day_ux")
@@index([calendar_id, date], map: "idx_holiday_calendar_days_calendar_date")
@@map("holiday_calendar_days")
}
model ReimbursementForm {
id String @id @default(uuid()) @db.Uuid
form_number String? @unique