import { Type } from 'class-transformer'; import { IsArray, ArrayMaxSize, ArrayMinSize, IsDateString, IsIn, IsInt, IsMobilePhone, IsOptional, IsString, IsUUID, Length, Max, Matches, Min, ValidateNested, } from 'class-validator'; import { OLD_ITEM_CATEGORIES, OLD_ITEM_CONDITIONS, OLD_ITEM_DONATION_METHODS, OLD_ITEM_DONATION_STATUSES, OLD_ITEM_NEED_STATUSES, OLD_ITEM_INVENTORY_STATUSES, } from '@lehuo/contracts'; import { PaginationDto } from '../../case-management/dto/case-management.dto'; export class OldItemDonationQueryDto extends PaginationDto { @IsOptional() @IsIn(OLD_ITEM_DONATION_STATUSES) status?: string; @IsOptional() @IsIn(OLD_ITEM_DONATION_METHODS) method?: string; @IsOptional() @IsString() @Length(1, 100) keyword?: string; } export class OldItemNeedQueryDto extends PaginationDto { @IsOptional() @IsIn(OLD_ITEM_CATEGORIES) category?: string; @IsOptional() @IsIn(OLD_ITEM_NEED_STATUSES) status?: string; } export class CreateOldItemDonationDto { @IsUUID('4') clientRequestId!: string; @IsIn(OLD_ITEM_CATEGORIES) category!: string; @IsIn(OLD_ITEM_CONDITIONS) itemCondition!: string; @Type(() => Number) @IsInt() @Min(1) @Max(9999) quantity!: number; @IsString() @Length(2, 1000) description!: string; @IsIn(OLD_ITEM_DONATION_METHODS) method!: 'PICKUP' | 'DROP_OFF'; @IsString() @Length(2, 50) contactName!: string; @IsMobilePhone('zh-CN') mobile!: string; @IsOptional() @IsString() @Length(5, 500) address?: string; @IsOptional() @IsDateString() appointmentAt?: string; @IsOptional() @IsUUID('4') dropOffPointPublicId?: string; @IsOptional() @IsUUID('4') targetNeedPublicId?: string; @IsOptional() @IsArray() @IsUUID('4', { each: true }) imagePublicIds?: string[]; } export class CreateOldItemMediaUploadIntentDto { @IsUUID('4') clientRequestId!: string; @IsIn(['OLD_ITEM_DONATION_IMAGE']) businessType!: 'OLD_ITEM_DONATION_IMAGE'; @IsString() @Length(1, 255) filename!: string; @IsIn(['image/jpeg', 'image/png', 'image/webp']) mimeType!: 'image/jpeg' | 'image/png' | 'image/webp'; @Type(() => Number) @IsInt() @Min(1) @Max(10 * 1024 * 1024) size!: number; @IsOptional() @Matches(/^[a-fA-F0-9]{64}$/) sha256?: string; } export class TransitionOldItemDonationDto { @IsUUID('4') clientRequestId!: string; @Type(() => Number) @IsInt() @Min(1) expectedRevision!: number; @IsIn(OLD_ITEM_DONATION_STATUSES) targetStatus!: string; @IsOptional() @IsString() @Length(1, 500) note?: string; @IsOptional() @IsUUID('4') assignedUserPublicId?: string; @IsOptional() @Type(() => Number) @IsInt() @Min(0) @Max(999999) assistedPeople?: number; } export class CreateOldItemNeedDto { @IsUUID('4') clientRequestId!: string; @IsString() @Length(2, 160) title!: string; @IsIn(OLD_ITEM_CATEGORIES) category!: string; @IsString() @Length(2, 120) regionText!: string; @IsString() @Length(2, 160) beneficiaryGroup!: string; @IsString() @Length(2, 2000) description!: string; @Type(() => Number) @IsInt() @Min(1) @Max(999999) requestedQuantity!: number; @IsOptional() @Type(() => Number) @IsInt() @Min(0) @Max(100) priority?: number; @IsOptional() @Type(() => Number) @IsInt() @Min(-9999) @Max(9999) sortOrder?: number; } export class UpdateOldItemNeedDto { @Type(() => Number) @IsInt() @Min(1) expectedRevision!: number; @IsString() @Length(2, 160) title!: string; @IsIn(OLD_ITEM_CATEGORIES) category!: string; @IsString() @Length(2, 120) regionText!: string; @IsString() @Length(2, 160) beneficiaryGroup!: string; @IsString() @Length(2, 2000) description!: string; @Type(() => Number) @IsInt() @Min(1) @Max(999999) requestedQuantity!: number; @IsOptional() @Type(() => Number) @IsInt() @Min(0) @Max(100) priority?: number; @IsOptional() @Type(() => Number) @IsInt() @Min(-9999) @Max(9999) sortOrder?: number; } export class TransitionOldItemNeedDto { @IsUUID('4') clientRequestId!: string; @Type(() => Number) @IsInt() @Min(1) expectedRevision!: number; @IsIn(OLD_ITEM_NEED_STATUSES) targetStatus!: string; } export class CreateOldItemDropOffPointDto { @IsString() @Length(2, 120) name!: string; @IsString() @Length(2, 120) regionText!: string; @IsString() @Length(5, 300) addressText!: string; @IsString() @Length(2, 200) openingHours!: string; @IsOptional() @Type(() => Number) @IsInt() @Min(-9999) @Max(9999) sortOrder?: number; } export class OldItemInventoryQueryDto extends PaginationDto { @IsOptional() @IsIn(OLD_ITEM_INVENTORY_STATUSES) status?: string; @IsOptional() @IsIn(OLD_ITEM_CATEGORIES) category?: string; @IsOptional() @IsString() @Length(1, 100) keyword?: string; } export class CreateOldItemInventoryDto { @IsUUID('4') clientRequestId!: string; @IsOptional() @IsUUID('4') sourceDonationPublicId?: string; @IsIn(OLD_ITEM_CATEGORIES) category!: string; @IsString() @Length(1, 160) itemName!: string; @Type(() => Number) @IsInt() @Min(1) @Max(999999) quantity!: number; @IsString() @Length(1, 20) unit!: string; @IsString() @Length(2, 160) storageLocation!: string; @IsOptional() @IsUUID('4') targetNeedPublicId?: string; @IsOptional() @IsString() @Length(1, 1000) note?: string; @IsOptional() @IsDateString() inboundAt?: string; } export class OldItemInventoryImportRowDto { @IsOptional() @IsString() @Length(1, 32) sourceDonationNo?: string; @IsIn(OLD_ITEM_CATEGORIES) category!: string; @IsString() @Length(1, 160) itemName!: string; @Type(() => Number) @IsInt() @Min(1) @Max(999999) quantity!: number; @IsString() @Length(1, 20) unit!: string; @IsString() @Length(2, 160) storageLocation!: string; @IsOptional() @IsUUID('4') targetNeedPublicId?: string; @IsOptional() @IsString() @Length(1, 1000) note?: string; @IsOptional() @IsDateString() inboundAt?: string; } export class ImportOldItemInventoryDto { @IsUUID('4') clientRequestId!: string; @IsString() @Length(1, 255) originalFilename!: string; @IsArray() @ArrayMinSize(1) @ArrayMaxSize(500) @ValidateNested({ each: true }) @Type(() => OldItemInventoryImportRowDto) rows!: OldItemInventoryImportRowDto[]; } export class TransitionOldItemInventoryDto { @IsUUID('4') clientRequestId!: string; @Type(() => Number) @IsInt() @Min(1) expectedRevision!: number; @IsIn(OLD_ITEM_INVENTORY_STATUSES) targetStatus!: string; @IsOptional() @IsDateString() eventAt?: string; @IsOptional() @IsString() @Length(2, 160) locationText?: string; @IsOptional() @IsString() @Length(1, 1000) note?: string; @IsOptional() @IsUUID('4') targetNeedPublicId?: string; @IsOptional() @IsUUID('4') beneficiaryPublicId?: string; @IsOptional() @IsString() @Length(2, 120) destinationRegion?: string; @IsOptional() @Type(() => Number) @IsInt() @Min(0) @Max(999999) assistedPeople?: number; } export class ActivateOldItemRewardConfigDto { @IsUUID('4') clientRequestId!: string; @IsString() @Length(2, 120) certificateTitle!: string; @IsString() @Length(10, 1000) certificateMessage!: string; @IsString() @Length(2, 120) issuerName!: string; @IsString() @Length(10, 500) legalNotice!: string; @Type(() => Number) @IsInt() @Min(0) @Max(1000) clothingPoints!: number; @Type(() => Number) @IsInt() @Min(0) @Max(1000) booksPoints!: number; @Type(() => Number) @IsInt() @Min(0) @Max(1000) householdPoints!: number; @Type(() => Number) @IsInt() @Min(0) @Max(1000) sportsPoints!: number; @Type(() => Number) @IsInt() @Min(0) @Max(100000) maxPointsPerDonation!: number; } export class IssueOldItemCertificateDto { @IsUUID('4') clientRequestId!: string; } export class RevokeOldItemCertificateDto { @IsUUID('4') clientRequestId!: string; @IsString() @Length(2, 500) reason!: string; } export class AdjustOldItemPointsDto { @IsUUID('4') clientRequestId!: string; @Type(() => Number) @IsInt() @Min(1) expectedRevision!: number; @Type(() => Number) @IsInt() @Min(-100000) @Max(100000) pointsDelta!: number; @IsString() @Length(2, 500) reason!: string; } export class OldItemPointAccountQueryDto extends PaginationDto { @IsOptional() @IsString() @Length(1, 100) keyword?: string; }