improve bazdid
This commit is contained in:
1 parent
2aee85593f
commit
534a84f977
12 files changed
+2305
-339
No files matched your search
@@ -0,0 +1,468 @@
|
||||
# «قرار بعدی» بازدید و صفحهٔ انتظار — توضیح کامل عملکرد
|
||||
|
||||
این سند رفتار نهایی صفحهٔ `/panel/entezar/`، فیلد «تا تاریخ پیگیری نشود» در فرم
|
||||
اقدام، و قواعد محاسبه را توضیح میدهد. هدف: بعد از این تغییر، **هماهنگیِ انجامشده
|
||||
هم** مشتری را تا تاریخ توافق از فهرست خارج کند و کاربر بتواند بازدیدهای
|
||||
«هماهنگشده» را از «هماهنگنشده» جدا ببیند.
|
||||
|
||||
---
|
||||
|
||||
## ۱. صورت مسئله
|
||||
|
||||
پیش از این تغییر، فقط دو حالت مشتری را از فهرست خارج میکرد:
|
||||
|
||||
1. اقدام `bazdid` با وضعیت `waite` و تاریخ آینده (بازدید برنامهریزیشده)
|
||||
2. اقدام `hamahangi` با تاریخ **آینده** در فیلد تاریخ اقدام
|
||||
|
||||
اما سناریوی واقعی کارشناس این بود:
|
||||
|
||||
> «همین حالا با مشتری تماس گرفتم، توافق کردیم هفتهٔ بعد بیاییم، و تیک *انجام شد* را
|
||||
> زدم.»
|
||||
|
||||
در این حالت، فیلد «تاریخ اقدام» روی **همین حالا** مینشیند، پس هیچ قرار آیندهای
|
||||
وجود نداشت و مشتری در فهرست میماند و کارشناس دیگری دوباره تماس میگرفت.
|
||||
|
||||
**ریشه:** «تاریخ تماس» و «تاریخ قرار بعدی» دو مفهوم متفاوتاند ولی در یک فیلد
|
||||
(`actionDateTime`) جمع شده بودند.
|
||||
|
||||
---
|
||||
|
||||
## ۲. راهحل: ستون «قرار بعدی»
|
||||
|
||||
دو ستون به مدل `Customer` اضافه شد:
|
||||
|
||||
| ستون | نوع | معنا |
|
||||
|---|---|---|
|
||||
| `visit_hold_until` | `DateTimeField(null=True)` | تا **پایان** این روز پیگیری لازم نیست |
|
||||
| `visit_hold_set_at` | `DateTimeField(null=True)` | زمان ثبت، برای حسابرسی |
|
||||
|
||||
### قاعدهٔ طلایی: ستون، «مرجع» نیست
|
||||
|
||||
> `visit_hold_until` هیچ اعتباری بهتنهایی ندارد. فقط وقتی اثر دارد که برای همان
|
||||
> مشتری یک اقدام **هماهنگیِ فعال** (`waite` یا `finish`) وجود داشته باشد.
|
||||
|
||||
نتیجهٔ این قاعده:
|
||||
|
||||
| رویداد | اثر روی قرار |
|
||||
|---|---|
|
||||
| حذف اقدام هماهنگی | قرار **خودکار بیاثر** میشود |
|
||||
| لغو هماهنگی (`cancell`) | بیاثر میشود |
|
||||
| ویرایش تاریخ هماهنگی | قرار با تاریخ جدید همراستا میشود |
|
||||
| کهنه ماندن ستون | **هیچ اثر مخربی ندارد** |
|
||||
|
||||
به همین دلیل دیگر خطر «کش کهنه» وجود ندارد: منبع حقیقت همیشه جدول `Action` است.
|
||||
|
||||
---
|
||||
|
||||
## ۳. سه منبع «قرار بعدی»
|
||||
|
||||
تصمیم «مشتری در فهرست هست یا نه» از اجتماع سه منبع گرفته میشود:
|
||||
|
||||
| منبع | تعریف | تاریخ قرار |
|
||||
|---|---|---|
|
||||
| `manual` | ستون `visit_hold_until` (با اعتبارسنجی بالا) | همان ستون (پایان روز) |
|
||||
| `scheduled` | `bazdid + waite` با تاریخ آینده | `actionDateTime` |
|
||||
| `coordination` | `hamahangi` با `waite` یا `finish` و تاریخ آینده | `actionDateTime` (یا `finishDateTime`) |
|
||||
|
||||
تابع واحد: `visit_policy.next_appointment_map(now)` — **همان تابعی که اسکنر پیامک
|
||||
هم استفاده میکند**، پس صفحه و پیامک هرگز واگرا نمیشوند.
|
||||
|
||||
اگر مشتری چند قرار داشته باشد، **زودترین** تاریخ ملاک نمایش است؛ اما برای
|
||||
«بازگشت به فهرست» کافی است **آخرین** قرار منقضی شود.
|
||||
|
||||
---
|
||||
|
||||
## ۴. فرم ثبت اقدام (UI)
|
||||
|
||||
در مودال «ایجاد وظیفه» (`customerActionInc.html`):
|
||||
|
||||
| مورد | رفتار |
|
||||
|---|---|
|
||||
| نمایش فیلد | فقط وقتی نوع اقدام = **هماهنگی** انتخاب شود |
|
||||
| برچسب | «تا تاریخ پیگیری نشود» |
|
||||
| کنترل | تقویم شمسی (همان `pDatepicker` پروژه) |
|
||||
| پیشفرض | اگر خالی بماند و تیک «انجام شد» زده شود ⇒ **+۱۴ روز** |
|
||||
| سقف | **۶ ماه** (اعتبارسنجی سروری) |
|
||||
| حالت ویرایش | فیلد با نوع اقدام همراستا میشود (نمایش/پنهان) |
|
||||
|
||||
نکتهٔ مهم: فیلد «تاریخ و ساعتی که کار باید انجام شود» (`dateTimeAnjam`) همچنان
|
||||
«زمان تماس» است و دست نخورده باقی میماند. دو مفهوم، دو فیلد.
|
||||
|
||||
### ۴.۱ چیدمان مودال (mobile first)
|
||||
|
||||
مودال به سه گام شمارهدار تقسیم شده تا کاربر بداند چه چیزی را کجا وارد کند:
|
||||
|
||||
| گام | محتوا |
|
||||
|---|---|
|
||||
| ۱ | نوع اقدام + مسئول (توسط) — کنار هم در دسکتاپ، زیر هم در موبایل |
|
||||
| ۲ | زمانبندی: تاریخ انجام، «تا تاریخ پیگیری نشود»، و راهنمای بازشونده |
|
||||
| ۳ | توضیحات، تیک «انجام شده»، تاریخ اتمام و نتیجه |
|
||||
|
||||
نکات پیادهسازی:
|
||||
|
||||
* پیشوند همهٔ کلاسها `ax-` و همهٔ انتخابگرها زیر `#ActionBox` است ⇒ هیچ استایلی
|
||||
به سایر صفحات نشت نمیکند.
|
||||
* روی موبایل: کارت تمامعرض (`calc(100% - 1rem)`)، بدنهٔ اسکرولشونده، هدف لمسی
|
||||
حداقل ۲٫۶rem، و دکمههای پاصفحه تمامعرض.
|
||||
* روی دسکتاپ (≥۷۶۸px): شبکهٔ دوستونه، عرض حداکثر ۴۴rem.
|
||||
* سرصفحه نام مشتری را نشان میدهد تا کاربر بداند برای چه کسی وظیفه میسازد.
|
||||
* **همان تقویم شمسی قبلی** استفاده میشود: `dateTimePickerAnjam`،
|
||||
`dateTimePickerFinish` و `dateTimePickerHoldUntil` با `pDatepicker` و
|
||||
`calendar.persian.locale = 'fa'`. هیچ کتابخانهٔ جدیدی اضافه نشده است.
|
||||
* **نام کلاس فیلد باید با سلکتور JS یکی باشد.** هر فیلد تاریخ دو المان دارد:
|
||||
ورودی نمایشی (با کلاس `dateTimePickerXxx`) و ورودی مخفیِ ارسال (با کلاس
|
||||
`dateTimePickerXxx-alt`). اگر این نامها همخوانی نداشته باشند،
|
||||
`pDatepicker` روی مجموعهٔ خالی اجرا میشود، `undefined` برمیگرداند و
|
||||
`setDate()` با `TypeError` کل هندلر را میشکند — نتیجه: تقویم باز نمیشود و
|
||||
بقیهٔ منطق (پنهانکردن فیلدها، برداشتن تیک خودکار) هم اجرا نمیشود.
|
||||
دو تست اختصاصی
|
||||
(`test_every_picker_selector_matches_markup` و
|
||||
`test_every_alt_field_class_exists_in_markup`) همین را قفل کردهاند.
|
||||
* `altField` با فرمت پیشفرض `unix` مقدار میدهد؛ بنابراین `visitHoldUntil`
|
||||
یک timestamp میلیثانیهای است که `_parse_form_datetime` آن را میخواند.
|
||||
* تقویم به `body` اضافه میشود (نه داخل مودال) ⇒ اسکرول بدنهٔ مودال آن را نمیبرد.
|
||||
|
||||
### ۴.۲ هشدار زمانبندی و پیشفرض «انجام شده» (فقط هماهنگی)
|
||||
|
||||
چون در عمل «ثبت هماهنگی» یعنی «همین حالا با مشتری تماس گرفتم»، انتخاب نوع
|
||||
**هماهنگی** بهطور خودکار تیک «این کار انجام شده است» را میزند (و فیلدهای
|
||||
تاریخ اتمام و نتیجه را نمایش میدهد). برای جلوگیری از ثبتِ ناخواسته، دو لایه
|
||||
محافظ اضافه شده است:
|
||||
|
||||
**۱) هشدار همیشگی** — بهمحض تیکخوردن و تا وقتی نوع هماهنگی است، یک کادر
|
||||
کهربایی زیر تیک نمایش داده میشود:
|
||||
|
||||
> آیا مطمئن هستی که هماهنگی را انجام دادی؟
|
||||
> اگر هنوز هماهنگی نکردی، این تیک را بردار.
|
||||
|
||||
**۲) تأیید در لحظهٔ ثبت** — اگر کاربر روی «ثبت» بزند و نوع هماهنگی و تیک
|
||||
«انجام شده» فعال باشد، ارسال متوقف میشود و همان کادر برجسته شده و دو دکمه
|
||||
نشان میدهد:
|
||||
|
||||
| دکمه | نتیجه |
|
||||
|---|---|
|
||||
| بله، هماهنگی انجام شد | فرم ارسال میشود (هماهنگی با وضعیت `finish` ثبت میشود) |
|
||||
| نه، تیک را بردار | تیک برداشته میشود، فیلدهای اتمام پنهان میشوند و ارسال نمیشود |
|
||||
|
||||
قواعد ایمنی:
|
||||
|
||||
* **فقط هماهنگی**: سایر انواع اقدام (بازدید، نصب، وصول، تماس…) هیچ تیک
|
||||
خودکار و هیچ تأییدی ندارند و رفتارشان دقیقاً مثل قبل است.
|
||||
* **تغییر نوع = برداشتن تیک خودکار**: اگر سیستم تیک زده باشد و کاربر نوع را
|
||||
به غیر هماهنگی تغییر دهد، تیک برداشته میشود (تا ناخواسته `last_bazdid_dt`
|
||||
یا وضعیت «انجام شده» ثبت نشود). اگر کاربر خودش تیک زده باشد، دستنخورده
|
||||
میماند.
|
||||
* **حالت ویرایش**: تأیید گرفته نمیشود (کاربر فقط رکورد موجود را اصلاح میکند)؛
|
||||
اما کادر هشدار برای هماهنگیِ انجامشده بهصورت اطلاعاتی نمایش داده میشود.
|
||||
* **باز شدن مجدد مودال**: تیک، هشدار و وضعیت تأیید همیشه ریست میشوند.
|
||||
|
||||
### ۴.۳ راهنمای بازشونده (فقط «هماهنگی»)
|
||||
|
||||
زیر فیلد تاریخ پیگیری، یک دکمهٔ راهنما با آیکون `!` قرار دارد که پنل توضیحات را
|
||||
باز/بسته میکند. محتوای پنل:
|
||||
|
||||
* «این تاریخ چه کاری میکند؟» — تعریف ساده + اینکه تا پایان همان روز معتبر است.
|
||||
* «مثال» — سناریوی واقعی با تاریخ نمونه.
|
||||
* «نکات مهم» — خالی + تیک ⇒ ۱۴ روز، خالی + بدون تیک ⇒ بدون تعویق،
|
||||
فقط تمدید (نه کوتاهکردن)، حذف/لغو هماهنگی ⇒ بازگشت فوری، سقف ۶ ماه،
|
||||
تفاوت با «تاریخ بازدید پرسنل»، و توقف پیامک یادآوری در مدت تعویق.
|
||||
|
||||
رفتار:
|
||||
|
||||
| رویداد | نتیجه |
|
||||
|---|---|
|
||||
| انتخاب نوع = هماهنگی | دکمهٔ راهنما ظاهر میشود (پنل بسته) |
|
||||
| کلیک روی دکمه | پنل باز/بسته میشود و `aria-expanded` بهروز میشود |
|
||||
| تغییر نوع به غیر هماهنگی | فیلد و راهنما پنهان و پنل بسته میشود |
|
||||
| باز شدن مجدد مودال (ایجاد یا ویرایش) | پنل همیشه بسته شروع میشود |
|
||||
|
||||
دسترسیپذیری: دکمه `aria-expanded` و `aria-controls="holdHelpPanel"` دارد و
|
||||
پنل با `is-hidden` کنترل میشود.
|
||||
|
||||
### قواعد اعتبارسنجی (سرور)
|
||||
|
||||
* تاریخ قرار نباید **پیش از امروز** باشد ⇒ پیام: «تاریخ قرار نمیتواند پیش از امروز باشد.»
|
||||
* حداکثر **۱۸۳ روز** (≈۶ ماه) جلوتر ⇒ پیام: «قرار بعدی حداکثر میتواند ۱۸۳ روز (۶ ماه) جلوتر باشد.»
|
||||
* تاریخ «امروز» پذیرفته است و به **۲۳:۵۹:۵۹ همان روز** تبدیل میشود (تا پایان روز معتبر).
|
||||
* اگر اعتبارسنجی رد شود، **هیچ اقدامی ذخیره نمیشود**.
|
||||
|
||||
### قاعدهٔ «تمدید مجاز، کوتاهکردن ممنوع» (max)
|
||||
|
||||
قرار ذخیرهشده همیشه **بزرگترین** تاریخِ ثبتشده است:
|
||||
|
||||
```
|
||||
visit_hold_until = max(مقدار فعلی، تاریخ جدید)
|
||||
```
|
||||
|
||||
| وضعیت | نتیجه |
|
||||
|---|---|
|
||||
| قرار فعلی ۱ آذر، کارشناس جدید ۸ آذر | **تمدید میشود به ۸ آذر** ✅ |
|
||||
| قرار فعلی ۸ آذر، کارشناس جدید ۱ آذر | **تغییری نمیکند** (۸ آذر میماند) |
|
||||
|
||||
منطق: اگر مشتری گفته «۸ آذر تماس بگیرید»، سیستم نباید ۱ آذر زنگ بزند. در مقابل،
|
||||
یک ثبت اشتباه نباید قرارِ طولانیِ قبلی را نابود کند.
|
||||
|
||||
**برای عقببردن قرار** (مثلاً مشتری گفت زودتر بیایید): هماهنگی را **حذف** و دوباره
|
||||
با تاریخ جدید ثبت کنید.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## ۵. صفحهٔ انتظار: چهار گروه و فیلترها
|
||||
|
||||
هر مشتری معوق **دقیقاً در یکی** از این چهار گروه است:
|
||||
|
||||
| گروه | تعریف |
|
||||
|---|---|
|
||||
| **A** | معوق، بدون هیچ قرار |
|
||||
| **B** | معوق، فقط قرار دستی (`manual`) |
|
||||
| **C** | معوق، فقط بازدید برنامهریزیشده یا هماهنگی در انتظار |
|
||||
| **D** | معوق، هم قرار دستی و هم بازدید برنامهریزیشده |
|
||||
|
||||
### فیلترها (قابل بوکمارک و ترکیب با جستوجو)
|
||||
|
||||
| URL | نمایش | شامل |
|
||||
|---|---|---|
|
||||
| `/panel/entezar/` (بدون پارامتر) | **پیشفرض = فقط A** (رفتار قبلی صفحه) | A |
|
||||
| `?view=uncoordinated` | بدون قرار | A |
|
||||
| `?view=manual` | قرار هماهنگی | B + D |
|
||||
| `?view=scheduled` | بازدید برنامهریزیشده | C + D |
|
||||
| `?view=coordinated` | همهٔ دارای قرار | B + C + D |
|
||||
| `?view=all` | همهٔ معوقها | A + B + C + D |
|
||||
| مقدار نامعتبر | برگشت به پیشفرض، **بدون خطا** | A |
|
||||
|
||||
### ستونهای جدول
|
||||
|
||||
| ستون | توضیح |
|
||||
|---|---|
|
||||
| وضعیت قرار | برچسب «با قرار» / «بدون قرار» |
|
||||
| قرار هماهنگی | تاریخ شمسی قرار دستی (یا —) |
|
||||
| بازدید برنامهریزیشده | تاریخ شمسی قرار `Action` (یا —) |
|
||||
| آخرین بازدید | بدون تغییر نسبت به قبل |
|
||||
|
||||
### شمارندهٔ داشبورد
|
||||
|
||||
`CacheTable('9mahbazdid')` = **گروه A** (کارِ فوری = بدون قرار). هر بار باز شدن
|
||||
صفحه بهروز میشود.
|
||||
|
||||
---
|
||||
|
||||
## ۶. تعامل با سایر بخشها
|
||||
|
||||
| بخش | اثر |
|
||||
|---|---|
|
||||
| **آخرین بازدید** (`last_visit_map`) | دستنخورده — فقط `bazdid + finish` |
|
||||
| **چرخهٔ ۹ ماهه** (`cycle_anchor_map`) | دستنخورده — `bazdid` و `nasb` |
|
||||
| **اسکنر پیامک** (`scan_visit`) | فقط یک منبع اضافه در `next_appointment_map` |
|
||||
| **`recalc_last_bazdid`** | دستنخورده |
|
||||
| **`last_bazdid_dt`** | بدون تغییر (نمایش/ترتیب) |
|
||||
| **ایندکس `act_visit_idx`** | بدون تغییر |
|
||||
|
||||
قاعدهٔ طلایی حفظ شده است: **هماهنگی هرگز بازدید حساب نمیشود.**
|
||||
|
||||
---
|
||||
|
||||
## ۷. سناریوهای تستشده
|
||||
|
||||
| # | سناریو | نتیجهٔ انتظار | وضعیت |
|
||||
|---|---|---|---|
|
||||
| ۱ | هماهنگی با قرار «امروز» | تا پایان روز خارج از فهرست | ✅ |
|
||||
| ۲ | هماهنگی finish بدون تاریخ قرار | پیشفرض ۱۴ روز | ✅ |
|
||||
| ۳ | حذف اقدام هماهنگی | قرار بیاثر، مشتری برمیگردد | ✅ |
|
||||
| ۴ | لغو هماهنگی (`cancell`) | قرار بیاثر | ✅ |
|
||||
| ۵ | هماهنگی دوم با تاریخ کوچکتر | قرار قبلی حفظ میشود | ✅ |
|
||||
| ۶ | هماهنگی دوم با تاریخ بزرگتر | قرار تمدید میشود | ✅ |
|
||||
| ۷ | قرار بیش از ۶ ماه | رد با پیام، هیچ ذخیرهای | ✅ |
|
||||
| ۸ | قرار در گذشته | رد با پیام | ✅ |
|
||||
| ۹ | بازدید واقعی بعد از قرار | مشتری از فهرست خارج میماند | ✅ |
|
||||
| ۱۰ | هماهنگی finish با تاریخ آینده (بدون ستون) | خارج از فهرست | ✅ |
|
||||
| ۱۱ | تفکیک A/B/C/D و هر پنج فیلتر | اعداد و فهرست درست | ✅ |
|
||||
| ۱۲ | `?view=nonsense` | پیشفرض، بدون خطا | ✅ |
|
||||
| ۱۳ | اسکنر پیامک با قرار دستی | پیامک ارسال نمیشود | ✅ |
|
||||
| ۱۴ | اجتماع منابع در `next_appointment_map` | زودترین تاریخ | ✅ |
|
||||
|
||||
جمع: **۳۷۶ تست موفق** در کل پروژه (۱۵ تست جدید مربوط به این قابلیت).
|
||||
|
||||
---
|
||||
|
||||
## ۸. استقرار
|
||||
|
||||
```bash
|
||||
# ۱) بکاپ
|
||||
python manage.py sqlite_db_backup # یا کپی فایل دیتابیس
|
||||
|
||||
# ۲) مهاجرت (دو ستون nullable — امن و سریع)
|
||||
python manage.py migrate
|
||||
|
||||
# ۳) بررسی
|
||||
python manage.py check
|
||||
python manage.py test tests
|
||||
```
|
||||
|
||||
### رفتار دادهٔ موجود
|
||||
|
||||
* همهٔ مشتریان با `visit_hold_until = NULL` شروع میکنند ⇒ **رفتار امروز دقیقاً حفظ میشود**.
|
||||
* هماهنگیهای قدیمی (۵ رکورد سال ۲۰۲۲) هیچ ستونی ندارند و فقط از مسیر `Action`
|
||||
ارزیابی میشوند.
|
||||
|
||||
---
|
||||
|
||||
## ۹. نکات عملیاتی
|
||||
|
||||
1. **حذف هماهنگی** بهترین راه برای «لغو قرار» است.
|
||||
2. اگر قرار اشتباه ثبت شد، هماهنگی را **حذف** و دوباره ثبت کنید (قرار جدید فقط
|
||||
میتواند تمدید کند، نه آن را کوتاهتر کند).
|
||||
|
||||
---
|
||||
|
||||
# بخش دوم — امکانات جدید رابط کاربری صفحهٔ انتظار
|
||||
|
||||
این بخش قابلیتهایی را توضیح میدهد که برای «راحت دیدن اطلاعات و تصمیم درست
|
||||
گرفتن» اضافه شدهاند. طراحی **mobile first** است: در موبایل هر مشتری یک کارت
|
||||
میشود و در دسکتاپ همان جدول قبلی؛ هیچ صفحه/منوی جدیدی اضافه نشده و شکل کلی
|
||||
صفحه حفظ شده است.
|
||||
|
||||
## ۱. نوار آمار (بالای صفحه)
|
||||
|
||||
پنج کارت که هر کدام هم **عدد** را نشان میدهد و هم **لینک فیلتر** است:
|
||||
|
||||
| کارت | چه چیزی را نشان میدهد |
|
||||
|---|---|
|
||||
| کل معوق | همهٔ مشتریان عقبافتاده (با قرار و بدون قرار) |
|
||||
| بدون قرار | کسانی که هیچ قراری ندارند — **کار عملیاتی امروز** |
|
||||
| با قرار | قرار هماهنگی یا بازدید برنامهریزیشده دارند |
|
||||
| قرار هماهنگی | قرار دستی ثبتشده روی مشتری |
|
||||
| بازدید برنامهریزیشده | بازدید/هماهنگیِ در جریان از نوع `Action` |
|
||||
|
||||
کارت فعال با حاشیهٔ آبی مشخص میشود.
|
||||
|
||||
## ۲. تفکیک مدت تأخیر
|
||||
|
||||
زیر نوار آمار، تعداد مشتریان بر اساس **مدت عقبافتادگی** نمایش داده میشود:
|
||||
|
||||
- کمتر از ۳۰ روز
|
||||
- ۳۰ تا ۹۰ روز
|
||||
- ۹۰ تا ۱۸۰ روز
|
||||
- بیش از ۶ ماه
|
||||
|
||||
**مبنای محاسبه:** «موعد بازدید» = آخرین بازدید معتبر + دورهٔ قالب (پیشفرض ۹ ماه).
|
||||
برای مشتریِ بدون بازدید، مبنای مقایسه مقطع دوره است تا عدد بیمعنا نشود.
|
||||
یعنی «۳ ماه تأخیر» یعنی «۳ ماه از موعد بازدید گذشته»، نه «۳ ماه از خود بازدید».
|
||||
|
||||
## ۳. مرتبسازی
|
||||
|
||||
سه حالت اختیاری (پارامتر `sort` در URL، قابل بوکمارک):
|
||||
|
||||
| مقدار | ترتیب | کاربرد |
|
||||
|---|---|---|
|
||||
| `oldest` (پیشفرض) | قدیمیترین بازدید اول | اولویت کارشناس |
|
||||
| `overdue` | بیشترین تأخیر اول | ببینیم چه کسی از همه دیرتر است |
|
||||
| `newest` | جدیدترین بازدید اول | بررسی موارد تازهمعوق |
|
||||
|
||||
ترتیب بر مبنای **تاریخ مؤثر بازدید از `Action`** است، نه ستون
|
||||
`last_bazdid_dt` (که ممکن است کهنه باشد). برای گروهِ بدون بازدید، مبنای
|
||||
ترتیب مقطع دوره است.
|
||||
|
||||
## ۴. جستوجو (تکمیلشده)
|
||||
|
||||
پیشتر فقط جستوجو بر اساس **آدرس** ممکن بود. اکنون:
|
||||
|
||||
| فیلد | جستوجو در |
|
||||
|---|---|
|
||||
| نام و نام خانوادگی | `name_family` |
|
||||
| تلفن | `phone1`، `phone2`، `phone3` |
|
||||
| آدرس | `address` |
|
||||
| کد مشتری | `idCode` |
|
||||
|
||||
نما و مرتبسازی هنگام جستوجو **حفظ میشوند** و دکمهٔ «حذف جستجو» برای برگشت
|
||||
به فهرست کامل هست.
|
||||
|
||||
## ۵. چیدمان ستونها (بازطراحی)
|
||||
|
||||
پیشتر ستون «ردیف» یک ستون کامل جدول را برای یک عدد دو رقمی میگرفت و دو ستون
|
||||
با `min-width` ثابت (۱۹۰px و ۳۲۰px) تعیین عرض میکردند؛ نتیجه: بیتناسبی
|
||||
فاصلهها و اسکرول افقی. تغییرات:
|
||||
|
||||
1. **ستون «ردیف» حذف شد.** شمارهٔ ردیف حالا یک **چیپ کوچک کنار نام** است
|
||||
(`.ez-idx`) که هم فضا نمیخورد و هم برای پیدا کردن ردیف کافی است.
|
||||
2. **عرض ستونها با `<colgroup>` درصدی** تعیین میشود و جدول
|
||||
`table-layout: fixed` است. بنابراین:
|
||||
- مجموع عرضها همیشه ۱۰۰٪ است،
|
||||
- هیچ ستونی بیدلیل پهن نمیشود،
|
||||
- اسکرول افقی در حالت جدول رخ نمیدهد.
|
||||
3. **مقیاس فاصله یکسان:** همهٔ حاشیهها مضرب ۰٫۲۵rem (۴px) هستند.
|
||||
4. **سرستون چسبان (sticky)** هنگام اسکرول عمودی.
|
||||
5. **اعداد همعرض** (`tabular-nums`) تا ستون تاریخها لق نزند.
|
||||
6. **تلفن با `direction: ltr`** تا ارقام در متن راستبهچپ جابهجا نشوند.
|
||||
7. **آدرس حداکثر دو خط** (`line-clamp`) با متن کامل در `title`.
|
||||
8. **تأخیر بهشکل چیپ رنگی** (خاکستری/کهربایی/قرمز/تیره) برای اسکن سریع.
|
||||
|
||||
| ستون | عرض | محتوا |
|
||||
|---|---|---|
|
||||
| نام و نام خانوادگی | ۲۳٪ | چیپ شماره + نام + کد مشتری |
|
||||
| وضعیت قرار | ۱۳٪ | برچسب رنگی وضعیت |
|
||||
| قرار هماهنگی | ۱۰٪ | تاریخ شمسی قرار دستی |
|
||||
| بازدید برنامهریزیشده | ۱۱٪ | تاریخ قرار از `Action` |
|
||||
| آخرین بازدید | ۱۰٪ | تاریخ مؤثر واقعی |
|
||||
| تأخیر | ۹٪ | چیپ تعداد روز |
|
||||
| تلفن | ۱۱٪ | شمارهٔ اول (LTR) |
|
||||
| آدرس | ۱۳٪ | دو خط + `title` |
|
||||
|
||||
**نقطهٔ شکست (breakpoint):** تا **۸۹۹px** حالت «کارت» و از **۹۰۰px** حالت
|
||||
«جدول». این دو مرز باید همیشه یکی باشند؛ اگر نباشند، در بازهای از عرض صفحه هر
|
||||
دو حالت همزمان اعمال میشوند و چیدمان میشکند. یک تست اختصاصی
|
||||
(`test_card_and_table_breakpoints_agree`) همین را قفل کرده است.
|
||||
|
||||
## ۶. قابلیتهای موبایل
|
||||
|
||||
- هر ردیف یک **کارت** میشود. نام مشتری سرِ کارت است (بدون برچسب) و بقیهٔ
|
||||
مقادیر با برچسب ثابت ۶٫۵rem همتراز میشوند.
|
||||
- برچسب «وضعیت» حذف میشود چون خودِ برچسب رنگی گویاست.
|
||||
- دکمهٔ **«تماس»** (`tel:`) و **«ثبت اقدام»** بهصورت دو دکمهٔ تمامعرض.
|
||||
- شمارههای دوم و سوم در موبایل مخفیاند (برای تماس، شمارهٔ اول کافی است).
|
||||
|
||||
## ۷. نمای خالی
|
||||
|
||||
اگر در نما/جستوجوی جاری موردی نباشد، پیام «موردی در این نما پیدا نشد»
|
||||
نمایش داده میشود (بهجای جدولِ خالی و گمراهکننده).
|
||||
|
||||
## ۸. کارایی
|
||||
|
||||
| سنجه | مقدار |
|
||||
|---|---|
|
||||
| تعداد کوئری در بارگذاری صفحه | **۱۹** |
|
||||
| رندر کامل صفحه روی دادهٔ واقعی (۳٬۲۴۳ معوق) | ~۱ ثانیه |
|
||||
|
||||
نکتهٔ پیادهسازی: دورهٔ قالب **یک بار** خوانده میشود و به حلقهٔ محاسبهٔ تأخیر
|
||||
پاس داده میشود (`months=period_months`). اگر این پارامتر پاس نشود، برای هر
|
||||
مشتری یک کوئری اضافه زده میشود (باگ N+1 که در تستها کشف و رفع شد).
|
||||
|
||||
## ۹. آنچه تغییر نکرد
|
||||
|
||||
- منطق «چه کسی عقبافتاده است» (همان `last_visit_map` + `due_cut`).
|
||||
- قاعدهٔ اعتبار قرار دستی (وجود هماهنگی فعال).
|
||||
- اسکنر پیامک، `recalc_last_bazdid` و چرخهٔ ۹ ماهه.
|
||||
- لینکهای قدیمی `?view=...` و رفتار پیشفرض (نمای «بدون قرار»).
|
||||
|
||||
## ۱۰. پارامترهای URL
|
||||
|
||||
```
|
||||
/panel/entezar/ نمای پیشفرض (بدون قرار، قدیمیترین)
|
||||
?view=all همهٔ معوقها
|
||||
?view=coordinated با قرار
|
||||
?view=manual فقط قرار هماهنگی
|
||||
?view=scheduled فقط بازدید برنامهریزیشده
|
||||
?sort=overdue بیشترین تأخیر اول
|
||||
?sort=newest جدیدترین بازدید اول
|
||||
?searchVal=رضایی&searchOn=name جستوجوی نام
|
||||
?searchVal=0912&searchOn=phone جستوجوی تلفن
|
||||
?view=all&sort=overdue&page=3 ترکیبپذیر
|
||||
```
|
||||
|
||||
مقدار نامعتبر `view` یا `sort` بیصدا به پیشفرض برمیگردد (هیچ خطای ۴۰۰/۵۰۰).
|
||||
|
||||
3. پس از تاریخ قرار، مشتری **خودکار** در گروه A ظاهر میشود؛ نیازی به کار دستی نیست.
|
||||
4. عدد «بدون قرار» در داشبورد همان لیست کاریِ فوری است.
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user