import { Type } from 'class-transformer'; import { IsArray, IsBoolean, IsIn, IsNotEmpty, IsNumber, IsObject, IsOptional, IsString, Min } from 'class-validator'; export class UpdateStoreStatusDto { @IsString() @IsIn(['OPEN', 'PAUSED', 'CLOSED']) status: string; } export class CreateStoreDto { @IsString() @IsNotEmpty() partnerId: string; @IsString() @IsNotEmpty() cityId: string; @IsString() @IsNotEmpty() name: string; @IsString() @IsNotEmpty() phone: string; @IsOptional() @IsString() categoryId?: string; @IsOptional() @IsString() province?: string; @IsOptional() @IsString() city?: string; @IsOptional() @IsString() district?: string; @IsString() @IsNotEmpty() address: string; @IsOptional() @IsString() intro?: string; @IsOptional() @IsString() coverUrl?: string; @IsOptional() @IsString() accountName?: string; @IsOptional() @IsString() bankAccountName?: string; @IsOptional() @IsString() bankAccountNo?: string; @IsOptional() @IsString() bankBranch?: string; @IsOptional() @IsArray() @IsString({ each: true }) envPhotoUrls?: string[]; @IsOptional() @IsString() contractUrl?: string; } export class UpdateStoreDto { @IsOptional() @IsString() name?: string; @IsOptional() @IsString() phone?: string; @IsOptional() @IsString() intro?: string; @IsOptional() @IsString() coverUrl?: string; @IsOptional() @IsString() address?: string; @IsOptional() @IsString() district?: string; } export class CreateStoreAccountDto { @IsString() @IsNotEmpty() storeId: string; @IsString() @IsNotEmpty() phone: string; @IsString() @IsNotEmpty() name: string; } export class UpdateStoreAccountDto { @IsOptional() @IsString() name?: string; @IsOptional() @IsString() phone?: string; @IsOptional() @IsIn(['ACTIVE', 'DISABLED']) status?: string; } export class CreatePartnerDto { @IsString() @IsNotEmpty() companyName: string; @IsString() @IsNotEmpty() address: string; @IsString() @IsNotEmpty() contactPhone: string; @IsOptional() @IsString() bankAccountName?: string; @IsOptional() @IsString() bankAccountNo?: string; @IsOptional() @IsString() bankBranch?: string; } export class UpdatePartnerDto { @IsOptional() @IsString() companyName?: string; @IsOptional() @IsString() address?: string; @IsOptional() @IsString() contactPhone?: string; @IsOptional() @IsString() bankAccountName?: string; @IsOptional() @IsString() bankAccountNo?: string; @IsOptional() @IsString() bankBranch?: string; } export class UpdatePartnerAccountDto { @IsOptional() @IsString() name?: string; @IsOptional() @IsString() phone?: string; @IsOptional() @IsIn(['ACTIVE', 'DISABLED']) status?: string; } export class CreatePartnerAccountDto { @IsString() @IsNotEmpty() partnerId: string; @IsString() @IsNotEmpty() phone: string; @IsString() @IsNotEmpty() name: string; @IsOptional() @IsIn(['PARTNER', 'INTERNAL', 'PROMOTER']) staffRole?: string; } export class CreateCityDto { @IsString() @IsNotEmpty() code: string; @IsString() @IsNotEmpty() name: string; @IsString() @IsNotEmpty() province: string; @IsOptional() @IsString() partnerId?: string; @IsOptional() @IsIn(['PENDING', 'ACTIVE', 'PAUSED']) status?: string; } export class UpdateCityDto { @IsOptional() @IsString() name?: string; @IsOptional() @IsString() province?: string; @IsOptional() @IsString() partnerId?: string; @IsOptional() @IsIn(['PENDING', 'ACTIVE', 'PAUSED']) status?: string; @IsOptional() localMinQty?: number; @IsOptional() crossMinQty?: number; } export class CreateStoreMediaDto { @IsString() @IsNotEmpty() storeId: string; @IsString() @IsIn(['IMAGE', 'VIDEO']) mediaType: string; @IsString() @IsNotEmpty() url: string; @IsOptional() sortOrder?: number; } export class UpdateStoreMediaDto { @IsOptional() @IsString() url?: string; @IsOptional() @IsIn(['IMAGE', 'VIDEO']) mediaType?: string; @IsOptional() sortOrder?: number; } export class UpdateOrderStatusDto { @IsString() @IsIn([ 'PENDING_PAY', 'PENDING_SHIP', 'OUT_WAREHOUSE', 'SHIPPING', 'PENDING_RECEIVE', 'COMPLETED', 'CANCELLED', 'REFUNDING', 'REFUNDED', ]) status: string; } export class BatchDeleteOrdersDto { @IsArray() @IsString({ each: true }) ids: string[]; } export class BatchDeleteUsersDto { @IsArray() @IsString({ each: true }) ids: string[]; } export class BatchDeleteUsersConfirmDto extends BatchDeleteUsersDto { @IsBoolean() confirmRisk: boolean; } /** HQ 订单发货(目前仅小飞侠 XFX) */ export class AdminShipOrderDto { @IsIn(['XFX']) provider: string; @IsOptional() @IsString() fromName?: string; @IsOptional() @IsString() fromMobile?: string; @IsOptional() @IsString() fromAddress?: string; @IsOptional() @IsString() fromAddressDetail?: string; @IsOptional() @IsNumber() fromLng?: number; @IsOptional() @IsNumber() fromLat?: number; @IsOptional() @Type(() => Number) @IsNumber() @Min(0.01) weight?: number; @IsOptional() @IsIn(['1', '2']) payMode?: string; @IsOptional() @IsString() remark?: string; } export class AdminRedeemDebugCreateTokenDto { @IsString() @IsNotEmpty() userId: string; @Type(() => Number) @IsNumber() @Min(0.01) amount: number; @IsOptional() @IsString() couponId?: string; @IsOptional() @IsString() storeId?: string; } export class AdminRedeemDebugStoreTokenDto { @IsString() @IsNotEmpty() storeId: string; @IsString() @IsNotEmpty() token: string; } export class UpdateDeliveryDto { @IsOptional() @IsString() provider?: string; @IsOptional() @IsString() providerOrderNo?: string; @IsOptional() @IsString() trackingNo?: string; } export class CreateHqAccountDto { @IsString() @IsNotEmpty() phone: string; @IsString() @IsNotEmpty() name: string; @IsOptional() @IsIn(['SUPER_ADMIN', 'OPS', 'FINANCE', 'CUSTOMER_SERVICE']) adminRole?: string; } export class UpdateHqAccountDto { @IsOptional() @IsString() name?: string; @IsOptional() @IsIn(['SUPER_ADMIN', 'OPS', 'FINANCE', 'CUSTOMER_SERVICE']) adminRole?: string; @IsOptional() @IsIn(['ACTIVE', 'DISABLED']) status?: string; } export class CreateProductDto { @IsString() @IsNotEmpty() skuCode: string; @IsString() @IsNotEmpty() barcode69: string; @IsString() @IsNotEmpty() name: string; @IsOptional() @IsString() subtitle?: string; @IsIn(['QINGXIANG', 'JIANGXIANG', 'NONGXIANG']) aromaType: string; @IsString() @IsNotEmpty() spec: string; @IsNumber() price: number; @IsOptional() @IsNumber() benefitAmount?: number; @IsOptional() @IsIn(['DRAFT', 'ON_SALE', 'OFF_SALE']) status?: string; @IsOptional() @IsNumber() sortOrder?: number; @IsOptional() @IsString() coverUrl?: string; @IsOptional() @IsArray() @IsString({ each: true }) carouselUrls?: string[]; @IsOptional() @IsArray() @IsString({ each: true }) detailImageUrls?: string[]; @IsOptional() @IsObject() detailContent?: Record; } export class UpdateProductDto { @IsOptional() @IsString() name?: string; @IsOptional() @IsString() subtitle?: string; @IsOptional() @IsString() spec?: string; @IsOptional() @IsNumber() price?: number; @IsOptional() @IsNumber() benefitAmount?: number; @IsOptional() @IsIn(['DRAFT', 'ON_SALE', 'OFF_SALE']) status?: string; @IsOptional() @IsNumber() sortOrder?: number; @IsOptional() @IsString() coverUrl?: string; @IsOptional() @IsArray() @IsString({ each: true }) carouselUrls?: string[]; @IsOptional() @IsArray() @IsString({ each: true }) detailImageUrls?: string[]; @IsOptional() @IsObject() detailContent?: Record; } class ProductDetailFeatureInputDto { @IsString() icon: string; @IsString() title: string; @IsString() desc: string; } export class CreateProductDetailTemplateDto { @IsString() @IsNotEmpty() code: string; @IsString() @IsNotEmpty() name: string; @IsOptional() @IsString() description?: string; @IsOptional() @IsIn(['QINGXIANG', 'JIANGXIANG', 'NONGXIANG']) aromaType?: string; @IsOptional() @IsString() storyTitle?: string; @IsOptional() @IsString() storyText?: string; @IsOptional() @IsArray() features?: ProductDetailFeatureInputDto[]; @IsOptional() @IsArray() @IsString({ each: true }) detailImageUrls?: string[]; @IsOptional() @IsNumber() suggestedDetailImageCount?: number; @IsOptional() @IsNumber() sortOrder?: number; @IsOptional() @IsIn(['ACTIVE', 'DISABLED']) status?: string; } export class UpdateProductDetailTemplateDto { @IsOptional() @IsString() code?: string; @IsOptional() @IsString() name?: string; @IsOptional() @IsString() description?: string; @IsOptional() @IsIn(['QINGXIANG', 'JIANGXIANG', 'NONGXIANG', null]) aromaType?: string | null; @IsOptional() @IsString() storyTitle?: string; @IsOptional() @IsString() storyText?: string; @IsOptional() @IsArray() features?: ProductDetailFeatureInputDto[]; @IsOptional() @IsArray() @IsString({ each: true }) detailImageUrls?: string[]; @IsOptional() @IsNumber() suggestedDetailImageCount?: number; @IsOptional() @IsNumber() sortOrder?: number; @IsOptional() @IsIn(['ACTIVE', 'DISABLED']) status?: string; } export class CreatePromoCodeDto { @IsString() @IsNotEmpty() name: string; @IsOptional() @IsString() code?: string; } export class UpdatePromoCodeStatusDto { @IsString() @IsIn(['ACTIVE', 'DISABLED']) status: 'ACTIVE' | 'DISABLED'; }