import { IsEmail, IsIn, IsOptional, IsString, IsUUID, Matches, MaxLength } from "class-validator"; const TENANT_STATUSES = ["TRIAL", "ACTIVE", "SUSPENDED", "PAST_DUE", "CANCELLED"]; export class CreateTenantDto { @IsString() @MaxLength(40) @Matches(/^[a-z0-9-]+$/, { message: "code deve ser minusculo, so letras/numeros/hifen (vira tambem o slug)" }) code!: string; @IsString() @MaxLength(200) legalName!: string; @IsOptional() @IsString() @MaxLength(200) tradeName?: string; @IsOptional() @IsString() @MaxLength(40) taxId?: string; @IsUUID() planId!: string; /** Domínio SIP deste tenant (secao 178, docs/EXTENSIONS.md) — achado * real reportado pelo usuário: antes disto todo tenant nascia com o * mesmo domínio fixo ("b2bcall.local"), quebrando isolamento de PABX * (call groups, filas, IVR não conseguem distinguir um tenant do * outro). A tela sugere `{code}.b2bcall.net`, mas quem cria pode * digitar outro — só precisa ser único (constraint no banco) e ter * cara de domínio (não precisa resolver de verdade por DNS: o * telefone/softphone aponta pro IP do servidor via `proxy=`, este * campo só serve pra identificar o tenant no REGISTER). */ @IsString() @MaxLength(120) @Matches(/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+$/, { message: "telephonyDomain precisa ter formato de domínio (ex.: minhaempresa.b2bcall.net)", }) telephonyDomain!: string; /** Cria o primeiro usuário (tenant_admin) na mesma transação — sem essa * conta o tenant fica inacessível (secao 141: "Tenant Admin é criado * junto com o tenant"). Senha gerada e devolvida uma única vez, mesmo * padrão de `SecretReveal` já usado pra senha SIP de ramal. */ @IsEmail() adminEmail!: string; @IsString() @MaxLength(120) adminName!: string; } export class UpdateTenantDto { @IsOptional() @IsIn(TENANT_STATUSES) status?: string; @IsOptional() @IsUUID() planId?: string; @IsOptional() @IsString() @MaxLength(200) tradeName?: string; }