2026-08-29 21:06:30 +03:30
|
|
|
import { Type } from 'class-transformer';
|
|
|
|
|
import {
|
2026-10-03 18:28:47 +03:30
|
|
|
Allow,
|
2026-09-26 14:59:48 +03:30
|
|
|
IsArray,
|
2026-09-05 02:04:39 +03:30
|
|
|
IsBoolean,
|
2026-08-29 21:06:30 +03:30
|
|
|
IsDateString,
|
|
|
|
|
IsIn,
|
|
|
|
|
IsInt,
|
|
|
|
|
IsOptional,
|
|
|
|
|
IsString,
|
|
|
|
|
Max,
|
|
|
|
|
MaxLength,
|
|
|
|
|
Min,
|
|
|
|
|
MinLength,
|
|
|
|
|
ValidateIf,
|
|
|
|
|
} from 'class-validator';
|
|
|
|
|
|
2026-10-03 18:28:47 +03:30
|
|
|
/** تکههای 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;
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-29 21:06:30 +03:30
|
|
|
const ACTIVITY_TYPES = ['call', 'meeting', 'task', 'note'] as const;
|
|
|
|
|
const ACTIVITY_STATUSES = ['open', 'done', 'canceled'] as const;
|
2026-09-02 21:29:00 +03:30
|
|
|
const ACTIVITY_PRIORITIES = ['very_low', 'low', 'medium', 'high', 'very_high'] as const;
|
2026-08-29 21:06:30 +03:30
|
|
|
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;
|
|
|
|
|
|
2026-09-28 12:28:14 +03:30
|
|
|
@IsOptional()
|
|
|
|
|
@IsIn(['mine', 'team'])
|
|
|
|
|
desk?: 'mine' | 'team';
|
|
|
|
|
|
2026-10-03 12:00:46 +03:30
|
|
|
@IsOptional()
|
|
|
|
|
@IsIn(ACTIVITY_TYPES)
|
|
|
|
|
type?: (typeof ACTIVITY_TYPES)[number];
|
|
|
|
|
|
|
|
|
|
@IsOptional()
|
|
|
|
|
@IsIn(ACTIVITY_STATUSES)
|
|
|
|
|
status?: (typeof ACTIVITY_STATUSES)[number];
|
|
|
|
|
|
|
|
|
|
@IsOptional()
|
|
|
|
|
@IsString()
|
|
|
|
|
assigneeId?: string;
|
|
|
|
|
|
2026-08-29 21:06:30 +03:30
|
|
|
@IsOptional()
|
|
|
|
|
@IsString()
|
|
|
|
|
personId?: string;
|
|
|
|
|
|
|
|
|
|
@IsOptional()
|
|
|
|
|
@IsString()
|
|
|
|
|
companyId?: string;
|
|
|
|
|
|
|
|
|
|
@IsOptional()
|
|
|
|
|
@IsString()
|
|
|
|
|
dealId?: 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class CreateActivityDto {
|
|
|
|
|
@IsString()
|
|
|
|
|
@MinLength(2)
|
|
|
|
|
@MaxLength(200)
|
|
|
|
|
title!: string;
|
|
|
|
|
|
|
|
|
|
@IsOptional()
|
|
|
|
|
@IsIn(ACTIVITY_TYPES)
|
|
|
|
|
type?: (typeof ACTIVITY_TYPES)[number];
|
|
|
|
|
|
2026-09-02 21:29:00 +03:30
|
|
|
@IsOptional()
|
|
|
|
|
@IsIn(ACTIVITY_PRIORITIES)
|
|
|
|
|
priority?: (typeof ACTIVITY_PRIORITIES)[number];
|
|
|
|
|
|
2026-08-29 21:06:30 +03:30
|
|
|
@IsOptional()
|
|
|
|
|
@IsString()
|
|
|
|
|
@MaxLength(2000)
|
|
|
|
|
description?: string;
|
|
|
|
|
|
|
|
|
|
@IsOptional()
|
|
|
|
|
@ValidateIf((_, v) => v !== '' && v != null)
|
|
|
|
|
@IsDateString()
|
|
|
|
|
dueAt?: string | null;
|
|
|
|
|
|
2026-09-02 21:29:00 +03:30
|
|
|
@IsOptional()
|
|
|
|
|
@Type(() => Number)
|
|
|
|
|
@IsInt()
|
|
|
|
|
@Min(1)
|
|
|
|
|
@Max(24 * 60)
|
|
|
|
|
durationMinutes?: number | null;
|
|
|
|
|
|
|
|
|
|
@IsOptional()
|
|
|
|
|
@ValidateIf((_, v) => v !== '' && v != null)
|
|
|
|
|
@IsDateString()
|
|
|
|
|
reminderAt?: string | null;
|
|
|
|
|
|
2026-09-05 02:04:39 +03:30
|
|
|
@IsOptional()
|
|
|
|
|
@IsBoolean()
|
|
|
|
|
reminderNotifyApp?: boolean;
|
|
|
|
|
|
|
|
|
|
@IsOptional()
|
|
|
|
|
@IsBoolean()
|
|
|
|
|
reminderNotifySms?: boolean;
|
|
|
|
|
|
2026-09-26 14:59:48 +03:30
|
|
|
@IsOptional()
|
|
|
|
|
@IsArray()
|
|
|
|
|
@IsString({ each: true })
|
|
|
|
|
tags?: string[];
|
|
|
|
|
|
2026-08-29 21:06:30 +03:30
|
|
|
@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()
|
|
|
|
|
assigneeId?: string | null;
|
2026-10-03 13:16:13 +03:30
|
|
|
|
|
|
|
|
@IsOptional()
|
|
|
|
|
@IsArray()
|
|
|
|
|
@IsString({ each: true })
|
|
|
|
|
assigneeIds?: string[];
|
2026-08-29 21:06:30 +03:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class UpdateActivityDto {
|
|
|
|
|
@IsOptional()
|
|
|
|
|
@IsString()
|
|
|
|
|
@MinLength(2)
|
|
|
|
|
@MaxLength(200)
|
|
|
|
|
title?: string;
|
|
|
|
|
|
|
|
|
|
@IsOptional()
|
|
|
|
|
@IsIn(ACTIVITY_TYPES)
|
|
|
|
|
type?: (typeof ACTIVITY_TYPES)[number];
|
|
|
|
|
|
|
|
|
|
@IsOptional()
|
|
|
|
|
@IsIn(ACTIVITY_STATUSES)
|
|
|
|
|
status?: (typeof ACTIVITY_STATUSES)[number];
|
|
|
|
|
|
2026-09-02 21:29:00 +03:30
|
|
|
@IsOptional()
|
|
|
|
|
@IsIn(ACTIVITY_PRIORITIES)
|
|
|
|
|
priority?: (typeof ACTIVITY_PRIORITIES)[number];
|
|
|
|
|
|
2026-08-29 21:06:30 +03:30
|
|
|
@IsOptional()
|
|
|
|
|
@IsString()
|
|
|
|
|
@MaxLength(2000)
|
|
|
|
|
description?: string | null;
|
|
|
|
|
|
|
|
|
|
@IsOptional()
|
|
|
|
|
@ValidateIf((_, v) => v !== '' && v != null)
|
|
|
|
|
@IsDateString()
|
|
|
|
|
dueAt?: string | null;
|
|
|
|
|
|
2026-09-02 21:29:00 +03:30
|
|
|
@IsOptional()
|
|
|
|
|
@Type(() => Number)
|
|
|
|
|
@IsInt()
|
|
|
|
|
@Min(1)
|
|
|
|
|
@Max(24 * 60)
|
|
|
|
|
durationMinutes?: number | null;
|
|
|
|
|
|
|
|
|
|
@IsOptional()
|
|
|
|
|
@ValidateIf((_, v) => v !== '' && v != null)
|
|
|
|
|
@IsDateString()
|
|
|
|
|
reminderAt?: string | null;
|
|
|
|
|
|
2026-09-05 02:04:39 +03:30
|
|
|
@IsOptional()
|
|
|
|
|
@IsBoolean()
|
|
|
|
|
reminderNotifyApp?: boolean;
|
|
|
|
|
|
|
|
|
|
@IsOptional()
|
|
|
|
|
@IsBoolean()
|
|
|
|
|
reminderNotifySms?: boolean;
|
|
|
|
|
|
2026-09-26 14:59:48 +03:30
|
|
|
@IsOptional()
|
|
|
|
|
@IsArray()
|
|
|
|
|
@IsString({ each: true })
|
|
|
|
|
tags?: string[];
|
|
|
|
|
|
2026-08-29 21:06:30 +03:30
|
|
|
@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()
|
|
|
|
|
assigneeId?: string | null;
|
2026-10-03 13:16:13 +03:30
|
|
|
|
|
|
|
|
@IsOptional()
|
|
|
|
|
@IsArray()
|
|
|
|
|
@IsString({ each: true })
|
|
|
|
|
assigneeIds?: string[];
|
2026-08-29 21:06:30 +03:30
|
|
|
}
|