ticket
This commit is contained in:
@@ -35,13 +35,6 @@ export class CreateTicketDto {
|
|||||||
@IsString()
|
@IsString()
|
||||||
content: string;
|
content: string;
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'Ticket status',
|
|
||||||
enum: TicketStatusEnum,
|
|
||||||
default: TicketStatusEnum.OPEN,
|
|
||||||
})
|
|
||||||
@IsEnum(TicketStatusEnum)
|
|
||||||
status: TicketStatusEnum = TicketStatusEnum.OPEN;
|
|
||||||
|
|
||||||
@ApiPropertyOptional({
|
@ApiPropertyOptional({
|
||||||
description: 'Attachments',
|
description: 'Attachments',
|
||||||
|
|||||||
@@ -12,12 +12,11 @@ export class TicketRepository extends EntityRepository<Ticket> {
|
|||||||
super(em, Ticket);
|
super(em, Ticket);
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAllPaginated(dto: SearchTicketQueryDto): Promise<PaginatedResult<Ticket>> {
|
async findTicketsPaginated(dto: SearchTicketQueryDto): Promise<PaginatedResult<Ticket>> {
|
||||||
const {
|
const {
|
||||||
page = 1,
|
page = 1,
|
||||||
limit = 10,
|
limit = 10,
|
||||||
statuses,
|
statuses,
|
||||||
parentId,
|
|
||||||
adminId,
|
adminId,
|
||||||
userId,
|
userId,
|
||||||
search,
|
search,
|
||||||
@@ -29,7 +28,89 @@ export class TicketRepository extends EntityRepository<Ticket> {
|
|||||||
|
|
||||||
const offset = (page - 1) * limit;
|
const offset = (page - 1) * limit;
|
||||||
|
|
||||||
const where: FilterQuery<Ticket> = {};
|
const where: FilterQuery<Ticket> = {parent:null};
|
||||||
|
|
||||||
|
|
||||||
|
if (adminId !== undefined) {
|
||||||
|
if (adminId === null || adminId === '') {
|
||||||
|
where.admin = null;
|
||||||
|
} else {
|
||||||
|
where.admin = { id: adminId };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userId !== undefined) {
|
||||||
|
if (userId === null || userId === '') {
|
||||||
|
where.user = null;
|
||||||
|
} else {
|
||||||
|
where.user = { id: userId };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statuses?.length) {
|
||||||
|
const normalizedStatuses = Array.isArray(statuses) ? statuses : [statuses];
|
||||||
|
const validStatuses = normalizedStatuses.filter((s): s is TicketStatusEnum => !!s);
|
||||||
|
if (validStatuses.length === 1) {
|
||||||
|
where.status = validStatuses[0];
|
||||||
|
} else if (validStatuses.length > 1) {
|
||||||
|
where.status = { $in: validStatuses };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from || to) {
|
||||||
|
where.createdAt = {};
|
||||||
|
if (from) where.createdAt.$gte = new Date(from);
|
||||||
|
if (to) where.createdAt.$lte = new Date(to);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (search) {
|
||||||
|
const searchPattern = `%${search}%`;
|
||||||
|
where.$or = [
|
||||||
|
{ subject: { $ilike: searchPattern } },
|
||||||
|
{ content: { $ilike: searchPattern } },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
const [data, total] = await this.findAndCount(where, {
|
||||||
|
limit,
|
||||||
|
offset,
|
||||||
|
orderBy: { [orderBy]: order.toLowerCase() as 'asc' | 'desc' },
|
||||||
|
populate: ['parent', 'children', 'admin', 'user'],
|
||||||
|
filters: ['notDeleted'],
|
||||||
|
});
|
||||||
|
|
||||||
|
const totalPages = Math.ceil(total / limit);
|
||||||
|
|
||||||
|
return {
|
||||||
|
data,
|
||||||
|
meta: {
|
||||||
|
total,
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
totalPages,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async findTicketMessagesPaginated(dto: SearchTicketQueryDto): Promise<PaginatedResult<Ticket>> {
|
||||||
|
const {
|
||||||
|
page = 1,
|
||||||
|
limit = 10,
|
||||||
|
statuses,
|
||||||
|
adminId,
|
||||||
|
userId,
|
||||||
|
search,
|
||||||
|
orderBy = 'createdAt',
|
||||||
|
order = 'desc',
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
parentId
|
||||||
|
} = dto;
|
||||||
|
|
||||||
|
const offset = (page - 1) * limit;
|
||||||
|
|
||||||
|
const where: FilterQuery<Ticket> = {parent:null};
|
||||||
|
|
||||||
if (parentId !== undefined) {
|
if (parentId !== undefined) {
|
||||||
if (parentId === null || parentId === '') {
|
if (parentId === null || parentId === '') {
|
||||||
|
|||||||
@@ -49,9 +49,9 @@ export class TicketController {
|
|||||||
|
|
||||||
@Get('public/tickets/:id')
|
@Get('public/tickets/:id')
|
||||||
@UseGuards(AuthGuard)
|
@UseGuards(AuthGuard)
|
||||||
@ApiOperation({ summary: 'Get one of my tickets by id' })
|
@ApiOperation({ summary: 'Get tickets messages by parent id' })
|
||||||
findOneAsUser(@Param('id') id: string, @UserId() userId: string) {
|
findOneAsUser(@Param('id') id: string, @UserId() userId: string) {
|
||||||
return this.ticketService.findOneAsUser(id, userId);
|
return this.ticketService.findTicketMessagesAsUser(id, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch('public/tickets/:id')
|
@Patch('public/tickets/:id')
|
||||||
@@ -91,15 +91,15 @@ export class TicketController {
|
|||||||
@Permissions(PermissionEnum.MANAGE_TICKETS)
|
@Permissions(PermissionEnum.MANAGE_TICKETS)
|
||||||
@ApiOperation({ summary: 'Get all tickets with pagination' })
|
@ApiOperation({ summary: 'Get all tickets with pagination' })
|
||||||
findAllAsAdmin(@Query() queryDto: SearchTicketQueryDto) {
|
findAllAsAdmin(@Query() queryDto: SearchTicketQueryDto) {
|
||||||
return this.ticketService.findAll(queryDto);
|
return this.ticketService.findTickets(queryDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('admin/tickets/:id')
|
@Get('admin/tickets/:id')
|
||||||
@UseGuards(AdminAuthGuard)
|
@UseGuards(AdminAuthGuard)
|
||||||
@Permissions(PermissionEnum.MANAGE_TICKETS)
|
@Permissions(PermissionEnum.MANAGE_TICKETS)
|
||||||
@ApiOperation({ summary: 'Get one ticket by id' })
|
@ApiOperation({ summary: 'Get ticket messages by parent id' })
|
||||||
findOneAsAdmin(@Param('id') id: string) {
|
findOneAsAdmin(@Param('id') id: string) {
|
||||||
return this.ticketService.findOne(id);
|
return this.ticketService.findTicketMessagesAsAdmin(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch('admin/tickets/:id')
|
@Patch('admin/tickets/:id')
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ export class TicketService {
|
|||||||
parent: parent ?? undefined,
|
parent: parent ?? undefined,
|
||||||
admin: admin ?? undefined,
|
admin: admin ?? undefined,
|
||||||
user: user ?? undefined,
|
user: user ?? undefined,
|
||||||
|
status: TicketStatusEnum.OPEN,
|
||||||
});
|
});
|
||||||
await this.em.persistAndFlush(ticket);
|
await this.em.persistAndFlush(ticket);
|
||||||
return ticket;
|
return ticket;
|
||||||
@@ -96,18 +97,18 @@ export class TicketService {
|
|||||||
return ticket;
|
return ticket;
|
||||||
}
|
}
|
||||||
|
|
||||||
findAll(dto: SearchTicketQueryDto) {
|
findTickets(dto: SearchTicketQueryDto) {
|
||||||
return this.ticketRepository.findAllPaginated(dto);
|
return this.ticketRepository.findTicketsPaginated(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
findMyTickets(userId: string, dto: SearchTicketQueryDto) {
|
findMyTickets(userId: string, dto: SearchTicketQueryDto) {
|
||||||
return this.ticketRepository.findAllPaginated({ ...dto, userId });
|
return this.ticketRepository.findTicketsPaginated({ ...dto, userId });
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOneAsUser(id: string, userId: string) {
|
async findTicketMessagesAsUser(ticketId: string, userId: string) {
|
||||||
const ticket = await this.ticketRepository.findOne(
|
const ticket = await this.ticketRepository.find(
|
||||||
{ id, user: { id: userId } },
|
{ parent: { id: ticketId }, user: { id: userId } },
|
||||||
{ populate: ['parent', 'children', 'admin', 'user'], filters: ['notDeleted'] },
|
{ populate: ['admin', 'user'], filters: ['notDeleted'] },
|
||||||
);
|
);
|
||||||
if (!ticket) {
|
if (!ticket) {
|
||||||
throw new NotFoundException('Ticket not found');
|
throw new NotFoundException('Ticket not found');
|
||||||
@@ -115,10 +116,10 @@ export class TicketService {
|
|||||||
return ticket;
|
return ticket;
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOne(id: string) {
|
async findTicketMessagesAsAdmin(ticketId: string) {
|
||||||
const ticket = await this.ticketRepository.findOne(
|
const ticket = await this.ticketRepository.find(
|
||||||
{ id },
|
{ parent: { id: ticketId } },
|
||||||
{ populate: ['parent', 'children', 'admin', 'user'], filters: ['notDeleted'] },
|
{ populate: ['admin', 'user'], filters: ['notDeleted'] },
|
||||||
);
|
);
|
||||||
if (!ticket) {
|
if (!ticket) {
|
||||||
throw new NotFoundException('Ticket not found');
|
throw new NotFoundException('Ticket not found');
|
||||||
|
|||||||
Reference in New Issue
Block a user