422 lines
16 KiB
Plaintext
422 lines
16 KiB
Plaintext
// This is your Prisma schema file,
|
||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||
|
||
generator client {
|
||
provider = "prisma-client-js"
|
||
}
|
||
|
||
datasource db {
|
||
provider = "mysql"
|
||
url = env("DATABASE_URL")
|
||
}
|
||
|
||
model AssetType {
|
||
id Int @id @default(autoincrement())
|
||
name String @unique @db.VarChar(50)
|
||
short_name String? @db.VarChar(20)
|
||
status String @default("active") @db.VarChar(20)
|
||
can_be_parent Boolean @default(false) // 可作为父资产
|
||
can_be_child Boolean @default(false) // 可作为子资产
|
||
created_at DateTime @default(now())
|
||
updated_at DateTime @updatedAt
|
||
|
||
equipments Equipment[]
|
||
|
||
@@index([status])
|
||
@@index([short_name])
|
||
@@map("asset_type")
|
||
}
|
||
|
||
model Department {
|
||
id Int @id @default(autoincrement())
|
||
name String @db.VarChar(100)
|
||
status String @default("active") @db.VarChar(20)
|
||
parent_id Int? // 父部门ID,null表示根部门
|
||
source_group_id Int? @unique
|
||
source_parent_group_id Int?
|
||
source_system String? @db.VarChar(30)
|
||
last_synced_at DateTime?
|
||
created_at DateTime @default(now())
|
||
updated_at DateTime @updatedAt
|
||
|
||
// 自关联 - 部门层级
|
||
parent Department? @relation("DepartmentHierarchy", fields: [parent_id], references: [id])
|
||
children Department[] @relation("DepartmentHierarchy")
|
||
|
||
equipments Equipment[]
|
||
mainPersons Person[] @relation("PersonMainDepartment")
|
||
personDepartments PersonDepartment[]
|
||
|
||
@@index([status])
|
||
@@index([parent_id])
|
||
@@index([source_system])
|
||
@@index([last_synced_at])
|
||
@@map("department")
|
||
}
|
||
|
||
model Equipment {
|
||
id Int @id @default(autoincrement())
|
||
equipment_code String @unique @db.VarChar(50)
|
||
equipment_name String @db.VarChar(100)
|
||
equipment_model String? @db.VarChar(100)
|
||
equipment_type String @db.VarChar(50)
|
||
code_generation_mode String @default("auto") @db.VarChar(20)
|
||
status String @default("可用") @db.VarChar(20)
|
||
total_quantity Int @default(0)
|
||
remaining_quantity Int @default(0)
|
||
unit_price Decimal @default(0.00) @db.Decimal(10, 2)
|
||
total_value Decimal @default(0.00) @db.Decimal(12, 2)
|
||
borrowed_value Decimal @default(0.00) @db.Decimal(12, 2)
|
||
available_value Decimal @default(0.00) @db.Decimal(12, 2)
|
||
description String? @db.Text
|
||
purchase_date DateTime? @db.Date
|
||
supplier String? @db.VarChar(100)
|
||
storage_location_id Int?
|
||
asset_type_id Int?
|
||
department_id Int?
|
||
// 父子资产关联字段
|
||
parent_id Int? // 父资产ID(如果已挂载)
|
||
mount_status String @default("none") @db.VarChar(20) // none/mounted/unmounted
|
||
total_value_with_children Decimal @default(0.00) @db.Decimal(12, 2) // 含配件总价值
|
||
created_at DateTime @default(now())
|
||
updated_at DateTime @updatedAt
|
||
|
||
borrow_records BorrowRecord[]
|
||
storageLocation StorageLocation? @relation(fields: [storage_location_id], references: [id])
|
||
assetType AssetType? @relation(fields: [asset_type_id], references: [id])
|
||
department Department? @relation(fields: [department_id], references: [id])
|
||
// 父子资产自关联
|
||
parent Equipment? @relation("ParentChild", fields: [parent_id], references: [id])
|
||
children Equipment[] @relation("ParentChild")
|
||
// 挂载历史关联
|
||
mountHistories MountHistory[]
|
||
// 报废记录关联
|
||
disposalRecords DisposalRecord[]
|
||
// 维修记录关联
|
||
maintenanceRecords MaintenanceRecord[]
|
||
|
||
@@index([equipment_code])
|
||
@@index([equipment_type])
|
||
@@index([status])
|
||
@@index([code_generation_mode])
|
||
@@index([unit_price])
|
||
@@index([storage_location_id])
|
||
@@index([asset_type_id])
|
||
@@index([department_id])
|
||
@@index([parent_id])
|
||
@@index([mount_status])
|
||
@@map("equipment")
|
||
}
|
||
|
||
model BorrowRecord {
|
||
id Int @id @default(autoincrement())
|
||
equipment_id Int
|
||
equipment_code String @db.VarChar(50)
|
||
person_id Int
|
||
person_name String @db.VarChar(50)
|
||
person_nickname String @db.VarChar(50)
|
||
person_identifier String? @db.VarChar(50)
|
||
borrow_time DateTime @default(now())
|
||
expected_return_time DateTime?
|
||
is_long_term Boolean @default(false)
|
||
return_time DateTime?
|
||
status String @default("已借出") @db.VarChar(20)
|
||
return_condition String @default("正常") @db.VarChar(20)
|
||
notes String? @db.Text
|
||
children_snapshot String? @db.Text // JSON格式的配件快照
|
||
created_at DateTime @default(now())
|
||
updated_at DateTime @updatedAt
|
||
|
||
equipment Equipment @relation(fields: [equipment_id], references: [id])
|
||
person Person @relation(fields: [person_id], references: [id])
|
||
|
||
@@index([equipment_id])
|
||
@@index([person_id])
|
||
@@index([status])
|
||
@@index([borrow_time])
|
||
@@map("borrow_record")
|
||
}
|
||
|
||
model User {
|
||
id Int @id @default(autoincrement())
|
||
username String @unique @db.VarChar(50)
|
||
password String @db.VarChar(255)
|
||
name String @db.VarChar(50)
|
||
email String? @db.VarChar(100)
|
||
phone String? @db.VarChar(20)
|
||
role String @default("user") @db.VarChar(20)
|
||
status String @default("active") @db.VarChar(20)
|
||
last_login_at DateTime? @db.DateTime
|
||
created_at DateTime @default(now())
|
||
updated_at DateTime @updatedAt
|
||
|
||
operation_logs OperationLog[]
|
||
site_configs SiteConfig[] @relation("SiteConfigUpdatedBy")
|
||
mount_histories MountHistory[]
|
||
// 报废记录关联
|
||
disposal_applied DisposalRecord[] @relation("DisposalApplier")
|
||
disposal_approved DisposalRecord[] @relation("DisposalApprover")
|
||
// 维修记录关联
|
||
maintenance_records MaintenanceRecord[]
|
||
notifications UserNotification[]
|
||
processed_sync_changes SyncChange[] @relation("SyncChangeProcessedBy")
|
||
|
||
@@index([role])
|
||
@@index([status])
|
||
@@map("user")
|
||
}
|
||
|
||
model SiteConfig {
|
||
id Int @id @default(autoincrement())
|
||
site_name String @db.VarChar(100)
|
||
logo_url String? @db.VarChar(255)
|
||
favicon_url String? @db.VarChar(255)
|
||
theme_color String? @db.VarChar(20)
|
||
updated_by Int?
|
||
created_at DateTime @default(now())
|
||
updated_at DateTime @default(now())
|
||
|
||
updatedBy User? @relation("SiteConfigUpdatedBy", fields: [updated_by], references: [id])
|
||
|
||
@@map("site_config")
|
||
}
|
||
|
||
model Person {
|
||
id Int @id @default(autoincrement())
|
||
nickname String @db.VarChar(50)
|
||
real_name String @db.VarChar(50)
|
||
id_number String? @unique @db.VarChar(50)
|
||
department String? @db.VarChar(100)
|
||
main_department_id Int?
|
||
position String? @db.VarChar(100)
|
||
phone String? @db.VarChar(20)
|
||
email String? @db.VarChar(100)
|
||
status String @default("active") @db.VarChar(20)
|
||
remarks String? @db.Text
|
||
source_userid String? @unique @db.VarChar(100)
|
||
source_system String? @db.VarChar(30)
|
||
source_main_department_id Int?
|
||
source_dept_ids String? @db.Text
|
||
manager_source_userid String? @db.VarChar(100)
|
||
source_employee_status String? @db.VarChar(30)
|
||
last_synced_at DateTime?
|
||
created_at DateTime @default(now())
|
||
updated_at DateTime @updatedAt
|
||
|
||
borrow_records BorrowRecord[]
|
||
mainDepartment Department? @relation("PersonMainDepartment", fields: [main_department_id], references: [id])
|
||
personDepartments PersonDepartment[]
|
||
|
||
@@index([nickname])
|
||
@@index([real_name])
|
||
@@index([status])
|
||
@@index([main_department_id])
|
||
@@index([source_system])
|
||
@@index([last_synced_at])
|
||
@@map("person")
|
||
}
|
||
|
||
model PersonDepartment {
|
||
person_id Int
|
||
department_id Int
|
||
created_at DateTime @default(now())
|
||
updated_at DateTime @updatedAt
|
||
|
||
person Person @relation(fields: [person_id], references: [id], onDelete: Cascade)
|
||
department Department @relation(fields: [department_id], references: [id], onDelete: Cascade)
|
||
|
||
@@id([person_id, department_id])
|
||
@@index([department_id])
|
||
@@map("person_department")
|
||
}
|
||
|
||
model StorageLocation {
|
||
id Int @id @default(autoincrement())
|
||
name String @db.VarChar(100)
|
||
code String? @db.VarChar(50)
|
||
status String @default("active") @db.VarChar(20)
|
||
description String? @db.Text
|
||
created_at DateTime @default(now())
|
||
updated_at DateTime @updatedAt
|
||
|
||
equipments Equipment[]
|
||
|
||
@@index([status])
|
||
@@map("storage_location")
|
||
}
|
||
|
||
model OperationLog {
|
||
id Int @id @default(autoincrement())
|
||
user_id Int?
|
||
username String? @db.VarChar(50)
|
||
operation_type String @db.VarChar(50)
|
||
equipment_id Int?
|
||
equipment_code String? @db.VarChar(50)
|
||
operation_details String? @db.Text
|
||
ip_address String? @db.VarChar(50)
|
||
created_at DateTime @default(now())
|
||
|
||
user User? @relation(fields: [user_id], references: [id])
|
||
|
||
@@index([user_id])
|
||
@@index([operation_type])
|
||
@@index([created_at])
|
||
@@map("operation_log")
|
||
}
|
||
|
||
model SyncJob {
|
||
id Int @id @default(autoincrement())
|
||
sync_type String @db.VarChar(30)
|
||
trigger_mode String @db.VarChar(30)
|
||
status String @default("success") @db.VarChar(20)
|
||
operator String? @db.VarChar(50)
|
||
summary String? @db.Text
|
||
result_payload String? @db.Text
|
||
created_at DateTime @default(now())
|
||
|
||
changes SyncChange[]
|
||
notifications Notification[]
|
||
|
||
@@index([sync_type, created_at])
|
||
@@index([status, created_at])
|
||
@@map("sync_job")
|
||
}
|
||
|
||
model SyncChange {
|
||
id Int @id @default(autoincrement())
|
||
sync_job_id Int
|
||
entity_type String @db.VarChar(20)
|
||
entity_key String? @db.VarChar(100)
|
||
entity_name String @db.VarChar(100)
|
||
change_type String @db.VarChar(50)
|
||
title String @db.VarChar(150)
|
||
detail String? @db.Text
|
||
before_snapshot String? @db.Text
|
||
after_snapshot String? @db.Text
|
||
processing_status String @default("pending") @db.VarChar(20)
|
||
processing_notes String? @db.Text
|
||
processed_by Int?
|
||
processed_at DateTime?
|
||
created_at DateTime @default(now())
|
||
|
||
syncJob SyncJob @relation(fields: [sync_job_id], references: [id], onDelete: Cascade)
|
||
processedBy User? @relation("SyncChangeProcessedBy", fields: [processed_by], references: [id], onDelete: SetNull)
|
||
|
||
@@index([sync_job_id])
|
||
@@index([entity_type, change_type])
|
||
@@index([processing_status, created_at])
|
||
@@index([processed_by])
|
||
@@map("sync_change")
|
||
}
|
||
|
||
model Notification {
|
||
id Int @id @default(autoincrement())
|
||
title String @db.VarChar(150)
|
||
content String? @db.Text
|
||
type String @default("info") @db.VarChar(30)
|
||
level String @default("info") @db.VarChar(20)
|
||
action_url String? @db.VarChar(255)
|
||
related_sync_job_id Int?
|
||
metadata String? @db.Text
|
||
created_at DateTime @default(now())
|
||
|
||
syncJob SyncJob? @relation(fields: [related_sync_job_id], references: [id], onDelete: SetNull)
|
||
recipients UserNotification[]
|
||
|
||
@@index([related_sync_job_id])
|
||
@@index([created_at])
|
||
@@map("notification")
|
||
}
|
||
|
||
model UserNotification {
|
||
id Int @id @default(autoincrement())
|
||
user_id Int
|
||
notification_id Int
|
||
is_read Boolean @default(false)
|
||
read_at DateTime?
|
||
created_at DateTime @default(now())
|
||
|
||
user User @relation(fields: [user_id], references: [id], onDelete: Cascade)
|
||
notification Notification @relation(fields: [notification_id], references: [id], onDelete: Cascade)
|
||
|
||
@@unique([user_id, notification_id])
|
||
@@index([user_id, is_read, created_at])
|
||
@@map("user_notification")
|
||
}
|
||
|
||
|
||
model MountHistory {
|
||
id Int @id @default(autoincrement())
|
||
child_id Int // 子资产ID
|
||
parent_id Int? // 父资产ID
|
||
operation_type String @db.VarChar(20) // mount/unmount/replace
|
||
operated_at DateTime @default(now())
|
||
operated_by Int // 操作人ID
|
||
notes String? @db.Text
|
||
old_parent_id Int? // 更换时的旧父资产ID
|
||
new_parent_id Int? // 更换时的新父资产ID
|
||
|
||
child Equipment @relation(fields: [child_id], references: [id])
|
||
operator User @relation(fields: [operated_by], references: [id])
|
||
|
||
@@index([child_id])
|
||
@@index([parent_id])
|
||
@@index([operation_type])
|
||
@@index([operated_at])
|
||
@@map("mount_history")
|
||
}
|
||
|
||
// 报废记录
|
||
model DisposalRecord {
|
||
id Int @id @default(autoincrement())
|
||
equipment_id Int
|
||
equipment_code String @db.VarChar(50)
|
||
disposal_reason String @db.Text // 报废原因
|
||
disposal_method String @db.VarChar(50) // 处置方式:报废/转让/捐赠
|
||
estimated_value Decimal @db.Decimal(12,2) // 残值估价
|
||
actual_value Decimal? @db.Decimal(12,2) // 实际处置价值
|
||
status String @default("pending") @db.VarChar(20) // pending/approved/rejected/completed
|
||
applied_by Int // 申请人
|
||
applied_at DateTime @default(now())
|
||
approved_by Int? // 审批人
|
||
approved_at DateTime?
|
||
completed_at DateTime? // 完成时间
|
||
notes String? @db.Text
|
||
created_at DateTime @default(now())
|
||
updated_at DateTime @updatedAt
|
||
|
||
equipment Equipment @relation(fields: [equipment_id], references: [id])
|
||
applier User @relation("DisposalApplier", fields: [applied_by], references: [id])
|
||
approver User? @relation("DisposalApprover", fields: [approved_by], references: [id])
|
||
|
||
@@index([equipment_id])
|
||
@@index([status])
|
||
@@map("disposal_record")
|
||
}
|
||
|
||
// 维修记录
|
||
model MaintenanceRecord {
|
||
id Int @id @default(autoincrement())
|
||
equipment_id Int
|
||
equipment_code String @db.VarChar(50)
|
||
issue_description String @db.Text // 故障描述
|
||
repair_vendor String? @db.VarChar(100) // 维修商
|
||
estimated_cost Decimal @db.Decimal(10,2) // 预估费用
|
||
actual_cost Decimal? @db.Decimal(10,2) // 实际费用
|
||
start_date DateTime @default(now()) // 送修日期
|
||
expected_end_date DateTime? // 预计完成日期
|
||
actual_end_date DateTime? // 实际完成日期
|
||
status String @default("in_progress") @db.VarChar(20) // in_progress/completed/cancelled
|
||
repair_result String? @db.Text // 维修结果
|
||
created_by Int
|
||
created_at DateTime @default(now())
|
||
updated_at DateTime @updatedAt
|
||
|
||
equipment Equipment @relation(fields: [equipment_id], references: [id])
|
||
creator User @relation(fields: [created_by], references: [id])
|
||
|
||
@@index([equipment_id])
|
||
@@index([status])
|
||
@@map("maintenance_record")
|
||
}
|