- Add implementation notes for cancellation and waitlist features. - Create task documentation outlining goals, current status, and acceptance criteria for cancellation policy and resource utilization reporting. - Establish architecture for domain events and outbox pattern to ensure reliable event publishing. - Define database schema for domain events and necessary queries for resource utilization and plan accuracy reports. - Implement detailed implementation notes covering edge cases, testing strategies, and documentation requirements.
4.6 KiB
4.6 KiB
تسک ۰۷ — رزرو موقت و ثبت نهایی چندمنبعی
فاز: ۱ (هسته) · وابستگی: ۰۶ · زمان: ۱۶-۲۰ ساعت
هدف
مستند بند ۱۱ و قانون سوم جمعبندی: «جلوگیری از رزرو تکراری کار دیتابیس است، نه کار کد».
سه مرحلهٔ جستجو → رزرو موقت → ثبت نهایی روی چند منبع پیاده شود، با تضمین یکتایی
در سطح دیتابیس.
وضعیت فعلی — نقطهٔ قوت پروژه
// src/Appointment/Entity/Appointment.php
public const PAYMENT_TTL = 900;
#[ORM\Column(name: 'active_slot_key', length: 64, nullable: true, unique: true)]
private ?string $activeSlotKey = null; // "{doctorId}:{slotStart}" یا NULL
private function refreshActiveSlotKey(): void {
$this->activeSlotKey = !$this->isReserve && in_array($this->status, self::SLOT_OCCUPYING_STATUSES, true)
? sprintf('%d:%d', $this->doctor->getId(), $this->slotStart)
: null;
}
سه مرحله و تضمین دیتابیسی از قبل درست پیاده شدهاند. محدودیت: کلید فقط
doctor + slot_start است و هیچ منبع دیگری را نمیپوشاند، و مدل «یک ردیف = یک بازهٔ پیوسته»
است.
دامنه
هست:
resource_occupancy— تنها مرجع حقیقت اشغال منابعappointment_segments— بخشهای نوبت ثبتشدهHoldService— رزرو موقت چندمنبعی با TTLBookingService— ثبت نهایی اتمی- تضمین یکتایی در MariaDB (بدون
EXCLUDE— راهحل «سطل زمانی») - انقضای خودکار hold ها (توسعهٔ
ExpireAppointmentsHandlerموجود) - وضعیت
rescheduledو رویداد جابهجایی
نیست: قیمتگذاری تفکیکشده (تسک ۰۸)، سیاست لغو و جریمه (تسک ۱۳).
Endpoint ها
| متد | مسیر | توضیح |
|---|---|---|
| POST | /api/v1/appointment-hold |
رزرو موقت یک زمان + منابعش |
| DELETE | /api/v1/appointment-hold/{uuid} |
آزادسازی زودهنگام |
| POST | /api/v1/appointment-confirm |
ثبت نهایی از یک hold معتبر |
| POST | /api/v1/appointment/{uuid}/reschedule |
جابهجایی (hold جدید + آزادسازی قدیم، اتمی) |
معیار پذیرش
- ✅ موفق:
POST /appointment-holdبا زمان وassignmentمعتبر →201باhold_uuidوexpires_at؛ ردیفهایresource_occupancyباstatus='hold'برای هر بخش × هر منبع ثبت میشوند. - ✅ موفق: بلافاصله بعد از hold،
POST /appointment-availabilityهمان زمان را برنمیگرداند. - ✅ موفق:
POST /appointment-confirm→200، وضعیتconfirmed، همهٔ ردیفهای اشغالstatus='booked'وexpires_at = NULL. - ✅ موفق (تست همزمانی — اصلیترین): دو درخواست hold همزمان روی همان منبع و بازه →
دقیقاً یکی
201و دیگری409باERR_SLOT_TAKEN. تست باید با تراکنش واقعی موازی اجرا شود، نه mock. - ✅ موفق: hold منقضیشده →
POST /appointment-confirmبا409 ERR_HOLD_EXPIREDو آن زمان دوباره در جستجو ظاهر میشود. - ✅ موفق: آزادسازی ظرفیت حفظ میشود — اپراتور در بخش انتظار ردیف اشغال ندارد.
- ❌ خطا:
confirmبا hold متعلق به کاربر دیگر →404. - ❌ خطا: hold با منبعی که در
assignmentنیست ولی نیازمندی دارد →422. - ⚠️ مرزی: منبع با
capacity=3→ سه hold همزمان موفق، چهارمی409. - ⚠️ مرزی: لغو نوبت → همهٔ ردیفهای اشغالش آزاد (
status='released')، نه حذف فیزیکی. - ⚠️ مرزی:
rescheduleکه hold جدیدش شکست بخورد → نوبت قدیمی دستنخورده بماند. - ⚠️ مرزی: نوبتهای حالت
slot/service→active_slot_keyقدیمی همچنان کار میکند و ردیف اشغال هم برایشان ساخته میشود (تور ایمنی دوگانه).
خروجی
src/Appointment/Booking/- توسعهٔ
Appointmententity باsegmentsو رابطهٔ اشغال docs/api/appointment-booking.md+ بهروزرسانیdocs/api/appointment.md- تست همزمانی واقعی