- DB: protocol_booking_slots.days_of_week integer[] NOT NULL default {0..6} (0=Sun..6=Sat, Riyadh); pushed via drizzle-kit, legacy rows keep all-days behaviour.
- API (routes/protocol.ts): slot create/patch accept daysOfWeek (validated, deduped, sorted); new POST /protocol/booking-slots/generate (requireManageRooms) generates stepped slots in [from,to); duplicate rule is day-scoped: same start time on a different day merges the days into the existing slot (existing duration kept), fully covered times skipped; returns {created,merged,skipped,slots}; manual POST create also merges disjoint days instead of 409; matchesActiveSlot and public availability filter by Riyadh weekday.
- UI (protocol.tsx): interval-generation form (from/to/duration + day toggle pills + workdays/all-days presets), toast shows created/merged/skipped, slot list shows day names, booking dialog filters slots by chosen date weekday with stale-selection reset and empty-day hint. i18n keys added (ar/en).
- Tests: 13/13 pass incl. generation, day-scoped merge (same time different day is NOT a duplicate), duplicate skipping, validation, weekday filtering in availability + booking rejection, viewer 403 on generate.
- DB: protocol_booking_slots (وقت "HH:mm" بتوقيت الرياض، مدة، تفعيل، ترتيب)
+ protocol_settings (booking.minLeadMinutes، الافتراضي 60 دقيقة).
- API: CRUD /protocol/booking-slots (الكتابة تتطلب protocol.rooms.manage،
تكرار الوقت → 409 duplicate_slot)، GET/PATCH /protocol/settings (upsert + سجل
تدقيق)، ونقطة عامة /protocol/public/availability (محدّد معدل خاص، تعيد
booked/tooSoon/available لكل وقت).
- الفرض في الخادم: الطلب العام يجب أن يطابق وقتاً مفعّلاً + يحترم المهلة
(400 invalid_slot / lead_time برسائل عربية)؛ الموظفون ملزمون بالأوقات لكن
معفيون من المهلة. بدون أوقات مفعّلة يعمل الوضع الحر القديم.
- الواجهة: نموذج الطلب العام يعرض شبكة أوقات حسب التوفر (مع fallback قديم)؛
تبويب القاعات يعرض قسم إدارة الأوقات + المهلة لمن يملك canManageRooms؛
حوار الحجز الداخلي يتحول لتاريخ + قائمة أوقات عند وجود أوقات مفعّلة.
- i18n: مفاتيح protocol.slots.* بالعربية والإنجليزية.
- اختبارات: tests/protocol-booking-slots.test.mjs — 10 اختبارات ناجحة
(CRUD/تكرار، الإعدادات، التوفر، invalid_slot، lead_time، تعارض، وقت معطّل،
إعفاء الموظفين، صلاحيات القراءة/الكتابة، الحذف).
- مراجعة المعماري: PASS؛ عولجت الملاحظات (توثيق قرار الصلاحيات + اختبار
regression له، ومنع الإرسال في الواجهة قبل اختيار التاريخ والوقت).
- تعديل بعد الرفض الأول: قراءة قائمة الأوقات الكاملة والإعدادات تتطلب
protocol.rooms.manage (حسب المواصفة)؛ أُضيفت نقطة قراءة مصغّرة
/protocol/booking-slots/active (protocol.access) لحوار الحجز فقط.
- تعديل بعد الرفض الثاني: مهلة الحجز المسبقة (minLeadMinutes) تُطبَّق الآن
أيضًا على الحجوزات الداخلية (إنشاء وتعديل) — لا استثناء للموظفين.
- DB: protocol_booking_slots (وقت "HH:mm" بتوقيت الرياض، مدة، تفعيل، ترتيب)
+ protocol_settings (booking.minLeadMinutes، الافتراضي 60 دقيقة).
- API: CRUD /protocol/booking-slots (الكتابة تتطلب protocol.rooms.manage،
تكرار الوقت → 409 duplicate_slot)، GET/PATCH /protocol/settings (upsert + سجل
تدقيق)، ونقطة عامة /protocol/public/availability (محدّد معدل خاص، تعيد
booked/tooSoon/available لكل وقت).
- الفرض في الخادم: الطلب العام يجب أن يطابق وقتاً مفعّلاً + يحترم المهلة
(400 invalid_slot / lead_time برسائل عربية)؛ الموظفون ملزمون بالأوقات لكن
معفيون من المهلة. بدون أوقات مفعّلة يعمل الوضع الحر القديم.
- الواجهة: نموذج الطلب العام يعرض شبكة أوقات حسب التوفر (مع fallback قديم)؛
تبويب القاعات يعرض قسم إدارة الأوقات + المهلة لمن يملك canManageRooms؛
حوار الحجز الداخلي يتحول لتاريخ + قائمة أوقات عند وجود أوقات مفعّلة.
- i18n: مفاتيح protocol.slots.* بالعربية والإنجليزية.
- اختبارات: tests/protocol-booking-slots.test.mjs — 10 اختبارات ناجحة
(CRUD/تكرار، الإعدادات، التوفر، invalid_slot، lead_time، تعارض، وقت معطّل،
إعفاء الموظفين، صلاحيات القراءة/الكتابة، الحذف).
- مراجعة المعماري: PASS؛ عولجت الملاحظات (توثيق قرار الصلاحيات + اختبار
regression له، ومنع الإرسال في الواجهة قبل اختيار التاريخ والوقت).
- تعديل بعد الرفض الأول: قراءة قائمة الأوقات الكاملة والإعدادات تتطلب
protocol.rooms.manage (حسب المواصفة)؛ أُضيفت نقطة قراءة مصغّرة
/protocol/booking-slots/active (protocol.access) لحوار الحجز فقط.
- DB: protocol_booking_slots (وقت "HH:mm" بتوقيت الرياض، مدة، تفعيل، ترتيب)
+ protocol_settings (booking.minLeadMinutes، الافتراضي 60 دقيقة).
- API: CRUD /protocol/booking-slots (الكتابة تتطلب protocol.rooms.manage،
تكرار الوقت → 409 duplicate_slot)، GET/PATCH /protocol/settings (upsert + سجل
تدقيق)، ونقطة عامة /protocol/public/availability (محدّد معدل خاص، تعيد
booked/tooSoon/available لكل وقت).
- الفرض في الخادم: الطلب العام يجب أن يطابق وقتاً مفعّلاً + يحترم المهلة
(400 invalid_slot / lead_time برسائل عربية)؛ الموظفون ملزمون بالأوقات لكن
معفيون من المهلة. بدون أوقات مفعّلة يعمل الوضع الحر القديم.
- الواجهة: نموذج الطلب العام يعرض شبكة أوقات حسب التوفر (مع fallback قديم)؛
تبويب القاعات يعرض قسم إدارة الأوقات + المهلة لمن يملك canManageRooms؛
حوار الحجز الداخلي يتحول لتاريخ + قائمة أوقات عند وجود أوقات مفعّلة.
- i18n: مفاتيح protocol.slots.* بالعربية والإنجليزية.
- اختبارات: tests/protocol-booking-slots.test.mjs — 10 اختبارات ناجحة
(CRUD/تكرار، الإعدادات، التوفر، invalid_slot، lead_time، تعارض، وقت معطّل،
إعفاء الموظفين، صلاحيات القراءة/الكتابة، الحذف).
- مراجعة المعماري: PASS؛ عولجت الملاحظات (توثيق قرار الصلاحيات + اختبار
regression له، ومنع الإرسال في الواجهة قبل اختيار التاريخ والوقت).