feat(migrations): add clinic_id context to weekly_schedules, date_overrides, and holidays

- Introduced clinic_id to weekly_schedules, date_overrides, and holidays to differentiate between personal and clinic schedules.
- Updated unique constraints and indexes to accommodate the new clinic context.

feat(command): create AssignScheduleClinicCommand to move schedules

- Added a command to move a doctor's personal weekly schedule into a clinic context.
- Implemented checks to ensure sessions align with the target clinic.

feat(context): implement EntityContext and EntityContextResolver

- Created EntityContext to represent the effective working environment of a request (doctor or clinic).
- Developed EntityContextResolver to determine the execution context based on user roles and active contexts.

test: add ServiceModeContextTest for appointment scheduling

- Implemented tests to ensure service booking respects clinic and personal contexts.
- Verified that financial data is omitted in clinic contexts in InvitedDoctorDashboardScopeTest.
This commit is contained in:
hamed
2026-07-18 13:32:56 +03:30
parent 2553b45990
commit f1258d206d
28 changed files with 2126 additions and 276 deletions
+11 -1
View File
@@ -1137,10 +1137,20 @@ export default function DoctorDetailPage({ isOwnProfile = false }: { isOwnProfil
const primaryRole = useAuthStore(s => s.primaryRole);
const dbUuid = useAuthStore(s => s.dbUuid);
const doctorUuid = useAuthStore(s => s.doctorUuid);
const context = useAuthStore(s => s.context);
const availableContexts = useAuthStore(s => s.availableContexts);
const uuid = isOwnProfile ? (doctorUuid ?? dbUuid ?? undefined) : paramUuid;
// نماینده فقط مشاهده می‌کند؛ هیچ بخشی قابل ویرایش نیست.
const isReadOnly = primaryRole === 'representation';
// صفحهٔ پزشک در پنل کلینیک، تنظیمات نوبت‌دهیِ همان کلینیک را ویرایش می‌کند — نه
// برنامهٔ مطب شخصی پزشک، که فقط خودش به آن دسترسی دارد.
const scheduleClinicUuid = useMemo(() => {
if (isOwnProfile) return null;
if (context?.type === 'clinic') return dbUuid;
return availableContexts.find(c => c.type === 'clinic')?.db_uuid ?? null;
}, [isOwnProfile, context, dbUuid, availableContexts]);
const [editOpen, setEditOpen] = useState(searchParams.get('edit') === '1');
const [deleteOpen, setDeleteOpen] = useState(false);
const [toggleConfirm, setToggleConfirm] = useState(false);
@@ -1589,7 +1599,7 @@ export default function DoctorDetailPage({ isOwnProfile = false }: { isOwnProfil
)}
</div>
{uuid && !isOwnProfile && <ScheduleSection doctorUuid={uuid} readOnly={isReadOnly} />}
{uuid && !isOwnProfile && <ScheduleSection doctorUuid={uuid} clinicUuid={scheduleClinicUuid} readOnly={isReadOnly} />}
{isOwnProfile && <ClinicInvitationsSection />}