improve bazdid 4

This commit is contained in:
javad committed 2026-10-21 15:13:35 +03:30
1 parent f86d060e4d
commit 8fd881e0ea
10 files changed
+1752 -320

No files matched your search

+187 -41
View File
@@ -273,14 +273,15 @@ visit_hold_until = max(مقدار فعلی، تاریخ جدید)
| URL | نمایش | شامل |
|---|---|---|
| `/panel/entezar/` (بدون پارامتر) | **پیش‌فرض = بدون قرار** (رفتار قبلی) | بدون هیچ منبع |
| `/panel/entezar/` (بدون پارامتر) | **پیش‌فرض = نیازمند پیگیری امروز** | موعد تماس‌های امروز |
| `/panel/entezar/?view=today` | نیازمند پیگیری امروز (یا تاریخ `fdate`) | موعد تماس‌های آن روز |
| `?view=uncoordinated` | بدون قرار | بدون هیچ منبع |
| `?view=manual` | قرار دستی | هر مشتری با `manual` |
| `?view=scheduled` | بازدید برنامه‌ریزی‌شده | هر مشتری با `scheduled` |
| `?view=coordination` | هماهنگی | هر مشتری با `coordination` |
| `?view=coordinated` | همهٔ دارای قرار | اجتماع هر سه منبع |
| `?view=all` | همهٔ معوق‌ها | همه |
| مقدار نامعتبر | برگشت به پیش‌فرض، **بدون خطا** | بدون هیچ منبع |
| مقدار نامعتبر | برگشت به پیش‌فرض (`today`)، **بدون خطا** | موعد تماس‌های امروز |
چون یک مشتری می‌تواند چند منبع داشته باشد، در چند فیلتر دیده می‌شود؛ اما در
`?view=coordinated` فقط **یک‌بار** شمرده می‌شود. به همین دلیل جمع سه کارت منبع
@@ -380,48 +381,180 @@ python manage.py test tests
## ۱. نوار آمار (بالای صفحه)
پنج کارت که هر کدام هم **عدد** را نشان می‌دهد و هم **لینک فیلتر** است:
چهار کارت. عنوان‌ها با **زبان کسب‌وکار** انتخاب شده‌اند، نه زبان دیتابیس. هر کارت
هم عدد را نشان می‌دهد و هم **لینک فیلتر** است:
| کارت | چه چیزی را نشان می‌دهد |
| کارت | معنا | توضیح زیر عدد |
|---|---|---|
| **نیازمند پیگیری امروز** | موعد تماسشان **امروز** است و بازدید ندارند — فهرست کارِ امروز | موعد تماسشان امروز است — بازدید ندارند |
| **همهٔ مشتریان عقب‌افتاده** | همه، با هر وضعیت پیگیری | با هر وضعیت پیگیری |
| **تعیین تکلیف نشده** | هنوز هیچ وقت بازدید/پیگیری ندارند | هنوز وقت بازدید تعیین نشده — نیاز به تماس |
| **تعیین تکلیف شده** | وقت بعدی‌شان مشخص است | وقت بعدی‌شان مشخص است |
> **چرا «مشتری» و نه «بازدید»؟** عددِ کارت دوم تعداد **مشتری** است، نه تعداد
> بازدید. یک مشتری می‌تواند ده‌ها بازدید گذشته داشته باشد ولی فقط **یک بار**
> در این فهرست شمرده شود.
### تفکیک نوع قرار — در دراپ‌داون، نه روی کارت
کارت‌ها **عمداً ساده** نگه داشته شده‌اند: فقط عنوان، عدد و یک توضیح. جزئیات سه
نوع قرار (تعویق / بازدید / پیگیری) روی کارت چاپ **نمی‌شود**؛ چون:
- شش عدد روی کارت‌ها باعث سردرگمی می‌شد (بازخورد کاربران).
- ارتفاع کارت‌ها نامساوی و چیدمان موبایل به‌هم می‌ریخت.
- همان اطلاعات از دراپ‌داون **«نوع قرار»** در نوار فیلتر در دسترس است.
> جمع سه منبع می‌تواند از عدد «تعیین تکلیف شده» بیشتر باشد، چون یک مشتری
> می‌تواند چند منبع قرار داشته باشد؛ در `?view=coordinated` هر مشتری فقط
> **یک‌بار** شمرده می‌شود.
## ۱.۱ نمای «نیازمند پیگیری امروز» (`?view=today`) — **پیش‌فرض صفحه**
> **پیش‌فرض:** با باز کردن `/panel/entezar/` (بدون پارامتر)، همین نما نمایش داده
> می‌شود؛ کاربر بلافاصله فهرست کارِ امروز را می‌بیند.
فهرست کاریِ روزانهٔ کارشناس: **با چه کسانی امروز باید تماس بگیریم؟**
### این فهرست از کجا می‌آید؟
دو منبع، هر دو با شرط «موعد = همان روز»:
| منبع | تعریف |
|---|---|
| کل معوق | همهٔ مشتریان عقب‌افتاده (با قرار و بدون قرار) |
| بدون قرار | کسانی که هیچ قراری ندارند — **کار عملیاتی امروز** |
| با قرار | قرار هماهنگی یا بازدید برنامه‌ریزی‌شده دارند |
| قرار هماهنگی | قرار دستی ثبت‌شده روی مشتری |
| بازدید برنامه‌ریزی‌شده | بازدید/هماهنگیِ در جریان از نوع `Action` |
| **هماهنگی** | اقدام `hamahangi` با `status` در (`waite`/`finish`) و `actionDateTime` (وگرنه `finishDateTime`) در همان روز |
| **قرار دستی** | `Customer.visit_hold_until` که تاریخش همان روز است (با همان اعتبارسنجی «ستون، مرجع نیست») |
کارت فعال با حاشیهٔ آبی مشخص می‌شود.
### قاعدهٔ قطعی: «بازدید» اینجا نمی‌آید
## ۲. تفکیک مدت تأخیر
> اگر برای مشتری **قرار بازدید** (`bazdid + waite`) ثبت شده باشد، **هرگز** در این
> فهرست نمایش داده نمی‌شود — حتی اگر برای همان روز هم موعد پیگیری داشته باشد.
زیر نوار آمار، تعداد مشتریان بر اساس **مدت عقب‌افتادگی** نمایش داده می‌شود:
دلیلش روشن است: وقتی پرسنل برای بازدید می‌آید، تماس تلفنی لازم نیست.
- کمتر از ۳۰ روز
**استثنای مهم:** بازدیدهای بسیار قدیمی که هرگز بسته نشده‌اند (backlog) قرار فعال
محسوب نمی‌شوند؛ وگرنه یک رکورد کهنه می‌توانست مشتری را برای همیشه از فهرست
پنهان کند. شرط دقیق: بازدیدِ در انتظار با تاریخ **≥ آغاز روز مورد نظر**.
### تفاوت با فهرست «عقب‌افتاده»
| | «نیازمند پیگیری» | «عقب‌افتاده» |
|---|---|---|
| شرط ورود | موعد تماس = آن روز | از آخرین بازدید بیش از دوره گذشته |
| مشتری سالم | ✅ اگر قرار تماس داشته باشد می‌آید | ❌ نمی‌آید |
| شرط `installDate` | ندارد | دارد |
| ترتیب پیش‌فرض | زودترین ساعت موعد | قدیمی‌ترین بازدید |
### تقویم شمسی (گذشته و آینده)
نوار تاریخ فقط در این نما ظاهر می‌شود و شامل این‌هاست:
- **تقویم شمسی** (`pDatepicker`) برای انتخاب هر روزی
- دکمه‌های **‹ روز قبل** و **روز بعد ›**
- دکمهٔ **بازگشت به امروز** (اگر تاریخ انتخابی امروز نباشد)
```
/panel/entezar/?view=today امروز
/panel/entezar/?view=today&fdate=1405/07/28 روز دیگر (شمسی)
```
- مقدار نامعتبر/خالی ⇒ **امروز** (بدون خطا).
- عدد کارت «نیازمند پیگیری امروز» **همیشه عدد امروز** را نشان می‌دهد، حتی وقتی
در تقویم روز دیگری را می‌بینید.
- فیلتر «میزان تأخیر» و تفکیک آن در این نما **پنهان** می‌شود (مشتری این فهرست
ممکن است اصلاً تأخیری نداشته باشد)؛ اما جست‌وجو و مرتب‌سازی فعال است.
### ستون «تأخیر» در این نما نمایش داده نمی‌شود
این فهرست دربارهٔ «موعد تماس امروز» است، نه عقب‌افتادگی بازدید؛ پس ستون «تأخیر»
فقط در سایر نماها دیده می‌شود. عرض آن (۸٪) به ستون «نام» اضافه می‌شود تا مجموع
عرض ستون‌ها همچنان دقیقاً ۱۰۰٪ بماند (۸ ستون به‌جای ۹).
### هشدار «پیگیری‌های عقب‌افتاده»
اگر موعد پیگیری مشتریانی گذشته باشد و هنوز تعیین تکلیف نشده باشند، زیر نوار تاریخ
یک هشدار مینیمال قرمز با نقطهٔ کوچک نمایش داده می‌شود:
```
● 72 مورد نیازمند پیگیری از روزهای قبل باقی مانده
```
قواعد محاسبه (`visit_policy.overdue_followups`):
- مبنای هر مشتری، **آخرین** اقدام هماهنگی (`waite`/`finish`) است.
- اگر آن تاریخ **پیش از امروز** باشد ⇒ عقب‌افتاده.
- اگر مشتری هماهنگیِ امروز یا آینده داشته باشد ⇒ عقب‌افتاده **نیست**
(یعنی تمدید شده و از فهرست بیرون می‌رود).
- اگر برایش **قرار بازدید** ثبت شده باشد ⇒ حذف می‌شود (همان قاعدهٔ «بازدید گذاشته
شده ⇒ تماس لازم نیست»).
- هماهنگیِ لغوشده (`cancell`) اصلاً دیده نمی‌شود.
کلیک روی هشدار، همان فهرست را باز می‌کند:
```
/panel/entezar/?view=today&missed=1
```
در این حالت یک چیپ قرمز «نمایش N پیگیریِ عقب‌افتاده ✕ بازگشت به امروز» نشان داده
می‌شود و هشدار پنهان می‌گردد. عدد هشدار **دقیقاً** برابر تعداد ردیف‌های همین
فهرست است (هر دو از یک مسیر محاسبه می‌شوند).
## ۲. فیلترها (نوار زیر کارت‌ها)
یک ردیف فشرده با چهار کنترل؛ همه با هم ترکیب‌پذیرند و در URL حفظ می‌شوند.
| کنترل | پارامتر | مقادیر |
|---|---|---|
| نوع قرار | `view` | `all` · `uncoordinated` · `coordinated` · `manual` · `scheduled` · `coordination` |
| میزان تأخیر | `delay` | `lt30` · `30to90` · `90to180` · `gt180` (خالی = همه) |
| مرتب‌سازی | `sort` + `dir` | `last_visit` · `overdue` · `name` · `status` · `coordination` (و هر ستون دیگر) |
| جست‌وجو | `searchVal` + `searchOn` | `name` · `phone` · `code` · `address` |
- تغییر هر دراپ‌داون ⇒ فرم **خودکار** ارسال می‌شود.
- دکمهٔ **✕ حذف فیلترها** فقط وقتی فیلتری فعال است ظاهر می‌شود و همه را به
حالت پیش‌فرض برمی‌گرداند.
- **کارت‌ها هیچ‌وقت با فیلتر تغییر نمی‌کنند** — همیشه کل جامعه را نشان می‌دهند.
فقط فهرست زیرشان فیلتر می‌شود.
## ۳. تفکیک مدت تأخیر (کلیک‌پذیر)
زیر نوار فیلتر، تعداد مشتریان بر اساس **مدت عقب‌افتادگی** در **نمای جاری**
نمایش داده می‌شود و هر عدد **لینک فیلتر** است:
- تا ۳۰ روز
- ۳۰ تا ۹۰ روز
- ۹۰ تا ۱۸۰ روز
- بیش از ۶ ماه
**مبنای محاسبه:** «موعد بازدید» = آخرین بازدید معتبر + دورهٔ قالب (پیش‌فرض ۹ ماه).
برای مشتریِ بدون بازدید، مبنای مقایسه مقطع دوره است تا عدد بی‌معنا نشود.
یعنی «۳ ماه تأخیر» یعنی «۳ ماه از موعد بازدید گذشته»، نه «۳ ماه از خود بازدید».
**مبنای محاسبه:** «موعد بازدید» = آخرین بازدید معتبر + دورهٔ قالب. برای
مشتریِ بدون بازدید، مبنای مقایسه مقطع دوره است تا عدد بی‌معنا نشود.
یعنی «۳ ماه تأخیر» = «۳ ماه از موعد بازدید گذشته»، نه «۳ ماه از خود بازدید».
## ۳. مرتب‌سازی
> جمع این چهار عدد همیشه برابر تعداد ردیف‌های نمای جاری است (تست‌شده).
سه حالت اختیاری (پارامتر `sort` در URL، قابل بوکمارک):
## ۴. مرتب‌سازی (ستون‌ها و دراپ‌داون)
| مقدار | ترتیب | کاربرد |
|---|---|---|
| `oldest` (پیش‌فرض) | قدیمی‌ترین بازدید اول | اولویت کارشناس |
| `overdue` | بیشترین تأخیر اول | ببینیم چه کسی از همه دیرتر است |
| `newest` | جدیدترین بازدید اول | بررسی موارد تازه‌معوق |
**هر ۹ ستون** با کلیک روی سرستون مرتب می‌شوند؛ کلیک دوباره جهت را برمی‌گرداند:
ترتیب بر مبنای **تاریخ مؤثر بازدید از `Action`** است، نه ستون
`last_bazdid_dt` (که ممکن است کهنه باشد). برای گروهِ بدون بازدید، مبنای
ترتیب مقطع دوره است.
| ستون | مبنا |
|---|---|
| نام و نام خانوادگی | الفبایی |
| وضعیت قرار | بدون قرار ← تعویق ← بازدید ← پیگیری ← چندقراره |
| قرار دستی | تاریخ قرار (خالی‌ها آخر) |
| بازدید برنامه‌ریزی‌شده | تاریخ قرار (خالی‌ها آخر) |
| هماهنگی | تاریخ پیگیری (خالی‌ها آخر) |
| آخرین بازدید | تاریخ مؤثر بازدید از `Action` |
| تأخیر | تعداد روز تأخیر |
| تلفن | مقدار `phone1` |
| آدرس | الفبایی |
## ۴. جست‌وجو (تکمیل‌شده)
- سرستون فعال با فلش **▲/▼** و ستون‌های دیگر با **⇅** مشخص می‌شوند.
- **مقادیر خالی همیشه آخر می‌آیند**، مستقل از جهت — وگرنه مرتب‌سازی ستون‌های
قرار، فهرست را بی‌معنا می‌کرد.
- دراپ‌داون «مرتب‌سازی» چند گزینهٔ پرکاربرد را کوتاه می‌کند.
- مقادیر قدیمی `sort=oldest|newest|overdue` همچنان کار می‌کنند (سازگاری با
بوکمارک‌های قبلی).
پیش‌تر فقط جست‌وجو بر اساس **آدرس** ممکن بود. اکنون:
## ۵. جست‌وجو
| فیلد | جست‌وجو در |
|---|---|
@@ -430,8 +563,7 @@ python manage.py test tests
| آدرس | `address` |
| کد مشتری | `idCode` |
نما و مرتب‌سازی هنگام جست‌وجو **حفظ می‌شوند** و دکمهٔ «حذف جستجو» برای برگشت
به فهرست کامل هست.
نما، فیلتر تأخیر و مرتب‌سازی هنگام جست‌وجو **حفظ می‌شوند**.
## ۵. چیدمان ستون‌ها (بازطراحی)
@@ -506,23 +638,37 @@ python manage.py test tests
## ۱۰. پارامترهای URL
```
/panel/entezar/ نمای پیش‌فرض (بدون قرار، قدیمی‌ترین)
?view=all همهٔ معوق‌ها
?view=coordinated با قرار (اجتماع سه منبع)
?view=manual فقط قرار دستی
/panel/entezar/ پیش‌فرض: نیازمند پیگیری امروز
?view=all همهٔ عقب‌افتاده‌ها
?view=coordinated تعیین تکلیف شده (اجتماع سه منبع)
?view=today نیازمند پیگیری امروز
?view=today&fdate=1405/07/28 نیازمند پیگیری در یک روز دیگر (شمسی)
?view=manual فقط تعویق دستی
?view=scheduled فقط بازدید برنامه‌ریزی‌شده
?view=coordination فقط هماهنگی
?sort=overdue بیشترین تأخیر اول
?sort=newest جدیدترین بازدید اول
?view=coordination فقط پیگیری تلفنی
?delay=gt180 فقط بیش از ۶ ماه تأخیر
?sort=overdue&dir=desc بیشترین تأخیر اول
?sort=name&dir=asc الفبایی (صعودی)
?sort=manual&dir=desc تاریخ قرار دستی (نزولی)
?searchVal=رضایی&searchOn=name جست‌وجوی نام
?searchVal=0912&searchOn=phone جست‌وجوی تلفن
?view=all&sort=overdue&page=3 ترکیب‌پذیر
?view=all&delay=gt180&sort=name&dir=asc&page=3 همه با هم (ترکیب‌پذیر)
?view=today&missed=1 فقط پیگیری‌های عقب‌افتاده
```
مقدار نامعتبر `view` یا `sort` بی‌صدا به پیش‌فرض برمی‌گردد (هیچ خطای ۴۰۰/۵۰۰).
- **اندازهٔ صفحه = ۱۰۰ ردیف** (`ENTEZAR_PAGE_SIZE`)؛ صفحه‌بندی فقط از ردیف ۱۰۱ به
بعد فعال می‌شود.
3. پس از تاریخ قرار، مشتری **خودکار** در گروه A ظاهر می‌شود؛ نیازی به کار دستی نیست.
4. عدد «بدون قرار» در داشبورد همان لیست کاریِ فوری است.
- مقدار نامعتبر `view`/`sort`/`delay` بی‌صدا به پیش‌فرض برمی‌گردد (بدون ۴۰۰/۵۰۰).
- مقادیر قدیمی `sort=oldest|newest|overdue` همچنان معتبرند.
- همهٔ لینک‌های داخلی (کارت‌ها، بازه‌های تأخیر، سرستون‌ها، صفحه‌بندی) **بقیهٔ
فیلترها را حفظ می‌کنند**.
---
3. پس از تاریخ قرار، مشتری **خودکار** در گروه «تعیین تکلیف نشده» ظاهر می‌شود؛
نیازی به کار دستی نیست.
4. عدد «تعیین تکلیف نشده» در داشبورد همان لیست کاریِ فوری است.