diff --git a/src/common/enums/message.enum.ts b/src/common/enums/message.enum.ts index 6c52c07..5f29d0e 100755 --- a/src/common/enums/message.enum.ts +++ b/src/common/enums/message.enum.ts @@ -585,6 +585,8 @@ export const enum CompanyMessage { COMPANY_REQUEST_STATUS_REQUIRED = "وضعیت درخواست الزامی است", COMPANY_REQUEST_STATUS_MUST_BE_ENUM = "وضعیت درخواست باید یک عنصر از جعبه انتخابی وضعیت درخواست باشد", COMPANY_REQUEST_ALREADY_EXISTS = "درخواست شرکت قبلا ثبت شده است", + COMPANY_REQUEST_NOT_FOUND = "درخواست شرکت یافت نشد", + REJECT_REASON_MUST_BE_STRING = "دلیل رد باید یک رشته باشد", } export const enum BusinessMessage { diff --git a/src/modules/companies/DTO/create-company.dto.ts b/src/modules/companies/DTO/create-company.dto.ts index 330f30c..e8c1997 100644 --- a/src/modules/companies/DTO/create-company.dto.ts +++ b/src/modules/companies/DTO/create-company.dto.ts @@ -125,12 +125,16 @@ export class CreateCompanyRequestDto extends PickType(CreateCompanyDto, [ chiefExecutiveOfficer: string; } -export class ApproveCompanyRequestDto { +export class ChangeCompanyRequestStatusDto { @IsNotEmpty({ message: CompanyMessage.COMPANY_REQUEST_STATUS_REQUIRED }) @IsEnum(CompanyRequestStatus) @ApiProperty({ enum: CompanyRequestStatus, description: "وضعیت درخواست" }) requestStatus: CompanyRequestStatus; + @IsOptional() + @IsString({ message: CompanyMessage.REJECT_REASON_MUST_BE_STRING }) @ApiProperty({ required: false, description: "دلیل رد درخواست" }) rejectReason?: string; } + +//----------------------------------- diff --git a/src/modules/companies/companies.controller.ts b/src/modules/companies/companies.controller.ts index 15de5f3..7a1f6f9 100644 --- a/src/modules/companies/companies.controller.ts +++ b/src/modules/companies/companies.controller.ts @@ -2,7 +2,7 @@ import { Body, Controller, Delete, Get, Param, Patch, Post, Query, UseIntercepto import { ApiOperation } from "@nestjs/swagger"; 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 { CompaniesService } from "./services/companies.service"; 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 { BusinessInterceptor } from "../../core/interceptors/business.interceptor"; import { Business } from "../businesses/entities/business.entity"; +import { RoleEnum } from "../users/enums/role.enum"; @Controller("companies") @UseInterceptors(BusinessInterceptor) @@ -78,6 +79,18 @@ export class CompaniesController { 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") @AuthGuards() @ApiOperation({ summary: "get all company registration requests (user)" }) @@ -92,10 +105,10 @@ export class CompaniesController { return this.companiesService.getCompanyRequests(businessId); } - @Patch("requests/:id/approve") + @Patch("requests/:id/change-status") @AuthGuards() @ApiOperation({ summary: "approve/reject company registration request (admin)" }) - approveCompanyRequest(@Param() paramDto: ParamDto, @Body() approveDto: ApproveCompanyRequestDto, @BusinessDec("id") businessId: string) { - return this.companiesService.approveCompanyRequest(paramDto.id, approveDto, businessId); + changeCompanyRequestStatus(@Param() paramDto: ParamDto, @Body() dto: ChangeCompanyRequestStatusDto, @BusinessDec("id") businessId: string) { + return this.companiesService.changeCompanyRequestStatus(paramDto.id, dto, businessId); } } diff --git a/src/modules/companies/services/companies.service.ts b/src/modules/companies/services/companies.service.ts index 5b93bd4..6c6f843 100644 --- a/src/modules/companies/services/companies.service.ts +++ b/src/modules/companies/services/companies.service.ts @@ -6,10 +6,11 @@ import { CompanyMessage, IndustryMessage } from "../../../common/enums/message.e import { Business } from "../../businesses/entities/business.entity"; import { Industry } from "../../industries/entities/industry.entity"; import { User } from "../../users/entities/user.entity"; +import { RoleEnum } from "../../users/enums/role.enum"; import { UsersService } from "../../users/services/users.service"; import { PasswordService } from "../../utils/providers/password.service"; 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 { CompanyProduct } from "../entities/company-product.entity"; import { CompanyRequest } from "../entities/company-request.enitiy"; @@ -279,6 +280,23 @@ export class CompaniesService { 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(); try { 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; diff --git a/src/modules/tickets/entities/ticket-message.entity.ts b/src/modules/tickets/entities/ticket-message.entity.ts index a8a3631..ffb0f06 100755 --- a/src/modules/tickets/entities/ticket-message.entity.ts +++ b/src/modules/tickets/entities/ticket-message.entity.ts @@ -17,8 +17,8 @@ export class TicketMessage extends BaseEntity { @ManyToOne(() => Ticket, { deleteRule: "cascade", nullable: false }) ticket!: Ticket; - @ManyToOne(() => User, { deleteRule: "cascade", nullable: false }) - author!: User; + @ManyToOne(() => User, { deleteRule: "cascade", nullable: true }) + author!: User | null; [EntityRepositoryType]?: TicketMessagesRepository; } diff --git a/src/modules/tickets/providers/tickets.service.ts b/src/modules/tickets/providers/tickets.service.ts index 89a3c8a..7f94b3e 100755 --- a/src/modules/tickets/providers/tickets.service.ts +++ b/src/modules/tickets/providers/tickets.service.ts @@ -189,8 +189,8 @@ export class TicketsService { return { tickets, count, paginate: true }; } //******************************** */ - async getTicketForAdmin(queryDto: SearchTicketQueryDto, adminId: string, businessId: string) { - const [tickets, count] = await this.ticketsRepository.findTicketsListForAdmin(queryDto, adminId, businessId); + async getTicketForAdmin(queryDto: SearchTicketQueryDto, businessId: string) { + const [tickets, count] = await this.ticketsRepository.findTicketsListForAdmin(queryDto, businessId); return { tickets, count, paginate: true }; } @@ -203,13 +203,16 @@ export class TicketsService { try { 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 (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 }); - if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND); + let user = null; + 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, { content: createDto.content, @@ -225,8 +228,11 @@ export class TicketsService { this.updateTicketStatus(ticket, role === RoleEnum.ADMIN); await em.persistAndFlush(ticket); - if (role === RoleEnum.ADMIN) { - await this.sendNotificationForAdminResponse(ticket, user); + if (role !== RoleEnum.USER) { + //TODO Fix this + console.log(user, "user"); + // await this.sendNotificationForAdminResponse(ticket, user); + console.log(this.sendNotificationForAdminResponse, "sendNotificationForAdminResponse"); } await em.commit(); @@ -246,10 +252,10 @@ export class TicketsService { async getTicketMessages(ticketId: string, userId: string, role: RoleEnum, businessId: string) { let ticket = null; // - if (role === RoleEnum.ADMIN) { - ticket = await this.ticketsRepository.findTicketById(ticketId, businessId); - } else { + if (role === RoleEnum.USER) { 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); @@ -265,10 +271,10 @@ export class TicketsService { async closeTicketByUser(ticketId: string, userId: string, role: RoleEnum, businessId: string) { let ticket = null; - if (role === RoleEnum.ADMIN) { - ticket = await this.ticketsRepository.findTicketById(ticketId, businessId); - } else { + if (role === RoleEnum.USER) { 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); @@ -378,7 +384,7 @@ export class TicketsService { private async findTicket(em: EntityManager, ticketId: string, businessId: string, userId: string, isAdmin: boolean): Promise { 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"] }); if (!ticket) throw new BadRequestException(TicketMessageEnum.TICKET_NOT_FOUND); diff --git a/src/modules/tickets/repositories/tickets.repository.ts b/src/modules/tickets/repositories/tickets.repository.ts index 8ece86c..9565207 100755 --- a/src/modules/tickets/repositories/tickets.repository.ts +++ b/src/modules/tickets/repositories/tickets.repository.ts @@ -69,13 +69,11 @@ export class TicketsRepository extends EntityRepository { }); } //******************************** */ - async findTicketsListForAdmin(queryDto: SearchTicketQueryDto, adminId: string, businessId: string) { + async findTicketsListForAdmin(queryDto: SearchTicketQueryDto, businessId: string) { const { limit, skip } = PaginationUtils(queryDto); const where: FilterQuery = { business: { id: businessId } }; - where.assignedTo = { id: adminId }; - if (queryDto.status) { where.status = queryDto.status; } diff --git a/src/modules/tickets/tickets.controller.ts b/src/modules/tickets/tickets.controller.ts index 7deee4d..d0379b5 100755 --- a/src/modules/tickets/tickets.controller.ts +++ b/src/modules/tickets/tickets.controller.ts @@ -78,8 +78,8 @@ export class TicketsController { @ApiOperation({ summary: "Get all tickets (admin)" }) @Get("admin") - getAllTickets(@Query() queryDto: SearchTicketQueryDto, @UserDec("id") adminId: string, @BusinessDec("id") businessId: string) { - return this.ticketsService.getTicketForAdmin(queryDto, adminId, businessId); + getAllTickets(@Query() queryDto: SearchTicketQueryDto, @BusinessDec("id") businessId: string) { + return this.ticketsService.getTicketForAdmin(queryDto, businessId); } @ApiOperation({ summary: "create ticket messages" })