chore: fix ticket problem

This commit is contained in:
Mahyargdz
2025-05-21 12:41:56 +03:30
parent e83f7366ca
commit 8da977291b
8 changed files with 72 additions and 30 deletions
+2
View File
@@ -585,6 +585,8 @@ export const enum CompanyMessage {
COMPANY_REQUEST_STATUS_REQUIRED = "وضعیت درخواست الزامی است", COMPANY_REQUEST_STATUS_REQUIRED = "وضعیت درخواست الزامی است",
COMPANY_REQUEST_STATUS_MUST_BE_ENUM = "وضعیت درخواست باید یک عنصر از جعبه انتخابی وضعیت درخواست باشد", COMPANY_REQUEST_STATUS_MUST_BE_ENUM = "وضعیت درخواست باید یک عنصر از جعبه انتخابی وضعیت درخواست باشد",
COMPANY_REQUEST_ALREADY_EXISTS = "درخواست شرکت قبلا ثبت شده است", COMPANY_REQUEST_ALREADY_EXISTS = "درخواست شرکت قبلا ثبت شده است",
COMPANY_REQUEST_NOT_FOUND = "درخواست شرکت یافت نشد",
REJECT_REASON_MUST_BE_STRING = "دلیل رد باید یک رشته باشد",
} }
export const enum BusinessMessage { export const enum BusinessMessage {
@@ -125,12 +125,16 @@ export class CreateCompanyRequestDto extends PickType(CreateCompanyDto, [
chiefExecutiveOfficer: string; chiefExecutiveOfficer: string;
} }
export class ApproveCompanyRequestDto { export class ChangeCompanyRequestStatusDto {
@IsNotEmpty({ message: CompanyMessage.COMPANY_REQUEST_STATUS_REQUIRED }) @IsNotEmpty({ message: CompanyMessage.COMPANY_REQUEST_STATUS_REQUIRED })
@IsEnum(CompanyRequestStatus) @IsEnum(CompanyRequestStatus)
@ApiProperty({ enum: CompanyRequestStatus, description: "وضعیت درخواست" }) @ApiProperty({ enum: CompanyRequestStatus, description: "وضعیت درخواست" })
requestStatus: CompanyRequestStatus; requestStatus: CompanyRequestStatus;
@IsOptional()
@IsString({ message: CompanyMessage.REJECT_REASON_MUST_BE_STRING })
@ApiProperty({ required: false, description: "دلیل رد درخواست" }) @ApiProperty({ required: false, description: "دلیل رد درخواست" })
rejectReason?: string; rejectReason?: string;
} }
//-----------------------------------
+17 -4
View File
@@ -2,7 +2,7 @@ import { Body, Controller, Delete, Get, Param, Patch, Post, Query, UseIntercepto
import { ApiOperation } from "@nestjs/swagger"; import { ApiOperation } from "@nestjs/swagger";
import { CompanyListPublicQueryDto, CompanyListQueryDto } from "./DTO/company-list-query.dto"; import { CompanyListPublicQueryDto, CompanyListQueryDto } from "./DTO/company-list-query.dto";
import { ApproveCompanyRequestDto, CreateCompanyDto, CreateCompanyRequestDto } from "./DTO/create-company.dto"; import { ChangeCompanyRequestStatusDto, CreateCompanyDto, CreateCompanyRequestDto } from "./DTO/create-company.dto";
import { UpdateCompanyDto } from "./DTO/update-company.dto"; import { UpdateCompanyDto } from "./DTO/update-company.dto";
import { CompaniesService } from "./services/companies.service"; import { CompaniesService } from "./services/companies.service";
import { AuthGuards } from "../../common/decorators/auth-guard.decorator"; import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
@@ -11,6 +11,7 @@ import { UserDec } from "../../common/decorators/user.decorator";
import { ParamDto } from "../../common/DTO/param.dto"; import { ParamDto } from "../../common/DTO/param.dto";
import { BusinessInterceptor } from "../../core/interceptors/business.interceptor"; import { BusinessInterceptor } from "../../core/interceptors/business.interceptor";
import { Business } from "../businesses/entities/business.entity"; import { Business } from "../businesses/entities/business.entity";
import { RoleEnum } from "../users/enums/role.enum";
@Controller("companies") @Controller("companies")
@UseInterceptors(BusinessInterceptor) @UseInterceptors(BusinessInterceptor)
@@ -78,6 +79,18 @@ export class CompaniesController {
return this.companiesService.createCompanyRequest(createDto, userId, business); return this.companiesService.createCompanyRequest(createDto, userId, business);
} }
@Get("requests/:id")
@AuthGuards()
@ApiOperation({ summary: "get company registration request by id" })
getCompanyRequestById(
@Param() paramDto: ParamDto,
@UserDec("role") role: RoleEnum,
@UserDec("id") userId: string,
@BusinessDec("id") businessId: string,
) {
return this.companiesService.getCompanyRequestById(paramDto.id, role, userId, businessId);
}
@Get("requests/user") @Get("requests/user")
@AuthGuards() @AuthGuards()
@ApiOperation({ summary: "get all company registration requests (user)" }) @ApiOperation({ summary: "get all company registration requests (user)" })
@@ -92,10 +105,10 @@ export class CompaniesController {
return this.companiesService.getCompanyRequests(businessId); return this.companiesService.getCompanyRequests(businessId);
} }
@Patch("requests/:id/approve") @Patch("requests/:id/change-status")
@AuthGuards() @AuthGuards()
@ApiOperation({ summary: "approve/reject company registration request (admin)" }) @ApiOperation({ summary: "approve/reject company registration request (admin)" })
approveCompanyRequest(@Param() paramDto: ParamDto, @Body() approveDto: ApproveCompanyRequestDto, @BusinessDec("id") businessId: string) { changeCompanyRequestStatus(@Param() paramDto: ParamDto, @Body() dto: ChangeCompanyRequestStatusDto, @BusinessDec("id") businessId: string) {
return this.companiesService.approveCompanyRequest(paramDto.id, approveDto, businessId); return this.companiesService.changeCompanyRequestStatus(paramDto.id, dto, businessId);
} }
} }
@@ -6,10 +6,11 @@ import { CompanyMessage, IndustryMessage } from "../../../common/enums/message.e
import { Business } from "../../businesses/entities/business.entity"; import { Business } from "../../businesses/entities/business.entity";
import { Industry } from "../../industries/entities/industry.entity"; import { Industry } from "../../industries/entities/industry.entity";
import { User } from "../../users/entities/user.entity"; import { User } from "../../users/entities/user.entity";
import { RoleEnum } from "../../users/enums/role.enum";
import { UsersService } from "../../users/services/users.service"; import { UsersService } from "../../users/services/users.service";
import { PasswordService } from "../../utils/providers/password.service"; import { PasswordService } from "../../utils/providers/password.service";
import { CompanyListPublicQueryDto, CompanyListQueryDto } from "../DTO/company-list-query.dto"; import { CompanyListPublicQueryDto, CompanyListQueryDto } from "../DTO/company-list-query.dto";
import { ApproveCompanyRequestDto, CreateCompanyDto, CreateCompanyRequestDto } from "../DTO/create-company.dto"; import { ChangeCompanyRequestStatusDto, CreateCompanyDto, CreateCompanyRequestDto } from "../DTO/create-company.dto";
import { UpdateCompanyDto } from "../DTO/update-company.dto"; import { UpdateCompanyDto } from "../DTO/update-company.dto";
import { CompanyProduct } from "../entities/company-product.entity"; import { CompanyProduct } from "../entities/company-product.entity";
import { CompanyRequest } from "../entities/company-request.enitiy"; import { CompanyRequest } from "../entities/company-request.enitiy";
@@ -279,6 +280,23 @@ export class CompaniesService {
throw error; throw error;
} }
} }
//-----------------------------------
async getCompanyRequestById(id: string, role: RoleEnum, userId: string, businessId: string) {
let request = null;
if (role === RoleEnum.USER) {
request = await this.companyRequestRepository.findOne(
{ id, business: { id: businessId }, user: { id: userId }, deletedAt: null },
{ populate: ["company"] },
);
} else {
request = await this.companyRequestRepository.findOne({ id, business: { id: businessId }, deletedAt: null }, { populate: ["company"] });
}
if (!request) throw new BadRequestException(CompanyMessage.COMPANY_REQUEST_NOT_FOUND);
return { request };
}
//----------------------------------- //-----------------------------------
@@ -305,11 +323,12 @@ export class CompaniesService {
//----------------------------------- //-----------------------------------
async approveCompanyRequest(id: string, dto: ApproveCompanyRequestDto, businessId: string) { async changeCompanyRequestStatus(id: string, dto: ChangeCompanyRequestStatusDto, businessId: string) {
const em = this.em.fork(); const em = this.em.fork();
try { try {
await em.begin(); await em.begin();
const request = await em.findOneOrFail(CompanyRequest, { id, business: { id: businessId } }, { populate: ["company"] }); const request = await em.findOne(CompanyRequest, { id, business: { id: businessId } }, { populate: ["company"] });
if (!request) throw new BadRequestException(CompanyMessage.COMPANY_REQUEST_NOT_FOUND);
request.requestStatus = dto.requestStatus; request.requestStatus = dto.requestStatus;
@@ -17,8 +17,8 @@ export class TicketMessage extends BaseEntity {
@ManyToOne(() => Ticket, { deleteRule: "cascade", nullable: false }) @ManyToOne(() => Ticket, { deleteRule: "cascade", nullable: false })
ticket!: Ticket; ticket!: Ticket;
@ManyToOne(() => User, { deleteRule: "cascade", nullable: false }) @ManyToOne(() => User, { deleteRule: "cascade", nullable: true })
author!: User; author!: User | null;
[EntityRepositoryType]?: TicketMessagesRepository; [EntityRepositoryType]?: TicketMessagesRepository;
} }
@@ -189,8 +189,8 @@ export class TicketsService {
return { tickets, count, paginate: true }; return { tickets, count, paginate: true };
} }
//******************************** */ //******************************** */
async getTicketForAdmin(queryDto: SearchTicketQueryDto, adminId: string, businessId: string) { async getTicketForAdmin(queryDto: SearchTicketQueryDto, businessId: string) {
const [tickets, count] = await this.ticketsRepository.findTicketsListForAdmin(queryDto, adminId, businessId); const [tickets, count] = await this.ticketsRepository.findTicketsListForAdmin(queryDto, businessId);
return { tickets, count, paginate: true }; return { tickets, count, paginate: true };
} }
@@ -203,13 +203,16 @@ export class TicketsService {
try { try {
await em.begin(); await em.begin();
const ticket = await this.findTicket(em, ticketId, businessId, userId, role === RoleEnum.ADMIN); const ticket = await this.findTicket(em, ticketId, businessId, userId, role !== RoleEnum.ADMIN);
if (ticket.status === TicketStatus.CLOSED) throw new BadRequestException(TicketMessageEnum.TICKET_CLOSED); if (ticket.status === TicketStatus.CLOSED) throw new BadRequestException(TicketMessageEnum.TICKET_CLOSED);
if (role === RoleEnum.ADMIN && ticket.assignedTo?.id !== userId) throw new BadRequestException(TicketMessageEnum.TICKET_NOT_ASSIGNED_TO_USER); // if (role !== RoleEnum.ADMIN && ticket.assignedTo?.id !== userId) throw new BadRequestException(TicketMessageEnum.TICKET_NOT_ASSIGNED_TO_USER);
const user = await em.findOne(User, { id: userId }); let user = null;
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND); if (role === RoleEnum.USER) {
user = await em.findOne(User, { id: userId });
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
}
const ticketMessage = em.create(TicketMessage, { const ticketMessage = em.create(TicketMessage, {
content: createDto.content, content: createDto.content,
@@ -225,8 +228,11 @@ export class TicketsService {
this.updateTicketStatus(ticket, role === RoleEnum.ADMIN); this.updateTicketStatus(ticket, role === RoleEnum.ADMIN);
await em.persistAndFlush(ticket); await em.persistAndFlush(ticket);
if (role === RoleEnum.ADMIN) { if (role !== RoleEnum.USER) {
await this.sendNotificationForAdminResponse(ticket, user); //TODO Fix this
console.log(user, "user");
// await this.sendNotificationForAdminResponse(ticket, user);
console.log(this.sendNotificationForAdminResponse, "sendNotificationForAdminResponse");
} }
await em.commit(); await em.commit();
@@ -246,10 +252,10 @@ export class TicketsService {
async getTicketMessages(ticketId: string, userId: string, role: RoleEnum, businessId: string) { async getTicketMessages(ticketId: string, userId: string, role: RoleEnum, businessId: string) {
let ticket = null; let ticket = null;
// //
if (role === RoleEnum.ADMIN) { if (role === RoleEnum.USER) {
ticket = await this.ticketsRepository.findTicketById(ticketId, businessId);
} else {
ticket = await this.ticketsRepository.findTicketById(ticketId, businessId, userId); ticket = await this.ticketsRepository.findTicketById(ticketId, businessId, userId);
} else {
ticket = await this.ticketsRepository.findTicketById(ticketId, businessId);
} }
if (!ticket) throw new BadRequestException(TicketMessageEnum.TICKET_NOT_FOUND); if (!ticket) throw new BadRequestException(TicketMessageEnum.TICKET_NOT_FOUND);
@@ -265,10 +271,10 @@ export class TicketsService {
async closeTicketByUser(ticketId: string, userId: string, role: RoleEnum, businessId: string) { async closeTicketByUser(ticketId: string, userId: string, role: RoleEnum, businessId: string) {
let ticket = null; let ticket = null;
if (role === RoleEnum.ADMIN) { if (role === RoleEnum.USER) {
ticket = await this.ticketsRepository.findTicketById(ticketId, businessId);
} else {
ticket = await this.ticketsRepository.findTicketById(ticketId, businessId, userId); ticket = await this.ticketsRepository.findTicketById(ticketId, businessId, userId);
} else {
ticket = await this.ticketsRepository.findTicketById(ticketId, businessId);
} }
if (!ticket) throw new BadRequestException(TicketMessageEnum.TICKET_NOT_FOUND); if (!ticket) throw new BadRequestException(TicketMessageEnum.TICKET_NOT_FOUND);
@@ -378,7 +384,7 @@ export class TicketsService {
private async findTicket(em: EntityManager, ticketId: string, businessId: string, userId: string, isAdmin: boolean): Promise<Ticket> { private async findTicket(em: EntityManager, ticketId: string, businessId: string, userId: string, isAdmin: boolean): Promise<Ticket> {
const ticket = isAdmin const ticket = isAdmin
? await em.findOne(Ticket, { id: ticketId, user: { id: userId }, business: { id: businessId } }, { populate: ["user", "assignedTo"] }) ? await em.findOne(Ticket, { id: ticketId, business: { id: businessId } }, { populate: ["user", "assignedTo"] })
: await em.findOne(Ticket, { id: ticketId, user: { id: userId }, business: { id: businessId } }, { populate: ["user", "assignedTo"] }); : await em.findOne(Ticket, { id: ticketId, user: { id: userId }, business: { id: businessId } }, { populate: ["user", "assignedTo"] });
if (!ticket) throw new BadRequestException(TicketMessageEnum.TICKET_NOT_FOUND); if (!ticket) throw new BadRequestException(TicketMessageEnum.TICKET_NOT_FOUND);
@@ -69,13 +69,11 @@ export class TicketsRepository extends EntityRepository<Ticket> {
}); });
} }
//******************************** */ //******************************** */
async findTicketsListForAdmin(queryDto: SearchTicketQueryDto, adminId: string, businessId: string) { async findTicketsListForAdmin(queryDto: SearchTicketQueryDto, businessId: string) {
const { limit, skip } = PaginationUtils(queryDto); const { limit, skip } = PaginationUtils(queryDto);
const where: FilterQuery<Ticket> = { business: { id: businessId } }; const where: FilterQuery<Ticket> = { business: { id: businessId } };
where.assignedTo = { id: adminId };
if (queryDto.status) { if (queryDto.status) {
where.status = queryDto.status; where.status = queryDto.status;
} }
+2 -2
View File
@@ -78,8 +78,8 @@ export class TicketsController {
@ApiOperation({ summary: "Get all tickets (admin)" }) @ApiOperation({ summary: "Get all tickets (admin)" })
@Get("admin") @Get("admin")
getAllTickets(@Query() queryDto: SearchTicketQueryDto, @UserDec("id") adminId: string, @BusinessDec("id") businessId: string) { getAllTickets(@Query() queryDto: SearchTicketQueryDto, @BusinessDec("id") businessId: string) {
return this.ticketsService.getTicketForAdmin(queryDto, adminId, businessId); return this.ticketsService.getTicketForAdmin(queryDto, businessId);
} }
@ApiOperation({ summary: "create ticket messages" }) @ApiOperation({ summary: "create ticket messages" })