mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
units,lesson as standalone
This commit is contained in:
@@ -14,6 +14,9 @@ const sequelize = require('../../config/db.config');
|
||||
const { TaskCompletion, TaskCompletionFile } = require('../../models/task/task_completion.mdl');
|
||||
const { Task } = require('../../models/task/task.mdl');
|
||||
const mdl_Users = require('../../models/users/users.mdl');
|
||||
const UserNotification = require('../../models/notifications/user_notification.mdl');
|
||||
const { renderNotification } = require('../../services/notificationTemplate.service');
|
||||
const { checkTaskCompletion, fireTaskCompletedEvent } = require('../client/task.controller');
|
||||
|
||||
const { adminExclude } = require('../../models/task/task_completion.attributes');
|
||||
const R = require('../../utils/response.util');
|
||||
@@ -140,6 +143,69 @@ exports.getCompletionsByUser = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
// ─── REVIEW ───────────────────────────────────────────────────────────────────
|
||||
// PATCH /admin/task-lists/:taskListId/tasks/:taskId/completions/:completionId/review
|
||||
// Approves/rejects a submission for a requirement flagged requires_review.
|
||||
// Notifies the submitting learner via the existing template pattern (same shape
|
||||
// as updateTask's task_requirements_updated notify block).
|
||||
|
||||
exports.reviewSubmission = async (req, res) => {
|
||||
const t = await sequelize.transaction();
|
||||
try {
|
||||
const { taskListId, taskId, completionId } = req.params;
|
||||
const { status, review_note } = req.body;
|
||||
|
||||
if (!['approved', 'rejected'].includes(status)) {
|
||||
await t.rollback();
|
||||
return R.error(res, 'status must be "approved" or "rejected".', 400);
|
||||
}
|
||||
|
||||
const task = await Task.findOne({ where: { task_id: taskId, task_list_id: taskListId }, transaction: t });
|
||||
if (!task) { await t.rollback(); return R.error(res, 'Task not found.', 404); }
|
||||
|
||||
const completion = await TaskCompletion.findOne({
|
||||
where: { completion_id: completionId, task_id: taskId },
|
||||
transaction: t,
|
||||
});
|
||||
if (!completion) { await t.rollback(); return R.error(res, 'Completion not found.', 404); }
|
||||
|
||||
const wasComplete = status === 'approved' ? await checkTaskCompletion(completion.user_id, taskId) : false;
|
||||
|
||||
await completion.update({
|
||||
status,
|
||||
review_note: review_note || null,
|
||||
reviewed_by: req.user.user_id,
|
||||
reviewed_at: new Date(),
|
||||
updatedBy: req.user.user_id,
|
||||
}, { transaction: t });
|
||||
|
||||
await t.commit();
|
||||
|
||||
if (status === 'approved' && !wasComplete && await checkTaskCompletion(completion.user_id, taskId)) {
|
||||
fireTaskCompletedEvent(completion.user_id, taskId); // fire-and-forget
|
||||
}
|
||||
|
||||
logActivity(req.user.user_id, 'review_task_submission', {
|
||||
entityType: 'task_completion', entityId: completionId, details: { task_id: taskId, status },
|
||||
});
|
||||
|
||||
try {
|
||||
const notify = await renderNotification({ type: 'task_submission_reviewed', data: {
|
||||
taskName: task.name, status, review_note: review_note || null,
|
||||
} });
|
||||
await UserNotification.create({ user_id: completion.user_id, ...notify, seen: false });
|
||||
} catch (notifyErr) {
|
||||
console.error('[ADMIN][REVIEW SUBMISSION][NOTIFY]', notifyErr);
|
||||
}
|
||||
|
||||
return R.success(res, 'Submission reviewed.', completion);
|
||||
} catch (err) {
|
||||
await t.rollback();
|
||||
console.error('[ADMIN][REVIEW SUBMISSION]', err);
|
||||
return R.error(res, 'Could not review submission.', 500);
|
||||
}
|
||||
};
|
||||
|
||||
// ─── ARCHIVE ──────────────────────────────────────────────────────────────────
|
||||
// DELETE /admin/task-lists/:taskListId/tasks/:taskId/completions/:completionId
|
||||
|
||||
|
||||
Reference in New Issue
Block a user