model AutomationTask { id String @id @default(uuid()) @db.Uuid name String code String @unique description String? type AutomationTaskType status AutomationTaskStatus @default(ACTIVE) scheduleType String @map("schedule_type") scheduleConfig Json @default("{}") @map("schedule_config") config Json @default("{}") timeout Int @default(300000) retryCount Int @default(3) @map("retry_count") lastRunAt DateTime? @map("last_run_at") @db.Timestamptz(3) lastStatus AutomationExecutionStatus? @map("last_status") nextRunAt DateTime? @map("next_run_at") @db.Timestamptz(3) totalRuns Int @default(0) @map("total_runs") successRuns Int @default(0) @map("success_runs") failedRuns Int @default(0) @map("failed_runs") createdById String? @map("created_by_id") @db.Uuid createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) executions AutomationExecution[] createdBy User? @relation("AutomationTaskCreator", fields: [createdById], references: [id]) @@index([code]) @@index([type]) @@index([status]) @@map("automation_tasks") @@schema("platform_automation") } model AutomationExecution { id String @id @default(uuid()) @db.Uuid taskId String @map("task_id") @db.Uuid status AutomationExecutionStatus startedAt DateTime @default(now()) @map("started_at") @db.Timestamptz(3) completedAt DateTime? @map("completed_at") @db.Timestamptz(3) duration Int? result Json? error String? logs String? triggerType String @map("trigger_type") triggeredBy String? @map("triggered_by") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) task AutomationTask @relation(fields: [taskId], references: [id], onDelete: Cascade) @@index([taskId]) @@index([status]) @@index([startedAt]) @@map("automation_executions") @@schema("platform_automation") } enum AutomationTaskType { LDAP_SYNC DATA_CLEANUP REPORT_GENERATION NOTIFICATION BACKUP DINGTALK_SYNC ADP_SYNC M365_DORMANT_SYNC CUSTOM @@schema("platform_automation") } enum AutomationTaskStatus { ACTIVE PAUSED DISABLED @@schema("platform_automation") } enum AutomationExecutionStatus { PENDING RUNNING SUCCESS FAILED TIMEOUT CANCELLED @@schema("platform_automation") } model DingtalkSyncConfig { id String @id @default(uuid()) @db.Uuid taskCode String @unique @map("task_code") formUuid String? @map("form_uuid") appType String? @map("app_type") fieldMapping Json @default("{}") syncDirection String @map("sync_direction") searchCondition Json? @map("search_condition") lookbackMinutes Int @default(30) @map("lookback_minutes") metadata Json @default("{}") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) @@map("dingtalk_sync_configs") @@schema("platform_automation") } model DingtalkLeaveCode { id String @id @default(uuid()) @db.Uuid code String @unique name String year Int? category String isActive Boolean @default(true) @map("is_active") metadata Json @default("{}") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) @@map("dingtalk_leave_codes") @@schema("platform_automation") } model DingtalkLeaveQuotaSnapshot { id String @id @default(uuid()) @db.Uuid userId String @map("user_id") employeeName String @map("employee_name") employeeNumber String @default("") @map("employee_number") leaveCode String @map("leave_code") leaveType String @map("leave_type") quotaCycle String @default("") @map("quota_cycle") totalDays Decimal @default(0) @map("total_days") @db.Decimal(10, 2) usedDays Decimal @default(0) @map("used_days") @db.Decimal(10, 2) remainingDays Decimal @default(0) @map("remaining_days") @db.Decimal(10, 2) startDate DateTime? @map("start_date") @db.Date endDate DateTime? @map("end_date") @db.Date usageRecords Json? @map("usage_records") releaseRecords Json? @map("release_records") snapshotAt DateTime @map("snapshot_at") @db.Timestamptz(3) createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) @@unique([userId, leaveCode, quotaCycle, startDate, endDate], map: "dingtalk_leave_quota_snapshots_user_period_key") @@index([userId], map: "dingtalk_leave_quota_snapshots_user_id_idx") @@index([leaveCode], map: "dingtalk_leave_quota_snapshots_leave_code_idx") @@index([snapshotAt], map: "dingtalk_leave_quota_snapshots_snapshot_at_idx") @@map("dingtalk_leave_quota_snapshots") @@schema("platform_automation") } model SapPurchaseSyncRecord { id String @id @default(uuid()) @db.Uuid serialNumber String @unique @map("serial_number") formInstanceId String @map("form_instance_id") applicantName String @map("applicant_name") budgetAmount Decimal @default(0) @map("budget_amount") @db.Decimal(12, 2) sapPrNumber String? @map("sap_pr_number") sapStatus String @map("sap_status") sapMessages Json? @map("sap_messages") sapRawResponse Json? @map("sap_raw_response") approverChain String? @map("approver_chain") syncedAt DateTime @default(now()) @map("synced_at") @db.Timestamptz(3) createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) @@index([sapStatus], map: "sap_purchase_sync_records_status_idx") @@index([syncedAt], map: "sap_purchase_sync_records_synced_at_idx") @@map("sap_purchase_sync_records") @@schema("platform_automation") } model DingtalkEmployee { id String @id @default(uuid()) @db.Uuid userId String @unique @map("user_id") name String @default("") employeeNumber String @default("") @map("employee_number") department String @default("") position String @default("") rank String @default("") phone String @default("") country String @default("") workPlace String @default("") @map("work_place") contractCompany String @default("") @map("contract_company") bank String @default("") bankCardLast4 String @default("") @map("bank_card_last4") monthlyStandardHours String @default("") @map("monthly_standard_hours") workHourLimit String @default("") @map("work_hour_limit") joinDate DateTime? @map("join_date") @db.Timestamptz(3) workStartDate DateTime? @map("work_start_date") @db.Timestamptz(3) tenureDays Int @default(0) @map("tenure_days") status String @default("正常") lastSyncedAt DateTime? @map("last_synced_at") @db.Timestamptz(3) createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) @@index([status], map: "dingtalk_employees_status_idx") @@index([name], map: "dingtalk_employees_name_idx") @@map("dingtalk_employees") @@schema("platform_automation") } model DingtalkEmployeeEmploymentPeriod { id String @id @default(uuid()) @db.Uuid userId String @map("user_id") periodIndex Int @map("period_index") joinDate DateTime @map("join_date") @db.Date leaveDate DateTime? @map("leave_date") @db.Date countInTenure Boolean @default(true) @map("count_in_tenure") note String @default("") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) @@unique([userId, periodIndex], map: "dingtalk_employee_employment_periods_user_index_key") @@index([userId], map: "dingtalk_employee_employment_periods_user_id_idx") @@map("dingtalk_employee_employment_periods") @@schema("platform_automation") } model DingtalkEmployeeSuspensionPeriod { id String @id @default(uuid()) @db.Uuid userId String @map("user_id") startDate DateTime @map("start_date") @db.Date endDate DateTime? @map("end_date") @db.Date reason String @default("") note String @default("") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) @@index([userId], map: "dingtalk_employee_suspension_periods_user_id_idx") @@map("dingtalk_employee_suspension_periods") @@schema("platform_automation") } model SapPurchaseCache { id String @id @default(uuid()) @db.Uuid serialNumber String @unique @map("serial_number") formInstanceId String @map("form_instance_id") sapEnv String @map("sap_env") applicantName String @default("") @map("applicant_name") applicantDept String @default("") @map("applicant_dept") budgetNumber String @default("") @map("budget_number") budgetAmount Decimal @default(0) @map("budget_amount") @db.Decimal(12, 2) purchaseProjectDescription String @default("") @map("purchase_project_description") applicationDate String @default("") @map("application_date") demandCategory String @default("") @map("demand_category") purchasingCompanyName String @default("") @map("purchasing_company_name") materialGroup String @default("") @map("material_group") formData Json @default("{}") @map("form_data") yidaModifiedAt String @default("") @map("yida_modified_at") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) @@index([sapEnv], map: "sap_purchase_cache_env_idx") @@index([applicantName], map: "sap_purchase_cache_applicant_idx") @@map("sap_purchase_cache") @@schema("platform_automation") } // ADP PTO 时段镜像 // 隐私合规:只存"何人/何时不在",不存请假类型/原因/payCode(CPRA 健康信息保护) // 同步策略:每日窗口拉取(today-7d ~ today+35d),仅 approved 状态进入;ADP 端 cancel/pending → 本地硬删 model AdpPtoSchedule { id String @id @default(cuid()) @db.VarChar(32) userId String @map("user_id") @db.Uuid adpAoid String @map("adp_aoid") @db.VarChar(64) // ADP associateOID, 冗余存便于断链追溯 leaveDate DateTime @map("leave_date") @db.Date startTime DateTime @map("start_time") @db.Timestamptz(3) endTime DateTime @map("end_time") @db.Timestamptz(3) adpEntryId String @map("adp_entry_id") @db.VarChar(128) // 不透明锚点,仅做 upsert/delete 幂等 syncedAt DateTime @default(now()) @map("synced_at") @db.Timestamptz(3) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([userId, adpEntryId]) @@index([userId, leaveDate]) @@index([startTime, endTime]) @@map("adp_pto_schedules") @@schema("platform_automation") } model DingtalkAnnualLeaveReleasePlan { id String @id @default(uuid()) @db.Uuid userId String @map("user_id") employeeName String @default("") @map("employee_name") employeeNumber String @default("") @map("employee_number") year Int status String @default("正常") joinDate DateTime? @map("join_date") @db.Date workStartDate DateTime? @map("work_start_date") @db.Date adjustmentDays Decimal @default(0) @map("adjustment_days") @db.Decimal(10, 2) notCountDays Int @default(0) @map("not_count_days") totalDays Int @default(0) @map("total_days") releaseSchedule Json @default("[]") @map("release_schedule") lastCalculatedAt DateTime @map("last_calculated_at") @db.Timestamptz(3) createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) @@unique([userId, year], map: "dingtalk_annual_leave_release_plans_user_year_key") @@index([year], map: "dingtalk_annual_leave_release_plans_year_idx") @@index([status], map: "dingtalk_annual_leave_release_plans_status_idx") @@index([userId], map: "dingtalk_annual_leave_release_plans_user_id_idx") @@index([lastCalculatedAt], map: "dingtalk_annual_leave_release_plans_last_calculated_at_idx") @@map("dingtalk_annual_leave_release_plans") @@schema("platform_automation") }