Initial Mento CRM: portal OTP, reports, SMS, and deploy for crm.montzar.ir.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,104 @@
|
||||
MENT SMART NOTES
|
||||
داکیومنت محصول — یادداشت هوشمند و حافظه مشتری
|
||||
نسخه 1.0 | مناسب برای Product، UI/UX و تیم فنی
|
||||
1. هدف قابلیت
|
||||
Smart Notes باید ثبت اطلاعات مشتری را به سریعترین و طبیعیترین بخش CRM تبدیل کند. کاربر نباید برای ثبت هر تماس، جلسه یا نکته وارد فرمهای سنگین شود؛ کافی است مثل Google Keep یک یادداشت کوتاه بنویسد. سیستم، یادداشت را به پرونده مشتری متصل و در صورت نیاز با AI به اطلاعات ساختاریافته تبدیل میکند.
|
||||
• کاهش اصطکاک ثبت اطلاعات مشتری و افزایش نرخ استفاده واقعی از CRM
|
||||
• جلوگیری از فراموششدن نکات شفاهی، قولها، حساسیتها و پیگیریها
|
||||
• تبدیل یادداشت آزاد به Task، Reminder، Tag و Insight با کمک AI
|
||||
• ساخت یک حافظه مشترک از مشتری برای کل تیم فروش
|
||||
2. تجربه اصلی کاربر
|
||||
کاربر وارد پروفایل مشتری میشود و تب «یادداشتها» را باز میکند. در بالای صفحه یک Composer ساده وجود دارد. کاربر متن، صدا یا فایل اضافه میکند و دکمه «ثبت یادداشت» را میزند. یادداشت بلافاصله در کارتهای Notes ظاهر میشود و در صورت وجود اطلاعات قابل اقدام، MENT پیشنهادهای هوشمند ارائه میدهد.
|
||||
3. انواع Note
|
||||
• یادداشت معمولی — نکته آزاد درباره مشتری
|
||||
• نتیجه تماس — خلاصه یک تماس و تصمیمات آن
|
||||
• جلسه — نکات جلسه، نیازها و اقدامات بعدی
|
||||
• نکته مهم — اطلاعاتی که باید همیشه جلوی چشم تیم باشد
|
||||
• هشدار — ریسک، نارضایتی یا موضوع حساس
|
||||
• کار بعدی — موردی که باید تبدیل به Task یا Reminder شود
|
||||
نوع Note بهتر است اجباری نباشد. کاربر میتواند آزادانه بنویسد و سیستم نوع احتمالی را تشخیص دهد؛ هدف این است که سادگی Keep حفظ شود.
|
||||
4. رفتار AI داخل Smart Notes
|
||||
AI نباید صرفاً متن را خلاصه کند؛ باید اطلاعات قابل استفاده برای فروش را استخراج کند. مثال:
|
||||
خروجی پیشنهادی MENT:
|
||||
• حساسیت: قیمت
|
||||
• علاقهمندی: پلن سالانه
|
||||
• فرد مؤثر در تصمیم: مدیر مالی
|
||||
• Next Action: تماس پیگیری
|
||||
• زمان پیگیری: پنجشنبه ساعت ۱۰
|
||||
سیستم باید برای اقدامات مهم تأیید بگیرد. AI حق ندارد بدون اطلاع کاربر، Reminder مهم، اطلاعات شخصیتی یا Memory دائمی ثبت کند.
|
||||
5. MENT Memory
|
||||
MENT Memory یک خلاصه زنده از نکات مهم و نسبتاً پایدار مشتری است. هدف این بخش این است که یک کارشناس جدید بدون خواندن دهها یادداشت بفهمد برای ارتباط با این مشتری چه چیزهایی مهم است.
|
||||
• به قیمت حساس است
|
||||
• پیامهای کوتاه را ترجیح میدهد
|
||||
• تماس تلفنی را به پیام ترجیح میدهد
|
||||
• مدیر مالی در تصمیم مؤثر است
|
||||
• علاقهمند به پلن سالانه است
|
||||
• معمولاً صبحها پاسخ میدهد
|
||||
هر Memory Item باید منبع داشته باشد: Note، تماس، جلسه یا پیام. کاربر باید بتواند آن را ویرایش، تأیید یا حذف کند.
|
||||
6. جستوجوی طبیعی در Notes
|
||||
در پایین یا بالای صفحه یک ورودی «از منتک بپرس» وجود داشته باشد. کاربر بتواند به زبان طبیعی درباره سوابق مشتری سؤال کند.
|
||||
• نمونه سؤال: «آخرین بار درباره قیمت چی گفت؟»
|
||||
• نمونه سؤال: «کی باید دوباره باهاش تماس بگیریم؟»
|
||||
• نمونه سؤال: «بیشترین دغدغه این مشتری چیه؟»
|
||||
• نمونه سؤال: «تا حالا چه قولهایی بهش دادیم؟»
|
||||
پاسخ باید همراه با تاریخ و منبع باشد تا کاربر بتواند به Note یا تماس اصلی برگردد.
|
||||
7. ساختار کارت Note
|
||||
• عنوان یا نوع Note
|
||||
• متن اصلی
|
||||
• نویسنده
|
||||
• تاریخ و ساعت
|
||||
• Tagها
|
||||
• Pin / Unpin
|
||||
• Reminder متصل
|
||||
• فایل و Voice Note
|
||||
• Deal مرتبط
|
||||
• سهنقطه: ویرایش، حذف، تبدیل به Task
|
||||
• AI Insights کوچک و غیرمزاحم
|
||||
8. MVP پیشنهادی
|
||||
9. قوانین محصول و UX
|
||||
• ثبت Note باید با حداکثر یک کلیک بعد از تایپ انجام شود.
|
||||
• فرم اجباری برای ثبت Note وجود نداشته باشد.
|
||||
• کاربر بتواند Noteهای شخصی و تیمی را در نسخههای بعدی تفکیک کند.
|
||||
• AI Suggestionها باید قابل رد کردن باشند و مزاحم جریان کار نشوند.
|
||||
• اطلاعات استخراجشده درباره شخصیت یا ترجیحات مشتری باید بهعنوان «برداشت سیستم» نمایش داده شوند، نه حقیقت قطعی.
|
||||
• تاریخچه ویرایش برای Noteهای مهم سازمانی در نسخه Enterprise نگهداری شود.
|
||||
• سطوح دسترسی Notes از Permissionهای پرونده مشتری تبعیت کند.
|
||||
10. معیارهای موفقیت
|
||||
• درصد مشتریانی که حداقل یک Note دارند
|
||||
• تعداد Note ثبتشده به ازای هر کارشناس در هفته
|
||||
• درصد Noteهایی که به Task/Reminder تبدیل میشوند
|
||||
• کاهش تعداد Follow-upهای فراموششده
|
||||
• نرخ استفاده از MENT Memory
|
||||
• نرخ پذیرش پیشنهادهای AI
|
||||
• زمان متوسط ثبت یک Note
|
||||
11. اتود رابط کاربری
|
||||
نمونه زیر جهت انتقال کانسپت است: Notes بهصورت کارتهای ساده و قابل اسکن، Composer در بالای صفحه و MENT Memory در ستون کناری.
|
||||
اتود MENT Smart Notes — مرجع اولیه برای طراحی UI/UX
|
||||
12. جمعبندی محصول
|
||||
Smart Notes نباید فقط یک بخش یادداشت در CRM باشد. ارزش واقعی آن زمانی ایجاد میشود که ثبت آزاد و سریع اطلاعات را با حافظه مشتری، پیگیری هوشمند و AI ترکیب کند. تجربه ایدهآل این است که کارشناس هر چیزی را همان لحظه ثبت کند و MENT آن را به اطلاعات قابل اقدام تبدیل کند.
|
||||
|
||||
--- TABLE 1 ---
|
||||
ایده مرکزی: «هرچی درباره مشتری میدونی، فقط بنویس؛ منتک بقیهش رو میفهمه.»
|
||||
|
||||
--- TABLE 2 ---
|
||||
مرحله | عنوان | رفتار
|
||||
1 | ثبت سریع | متن بنویسد، Voice Note بگذارد یا فایل پیوست کند.
|
||||
2 | تشخیص هوشمند | AI تاریخ، پیگیری، حساسیت، ترجیح و شخص مؤثر در تصمیم را تشخیص دهد.
|
||||
3 | پیشنهاد اقدام | مثلاً «پنجشنبه ساعت ۱۰ یادآوری بسازم؟» یا «این مورد را به Deal اضافه کنم؟»
|
||||
4 | ذخیره در Memory | نکات پایدار و مهم، پس از تأیید کاربر وارد MENT Memory شوند.
|
||||
|
||||
--- TABLE 3 ---
|
||||
«صحبت کردم. گفت قیمت یکم بالاست. تا پنجشنبه با مدیر مالی صحبت میکنه. پنجشنبه ساعت ۱۰ زنگ بزنم. بیشتر دنبال پلن یکسالهست.»
|
||||
|
||||
--- TABLE 4 ---
|
||||
اولویت | قابلیت | نسخه
|
||||
ضروری | ثبت/ویرایش/حذف Note | MVP
|
||||
ضروری | Pin کردن Note | MVP
|
||||
ضروری | Tag و جستوجو | MVP
|
||||
ضروری | اتصال Note به مشتری و Deal | MVP
|
||||
ضروری | Reminder از داخل Note | MVP
|
||||
ضروری | Activity Timeline | MVP
|
||||
پیشنهادی | استخراج تاریخ و Next Action با AI | MVP+
|
||||
پیشنهادی | MENT Memory | MVP+
|
||||
بعدی | Voice-to-Note و خلاصه تماس | V2
|
||||
بعدی | Ask MENT روی کل تاریخچه مشتری | V2
|
||||
@@ -0,0 +1,410 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Convert Persian CRM markdown docs into proper RTL Word documents."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from docx import Document
|
||||
from docx.enum.table import WD_TABLE_ALIGNMENT
|
||||
from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_LINE_SPACING
|
||||
from docx.oxml import OxmlElement
|
||||
from docx.oxml.ns import qn
|
||||
from docx.shared import Cm, Pt, RGBColor
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
|
||||
FONT = "B Nazanin"
|
||||
CODE_FONT = "Consolas"
|
||||
|
||||
NAVY = RGBColor(0x12, 0x2B, 0x4A)
|
||||
TEAL = RGBColor(0x0F, 0x5C, 0x63)
|
||||
BODY = RGBColor(0x22, 0x22, 0x22)
|
||||
MUTED = RGBColor(0x55, 0x55, 0x55)
|
||||
QUOTE_BG = "E8F3F4"
|
||||
CODE_BG = "F4F1EA"
|
||||
HEADER_BG = "122B4A"
|
||||
ROW_ALT = "F6F8FA"
|
||||
|
||||
|
||||
PRESETS = {
|
||||
"roadmap": {
|
||||
"md": "راهنما-و-نقشه-راه.md",
|
||||
"docx": "راهنما-و-نقشه-راه.docx",
|
||||
"header": "سند محصول و نقشه راه CRM",
|
||||
"footer": "راهنما و نقشه راه ساخت CRM | نسخه ۰.۵ | آمادهی شروع",
|
||||
},
|
||||
"user-guide": {
|
||||
"md": "راهنمای-کاربری.md",
|
||||
"docx": "راهنمای-کاربری.docx",
|
||||
"header": "راهنمای کاربری منتو (Mento CRM)",
|
||||
"footer": "راهنمای کاربری منتو | آموزش گامبهگام برای همه همکاران",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def ensure_child(parent, tag: str):
|
||||
el = parent.find(qn(f"w:{tag}"))
|
||||
if el is None:
|
||||
el = OxmlElement(f"w:{tag}")
|
||||
parent.append(el)
|
||||
return el
|
||||
|
||||
|
||||
def set_run_font(run, size: int, bold: bool = False, color: RGBColor | None = None, code: bool = False):
|
||||
run.bold = bold
|
||||
run.font.size = Pt(size)
|
||||
run.font.color.rgb = color or BODY
|
||||
font_name = CODE_FONT if code else FONT
|
||||
run.font.name = font_name
|
||||
|
||||
r_pr = run._r.get_or_add_rPr()
|
||||
r_fonts = ensure_child(r_pr, "rFonts")
|
||||
for attr in ("ascii", "hAnsi", "cs", "eastAsia"):
|
||||
r_fonts.set(qn(f"w:{attr}"), font_name)
|
||||
|
||||
sz_cs = ensure_child(r_pr, "szCs")
|
||||
sz_cs.set(qn("w:val"), str(size * 2))
|
||||
|
||||
if bold:
|
||||
ensure_child(r_pr, "bCs")
|
||||
|
||||
rtl = ensure_child(r_pr, "rtl")
|
||||
rtl.set(qn("w:val"), "0" if code else "1")
|
||||
|
||||
if not code:
|
||||
ensure_child(r_pr, "cs")
|
||||
|
||||
|
||||
def set_paragraph_rtl(paragraph, align=WD_ALIGN_PARAGRAPH.RIGHT, space_after=8, space_before=0):
|
||||
paragraph.paragraph_format.space_after = Pt(space_after)
|
||||
paragraph.paragraph_format.space_before = Pt(space_before)
|
||||
paragraph.paragraph_format.line_spacing_rule = WD_LINE_SPACING.MULTIPLE
|
||||
paragraph.paragraph_format.line_spacing = 1.2
|
||||
|
||||
p_pr = paragraph._p.get_or_add_pPr()
|
||||
bidi = ensure_child(p_pr, "bidi")
|
||||
bidi.set(qn("w:val"), "1")
|
||||
|
||||
if align == WD_ALIGN_PARAGRAPH.CENTER:
|
||||
jc_val = "center"
|
||||
paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
elif align == WD_ALIGN_PARAGRAPH.LEFT:
|
||||
jc_val = "left"
|
||||
paragraph.alignment = WD_ALIGN_PARAGRAPH.LEFT
|
||||
else:
|
||||
jc_val = "right"
|
||||
paragraph.alignment = WD_ALIGN_PARAGRAPH.RIGHT
|
||||
|
||||
jc = ensure_child(p_pr, "jc")
|
||||
jc.set(qn("w:val"), jc_val)
|
||||
|
||||
|
||||
def shade_paragraph(paragraph, fill: str):
|
||||
p_pr = paragraph._p.get_or_add_pPr()
|
||||
shd = ensure_child(p_pr, "shd")
|
||||
shd.set(qn("w:val"), "clear")
|
||||
shd.set(qn("w:color"), "auto")
|
||||
shd.set(qn("w:fill"), fill)
|
||||
|
||||
|
||||
def set_cell_shading(cell, fill: str):
|
||||
tc_pr = cell._tc.get_or_add_tcPr()
|
||||
shd = ensure_child(tc_pr, "shd")
|
||||
shd.set(qn("w:val"), "clear")
|
||||
shd.set(qn("w:color"), "auto")
|
||||
shd.set(qn("w:fill"), fill)
|
||||
|
||||
|
||||
def set_table_rtl(table):
|
||||
tbl = table._tbl
|
||||
tbl_pr = tbl.tblPr
|
||||
if tbl_pr is None:
|
||||
tbl_pr = OxmlElement("w:tblPr")
|
||||
tbl.insert(0, tbl_pr)
|
||||
|
||||
ensure_child(tbl_pr, "bidiVisual")
|
||||
|
||||
borders = ensure_child(tbl_pr, "tblBorders")
|
||||
for edge in ("top", "left", "bottom", "right", "insideH", "insideV"):
|
||||
el = borders.find(qn(f"w:{edge}"))
|
||||
if el is None:
|
||||
el = OxmlElement(f"w:{edge}")
|
||||
borders.append(el)
|
||||
el.set(qn("w:val"), "single")
|
||||
el.set(qn("w:sz"), "4")
|
||||
el.set(qn("w:space"), "0")
|
||||
el.set(qn("w:color"), "C5CDD6")
|
||||
|
||||
|
||||
def add_inline(paragraph, text: str, size: int = 13, color: RGBColor | None = None):
|
||||
parts = re.split(r"(\*\*[^*]+\*\*|`[^`]+`|\[[^\]]+\]\([^)]+\))", text)
|
||||
for part in parts:
|
||||
if not part:
|
||||
continue
|
||||
if part.startswith("**") and part.endswith("**"):
|
||||
run = paragraph.add_run(part[2:-2])
|
||||
set_run_font(run, size, bold=True, color=color or NAVY)
|
||||
elif part.startswith("`") and part.endswith("`"):
|
||||
run = paragraph.add_run(part[1:-1])
|
||||
set_run_font(run, max(size - 1, 9), color=TEAL, code=True)
|
||||
elif part.startswith("[") and "](" in part:
|
||||
m = re.match(r"\[([^\]]+)\]\(([^)]+)\)", part)
|
||||
label = m.group(1) if m else part
|
||||
run = paragraph.add_run(label)
|
||||
set_run_font(run, size, color=TEAL)
|
||||
run.underline = True
|
||||
else:
|
||||
run = paragraph.add_run(part)
|
||||
set_run_font(run, size, color=color)
|
||||
|
||||
|
||||
def add_heading(doc, text: str, level: int):
|
||||
sizes = {1: 26, 2: 18, 3: 15}
|
||||
colors = {1: NAVY, 2: NAVY, 3: TEAL}
|
||||
spaces = {1: (4, 14), 2: (16, 8), 3: (12, 6)}
|
||||
p = doc.add_paragraph()
|
||||
before, after = spaces[level]
|
||||
align = WD_ALIGN_PARAGRAPH.CENTER if level == 1 else WD_ALIGN_PARAGRAPH.RIGHT
|
||||
set_paragraph_rtl(p, align=align, space_before=before, space_after=after)
|
||||
run = p.add_run(text)
|
||||
set_run_font(run, sizes[level], bold=True, color=colors[level])
|
||||
|
||||
|
||||
def add_body(doc, text: str):
|
||||
p = doc.add_paragraph()
|
||||
set_paragraph_rtl(p, space_after=8)
|
||||
add_inline(p, text, 13)
|
||||
|
||||
|
||||
def add_quote(doc, text: str):
|
||||
p = doc.add_paragraph()
|
||||
set_paragraph_rtl(p, space_after=10, space_before=4)
|
||||
p.paragraph_format.right_indent = Cm(0.35)
|
||||
shade_paragraph(p, QUOTE_BG)
|
||||
add_inline(p, text, 13, color=TEAL)
|
||||
|
||||
|
||||
def add_code(doc, text: str):
|
||||
p = doc.add_paragraph()
|
||||
set_paragraph_rtl(p, align=WD_ALIGN_PARAGRAPH.LEFT, space_after=10, space_before=4)
|
||||
shade_paragraph(p, CODE_BG)
|
||||
run = p.add_run(text.strip("\n"))
|
||||
set_run_font(run, 10, color=NAVY, code=True)
|
||||
|
||||
|
||||
def add_list_item(doc, text: str, ordered: bool = False, number: int = 1):
|
||||
p = doc.add_paragraph()
|
||||
set_paragraph_rtl(p, space_after=3)
|
||||
p.paragraph_format.right_indent = Cm(0.25)
|
||||
prefix = f"{number}. " if ordered else "• "
|
||||
run = p.add_run(prefix)
|
||||
set_run_font(run, 13, bold=True, color=TEAL)
|
||||
add_inline(p, text, 13)
|
||||
|
||||
|
||||
def add_table(doc, header: list[str], rows: list[list[str]]):
|
||||
header_rtl = list(reversed(header))
|
||||
rows_rtl = [list(reversed(r)) for r in rows]
|
||||
|
||||
table = doc.add_table(rows=1 + len(rows_rtl), cols=len(header_rtl))
|
||||
table.alignment = WD_TABLE_ALIGNMENT.CENTER
|
||||
table.autofit = True
|
||||
set_table_rtl(table)
|
||||
|
||||
for i, cell_text in enumerate(header_rtl):
|
||||
cell = table.rows[0].cells[i]
|
||||
set_cell_shading(cell, HEADER_BG)
|
||||
p = cell.paragraphs[0]
|
||||
set_paragraph_rtl(p, align=WD_ALIGN_PARAGRAPH.CENTER, space_after=2, space_before=2)
|
||||
run = p.add_run(cell_text.strip())
|
||||
set_run_font(run, 11, bold=True, color=RGBColor(255, 255, 255))
|
||||
|
||||
for r_idx, row in enumerate(rows_rtl):
|
||||
for c_idx, cell_text in enumerate(row):
|
||||
if c_idx >= len(table.rows[r_idx + 1].cells):
|
||||
continue
|
||||
cell = table.rows[r_idx + 1].cells[c_idx]
|
||||
if r_idx % 2 == 1:
|
||||
set_cell_shading(cell, ROW_ALT)
|
||||
p = cell.paragraphs[0]
|
||||
set_paragraph_rtl(p, space_after=2, space_before=2)
|
||||
add_inline(p, cell_text.strip(), 11)
|
||||
|
||||
spacer = doc.add_paragraph()
|
||||
set_paragraph_rtl(spacer, space_after=8)
|
||||
|
||||
|
||||
def add_hr(doc):
|
||||
p = doc.add_paragraph()
|
||||
set_paragraph_rtl(p, space_after=8, space_before=4)
|
||||
p_pr = p._p.get_or_add_pPr()
|
||||
p_bdr = ensure_child(p_pr, "pBdr")
|
||||
bottom = ensure_child(p_bdr, "bottom")
|
||||
bottom.set(qn("w:val"), "single")
|
||||
bottom.set(qn("w:sz"), "8")
|
||||
bottom.set(qn("w:space"), "1")
|
||||
bottom.set(qn("w:color"), "C5CDD6")
|
||||
|
||||
|
||||
def configure_document(doc):
|
||||
section = doc.sections[0]
|
||||
section.page_width = Cm(21)
|
||||
section.page_height = Cm(29.7)
|
||||
section.top_margin = Cm(2)
|
||||
section.bottom_margin = Cm(2)
|
||||
section.left_margin = Cm(2)
|
||||
section.right_margin = Cm(2)
|
||||
|
||||
sect_pr = section._sectPr
|
||||
bidi = ensure_child(sect_pr, "bidi")
|
||||
bidi.set(qn("w:val"), "1")
|
||||
|
||||
style = doc.styles["Normal"]
|
||||
style.font.name = FONT
|
||||
style.font.size = Pt(13)
|
||||
|
||||
r_pr = style.element.get_or_add_rPr()
|
||||
r_fonts = ensure_child(r_pr, "rFonts")
|
||||
for attr in ("ascii", "hAnsi", "cs", "eastAsia"):
|
||||
r_fonts.set(qn(f"w:{attr}"), FONT)
|
||||
sz_cs = ensure_child(r_pr, "szCs")
|
||||
sz_cs.set(qn("w:val"), "26")
|
||||
rtl = ensure_child(r_pr, "rtl")
|
||||
rtl.set(qn("w:val"), "1")
|
||||
|
||||
p_pr = style.element.get_or_add_pPr()
|
||||
bidi_p = ensure_child(p_pr, "bidi")
|
||||
bidi_p.set(qn("w:val"), "1")
|
||||
jc = ensure_child(p_pr, "jc")
|
||||
jc.set(qn("w:val"), "right")
|
||||
|
||||
|
||||
def parse_table(lines: list[str], start: int) -> tuple[list[str], list[list[str]], int]:
|
||||
header = [c.strip() for c in lines[start].strip().strip("|").split("|")]
|
||||
rows = []
|
||||
i = start + 2
|
||||
while i < len(lines) and lines[i].strip().startswith("|"):
|
||||
rows.append([c.strip() for c in lines[i].strip().strip("|").split("|")])
|
||||
i += 1
|
||||
return header, rows, i
|
||||
|
||||
|
||||
def convert(md_path: Path, docx_path: Path, header_text: str, footer_text: str):
|
||||
if not md_path.exists():
|
||||
raise FileNotFoundError(md_path)
|
||||
|
||||
lines = md_path.read_text(encoding="utf-8").splitlines()
|
||||
doc = Document()
|
||||
configure_document(doc)
|
||||
|
||||
i = 0
|
||||
in_code = False
|
||||
code_lines: list[str] = []
|
||||
|
||||
while i < len(lines):
|
||||
line = lines[i]
|
||||
stripped = line.strip()
|
||||
|
||||
if stripped.startswith("```"):
|
||||
if in_code:
|
||||
add_code(doc, "\n".join(code_lines))
|
||||
code_lines = []
|
||||
in_code = False
|
||||
else:
|
||||
in_code = True
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if in_code:
|
||||
code_lines.append(line)
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if not stripped:
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if stripped == "---":
|
||||
add_hr(doc)
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if stripped.startswith("# "):
|
||||
add_heading(doc, stripped[2:], 1)
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if stripped.startswith("## "):
|
||||
add_heading(doc, stripped[3:], 2)
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if stripped.startswith("### "):
|
||||
add_heading(doc, stripped[4:], 3)
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if stripped.startswith("|") and i + 1 < len(lines) and re.match(r"^\|?\s*:?---", lines[i + 1].strip()):
|
||||
header, rows, i = parse_table(lines, i)
|
||||
add_table(doc, header, rows)
|
||||
continue
|
||||
|
||||
if stripped.startswith("> "):
|
||||
add_quote(doc, stripped[2:])
|
||||
i += 1
|
||||
continue
|
||||
|
||||
m_num = re.match(r"^(\d+)\.\s+(.*)$", stripped)
|
||||
if m_num:
|
||||
add_list_item(doc, m_num.group(2), ordered=True, number=int(m_num.group(1)))
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if stripped.startswith("- "):
|
||||
add_list_item(doc, stripped[2:])
|
||||
i += 1
|
||||
continue
|
||||
|
||||
add_body(doc, stripped)
|
||||
i += 1
|
||||
|
||||
header = doc.sections[0].header
|
||||
hp = header.paragraphs[0]
|
||||
set_paragraph_rtl(hp, align=WD_ALIGN_PARAGRAPH.CENTER, space_after=0)
|
||||
run = hp.add_run(header_text)
|
||||
set_run_font(run, 10, bold=True, color=NAVY)
|
||||
|
||||
footer = doc.sections[0].footer
|
||||
fp = footer.paragraphs[0]
|
||||
set_paragraph_rtl(fp, align=WD_ALIGN_PARAGRAPH.CENTER, space_after=0)
|
||||
run = fp.add_run(footer_text)
|
||||
set_run_font(run, 9, color=MUTED)
|
||||
|
||||
doc.save(docx_path)
|
||||
print("DOCX_OK")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Export Persian markdown docs to RTL DOCX")
|
||||
parser.add_argument(
|
||||
"--preset",
|
||||
choices=sorted(PRESETS.keys()),
|
||||
default="user-guide",
|
||||
help="Built-in document preset (default: user-guide)",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
preset = PRESETS[args.preset]
|
||||
convert(
|
||||
ROOT / preset["md"],
|
||||
ROOT / preset["docx"],
|
||||
preset["header"],
|
||||
preset["footer"],
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,491 @@
|
||||
# راهنمای کاربری منتو (Mento CRM)
|
||||
|
||||
نسخه راهنما: همزمان با ساخت محصول بهروز میشود.
|
||||
مخاطب: همه همکاران فروش و پشتیبانی — با یا بدون تجربه نرمافزار.
|
||||
|
||||
---
|
||||
|
||||
## این راهنما چیست؟
|
||||
|
||||
این سند به زبان ساده میگوید:
|
||||
|
||||
1. منتو چیست و به چه کار میآید
|
||||
2. چطور وارد شوید
|
||||
3. چطور مشتری (شخص / شرکت) ثبت کنید
|
||||
4. چطور معامله را در کاریز فروش جلو ببرید
|
||||
5. چطور فعالیتهای امروز و عقبافتاده را مدیریت کنید
|
||||
6. چطور یادداشت سریع (Smart Notes) ثبت کنید
|
||||
7. چطور فیلد سفارشی تعریف کنید
|
||||
8. چطور مخاطبین را از اکسل وارد یا خارج کنید
|
||||
9. چطور اعلانهای داخل برنامه را ببینید
|
||||
10. چطور تایملاین پرونده را ببینید
|
||||
|
||||
هر بخش را **به ترتیب** بخوانید. اگر تازهکارید، از «شروع خیلی ساده» شروع کنید.
|
||||
|
||||
> این راهنما با پیشرفت محصول کاملتر میشود. بخشهایی که هنوز ساخته نشدهاند با برچسب **بهزودی** مشخصاند.
|
||||
|
||||
---
|
||||
|
||||
## منتو چیست؟ (به زبان خیلی ساده)
|
||||
|
||||
تصور کنید دفترچه تماس، تخته وظایف فروش، و پیگیری مشتری را یکجا داشته باشید.
|
||||
|
||||
- **شخص**: آدم واقعی که با او حرف میزنید (مثلاً خانم محمدی)
|
||||
- **شرکت**: سازمانی که آن شخص برایش کار میکند (مثلاً شرکت آکمه)
|
||||
- **معامله / فرصت**: یک فروش احتمالی که دارید جلو میبرید
|
||||
- **کاریز فروش**: یک تخته ستونی (مثل تخته وایتبرد) که هر ستون یک مرحله فروش است؛ کارت معامله را ستونبهستون جلو میکشید
|
||||
|
||||
هدف: هیچ پیگیری گم نشود و مدیر ببیند فروش تیم در چه مرحلهای است.
|
||||
|
||||
---
|
||||
|
||||
## شروع خیلی ساده (۵ دقیقه)
|
||||
|
||||
### گام ۱ — باز کردن پنل
|
||||
|
||||
1. مرورگر را باز کنید (کروم یا اج پیشنهاد میشود).
|
||||
2. این آدرس را بنویسید: `http://localhost:5173`
|
||||
3. Enter بزنید.
|
||||
|
||||
اگر صفحه باز نشد، به مسئول فنی بگویید: «وب یا API بالا نیست.»
|
||||
|
||||
### گام ۲ — ورود
|
||||
|
||||
1. در کادر **ایمیل** بنویسید: `owner@demo.local`
|
||||
2. در کادر **رمز عبور** بنویسید: `demo1234`
|
||||
3. روی دکمه **ورود** بزنید.
|
||||
|
||||
اگر پیام «اتصال به سرور برقرار نشد» دیدید، API روی پورت ۳۰۰۰ باید روشن باشد.
|
||||
|
||||
### گام ۳ — آشنایی با منوی سمت راست/چپ
|
||||
|
||||
بعد از ورود، منو را میبینید:
|
||||
|
||||
| منو | کارش |
|
||||
|---|---|
|
||||
| خانه امروز | خلاصه وضعیت و میانبرها |
|
||||
| فعالیتها | تماس، جلسه، وظیفه و لیست امروز/عقبافتاده |
|
||||
| تقویم فعالیتها | نمای ماهانه موعدها |
|
||||
| کاریز فروش | تخته معاملات |
|
||||
| هدف و پیشبینی | تارگت ماهانه و پیشبینی ساده فروش |
|
||||
| تیکتها | پشتیبانی و پیگیری درخواست مشتری |
|
||||
| پیشفاکتورها | صدور و پیگیری پیشفاکتور |
|
||||
| فاکتورها | صدور فاکتور، پرداخت و اقساط |
|
||||
| اشخاص و شرکتها | دفترچه مخاطبین + ورود/خروج اکسل |
|
||||
| یادداشتها | ثبت سریع، پین، تگ، تبدیل به وظیفه |
|
||||
| تیم و نقشها | افزودن کاربر و تعیین نقش (فقط مالک/مدیر) |
|
||||
| فرمساز سرنخ | لینک / iframe / QR برای جذب سرنخ (فقط مالک/مدیر) |
|
||||
| فیلدهای سفارشی | تعریف فیلد اختصاصی برای شخص/شرکت/معامله (فقط مالک/مدیر) |
|
||||
| محصولات | کاتالوگ محصول/خدمت برای معامله (فقط مالک/مدیر) |
|
||||
| ارزها | ارز پایه، ارزهای فعال و نرخ تبدیل (فقط مالک/مدیر) |
|
||||
| اعلانها (پایین منو) | خبر فعالیت ارجاعشده، جابهجایی معامله، یادآور |
|
||||
|
||||
### گام ۴ — یک دور سریع تمرین
|
||||
|
||||
1. بروید به **اشخاص و شرکتها** و لیست را ببینید.
|
||||
2. بروید به **کاریز فروش** و کارتها را ببینید.
|
||||
3. یک کارت را با ماوس بگیرید و به ستون بعدی بکشید.
|
||||
4. بروید به **فعالیتها** و لیست امروز را ببینید.
|
||||
5. بروید به **یادداشتها** و یک یادداشت کوتاه ثبت کنید.
|
||||
|
||||
---
|
||||
|
||||
## ۱) ورود و خروج
|
||||
|
||||
### ورود
|
||||
|
||||
1. صفحه ورود را باز کنید.
|
||||
2. ایمیل و رمز را وارد کنید.
|
||||
3. **ورود** را بزنید.
|
||||
|
||||
### خروج
|
||||
|
||||
1. پایین منوی کناری، دکمه **خروج** را بزنید.
|
||||
2. دوباره به صفحه ورود میروید.
|
||||
|
||||
### نقشها
|
||||
|
||||
| نقش | دسترسی |
|
||||
|---|---|
|
||||
| مالک | همه چیز + مدیریت کاربران و تنظیمات + مشاهده همه پروندهها |
|
||||
| مدیر | تنظیمات و دعوت کاربر (بدون تغییر مالک) + مشاهده همه پروندهها |
|
||||
| فروش / پشتیبانی | فقط پروندهها، معاملات، فاکتورها و فعالیتهای خودشان |
|
||||
|
||||
حسابهای دمو اضافه: `admin@demo.local` و `sales@demo.local` با همان رمز `demo1234`.
|
||||
|
||||
با حساب **فروش** فقط پروندههای تخصیصیافته به همان کاربر دیده میشود؛ مالک و مدیر همه را میبینند.
|
||||
|
||||
### ثبتنام سازمان جدید
|
||||
|
||||
اگر سازمان ندارید:
|
||||
|
||||
1. روی **ثبتنام سازمان** بزنید.
|
||||
2. نام سازمان، نام خودتان، ایمیل و رمز را پر کنید.
|
||||
3. ثبت کنید؛ بعد از ثبت، وارد پنل میشوید.
|
||||
|
||||
---
|
||||
|
||||
## ۲) اشخاص و شرکتها
|
||||
|
||||
اینجا دفترچه تلفن و بانک مشتری شماست.
|
||||
|
||||
### دیدن لیست
|
||||
|
||||
1. از منو **اشخاص و شرکتها** را باز کنید.
|
||||
2. دو زبانه دارید:
|
||||
- **اشخاص**
|
||||
- **شرکتها**
|
||||
3. برای پیدا کردن کسی، در کادر جستجو نام / ایمیل / موبایل را بنویسید و **جستجو** بزنید.
|
||||
|
||||
### ثبت شخص جدید
|
||||
|
||||
1. زبانه **اشخاص** را انتخاب کنید.
|
||||
2. **شخص جدید** را بزنید.
|
||||
3. حداقل **نام** و **نام خانوادگی** را پر کنید.
|
||||
4. در صورت امکان موبایل یا ایمیل را هم بگذارید (برای جلوگیری از تکراری مفید است).
|
||||
5. اگر به شرکتی وصل است، از لیست **شرکت** انتخاب کنید.
|
||||
6. **ذخیره** را بزنید.
|
||||
|
||||
### ویرایش یا حذف شخص
|
||||
|
||||
1. در لیست، روی نام شخص کلیک کنید.
|
||||
2. اطلاعات را عوض کنید و **ذخیره** بزنید.
|
||||
3. برای حذف، **حذف** را بزنید و تأیید کنید.
|
||||
|
||||
### ثبت شرکت جدید
|
||||
|
||||
1. زبانه **شرکتها** را انتخاب کنید.
|
||||
2. **شرکت جدید** را بزنید.
|
||||
3. **نام شرکت** را وارد کنید.
|
||||
4. در صورت تمایل تلفن، ایمیل، آدرس و یادداشت را پر کنید.
|
||||
5. **ذخیره** را بزنید.
|
||||
|
||||
### نکته مهم درباره تکراری
|
||||
|
||||
سیستم جلوی ثبت دوباره با **ایمیل** یا **موبایل** یکسان (برای اشخاص) و **ایمیل / تلفن / شناسه ملی** یکسان (برای شرکتها) را میگیرد.
|
||||
اگر پیام تکراری دیدید، یعنی آن مخاطب از قبل هست؛ همان را پیدا و ویرایش کنید.
|
||||
|
||||
---
|
||||
|
||||
## ۳) کاریز فروش (معاملات)
|
||||
|
||||
کاریز مثل تخته فروش است. هر ستون یک مرحله است:
|
||||
|
||||
1. سرنخ
|
||||
2. تماس اول
|
||||
3. پیشنهاد
|
||||
4. مذاکره
|
||||
5. برنده
|
||||
6. از دسترفته
|
||||
|
||||
### دیدن کاریز
|
||||
|
||||
1. از منو **کاریز فروش** را باز کنید.
|
||||
2. از لیست **کاریز** میتوانید بین کاریزها جابهجا شوید.
|
||||
3. با **کاریز جدید** یک تخته جدا با همان مراحل پیشفرض بسازید.
|
||||
2. ستونها و کارتهای معامله را میبینید.
|
||||
3. زیر عنوان هر ستون، تعداد کارت و جمع مبلغ همان ستون نشان داده میشود.
|
||||
|
||||
### ساخت معامله جدید
|
||||
|
||||
1. روی **معامله جدید** بزنید.
|
||||
2. **عنوان معامله** را بنویسید (مثلاً «فروش بسته سازمانی آکمه»).
|
||||
3. در صورت امکان **مبلغ** را به ریال وارد کنید.
|
||||
4. شخص و/یا شرکت مرتبط را انتخاب کنید.
|
||||
5. مرحله اولیه را انتخاب کنید (معمولاً «سرنخ»).
|
||||
6. **ذخیره** را بزنید.
|
||||
|
||||
### جلو بردن معامله (کشیدن کارت)
|
||||
|
||||
1. روی کارت ماوس را نگه دارید.
|
||||
2. کارت را بگیرید و به ستون بعدی بکشید.
|
||||
3. رها کنید.
|
||||
|
||||
مثال: وقتی پیشنهاد فرستادید، کارت را از «تماس اول» به «پیشنهاد» بکشید.
|
||||
|
||||
### ویرایش معامله
|
||||
|
||||
1. روی کارت کلیک کنید.
|
||||
2. عنوان، مبلغ، شخص، شرکت، مرحله یا یادداشت را عوض کنید.
|
||||
3. در صورت نیاز **منبع آشنایی**، **برچسب** و تاریخ بستهشدن مورد انتظار را پر کنید.
|
||||
4. میتوانید از منوی **محصولات** کاتالوگ بسازید و روی معامله ردیف محصول اضافه کنید؛ مبلغ از جمع ردیفها محاسبه میشود.
|
||||
5. اگر پیگیری متوقف شده **راکد**، و اگر تقریباً از دست رفته **فاسد** را علامت بزنید.
|
||||
6. **ذخیره** را بزنید. روی کارت کاریز، برچسب و نشان راکد/فاسد دیده میشود.
|
||||
7. با **بازگشت به کاریز** به تخته برگردید.
|
||||
|
||||
### معامله برنده یا از دسترفته
|
||||
|
||||
- اگر فروش قطعی شد، کارت را به ستون **برنده** بکشید.
|
||||
- اگر معامله شکست خورد، به ستون **از دسترفته** بکشید.
|
||||
- در صفحه ویرایش میتوانید **دلیل شکست** را هم بنویسید (برای تحلیل بعدی).
|
||||
|
||||
### حذف معامله
|
||||
|
||||
1. معامله را باز کنید.
|
||||
2. **حذف** را بزنید و تأیید کنید.
|
||||
|
||||
---
|
||||
|
||||
## ۴) فعالیتها (تماس، جلسه، وظیفه)
|
||||
|
||||
فعالیت یعنی کاری که باید برای مشتری یا معامله انجام دهید.
|
||||
|
||||
### دیدن کارهای امروز
|
||||
|
||||
1. وارد **خانه امروز** شوید.
|
||||
2. بخشهای **عقبافتاده** و **امروز** را ببینید.
|
||||
3. وقتی کار تمام شد، **انجام شد** را بزنید.
|
||||
|
||||
### فهرست کامل
|
||||
|
||||
1. از منو **فعالیتها** را باز کنید.
|
||||
2. زبانهها: امروز / عقبافتاده / بعداً / انجامشده / همه
|
||||
3. با جستجو عنوان را پیدا کنید.
|
||||
4. برای نمای ماهانه، **تقویم** را بزنید (یا از منو **تقویم فعالیتها**).
|
||||
|
||||
### تقویم ماهانه
|
||||
|
||||
1. ماه را با **ماه قبل / ماه بعد** عوض کنید؛ یا **برو به امروز**.
|
||||
2. روی یک روز کلیک کنید تا فعالیتهای همان روز در پنل کناری دیده شود.
|
||||
3. **افزودن در این روز** فعالیت جدید با موعد همان روز میسازد.
|
||||
|
||||
### ثبت فعالیت جدید
|
||||
|
||||
1. **فعالیت جدید** را بزنید.
|
||||
2. عنوان را بنویسید (مثلاً «تماس پیگیری پیشنهاد»).
|
||||
3. نوع را انتخاب کنید: تماس، جلسه، وظیفه یا یادداشت.
|
||||
4. موعد را بگذارید.
|
||||
5. در صورت تمایل شخص و معامله مرتبط را انتخاب کنید.
|
||||
6. **ذخیره** را بزنید.
|
||||
|
||||
### پیشنهاد روزانه
|
||||
|
||||
1. صبح وارد شوید و خانه امروز را ببینید.
|
||||
2. عقبافتادهها را اول جمع کنید.
|
||||
3. کارهای امروز را یکییکی انجام و تیک بزنید.
|
||||
4. معاملهها را در کاریز جلو ببرید.
|
||||
5. مشتری جدید را در اشخاص ثبت کنید.
|
||||
|
||||
---
|
||||
|
||||
## ۵) یادداشتهای هوشمند (Smart Notes)
|
||||
|
||||
اینجا مثل Google Keep سریع مینویسید؛ بعداً AI و حافظه مشتری اضافه میشود.
|
||||
|
||||
### ثبت یادداشت
|
||||
|
||||
1. از منو **یادداشتها** را باز کنید.
|
||||
2. نوع را انتخاب کنید: معمولی، نتیجه تماس، جلسه، نکته مهم، هشدار یا کار بعدی.
|
||||
3. در کادر بالا متن را بنویسید (عنوان اختیاری است).
|
||||
4. در صورت نیاز، شخص، معامله، یادآوری یا برچسب اضافه کنید.
|
||||
5. با **پیوست فایل** میتوانید تصویر، PDF، Word، Excel یا ZIP اضافه کنید (حداکثر ۱۰ مگابایت).
|
||||
6. **ثبت یادداشت** را بزنید.
|
||||
|
||||
با تبهای بالای صفحه میتوانید فقط یک نوع یادداشت را ببینید.
|
||||
|
||||
روی هر کارت یادداشت هم میتوانید پیوست جدید اضافه کنید، دانلود کنید یا حذف کنید.
|
||||
|
||||
### پیوست فایل
|
||||
|
||||
- هنگام ثبت، **پیوست فایل** را بزنید (تصویر، PDF، Word، Excel، متن یا ZIP؛ حداکثر ۱۰ مگابایت).
|
||||
- روی کارت یادداشت هم میتوانید پیوست اضافه، دانلود یا حذف کنید.
|
||||
|
||||
### سنجاق، رنگ، تبدیل به وظیفه
|
||||
|
||||
- برای مهمها دکمه سنجاق را بزنید تا بالا بمانند.
|
||||
- رنگ کارت را عوض کنید تا دستهبندی بصری داشته باشید.
|
||||
- **تبدیل به وظیفه** یادداشت را به یک فعالیت در بخش فعالیتها تبدیل میکند.
|
||||
|
||||
### جستجو
|
||||
|
||||
در بالای صفحه با متن یا برچسب جستجو کنید.
|
||||
|
||||
---
|
||||
|
||||
## ۶) فیلدهای سفارشی
|
||||
|
||||
گاهی برای کسبوکار شما فیلدی لازم است که در فرم استاندارد نیست (مثلاً «صنعت» یا «کانال ترجیحی»).
|
||||
|
||||
### تعریف فیلد
|
||||
|
||||
1. از منو **فیلدهای سفارشی** را باز کنید (فقط مالک یا مدیر).
|
||||
2. عنوان، نوع (متن / عدد / تاریخ / بلهخیر / لیست)، و اینکه روی شخص / شرکت / معامله باشد را مشخص کنید.
|
||||
3. **افزودن فیلد** را بزنید.
|
||||
|
||||
### پر کردن روی پرونده
|
||||
|
||||
وقتی شخص، شرکت یا معامله را باز میکنید، بخش **فیلدهای سفارشی** زیر فرم اصلی ظاهر میشود. مقدار را وارد و ذخیره کنید.
|
||||
|
||||
---
|
||||
|
||||
## ۷) ورود و خروج اکسل مخاطبین
|
||||
|
||||
### خروجی اکسل
|
||||
|
||||
1. بروید به **اشخاص و شرکتها**.
|
||||
2. تب اشخاص یا شرکتها را انتخاب کنید.
|
||||
3. **خروجی اکسل** را بزنید؛ فایل `.xlsx` دانلود میشود.
|
||||
اگر جستجو فعال باشد، همان نتایج فیلترشده خارج میشوند.
|
||||
|
||||
### ورود از اکسل
|
||||
|
||||
1. ترجیحاً یکبار خروجی بگیرید تا قالب ستونها درست باشد.
|
||||
2. فایل را پر کنید و **ورود از اکسل** را بزنید.
|
||||
3. موارد تکراری (ایمیل/موبایل شخص یا ایمیل/تلفن/شناسه ملی شرکت) رد میشوند و بقیه ثبت میشوند.
|
||||
|
||||
---
|
||||
|
||||
## ۸) اعلانهای داخل برنامه
|
||||
|
||||
در پایین منوی کناری دکمه **اعلانها** را میبینید. اگر اعلان خواندهنشده باشد، عدد قرمز روی دکمه ظاهر میشود.
|
||||
|
||||
### دیدن اعلانها
|
||||
|
||||
1. روی **اعلانها** کلیک کنید.
|
||||
2. لیست اعلانها باز میشود (جدیدترها بالا).
|
||||
3. روی یک اعلان بزنید تا خوانده شود و در صورت داشتن لینک، به همان صفحه بروید.
|
||||
|
||||
### انواع رایج
|
||||
|
||||
- **فعالیت جدید برای شما** — وقتی فعالیتی به شما ارجاع شود
|
||||
- **جابهجایی معامله** — وقتی معاملهای که مالکتان است در کاریز جابهجا شود
|
||||
- **فعالیت عقبافتاده** / **یادآوری یادداشت** — وقتی سررسید گذشته باشد
|
||||
|
||||
### همه را خوانده علامت بزنید
|
||||
|
||||
در بالای پنل اعلانها، **همه خوانده شد** را بزنید.
|
||||
|
||||
---
|
||||
|
||||
## ۹) تایملاین پرونده
|
||||
|
||||
روی پروندهٔ ذخیرهشدهٔ **شخص**، **شرکت** یا **معامله**، پایین فرم بخش **تایملاین** را میبینید.
|
||||
|
||||
### چه چیزی نشان داده میشود؟
|
||||
|
||||
- یادداشتهای Smart Notes متصل به همان پرونده
|
||||
- فعالیتهای مرتبط (تماس، جلسه، وظیفه، …)
|
||||
|
||||
### ثبت سریع
|
||||
|
||||
1. در کادر **یادداشت سریع** بنویسید و **ثبت یادداشت** را بزنید.
|
||||
2. یا عنوان یک پیگیری را بنویسید و **افزودن فعالیت** را بزنید.
|
||||
3. برای فعالیت باز، میتوانید همانجا **انجام شد** بزنید.
|
||||
|
||||
تایملاین فقط بعد از اولین ذخیرهٔ پرونده ظاهر میشود (روی فرم «جدید» نیست).
|
||||
|
||||
---
|
||||
|
||||
## ۱۰) مشکلات رایج
|
||||
|
||||
| مشکل | کار ساده |
|
||||
|---|---|
|
||||
| ورود ناموفق / اتصال برقرار نشد | بپرسید API روشن است یا نه؛ در صورت نیاز دوباره وارد شوید |
|
||||
| مخاطب تکراری | همان مخاطب قبلی را جستجو و ویرایش کنید |
|
||||
| کارت جابهجا نمیشود | صفحه را بروزرسانی کنید؛ دوباره بکشید |
|
||||
| صفحه خالی است | از منو دوباره همان بخش را باز کنید؛ در صورت نیاز خارج و دوباره وارد شوید |
|
||||
|
||||
---
|
||||
|
||||
## ۱۰) پیشفاکتور
|
||||
|
||||
1. از منو **پیشفاکتورها** را باز کنید یا از پرونده معامله **صدور پیشفاکتور** را بزنید.
|
||||
2. عنوان، شخص/شرکت و ردیفهای محصول را پر کنید.
|
||||
3. وضعیت را (پیشنویس / ارسالشده / …) تنظیم و ذخیره کنید.
|
||||
4. برای نسخه کاغذی، **چاپ** را بزنید.
|
||||
5. در صورت تأیید، از همان پرونده **صدور فاکتور** بزنید.
|
||||
|
||||
---
|
||||
|
||||
## ۱۱) فاکتور، پرداخت و اقساط
|
||||
|
||||
1. از منو **فاکتورها** یا از معامله / پیشفاکتور **صدور فاکتور** را باز کنید.
|
||||
2. ردیفها را بررسی کنید؛ در صورت نیاز با دکمهٔ **۲ قسط** / **۳ قسط** برنامه اقساط بسازید.
|
||||
3. وضعیت را روی **صادرشده** بگذارید و ذخیره کنید.
|
||||
4. در بخش **ثبت پرداخت** مبلغ، روش و در صورت نیاز قسط مرتبط را وارد کنید.
|
||||
5. وضعیت وصول (جزئی / تسویه) بر اساس مجموع پرداختها بهروز میشود.
|
||||
|
||||
---
|
||||
|
||||
## ۱۲) فرمساز سرنخ
|
||||
|
||||
1. با حساب مالک/مدیر از منو **فرمساز سرنخ** را باز کنید.
|
||||
2. نام فرم و در صورت نیاز مسئولان توزیع نوبتی را مشخص کنید و **ساخت فرم** را بزنید.
|
||||
3. لینک عمومی، کد iframe یا QR را کپی کنید و در سایت بگذارید.
|
||||
4. هر ارسال، یک **شخص** و یک **معامله** در مرحلهٔ اول کاریز میسازد (یا شخص تکراری را بهروز میکند).
|
||||
|
||||
---
|
||||
|
||||
## ۱۳) هدف و پیشبینی فروش
|
||||
|
||||
1. از منو **هدف و پیشبینی** را باز کنید (یا کارت «فروش این ماه» در خانه).
|
||||
2. مبلغ هدف، بازه تاریخ و در صورت مالک/مدیر بودن، مخاطب هدف (سازمان یا کاربر) را مشخص کنید.
|
||||
3. **تحقق** از معاملات برندهٔ همان دوره، **کاریز باز** از معاملات باز، و **پیشبینی** = تحقق + ۴۰٪ کاریز باز محاسبه میشود.
|
||||
4. کارشناس فروش فقط اعداد پروندههای خودش را میبیند.
|
||||
|
||||
---
|
||||
|
||||
## ۱۴) ارزها
|
||||
|
||||
1. با حساب مالک/مدیر از منو **ارزها** را باز کنید.
|
||||
2. ارز پایه (مثلاً ریال) و ارزهای فعال را انتخاب کنید.
|
||||
3. برای هر ارز خارجی، نرخ به ارز پایه را وارد کنید (۱ دلار = چند ریال).
|
||||
4. در معامله، پیشفاکتور، فاکتور و محصول میتوانید ارز را عوض کنید.
|
||||
5. جمع ستونهای کاریز و پیشبینی فروش بر اساس ارز پایه محاسبه میشود.
|
||||
|
||||
---
|
||||
|
||||
## ۱۵) تیکت پشتیبانی
|
||||
|
||||
1. از منو **تیکتها** را باز کنید و **تیکت جدید** بزنید.
|
||||
2. موضوع، اولویت، شخص/شرکت و در صورت نیاز مسئول را مشخص کنید.
|
||||
3. وضعیت را (باز / در حال رسیدگی / …) بهروز کنید.
|
||||
4. در بخش گفتگو پاسخ بفرستید؛ برای یادداشت تیمی، **یادداشت داخلی** را بزنید.
|
||||
5. کارشناس فروش/پشتیبانی فقط تیکتهایی را میبیند که مسئول یا ثبتکنندهٔ آنهاست.
|
||||
6. مهلت پاسخ اول (SLA) بر اساس اولویت تنظیم میشود؛ فیلتر «فقط تأخیر SLA» در لیست موجود است.
|
||||
7. بعد از حل/بستن تیکت میتوانید امتیاز رضایت (CSAT) ۱ تا ۵ ثبت کنید.
|
||||
8. مقالات FAQ از **تنظیمات → FAQ** مدیریت میشوند و هنگام ساخت تیکت جدید پیشنهاد میشوند.
|
||||
|
||||
---
|
||||
|
||||
## ۱۶) پرتال مشتری (OTP)
|
||||
|
||||
1. آدرس عمومی: `/p/demo-mento` (بهجای `demo-mento` اسلاگ سازمان خودتان).
|
||||
2. مشتری موبایل را وارد میکند و کد تأیید پیامکی میگیرد. در توسعهٔ لوکال ممکن است کد روی صفحه هم دیده شود.
|
||||
3. بعد از ورود میتواند FAQ ببیند، تیکت بسازد، گفتگو کند و پس از حل، رضایت بدهد.
|
||||
4. یادداشتهای داخلی تیم در پرتال دیده نمیشوند.
|
||||
5. آدرس عمومی روی سرور: `https://crm.montzar.ir/p/demo-mento`
|
||||
|
||||
---
|
||||
|
||||
## ۱۷) گزارشات و داشبورد
|
||||
|
||||
1. از منو **گزارشات** را باز کنید.
|
||||
2. بازه تاریخ را انتخاب و **اعمال** بزنید.
|
||||
3. KPI فروش، قیف باز، فعالیتها، عملکرد تیم و وضعیت تیکت/CSAT را یکجا میبینید.
|
||||
4. لینک پرتال مشتری سازمان هم در همین صفحه هست.
|
||||
|
||||
---
|
||||
|
||||
## ۱۸) بخشهای بعدی (بهزودی)
|
||||
|
||||
اینها در راهنما اضافه میشوند وقتی ساخته شدند:
|
||||
|
||||
- پیشنهاد AI داخل یادداشت و Mento Memory
|
||||
- Ask Mento
|
||||
- کاریز پروژه / باشگاه مشتریان
|
||||
- اتوماسیون اگر/آنگاه
|
||||
|
||||
---
|
||||
|
||||
## برای مسئول فنی (کوتاه)
|
||||
|
||||
- پنل: `npm run dev:web` → `http://localhost:5173`
|
||||
- API: `npm run dev:api` → `http://localhost:3000/api`
|
||||
- حساب دمو: `owner@demo.local` / `demo1234`
|
||||
- پرتال دمو: `http://localhost:5173/p/demo-mento` با موبایل `09121234567`
|
||||
- نقشه راه محصول: `docs/راهنما-و-نقشه-راه.md`
|
||||
|
||||
---
|
||||
|
||||
**یادآوری:** این راهنما زنده است. با هر قابلیت جدید، همین فایل بهروز میشود تا همیشه با نرمافزار واقعی یکی باشد.
|
||||
Binary file not shown.
@@ -0,0 +1,148 @@
|
||||
# وضعیت پیشرفت منتو (Mento CRM)
|
||||
|
||||
سند زندهٔ کارها — با هر قابلیت جدید همین فایل بهروز میشود.
|
||||
آخرین بهروزرسانی: ۸ شهریور ۱۴۰۵
|
||||
|
||||
**راهنما:**
|
||||
- `[x]` انجام شده
|
||||
- `[ ]` انجام نشده / ناقص
|
||||
- وقتی موردی تمام میشود: تیک میخورد و تاریخ در بخش «تغییرات اخیر» ثبت میشود.
|
||||
|
||||
---
|
||||
|
||||
## تغییرات اخیر
|
||||
|
||||
| تاریخ | مورد |
|
||||
|---|---|
|
||||
| ۱۴۰۵/۶/۷ | پرتال مشتری OTP + گزارشات و داشبورد |
|
||||
| ۱۴۰۵/۶/۷ | SLA + FAQ + CSAT روی تیکت |
|
||||
| ۱۴۰۵/۶/۷ | تیکتینگ پایه (لیست/فرم/گفتگو/ارجاع) |
|
||||
| ۱۴۰۵/۶/۷ | چندارزی واقعی (ارز پایه، نرخ، انتخاب روی معامله/فاکتور) |
|
||||
| ۱۴۰۵/۶/۷ | هدفگذاری و پیشبینی فروش پایه |
|
||||
| ۱۴۰۵/۶/۷ | سطح دسترسی پروندهای (مالک/مدیر همه؛ فروش/پشتیبانی فقط مالکیت خود) |
|
||||
| ۱۴۰۵/۶/۷ | فاکتور / پرداخت / اقساط ساده |
|
||||
| ۱۴۰۵/۶/۸ | پیشفاکتور (لیست/فرم، از معامله، چاپ ساده) |
|
||||
| ۱۴۰۵/۶/۸ | فرمساز سرنخ (لینک / iframe / QR + ثبت شخص و معامله + round-robin) |
|
||||
| ۱۴۰۵/۶/۸ | نقش و دسترسی سازمانی سبک (تیم، RolesGuard، تنظیمات فقط مالک/مدیر) |
|
||||
| ۱۴۰۵/۶/۸ | پیوست فایل روی Note (آپلود/دانلود/حذف؛ ذخیره محلی) |
|
||||
| ۱۴۰۵/۶/۵ | انواع Note (معمولی، نتیجه تماس، جلسه، نکته مهم، هشدار، کار بعدی) |
|
||||
| ۱۴۰۵/۶/۵ | چند کاریز فروش (انتخاب + ساخت) |
|
||||
| ۱۴۰۵/۶/۵ | تقویم فعالیتها (شمسی) |
|
||||
| ۱۴۰۵/۶/۵ | تایملاین پرونده شخص/شرکت/معامله |
|
||||
| ۱۴۰۵/۶/۵ | نوتیفیکیشن داخل برنامه |
|
||||
| ۱۴۰۵/۶/۵ | ریسپانسیو موبایل (منو + صفحات اصلی) |
|
||||
| ۱۴۰۵/۶/۵ | محصول/خدمت روی معامله |
|
||||
| ۱۴۰۵/۶/۵ | غنیسازی معامله، اکسل مخاطبین، فیلد سفارشی، Smart Notes پایه |
|
||||
|
||||
---
|
||||
|
||||
## ۱-الف — هسته فروش
|
||||
|
||||
| وضعیت | مورد | توضیح |
|
||||
|---|---|---|
|
||||
| [x] | ورود / نشست / سازمان | حساب دمو و JWT |
|
||||
| [x] | اشخاص و شرکتها | جستجو + جلوگیری از تکراری |
|
||||
| [x] | فیلد سفارشی | تعریف + مقدار روی شخص/شرکت/معامله |
|
||||
| [x] | کاریز کانبان | کشیدن معامله بین مراحل |
|
||||
| [x] | چند کاریز | انتخاب کاریز + ساخت کاریز جدید |
|
||||
| [x] | غنیسازی معامله | منبع، دلیل شکست، برچسب، راکد/فاسد |
|
||||
| [x] | محصول/خدمت روی معامله | کاتالوگ + ردیف + جمع مبلغ |
|
||||
| [x] | فعالیتها | امروز / عقبافتاده / لیست و فرم |
|
||||
| [x] | تقویم فعالیتها | نمای ماهانه شمسی |
|
||||
| [x] | ایمپورت/اکسپورت اکسل | اشخاص و شرکتها |
|
||||
| [x] | نوتیفیکیشن داخل برنامه | زنگ، خوانده/نخوانده، رویدادها |
|
||||
| [x] | تایملاین پرونده | یادداشت + فعالیت روی شخص/شرکت/معامله |
|
||||
| [x] | ریسپانسیو موبایل | منوی کشویی + صفحات اصلی |
|
||||
| [x] | نقش و دسترسی سازمانی | مالک/مدیر/فروش/پشتیبانی؛ صفحه تیم؛ گارد تنظیمات |
|
||||
| [x] | سطح دسترسی پروندهای | فروش/پشتیبانی فقط پروندههای خود؛ مالک/مدیر همه |
|
||||
| [x] | چندارزی واقعی | ارز پایه سازمان، نرخ تبدیل، انتخاب ارز روی معامله/پیشفاکتور/فاکتور/محصول |
|
||||
|
||||
**جمع ۱-الف:** کامل از نظر چکلیست فعلی.
|
||||
|
||||
---
|
||||
|
||||
## ۱-ب — Smart Notes کامل
|
||||
|
||||
| وضعیت | مورد | توضیح |
|
||||
|---|---|---|
|
||||
| [x] | Composer سریع شبیه Keep | ثبت بدون فرم سنگین |
|
||||
| [x] | Pin / Tag / Reminder | پایه آماده است |
|
||||
| [x] | اتصال به شخص/شرکت/معامله | |
|
||||
| [x] | تبدیل Note به Task | |
|
||||
| [x] | تایملاین یکپارچه (پایه) | روی پروندهها |
|
||||
| [x] | انواع Note | معمولی، نتیجه تماس، جلسه، نکته مهم، هشدار، کار بعدی |
|
||||
| [x] | پیوست فایل روی Note | ذخیره محلی (`uploads/`)؛ آماده ارتقا به MinIO/S3 |
|
||||
| [ ] | AI: استخراج Next Action | با تأیید کاربر |
|
||||
| [ ] | پیشنهاد اقدام هوشمند | یادآور/فعالیت با تأیید |
|
||||
| [ ] | Mento Memory با منبع | خلاصه پایدار مشتری |
|
||||
| [ ] | ویرایش/حذف Memory Item | |
|
||||
| [ ] | Voice-to-Note / خلاصه تماس | فاز بعدتر |
|
||||
| [ ] | Ask Mento | پرسش زبان طبیعی |
|
||||
| [ ] | Note شخصی در برابر تیمی | |
|
||||
| [ ] | تاریخچه ویرایش Note | |
|
||||
|
||||
---
|
||||
|
||||
## ۱-ج — سرنخ و مالی سبک
|
||||
|
||||
| وضعیت | مورد |
|
||||
|---|---|
|
||||
| [x] | فرمساز سرنخ + لینک / iframe / QR | ثبت شخص+معامله؛ توزیع نوبتی مسئول |
|
||||
| [x] | توزیع round-robin | داخل فرمساز سرنخ |
|
||||
| [x] | پیشفاکتور | لیست/فرم، ساخت از معامله، چاپ |
|
||||
| [x] | فاکتور / پرداخت / اقساط ساده | صدور از معامله/پیشفاکتور، ثبت پرداخت، برنامه اقساط |
|
||||
| [x] | هدفگذاری و پیشبینی فروش پایه | هدف ماهانه + تحقق/کاریز/پیشبینی ساده روی خانه |
|
||||
|
||||
---
|
||||
|
||||
## ۱-د — پسازفروش و پروژه
|
||||
|
||||
| وضعیت | مورد |
|
||||
|---|---|
|
||||
| [x] | تیکتینگ | لیست/فرم، گفتگو، ارجاع، وضعیت و اولویت؛ ACL مسئول/ثبتکننده |
|
||||
| [x] | پرتال مشتری OTP | ورود موبایل+کد؛ FAQ؛ تیکت/گفتگو/CSAT در `/p/:slug`؛ SMS ترِز مثل مونتایم |
|
||||
| [x] | SLA + FAQ + CSAT | مهلت پاسخ اول، فیلتر تأخیر، FAQ در تنظیمات، رضایت ۱–۵ بعد از حل |
|
||||
| [ ] | کاریز کارت / پروژه سبک |
|
||||
| [ ] | باشگاه مشتریان ساده |
|
||||
|
||||
---
|
||||
|
||||
## ۱-هـ — گزارش، اتوماسیون، API، اتصال
|
||||
|
||||
| وضعیت | مورد |
|
||||
|---|---|
|
||||
| [x] | گزارشات و داشبوردها | داشبورد یکصفحهای: فروش/قیف/فعالیت/تیم/تیکت با فیلتر تاریخ |
|
||||
| [ ] | اتوماسیون اگر/آنگاه |
|
||||
| [ ] | API عمومی و وبهوک |
|
||||
| [ ] | پنل پیامکی |
|
||||
| [ ] | درگاه پرداخت |
|
||||
| [ ] | زیرساخت VoIP / ووکامرس / حسابداری |
|
||||
|
||||
---
|
||||
|
||||
## عمداً عقبافتاده (تصمیم محصول)
|
||||
|
||||
| وضعیت | مورد | یادداشت |
|
||||
|---|---|---|
|
||||
| [ ] | `platform_admin` SaaS | فقط وقتی فروش حساب چندمستأجری شروع شود؛ با `owner` سازمانی اشتباه نشود |
|
||||
| [ ] | اپ بومی اندروید/iOS | بیرون فاز ۱ |
|
||||
| [ ] | حسابداری کامل / انبار | CRM نباید ERP شود |
|
||||
| [ ] | لندینگ Nuxt جدا | بعد از ثبات محصول |
|
||||
|
||||
---
|
||||
|
||||
## گام بعدی پیشنهادی
|
||||
|
||||
ترتیب پیشنهادی برای ادامه:
|
||||
|
||||
1. کاریز کارت / پروژه سبک یا باشگاه مشتریان
|
||||
2. اتوماسیون اگر/آنگاه
|
||||
3. Smart Notes AI / Memory وقتی کلید مدل مشخص شد
|
||||
4. ارتقای ذخیره فایل به MinIO در صورت نیاز استقرار
|
||||
---
|
||||
|
||||
## لینکهای مرتبط
|
||||
|
||||
- نقشه راه کامل: [`docs/راهنما-و-نقشه-راه.md`](راهنما-و-نقشه-راه.md)
|
||||
- راهنمای کاربری: [`docs/راهنمای-کاربری.md`](راهنمای-کاربری.md)
|
||||
- خلاصه در ریشه: [`README.md`](../README.md)
|
||||
Reference in New Issue
Block a user