تغییرات بک‌اند — پارت‌بندی‌شده

این صفحه همه قابلیت‌های جدید را به صورت PART جدا می‌کند. اگر بخشی اشتباه پیاده شده، همان PART را بگو تا فقط همان تغییر کند.

پرامپت کامل فرانت: Documents/FRONTEND_PROMPT_WORKLINE.txt


Migration مشترک: *_workline_negotiator_visits_outcomes.py در اپ‌های Properties / Tracking / Tasks

PART A — مذاکره‌کننده + تسک معرفی ملک

  • مدل: PropertyModel.negotiator → FK به User
  • تسک: task_type=property_introduction + فیلدهای intro_*
  • تأیید مشاور: POST /tasks/<id>/introduction/confirm/
  • پاسخ تأیید: property_create_draft با negotiator پرشده
  • در create ملک: from_introduction_task_id و negotiator
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 }

PART B — تلاش ثبت ملک تکراری

  • مدل: DuplicatePropertyAttempt (payload + match_fields)
  • در POST /properties/create/ اگر تکراری باشد ذخیره + نوتیف منیجر
  • معیار: owner + city + location + floor_number
  • نوتیف: data.type = duplicate_property_attempt

PART C — ارزش فایل هنگام ثبت

  • PropertyModel.file_value = ۲۰ یا ۸۰ — اجباری در create
  • از فرم Approve منیجر حذف شد
  • در جزئیات ملک فقط برای منیجر/مشاور مالک نمایش داده می‌شود
  • در workline: مرحله file_value فقط readonly
  • set_file_value از complete حذف شد

PART D — معرفی مشتریان قدیمی فقط مشاور

  • actor مرحله introduce_to_old_clients = agent
  • دیگر در Approve منیجر نیست
  • فقط برای فایل ۲۰

PART E — هم‌رنج (AgentType)

  • رنج = AgentProfileModel.agent_type
  • GET /properties/list/?scope=mine|range
  • هم‌رنج: visibility=limited → تلفن مالک/ملک مخفی
  • ملک خودم: visibility=full, is_mine=true
  • بعد از Approve: نوتیف به همه هم‌رنج‌ها (range_new_property)

PART F — بازدید / قرارداد / وضعیت / GPS / رسانه

F1 — GPS کارشناسی
POST /tracking/<id>/complete/
{
  "step": "expert_media",
  "latitude": 35.6892,
  "longitude": 51.3890,
  "accuracy": 12.5,
  "note": "..."
}

بدون latitude/longitude خطا می‌دهد. باید از GPS دستگاه بیاید.

F2 — بازدید
POST /tracking/<id>/complete/
{ "step": "visit", "note": "بازدید اول" }

GET /tracking/<id>/visits/analytics/

مدل PropertyVisitLog + شمارنده visit_count.

F3 — قرارداد + رسانه
POST /tracking/<id>/complete/
{ "step": "contract", "note": "امضا شد" }

POST /tracking/<id>/contract-media/
# multipart: file, media_type=photo|video, caption
F4 — وضعیت نهایی (نام‌های دقیق)
valuelabel
sold_by_usفروش رفته توسط ما
sold_by_ownerفروش رفته توسط خودشون
rented_by_usاجاره رفته توسط ما
rented_by_ownerاجاره رفته توسط خودشون
cancelledمنصرف شده → تسک تماس یک‌ماه بعد
POST /tracking/<id>/complete/
{ "step": "outcome", "outcome": "sold_by_us", "note": "..." }

PART G — گزارش و داشبورد

اندپوینتتوضیح
GET /reports/dashboard/kpis/?agent_type=KPI منیجر با فیلتر رنج
GET /reports/dashboard/weekly-trend/?metric=&agent_type=&agent_id=چارت تب‌دار
GET /reports/dashboard/agent-type-breakdown/قیف جدا برای ۳ رنج
GET /reports/dashboard/visits-by-agent/بازدید به تفکیک مشاور
GET /reports/dashboard/agent/me/داشبورد خود مشاور

متریک‌های تب:

  • sale_outcomes / rent_outcomes
  • not_closed_at_agency
  • in_progress_vs_closed
  • visits_trend
  • workline_funnel (ارجاع / کارشناسی / بازدید / قرارداد)

جزئیات بیشتر رصد: Tracking — تسک‌ها: Notes & Tasks — گزارش: Reports