import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsArray, IsBoolean, IsDateString, IsIn, IsInt, IsNotEmpty, IsOptional, IsString, Min, ValidateNested, } from 'class-validator'; /** 计划项(svc_plan_item)入参。svc_id 引用本机构 L4(svc_org.id)。 */ export class PlanItemInputDto { @ApiProperty({ description: '本机构 L4 项目库 svc_org.id' }) @IsString() @IsNotEmpty() svcId!: string; @ApiPropertyOptional({ description: '频次类型:daily/weekly_n/monthly_n/as_needed' }) @IsOptional() @IsString() freqType?: string; @ApiPropertyOptional({ description: '频次值(如每周 3 次填 3)' }) @IsOptional() @IsInt() freqValue?: number; @ApiPropertyOptional({ description: '单次时长(分钟)' }) @IsOptional() @IsInt() durationMin?: number; @ApiPropertyOptional({ description: '拍照档位:must/optional/free', enum: ['must', 'optional', 'free'] }) @IsOptional() @IsIn(['must', 'optional', 'free']) photoTier?: string; @ApiPropertyOptional({ description: '注意事项' }) @IsOptional() @IsString() cautionNote?: string; @ApiPropertyOptional({ description: '是否医疗护理类' }) @IsOptional() @IsBoolean() isMedical?: boolean; @ApiPropertyOptional({ description: '是否要求持证' }) @IsOptional() @IsBoolean() needCert?: boolean; } /** 制定服务计划入参。plan_status 由服务端定(制定=draft),不接受前端传入。 */ export class CreatePlanDto { @ApiProperty({ description: '老人 ID' }) @IsString() @IsNotEmpty() elderId!: string; @ApiProperty({ description: '计划周期起(YYYY-MM-DD)' }) @IsDateString() planPeriodStart!: string; @ApiProperty({ description: '计划周期止(YYYY-MM-DD)' }) @IsDateString() planPeriodEnd!: string; @ApiProperty({ description: '护理等级:care_1/care_2/care_3', enum: ['care_1', 'care_2', 'care_3'] }) @IsString() @IsNotEmpty() careLevel!: string; @ApiProperty({ description: '护理方式:inst_medical/inst_nursing/home_org/home_individual', enum: ['inst_medical', 'inst_nursing', 'home_org', 'home_individual'], }) @IsString() @IsNotEmpty() careMode!: string; @ApiProperty({ description: '计划项目列表', type: [PlanItemInputDto] }) @IsArray() @ValidateNested({ each: true }) @Type(() => PlanItemInputDto) items!: PlanItemInputDto[]; @ApiPropertyOptional({ description: '每周次数(居家类)' }) @IsOptional() @IsInt() @Min(0) weekFreq?: number; @ApiPropertyOptional({ description: '每月小时数(居家类)' }) @IsOptional() @IsInt() @Min(0) monthHours?: number; @ApiPropertyOptional({ description: '附加项数(≤5)' }) @IsOptional() @IsInt() @Min(0) extraItemCount?: number; @ApiPropertyOptional({ description: '计划依据快照(json)' }) @IsOptional() planBasis?: unknown; } /** 变更计划入参:change_from_plan_id 指向被变更的旧计划。 */ export class ChangePlanDto extends CreatePlanDto { @ApiProperty({ description: '被变更的旧计划 ID' }) @IsString() @IsNotEmpty() changeFromPlanId!: string; } /** 计划确认入参(老人/家属确认,确认后计划转 active)。 */ export class ConfirmPlanDto { @ApiProperty({ description: '老人确认' }) @IsBoolean() confirmElder!: boolean; @ApiPropertyOptional({ description: '家属确认(可选)' }) @IsOptional() @IsBoolean() confirmGuardian?: boolean; }