161 lines
3.2 KiB
TypeScript
161 lines
3.2 KiB
TypeScript
import { Transform, Type } from 'class-transformer';
|
|
import { IsArray, IsIn, IsNotEmpty, IsOptional, IsString, MaxLength, ValidateIf } from 'class-validator';
|
|
import { PromoCodeScene, PromoCodeStatus } from '@dukang/shared-types';
|
|
|
|
function toOptionalNullableString(value: unknown): string | null | undefined {
|
|
if (value === undefined) return undefined;
|
|
if (value === null) return null;
|
|
const t = String(value).trim();
|
|
return t.length ? t : null;
|
|
}
|
|
|
|
export class PromoCodeListQueryDto {
|
|
@IsOptional()
|
|
@Type(() => Number)
|
|
page?: number;
|
|
|
|
@IsOptional()
|
|
@Type(() => Number)
|
|
pageSize?: number;
|
|
|
|
@IsOptional()
|
|
@IsString()
|
|
name?: string;
|
|
|
|
@IsOptional()
|
|
@IsString()
|
|
code?: string;
|
|
|
|
@IsOptional()
|
|
@IsIn(['ACTIVE', 'DISABLED'])
|
|
status?: PromoCodeStatus;
|
|
|
|
@IsOptional()
|
|
@IsIn(['ONLINE_LINK', 'OFFLINE_PICKUP', 'PARTNER_CHANNEL', 'EVENT', 'OTHER'])
|
|
scene?: PromoCodeScene;
|
|
|
|
@IsOptional()
|
|
@IsString()
|
|
ownerUserId?: string;
|
|
|
|
@IsOptional()
|
|
@IsString()
|
|
channelOwnerPartnerId?: string;
|
|
|
|
@IsOptional()
|
|
@IsString()
|
|
assocPartnerAccountId?: string;
|
|
}
|
|
|
|
export class CreatePromoCodeDto {
|
|
@IsString()
|
|
@IsNotEmpty()
|
|
@MaxLength(128)
|
|
name: string;
|
|
|
|
@IsOptional()
|
|
@IsString()
|
|
@MaxLength(32)
|
|
code?: string;
|
|
|
|
@IsOptional()
|
|
@IsIn(['ONLINE_LINK', 'OFFLINE_PICKUP', 'PARTNER_CHANNEL', 'EVENT', 'OTHER'])
|
|
scene?: PromoCodeScene;
|
|
|
|
@IsOptional()
|
|
@IsString()
|
|
ownerUserId?: string;
|
|
|
|
@IsOptional()
|
|
@IsArray()
|
|
@IsString({ each: true })
|
|
channelOwnerPartnerIds?: string[];
|
|
|
|
@IsOptional()
|
|
@Transform(({ value }) => toOptionalNullableString(value))
|
|
@ValidateIf((_, v) => v !== null && v !== undefined)
|
|
@IsString()
|
|
assocPartnerAccountId?: string | null;
|
|
|
|
@IsOptional()
|
|
@IsString()
|
|
@MaxLength(256)
|
|
remark?: string;
|
|
|
|
/** 小程序码落地页路径,如 pages/home/index;留空用环境变量 WX_MINI_PROMO_PAGE */
|
|
@IsOptional()
|
|
@IsString()
|
|
@MaxLength(128)
|
|
page?: string;
|
|
}
|
|
|
|
export class UpdatePromoCodeDto {
|
|
@IsOptional()
|
|
@IsString()
|
|
@MaxLength(128)
|
|
name?: string;
|
|
|
|
@IsOptional()
|
|
@IsIn(['ONLINE_LINK', 'OFFLINE_PICKUP', 'PARTNER_CHANNEL', 'EVENT', 'OTHER'])
|
|
scene?: PromoCodeScene;
|
|
|
|
@IsOptional()
|
|
@IsString()
|
|
ownerUserId?: string | null;
|
|
|
|
@IsOptional()
|
|
@IsArray()
|
|
@IsString({ each: true })
|
|
channelOwnerPartnerIds?: string[];
|
|
|
|
@IsOptional()
|
|
@Transform(({ value }) => toOptionalNullableString(value))
|
|
@ValidateIf((_, v) => v !== null && v !== undefined)
|
|
@IsString()
|
|
assocPartnerAccountId?: string | null;
|
|
|
|
@IsOptional()
|
|
@IsString()
|
|
@MaxLength(256)
|
|
remark?: string | null;
|
|
}
|
|
|
|
export class UpdatePromoCodeStatusDto {
|
|
@IsIn(['ACTIVE', 'DISABLED'])
|
|
status: PromoCodeStatus;
|
|
}
|
|
|
|
export class PromoMetricTimelineQueryDto {
|
|
@IsString()
|
|
dateFrom: string;
|
|
|
|
@IsString()
|
|
dateTo: string;
|
|
|
|
@IsOptional()
|
|
@IsIn(['day', 'hour'])
|
|
granularity?: 'day' | 'hour';
|
|
}
|
|
|
|
export class PromoMetricEventsQueryDto {
|
|
@IsOptional()
|
|
@Type(() => Number)
|
|
page?: number;
|
|
|
|
@IsOptional()
|
|
@Type(() => Number)
|
|
pageSize?: number;
|
|
|
|
@IsOptional()
|
|
@IsIn(['SCAN', 'ATTRIBUTION', 'REGISTER', 'ORDER'])
|
|
eventType?: 'SCAN' | 'ATTRIBUTION' | 'REGISTER' | 'ORDER';
|
|
|
|
@IsOptional()
|
|
@IsString()
|
|
dateFrom?: string;
|
|
|
|
@IsOptional()
|
|
@IsString()
|
|
dateTo?: string;
|
|
}
|