diff --git a/src/controllers/schedule.ts b/src/controllers/schedule.ts index 1a2177a..9dc791c 100644 --- a/src/controllers/schedule.ts +++ b/src/controllers/schedule.ts @@ -197,7 +197,11 @@ export class ScheduleController { code: 200, message: 'success', data: { - series: { id: 'uuid-string', title: 'Practice Schedule' }, + series: { + id: 'uuid-string', + title: 'Practice Schedule', + recurrence: { $ref: '#/components/schemas/scheduleRecurrence' } + }, exceptions: [{ id: 'uuid-string', occurrence_date: '2026-03-24' }] } } diff --git a/src/model/schedule.ts b/src/model/schedule.ts index e565062..8494620 100644 --- a/src/model/schedule.ts +++ b/src/model/schedule.ts @@ -237,7 +237,16 @@ export class ScheduleModel { .orderBy("ScheduleException.occurrence_date", "ASC") .getMany(); - return { series, exceptions }; + const recurrenceRule = series.recurrence_rule; + const { recurrence_rule: _omitRule, ...seriesRest } = series as ScheduleSeries & { recurrence_rule?: string | null }; + + return { + series: { + ...seriesRest, + recurrence: ScheduleModel.rRuleToRecurrence(recurrenceRule), + }, + exceptions, + }; } static async createSeries(payload: ScheduleSeriesPayload, actor: string): Promise { @@ -466,6 +475,30 @@ export class ScheduleModel { throw new Error("Unsupported recurrence type"); } + private static rRuleToRecurrence(recurrence_rule: string | null): RecurrenceInput | null { + if (!recurrence_rule || !String(recurrence_rule).trim()) return null; + const parsed = ScheduleModel.parseRRule(recurrence_rule); + if (!parsed.freq) return null; + + const interval = parsed.interval && parsed.interval > 0 ? parsed.interval : 1; + const freq = parsed.freq.toUpperCase(); + + if (freq === "DAILY") { + return { type: "daily", interval }; + } + if (freq === "WEEKLY") { + const out: RecurrenceInput = { type: "weekly", interval }; + if (parsed.byDay && parsed.byDay.length > 0) { + out.daysOfWeek = parsed.byDay; + } + return out; + } + if (freq === "MONTHLY") { + return { type: "monthly", interval }; + } + return null; + } + private static async getDailyUsedQuotaMap(seriesIds: string[], rangeStart: Date, rangeEnd: Date): Promise> { const usedQuotaMap = new Map(); if (seriesIds.length === 0) return usedQuotaMap; diff --git a/src/swagger/builder.js b/src/swagger/builder.js index 022d920..c9167ef 100644 --- a/src/swagger/builder.js +++ b/src/swagger/builder.js @@ -385,6 +385,22 @@ const doc = { $endTimeLocal: "13:00:00", $recurrence: { $ref: "#/components/schemas/scheduleRecurrence" } }, + scheduleSeriesDetail: { + $id: "uuid-string", + $room_id: "uuid-string", + $doctor_id: "uuid-string", + $title: "Practice Schedule", + $timezone: "Asia/Jakarta", + $quota: 20, + $start_date: "2026-03-20", + $until_date: "2026-06-30", + $start_time_local: "09:00:00", + $end_time_local: "12:00:00", + $recurrence: { $ref: "#/components/schemas/scheduleRecurrence" }, + $status: "Active", + $room: { id: "uuid-string", room: "Room 1" }, + $doctor: { id: "uuid-string", name: "Dr A" } + }, scheduleExceptionCreate: { $occurrenceDate: "2026-03-24", $isCancelled: false,