feat: add payment module and factory

This commit is contained in:
mahyargdz
2025-02-03 15:41:53 +03:30
parent 8fb587f976
commit 31368610dd
48 changed files with 931 additions and 81 deletions
@@ -1,9 +1,10 @@
import { BadRequestException, Injectable } from "@nestjs/common";
import { Not } from "typeorm";
import { BadRequestException, HttpException, Injectable, InternalServerErrorException } from "@nestjs/common";
import { DataSource, Not } from "typeorm";
import { ParamDto } from "../../../common/DTO/param.dto";
import { CommonMessage, TicketMessageEnum } from "../../../common/enums/message.enum";
import { CommonMessage, TicketMessageEnum, UserMessage } from "../../../common/enums/message.enum";
import { Role } from "../../users/entities/role.entity";
import { User } from "../../users/entities/user.entity";
import { RoleEnum } from "../../users/enums/role.enum";
import { UsersService } from "../../users/providers/users.service";
import { PaginationUtils } from "../../utils/providers/pagination.utils";
@@ -13,6 +14,7 @@ import { CreateTicketDto } from "../DTO/create-ticket.dto";
import { SearchTicketCategoryDto } from "../DTO/search-ticket-category.dto";
import { SearchTicketQueryDto } from "../DTO/search-ticket-query.dto";
import { UpdateTicketCategoryDto } from "../DTO/update-ticket-category.dto";
import { TicketMessageAttachment } from "../entities/ticket-message-attachment";
import { TicketMessage } from "../entities/ticket-message.entity";
import { Ticket } from "../entities/ticket.entity";
import { TicketStatus } from "../enums/ticket-status.enum";
@@ -27,6 +29,7 @@ export class TicketsService {
private readonly ticketsRepository: TicketsRepository,
private readonly ticketMessagesRepository: TicketMessagesRepository,
private readonly usersService: UsersService,
private dataSource: DataSource,
) {}
//******************************** */
async getTicketCategories() {
@@ -109,15 +112,26 @@ export class TicketsService {
const { user } = await this.usersService.findOneById(userId);
const ticketCategory = await this.ticketsCategoryRepository.findCategoryById(createDto.categoryId);
if (!ticketCategory) throw new BadRequestException(TicketMessageEnum.CATEGORY_NOT_FOUND);
const { attachmentUrls } = createDto;
//
const ticketMessage: Partial<TicketMessage> = { content: createDto.message, author: user };
if (attachmentUrls) {
ticketMessage.attachments = attachmentUrls.map((url) => {
const attachment = new TicketMessageAttachment();
attachment.attachmentUrl = url;
return attachment;
});
}
const ticket = this.ticketsRepository.create({ ...createDto, user, category: ticketCategory, messages: [ticketMessage] });
await this.ticketsRepository.save(ticket);
return {
message: TicketMessageEnum.CREATED,
ticketId: ticket.id,
};
}
@@ -146,31 +160,83 @@ export class TicketsService {
return { tickets, count, paginate: true };
}
//******************************** */
//TODO: get for admin with group of category
async getAllTickets(queryDto: SearchTicketQueryDto) {
const { limit, skip } = PaginationUtils(queryDto);
const findOptions = {
where: {
...(queryDto.status && { status: queryDto.status }),
},
relations: {
category: true,
user: true,
},
order: {
createdAt: "DESC" as const,
},
skip,
take: limit,
};
const [tickets, count] = await this.ticketsRepository.findAndCount(findOptions);
return { tickets, count, paginate: true };
}
//******************************** */
async createTicketMessage(ticketId: string, createDto: CreateTicketMessageDto, userId: string, role: Role) {
const userRole = role as unknown as RoleEnum;
let ticket: null | Ticket = null;
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
if (userRole === RoleEnum.ADMIN) {
ticket = await this.ticketsRepository.findTicketById(ticketId);
} else {
ticket = await this.ticketsRepository.findTicketById(ticketId, userId);
try {
const userRole = role as unknown as RoleEnum;
let ticket: null | Ticket = null;
if (userRole === RoleEnum.ADMIN) {
ticket = await queryRunner.manager.findOneBy(Ticket, { id: ticketId });
} else {
ticket = await queryRunner.manager.findOneBy(Ticket, { id: ticketId, user: { id: userId } });
}
if (!ticket) throw new BadRequestException(TicketMessageEnum.TICKET_NOT_FOUND);
if (ticket.status === TicketStatus.CLOSED) throw new BadRequestException(TicketMessageEnum.TICKET_CLOSED);
const user = await queryRunner.manager.findOneBy(User, { id: userId });
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
const ticketMessage = queryRunner.manager.create(TicketMessage, { ...createDto, author: user, ticket });
if (userRole === RoleEnum.ADMIN && ticket.status === TicketStatus.PENDING) {
ticket.status = TicketStatus.ANSWERED;
}
await queryRunner.manager.save(Ticket, ticket);
await queryRunner.manager.save(TicketMessage, ticketMessage);
if (createDto.attachmentUrls) {
const attachments = createDto.attachmentUrls.map((url) =>
queryRunner.manager.create(TicketMessageAttachment, { attachmentUrl: url, ticketMessage }),
);
await queryRunner.manager.save(TicketMessageAttachment, attachments);
}
await queryRunner.commitTransaction();
return {
message: TicketMessageEnum.MESSAGE_CREATED,
ticketMessage,
};
} catch (error) {
await queryRunner.rollbackTransaction();
if (error instanceof HttpException) throw error;
throw new InternalServerErrorException(TicketMessageEnum.ERROR_IN_TICKET_MSG_CREATION);
} finally {
await queryRunner.release();
}
if (!ticket) throw new BadRequestException(TicketMessageEnum.TICKET_NOT_FOUND);
const { user } = await this.usersService.findOneById(userId);
const ticketMessage = this.ticketMessagesRepository.create({ ...createDto, author: user, ticket });
await this.ticketMessagesRepository.save(ticketMessage);
return {
message: TicketMessageEnum.MESSAGE_CREATED,
// ticketMessage,
};
}
//******************************** */