Fix web build failure from corrupted Tahesab status types.

Restore MandehValueDto status encoding and derive بس/بد labels from amount.
This commit is contained in:
2026-09-27 21:26:56 +03:30
parent 647503810d
commit 7e73ba9936
2 changed files with 246 additions and 245 deletions
+245 -244
View File
@@ -3,13 +3,13 @@ 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: "پشتیبانی",
owner: "مالک",
admin: "مدیر",
sales: "فروش",
support: "پشتیبانی",
};
/** تنظیمات سازمانی و مدیریت کاربران */
/** تنظیمات سازمانی و مدیریت کاربران */
export function canManageSettings(role: UserRole | string | null | undefined): boolean {
return role === "owner" || role === "admin";
}
@@ -18,12 +18,12 @@ export function canManageUsers(role: UserRole | string | null | undefined): bool
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";
}
@@ -37,10 +37,10 @@ export interface AuthUserDto {
organizationId: string;
organizationName?: string;
hasAvatar?: boolean;
/** مالک محیط فعلی — اشتراک متعلق به مالک است نه عضو زیرمجموعه */
/** مالک محیط فعلی — اشتراک متعلق به مالک است نه عضو زیرمجموعه */
isOrgOwner?: boolean;
enabledModules?: OrgModuleKey[];
/** خلاصه اشتراک مالک محیط (برای اعضا فقط جهت نمایش/گیت ورود) */
/** خلاصه اشتراک مالک محیط (برای اعضا فقط جهت نمایش/گیت ورود) */
subscription?: SubscriptionSummaryDto | null;
}
@@ -64,15 +64,15 @@ export const BILLING_PLAN_CODES: BillingPlanCode[] = [
];
export const BILLING_PLAN_LABELS: Record<BillingPlanCode, string> = {
trial: "دمو ۱۵ روزه",
monthly: "ماهانه",
quarterly: "سه‌ماهه",
semiannual: "شش‌ماهه",
yearly: "یکساله",
custom: "سفارشی",
trial: "دمو ۱۵ روزه",
monthly: "ماهانه",
quarterly: "سه‌ماهه",
semiannual: "شش‌ماهه",
yearly: "یکساله",
custom: "سفارشی",
};
/** مدت پیش‌فرض پلن‌ها (روز) — custom ندارد */
/** مدت پیش‌فرض پلن‌ها (روز) — custom ندارد */
export const BILLING_PLAN_DAYS: Record<Exclude<BillingPlanCode, "custom">, number> = {
trial: 15,
monthly: 30,
@@ -164,49 +164,49 @@ export const ORG_MODULE_KEYS: OrgModuleKey[] = [
];
export const ORG_MODULE_LABELS: Record<OrgModuleKey, string> = {
customers: "مشتریان",
pipeline: "کاریز فروش",
products: "محصولات",
invoices: "فاکتورها",
quotes: "پیش‌فاکتورها",
commissions: "پورسانت",
sales_forecast: "هدف و پیش‌بینی",
activities: "فعالیت‌ها",
tickets: "تیکت‌ها",
workflow_automations: "اتوماسیون گردش کار",
message_automations: "اتوماسیون پیامک",
lead_forms: "فرم‌ساز سرنخ",
leads: "مدیریت لیدها",
project_boards: "کاریز پروژه",
inventory: "انبار",
cheques: "چک‌ها",
attachments: "پیوست‌ها",
loyalty: "باشگاه مشتریان",
reports: "گزارش‌ها",
notes: "یادداشت‌ها",
tahesab: "ته‌حساب",
custom_fields: "فیلدهای سفارشی",
currencies: "ارزها",
team_settings: "تیم و تنظیمات سازمان",
customers: "مشتریان",
pipeline: "کاریز فروش",
products: "محصولات",
invoices: "فاکتورها",
quotes: "پیش‌فاکتورها",
commissions: "پورسانت",
sales_forecast: "هدف و پیش‌بینی",
activities: "فعالیت‌ها",
tickets: "تیکت‌ها",
workflow_automations: "اتوماسیون گردش کار",
message_automations: "اتوماسیون پیامک",
lead_forms: "فرم‌ساز سرنخ",
leads: "مدیریت لیدها",
project_boards: "کاریز پروژه",
inventory: "انبار",
cheques: "چک‌ها",
attachments: "پیوست‌ها",
loyalty: "باشگاه مشتریان",
reports: "گزارش‌ها",
notes: "یادداشت‌ها",
tahesab: "ته‌حساب",
custom_fields: "فیلدهای سفارشی",
currencies: "ارزها",
team_settings: "تیم و تنظیمات سازمان",
faq: "FAQ",
audit_logs: "لاگ فعالیت کاربران",
saved_views: "فیلترهای ذخیره‌شده",
public_api: "API و وب‌هوک",
sms_campaigns: "پیامک گروهی",
teams: "تیم‌ها و سطح دسترسی به پرونده‌ها",
woocommerce: "ووکامرس",
voip: "تلفن سازمانی",
reservations: "رزرو و نوبت‌دهی",
audit_logs: "لاگ فعالیت کاربران",
saved_views: "فیلترهای ذخیره‌شده",
public_api: "API و وب‌هوک",
sms_campaigns: "پیامک گروهی",
teams: "تیم‌ها و سطح دسترسی به پرونده‌ها",
woocommerce: "ووکامرس",
voip: "تلفن سازمانی",
reservations: "رزرو و نوبت‌دهی",
};
export const ORG_MODULE_GROUPS: Array<{
title: string;
keys: OrgModuleKey[];
}> = [
{ title: "مشتریان", keys: ["customers"] },
{ title: "لیدها", keys: ["leads", "lead_forms"] },
{ title: "مشتریان", keys: ["customers"] },
{ title: "لیدها", keys: ["leads", "lead_forms"] },
{
title: "فروش",
title: "فروش",
keys: [
"pipeline",
"products",
@@ -216,10 +216,10 @@ export const ORG_MODULE_GROUPS: Array<{
"sales_forecast",
],
},
{ title: "فعالیت‌ها", keys: ["activities", "notes"] },
{ title: "پشتیبانی", keys: ["tickets", "faq"] },
{ title: "فعالیت‌ها", keys: ["activities", "notes"] },
{ title: "پشتیبانی", keys: ["tickets", "faq"] },
{
title: "اتوماسیون",
title: "اتوماسیون",
keys: [
"workflow_automations",
"message_automations",
@@ -227,7 +227,7 @@ export const ORG_MODULE_GROUPS: Array<{
],
},
{
title: "ابزارها",
title: "ابزارها",
keys: [
"project_boards",
"inventory",
@@ -242,7 +242,7 @@ export const ORG_MODULE_GROUPS: Array<{
],
},
{
title: "تنظیمات",
title: "تنظیمات",
keys: [
"team_settings",
"teams",
@@ -312,7 +312,7 @@ export interface OrgUserDto {
lastLoginAt?: string | null;
hasAvatar?: boolean;
commissionPercent?: number;
/** own = فقط خود | team = هم‌تیمی‌ها | org = کل سازمان */
/** own = فقط خود | team = هم‌تیمی‌ها | org = کل سازمان */
dataVisibility?: DataVisibility;
createdAt: string;
}
@@ -322,9 +322,9 @@ export type DataVisibility = "own" | "team" | "org";
export const DATA_VISIBILITIES: DataVisibility[] = ["own", "team", "org"];
export const DATA_VISIBILITY_LABELS: Record<DataVisibility, string> = {
own: "فقط پرونده‌های خود",
team: "تیم‌های عضو",
org: "کل سازمان",
own: "فقط پرونده‌های خود",
team: "تیم‌های عضو",
org: "کل سازمان",
};
export interface UpdateUserVisibilityRequest {
@@ -345,14 +345,14 @@ export const ROLE_PERMISSION_ITEMS: Array<{
key: RolePermissionKey;
label: string;
}> = [
{ key: "customers", label: "مشتریان" },
{ key: "sales", label: "فروش و معاملات" },
{ key: "billing", label: "پیش‌فاکتورها و فاکتورها" },
{ key: "products", label: "محصولات و خدمات" },
{ key: "activities", label: "فعالیت‌ها" },
{ key: "notes", label: "یادداشت‌ها" },
{ key: "reports", label: "گزارش‌ها" },
{ key: "audit", label: "لاگ فعالیت کاربران" },
{ key: "customers", label: "مشتریان" },
{ key: "sales", label: "فروش و معاملات" },
{ key: "billing", label: "پیش‌فاکتورها و فاکتورها" },
{ key: "products", label: "محصولات و خدمات" },
{ key: "activities", label: "فعالیت‌ها" },
{ key: "notes", label: "یادداشت‌ها" },
{ key: "reports", label: "گزارش‌ها" },
{ key: "audit", label: "لاگ فعالیت کاربران" },
];
export interface OrgRoleMemberDto {
@@ -422,7 +422,7 @@ export interface ApiErrorBody {
}
export interface LoginRequest {
/** ایمیل یا شماره موبایل */
/** ایمیل یا شماره موبایل */
identifier: string;
password: string;
}
@@ -444,7 +444,7 @@ export interface LoginChallengeResponse {
channel: 'email' | 'mobile';
expiresInSeconds: number;
maskedDestination?: string;
/** فقط در محیط توسعه / AUTH_RETURN_OTP */
/** فقط در محیط توسعه / AUTH_RETURN_OTP */
devCode?: string;
}
@@ -453,7 +453,7 @@ export interface RegisterChallengeResponse {
expiresInSeconds: number;
maskedEmail?: string;
maskedMobile?: string;
/** وقتی سرویس ایمیل خاموش است false — فقط OTP موبایل لازم است */
/** وقتی سرویس ایمیل خاموش است false — فقط OTP موبایل لازم است */
emailOtpRequired?: boolean;
devEmailCode?: string;
devMobileCode?: string;
@@ -531,7 +531,7 @@ export interface UpdateOrganizationRequest {
businessField?: BusinessField;
}
/** زمینه فعالیت سازمان — هم‌تراز صنایع دیدار */
/** زمینه فعالیت سازمان — هم‌تراز صنایع دیدار */
export const BUSINESS_FIELDS = [
"education",
"beauty",
@@ -558,26 +558,26 @@ export const BUSINESS_FIELDS = [
export type BusinessField = (typeof BUSINESS_FIELDS)[number];
export const BUSINESS_FIELD_LABELS: Record<BusinessField, string> = {
education: "آموزشگاه و مؤسسات آموزشی",
beauty: "کلینیک زیبایی و آرایشگاه",
real_estate: "املاک و مشاورین مسکن",
construction: "صنعت ساختمان",
advertising: "تبلیغات و مشاوره کسب‌وکار",
insurance: "بیمه",
consulting: "شرکت‌های مشاور",
startup: "استارتاپ و کسب‌وکار آنلاین",
medical_devices: "تجهیزات پزشکی",
travel: "گردشگری و مهاجرت",
contractor: "پیمانکاری و پروژه‌ای",
trading: "بازرگانی",
manufacturing: "تولیدی و صنعتی",
personal: "کسب‌وکار شخصی و خانگی",
tech: "نرم‌افزار و سخت‌افزار",
legal: "وکلا و مشاورین حقوقی",
repair: "خدمات و تعمیرات",
retail: "خرده‌فروشی",
jewelry: "طلا و جواهر",
other: "سایر",
education: "آموزشگاه و مؤسسات آموزشی",
beauty: "کلینیک زیبایی و آرایشگاه",
real_estate: "املاک و مشاورین مسکن",
construction: "صنعت ساختمان",
advertising: "تبلیغات و مشاوره کسب‌وکار",
insurance: "بیمه",
consulting: "شرکت‌های مشاور",
startup: "استارتاپ و کسب‌وکار آنلاین",
medical_devices: "تجهیزات پزشکی",
travel: "گردشگری و مهاجرت",
contractor: "پیمانکاری و پروژه‌ای",
trading: "بازرگانی",
manufacturing: "تولیدی و صنعتی",
personal: "کسب‌وکار شخصی و خانگی",
tech: "نرم‌افزار و سخت‌افزار",
legal: "وکلا و مشاورین حقوقی",
repair: "خدمات و تعمیرات",
retail: "خرده‌فروشی",
jewelry: "طلا و جواهر",
other: "سایر",
};
export function isBusinessField(value: string): value is BusinessField {
@@ -593,7 +593,7 @@ export interface ExchangeRateDto {
export interface UpdateOrgCurrenciesRequest {
baseCurrency?: string;
enabledCurrencies?: string[];
/** نرخ‌ها نسبت به ارز پایه؛ ارز پایه نیازی به نرخ ندارد */
/** نرخ‌ها نسبت به ارز پایه؛ ارز پایه نیازی به نرخ ندارد */
rates?: Array<{ currency: string; rateToBase: number }>;
}
@@ -602,12 +602,12 @@ export const CURRENCY_CATALOG: Array<{
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: "پوند" },
{ 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 {
@@ -677,10 +677,10 @@ export const PERSON_MOODS = ["newcomer", "happy", "unhappy", "special"] as const
export type PersonMood = (typeof PERSON_MOODS)[number];
export const PERSON_MOOD_LABELS: Record<PersonMood, string> = {
newcomer: "مشتری تازه وارد",
happy: "مشتری خوشحال",
unhappy: "مشتری ناراضی",
special: "مشتری خاص",
newcomer: "مشتری تازه وارد",
happy: "مشتری خوشحال",
unhappy: "مشتری ناراضی",
special: "مشتری خاص",
};
export interface PersonDto {
@@ -777,7 +777,7 @@ export interface DealDto {
person: PersonSummaryDto | null;
company: CompanySummaryDto | null;
owner: UserSummaryDto | null;
/** مسئولان مشترک معامله (علاوه بر مالک اصلی) */
/** مسئولان مشترک معامله (علاوه بر مالک اصلی) */
assignees: UserSummaryDto[];
lineItems: DealLineItemDto[];
createdAt: string;
@@ -849,7 +849,7 @@ export interface UpdateDealRequest {
lineItems?: DealLineItemInput[];
}
/** فیلتر ذخیره‌شدهٔ لیست اشخاص */
/** فیلتر ذخیره‌شدهٔ لیست اشخاص */
export interface PeopleViewFilters {
q?: string;
sort?: string;
@@ -857,7 +857,7 @@ export interface PeopleViewFilters {
page?: number;
}
/** فیلتر ذخیره‌شدهٔ کاریز / معاملات */
/** فیلتر ذخیره‌شدهٔ کاریز / معاملات */
export interface DealsViewFilters {
q?: string;
amountMin?: string;
@@ -1014,7 +1014,7 @@ export interface NoteDto {
title: string | null;
body: string;
noteType: NoteType | string;
/** team = تیمی | personal = فقط نویسنده */
/** team = تیمی | personal = فقط نویسنده */
visibility: NoteVisibility;
pinned: boolean;
color: string | null;
@@ -1029,7 +1029,7 @@ export interface NoteDto {
activity: { id: string; title: string } | null;
author: UserSummaryDto | null;
attachments: NoteAttachmentDto[];
/** تعداد نسخه‌های قبلی (برای نمایش دکمه تاریخچه) */
/** تعداد نسخه‌های قبلی (برای نمایش دکمه تاریخچه) */
revisionCount?: number;
createdAt: string;
updatedAt: string;
@@ -1040,8 +1040,8 @@ export type NoteVisibility = "team" | "personal";
export const NOTE_VISIBILITIES: NoteVisibility[] = ["team", "personal"];
export const NOTE_VISIBILITY_LABELS: Record<NoteVisibility, string> = {
team: "تیمی",
personal: "شخصی (فقط من)",
team: "تیمی",
personal: "شخصی (فقط من)",
};
export interface NoteRevisionDto {
@@ -1865,7 +1865,7 @@ export interface CreateSalesGoalRequest {
probability?: number | null;
currency?: string;
notes?: string;
/** فقط مالک/مدیر؛ در غیر این صورت هدف برای خود کاربر */
/** فقط مالک/مدیر؛ در غیر این صورت هدف برای خود کاربر */
userId?: string | null;
}
@@ -1896,13 +1896,13 @@ export interface SalesForecastDto {
periodStart: string;
periodEnd: string;
currency: string;
/** مجموع اهداف هم‌پوشان با بازه */
/** مجموع اهداف هم‌پوشان با بازه */
targetAmount: number;
/** معاملات برنده‌شده در بازه */
/** معاملات برنده‌شده در بازه */
wonAmount: number;
/** معاملات باز فعلی */
/** معاملات باز فعلی */
openPipelineAmount: number;
/** پیش‌بینی: تحقق + کاریز باز × میانگین احتمال */
/** پیش‌بینی: تحقق + کاریز باز × میانگین احتمال */
forecastAmount: number;
progressPercent: number | null;
openDealsCount: number;
@@ -1910,7 +1910,7 @@ export interface SalesForecastDto {
goals: SalesGoalDto[];
kpis: SalesForecastKpiDto[];
newCustomersCount: number;
/** معاملات ایجادشده در بازه */
/** معاملات ایجادشده در بازه */
newDealsCount: number;
}
@@ -2011,7 +2011,7 @@ export interface UpdateFaqArticleRequest {
position?: number;
}
/** ساعات مهلت پاسخ اول بر اساس اولویت */
/** ساعات مهلت پاسخ اول بر اساس اولویت */
export const TICKET_SLA_HOURS: Record<TicketPriority, number> = {
urgent: 4,
high: 8,
@@ -2019,7 +2019,7 @@ export const TICKET_SLA_HOURS: Record<TicketPriority, number> = {
low: 48,
};
/* ——— پرتال مشتری (OTP) ——— */
/* ——— پرتال مشتری (OTP) ——— */
export interface PortalOrgInfoDto {
name: string;
@@ -2032,7 +2032,7 @@ export interface PortalRequestOtpRequest {
export interface PortalRequestOtpResponse {
ok: true;
/** فقط در حالت توسعه / دمو وقتی SMS واقعی وصل نیست */
/** فقط در حالت توسعه / دمو وقتی SMS واقعی وصل نیست */
devCode?: string;
expiresInSeconds: number;
}
@@ -2089,7 +2089,7 @@ export interface PortalTicketDto {
updatedAt: string;
}
/* ——— گزارشات و داشبورد ——— */
/* ——— گزارشات و داشبورد ——— */
export interface ReportsKpiDto {
key: string;
@@ -2127,7 +2127,7 @@ export interface ReportsTeamRowDto {
activitiesDone: number;
}
/** گونه‌های drill-down گزارش عمیق (فاز ۱ BI) */
/** گونه‌های drill-down گزارش عمیق (فاز ۱ BI) */
export type ReportsDrillKind =
| "stage_open"
| "team_won"
@@ -2152,25 +2152,25 @@ export interface ReportsFunnelStageDto {
pipelineName: string;
count: number;
amount: number;
/** درصد تبدیل نسبت به مرحله قبل همان کاریز؛ null برای اولین مرحله */
/** درصد تبدیل نسبت به مرحله قبل همان کاریز؛ null برای اولین مرحله */
conversionFromPrevPercent: number | null;
/** سهم از کل معاملات باز همان کاریز */
/** سهم از کل معاملات باز همان کاریز */
shareOfPipelinePercent: number;
}
/** یک ردیف نرخ تبدیل (ورودی → موفق) مثل دیدار */
/** یک ردیف نرخ تبدیل (ورودی → موفق) مثل دیدار */
export interface ReportsConversionRateRowDto {
key: string;
label: string;
incomingCount: number;
wonCount: number;
/** درصد؛ اگر ورودی صفر باشد ۰ */
/** درصد؛ اگر ورودی صفر باشد ۰ */
conversionPercent: number;
}
/**
* نرخ تبدیل به سبک دیدار:
* از معاملات تازه‌ساخته‌شده در بازه، چند درصد الان برنده شده‌اند.
* نرخ تبدیل به سبک دیدار:
* از معاملات تازه‌ساخته‌شده در بازه، چند درصد الان برنده شده‌اند.
*/
export interface ReportsConversionRateDto {
incomingCount: number;
@@ -2192,7 +2192,7 @@ export interface ReportsPeriodCompareRowDto {
current: number;
previous: number;
changePercent: number | null;
/** اگر قابل کلیک برای لیست پرونده باشد */
/** اگر قابل کلیک برای لیست پرونده باشد */
drillKind?: ReportsDrillKind;
}
@@ -2249,9 +2249,9 @@ export interface ReportsDashboardDto {
winRate: number;
};
funnel: ReportsFunnelStageDto[];
/** نرخ تبدیل ورودی→موفق (سبک دیدار) */
/** نرخ تبدیل ورودی→موفق (سبک دیدار) */
conversionRate: ReportsConversionRateDto;
/** مقایسه صریح بازه فعلی با دوره قبل هم‌طول */
/** مقایسه صریح بازه فعلی با دوره قبل هم‌طول */
periodCompare: ReportsPeriodCompareRowDto[];
tickets: {
open: number;
@@ -2309,7 +2309,7 @@ export interface HomeDashboardDto {
topCustomers: HomeDashboardTopCustomerDto[];
}
/** برد پروژه / کاریز کارت */
/** برد پروژه / کاریز کارت */
export interface ProjectBoardStageDto {
id: string;
name: string;
@@ -2373,7 +2373,7 @@ export interface MoveProjectCardRequest {
position?: number;
}
/** باشگاه مشتریان */
/** باشگاه مشتریان */
export interface LoyaltyTierDto {
id: string;
name: string;
@@ -2476,7 +2476,7 @@ export interface RedeemLoyaltyRewardRequest {
personId: string;
}
/** اتوماسیون اگر/آنگاه */
/** اتوماسیون اگر/آنگاه */
export type AutomationTrigger =
| "person_created"
| "lead_submitted"
@@ -2495,23 +2495,23 @@ export type AutomationAction =
| "add_loyalty_points";
export const AUTOMATION_TRIGGER_LABELS: Record<AutomationTrigger, string> = {
person_created: "مخاطب جدید ساخته شد",
lead_submitted: "فرم سرنخ ارسال شد",
deal_created: "معامله جدید ساخته شد",
deal_stage_changed: "مرحله معامله عوض شد",
deal_won: "معامله برنده شد",
deal_lost: "معامله باخت",
ticket_created: "تیکت جدید ساخته شد",
ticket_resolved: "تیکت حل شد",
invoice_issued: "فاکتور صادر شد",
invoice_paid: "پرداخت روی فاکتور ثبت شد",
activity_done: "فعالیت تمام شد",
person_created: "مخاطب جدید ساخته شد",
lead_submitted: "فرم سرنخ ارسال شد",
deal_created: "معامله جدید ساخته شد",
deal_stage_changed: "مرحله معامله عوض شد",
deal_won: "معامله برنده شد",
deal_lost: "معامله باخت",
ticket_created: "تیکت جدید ساخته شد",
ticket_resolved: "تیکت حل شد",
invoice_issued: "فاکتور صادر شد",
invoice_paid: "پرداخت روی فاکتور ثبت شد",
activity_done: "فعالیت تمام شد",
};
export const AUTOMATION_ACTION_LABELS: Record<AutomationAction, string> = {
create_activity: "ساخت فعالیت",
create_notification: "ارسال اعلان",
add_loyalty_points: "افزودن امتیاز باشگاه",
create_activity: "ساخت فعالیت",
create_notification: "ارسال اعلان",
add_loyalty_points: "افزودن امتیاز باشگاه",
};
export const MAX_AUTOMATION_STEPS = 8;
@@ -2540,14 +2540,14 @@ export const AUTOMATION_TRIGGER_GROUPS: {
label: string;
items: AutomationTrigger[];
}[] = [
{ label: "مخاطب", items: ["person_created", "lead_submitted"] },
{ label: "مخاطب", items: ["person_created", "lead_submitted"] },
{
label: "معامله",
label: "معامله",
items: ["deal_created", "deal_stage_changed", "deal_won", "deal_lost"],
},
{ label: "تیکت", items: ["ticket_created", "ticket_resolved"] },
{ label: "فعالیت", items: ["activity_done"] },
{ label: "مالی", items: ["invoice_issued", "invoice_paid"] },
{ label: "تیکت", items: ["ticket_created", "ticket_resolved"] },
{ label: "فعالیت", items: ["activity_done"] },
{ label: "مالی", items: ["invoice_issued", "invoice_paid"] },
];
export type AutomationStepKind = "action" | "condition";
@@ -2573,31 +2573,31 @@ export const AUTOMATION_CONDITION_FIELD_LABELS: Record<
AutomationConditionField,
string
> = {
deal_amount: "مبلغ معامله",
has_person: "مخاطب دارد",
has_company: "شرکت دارد",
ticket_priority: "اولویت تیکت",
deal_amount: "مبلغ معامله",
has_person: "مخاطب دارد",
has_company: "شرکت دارد",
ticket_priority: "اولویت تیکت",
};
export const AUTOMATION_CONDITION_OP_LABELS: Record<
AutomationConditionOp,
string
> = {
gte: "بزرگ‌تر یا مساوی",
lte: "کوچک‌تر یا مساوی",
eq: "مساوی",
neq: "نامساوی",
is_set: "دارد",
is_empty: "ندارد",
gte: "بزرگ‌تر یا مساوی",
lte: "کوچک‌تر یا مساوی",
eq: "مساوی",
neq: "نامساوی",
is_set: "دارد",
is_empty: "ندارد",
};
export const AUTOMATION_NOTIFY_CHANNEL_LABELS: Record<
AutomationNotifyChannel,
string
> = {
app: "ناتیفیکیشن داخلی",
sms: "پیامک",
both: "هر دو",
app: "ناتیفیکیشن داخلی",
sms: "پیامک",
both: "هر دو",
};
export const AUTOMATION_NOTIFY_CHANNELS = [
@@ -2660,7 +2660,7 @@ export interface AutomationRuleConfig {
notifyTarget?: AutomationNotifyTarget;
activityType?: "call" | "meeting" | "task" | "note";
points?: number;
/** زنجیرهٔ اعمال؛ اگر خالی باشد همان action تکی استفاده می‌شود */
/** زنجیرهٔ اعمال؛ اگر خالی باشد همان action تکی استفاده می‌شود */
steps?: AutomationStep[];
}
@@ -2756,7 +2756,7 @@ export function automationStepToConfig(step: AutomationStep): AutomationRuleConf
};
}
// —— ته‌حساب / حسابداری ——
// —— ته‌حساب / حسابداری ——
export const TAHSAB_SANAD_TYPES = [
"buy_sale_gold",
@@ -2769,11 +2769,11 @@ export const TAHSAB_SANAD_TYPES = [
export type TahesabSanadType = (typeof TAHSAB_SANAD_TYPES)[number];
export const TAHSAB_SANAD_LABELS: Record<TahesabSanadType, string> = {
buy_sale_gold: "خرید/فروش آبشده",
buy_sale_sekeh: "خرید/فروش سکه",
talab_bedehi: "طلب/بدهی",
vkh_gold: "واریز/خروج طلا",
vkh_bank: "واریز/خروج بانکی",
buy_sale_gold: "خرید/فروش آبشده",
buy_sale_sekeh: "خرید/فروش سکه",
talab_bedehi: "طلب/بدهی",
vkh_gold: "واریز/خروج طلا",
vkh_bank: "واریز/خروج بانکی",
};
export interface TahesabConnectionDto {
@@ -2822,7 +2822,8 @@ export interface PersonAccountingLinkDto {
export interface MandehValueDto {
amount: string | number;
unit: string;
status: "بس" | "بد";
/** بس = بستانکار | بد = بدهکار */
status: "بس" | "بد" | string;
}
export interface MandehDetailItemDto {
@@ -2843,7 +2844,7 @@ export interface PersonAssetsDto {
fetchedAt: string;
}
// —— پیام خودکار (جدا از اتوماسیون گردش کار) ——
// —— پیام خودکار (جدا از اتوماسیون گردش کار) ——
export type MessageAutomationTrigger =
| "person_created"
@@ -2887,37 +2888,37 @@ export const MESSAGE_AUTOMATION_TRIGGER_LABELS: Record<
MessageAutomationTrigger,
string
> = {
person_created: "مخاطب جدید ساخته شد",
lead_submitted: "فرم سرنخ ارسال شد",
deal_created: "معامله جدید ساخته شد",
deal_stage_changed: "مرحله معامله عوض شد",
deal_won: "معامله برنده شد",
deal_lost: "معامله باخت",
ticket_created: "تیکت جدید ساخته شد",
ticket_resolved: "تیکت حل شد",
invoice_issued: "فاکتور صادر شد",
invoice_paid: "پرداخت روی فاکتور ثبت شد",
activity_created: "فعالیت ثبت شد",
activity_done: "فعالیت تمام شد",
person_created: "مخاطب جدید ساخته شد",
lead_submitted: "فرم سرنخ ارسال شد",
deal_created: "معامله جدید ساخته شد",
deal_stage_changed: "مرحله معامله عوض شد",
deal_won: "معامله برنده شد",
deal_lost: "معامله باخت",
ticket_created: "تیکت جدید ساخته شد",
ticket_resolved: "تیکت حل شد",
invoice_issued: "فاکتور صادر شد",
invoice_paid: "پرداخت روی فاکتور ثبت شد",
activity_created: "فعالیت ثبت شد",
activity_done: "فعالیت تمام شد",
};
export const MESSAGE_AUTOMATION_UNIT_LABELS: Record<
MessageAutomationDelayUnit,
string
> = {
minutes: "دقیقه",
hours: "ساعت",
days: "روز",
weeks: "هفته",
months: "ماه",
minutes: "دقیقه",
hours: "ساعت",
days: "روز",
weeks: "هفته",
months: "ماه",
};
export const MESSAGE_AUTOMATION_FIELDS = [
{ token: "{نام}", label: "نام مشتری" },
{ token: "{شماره}", label: "شماره موبایل" },
{ token: "{تاریخ}", label: "تاریخ ارسال" },
{ token: "{عنوان}", label: "عنوان رکورد" },
{ token: "{شرکت}", label: "نام شرکت" },
{ token: "{نام}", label: "نام مشتری" },
{ token: "{شماره}", label: "شماره موبایل" },
{ token: "{تاریخ}", label: "تاریخ ارسال" },
{ token: "{عنوان}", label: "عنوان رکورد" },
{ token: "{شرکت}", label: "نام شرکت" },
] as const;
export const MESSAGE_AUTOMATION_SMS_SEGMENT = 70;
@@ -2926,18 +2927,18 @@ export const MESSAGE_AUTOMATION_CHANNEL_LABELS: Record<
MessageAutomationChannel,
string
> = {
app: "ناتیف داخل برنامه",
sms: "پیامک",
both: "پیامک و ناتیف",
app: "ناتیف داخل برنامه",
sms: "پیامک",
both: "پیامک و ناتیف",
};
export const MESSAGE_AUTOMATION_TARGET_LABELS: Record<
MessageAutomationTarget,
string
> = {
staff: "مسئول پرونده",
person: "مشتری",
both: "مشتری و مسئول",
staff: "مسئول پرونده",
person: "مشتری",
both: "مشتری و مسئول",
};
export interface MessageAutomationRuleDto {
@@ -3064,7 +3065,7 @@ export interface PlatformUserDto {
lastLoginAt?: string | null;
createdAt: string;
memberships: PlatformUserMembershipDto[];
/** فقط اگر حداقل یک عضویت مالک فعال دارد */
/** فقط اگر حداقل یک عضویت مالک فعال دارد */
isBillingOwner?: boolean;
billing?: BillingAccountDto | null;
}
@@ -3101,7 +3102,7 @@ export { brand, APP_NAME, APP_NAME_FA, brandSuggestionFa } from "./brand";
export type { Brand } from "./brand";
export const API_PREFIX = "api";
/* ——— لاگ فعالیت کاربران ——— */
/* ——— لاگ فعالیت کاربران ——— */
export interface AuditLogDto {
id: string;
@@ -3123,7 +3124,7 @@ export interface AuditLogListResponse {
limit: number;
}
/* ——— فیلترهای ذخیره‌شده ——— */
/* ——— فیلترهای ذخیره‌شده ——— */
export type SavedViewScope =
| "deals"
@@ -3142,7 +3143,7 @@ export const SAVED_VIEW_SCOPES: SavedViewScope[] = [
"reports",
];
/** فیلترهای ذخیره‌شدهٔ صفحه گزارشات */
/** فیلترهای ذخیره‌شدهٔ صفحه گزارشات */
export interface ReportsViewFilters {
/** today | week | month | quarter | year | custom */
period: string;
@@ -3158,7 +3159,7 @@ export interface ReportsViewFilters {
};
}
/** متریک‌های گزارش‌ساز ساده */
/** متریک‌های گزارش‌ساز ساده */
export type ReportsBuilderMetric =
| "won_amount"
| "won_count"
@@ -3186,18 +3187,18 @@ export const REPORTS_BUILDER_METRIC_LABELS: Record<
ReportsBuilderMetric,
string
> = {
won_amount: "مبلغ معاملات برنده",
won_count: "تعداد معاملات برنده",
lost_count: "تعداد معاملات باخته",
open_count: "تعداد معاملات باز",
open_amount: "مبلغ معاملات باز",
activities_done: "فعالیت انجام‌شده",
people_created: "مشتریان جدید",
invoice_amount: "مبلغ فاکتور",
invoice_count: "تعداد فاکتور",
won_amount: "مبلغ معاملات برنده",
won_count: "تعداد معاملات برنده",
lost_count: "تعداد معاملات باخته",
open_count: "تعداد معاملات باز",
open_amount: "مبلغ معاملات باز",
activities_done: "فعالیت انجام‌شده",
people_created: "مشتریان جدید",
invoice_amount: "مبلغ فاکتور",
invoice_count: "تعداد فاکتور",
};
/** ابعاد گروه‌بندی گزارش‌ساز */
/** ابعاد گروه‌بندی گزارش‌ساز */
export type ReportsBuilderDimension =
| "none"
| "owner"
@@ -3221,13 +3222,13 @@ export const REPORTS_BUILDER_DIMENSION_LABELS: Record<
ReportsBuilderDimension,
string
> = {
none: "بدون گروه‌بندی (جمع کل)",
owner: "کاربر / مسئول",
team: "تیم",
source: "منبع",
stage: "مرحله کاریز",
month: "ماه",
status: "وضعیت معامله",
none: "بدون گروه‌بندی (جمع کل)",
owner: "کاربر / مسئول",
team: "تیم",
source: "منبع",
stage: "مرحله کاریز",
month: "ماه",
status: "وضعیت معامله",
};
export interface ReportsBuilderQuery {
@@ -3278,7 +3279,7 @@ export interface CreateSavedViewRequest {
export type UpdateSavedViewRequest = Partial<CreateSavedViewRequest>;
/* ——— API عمومی و وب‌هوک ——— */
/* ——— API عمومی و وب‌هوک ——— */
export const WEBHOOK_EVENTS = [
"person.created",
@@ -3307,7 +3308,7 @@ export interface CreateOrganizationApiKeyRequest {
}
export interface CreateOrganizationApiKeyResponse extends OrganizationApiKeyDto {
/** فقط یک‌بار هنگام ساخت برگردانده می‌شود */
/** فقط یک‌بار هنگام ساخت برگردانده می‌شود */
rawKey: string;
}
@@ -3329,7 +3330,7 @@ export interface CreateWebhookEndpointRequest {
isActive?: boolean;
}
/** فقط هنگام ساخت؛ secret دوباره برنمی‌گردد */
/** فقط هنگام ساخت؛ secret دوباره برنمی‌گردد */
export interface CreateWebhookEndpointResponse extends WebhookEndpointDto {
secret: string;
}
@@ -3347,7 +3348,7 @@ export interface WebhookDeliveryDto {
deliveredAt: string | null;
}
/* ——— پیامک گروهی ——— */
/* ——— پیامک گروهی ——— */
export type SmsCampaignStatus =
| "draft"
@@ -3375,7 +3376,7 @@ export interface CreateSmsCampaignRequest {
body: string;
personIds: string[];
scheduledAt?: string | null;
/** اگر true باشد بلافاصله صف می‌شود */
/** اگر true باشد بلافاصله صف می‌شود */
queueNow?: boolean;
}
@@ -3384,7 +3385,7 @@ export interface SmsCampaignListResponse {
total: number;
}
/* ——— تیم‌ها و سطح دسترسی به پرونده‌ها ——— */
/* ——— تیم‌ها و سطح دسترسی به پرونده‌ها ——— */
export type TeamMemberRole = "member" | "manager";
@@ -3421,7 +3422,7 @@ export interface SetTeamMembersRequest {
members: Array<{ userId: string; role: TeamMemberRole }>;
}
/* ——— ووکامرس ——— */
/* ——— ووکامرس ——— */
export interface WooCommerceConnectionDto {
id: string;
@@ -3477,7 +3478,7 @@ export interface WooCommerceOrderLinkDto {
syncedAt: string;
}
/* ——— تلفن سازمانی / VoIP ——— */
/* ——— تلفن سازمانی / VoIP ——— */
export type VoipCallDirection = "inbound" | "outbound";
@@ -3493,7 +3494,7 @@ export interface VoipConnectionDto {
label: string;
enabled: boolean;
webhookSecretSet: boolean;
/** قالب URL برای شروع تماس؛ {number} جایگزین می‌شود */
/** قالب URL برای شروع تماس؛ {number} جایگزین می‌شود */
clickToCallUrl: string | null;
lastEventAt: string | null;
lastError: string | null;
@@ -3550,7 +3551,7 @@ export interface VoipClickToCallRequest {
}
export interface VoipWebhookEvent {
/** شناسه یکتای تماس در سانترال */
/** شناسه یکتای تماس در سانترال */
callId: string;
direction: VoipCallDirection;
status: VoipCallStatus | string;
@@ -3559,16 +3560,16 @@ export interface VoipWebhookEvent {
startedAt?: string;
endedAt?: string;
durationSec?: number;
/** لینک فایل ضبط (برای خلاصه خودکار) */
/** لینک فایل ضبط (برای خلاصه خودکار) */
recordingUrl?: string;
/** متن آمادهٔ تماس؛ اگر باشد STT رد می‌شود */
/** متن آمادهٔ تماس؛ اگر باشد STT رد می‌شود */
transcript?: string;
/** برای سازگاری با فیلدهای رایج دیگر */
/** برای سازگاری با فیلدهای رایج دیگر */
caller?: string;
callee?: string;
}
/* ——— رزرو و نوبت‌دهی ——— */
/* ——— رزرو و نوبت‌دهی ——— */
export type ReservationStatus =
| "pending"
@@ -3584,10 +3585,10 @@ export const RESERVATION_STATUSES: ReservationStatus[] = [
];
export const RESERVATION_STATUS_LABELS: Record<ReservationStatus, string> = {
pending: "در انتظار",
confirmed: "تأیید شده",
canceled: "لغو شده",
done: "انجام شده",
pending: "در انتظار",
confirmed: "تأیید شده",
canceled: "لغو شده",
done: "انجام شده",
};
export interface ReservationServiceDto {
@@ -3595,7 +3596,7 @@ export interface ReservationServiceDto {
name: string;
description: string;
durationMinutes: number;
/** روزهای هفته ۰=یکشنبه … ۶=شنبه (JS getDay) */
/** روزهای هفته ۰=یکشنبه … ۶=شنبه (JS getDay) */
workDays: number[];
dayStartHour: number;
dayEndHour: number;
@@ -3663,7 +3664,7 @@ export interface ReservationListResponse {
/* ——— مدیریت لیدها ——— */
/* ——— مدیریت لیدها ——— */
export type LeadAssignRule = "round_robin" | "equal_split";