feat: Implement resource booking functionality
- Add service timeline builder for appointments to manage available slots. - Create a hook to fetch resource booking services with effective durations. - Develop ResourceBookingSlotController to handle API requests for resource booking slots. - Implement ResourceBookingSlotService to calculate available time slots based on resource occupancy and service durations. - Add tests for resource appointment creation and booking slot functionality to ensure correct behavior and edge cases.
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { buildServiceTimeline } from './serviceTimeline';
|
||||
import type { Appointment } from '../../types';
|
||||
|
||||
const DAY = 1_800_000_000; // نیمهشبِ فرضی
|
||||
const at = (h: number) => DAY + h * 3600;
|
||||
|
||||
function appointment(from: number, to: number, over: Partial<Appointment> = {}): Appointment {
|
||||
return {
|
||||
uuid: `a-${from}`, patient_name: 'بیمار', patient_mobile: '09120000000',
|
||||
doctor_uuid: 'd1', doctor_name: 'دکتر', slot_start: from, slot_end: to,
|
||||
appointment_date: '', appointment_time: '', end_time: '',
|
||||
status: 'confirmed', version: 1, created_at: '',
|
||||
...over,
|
||||
} as Appointment;
|
||||
}
|
||||
|
||||
describe('buildServiceTimeline', () => {
|
||||
const window = [{ start: at(8), end: at(14) }];
|
||||
|
||||
it('یک نوبت، بازهٔ کاری را به «خالی — نوبت — خالی» میشکند', () => {
|
||||
const rows = buildServiceTimeline(window, [appointment(at(10), at(11))], at(0));
|
||||
|
||||
expect(rows.map(r => [r.start, r.end, r.appointment !== null])).toEqual([
|
||||
[at(8), at(10), false],
|
||||
[at(10), at(11), true],
|
||||
[at(11), at(14), false],
|
||||
]);
|
||||
});
|
||||
|
||||
it('بدون نوبت، کل بازهٔ کاری یک ردیفِ خالی است', () => {
|
||||
const rows = buildServiceTimeline(window, [], at(0));
|
||||
|
||||
expect(rows).toHaveLength(1);
|
||||
expect(rows[0].is_available).toBe(true);
|
||||
});
|
||||
|
||||
it('نوبت لغوشده جای خالی را نمیگیرد', () => {
|
||||
const rows = buildServiceTimeline(
|
||||
window,
|
||||
[appointment(at(10), at(11), { status: 'cancelled_by_doctor' })],
|
||||
at(0),
|
||||
);
|
||||
|
||||
expect(rows).toHaveLength(1);
|
||||
expect(rows[0].appointment).toBeNull();
|
||||
});
|
||||
|
||||
it('نوبتِ رزرو (روزانه) بازهای اشغال نمیکند', () => {
|
||||
const rows = buildServiceTimeline(window, [appointment(at(10), at(11), { is_reserve: true })], at(0));
|
||||
|
||||
expect(rows).toHaveLength(1);
|
||||
expect(rows[0].appointment).toBeNull();
|
||||
});
|
||||
|
||||
it('بازهٔ خالیِ گذشته به «اکنون» بریده میشود و ردیفِ تمامگذشته حذف', () => {
|
||||
const rows = buildServiceTimeline([{ start: at(8), end: at(9) }, { start: at(10), end: at(14) }], [], at(11));
|
||||
|
||||
expect(rows).toHaveLength(1);
|
||||
expect(rows[0].start).toBe(at(11));
|
||||
expect(rows[0].end).toBe(at(14));
|
||||
});
|
||||
|
||||
it('نوبتِ خارج از بازهٔ کاری، ردیف نمیسازد', () => {
|
||||
const rows = buildServiceTimeline(window, [appointment(at(20), at(21))], at(0));
|
||||
|
||||
expect(rows.every(r => r.appointment === null)).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user