- Add task for completing service mode in clinicpro with detailed objectives and acceptance criteria. - Create architecture documentation for task 00b, outlining involved components and necessary changes. - Develop checklist for task 00b to ensure all requirements are met. - Document implementation notes for task 00b, emphasizing API contract checks and design system adherence. - Update task documentation for task 00b, specifying goals and current issues with service mode.
124 lines
5.8 KiB
Markdown
124 lines
5.8 KiB
Markdown
# دیتابیس — تسک ۰۰
|
|
|
|
## تغییر `appointments` — دو ستون تهیپذیر
|
|
|
|
```sql
|
|
ALTER TABLE appointments
|
|
ADD COLUMN service_total_minutes SMALLINT NULL,
|
|
ADD COLUMN service_buffer_minutes SMALLINT NULL;
|
|
```
|
|
|
|
| ستون | معنی | چرا لازم است |
|
|
|---|---|---|
|
|
| `service_total_minutes` | مدت محاسبهشدهٔ ترکیب سرویسها در لحظهٔ ثبت | `slot_end - slot_start` عدد را دارد ولی نمیگوید عمدی بود یا دستی؛ و برای نوبت رزرو (که `slot_start = slot_end`) هیچجا مدت را نگه نمیداریم |
|
|
| `service_buffer_minutes` | `buffer_minutes` مؤثر در لحظهٔ ثبت | تغییر بافر در تنظیمات نباید معنای نوبتهای ثبتشده را عوض کند |
|
|
|
|
هر دو **تهیپذیر** و هر دو در حالت اسلاتی `NULL` میمانند. هیچ ستون موجودی حذف، تغییر
|
|
نوع یا تغییر معنا نمیدهد.
|
|
|
|
⛔ `slot_start` و `slot_end` و `active_slot_key` و `is_reserve` دستنخورده. خط سرخ.
|
|
|
|
### چرا نه یک ستون JSON
|
|
|
|
وسوسه: یک `service_meta JSON` با همهچیز. رد شد چون تسک ۱۴ (گزارش دقت برنامه) روی
|
|
`plan_total_minutes` تجمعی میزند و JSON را نمیتواند `AVG` کند. دو ستون `SMALLINT`
|
|
ارزانترند و تسک ۰۷ ستون `plan_total_minutes` را کنارشان اضافه میکند
|
|
(اسم متفاوت، معنی متفاوت: آن یکی مدت برنامهٔ چندبخشی است).
|
|
|
|
## ایندکس
|
|
|
|
هیچ ایندکس جدیدی. `idx_appointments_doctor_slot` و `idx_appointments_tenant_slot` موجود
|
|
همهٔ کوئریهای این تسک را پوشش میدهند.
|
|
|
|
## `appointment_service_items` — بدون تغییر schema
|
|
|
|
جدول واسط ManyToMany موجود. تنها تغییر، **رفتاری** است:
|
|
|
|
```php
|
|
// Appointment — متد جدید، بدون دست زدن به متدهای موجود
|
|
/** جایگزینی کامل سرویسها؛ serviceItem تکی هم با اولی همگام میشود. */
|
|
public function replaceServiceItems(array $items): self
|
|
{
|
|
$this->serviceItems->clear();
|
|
foreach ($items as $item) {
|
|
if (!$this->serviceItems->contains($item)) { $this->serviceItems->add($item); }
|
|
}
|
|
$this->serviceItem = $items[0] ?? null; // ← سازگاری با مصرفکنندهٔ تکی
|
|
$this->updatedAt = time();
|
|
return $this;
|
|
}
|
|
|
|
/** @return string[] uuid سرویسهای فعلی، به ترتیب */
|
|
public function currentServiceUuids(): array
|
|
{
|
|
$uuids = array_map(fn($i) => $i->getUuid(), $this->serviceItems->toArray());
|
|
if ($uuids === [] && $this->serviceItem !== null) { $uuids = [$this->serviceItem->getUuid()]; }
|
|
return $uuids;
|
|
}
|
|
```
|
|
|
|
همگامسازی `serviceItem` تکی اجباری است: `AppointmentsPage`، `ReserveAppointmentsPage`،
|
|
`nobat724_front` و `clinic-pro-tauri` هر چهار روی `service_item` تکی خواندهاند. رهاکردنش
|
|
یعنی نوبت با سرویسهای جدید ولی نام سرویس قدیمی در لیست.
|
|
|
|
## کدهای خطای جدید
|
|
|
|
در `src/Shared/Constant/ErrorCodes.php`:
|
|
|
|
```php
|
|
public const ERR_SERVICE_DURATION_MISMATCH = 'ERR_APPOINTMENT_010';
|
|
// پیام: مدت این نوبت با مجموع مدت سرویسهای انتخابی نمیخواند
|
|
|
|
public const ERR_WRONG_BOOKING_MODE = 'ERR_APPOINTMENT_011';
|
|
// پیام: این عملیات با روش نوبتدهی این محیط سازگار نیست
|
|
```
|
|
|
|
شمارهٔ بعدی دامنهٔ `APPOINTMENT` را از خود فایل بگیر، این دو عدد حدسیاند.
|
|
هر دو کد در تسکهای ۰۶ و ۰۷ هم استفاده میشوند، پس نامشان عمومی است نه مخصوص این تسک.
|
|
|
|
## Migration
|
|
|
|
```bash
|
|
ddev exec php bin/console doctrine:migrations:diff --no-interaction
|
|
ddev exec php bin/console doctrine:migrations:migrate --no-interaction
|
|
```
|
|
|
|
## backfill
|
|
|
|
```bash
|
|
ddev exec php bin/console app:appointment:backfill-service-duration # dry-run
|
|
ddev exec php bin/console app:appointment:backfill-service-duration --force
|
|
```
|
|
|
|
برای هر نوبت `pending`/`confirmed` **آیندهٔ** یک محیط سرویسی که `service_total_minutes`
|
|
ندارد:
|
|
|
|
```
|
|
service_total_minutes = (slot_end - slot_start) / 60
|
|
service_buffer_minutes = buffer_minutes فعلیِ همان برنامه
|
|
```
|
|
|
|
مقدار از خودِ نوبت گرفته میشود، **نه از مدت سرویسها** — چون نوبت موجود ممکن است با
|
|
مدت دستی ثبت شده باشد و بازمحاسبه یعنی تغییر گذشته.
|
|
|
|
نوبتهای اسلاتی و نوبتهای گذشته رد میشوند. idempotent.
|
|
|
|
## fixture های تست خط سرخ
|
|
|
|
```
|
|
tests/Appointment/fixtures/slot-mode-contract.json # پاسخ appointment-slots
|
|
tests/Appointment/fixtures/month-availability-contract.json # پاسخ month-availability
|
|
tests/Appointment/fixtures/slot-calculator-signatures.php # امضای متدهای عمومی
|
|
```
|
|
|
|
⛔ این سه فایل بعد از این تسک **read-only** اند. هیچ تسکی اجازهٔ بهروزرسانیشان را ندارد.
|
|
اگر تستی قرمز شد، کد باید برگردد نه fixture. این جمله را در بالای هر سه فایل بهعنوان
|
|
کامنت بنویس.
|
|
|
|
fixture ها با تاریخ ثابت ساخته میشوند (`2026-01-05` مثلاً)، نه `time()` — وگرنه فردا قرمز.
|
|
|
|
## طبقهبندی tenant
|
|
|
|
هیچ entity جدیدی. `appointments` از قبل جفت tenant دارد.
|
|
`TenantSchemaCoverageTest` باید بدون تغییر سبز بماند.
|