feat: ticketing system with technical/sales roles and department routing
Backend: - Added TECHNICAL and SALES roles to UserRole enum - Added TicketDepartment, TicketStatus, TicketPriority enums - Created Ticket and TicketMessage entities with relationships - Created TicketsModule with full CRUD service and controller - Ticket routing: users create tickets to technical/sales departments - Staff reply updates status (answered), user reply sets waiting - Role-based access: technical staff sees technical tickets, sales sees sales tickets - Admin sees all tickets with stats (total, open, avg response time) - Updated access control: technical role has admin-level access (except role change) - Sales role can view users and handle sales tickets - Clusters controller: technical role can manage clusters/pools - Users controller: technical/sales can view users, only admin changes roles Frontend: - New user ticket pages: list (with create form) + detail (chat-style messages) - Staff ticket panel: filtered by department with status filters - Admin all-tickets page with statistics dashboard and department/status filters - Updated sidebar: role-based nav items (admin/technical/sales sections) - Role badges in header for technical (blue) and sales (green) - Admin users page: new roles in dropdowns, role change restricted to admin only - Deploy page: technical role gets cluster selection access like admin
This commit is contained in:
@@ -63,16 +63,16 @@ export class UsersController {
|
||||
}
|
||||
|
||||
@Get()
|
||||
@Roles(UserRole.ADMIN)
|
||||
@ApiOperation({ summary: 'List all users with optional search (Admin only)' })
|
||||
@Roles(UserRole.ADMIN, UserRole.TECHNICAL, UserRole.SALES)
|
||||
@ApiOperation({ summary: 'List all users with optional search (Staff/Admin)' })
|
||||
@ApiQuery({ name: 'search', required: false, description: 'Search by name or email' })
|
||||
async findAll(@Query('search') search?: string) {
|
||||
return this.usersService.findAll(search);
|
||||
}
|
||||
|
||||
@Post()
|
||||
@Roles(UserRole.ADMIN)
|
||||
@ApiOperation({ summary: 'Create a new user (Admin only)' })
|
||||
@Roles(UserRole.ADMIN, UserRole.TECHNICAL)
|
||||
@ApiOperation({ summary: 'Create a new user (Admin/Technical only)' })
|
||||
async adminCreate(@Body() dto: AdminCreateUserDto) {
|
||||
return this.usersService.adminCreate(dto);
|
||||
}
|
||||
@@ -86,16 +86,16 @@ export class UsersController {
|
||||
}
|
||||
|
||||
@Patch(':id/deactivate')
|
||||
@Roles(UserRole.ADMIN)
|
||||
@ApiOperation({ summary: 'Deactivate a user (Admin only)' })
|
||||
@Roles(UserRole.ADMIN, UserRole.TECHNICAL)
|
||||
@ApiOperation({ summary: 'Deactivate a user (Admin/Technical)' })
|
||||
async deactivate(@Param('id') id: string) {
|
||||
await this.usersService.deactivate(id);
|
||||
return { message: 'User deactivated' };
|
||||
}
|
||||
|
||||
@Patch(':id/activate')
|
||||
@Roles(UserRole.ADMIN)
|
||||
@ApiOperation({ summary: 'Activate a user (Admin only)' })
|
||||
@Roles(UserRole.ADMIN, UserRole.TECHNICAL)
|
||||
@ApiOperation({ summary: 'Activate a user (Admin/Technical)' })
|
||||
async activate(@Param('id') id: string) {
|
||||
await this.usersService.activate(id);
|
||||
return { message: 'User activated' };
|
||||
|
||||
Reference in New Issue
Block a user