Notes و Tasks — یادداشت شخصی + تسک مرحله‌ای

دو سیستم جدا برای کار روزمره تیم: Notes فقط برای خود کاربر است (مثل to-do شخصی)، و Tasks تسک تیمی است که می‌تواند بین چند نفر جابه‌جا شود و همه مراحلش رصد شود.


خیلی ساده:
Notes = یادداشت شخصی برای امروز / فردا / هر تاریخ → تیک انجام شد.
Tasks = تسک تیمی با اولویت و مهلت → ارجاع مرحله‌به‌مرحله → نوتیف + رصد کامل.
همه APIها نیاز به JWT دارند: Authorization: Bearer <access_token>

بخش ۱ — Notes (یادداشت شخصی)

داستان Notes
  1. کاربر وارد پنل خودش می‌شود.
  2. برای امروز، فردا یا هر تاریخی که خواست یک یادداشت ثبت می‌کند.
  3. می‌تواند اولویت بدهد (کم / متوسط / زیاد).
  4. بعداً وضعیتش را عوض می‌کند: انجام نشده / انجام شده / لغو شده.
  5. فقط خودش یادداشت‌های خودش را می‌بیند (خصوصی).
فیلدهای یادداشت
<
فیلدنوعاجباری؟توضیح
idintخواندنیشناسه یادداشت
titlestring (حداکثر ۲۰۰)بلهعنوان کوتاه
bodystringخیرمتن توضیحی
note_datedate (YYYY-MM-DD)بلهتاریخی که این یادداشت برایش است
note_timetime (HH:MM:SS)خیرساعت اختیاری همان روز
statusstringخیر (پیش‌فرض todo)todo | done | cancelled
priorityintخیر (پیش‌فرض 2)1=کم، 2=متوسط، 3=زیاد
created_atdatetimeخواندنیزمان ساخت
updated_atdatetimeخواندنیآخرین ویرایش
done_atdatetime | nullخواندنیوقتی status به done برود خودکار پر می‌شود

اگر status را از done برگردانید، done_at پاک می‌شود.

جدول اندپوینت‌های Notes
کارمتد + آدرسدسترسی
لیست یادداشت‌های منGET /notes/کاربر لاگین‌شده (فقط مال خودش)
ساخت یادداشتPOST /notes/کاربر لاگین‌شده
جزئیات یک یادداشتGET /notes/<id>/صاحب یادداشت
ویرایش یادداشتPUT/PATCH /notes/<id>/صاحب یادداشت
حذف یادداشتDELETE /notes/<id>/صاحب یادداشت
اعداد badge پنلGET /notes/badge/کاربر لاگین‌شده
۱) لیست یادداشت‌ها
GET /notes/
GET /notes/?date=2026-07-09
GET /notes/?status=todo
GET /notes/?date=2026-07-09&status=done

Query params:

  • date — تاریخ هدف (YYYY-MM-DD)
  • status — todo | done | cancelled

نمونه پاسخ:

{
  "count": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": 11,
      "title": "تماس با مالک خیابان فرشته",
      "body": "ساعت ۱۱ صبح",
      "note_date": "2026-07-09",
      "note_time": "11:00:00",
      "status": "todo",
      "priority": 3,
      "created_at": "2026-07-08T14:20:00+00:00",
      "updated_at": "2026-07-08T14:20:00+00:00",
      "done_at": null
    },
    {
      "id": 10,
      "title": "چک لیست فایل‌های امروز",
      "body": "",
      "note_date": "2026-07-09",
      "note_time": null,
      "status": "done",
      "priority": 2,
      "created_at": "2026-07-08T13:00:00+00:00",
      "updated_at": "2026-07-08T15:10:00+00:00",
      "done_at": "2026-07-08T15:10:00+00:00"
    }
  ]
}
۲) ساخت یادداشت
POST /notes/
Content-Type: application/json
{
  "title": "پیگیری فایل نیاوران",
  "body": "با مشاور هماهنگ کنم برای کارشناسی",
  "note_date": "2026-07-09",
  "note_time": "10:30:00",
  "priority": 3,
  "status": "todo"
}

حداقل فیلدها:

{
  "title": "یادداشت فردا",
  "note_date": "2026-07-10"
}

نمونه پاسخ موفق (201):

{
  "id": 12,
  "title": "پیگیری فایل نیاوران",
  "body": "با مشاور هماهنگ کنم برای کارشناسی",
  "note_date": "2026-07-09",
  "note_time": "10:30:00",
  "status": "todo",
  "priority": 3,
  "created_at": "2026-07-08T14:30:00+00:00",
  "updated_at": "2026-07-08T14:30:00+00:00",
  "done_at": null
}
۳) ویرایش / انجام‌شده کردن
PATCH /notes/12/
Content-Type: application/json
{
  "status": "done"
}

یا ویرایش کامل‌تر:

{
  "title": "پیگیری فایل نیاوران — انجام شد",
  "body": "ساعت ۱۰:۴۵ تماس گرفتم",
  "status": "done",
  "priority": 2
}

برای برگرداندن به انجام‌نشده:

{
  "status": "todo"
}
۴) حذف یادداشت
DELETE /notes/12/

پاسخ موفق معمولاً 204 No Content است.

۵) جزئیات یک یادداشت
GET /notes/12/

همان آبجکت تکی یادداشت برمی‌گردد. اگر مال کاربر دیگری باشد، پیدا نمی‌شود (404).

۶) Badge Notes برای فرانت
GET /notes/badge/
{
  "today_total": 5,
  "today_todo": 3,
  "today_done": 2,
  "overdue": 1
}
  • today_total — کل یادداشت‌های امروز
  • today_todo — انجام‌نشده‌های امروز
  • today_done — انجام‌شده‌های امروز
  • overdue — یادداشت‌های قبل از امروز که هنوز todo هستند
پیشنهاد صفحات فرانت — Notes
  1. To-Do امروز ← GET /notes/?date=امروز + badge
  2. تقویم / تاریخ دلخواه ← انتخاب تاریخ → ?date=...
  3. افزودن سریع ← مودال ساده با title + note_date
  4. تیک انجام شد ← PATCH با status: "done"

بخش ۲ — Tasks (تسک مرحله‌ای و قابل ارجاع)

داستان Tasks (مثل سناریوی واقعی)
  1. سیستم‌منیجر تسک می‌سازد: «مالک تماس گرفته، منشی اطلاعاتش را بررسی کن.»
  2. منشی تسک را می‌بیند، بررسی می‌کند، سپس با handover به یک مشاور ارجاع می‌دهد.
  3. مشاور کار میدانی را انجام می‌دهد و وضعیت را عوض می‌کند / کامنت می‌گذارد.
  4. هر بار ارجاع یا تغییر وضعیت داخل transitions لاگ می‌شود.
  5. سازنده تسک همیشه می‌تواند همه مراحل را ببیند.
  6. سیستم‌منیجر همه تسک‌ها را می‌بیند (چه خودش ساخته، چه دیگران).
Notes خصوصی است و فقط مال خود کاربر است. Tasks تیمی است و بین افراد جابه‌جا می‌شود.
فیلدهای تسک
فیلدنوعاجباری؟توضیح
idintخواندنیشناسه تسک
titlestringبلهعنوان تسک
descriptionstringخیرتوضیح کامل کار
priorityintخیر (پیش‌فرض 2)1 کم · 2 متوسط · 3 زیاد · 4 فوری
statusstringسیستمopen | in_progress | waiting | done | cancelled
creatorintخواندنیآیدی سازنده
creator_namestringخواندنینام سازنده
current_assigneeint | nullخیرکاربر فعلی مسئول تسک
current_assignee_namestring | nullخواندنینام مسئول فعلی
due_atdatetime | nullخیرمهلت مطلق
due_in_minutesintفقط در ساختمثلاً ۶۰ = یک ساعت بعد از الان (جایگزین due_at)
is_overdueboolخواندنیآیا مهلت گذشته و هنوز done نشده؟
remaining_secondsint | nullخواندنیثانیه باقی‌مانده تا مهلت (منفی = گذشته)
transitionsarrayخواندنیتاریخچه کامل مراحل / ارجاع‌ها
commentsarrayخواندنیکامنت‌های تسک
done_atdatetime | nullخواندنیزمان انجام شدن
created_at / updated_atdatetimeخواندنیزمان ساخت / ویرایش
وضعیت‌ها و اولویت‌ها
statusمعنیپیشنهاد UI
openساخته شده، هنوز جدی شروع نشدهخاکستری / آبی روشن
in_progressدر حال انجام (بعد از اولین ارجاع معمولاً این می‌شود)آبی
waitingمنتظر پاسخ/اطلاعات دیگراننارنجی
doneانجام شدسبز
cancelledلغوقرمز کمرنگ
priorityبرچسب
1کم
2متوسط
3زیاد
4فوری
چه کسی چه چیزی را می‌بیند؟
نقشلیستجزئیات / رصد مراحلارجاع / وضعیت / کامنت
سیستم‌منیجر / ادمین همه تسک‌ها (با mode غیر از mine) همه بله
سازنده تسک تسک‌هایی که ساخته (mode=created) بله — حتی بعد از ارجاع بله
مسئول فعلی (assignee) تسک‌های تخصیص‌داده‌شده (mode=mine) بله بله
دیگران نه نه نه (403)
جدول اندپوینت‌های Tasks
کارمتد + آدرسدسترسی
لیست تسک‌هاGET /tasks/لاگین‌شده (با فیلتر role/mode)
ساخت تسکPOST /tasks/لاگین‌شده (منیجر / staff / مشاور)
جزئیات + transitions + commentsGET /tasks/<id>/سازنده یا مسئول فعلی یا ادمین
ارجاع مرحله‌ایPOST /tasks/<id>/handover/سازنده یا مسئول فعلی یا ادمین
تغییر وضعیتPOST /tasks/<id>/status/سازنده یا مسئول فعلی یا ادمین
افزودن کامنتPOST /tasks/<id>/comments/سازنده یا مسئول فعلی یا ادمین
badgeGET /tasks/badge/لاگین‌شده
۱) لیست تسک‌ها
GET /tasks/
GET /tasks/?mode=mine
GET /tasks/?mode=created
GET /tasks/?mode=all
  • mode=mine (پیش‌فرض): تسک‌هایی که الان مسئولش من هستم
  • mode=created: تسک‌هایی که خودم ساخته‌ام (برای رصد)
  • mode=all:
    • برای ادمین: همه تسک‌های سیستم
    • برای staff/agent: اتحاد تسک‌های ساخته‌شده یا تخصیص‌داده‌شده به خودش

برای سیستم‌منیجر، اگر mode چیزی غیر از mine باشد، همه تسک‌ها برمی‌گردد.

۲) ساخت تسک
POST /tasks/
Content-Type: application/json

نمونه با مهلت نسبی (یک ساعت بعد):

{
  "title": "بررسی تماس مالک جدید",
  "description": "مالک تماس گرفته؛ اطلاعات اولیه‌اش را کامل کنید و نتیجه را ثبت کنید.",
  "priority": 3,
  "current_assignee": 12,
  "due_in_minutes": 60
}

نمونه با مهلت مطلق:

{
  "title": "کارشناسی ملک نیاوران",
  "description": "رفتن به ملک و آماده‌سازی گزارش",
  "priority": 4,
  "current_assignee": 21,
  "due_at": "2026-07-09T18:00:00+03:30"
}

اگر هر دو بفرستید، due_in_minutes اولویت دارد و due_at را بازنویسی می‌کند.

نمونه پاسخ (201):

{
  "id": 15,
  "title": "بررسی تماس مالک جدید",
  "description": "مالک تماس گرفته؛ اطلاعات اولیه‌اش را کامل کنید و نتیجه را ثبت کنید.",
  "priority": 3,
  "status": "open",
  "creator": 1,
  "creator_name": "سیستم منیجر",
  "current_assignee": 12,
  "current_assignee_name": "منشی پذیرش",
  "due_at": "2026-07-08T15:30:00+00:00",
  "created_at": "2026-07-08T14:30:00+00:00",
  "updated_at": "2026-07-08T14:30:00+00:00",
  "done_at": null,
  "is_overdue": false,
  "remaining_seconds": 3600,
  "transitions": [
    {
      "id": 1,
      "action": "created",
      "note": "تسک ایجاد شد",
      "from_user": null,
      "to_user": 12,
      "from_user_name": null,
      "to_user_name": "منشی پذیرش",
      "acted_by": 1,
      "acted_by_name": "سیستم منیجر",
      "created_at": "2026-07-08T14:30:00+00:00"
    }
  ],
  "comments": []
}

همزمان یک نوتیف برای assignee ساخته می‌شود: «تسک جدید دارید».

۳) جزئیات تسک (رصد کامل مراحل)
GET /tasks/15/

فرانت برای صفحه جزئیات همین را صدا می‌زند. آرایه transitions خط زمانی کار است (مثل ورک‌لاین): چه کسی چه موقع به چه کسی ارجاع داد و چه نظری گذاشت.

{
  "id": 15,
  "title": "بررسی تماس مالک جدید",
  "status": "in_progress",
  "priority": 3,
  "creator_name": "سیستم منیجر",
  "current_assignee_name": "مشاور نیاوران",
  "is_overdue": false,
  "remaining_seconds": 1800,
  "transitions": [
    {
      "action": "created",
      "from_user_name": null,
      "to_user_name": "منشی پذیرش",
      "acted_by_name": "سیستم منیجر",
      "note": "تسک ایجاد شد",
      "created_at": "2026-07-08T14:30:00+00:00"
    },
    {
      "action": "handover",
      "from_user_name": "منشی پذیرش",
      "to_user_name": "مشاور نیاوران",
      "acted_by_name": "منشی پذیرش",
      "note": "بررسی اولیه انجام شد؛ لطفا کارشناسی میدانی",
      "created_at": "2026-07-08T14:50:00+00:00"
    }
  ],
  "comments": [
    {
      "id": 3,
      "author": 12,
      "author_name": "منشی پذیرش",
      "text": "شماره مالک و آدرس ثبت شد.",
      "created_at": "2026-07-08T14:45:00+00:00"
    }
  ]
}
۴) ارجاع مرحله‌ای (مهم‌ترین قابلیت)
POST /tasks/15/handover/
Content-Type: application/json
{
  "to_user": 21,
  "note": "بررسی اولیه انجام شد؛ لطفا بروید کارشناسی میدانی کنید"
}
  • to_user اجباری است (آیدی کاربر مقصد).
  • note اختیاری ولی خیلی توصیه می‌شود (توضیح مرحله).
  • اگر تسک هنوز open باشد، بعد از handover خودکار in_progress می‌شود.
  • یک رکورد transitions با action=handover ساخته می‌شود.
  • به کاربر مقصد نوتیف می‌رود: «تسک به شما ارجاع شد».

خطاها:

  • 400 — بدون to_user
  • 403 — نه سازنده هستید، نه مسئول فعلی، نه ادمین
۵) تغییر وضعیت
POST /tasks/15/status/
Content-Type: application/json
{
  "status": "done",
  "note": "کارشناسی تمام شد و گزارش در سیستم ثبت شد"
}

مقادیر مجاز status:

  • open
  • in_progress
  • waiting
  • done
  • cancelled

رفتار سیستم:

  • وقتی done شود، done_at پر می‌شود.
  • اگر از done به وضعیت دیگر برگردد، done_at پاک می‌شود.
  • یک transition با action مثل status:done ثبت می‌شود.

نمونه «منتظر اطلاعات»:

{
  "status": "waiting",
  "note": "منتظر مدارک مالک هستم"
}
۶) کامنت روی تسک
POST /tasks/15/comments/
Content-Type: application/json
{
  "text": "ساعت ۱۶ با مالک هماهنگ شدیم. فردا ساعت ۹ کارشناسی انجام می‌شود."
}

پاسخ (201):

{
  "id": 4,
  "author": 21,
  "author_name": "مشاور نیاوران",
  "text": "ساعت ۱۶ با مالک هماهنگ شدیم. فردا ساعت ۹ کارشناسی انجام می‌شود.",
  "created_at": "2026-07-08T15:05:00+00:00"
}

کامنت‌ها در جزئیات تسک (`GET /tasks/15/`) داخل آرایه comments هم دیده می‌شوند.

۷) Badge Tasks برای فرانت
GET /tasks/badge/
{
  "my_open": 4,
  "my_overdue": 1,
  "created_by_me_open": 2,
  "unread_notifications": 3
}
  • my_open — تسک‌هایی که الان مسئولش منم و هنوز done نیستند
  • my_overdue — از بین همان‌ها، مهلت‌گذشته‌ها
  • created_by_me_open — تسک‌هایی که خودم ساخته‌ام و هنوز بازند
  • unread_notifications — تعداد نوتیف خوانده‌نشده

نکته مهم: صدا زدن همین badge باعث می‌شود یادآوری‌های مهلت نزدیک/overdue برای تسک‌های من ساخته شوند (با dedupe تا اسپم نشود).


بخش ۳ — نوتیفیکیشن‌های مرتبط با Tasks

نوتیف‌ها در اپ جدا Notifications ذخیره می‌شوند. فرانت زنگوله را از آنجا می‌خواند.

اندپوینت‌های نوتیف
کارآدرس
لیست اعلان‌های منGET /notifications/
فقط خوانده‌نشده‌هاGET /notifications/?unread=1
عدد badgeGET /notifications/unread-count/
خوانده شدن یکیPOST /notifications/<id>/read/
خواندن همهPOST /notifications/mark-all-read/
چه وقت نوتیف تسک ساخته می‌شود؟
رویدادعنوانkindلینک
ساخت تسک با assigneeتسک جدید داریدinfo/tasks/<id>/
ارجاع (handover)تسک به شما ارجاع شدinfo/tasks/<id>/
کمتر از ۱ ساعت تا مهلتمهلت تسک شما نزدیک استdeadline/tasks/<id>/
گذشتن از مهلتتسک شما overdue شدهwarning/tasks/<id>/

نمونه data داخل نوتیف ارجاع:

{
  "kind": "info",
  "title": "تسک به شما ارجاع شد",
  "body": "تسک «بررسی تماس مالک جدید» به شما واگذار شد.",
  "link": "/tasks/15/",
  "data": {
    "task_id": 15,
    "type": "task_assignment"
  }
}

نمونه data یادآوری مهلت:

{
  "kind": "deadline",
  "title": "مهلت تسک شما نزدیک است",
  "body": "کمتر از یک ساعت تا مهلت تسک «بررسی تماس مالک جدید» مانده.",
  "link": "/tasks/15/",
  "data": {
    "task_id": 15,
    "remaining_seconds": 1200,
    "type": "task_due",
    "dedupe_key": "task-due:15:..."
  }
}

سناریوی کامل end-to-end

  1. سیستم‌منیجر تسک می‌سازد و به منشی می‌دهد:
    POST /tasks/
    {
      "title": "مالک تماس گرفته — بررسی اولیه",
      "priority": 3,
      "current_assignee": 12,
      "due_in_minutes": 60
    }
  2. منشی نوتیف می‌گیرد و جزئیات را می‌بیند: GET /tasks/15/
  3. منشی کامنت می‌گذارد:
    POST /tasks/15/comments/
    { "text": "اطلاعات مالک کامل شد." }
  4. منشی به مشاور ارجاع می‌دهد:
    POST /tasks/15/handover/
    {
      "to_user": 21,
      "note": "حالا مشاور برود کارشناسی کند"
    }
  5. مشاور نوتیف ارجاع می‌گیرد؛ status الان in_progress است.
  6. مشاور کار را تمام می‌کند:
    POST /tasks/15/status/
    {
      "status": "done",
      "note": "کارشناسی انجام شد"
    }
  7. سازنده تسک و سیستم‌منیجر با GET /tasks/15/ همه مراحل را در transitions می‌بینند.

پیشنهاد صفحات فرانت

پنل Notes
  1. لیست امروز + دکمه «فردا» / انتخابگر تاریخ
  2. مودال افزودن سریع (title + date + priority)
  3. تیک سریع انجام شد
  4. عدد badge کنار منوی یادداشت‌ها از /notes/badge/
پنل Tasks
  1. تسک‌های من ← GET /tasks/?mode=mine (مرتب‌سازی پیشنهادی فرانت: priority نزولی، سپس due_at نزدیک‌تر)
  2. تسک‌هایی که ساختم ← ?mode=created برای رصد مراحل
  3. همه تسک‌ها (ادمین) ← ?mode=all
  4. جزئیات تسک ← تایم‌لاین transitions + فرم handover + فرم status + لیست comments
  5. بدج‌ها از /tasks/badge/ + زنگوله از /notifications/

نمایش اولویت در UI:

const PRIORITY_LABEL = {
  1: "کم",
  2: "متوسط",
  3: "زیاد",
  4: "فوری",
};

نمایش وضعیت:

const STATUS_LABEL = {
  open: "باز",
  in_progress: "در حال انجام",
  waiting: "در انتظار",
  done: "انجام شده",
  cancelled: "لغو شده",
};

PART A — تسک معرفی ملک

نوع جدید تسک: task_type=property_introduction. کاربر (مذاکره‌کننده) فایل پایه را به مشاور هدف می‌دهد؛ مشاور تأیید می‌کند و draft فرم ثبت ملک برمی‌گردد.

POST /tasks/
{
  "task_type": "property_introduction",
  "current_assignee": 12,
  "intro_property_title": "آپارتمان فرشته",
  "intro_owner_name": "علی رضایی",
  "intro_work_location": "فرشته",
  "intro_property_type": "آپارتمان"
}

POST /tasks/5/introduction/confirm/
{ "accept": true }

GET /tasks/?task_type=property_introduction

جزئیات کامل: changelog-parts → PART A


مجوزهای RBAC

در کاتالوگ دسترسی‌ها این کدها تعریف شده‌اند:

  • notes.view / notes.manage
  • tasks.view / tasks.manage

الان خود APIهای Notes/Tasks با احراز هویت JWT کار می‌کنند و محدودیت دیداری بر اساس مالکیت/نقش داخل ویوها اعمال شده است (صاحب یادداشت، سازنده/مسئول تسک، ادمین). بعد از اضافه شدن پرمیشن‌ها، با python manage.py sync_rbac در دیتابیس هم سینک می‌شوند.

کجا در بک‌اند است؟

  • Notes/ — مدل PersonalNote + API لیست/ساخت/ویرایش/badge
  • Tasks/ — مدل Task / TaskTransition / TaskComment + سرویس create/handover/status/reminder
  • Notifications/ — صندوق اعلان و unread-count
  • Base URL: /notes/ و /tasks/ و /notifications/

نقشه سریع فرانت

# Notes
GET    /notes/
POST   /notes/
GET    /notes/badge/
GET    /notes/<id>/
PATCH  /notes/<id>/
DELETE /notes/<id>/

# Tasks
GET    /tasks/?mode=mine|created|all
GET    /tasks/?task_type=property_introduction
POST   /tasks/
GET    /tasks/badge/
GET    /tasks/<id>/
POST   /tasks/<id>/handover/
POST   /tasks/<id>/status/
POST   /tasks/<id>/comments/
POST   /tasks/<id>/introduction/confirm/

# Notifications
GET    /notifications/
GET    /notifications/unread-count/
POST   /notifications/<id>/read/
POST   /notifications/mark-all-read/