Files
CRM_Montzar/apps/api/src/users/dto.ts
T
MahdiandCursor 1ccbefa7a3 fix(treasury): scope finance access and hide it when the module is off
Accounts can be edited, including the opening balance, and finance sections and accounts can be granted on a role or on one user. The finance menu stays hidden when the organization module is disabled.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-04 10:02:31 +03:30

138 lines
2.9 KiB
TypeScript

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<string, 'own' | 'team' | 'org' | null>;
}
export class UpdateUserDataAccessDto {
/**
* null = پاک کردن override و ارث از نقش.
* آبجکت = جایگزینی کامل override.
*/
@ValidateIf((_, v) => v !== null)
@IsOptional()
@IsObject()
dataAccessOverride?: Record<string, unknown> | null;
/** null = ارث از نقش */
@ValidateIf((_, v) => v !== null)
@IsOptional()
@IsObject()
treasuryAccessOverride?: Record<string, unknown> | null;
}