mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
ready to test
Testing Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
@@ -20,6 +20,7 @@ const { filterableFields } = require('../../models/task/task.attributes');
|
||||
const { getFieldValues } = require('../../utils/fieldValues.util');
|
||||
const { archiveOne, archiveMany } = require("../../utils/courses/archive.util");
|
||||
const { restoreOne, restoreMany } = require("../../utils/courses/restore.util");
|
||||
const logActivity = require('../../utils/logActivity.util');
|
||||
|
||||
// ─── Allowed filter/sort fields ───────────────────────────────────────────────
|
||||
const TASK_LIST_FIELDS = ['name', 'description', 'createdAt', 'updatedAt', 'deletedAt'];
|
||||
@@ -118,6 +119,7 @@ exports.createTaskList = async (req, res) => {
|
||||
updatedBy: req.user.user_id,
|
||||
});
|
||||
|
||||
logActivity(req.user.user_id, 'create_task_list', { entityType: 'task_list', entityId: taskList.task_list_id, details: { name: taskList.name } });
|
||||
return R.success(res, 'Task list created successfully.', taskList, 201);
|
||||
} catch (err) {
|
||||
console.error('[ADMIN][CREATE TASK LIST]', err);
|
||||
@@ -138,6 +140,7 @@ exports.updateTaskList = async (req, res) => {
|
||||
|
||||
await taskList.update({ name, description, updatedBy: req.user.user_id });
|
||||
|
||||
logActivity(req.user.user_id, 'update_task_list', { entityType: 'task_list', entityId: taskList.task_list_id });
|
||||
return R.success(res, 'Task list updated successfully.', taskList);
|
||||
} catch (err) {
|
||||
console.error('[ADMIN][UPDATE TASK LIST]', err);
|
||||
@@ -152,12 +155,13 @@ exports.archiveTaskList = async (req, res) => {
|
||||
try {
|
||||
const { taskListId } = req.params;
|
||||
|
||||
const record = await archiveOne(TaskList, { task_list_id: taskListId },
|
||||
const record = await archiveOne(TaskList, { task_list_id: taskListId },
|
||||
req.user.user_id, t
|
||||
);
|
||||
if (!record) { await t.rollback(); return R.error(res, 'Task list not found.', 404); }
|
||||
|
||||
await t.commit();
|
||||
logActivity(req.user.user_id, 'archive_task_list', { entityType: 'task_list', entityId: Number(taskListId) });
|
||||
return R.success(res, 'Task list archived successfully.');
|
||||
} catch (err) {
|
||||
await t.rollback();
|
||||
@@ -177,6 +181,7 @@ exports.restoreTaskList = async (req, res) => {
|
||||
if (!record) { await t.rollback(); return R.error(res, 'Task list not found or not archived.', 404); }
|
||||
|
||||
await t.commit();
|
||||
logActivity(req.user.user_id, 'restore_task_list', { entityType: 'task_list', entityId: Number(taskListId) });
|
||||
return R.success(res, 'Task list restored successfully.', record);
|
||||
} catch (err) {
|
||||
await t.rollback();
|
||||
@@ -203,6 +208,7 @@ exports.bulkArchiveTaskLists = async (req, res) => {
|
||||
|
||||
const count = await archiveMany(TaskList, 'task_list_id', activeIds, req.user.user_id, t);
|
||||
await t.commit();
|
||||
logActivity(req.user.user_id, 'bulk_archive_task_lists', { entityType: 'task_list', details: { ids: activeIds, count } });
|
||||
return R.success(res, `${count} task list(s) archived successfully.`, {
|
||||
archived_ids: activeIds,
|
||||
skipped_ids: ids.filter((id) => !activeIds.includes(id)),
|
||||
@@ -232,6 +238,7 @@ exports.bulkRestoreTaskLists = async (req, res) => {
|
||||
|
||||
const count = await restoreMany(TaskList, 'task_list_id', deletedIds, req.user.user_id, t);
|
||||
await t.commit();
|
||||
logActivity(req.user.user_id, 'bulk_restore_task_lists', { entityType: 'task_list', details: { ids: deletedIds, count } });
|
||||
return R.success(res, `${count} task list(s) restored successfully.`, {
|
||||
restored_ids: deletedIds,
|
||||
skipped_ids: ids.filter((id) => !deletedIds.includes(id)),
|
||||
@@ -330,6 +337,7 @@ exports.assignGroups = async (req, res) => {
|
||||
}
|
||||
|
||||
await t.commit();
|
||||
logActivity(req.user.user_id, 'assign_groups', { entityType: 'task_list', entityId: Number(taskListId), details: { group_ids: newIds } });
|
||||
return R.success(res, `${newIds.length} group(s) assigned.`, {
|
||||
assigned_ids: newIds,
|
||||
already_assigned_ids: existingIds,
|
||||
@@ -384,6 +392,7 @@ exports.unassignGroups = async (req, res) => {
|
||||
});
|
||||
|
||||
await t.commit();
|
||||
logActivity(req.user.user_id, 'unassign_groups', { entityType: 'task_list', entityId: Number(taskListId), details: { group_ids: existingIds } });
|
||||
return R.success(res, `${existingIds.length} group(s) unassigned.`, {
|
||||
unassigned_ids: existingIds,
|
||||
skipped_ids: skippedIds,
|
||||
@@ -437,7 +446,6 @@ exports.getTask = async (req, res) => {
|
||||
{
|
||||
model: TaskRequirement,
|
||||
as: 'requirements',
|
||||
paranoid: false,
|
||||
attributes: { exclude: adminExclude },
|
||||
order: [['order', 'ASC']],
|
||||
},
|
||||
@@ -515,6 +523,7 @@ exports.createTask = async (req, res) => {
|
||||
}],
|
||||
});
|
||||
|
||||
logActivity(req.user.user_id, 'create_task', { entityType: 'task', entityId: task.task_id, details: { name: task.name } });
|
||||
return R.success(res, 'Task created successfully.', full, 201);
|
||||
} catch (err) {
|
||||
await t.rollback();
|
||||
@@ -546,6 +555,23 @@ exports.updateTask = async (req, res) => {
|
||||
{ transaction: t }
|
||||
);
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// PATCH: exports.updateTask in task.controller.js (admin)
|
||||
//
|
||||
// BUG: TaskRequirement.destroy({ where: { task_id }, force: false }) is a
|
||||
// SOFT delete (paranoid: true) — the row stays in the table with deletedAt
|
||||
// set, still occupying its requirement_id primary key slot. The subsequent
|
||||
// bulkCreate spread `...r`, which still carried the OLD requirement_id from
|
||||
// the requirement object the frontend sent back (since RequirementBuilder.jsx
|
||||
// initializes from the previously-fetched requirements, including their IDs).
|
||||
// Inserting a new row with that same requirement_id collides with the
|
||||
// soft-deleted row still sitting on that PK → SequelizeUniqueConstraintError.
|
||||
//
|
||||
// FIX: strip requirement_id (and any timestamp fields) from each incoming
|
||||
// requirement before building reqRows, so bulkCreate always lets the model's
|
||||
// defaultValue: DataTypes.UUIDV4 generate a fresh ID for the replacement set.
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
if (Array.isArray(requirements)) {
|
||||
// soft-delete existing requirements then insert fresh ones
|
||||
await TaskRequirement.destroy({
|
||||
@@ -555,17 +581,24 @@ exports.updateTask = async (req, res) => {
|
||||
});
|
||||
|
||||
if (requirements.length) {
|
||||
const reqRows = requirements.map((r, i) => ({
|
||||
...r,
|
||||
task_id: task.task_id,
|
||||
order: r.order ?? i,
|
||||
reference_id: r.reference_id || null, // '' → null (UUID column)
|
||||
reference_label: r.reference_label || null, // '' → null
|
||||
link_url: r.link_url || null,
|
||||
link_label: r.link_label || null,
|
||||
createdBy: req.user.user_id,
|
||||
updatedBy: req.user.user_id,
|
||||
}));
|
||||
const reqRows = requirements.map((r, i) => {
|
||||
// Strip requirement_id and timestamps — these are server-owned.
|
||||
// Reusing requirement_id here would collide with the soft-deleted
|
||||
// row still occupying that primary key.
|
||||
const { requirement_id, createdAt, updatedAt, deletedAt, ...rest } = r;
|
||||
|
||||
return {
|
||||
...rest,
|
||||
task_id: task.task_id,
|
||||
order: rest.order ?? i,
|
||||
reference_id: rest.reference_id || null, // '' → null (UUID column)
|
||||
reference_label: rest.reference_label || null, // '' → null
|
||||
link_url: rest.link_url || null,
|
||||
link_label: rest.link_label || null,
|
||||
createdBy: req.user.user_id,
|
||||
updatedBy: req.user.user_id,
|
||||
};
|
||||
});
|
||||
await TaskRequirement.bulkCreate(reqRows, { transaction: t });
|
||||
}
|
||||
}
|
||||
@@ -582,6 +615,7 @@ exports.updateTask = async (req, res) => {
|
||||
}],
|
||||
});
|
||||
|
||||
logActivity(req.user.user_id, 'update_task', { entityType: 'task', entityId: Number(taskId) });
|
||||
return R.success(res, 'Task updated successfully.', full);
|
||||
} catch (err) {
|
||||
await t.rollback();
|
||||
@@ -654,6 +688,7 @@ exports.archiveTask = async (req, res) => {
|
||||
if (!record) { await t.rollback(); return R.error(res, 'Task not found.', 404); }
|
||||
|
||||
await t.commit();
|
||||
logActivity(req.user.user_id, 'archive_task', { entityType: 'task', entityId: Number(taskId) });
|
||||
return R.success(res, 'Task archived successfully.');
|
||||
} catch (err) {
|
||||
await t.rollback();
|
||||
@@ -678,6 +713,7 @@ exports.restoreTask = async (req, res) => {
|
||||
if (!record) { await t.rollback(); return R.error(res, 'Task not found or not archived.', 404); }
|
||||
|
||||
await t.commit();
|
||||
logActivity(req.user.user_id, 'restore_task', { entityType: 'task', entityId: Number(taskId) });
|
||||
return R.success(res, 'Task restored successfully.', record);
|
||||
} catch (err) {
|
||||
await t.rollback();
|
||||
@@ -705,6 +741,7 @@ exports.bulkArchiveTasks = async (req, res) => {
|
||||
|
||||
const count = await archiveMany(Task, 'task_id', activeIds, req.user.user_id, t);
|
||||
await t.commit();
|
||||
logActivity(req.user.user_id, 'bulk_archive_tasks', { entityType: 'task', details: { ids: activeIds, count } });
|
||||
return R.success(res, `${count} task(s) archived successfully.`, {
|
||||
archived_ids: activeIds,
|
||||
skipped_ids: ids.filter((id) => !activeIds.includes(id)),
|
||||
@@ -738,6 +775,7 @@ exports.bulkRestoreTasks = async (req, res) => {
|
||||
|
||||
const count = await restoreMany(Task, 'task_id', deletedIds, req.user.user_id, t);
|
||||
await t.commit();
|
||||
logActivity(req.user.user_id, 'bulk_restore_tasks', { entityType: 'task', details: { ids: deletedIds, count } });
|
||||
return R.success(res, `${count} task(s) restored successfully.`, {
|
||||
restored_ids: deletedIds,
|
||||
skipped_ids: ids.filter((id) => !deletedIds.includes(id)),
|
||||
|
||||
Reference in New Issue
Block a user