feat: add soft delete for classes with cascade to sessions and linked records

This commit is contained in:
2026-08-21 13:19:50 +03:30
parent 5b56171328
commit e34fd25af7
15 changed files with 184 additions and 33 deletions
+9
View File
@@ -84,6 +84,15 @@ const sessionSchema = new mongoose.Schema({
adminNotes: {
type: [String],
default: []
},
isDeleted: {
type: Boolean,
default: false,
index: true
},
deletedAt: {
type: Date,
default: null
}
}, {
timestamps: true
+15 -6
View File
@@ -124,7 +124,7 @@ const buildStudentsByClassId = async (sessions) => {
)];
if (!classIds.length) return new Map();
const classes = await Class.find({ _id: { $in: classIds } }).select('students').lean();
const classes = await Class.find({ _id: { $in: classIds }, isDeleted: { $ne: true } }).select('students').lean();
const allStudentIds = [...new Set(
classes.flatMap((cls) => (cls.students || []).map(normalizeId)).filter(Boolean)
)];
@@ -257,6 +257,12 @@ const getAllSessions = async (queryParams) => {
}
if (queryParams.professorId) filter.professor = queryParams.professorId;
if (queryParams.trash === 'true' || queryParams.isDeleted === 'true') {
filter.isDeleted = true;
} else {
filter.isDeleted = { $ne: true };
}
if (filter.status) {
filter.status = STATUS_MAP[filter.status] || filter.status;
}
@@ -313,7 +319,7 @@ const deleteSession = async (id) => {
if (!session) {
throw new AppError('SESSION_NOT_FOUND');
}
await Session.findByIdAndDelete(id);
await Session.findByIdAndUpdate(id, { $set: { isDeleted: true, deletedAt: new Date() } });
return null;
};
@@ -328,8 +334,11 @@ const bulkDeleteSessions = async (ids) => {
throw new AppError('VALIDATION_FAILED', { ids: 'Required' }, 'هیچ جلسه‌ای انتخاب نشده است.');
}
const result = await Session.deleteMany({ _id: { $in: sessionIds } });
return { deletedCount: result.deletedCount || 0 };
const result = await Session.updateMany(
{ _id: { $in: sessionIds } },
{ $set: { isDeleted: true, deletedAt: new Date() } }
);
return { deletedCount: result.modifiedCount || result.nModified || 0 };
};
const bulkUpdateSessionStatus = async (ids, status, actorId = null) => {
@@ -405,10 +414,10 @@ const updateSessionAttendance = async (sessionId, attendanceList, recordedBy = n
};
const getMySessions = async (userId, queryParams) => {
const userClasses = await Class.find({ students: userId }).select('_id');
const userClasses = await Class.find({ students: userId, isDeleted: { $ne: true } }).select('_id');
const classIds = userClasses.map((c) => c._id);
const filter = { class: { $in: classIds } };
const filter = { class: { $in: classIds }, isDeleted: { $ne: true } };
const { page, limit, skip } = parsePaginationAndSort(queryParams, 'day', 'asc');
const [matched, totalCount] = await Promise.all([