Files
CRM_Montzar/packages/shared/src/index.ts
T

1364 lines
30 KiB
TypeScript
Raw Normal View History

export type UserRole = "owner" | "admin" | "sales" | "support";
export const USER_ROLES: UserRole[] = ["owner", "admin", "sales", "support"];
export const USER_ROLE_LABELS: Record<UserRole, string> = {
owner: "مالک",
admin: "مدیر",
sales: "فروش",
support: "پشتیبانی",
};
/** تنظیمات سازمانی و مدیریت کاربران */
export function canManageSettings(role: UserRole | string | null | undefined): boolean {
return role === "owner" || role === "admin";
}
export function canManageUsers(role: UserRole | string | null | undefined): boolean {
return role === "owner" || role === "admin";
}
/** مشاهده همه پرونده‌های سازمان (نه فقط مالکیت خود) */
export function canViewAllRecords(role: UserRole | string | null | undefined): boolean {
return role === "owner" || role === "admin";
}
/** تغییر مالک پرونده */
export function canReassignRecords(role: UserRole | string | null | undefined): boolean {
return role === "owner" || role === "admin";
}
export interface AuthUserDto {
id: string;
email: string;
fullName: string;
role: UserRole;
organizationId: string;
}
export interface OrgUserDto {
id: string;
email: string;
fullName: string;
role: UserRole;
createdAt: string;
}
export interface InviteUserRequest {
email: string;
fullName: string;
password: string;
role: Exclude<UserRole, "owner">;
}
export interface UpdateUserRoleRequest {
role: UserRole;
}
export type DealStatus = "open" | "won" | "lost";
export interface ApiErrorBody {
statusCode: number;
message: string | string[];
error?: string;
}
export interface LoginRequest {
email: string;
password: string;
}
export interface LoginResponse {
accessToken: string;
user: AuthUserDto;
}
export interface OrganizationDto {
id: string;
name: string;
slug: string;
baseCurrency: string;
enabledCurrencies: string[];
exchangeRates: ExchangeRateDto[];
}
export interface ExchangeRateDto {
currency: string;
rateToBase: number;
updatedAt: string;
}
export interface UpdateOrgCurrenciesRequest {
baseCurrency?: string;
enabledCurrencies?: string[];
/** نرخ‌ها نسبت به ارز پایه؛ ارز پایه نیازی به نرخ ندارد */
rates?: Array<{ currency: string; rateToBase: number }>;
}
export const CURRENCY_CATALOG: Array<{
code: string;
labelFa: string;
suffix: string;
}> = [
{ code: "IRR", labelFa: "ریال ایران", suffix: "ریال" },
{ code: "USD", labelFa: "دلار آمریکا", suffix: "دلار" },
{ code: "EUR", labelFa: "یورو", suffix: "یورو" },
{ code: "AED", labelFa: "درهم امارات", suffix: "درهم" },
{ code: "TRY", labelFa: "لیر ترکیه", suffix: "لیر" },
{ code: "GBP", labelFa: "پوند انگلیس", suffix: "پوند" },
];
export function currencySuffix(code: string): string {
return CURRENCY_CATALOG.find((c) => c.code === code)?.suffix ?? code;
}
export function formatMoneyAmount(amount: number, currency = "IRR"): string {
try {
const n = new Intl.NumberFormat("fa-IR").format(amount);
return `${n} ${currencySuffix(currency)}`;
} catch {
return `${amount} ${currency}`;
}
}
export interface HealthResponse {
status: "ok";
service: string;
timestamp: string;
}
export interface CompanySummaryDto {
id: string;
name: string;
}
export interface CompanyDto {
id: string;
name: string;
nationalId: string | null;
phone: string | null;
email: string | null;
website: string | null;
address: string | null;
notes: string | null;
customFields: Record<string, unknown>;
peopleCount: number;
owner: UserSummaryDto | null;
createdAt: string;
updatedAt: string;
}
export interface CreateCompanyRequest {
name: string;
nationalId?: string;
phone?: string;
email?: string;
website?: string;
address?: string;
notes?: string;
customFields?: Record<string, unknown>;
ownerId?: string | null;
}
export type UpdateCompanyRequest = Partial<CreateCompanyRequest>;
export interface LoyaltyTierSummaryDto {
id: string;
name: string;
minPoints: number;
color: string | null;
}
export interface PersonDto {
id: string;
firstName: string;
lastName: string;
fullName: string;
email: string | null;
phone: string | null;
mobile: string | null;
position: string | null;
notes: string | null;
customFields: Record<string, unknown>;
loyaltyPoints: number;
loyaltyTier: LoyaltyTierSummaryDto | null;
company: CompanySummaryDto | null;
owner: UserSummaryDto | null;
createdAt: string;
updatedAt: string;
}
export interface CreatePersonRequest {
firstName: string;
lastName: string;
email?: string;
phone?: string;
mobile?: string;
position?: string;
notes?: string;
companyId?: string | null;
customFields?: Record<string, unknown>;
ownerId?: string | null;
}
export type UpdatePersonRequest = Partial<CreatePersonRequest>;
export interface PaginatedResponse<T> {
items: T[];
total: number;
page: number;
limit: number;
}
export interface PersonSummaryDto {
id: string;
fullName: string;
}
export interface UserSummaryDto {
id: string;
fullName: string;
}
export interface PipelineStageDto {
id: string;
name: string;
position: number;
isWon: boolean;
isLost: boolean;
}
export interface PipelineDto {
id: string;
name: string;
isDefault: boolean;
stages: PipelineStageDto[];
}
export interface DealDto {
id: string;
title: string;
amount: number | null;
currency: string;
status: DealStatus;
source: string | null;
lostReason: string | null;
notes: string | null;
tags: string[];
isStale: boolean;
isRotten: boolean;
customFields: Record<string, unknown>;
expectedCloseAt: string | null;
position: number;
pipelineId: string;
stageId: string;
person: PersonSummaryDto | null;
company: CompanySummaryDto | null;
owner: UserSummaryDto | null;
lineItems: DealLineItemDto[];
createdAt: string;
updatedAt: string;
}
export interface PipelineBoardStageDto extends PipelineStageDto {
deals: DealDto[];
totalAmount: number;
}
export interface PipelineBoardDto {
pipeline: PipelineDto;
stages: PipelineBoardStageDto[];
}
export interface CreatePipelineRequest {
name: string;
}
export interface CreateDealRequest {
title: string;
pipelineId?: string;
stageId?: string;
amount?: number | null;
currency?: string;
source?: string;
notes?: string;
tags?: string[];
isStale?: boolean;
isRotten?: boolean;
expectedCloseAt?: string | null;
personId?: string | null;
companyId?: string | null;
ownerId?: string | null;
customFields?: Record<string, unknown>;
lineItems?: DealLineItemInput[];
}
export interface UpdateDealRequest {
title?: string;
amount?: number | null;
currency?: string;
source?: string;
notes?: string;
tags?: string[];
isStale?: boolean;
isRotten?: boolean;
lostReason?: string | null;
expectedCloseAt?: string | null;
personId?: string | null;
companyId?: string | null;
ownerId?: string | null;
customFields?: Record<string, unknown>;
lineItems?: DealLineItemInput[];
}
export interface MoveDealRequest {
stageId: string;
position?: number;
}
export type ActivityType = "call" | "meeting" | "task" | "note";
export type ActivityStatus = "open" | "done" | "canceled";
export type ActivityPriority = "very_low" | "low" | "medium" | "high" | "very_high";
export type ActivityFilter = "today" | "overdue" | "upcoming" | "done" | "all";
export type CustomFieldEntity = "person" | "company" | "deal";
export type CustomFieldType = "text" | "number" | "date" | "boolean" | "select";
export interface CustomFieldDefinitionDto {
id: string;
entityType: CustomFieldEntity;
key: string;
label: string;
fieldType: CustomFieldType;
options: string[];
required: boolean;
position: number;
isActive: boolean;
createdAt: string;
updatedAt: string;
}
export interface CreateCustomFieldRequest {
entityType: CustomFieldEntity;
label: string;
key?: string;
fieldType?: CustomFieldType;
options?: string[];
required?: boolean;
position?: number;
isActive?: boolean;
}
export interface UpdateCustomFieldRequest {
label?: string;
fieldType?: CustomFieldType;
options?: string[];
required?: boolean;
position?: number;
isActive?: boolean;
}
export interface DealSummaryDto {
id: string;
title: string;
}
export interface ActivityDto {
id: string;
type: ActivityType;
status: ActivityStatus;
priority: ActivityPriority;
title: string;
description: string | null;
dueAt: string | null;
durationMinutes: number | null;
reminderAt: string | null;
completedAt: string | null;
person: PersonSummaryDto | null;
company: CompanySummaryDto | null;
deal: DealSummaryDto | null;
assignee: UserSummaryDto | null;
createdBy: UserSummaryDto | null;
createdAt: string;
updatedAt: string;
}
export interface CreateActivityRequest {
title: string;
type?: ActivityType;
priority?: ActivityPriority;
description?: string;
dueAt?: string | null;
durationMinutes?: number | null;
reminderAt?: string | null;
personId?: string | null;
companyId?: string | null;
dealId?: string | null;
assigneeId?: string | null;
}
export interface UpdateActivityRequest {
title?: string;
type?: ActivityType;
status?: ActivityStatus;
priority?: ActivityPriority;
description?: string | null;
dueAt?: string | null;
durationMinutes?: number | null;
reminderAt?: string | null;
personId?: string | null;
companyId?: string | null;
dealId?: string | null;
assigneeId?: string | null;
}
export interface ActivitySummaryDto {
today: ActivityDto[];
overdue: ActivityDto[];
upcoming: ActivityDto[];
todayCount: number;
overdueCount: number;
}
export type NoteType =
| "general"
| "call_result"
| "meeting"
| "important"
| "warning"
| "next_action";
export interface NoteAttachmentDto {
id: string;
fileName: string;
mimeType: string;
sizeBytes: number;
createdAt: string;
}
export interface NoteDto {
id: string;
title: string | null;
body: string;
noteType: NoteType | string;
pinned: boolean;
color: string | null;
tags: string[];
reminderAt: string | null;
person: PersonSummaryDto | null;
company: CompanySummaryDto | null;
deal: DealSummaryDto | null;
author: UserSummaryDto | null;
attachments: NoteAttachmentDto[];
createdAt: string;
updatedAt: string;
}
export interface CreateNoteRequest {
title?: string;
body: string;
noteType?: NoteType | string;
pinned?: boolean;
color?: string;
tags?: string[];
reminderAt?: string | null;
personId?: string | null;
companyId?: string | null;
dealId?: string | null;
}
export interface UpdateNoteRequest {
title?: string | null;
body?: string;
noteType?: NoteType | string;
pinned?: boolean;
color?: string | null;
tags?: string[];
reminderAt?: string | null;
personId?: string | null;
companyId?: string | null;
dealId?: string | null;
}
export type NoteAiSuggestionStatus =
| 'pending'
| 'applied'
| 'dismissed'
| 'failed';
export type MemorySourceType = 'note' | 'manual';
export interface NoteAiNextActionDto {
title: string;
description?: string;
dueAt?: string | null;
}
export interface NoteAiMemoryExtractDto {
content: string;
category?: string;
}
export interface NoteAiPayloadDto {
nextAction: NoteAiNextActionDto | null;
memoryItems: NoteAiMemoryExtractDto[];
summary?: string;
}
export interface NoteAiSuggestionDto {
id: string;
noteId: string;
status: NoteAiSuggestionStatus;
payload: NoteAiPayloadDto | null;
errorMessage: string | null;
analyzedAt: string | null;
createdAt: string;
updatedAt: string;
}
export interface ApplyNoteAiSuggestionRequest {
applyNextAction?: boolean;
memoryIndices?: number[];
nextAction?: NoteAiNextActionDto;
memoryItems?: Array<{ index: number; content: string }>;
}
export interface MemoryItemDto {
id: string;
personId: string;
content: string;
sourceType: MemorySourceType;
sourceId: string | null;
confirmedBy: UserSummaryDto | null;
createdAt: string;
updatedAt: string;
}
export interface CreateMemoryItemRequest {
personId: string;
content: string;
}
export interface UpdateMemoryItemRequest {
content: string;
}
export interface ImportContactsResult {
created: number;
skipped: number;
errors: Array<{ row: number; message: string }>;
}
export interface ProductDto {
id: string;
name: string;
sku: string | null;
description: string | null;
unitPrice: number | null;
currency: string;
isActive: boolean;
createdAt: string;
updatedAt: string;
}
export interface CreateProductRequest {
name: string;
sku?: string;
description?: string;
unitPrice?: number | null;
currency?: string;
isActive?: boolean;
}
export interface UpdateProductRequest {
name?: string;
sku?: string | null;
description?: string | null;
unitPrice?: number | null;
currency?: string;
isActive?: boolean;
}
export interface DealLineItemDto {
id: string;
productId: string | null;
name: string;
quantity: number;
unitPrice: number;
currency: string;
position: number;
lineTotal: number;
}
export interface DealLineItemInput {
productId?: string | null;
name: string;
quantity: number;
unitPrice: number;
currency?: string;
}
export type NotificationType =
| "activity_assigned"
| "activity_overdue"
| "deal_moved"
| "note_reminder"
| "ticket_assigned"
| "automation"
| "system";
export interface NotificationDto {
id: string;
type: NotificationType | string;
title: string;
body: string | null;
link: string | null;
entityType: string | null;
entityId: string | null;
readAt: string | null;
createdAt: string;
}
export interface NotificationsListDto {
items: NotificationDto[];
unreadCount: number;
}
export type LeadFormFieldType = "text" | "email" | "phone" | "textarea";
export type LeadFormMapTo =
| "person.firstName"
| "person.lastName"
| "person.email"
| "person.mobile"
| "person.phone"
| "person.position"
| "deal.title"
| "deal.notes"
| "notes";
export interface LeadFormFieldDto {
id: string;
key: string;
label: string;
fieldType: LeadFormFieldType | string;
required: boolean;
mapTo: LeadFormMapTo | string;
position: number;
}
export interface LeadFormDto {
id: string;
name: string;
publicToken: string;
isActive: boolean;
createPerson: boolean;
createDeal: boolean;
pipelineId: string | null;
source: string | null;
thankYouMessage: string | null;
redirectUrl: string | null;
assigneeIds: string[];
fields: LeadFormFieldDto[];
publicPath: string;
createdAt: string;
updatedAt: string;
}
export interface LeadFormFieldInput {
key?: string;
label: string;
fieldType: LeadFormFieldType | string;
required?: boolean;
mapTo: LeadFormMapTo | string;
position?: number;
}
export interface CreateLeadFormRequest {
name: string;
createPerson?: boolean;
createDeal?: boolean;
pipelineId?: string | null;
source?: string | null;
thankYouMessage?: string | null;
redirectUrl?: string | null;
assigneeIds?: string[];
fields?: LeadFormFieldInput[];
}
export interface UpdateLeadFormRequest {
name?: string;
isActive?: boolean;
createPerson?: boolean;
createDeal?: boolean;
pipelineId?: string | null;
source?: string | null;
thankYouMessage?: string | null;
redirectUrl?: string | null;
assigneeIds?: string[];
fields?: LeadFormFieldInput[];
}
export interface PublicLeadFormDto {
name: string;
thankYouMessage: string | null;
fields: Array<{
key: string;
label: string;
fieldType: LeadFormFieldType | string;
required: boolean;
}>;
}
export interface SubmitLeadFormRequest {
values: Record<string, string>;
}
export interface SubmitLeadFormResponse {
ok: true;
thankYouMessage: string | null;
redirectUrl: string | null;
}
export type QuoteStatus =
| "draft"
| "sent"
| "accepted"
| "rejected"
| "expired";
export interface QuoteLineItemDto {
id: string;
productId: string | null;
name: string;
quantity: number;
unitPrice: number;
currency: string;
position: number;
lineTotal: number;
}
export interface QuoteDto {
id: string;
number: string;
title: string;
status: QuoteStatus | string;
currency: string;
notes: string | null;
validUntil: string | null;
totalAmount: number;
person: PersonSummaryDto | null;
company: CompanySummaryDto | null;
deal: DealSummaryDto | null;
owner: UserSummaryDto | null;
lineItems: QuoteLineItemDto[];
createdAt: string;
updatedAt: string;
}
export interface CreateQuoteRequest {
title: string;
status?: QuoteStatus | string;
currency?: string;
notes?: string;
validUntil?: string | null;
personId?: string | null;
companyId?: string | null;
dealId?: string | null;
fromDealId?: string | null;
lineItems?: DealLineItemInput[];
}
export interface UpdateQuoteRequest {
title?: string;
status?: QuoteStatus | string;
currency?: string;
notes?: string | null;
validUntil?: string | null;
personId?: string | null;
companyId?: string | null;
dealId?: string | null;
lineItems?: DealLineItemInput[];
}
export type InvoiceStatus =
| "draft"
| "issued"
| "partially_paid"
| "paid"
| "canceled";
export type PaymentMethod =
| "cash"
| "transfer"
| "card"
| "check"
| "other";
export type InstallmentStatus = "pending" | "paid" | "canceled";
export interface InvoiceLineItemDto {
id: string;
productId: string | null;
name: string;
quantity: number;
unitPrice: number;
currency: string;
position: number;
lineTotal: number;
}
export interface PaymentDto {
id: string;
amount: number;
currency: string;
method: PaymentMethod | string;
paidAt: string;
notes: string | null;
installmentId: string | null;
createdAt: string;
}
export interface InvoiceInstallmentDto {
id: string;
position: number;
dueDate: string;
amount: number;
currency: string;
status: InstallmentStatus | string;
paidAt: string | null;
paymentId: string | null;
}
export interface InvoiceDto {
id: string;
number: string;
title: string;
status: InvoiceStatus | string;
currency: string;
notes: string | null;
issuedAt: string | null;
dueDate: string | null;
totalAmount: number;
paidAmount: number;
remainingAmount: number;
person: PersonSummaryDto | null;
company: CompanySummaryDto | null;
deal: DealSummaryDto | null;
quote: { id: string; number: string; title: string } | null;
owner: UserSummaryDto | null;
lineItems: InvoiceLineItemDto[];
payments: PaymentDto[];
installments: InvoiceInstallmentDto[];
createdAt: string;
updatedAt: string;
}
export interface InvoiceInstallmentInput {
dueDate: string;
amount: number;
currency?: string;
}
export interface CreateInvoiceRequest {
title: string;
status?: InvoiceStatus | string;
currency?: string;
notes?: string;
issuedAt?: string | null;
dueDate?: string | null;
personId?: string | null;
companyId?: string | null;
dealId?: string | null;
quoteId?: string | null;
fromDealId?: string | null;
fromQuoteId?: string | null;
lineItems?: DealLineItemInput[];
installments?: InvoiceInstallmentInput[];
}
export interface UpdateInvoiceRequest {
title?: string;
status?: InvoiceStatus | string;
currency?: string;
notes?: string | null;
issuedAt?: string | null;
dueDate?: string | null;
personId?: string | null;
companyId?: string | null;
dealId?: string | null;
quoteId?: string | null;
lineItems?: DealLineItemInput[];
installments?: InvoiceInstallmentInput[];
}
export interface CreatePaymentRequest {
amount: number;
currency?: string;
method?: PaymentMethod | string;
paidAt?: string;
notes?: string;
installmentId?: string | null;
}
export interface SalesGoalDto {
id: string;
title: string;
periodStart: string;
periodEnd: string;
targetAmount: number;
currency: string;
notes: string | null;
user: UserSummaryDto | null;
createdAt: string;
updatedAt: string;
}
export interface CreateSalesGoalRequest {
title: string;
periodStart: string;
periodEnd: string;
targetAmount: number;
currency?: string;
notes?: string;
/** فقط مالک/مدیر؛ در غیر این صورت هدف برای خود کاربر */
userId?: string | null;
}
export interface UpdateSalesGoalRequest {
title?: string;
periodStart?: string;
periodEnd?: string;
targetAmount?: number;
currency?: string;
notes?: string | null;
userId?: string | null;
}
export interface SalesForecastDto {
periodStart: string;
periodEnd: string;
currency: string;
/** مجموع اهداف هم‌پوشان با بازه */
targetAmount: number;
/** معاملات برنده‌شده در بازه */
wonAmount: number;
/** معاملات باز فعلی */
openPipelineAmount: number;
/** پیش‌بینی ساده: تحقق + ۴۰٪ کاریز باز */
forecastAmount: number;
progressPercent: number | null;
openDealsCount: number;
wonDealsCount: number;
goals: SalesGoalDto[];
}
export type TicketStatus =
| "open"
| "in_progress"
| "waiting"
| "resolved"
| "closed";
export type TicketPriority = "low" | "normal" | "high" | "urgent";
export interface TicketMessageDto {
id: string;
body: string;
isInternal: boolean;
author: UserSummaryDto | null;
createdAt: string;
}
export interface TicketDto {
id: string;
number: string;
subject: string;
description: string | null;
status: TicketStatus | string;
priority: TicketPriority | string;
person: PersonSummaryDto | null;
company: CompanySummaryDto | null;
deal: DealSummaryDto | null;
assignee: UserSummaryDto | null;
reporter: UserSummaryDto | null;
resolvedAt: string | null;
slaDueAt: string | null;
firstRespondedAt: string | null;
slaBreached: boolean;
csatScore: number | null;
csatComment: string | null;
csatAt: string | null;
messages: TicketMessageDto[];
createdAt: string;
updatedAt: string;
}
export interface CreateTicketRequest {
subject: string;
description?: string;
status?: TicketStatus | string;
priority?: TicketPriority | string;
personId?: string | null;
companyId?: string | null;
dealId?: string | null;
assigneeId?: string | null;
}
export interface UpdateTicketRequest {
subject?: string;
description?: string | null;
status?: TicketStatus | string;
priority?: TicketPriority | string;
personId?: string | null;
companyId?: string | null;
dealId?: string | null;
assigneeId?: string | null;
csatScore?: number | null;
csatComment?: string | null;
}
export interface CreateTicketMessageRequest {
body: string;
isInternal?: boolean;
}
export interface FaqArticleDto {
id: string;
question: string;
answer: string;
category: string | null;
isPublished: boolean;
position: number;
createdAt: string;
updatedAt: string;
}
export interface CreateFaqArticleRequest {
question: string;
answer: string;
category?: string;
isPublished?: boolean;
position?: number;
}
export interface UpdateFaqArticleRequest {
question?: string;
answer?: string;
category?: string | null;
isPublished?: boolean;
position?: number;
}
/** ساعات مهلت پاسخ اول بر اساس اولویت */
export const TICKET_SLA_HOURS: Record<TicketPriority, number> = {
urgent: 4,
high: 8,
normal: 24,
low: 48,
};
/* ——— پرتال مشتری (OTP) ——— */
export interface PortalOrgInfoDto {
name: string;
slug: string;
}
export interface PortalRequestOtpRequest {
mobile: string;
}
export interface PortalRequestOtpResponse {
ok: true;
/** فقط در حالت توسعه / دمو وقتی SMS واقعی وصل نیست */
devCode?: string;
expiresInSeconds: number;
}
export interface PortalVerifyOtpRequest {
mobile: string;
code: string;
}
export interface PortalPersonDto {
id: string;
fullName: string;
mobile: string | null;
}
export interface PortalLoginResponse {
accessToken: string;
person: PortalPersonDto;
organization: PortalOrgInfoDto;
}
export interface PortalCreateTicketRequest {
subject: string;
description?: string;
priority?: TicketPriority | string;
}
export interface PortalCreateMessageRequest {
body: string;
}
export interface PortalCsatRequest {
csatScore: number;
csatComment?: string | null;
}
export interface PortalTicketDto {
id: string;
number: string;
subject: string;
description: string | null;
status: TicketStatus | string;
priority: TicketPriority | string;
resolvedAt: string | null;
csatScore: number | null;
csatComment: string | null;
messages: Array<{
id: string;
body: string;
createdAt: string;
fromStaff: boolean;
}>;
createdAt: string;
updatedAt: string;
}
/* ——— گزارشات و داشبورد ——— */
export interface ReportsDashboardDto {
from: string;
to: string;
currency: string;
sales: {
openCount: number;
wonCount: number;
lostCount: number;
openAmount: number;
wonAmount: number;
lostAmount: number;
winRate: number;
};
funnel: Array<{
stageId: string;
stageName: string;
pipelineName: string;
count: number;
amount: number;
}>;
activities: {
open: number;
done: number;
overdue: number;
byType: Array<{ type: string; count: number }>;
};
team: Array<{
userId: string;
fullName: string;
wonAmount: number;
wonCount: number;
activitiesDone: number;
}>;
tickets: {
open: number;
resolved: number;
closed: number;
slaBreached: number;
avgCsat: number | null;
csatCount: number;
};
peopleCreated: number;
}
export interface HomeDashboardKpiDto {
key: string;
label: string;
value: number;
changePercent: number | null;
changeLabel: string;
}
export interface HomeDashboardAlertDto {
key: string;
tone: 'urgent' | 'warning' | 'success' | 'info';
text: string;
link?: string;
}
export interface HomeDashboardTrendPointDto {
monthKey: string;
monthLabel: string;
amount: number;
}
export interface HomeDashboardSourceDto {
label: string;
count: number;
percent: number;
}
export interface HomeDashboardTopCustomerDto {
id: string;
name: string;
dealCount: number;
rank: number;
}
export interface HomeDashboardDto {
currency: string;
kpis: HomeDashboardKpiDto[];
alerts: HomeDashboardAlertDto[];
salesTrend: HomeDashboardTrendPointDto[];
sources: HomeDashboardSourceDto[];
topCustomers: HomeDashboardTopCustomerDto[];
}
/** برد پروژه / کاریز کارت */
export interface ProjectBoardStageDto {
id: string;
name: string;
position: number;
}
export interface ProjectBoardDto {
id: string;
name: string;
isDefault: boolean;
stages: ProjectBoardStageDto[];
}
export interface ProjectCardDto {
id: string;
title: string;
notes: string | null;
position: number;
boardId: string;
stageId: string;
person: PersonSummaryDto | null;
company: CompanySummaryDto | null;
deal: { id: string; title: string } | null;
owner: UserSummaryDto | null;
createdAt: string;
updatedAt: string;
}
export interface ProjectBoardColumnDto extends ProjectBoardStageDto {
cards: ProjectCardDto[];
}
export interface ProjectBoardBoardDto {
board: ProjectBoardDto;
stages: ProjectBoardColumnDto[];
}
export interface CreateProjectBoardRequest {
name: string;
}
export interface CreateProjectCardRequest {
title: string;
boardId?: string;
stageId?: string;
notes?: string;
personId?: string | null;
companyId?: string | null;
dealId?: string | null;
ownerId?: string | null;
}
export type UpdateProjectCardRequest = Partial<CreateProjectCardRequest>;
export interface MoveProjectCardRequest {
stageId: string;
position?: number;
}
/** باشگاه مشتریان */
export interface LoyaltyTierDto {
id: string;
name: string;
minPoints: number;
position: number;
color: string | null;
memberCount?: number;
}
export interface CreateLoyaltyTierRequest {
name: string;
minPoints: number;
color?: string | null;
}
export type UpdateLoyaltyTierRequest = Partial<CreateLoyaltyTierRequest>;
export interface AdjustLoyaltyPointsRequest {
delta: number;
reason?: string;
}
export interface LoyaltyMemberDto {
id: string;
fullName: string;
mobile: string | null;
email: string | null;
loyaltyPoints: number;
loyaltyTier: LoyaltyTierSummaryDto | null;
company: CompanySummaryDto | null;
}
/** اتوماسیون اگر/آنگاه */
export type AutomationTrigger = "deal_won" | "ticket_resolved";
export type AutomationAction =
| "create_activity"
| "create_notification"
| "add_loyalty_points";
export const AUTOMATION_TRIGGER_LABELS: Record<AutomationTrigger, string> = {
deal_won: "معامله برنده شد",
ticket_resolved: "تیکت حل شد",
};
export const AUTOMATION_ACTION_LABELS: Record<AutomationAction, string> = {
create_activity: "ساخت فعالیت",
create_notification: "ارسال اعلان",
add_loyalty_points: "افزودن امتیاز باشگاه",
};
export interface AutomationRuleConfig {
title?: string;
body?: string;
assigneeId?: string | null;
notifyUserId?: string | null;
activityType?: "call" | "meeting" | "task" | "note";
points?: number;
}
export interface AutomationRuleDto {
id: string;
name: string;
isActive: boolean;
trigger: AutomationTrigger;
action: AutomationAction;
config: AutomationRuleConfig;
createdAt: string;
updatedAt: string;
}
export interface CreateAutomationRuleRequest {
name: string;
trigger: AutomationTrigger;
action: AutomationAction;
isActive?: boolean;
config?: AutomationRuleConfig;
}
export type UpdateAutomationRuleRequest = Partial<CreateAutomationRuleRequest>;
export const APP_NAME = "Mento CRM";
export const APP_NAME_FA = "منتو";
export const API_PREFIX = "api";