496 lines
9.3 KiB
TypeScript
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';
|
|
}
|