update ticket
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { ArrayMinSize, IsEnum, IsNotEmpty, IsOptional, IsString, IsUUID, IsUrl, Length } from "class-validator";
|
||||
import { IsNotEmpty, IsOptional, IsString, IsUUID, IsUrl, Length } from "class-validator";
|
||||
|
||||
import { TicketMessageEnum, UserMessage } from "../../../common/enums/message.enum";
|
||||
import { TicketMessageEnum } from "../../../common/enums/message.enum";
|
||||
|
||||
|
||||
export class CreateTicketDto {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
|
||||
|
||||
export class SearchTicketCategoryDto {}
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
import { PartialType } from "@nestjs/swagger";
|
||||
import { CreateTicketDto } from "./create-ticket.dto";
|
||||
|
||||
|
||||
export class UpdateTicketDto extends PartialType(CreateTicketDto){}
|
||||
|
||||
@@ -10,6 +10,8 @@ import { UserRepository } from "src/modules/user/repositories/user.repository";
|
||||
import { AdminRepository } from "src/modules/admin/repositories/admin.repository";
|
||||
import { Admin } from "src/modules/admin/entities/admin.entity";
|
||||
import { FindTicketQueryDto } from "../DTO/search-ticket-query.dto";
|
||||
import { EntityManager } from "@mikro-orm/postgresql";
|
||||
import { UpdateTicketDto } from "../DTO/update-ticket.dto";
|
||||
|
||||
|
||||
@Injectable()
|
||||
@@ -21,7 +23,7 @@ export class TicketService {
|
||||
private readonly orderRepository: OrderRepository,
|
||||
private readonly userRepository: UserRepository,
|
||||
private readonly adminRepository: AdminRepository,
|
||||
// private readonly adminsService: AdminsService,
|
||||
private readonly em: EntityManager,
|
||||
) { }
|
||||
|
||||
async createTicket(orderId: string, dto: CreateTicketDto, userId?: string, adminId?: string) {
|
||||
@@ -67,271 +69,6 @@ export class TicketService {
|
||||
return ticket
|
||||
|
||||
}
|
||||
// async onModuleInit() {
|
||||
// await this.scheduleAutoCloseJob();
|
||||
// }
|
||||
|
||||
// //******************************** */
|
||||
// async getTicketCategories() {
|
||||
// const ticketCategories = await this.ticketsCategoryRepository.find({});
|
||||
// return {
|
||||
// ticketCategories,
|
||||
// };
|
||||
// }
|
||||
// //******************************** */
|
||||
|
||||
// async getCategoriesList(queryDto: SearchTicketCategoryDto) {
|
||||
// const [categories, count] = await this.ticketsCategoryRepository.findCategoriesList(queryDto);
|
||||
|
||||
// return { categories, count, paginate: true };
|
||||
// }
|
||||
// //******************************** */
|
||||
// async createTicketCategory(createDto: CreateTicketCategoryDto, userIpAndHeaders: IUserIpAndHeaders) {
|
||||
// const { userGroup } = await this.usersService.getUserGroupById(createDto.userGroupId);
|
||||
// const existCategory = await this.ticketsCategoryRepository.findCategoryByTitle(createDto.title);
|
||||
|
||||
// if (existCategory) throw new BadRequestException(TicketMessageEnum.CATEGORY_EXIST);
|
||||
// const ticketCategory = this.ticketsCategoryRepository.create({
|
||||
// ...createDto,
|
||||
// group: userGroup,
|
||||
// });
|
||||
|
||||
// await this.ticketsCategoryRepository.save(ticketCategory);
|
||||
|
||||
// await this.accessLogService.logCreate("TicketCategory", UserType.ADMIN, {
|
||||
// user: { id: userIpAndHeaders.userId },
|
||||
// endpoint: "/tickets/categories",
|
||||
// requestId: userIpAndHeaders.headers["x-request-id"],
|
||||
// ipAddress: userIpAndHeaders.ip,
|
||||
// userAgent: userIpAndHeaders.headers["user-agent"],
|
||||
// actionDescription: `Admin created ticket category: ${createDto.title}`,
|
||||
// metadata: {
|
||||
// categoryId: ticketCategory.id,
|
||||
// categoryTitle: ticketCategory.title,
|
||||
// },
|
||||
// });
|
||||
|
||||
// return {
|
||||
// message: TicketMessageEnum.CATEGORY_CREATED,
|
||||
// };
|
||||
// }
|
||||
|
||||
// //******************************** */
|
||||
// async updateCategory(paramDto: ParamDto, updateCategoryDto: UpdateTicketCategoryDto, userIpAndHeaders: IUserIpAndHeaders) {
|
||||
// const category = await this.ticketsCategoryRepository.findCategoryById(paramDto.id);
|
||||
// if (!category) throw new BadRequestException(TicketMessageEnum.CATEGORY_NOT_FOUND);
|
||||
|
||||
// if (updateCategoryDto.title) {
|
||||
// const { title } = updateCategoryDto;
|
||||
// const existCategory = await this.ticketsCategoryRepository.findOneBy({
|
||||
// title,
|
||||
// id: Not(paramDto.id),
|
||||
// });
|
||||
// if (existCategory) throw new BadRequestException(TicketMessageEnum.CATEGORY_EXIST);
|
||||
// }
|
||||
// await this.ticketsCategoryRepository.save({
|
||||
// ...category,
|
||||
// ...updateCategoryDto,
|
||||
// });
|
||||
|
||||
// await this.accessLogService.logUpdate("TicketCategory", paramDto.id, UserType.ADMIN, {
|
||||
// user: { id: userIpAndHeaders.userId },
|
||||
// endpoint: "/tickets/categories",
|
||||
// requestId: userIpAndHeaders.headers["x-request-id"],
|
||||
// ipAddress: userIpAndHeaders.ip,
|
||||
// userAgent: userIpAndHeaders.headers["user-agent"],
|
||||
// actionDescription: `Admin updated ticket category: ${category.title}`,
|
||||
// metadata: {
|
||||
// categoryId: category.id,
|
||||
// categoryTitle: category.title,
|
||||
// },
|
||||
// oldValues: JSON.stringify({ ...category }),
|
||||
// newValues: JSON.stringify({ ...updateCategoryDto }),
|
||||
// });
|
||||
|
||||
// return {
|
||||
// message: CommonMessage.UPDATE_SUCCESS,
|
||||
// };
|
||||
// }
|
||||
// //******************************** */
|
||||
// async toggleCategoryStatus(paramDto: ParamDto, userIpAndHeaders: IUserIpAndHeaders) {
|
||||
// const category = await this.ticketsCategoryRepository.findCategoryById(paramDto.id);
|
||||
// if (!category) throw new BadRequestException(TicketMessageEnum.CATEGORY_NOT_FOUND);
|
||||
// //
|
||||
// category.isActive = !category.isActive;
|
||||
// await this.ticketsCategoryRepository.save(category);
|
||||
// //
|
||||
// await this.accessLogService.logUpdate("TicketCategory", paramDto.id, UserType.ADMIN, {
|
||||
// user: { id: userIpAndHeaders.userId },
|
||||
// endpoint: "/tickets/categories",
|
||||
// requestId: userIpAndHeaders.headers["x-request-id"],
|
||||
// ipAddress: userIpAndHeaders.ip,
|
||||
// userAgent: userIpAndHeaders.headers["user-agent"],
|
||||
// actionDescription: `Admin toggled ticket category status: ${category.title}`,
|
||||
// metadata: {
|
||||
// categoryId: category.id,
|
||||
// categoryTitle: category.title,
|
||||
// isActive: category.isActive,
|
||||
// },
|
||||
// });
|
||||
|
||||
// return {
|
||||
// message: CommonMessage.UPDATE_SUCCESS,
|
||||
// isActive: category.isActive,
|
||||
// };
|
||||
// }
|
||||
|
||||
// //******************************** */
|
||||
|
||||
// private async checkTicketLimit(userId: string, queryRunner: QueryRunner): Promise<void> {
|
||||
// const { userSupportPlan } = await this.supportPlansService.getUserSupportPlanOfUser(userId);
|
||||
|
||||
// if (!userSupportPlan) throw new BadRequestException(TicketMessageEnum.NO_ACTIVE_SUPPORT_PLAN);
|
||||
|
||||
// const ticketLimitFeature = userSupportPlan.supportPlan.features.find(
|
||||
// (feature) => feature.featureKey === SupportPlanFeatureKey.TICKET_LIMIT,
|
||||
// );
|
||||
|
||||
// if (!ticketLimitFeature) throw new BadRequestException(TicketMessageEnum.TICKET_LIMIT_NOT_FOUND);
|
||||
|
||||
// const ticketLimit = parseInt(ticketLimitFeature.featureValue);
|
||||
// if (isNaN(ticketLimit)) return;
|
||||
|
||||
// const today = dayjs().startOf("day").toDate();
|
||||
|
||||
// const ticketCount = await queryRunner.manager.count(this.ticketsRepository.target, {
|
||||
// where: {
|
||||
// user: { id: userId },
|
||||
// createdAt: MoreThanOrEqual(today),
|
||||
// },
|
||||
// });
|
||||
|
||||
// if (ticketCount >= ticketLimit) throw new BadRequestException(TicketMessageEnum.TICKET_LIMIT_EXCEEDED);
|
||||
// }
|
||||
|
||||
// //******************************** */
|
||||
|
||||
// async createTicket(createDto: CreateTicketDto, userId: string) {
|
||||
// const queryRunner = this.dataSource.createQueryRunner();
|
||||
|
||||
// try {
|
||||
// await queryRunner.connect();
|
||||
// await queryRunner.startTransaction();
|
||||
|
||||
// const [user, ticketCategory] = await Promise.all([
|
||||
// this.usersService.findOneByIdWithQueryRunner(userId, queryRunner),
|
||||
// queryRunner.manager.findOne(TicketCategory, { where: { id: createDto.categoryId }, relations: { group: { users: true } } }),
|
||||
// ]);
|
||||
|
||||
// if (!ticketCategory) throw new BadRequestException(TicketMessageEnum.CATEGORY_NOT_FOUND);
|
||||
|
||||
// await this.checkTicketLimit(userId, queryRunner);
|
||||
|
||||
// let service = null;
|
||||
// if (createDto.danakServiceId) {
|
||||
// service = await queryRunner.manager.findOneBy(DanakService, { id: createDto.danakServiceId });
|
||||
// if (!service) throw new BadRequestException(TicketMessageEnum.SERVICE_NOT_FOUND);
|
||||
// }
|
||||
|
||||
// const ticketMessage: Partial<TicketMessage> = { content: createDto.message, author: user };
|
||||
|
||||
// if (createDto.attachmentUrls?.length) {
|
||||
// ticketMessage.attachments = createDto.attachmentUrls.map((url) => {
|
||||
// const attachment = new TicketMessageAttachment();
|
||||
// attachment.attachmentUrl = url;
|
||||
// return attachment;
|
||||
// });
|
||||
// }
|
||||
|
||||
// const ticket = queryRunner.manager.create(Ticket, {
|
||||
// ...createDto,
|
||||
// user,
|
||||
// category: ticketCategory,
|
||||
// messages: [ticketMessage],
|
||||
// danakService: service,
|
||||
// });
|
||||
|
||||
// await queryRunner.manager.save(Ticket, ticket);
|
||||
|
||||
// await this.assignTicketAndNotify(ticket, ticketCategory, user, queryRunner);
|
||||
|
||||
// await queryRunner.commitTransaction();
|
||||
|
||||
// return {
|
||||
// message: TicketMessageEnum.CREATED,
|
||||
// ticketId: ticket.id,
|
||||
// };
|
||||
// } catch (error) {
|
||||
// this.logger.error("Error in create ticket transaction", error);
|
||||
// await queryRunner.rollbackTransaction();
|
||||
// throw error;
|
||||
// } finally {
|
||||
// await queryRunner.release();
|
||||
// }
|
||||
// }
|
||||
// //******************************** */
|
||||
|
||||
// async createTicketByAdmin(createDto: CreateTicketByAdminDto, userIpAndHeaders: IUserIpAndHeaders) {
|
||||
// const queryRunner = this.dataSource.createQueryRunner();
|
||||
|
||||
// try {
|
||||
// await queryRunner.connect();
|
||||
// await queryRunner.startTransaction();
|
||||
|
||||
// const [user, admin, ticketCategory] = await Promise.all([
|
||||
// this.usersService.findOneByIdWithQueryRunner(createDto.userId, queryRunner),
|
||||
// this.usersService.findOneByIdWithQueryRunner(userIpAndHeaders.userId, queryRunner),
|
||||
// queryRunner.manager.findOne(TicketCategory, { where: { id: createDto.categoryId }, relations: { group: { users: true } } }),
|
||||
// ]);
|
||||
|
||||
// if (!ticketCategory) throw new BadRequestException(TicketMessageEnum.CATEGORY_NOT_FOUND);
|
||||
|
||||
// const ticketMessage: Partial<TicketMessage> = { content: createDto.message, author: admin };
|
||||
|
||||
// const ticket = queryRunner.manager.create(Ticket, {
|
||||
// ...createDto,
|
||||
// user,
|
||||
// category: ticketCategory,
|
||||
// messages: [ticketMessage],
|
||||
// assignedTo: admin,
|
||||
// });
|
||||
|
||||
// await queryRunner.manager.save(Ticket, ticket);
|
||||
|
||||
// await this.notificationQueue.addTicketNotification(user.id, {
|
||||
// ticketId: ticket.numericId.toString(),
|
||||
// subject: ticket.subject,
|
||||
// date: ticket.createdAt,
|
||||
// userPhone: user.phone,
|
||||
// userEmail: user.email,
|
||||
// });
|
||||
|
||||
// await this.accessLogService.logCreate("Ticket", UserType.ADMIN, {
|
||||
// user: { id: userIpAndHeaders.userId },
|
||||
// endpoint: "/tickets",
|
||||
// requestId: userIpAndHeaders.headers["x-request-id"],
|
||||
// ipAddress: userIpAndHeaders.ip,
|
||||
// userAgent: userIpAndHeaders.headers["user-agent"],
|
||||
// actionDescription: `Admin created ticket: ${ticket.subject}`,
|
||||
// metadata: {
|
||||
// ticketId: ticket.id,
|
||||
// ticketSubject: ticket.subject,
|
||||
// },
|
||||
// });
|
||||
|
||||
// await queryRunner.commitTransaction();
|
||||
|
||||
// return {
|
||||
// message: TicketMessageEnum.CREATED,
|
||||
// ticketId: ticket.id,
|
||||
// };
|
||||
// } catch (error) {
|
||||
// await queryRunner.rollbackTransaction();
|
||||
// throw error;
|
||||
// } finally {
|
||||
// await queryRunner.release();
|
||||
// }
|
||||
// }
|
||||
|
||||
// //******************************** */
|
||||
|
||||
@@ -341,7 +78,7 @@ export class TicketService {
|
||||
if (!order) {
|
||||
throw new BadRequestException("order not found!")
|
||||
}
|
||||
if(userId){
|
||||
if (userId) {
|
||||
if (order.user.id !== userId) {
|
||||
throw new BadRequestException("This ticket doenst belongs to You !")
|
||||
}
|
||||
@@ -350,8 +87,41 @@ export class TicketService {
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
//******************************** */
|
||||
|
||||
async deleteTicket(ticketId: string, userId?: string) {
|
||||
const ticket = await this.ticketsRepository.findOne({ id: ticketId }, { populate: ['order', 'order.user'] })
|
||||
if (!ticket) {
|
||||
throw new BadRequestException('ticket not found!')
|
||||
}
|
||||
if (userId && ticket.order.user.id !== userId) {
|
||||
throw new BadRequestException("You can not Delete this Ticket")
|
||||
}
|
||||
|
||||
await this.em.removeAndFlush(ticket)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// //******************************** */
|
||||
|
||||
async updateTicket(ticketId: string, dto: UpdateTicketDto, userId?: string) {
|
||||
const ticket = await this.ticketsRepository.findOne({ id: ticketId }, { populate: ['order', 'order.user'] })
|
||||
if (!ticket) {
|
||||
throw new BadRequestException('ticket not found!')
|
||||
}
|
||||
if (userId && ticket.order.user.id !== userId) {
|
||||
throw new BadRequestException("You can not Update this Ticket")
|
||||
}
|
||||
this.ticketsRepository.assign(ticket, dto, {
|
||||
onlyProperties: true,
|
||||
})
|
||||
|
||||
await this.em.flush()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// //******************************** */
|
||||
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import { Body, Controller, Get, HttpCode, HttpStatus, Param, Patch, Post, Query } from "@nestjs/common";
|
||||
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Patch, Post, Query } from "@nestjs/common";
|
||||
import { ApiOperation, ApiTags } from "@nestjs/swagger";
|
||||
import { CreateTicketDto } from "./DTO/create-ticket.dto";
|
||||
import { FindTicketQueryDto } from "./DTO/search-ticket-query.dto";
|
||||
import { TicketService } from "./providers/tickets.service";
|
||||
|
||||
|
||||
import { ParamDto } from "../../common/DTO/param.dto";
|
||||
import { UserId } from "src/common/decorators";
|
||||
import { AdminId } from "src/common/decorators/admin-id.decorator";
|
||||
import { UpdateTicketDto } from "./DTO/update-ticket.dto";
|
||||
|
||||
@Controller("tickets")
|
||||
@ApiTags("Tickets")
|
||||
@@ -73,8 +71,26 @@ export class TicketsController {
|
||||
return this.ticketsService.getTickets(orderId, queryDto, userId);
|
||||
}
|
||||
|
||||
@ApiOperation({ summary: "Delete Ticket ==> admin route" })
|
||||
@Delete('public/ticket/:ticketId')
|
||||
deleteTicket(@Param('ticketId') ticketId: string, @UserId() userId: string) {
|
||||
return this.ticketsService.deleteTicket(ticketId, userId);
|
||||
}
|
||||
|
||||
@ApiOperation({ summary: "Delete Ticket ==> admin route" })
|
||||
@Patch('public/ticket/:ticketId')
|
||||
updateTicket(@Param('ticketId') ticketId: string, @UserId() userId: string, @Body() body: UpdateTicketDto) {
|
||||
return this.ticketsService.updateTicket(ticketId, body, userId,);
|
||||
}
|
||||
|
||||
/*=========================== Admin ============================== */
|
||||
|
||||
@ApiOperation({ summary: "Delete Ticket ==> admin route" })
|
||||
@Delete('admin/ticket/:ticketId')
|
||||
deleteTicketAsAdmin(@Param('ticketId') ticketId: string) {
|
||||
return this.ticketsService.deleteTicket(ticketId);
|
||||
}
|
||||
|
||||
@Post('admin/ticket/order/:orderId')
|
||||
@ApiOperation({ summary: "create ticket ==> admin route" })
|
||||
createTicketAsAdmin(@Param('orderId') orderId: string, @Body() createDto: CreateTicketDto, @AdminId() adminId: string) {
|
||||
@@ -87,55 +103,10 @@ export class TicketsController {
|
||||
getTicketsAsAdmin(@Query() queryDto: FindTicketQueryDto, @Param('orderId') orderId: string) {
|
||||
return this.ticketsService.getTickets(orderId, queryDto);
|
||||
}
|
||||
// @ApiOperation({ summary: "Get all tickets ==> admin route" })
|
||||
// @AdminRoute()
|
||||
// @PermissionsDec(PermissionEnum.TICKETS)
|
||||
// @Get("admin")
|
||||
// getAllTickets(@Query() queryDto: SearchTicketQueryDto, @UserDec("id") adminId: string) {
|
||||
// return this.ticketsService.getTicketForAdmin(queryDto, adminId);
|
||||
// }
|
||||
|
||||
// @ApiOperation({ summary: "create ticket messages" })
|
||||
// @Post(":id/messages")
|
||||
// createTicketMessage(
|
||||
// @Param() paramDto: ParamDto,
|
||||
// @Body() createDto: CreateTicketMessageDto,
|
||||
// @UserDec("id") userId: string,
|
||||
// @UserDec("isAdmin") isAdmin: boolean,
|
||||
// ) {
|
||||
// return this.ticketsService.createTicketMessage(paramDto.id, createDto, userId, isAdmin);
|
||||
// }
|
||||
|
||||
// @ApiOperation({ summary: "Get all ticket messages of user" })
|
||||
// @Get(":id/messages")
|
||||
// getTicketMessages(@Param() paramDto: ParamDto, @UserDec("id") userId: string, @UserDec("isAdmin") isAdmin: boolean) {
|
||||
// return this.ticketsService.getTicketMessages(paramDto.id, userId, isAdmin);
|
||||
// }
|
||||
|
||||
// @ApiOperation({ summary: "close ticket by user or admin" })
|
||||
// @HttpCode(HttpStatus.OK)
|
||||
// @Post(":id/close")
|
||||
// closedTicketByUser(
|
||||
// @Param() paramDto: ParamDto,
|
||||
// @UserDec("isAdmin") isAdmin: boolean,
|
||||
// @UserIpAndHeaders() userIpAndHeaders: IUserIpAndHeaders,
|
||||
// ) {
|
||||
// return this.ticketsService.closeTicketByUser(paramDto.id, isAdmin, userIpAndHeaders);
|
||||
// }
|
||||
|
||||
// @ApiOperation({ summary: "open ticket by admin" })
|
||||
// @AdminRoute()
|
||||
// @PermissionsDec(PermissionEnum.TICKETS)
|
||||
// @Post(":id/open")
|
||||
// openTicketByAdmin(@Param() paramDto: ParamDto, @UserIpAndHeaders() userIpAndHeaders: IUserIpAndHeaders) {
|
||||
// return this.ticketsService.openTicketByAdmin(paramDto.id, userIpAndHeaders);
|
||||
// }
|
||||
|
||||
// @ApiOperation({ summary: "referer ticket ==> admin route" })
|
||||
// @AdminRoute()
|
||||
// @PermissionsDec(PermissionEnum.TICKETS)
|
||||
// @Post(":id/refer")
|
||||
// referTicket(@Param() paramDto: ParamDto, @Body() referDto: ReferTicketDto, @UserIpAndHeaders() userIpAndHeaders: IUserIpAndHeaders) {
|
||||
// return this.ticketsService.referTicket(paramDto.id, referDto, userIpAndHeaders);
|
||||
// }
|
||||
@ApiOperation({ summary: "Delete Ticket ==> admin route" })
|
||||
@Patch('admin/ticket/:ticketId')
|
||||
updateTicketAsAdmin(@Param('ticketId') ticketId: string, @Body() body: UpdateTicketDto) {
|
||||
return this.ticketsService.updateTicket(ticketId, body);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user