// /components/roles/roleService.js const Role = require('./roleModel'); const AppError = require('../../utils/AppError'); const { parsePaginationAndSort, buildFilterQuery, calculateMeta } = require('../../utils/pagination'); const createRole = async (roleData) => { const existing = await Role.findOne({ name: roleData.name }); if (existing) { throw new AppError('ROLE_ALREADY_EXISTS'); } const role = await Role.create(roleData); return role; }; const getRole = async (id) => { const role = await Role.findById(id); if (!role) { throw new AppError('ROLE_NOT_FOUND'); } return role; }; const getAllRoles = async (queryParams = {}) => { const { page, limit, skip, sort } = parsePaginationAndSort(queryParams); const filter = buildFilterQuery(queryParams, ['name', 'description']); const [roles, totalCount] = await Promise.all([ Role.find(filter).sort(sort).skip(skip).limit(limit), Role.countDocuments(filter) ]); const meta = calculateMeta(totalCount, page, limit); return { data: roles, meta }; }; const updateRole = async (id, updateData) => { const role = await Role.findById(id); if (!role) { throw new AppError('ROLE_NOT_FOUND'); } if (role.isSystem) { throw new AppError('SYSTEM_ROLE_PROTECTED'); } if (updateData.name && updateData.name !== role.name) { const existing = await Role.findOne({ name: updateData.name }); if (existing) { throw new AppError('ROLE_ALREADY_EXISTS'); } } Object.assign(role, updateData); await role.save(); return role; }; const deleteRole = async (id) => { const role = await Role.findById(id); if (!role) { throw new AppError('ROLE_NOT_FOUND'); } if (role.isSystem) { throw new AppError('SYSTEM_ROLE_PROTECTED'); } await Role.findByIdAndDelete(id); return null; }; const searchRoles = async (queryParams) => { return getAllRoles(queryParams); }; module.exports = { createRole, getRole, getAllRoles, updateRole, deleteRole, searchRoles };