diff --git a/src/controllers/schedule.ts b/src/controllers/schedule.ts index 9dc791c..809d383 100644 --- a/src/controllers/schedule.ts +++ b/src/controllers/schedule.ts @@ -341,4 +341,44 @@ export class ScheduleController { return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_insert, err.message); } } + + static async delete(req: Request, res: Response, next: NextFunction): Promise { + /* + #swagger.tags = ['Schedule'] + #swagger.security = [{ "bearerAuth": [] }] + #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } + #swagger.parameters['hard'] = { in: 'path', description: 'Is Hard Delete', required: false, type: 'boolean' } + #swagger.responses[200] = { + description: 'Schedule series deleted', + schema: { status: true, code: 200, message: 'success', data: {} } + } + */ + try { + const schema = Joi.object().keys({ + id: Joi.string().uuid().required().label("ID"), + hard: Joi.alternatives() + .try(Joi.boolean(), Joi.string().valid("", "true", "false", "1", "0")) + .optional() + .label("Is hard delete?"), + }); + + const param: { id: string; hard?: boolean | string } = await schema.validateAsync(req.params); + + const isHardDelete = + param.hard === true || param.hard === "true" || param.hard === "1"; + + const actor = req.auth?.data?.name || "system"; + const affected = await ScheduleModel.deleteSeries(param.id, isHardDelete, actor); + + if (affected > 0) { + return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); + } else { + return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); + } + } catch (e: unknown) { + log.error(e); + const err = e as Error; + return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); + } + } } diff --git a/src/model/schedule.ts b/src/model/schedule.ts index 8494620..9b43503 100644 --- a/src/model/schedule.ts +++ b/src/model/schedule.ts @@ -354,6 +354,42 @@ export class ScheduleModel { return OrmHelper.DB.manager.save(exception); } + static async deleteSeries(id: string, hard: boolean, actor: string): Promise { + const manager = OrmHelper.DB.manager; + + if (hard) { + await manager.delete(ScheduleException, { series_id: id }); + const result = await manager.delete(ScheduleSeries, { id }); + return result.affected ?? 0; + } + + const series = await OrmHelper.DB.getRepository(ScheduleSeries) + .createQueryBuilder("ScheduleSeries") + .where("ScheduleSeries.id = :id", { id }) + .andWhere("ScheduleSeries.deleted_at IS NULL") + .getOne(); + + if (!series) return 0; + + const now = new Date(); + + await manager.transaction(async (tx) => { + await tx + .createQueryBuilder() + .update(ScheduleException) + .set({ deleted_at: now, deleted_by: actor }) + .where("series_id = :id", { id }) + .andWhere("deleted_at IS NULL") + .execute(); + + series.deleted_at = now; + series.deleted_by = actor; + await tx.save(series); + }); + + return 1; + } + private static expandSeriesOccurrences(series: ScheduleSeries, rangeStart: Date, rangeEnd: Date): Date[] { const seriesStart = ScheduleModel.startOfDay(new Date(series.start_date)); const seriesUntil = series.until_date ? ScheduleModel.endOfDay(new Date(series.until_date)) : null; diff --git a/src/routes/private.ts b/src/routes/private.ts index f5549c1..88cd73f 100644 --- a/src/routes/private.ts +++ b/src/routes/private.ts @@ -213,6 +213,7 @@ export class RoutePrivate { app.get('/api/schedule/options', ScheduleController.options) app.get('/api/schedule/calendar', ScheduleController.calendar) app.post('/api/schedule/:id/create-exception', ScheduleController.createException) + app.delete('/api/schedule/delete/:id/:hard', ScheduleController.delete) app.get('/api/doctor-item/list', DoctorItemController.listAll) app.get('/api/doctor-item/list-fav', DoctorItemController.listFav)