Files
TurboHR/backend/src/schemas/contract.schema.ts
T
selfrelease 13f485a049 fix: contractType zod 枚举与 Prisma/前端对齐
zod schema 只允许 FIXED|UNFIXED|UNSIGNED 三种,但 Prisma 枚举和
前端 /contract-types 接口返回 8 种(含 LABOR/INTERNSHIP/DISPATCH/
OUTSOURCING/PARTTIME),导致选择劳务协议等类型时校验失败。

扩展 createEmployeeSchema 和 addContractSchema 的 contractType
枚举为全部 8 种,与 Prisma ContractType 枚举一致。

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-16 09:28:58 +08:00

76 lines
3.5 KiB
TypeScript

import { z } from 'zod'
export const createEmployeeSchema = z.object({
name: z.string().min(1, '姓名不能为空').max(30, '姓名最多30个字'),
department: z.string().min(1, '部门不能为空').max(50, '部门最多50个字'),
hireDate: z.string().datetime(),
monthlySalary: z.string().min(1, '月薪不能为空'),
idCardNumber: z.string().min(18, '证件号码不能为空且必须18位').max(18, '证件号码必须18位'),
gender: z.enum(['男', '女']).optional(),
femaleWorkerType: z.enum(['CADRE', 'WORKER']).optional(),
phone: z.string().regex(/^1[3-9]\d{9}$/).optional(),
isPregnant: z.boolean().default(false),
isInMedicalPeriod: z.boolean().default(false),
isWorkInjured: z.boolean().default(false),
city: z.string().max(20).optional(),
education: z.string().max(20).optional(),
position: z.string().max(50).optional(),
contract: z.object({
signDate: z.string().datetime().nullable(),
startDate: z.string().datetime(),
endDate: z.string().datetime().nullable(),
contractType: z.enum(['FIXED', 'UNFIXED', 'UNSIGNED', 'LABOR', 'INTERNSHIP', 'DISPATCH', 'OUTSOURCING', 'PARTTIME']),
signMethod: z.enum(['PAPER', 'ELECTRONIC']).default('PAPER'),
contractYears: z.number().int().min(1).max(10).default(3),
probationMonths: z.number().int().min(0).max(6).default(0),
probationSalary: z.number().min(0).default(0),
}).optional(),
})
export const updateEmployeeSchema = z.object({
name: z.string().min(1).max(30).optional(),
department: z.string().min(1).max(50).optional(),
hireDate: z.string().datetime().optional(),
monthlySalary: z.string().min(1).optional(),
idCardNumber: z.string().min(18).max(18).optional(),
gender: z.enum(['男', '女']).optional(),
femaleWorkerType: z.enum(['CADRE', 'WORKER']).optional(),
phone: z.string().regex(/^1[3-9]\d{9}$/).optional(),
bankName: z.string().max(50).optional(),
bankAccount: z.string().max(30).optional(),
emergencyContact: z.string().max(30).optional(),
emergencyPhone: z.string().max(20).optional(),
address: z.string().max(200).optional(),
isPregnant: z.boolean().optional(),
isInMedicalPeriod: z.boolean().optional(),
isWorkInjured: z.boolean().optional(),
socialInsBase: z.number().min(0).nullable().optional(),
housingFundBase: z.number().min(0).nullable().optional(),
specialDeduction: z.number().min(0).optional(),
city: z.string().max(20).optional(),
education: z.string().max(20).optional(),
position: z.string().max(50).optional(),
status: z.enum(['ACTIVE', 'PENDING_ONBOARD', 'RESIGNED', 'BLACKLISTED']).optional(),
cityChangeReason: z.string().max(200).optional(),
})
export const batchRenewSchema = z.object({
contractIds: z.array(z.string()).min(1, '至少选择一个合同'),
years: z.number().int().min(1).max(5).default(3),
})
export const addContractSchema = z.object({
employeeId: z.string().min(1),
signDate: z.string().datetime().nullable(),
startDate: z.string().datetime(),
endDate: z.string().datetime().nullable(),
contractType: z.enum(['FIXED', 'UNFIXED', 'UNSIGNED', 'LABOR', 'INTERNSHIP', 'DISPATCH', 'OUTSOURCING', 'PARTTIME']),
signMethod: z.enum(['PAPER', 'ELECTRONIC']).default('PAPER'),
contractYears: z.number().int().min(1).max(10).default(3),
probationMonths: z.number().int().min(0).max(6).default(0),
probationSalary: z.number().min(0).default(0),
attachmentUrl: z.string().nullable().optional(),
electronicContractNo: z.string().nullable().optional(),
electronicContractUrl: z.string().nullable().optional(),
})