mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
added and fix some of things
Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
@@ -1,15 +1,32 @@
|
||||
'use strict';
|
||||
const { Op } = require('sequelize');
|
||||
const mdl_Category = require('../../models/courses/categories.mdl');
|
||||
const mdl_Users = require('../../models/users/users.mdl');
|
||||
const { CourseProductCategory } = require('../../models/courses/courses.mdl');
|
||||
const R = require('../../utils/response.util');
|
||||
const logActivity = require('../../utils/logActivity.util');
|
||||
const { paginate } = require('../../utils/paginate.util');
|
||||
const {
|
||||
excludeAttributes: categoriesExclude,
|
||||
jsonbSchemas: categoriesSchemas,
|
||||
} = require('../../models/courses/categories.attributes');
|
||||
|
||||
const slugify = (str) =>
|
||||
str.toLowerCase().trim().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');
|
||||
|
||||
exports.getCategories = async (req, res) => {
|
||||
try {
|
||||
const rows = await mdl_Category.findAll({ order: [['name', 'ASC']], paranoid: false });
|
||||
return R.success(res, 'Categories retrieved.', rows);
|
||||
const archived = req.query.archived === 'true';
|
||||
const result = await paginate(mdl_Category, req, {
|
||||
excludeAttributes: categoriesExclude,
|
||||
jsonbSchemas: categoriesSchemas,
|
||||
context: archived ? 'archived' : 'list',
|
||||
auditOptions: { mdl_Users, parentAlias: 'Category' },
|
||||
findOptions: archived
|
||||
? { paranoid: false, where: { deletedAt: { [Op.ne]: null } } }
|
||||
: {},
|
||||
});
|
||||
return R.success(res, 'Categories retrieved.', result);
|
||||
} catch (err) {
|
||||
console.error('[ADMIN][CATEGORIES][GET ALL]', err);
|
||||
return R.error(res, 'Could not retrieve categories.', 500);
|
||||
@@ -33,7 +50,10 @@ exports.createCategory = async (req, res) => {
|
||||
if (!name) return R.error(res, 'name is required.', 400);
|
||||
|
||||
const slug = slugify(name);
|
||||
const row = await mdl_Category.create({ name, slug, description: description ?? null, is_active: is_active ?? true });
|
||||
const row = await mdl_Category.create({
|
||||
name, slug, description: description ?? null, is_active: is_active ?? true,
|
||||
createdBy: req.body.createdBy ?? req.user?.user_id ?? null,
|
||||
});
|
||||
logActivity(req.user?.user_id, 'create_category', { entityType: 'category', entityId: row.category_id, details: { name: row.name } });
|
||||
return R.success(res, 'Category created.', row, 201);
|
||||
} catch (err) {
|
||||
@@ -51,7 +71,10 @@ exports.updateCategory = async (req, res) => {
|
||||
|
||||
const { name, description, is_active } = req.body;
|
||||
const slug = name ? slugify(name) : row.slug;
|
||||
await row.update({ name: name ?? row.name, slug, description: description ?? row.description, is_active: is_active ?? row.is_active });
|
||||
await row.update({
|
||||
name: name ?? row.name, slug, description: description ?? row.description, is_active: is_active ?? row.is_active,
|
||||
updatedBy: req.body.updatedBy ?? req.user?.user_id ?? null,
|
||||
});
|
||||
logActivity(req.user?.user_id, 'update_category', { entityType: 'category', entityId: row.category_id });
|
||||
return R.success(res, 'Category updated.', row);
|
||||
} catch (err) {
|
||||
@@ -66,6 +89,7 @@ exports.archiveCategory = async (req, res) => {
|
||||
try {
|
||||
const row = await mdl_Category.findByPk(req.params.id);
|
||||
if (!row) return R.error(res, 'Category not found.', 404);
|
||||
await row.update({ deletedBy: req.user?.user_id ?? null, is_active: false });
|
||||
await row.destroy();
|
||||
logActivity(req.user?.user_id, 'archive_category', { entityType: 'category', entityId: row.category_id });
|
||||
return R.success(res, 'Category archived.');
|
||||
@@ -79,7 +103,9 @@ exports.restoreCategory = async (req, res) => {
|
||||
try {
|
||||
const row = await mdl_Category.findByPk(req.params.id, { paranoid: false });
|
||||
if (!row) return R.error(res, 'Category not found.', 404);
|
||||
if (!row.deletedAt) return R.error(res, 'Category is not archived.', 400);
|
||||
await row.restore();
|
||||
await row.update({ deletedBy: null, is_active: true });
|
||||
logActivity(req.user?.user_id, 'restore_category', { entityType: 'category', entityId: row.category_id });
|
||||
return R.success(res, 'Category restored.', row);
|
||||
} catch (err) {
|
||||
@@ -87,3 +113,107 @@ exports.restoreCategory = async (req, res) => {
|
||||
return R.error(res, 'Could not restore category.', 500);
|
||||
}
|
||||
};
|
||||
|
||||
exports.bulkArchiveCategories = async (req, res) => {
|
||||
try {
|
||||
const { ids } = req.body;
|
||||
if (!Array.isArray(ids) || !ids.length) return R.error(res, 'No category IDs provided.', 400);
|
||||
|
||||
const rows = await mdl_Category.findAll({ where: { id: ids } });
|
||||
if (!rows.length) return R.error(res, 'No categories found.', 404);
|
||||
|
||||
const activeIds = rows.map((r) => r.id);
|
||||
await Promise.all(rows.map((r) => r.update({ deletedBy: req.user?.user_id ?? null, is_active: false })));
|
||||
await mdl_Category.destroy({ where: { id: activeIds } });
|
||||
|
||||
logActivity(req.user?.user_id, 'bulk_archive_categories', { entityType: 'category', details: { ids: activeIds, count: activeIds.length } });
|
||||
return R.success(res, `${activeIds.length} categor${activeIds.length !== 1 ? 'ies' : 'y'} archived.`, {
|
||||
archived_ids: activeIds,
|
||||
skipped_ids: ids.filter((id) => !activeIds.includes(id)),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('[ADMIN][CATEGORIES][BULK ARCHIVE]', err);
|
||||
return R.error(res, 'Could not archive categories.', 500);
|
||||
}
|
||||
};
|
||||
|
||||
exports.getCategoryPermanentDeleteImpact = async (req, res) => {
|
||||
try {
|
||||
const row = await mdl_Category.findByPk(req.params.id, { paranoid: false });
|
||||
if (!row) return R.error(res, 'Category not found.', 404);
|
||||
const course_count = await CourseProductCategory.count({ where: { category_id: req.params.id } });
|
||||
return R.success(res, 'Category permanent-delete impact retrieved.', { course_count });
|
||||
} catch (err) {
|
||||
console.error('[ADMIN][CATEGORIES][PERMANENT DELETE IMPACT]', err);
|
||||
return R.error(res, 'Could not retrieve category permanent-delete impact.', 500);
|
||||
}
|
||||
};
|
||||
|
||||
exports.permanentlyDeleteCategory = async (req, res) => {
|
||||
try {
|
||||
const row = await mdl_Category.findByPk(req.params.id, { paranoid: false });
|
||||
if (!row) return R.error(res, 'Category not found.', 404);
|
||||
if (!row.deletedAt) return R.error(res, 'Category must be archived before it can be permanently deleted.', 400);
|
||||
// course_product_categories.category_id has no DB-level cascade (only course_id does) —
|
||||
// clean up the junction rows explicitly or they'd be left orphaned.
|
||||
await CourseProductCategory.destroy({ where: { category_id: row.id } });
|
||||
await row.destroy({ force: true });
|
||||
logActivity(req.user?.user_id, 'permanently_delete_category', { entityType: 'category', entityId: row.id, details: { name: row.name } });
|
||||
return R.success(res, 'Category permanently deleted.');
|
||||
} catch (err) {
|
||||
console.error('[ADMIN][CATEGORIES][PERMANENT DELETE]', err);
|
||||
return R.error(res, 'Could not permanently delete category.', 500);
|
||||
}
|
||||
};
|
||||
|
||||
exports.bulkRestoreCategories = async (req, res) => {
|
||||
try {
|
||||
const { ids } = req.body;
|
||||
if (!Array.isArray(ids) || !ids.length) return R.error(res, 'No category IDs provided.', 400);
|
||||
|
||||
const rows = await mdl_Category.findAll({ where: { id: ids }, paranoid: false });
|
||||
if (!rows.length) return R.error(res, 'No categories found.', 404);
|
||||
|
||||
const archivedRows = rows.filter((r) => r.deletedAt);
|
||||
if (!archivedRows.length) return R.error(res, 'All selected categories are already active.', 400);
|
||||
|
||||
const archivedIds = archivedRows.map((r) => r.id);
|
||||
await mdl_Category.restore({ where: { id: archivedIds } });
|
||||
await mdl_Category.update({ deletedBy: null, is_active: true }, { where: { id: archivedIds }, paranoid: false });
|
||||
|
||||
logActivity(req.user?.user_id, 'bulk_restore_categories', { entityType: 'category', details: { ids: archivedIds, count: archivedIds.length } });
|
||||
return R.success(res, `${archivedIds.length} categor${archivedIds.length !== 1 ? 'ies' : 'y'} restored.`, {
|
||||
restored_ids: archivedIds,
|
||||
skipped_ids: ids.filter((id) => !archivedIds.includes(id)),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('[ADMIN][CATEGORIES][BULK RESTORE]', err);
|
||||
return R.error(res, 'Could not restore categories.', 500);
|
||||
}
|
||||
};
|
||||
|
||||
exports.bulkPermanentlyDeleteCategories = async (req, res) => {
|
||||
try {
|
||||
const { ids } = req.body;
|
||||
if (!Array.isArray(ids) || !ids.length) return R.error(res, 'No category IDs provided.', 400);
|
||||
|
||||
const rows = await mdl_Category.findAll({ where: { id: ids }, paranoid: false });
|
||||
if (!rows.length) return R.error(res, 'No categories found.', 404);
|
||||
|
||||
const archivedRows = rows.filter((r) => r.deletedAt);
|
||||
if (!archivedRows.length) return R.error(res, 'All selected categories must be archived before they can be permanently deleted.', 400);
|
||||
|
||||
const archivedIds = archivedRows.map((r) => r.id);
|
||||
await CourseProductCategory.destroy({ where: { category_id: archivedIds } });
|
||||
await mdl_Category.destroy({ where: { id: archivedIds }, force: true });
|
||||
|
||||
logActivity(req.user?.user_id, 'bulk_permanently_delete_categories', { entityType: 'category', details: { ids: archivedIds, count: archivedIds.length } });
|
||||
return R.success(res, `${archivedIds.length} categor${archivedIds.length !== 1 ? 'ies' : 'y'} permanently deleted.`, {
|
||||
deleted_ids: archivedIds,
|
||||
skipped_ids: ids.filter((id) => !archivedIds.includes(id)),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('[ADMIN][CATEGORIES][BULK PERMANENT DELETE]', err);
|
||||
return R.error(res, 'Could not permanently delete categories.', 500);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user