import { Request, Response } from 'express'; import db from '../../database/models/index.js'; const { Role, Permission, RolePermission, User, DealerCode, AuditLog } = db; import { AUDIT_ACTIONS } from '../../common/config/constants.js'; import { AuthRequest } from '../../types/express.types.js'; // --- Roles Management --- export const getRoles = async (req: Request, res: Response) => { try { const roles = await Role.findAll({ include: [ { model: Permission, as: 'permissions', through: { attributes: [] } }, { model: User, as: 'users', attributes: ['id'] } ], order: [['roleName', 'ASC']] }); // Map to include userCount const result = roles.map((r: any) => ({ ...r.toJSON(), userCount: r.users?.length || 0 })); res.json({ success: true, data: result }); } catch (error) { console.error('Get roles error:', error); res.status(500).json({ success: false, message: 'Error fetching roles' }); } }; export const createRole = async (req: AuthRequest, res: Response) => { try { const { roleCode, roleName, description, permissionIds } = req.body; // permissionIds: string[] const role = await Role.create({ roleCode, roleName, description }); if (permissionIds && permissionIds.length > 0) { for (const pid of permissionIds) { await RolePermission.create({ roleId: role.id, permissionId: pid }); } } await AuditLog.create({ userId: req.user?.id, action: AUDIT_ACTIONS.CREATED, entityType: 'role', entityId: role.id, newData: req.body }); res.status(201).json({ success: true, data: role, message: 'Role created successfully' }); } catch (error) { console.error('Create role error:', error); res.status(500).json({ success: false, message: 'Error creating role' }); } }; export const updateRole = async (req: AuthRequest, res: Response) => { try { const { id } = req.params; const { roleName, description, permissionIds, isActive } = req.body; const role = await Role.findByPk(id); if (!role) return res.status(404).json({ success: false, message: 'Role not found' }); await role.update({ roleName, description, isActive }); if (permissionIds) { // Remove existing permissions and re-add new ones await RolePermission.destroy({ where: { roleId: id } }); for (const pid of permissionIds) { await RolePermission.create({ roleId: id, permissionId: pid }); } } await AuditLog.create({ userId: req.user?.id, action: AUDIT_ACTIONS.UPDATED, entityType: 'role', entityId: id, newData: req.body }); res.json({ success: true, message: 'Role updated successfully' }); } catch (error) { console.error('Update role error:', error); res.status(500).json({ success: false, message: 'Error updating role' }); } }; // --- Permissions Management --- export const getPermissions = async (req: Request, res: Response) => { try { const permissions = await Permission.findAll({ order: [['module', 'ASC']] }); res.json({ success: true, data: permissions }); } catch (error) { console.error('Get permissions error:', error); res.status(500).json({ success: false, message: 'Error fetching permissions' }); } }; // --- User Management (Admin) --- export const getAllUsers = async (req: Request, res: Response) => { try { const users = await User.findAll({ attributes: { exclude: ['password'] }, include: [ { model: Role, as: 'role', include: [ { model: Permission, as: 'permissions', through: { attributes: [] } } ] }, { model: db.Zone, as: 'zone' }, { model: db.Region, as: 'region' }, { model: db.Area, as: 'area' } ], order: [['createdAt', 'DESC']] }); res.json({ success: true, data: users }); } catch (error) { console.error('Get users error:', error); res.status(500).json({ success: false, message: 'Error fetching users' }); } }; export const updateUserStatus = async (req: AuthRequest, res: Response) => { try { const { id } = req.params; const { status, isActive } = req.body; const user = await User.findByPk(id); if (!user) return res.status(404).json({ success: false, message: 'User not found' }); await user.update({ status, isActive }); await AuditLog.create({ userId: req.user?.id, action: AUDIT_ACTIONS.UPDATED, entityType: 'user', entityId: id, newData: { status, isActive } }); res.json({ success: true, message: 'User status updated' }); } catch (error) { console.error('Update user status error:', error); res.status(500).json({ success: false, message: 'Error updating user status' }); } }; export const updateUser = async (req: AuthRequest, res: Response) => { try { const { id } = req.params; const { fullName, email, roleCode, status, isActive, employeeId, mobileNumber, department, designation, zoneId, regionId, stateId, districtId, areaId } = req.body; const user = await User.findByPk(id); if (!user) return res.status(404).json({ success: false, message: 'User not found' }); const oldData = user.toJSON(); await user.update({ fullName: fullName || user.fullName, email: email || user.email, roleCode: roleCode || user.roleCode, status: status || user.status, isActive: isActive !== undefined ? isActive : user.isActive, employeeId: employeeId || user.employeeId, mobileNumber: mobileNumber || user.mobileNumber, department: department || user.department, designation: designation || user.designation, zoneId: zoneId !== undefined ? zoneId : user.zoneId, regionId: regionId !== undefined ? regionId : user.regionId, stateId: stateId !== undefined ? stateId : user.stateId, districtId: districtId !== undefined ? districtId : user.districtId, areaId: areaId !== undefined ? areaId : user.areaId }); await AuditLog.create({ userId: req.user?.id, action: AUDIT_ACTIONS.UPDATED, entityType: 'user', entityId: id, oldData, newData: req.body }); res.json({ success: true, message: 'User updated successfully', data: user }); } catch (error) { console.error('Update user error:', error); res.status(500).json({ success: false, message: 'Error updating user' }); } }; // --- Dealer Codes --- export const generateDealerCode = async (req: AuthRequest, res: Response) => { try { const { regionId, stateId, channel } = req.body; // Logic to generate unique code based on format (e.g., RE-[Region]-[State]-[Seq]) // This is a placeholder for the actual business logic const timestamp = Date.now().toString().slice(-6); const code = `DLR-${timestamp}`; const dealerCode = await DealerCode.create({ code, isUsed: false, generatedBy: req.user?.id }); res.status(201).json({ success: true, data: dealerCode }); } catch (error) { console.error('Generate dealer code error:', error); res.status(500).json({ success: false, message: 'Error generating dealer code' }); } };