feat(api): add schedule series delete endpoint

This commit is contained in:
avicenan
2026-03-25 13:45:10 +07:00
parent ab14a0b670
commit ab40036f45
3 changed files with 77 additions and 0 deletions

View File

@ -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<void | Response> {
/*
#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);
}
}
}

View File

@ -354,6 +354,42 @@ export class ScheduleModel {
return OrmHelper.DB.manager.save(exception);
}
static async deleteSeries(id: string, hard: boolean, actor: string): Promise<number> {
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;

View File

@ -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)