import { Type } from 'class-transformer'; import { IsBoolean, IsIn, IsNumber, IsObject, IsOptional, IsString, Matches, Max, MaxLength, Min, MinLength, ValidateIf, } from 'class-validator'; const INVITE_ROLES = ['admin', 'sales', 'support'] as const; const ALL_ROLES = ['owner', 'admin', 'sales', 'support'] as const; export class InviteUserDto { @IsString() @Matches(/^09\d{9}$|^\+98\d{10}$|^98\d{10}$|^9\d{9}$/, { message: 'شماره موبایل معتبر نیست', }) mobile!: string; @IsString() @MinLength(2) @MaxLength(120) fullName!: string; @IsOptional() @ValidateIf((_, value) => typeof value === 'string' && value.length > 0) @IsString() @MinLength(8) @MaxLength(72) password?: string; @IsOptional() @IsIn(INVITE_ROLES) role?: (typeof INVITE_ROLES)[number]; @IsOptional() @IsString() orgRoleId?: string; } export class UpdateOrgUserDto { @IsString() @MinLength(2) @MaxLength(120) fullName!: string; @IsString() @Matches(/^09\d{9}$|^\+98\d{10}$|^98\d{10}$|^9\d{9}$/, { message: 'شماره موبایل معتبر نیست', }) mobile!: string; @IsOptional() @ValidateIf((_, value) => typeof value === 'string' && value.length > 0) @IsString() @MinLength(8) @MaxLength(72) password?: string; } export class UpdateUserRoleDto { @IsOptional() @IsIn(ALL_ROLES) role?: (typeof ALL_ROLES)[number]; @IsOptional() @IsString() orgRoleId?: string; } export class UpdateUserStatusDto { @Type(() => Boolean) @IsBoolean() isActive!: boolean; } export class UpdateUserLoginOtpOnlyDto { @Type(() => Boolean) @IsBoolean() loginOtpOnly!: boolean; } export class UpdateUserCommissionDto { @Type(() => Number) @IsNumber() @Min(0) @Max(100) commissionPercent!: number; } export class UpdateLogoutTimeDto { @IsOptional() @ValidateIf((_, value) => value != null && value !== '') @IsString() @Matches(/^([01]\d|2[0-3]):[0-5]\d$/, { message: 'ساعت خروج معتبر نیست' }) logoutTime?: string | null; /** بدون مقدار = بدون تغییر */ @IsOptional() @IsBoolean() blockLoginAfterLogout?: boolean; } export class UpdateUserVisibilityDto { @IsOptional() @IsIn(['own', 'team', 'org']) dataVisibility?: 'own' | 'team' | 'org'; /** سطح دید هر بخش؛ null یعنی «مثل پیش‌فرض». در سرویس اعتبارسنجی می‌شود. */ @IsOptional() @IsObject() scopes?: Record; } export class UpdateUserDataAccessDto { /** * null = پاک کردن override و ارث از نقش. * آبجکت = جایگزینی کامل override. */ @ValidateIf((_, v) => v !== null) @IsOptional() @IsObject() dataAccessOverride?: Record | null; /** null = ارث از نقش */ @ValidateIf((_, v) => v !== null) @IsOptional() @IsObject() treasuryAccessOverride?: Record | null; }