Files
CRM_Montzar/apps/api/src/activities/dto.ts
T

496 lines
9.3 KiB
TypeScript

import { Type } from 'class-transformer';
import {
Allow,
IsArray,
IsBoolean,
IsDateString,
IsIn,
IsInt,
IsObject,
IsOptional,
IsString,
Max,
MaxLength,
Min,
MinLength,
ValidateIf,
} from 'class-validator';
import type { ActivityFieldDef, ActivityFieldValues, ActivityTypeIcon } from '@mento/shared';
import { ACTIVITY_TYPE_ICONS } from '@mento/shared';
/** تکه‌های JSON از ایمپورت مرورگرگرا */
export class ImportActivityRowsDto {
@IsArray()
@Allow()
rows!: Array<Record<string, string>>;
@Type(() => Number)
@IsInt()
@Min(0)
offset!: number;
@Type(() => Number)
@IsInt()
@Min(0)
total!: number;
@IsOptional()
@IsString()
sessionId?: string;
}
const ACTIVITY_TYPES = ['call', 'meeting', 'task', 'note'] as const;
const ACTIVITY_STATUSES = ['open', 'done', 'canceled'] as const;
const ACTIVITY_PRIORITIES = ['very_low', 'low', 'medium', 'high', 'very_high'] as const;
const ACTIVITY_FILTERS = ['today', 'overdue', 'upcoming', 'done', 'all'] as const;
export class ListActivitiesQueryDto {
@IsOptional()
@IsIn(ACTIVITY_FILTERS)
filter?: (typeof ACTIVITY_FILTERS)[number] = 'today';
@IsOptional()
@IsString()
q?: string;
@IsOptional()
@IsIn(['mine', 'team'])
desk?: 'mine' | 'team';
@IsOptional()
@IsIn(ACTIVITY_TYPES)
type?: (typeof ACTIVITY_TYPES)[number];
@IsOptional()
@IsIn(ACTIVITY_STATUSES)
status?: (typeof ACTIVITY_STATUSES)[number];
@IsOptional()
@IsString()
assigneeId?: string;
/** فیلتر عنوان فعالیت، جدا از جستجوی کلی */
@IsOptional()
@IsString()
@MaxLength(120)
title?: string;
/** نام شخص یا شرکتِ مشتری */
@IsOptional()
@IsString()
@MaxLength(120)
customer?: string;
/** زمان شروع: set = دارد، unset = ندارد */
@IsOptional()
@IsIn(['set', 'unset'])
due?: 'set' | 'unset';
/** نوع فعالیت (تعریف‌شده در سازمان) */
@IsOptional()
@IsString()
typeDefId?: string;
/** شناسهٔ مرحله یا 'all' — حالت تب/کانبان مراحل */
@IsOptional()
@IsString()
stageId?: string;
/** گروه فعالیت؛ خالی = همهٔ گروه‌ها (در شمارش ستون‌ها = گروه پیش‌فرض) */
@IsOptional()
@IsString()
boardId?: string;
@IsOptional()
@IsString()
personId?: string;
@IsOptional()
@IsString()
companyId?: string;
@IsOptional()
@IsString()
dealId?: string;
@IsOptional()
@IsString()
leadId?: string;
/** Inclusive start (ISO). When set with/without filter, restricts dueAt. */
@IsOptional()
@IsDateString()
from?: string;
/** Exclusive end (ISO). */
@IsOptional()
@IsDateString()
to?: string;
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
page?: number = 1;
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
@Max(200)
limit?: number = 50;
}
const STAGE_COLORS = ['green', 'orange', 'purple', 'blue', 'rose', 'slate'] as const;
export class CreateActivityBoardDto {
@IsString()
@MinLength(2)
@MaxLength(80)
name!: string;
@IsOptional()
@IsArray()
@IsString({ each: true })
memberIds?: string[];
}
export class UpdateActivityBoardDto {
@IsOptional()
@IsString()
@MinLength(2)
@MaxLength(80)
name?: string;
@IsOptional()
@IsArray()
@IsString({ each: true })
memberIds?: string[];
}
export class ListActivityStagesQueryDto {
@IsOptional()
@IsString()
boardId?: string;
}
export class CreateActivityStageDto {
/** خالی = گروه پیش‌فرض */
@IsOptional()
@IsString()
boardId?: string;
@IsString()
@MinLength(1)
@MaxLength(80)
name!: string;
@IsOptional()
@IsIn(STAGE_COLORS)
color?: (typeof STAGE_COLORS)[number];
@IsOptional()
@IsIn(ACTIVITY_STATUSES)
kind?: (typeof ACTIVITY_STATUSES)[number];
}
export class UpdateActivityStageDto {
@IsOptional()
@IsString()
@MinLength(1)
@MaxLength(80)
name?: string;
@IsOptional()
@IsIn(STAGE_COLORS)
color?: (typeof STAGE_COLORS)[number];
@IsOptional()
@IsIn(ACTIVITY_STATUSES)
kind?: (typeof ACTIVITY_STATUSES)[number];
}
export class ReorderActivityStagesDto {
@IsArray()
@IsString({ each: true })
stageIds!: string[];
}
export class MoveActivityStageDto {
@IsString()
stageId!: string;
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(0)
position?: number;
}
/** محتوای fields در سرویس بر اساس تعریف نوع اعتبارسنجی می‌شود */
export class CreateActivityTypeDto {
@IsString()
@MinLength(1)
@MaxLength(60)
name!: string;
@IsOptional()
@IsIn(ACTIVITY_TYPES)
baseType?: (typeof ACTIVITY_TYPES)[number];
@IsOptional()
@IsIn(ACTIVITY_TYPE_ICONS)
icon?: ActivityTypeIcon;
@IsOptional()
@IsIn(STAGE_COLORS)
color?: (typeof STAGE_COLORS)[number];
@IsOptional()
@IsArray()
@Allow()
fields?: ActivityFieldDef[];
}
export class UpdateActivityTypeDto {
@IsOptional()
@IsString()
@MinLength(1)
@MaxLength(60)
name?: string;
@IsOptional()
@IsIn(ACTIVITY_TYPES)
baseType?: (typeof ACTIVITY_TYPES)[number];
@IsOptional()
@IsIn(ACTIVITY_TYPE_ICONS)
icon?: ActivityTypeIcon;
@IsOptional()
@IsIn(STAGE_COLORS)
color?: (typeof STAGE_COLORS)[number];
@IsOptional()
@IsArray()
@Allow()
fields?: ActivityFieldDef[];
@IsOptional()
@IsBoolean()
isActive?: boolean;
}
export class ReorderActivityTypesDto {
@IsArray()
@IsString({ each: true })
typeIds!: string[];
}
export class CreateActivityDto {
@IsString()
@MinLength(2)
@MaxLength(200)
title!: string;
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsString()
boardId?: string | null;
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsString()
stageId?: string | null;
@IsOptional()
@IsIn(ACTIVITY_TYPES)
type?: (typeof ACTIVITY_TYPES)[number];
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsString()
typeDefId?: string | null;
@IsOptional()
@IsObject()
fields?: ActivityFieldValues;
@IsOptional()
@IsIn(ACTIVITY_PRIORITIES)
priority?: (typeof ACTIVITY_PRIORITIES)[number];
@IsOptional()
@IsString()
@MaxLength(20000)
description?: string;
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsDateString()
dueAt?: string | null;
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
@Max(24 * 60)
durationMinutes?: number | null;
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsDateString()
reminderAt?: string | null;
@IsOptional()
@IsBoolean()
reminderNotifyApp?: boolean;
@IsOptional()
@IsBoolean()
reminderNotifySms?: boolean;
@IsOptional()
@IsArray()
@IsString({ each: true })
tags?: string[];
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsString()
personId?: string | null;
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsString()
companyId?: string | null;
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsString()
dealId?: string | null;
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsString()
leadId?: string | null;
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsString()
assigneeId?: string | null;
@IsOptional()
@IsArray()
@IsString({ each: true })
assigneeIds?: string[];
@IsOptional()
@IsIn(['any', 'all'])
completionMode?: 'any' | 'all';
}
export class UpdateActivityDto {
@IsOptional()
@IsString()
@MinLength(2)
@MaxLength(200)
title?: string;
/** null/خالی = گروه پیش‌فرض */
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsString()
boardId?: string | null;
@IsOptional()
@IsIn(ACTIVITY_TYPES)
type?: (typeof ACTIVITY_TYPES)[number];
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsString()
typeDefId?: string | null;
@IsOptional()
@IsObject()
fields?: ActivityFieldValues;
@IsOptional()
@IsIn(ACTIVITY_STATUSES)
status?: (typeof ACTIVITY_STATUSES)[number];
@IsOptional()
@IsIn(ACTIVITY_PRIORITIES)
priority?: (typeof ACTIVITY_PRIORITIES)[number];
@IsOptional()
@IsString()
@MaxLength(20000)
description?: string | null;
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsDateString()
dueAt?: string | null;
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
@Max(24 * 60)
durationMinutes?: number | null;
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsDateString()
reminderAt?: string | null;
@IsOptional()
@IsBoolean()
reminderNotifyApp?: boolean;
@IsOptional()
@IsBoolean()
reminderNotifySms?: boolean;
@IsOptional()
@IsArray()
@IsString({ each: true })
tags?: string[];
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsString()
personId?: string | null;
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsString()
companyId?: string | null;
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsString()
dealId?: string | null;
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsString()
leadId?: string | null;
@IsOptional()
@ValidateIf((_, v) => v !== '' && v != null)
@IsString()
assigneeId?: string | null;
@IsOptional()
@IsArray()
@IsString({ each: true })
assigneeIds?: string[];
@IsOptional()
@IsIn(['any', 'all'])
completionMode?: 'any' | 'all';
}