File

apps/recallassess/recallassess-api/src/api/shared/email/dto/preview-email.dto.ts

Index

Properties

Properties

Optional recipientEmail
Type : string
Decorators :
@Expose()
@ApiProperty({description: 'Recipient email address (for testing only)', example: 'test@example.com', required: false})
@IsOptional()
@IsString()
import { ApiProperty } from "@nestjs/swagger";
import { IsNotEmpty, IsOptional, IsString, IsObject } from "class-validator";
import { Exclude, Expose, Transform } from "class-transformer";

@Exclude()
export class PreviewEmailDto {
  @Expose()
  @ApiProperty({
    description: "Email template key",
    example: "account.welcome.email",
  })
  @IsNotEmpty()
  @IsString()
  templateKey!: string;

  /**
   * Mail-merge variable map keyed by dotted names (e.g. "system.knowledgeReviewUrl",
   * "user.name"). The keys are dynamic, so we can't @Expose() each one individually.
   *
   * The global ValidationPipe is configured with `excludeExtraneousValues: true`,
   * which — combined with `@Exclude()` on this class and `@Expose()` on each
   * property — causes class-transformer to recurse into this Record and strip
   * every key inside it (since none of the dynamic keys have @Expose()). The
   * symptom was `dto.variables` arriving as an empty `{}` even though the raw
   * HTTP body contained all the keys.
   *
   * `@Transform(({ obj }) => obj.variables)` short-circuits that recursion by
   * returning the original plain object verbatim from the raw incoming body,
   * so every dotted key survives intact.
   */
  @Expose()
  @Transform(({ obj }) => obj.variables, { toClassOnly: true })
  @ApiProperty({
    description: "Variables to replace in template",
    example: { "user.name": "John Doe", "user.email": "john@example.com" },
    required: false,
  })
  @IsOptional()
  @IsObject()
  variables?: Record<string, string>;
}

@Exclude()
export class TestEmailDto extends PreviewEmailDto {
  @Expose()
  @ApiProperty({
    description: "Recipient email address (for testing only)",
    example: "test@example.com",
    required: false,
  })
  @IsOptional()
  @IsString()
  recipientEmail?: string;
}

@Exclude()
export class ScheduleConfigDto {
  @Expose()
  @ApiProperty({
    description: "Email type",
    example: "hundred_day_journey",
  })
  @IsNotEmpty()
  @IsString()
  emailType!: string;

  @Expose()
  @ApiProperty({
    description: "Template key",
    example: "course.hundred.day.journey.email1",
  })
  @IsNotEmpty()
  @IsString()
  templateKey!: string;

  @Expose()
  @ApiProperty({
    description: "Days after trigger event",
    example: 2,
  })
  @IsNotEmpty()
  daysAfterTrigger!: number;

  @Expose()
  @ApiProperty({
    description: "Send time (HH:mm format)",
    example: "09:00",
  })
  @IsNotEmpty()
  @IsString()
  sendTime!: string;

  @Expose()
  @ApiProperty({
    description: "Timezone type: participant, company, or system",
    example: "participant",
  })
  @IsNotEmpty()
  @IsString()
  timezoneType!: "participant" | "company" | "system";

  @Expose()
  @ApiProperty({
    description: "Whether this schedule is enabled",
    example: true,
    required: false,
  })
  @IsOptional()
  enabled?: boolean;

  @Expose()
  @ApiProperty({
    description: "Additional metadata for the schedule configuration",
    example: { customField: "value" },
    required: false,
  })
  @IsOptional()
  @IsObject()
  metadata?: Record<string, any>;
}

@Exclude()
export class SendNowDto {
  @Expose()
  @ApiProperty({
    description: "Email log ID to send immediately",
    example: 1,
  })
  @IsNotEmpty()
  emailLogId!: number;
}

results matching ""

    No results matching ""