update: change the danak services fetch to another route and accept category id "

query for that
This commit is contained in:
mahyargdz
2025-03-02 15:19:55 +03:30
parent af9f365bc7
commit 4d0344c376
9 changed files with 99 additions and 25 deletions
+3 -1
View File
@@ -1,4 +1,4 @@
import { ApiProperty } from "@nestjs/swagger";
import { ApiProperty, PartialType } from "@nestjs/swagger";
import { IsNotEmpty, IsUUID } from "class-validator";
import { CommonMessage } from "../enums/message.enum";
@@ -10,6 +10,8 @@ export class ParamDto {
id: string;
}
export class OptionalParamDto extends PartialType(ParamDto) {}
export class ParamNumberIdDto {
@IsNotEmpty({ message: CommonMessage.ID_REQUIRED })
@ApiProperty({ description: "Id of the entity", example: "20" })
+5
View File
@@ -165,6 +165,7 @@ export const enum ServiceMessage {
REVIEW_REJECTED = "نظر با موفقیت رد شد",
IS_ACTIVE_SHOULD_BE_1_0 = "وضعیت سرویس باید یکی از مقادیر ۰ و ۱ باشد",
IS_SUGGEST_SHOULD_BE_1_0 = "وضعیت پیشنهادی بودن سرویس باید یکی از مقادیر ۰ و ۱ باشد",
REVIEW_STATUS_REQUIRED = "وضعیت نظر سرویس مورد نیاز است",
}
export const enum AnnouncementMessage {
@@ -560,3 +561,7 @@ export const enum UserQuickAccessMessage {
QUICK_ACCESS_LIMIT_REACHED = "حداکثر تعداد دسترسی سریع برای این کاربر ایجاد شده است",
QUICK_ACCESS_EXIST = "این دسترسی سریع قبلا ایجاد شده است",
}
export const enum SmsMessage {
SEND_SMS_ERROR = "خطا در ارسال پیامک",
}
@@ -1,13 +1,13 @@
import { ApiPropertyOptional } from "@nestjs/swagger";
import { ApiPropertyOptional, PickType } from "@nestjs/swagger";
import { Type } from "class-transformer";
import { IsIn, IsOptional, IsString } from "class-validator";
import { IsIn, IsOptional, IsString, IsUUID } from "class-validator";
import { PaginationDto } from "../../../common/DTO/pagination.dto";
import { CategoryMessage, ServiceMessage } from "../../../common/enums/message.enum";
export class DanakServicesSearchQueryDto extends PaginationDto {
@IsOptional()
@IsString({ message: CategoryMessage.CAT_ID_SHOULD_BE_UUID })
@IsUUID(4, { message: CategoryMessage.CAT_ID_SHOULD_BE_UUID })
@ApiPropertyOptional({ description: "Category id", example: "8b1e8b1e-8b1e-8b1e-8b1e-8b1e8b1e8b1e" })
categoryId?: string;
@@ -28,3 +28,5 @@ export class DanakServicesSearchQueryDto extends PaginationDto {
@ApiPropertyOptional({ description: "is danak suggest this service", example: 1 })
isDanakSuggest?: number;
}
export class DanakServicesQueryDto extends PickType(DanakServicesSearchQueryDto, ["limit", "page", "categoryId"] as const) {}
@@ -0,0 +1,13 @@
import { ApiProperty } from "@nestjs/swagger";
import { IsEnum, IsNotEmpty } from "class-validator";
import { ParamDto } from "../../../common/DTO/param.dto";
import { ServiceMessage } from "../../../common/enums/message.enum";
import { ReviewStatus } from "../enums/review-status.enum";
export class UpdateReviewStatusDto extends ParamDto {
@IsNotEmpty({ message: ServiceMessage.REVIEW_STATUS_REQUIRED })
@IsEnum(ReviewStatus)
@ApiProperty({ enum: ReviewStatus, example: ReviewStatus.APPROVED, description: "Review status" })
status: ReviewStatus;
}
@@ -1,4 +1,4 @@
import { Body, Controller, Get, HttpCode, HttpStatus, Param, Post, Query } from "@nestjs/common";
import { Body, Controller, Get, HttpCode, HttpStatus, Param, Patch, Post, Query } from "@nestjs/common";
import { ApiOperation, ApiTags } from "@nestjs/swagger";
import { AddReviewDto } from "./DTO/add-review.dto";
@@ -6,7 +6,8 @@ import { CategoryListSearchQueryDto, CategorySearchQueryDto } from "./DTO/catego
import { CreateCategoryDto } from "./DTO/create-category.dto";
import { CreateServiceDto } from "./DTO/create-service.dto";
import { DanakServiceReviewQueryDto } from "./DTO/danak-service-review-query.dto";
import { DanakServicesSearchQueryDto } from "./DTO/danak-services-search-query.dto";
import { DanakServicesQueryDto, DanakServicesSearchQueryDto } from "./DTO/danak-services-search-query.dto";
import { UpdateReviewStatusDto } from "./DTO/update-review-status.dto";
import { DanakServicesService } from "./providers/danak-services.service";
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
import { Pagination } from "../../common/decorators/pagination.decorator";
@@ -53,12 +54,12 @@ export class DanakServicesController {
return this.danakServicesService.getCategoriesUserSide();
}
@AuthGuards()
@ApiOperation({ summary: "get category services with category id" })
@Get("categories/:id/services")
getCategoryServices(@Param() paramDto: ParamDto) {
return this.danakServicesService.getCategoryServices(paramDto.id);
}
// @AuthGuards()
// @ApiOperation({ summary: "get category services with category id" })
// @Get("categories/:id/services")
// getCategoryServices(@Param() paramDto: ParamDto) {
// return this.danakServicesService.getCategoryServices(paramDto.id);
// }
@AuthGuards()
@PermissionsDec(PermissionEnum.SERVICES)
@@ -85,6 +86,13 @@ export class DanakServicesController {
return this.danakServicesService.getServicesList(queryDto);
}
@ApiOperation({ summary: "get all danak services for user side" })
@AuthGuards()
@Get("public")
getServicesForUser(@Query() queryDto: DanakServicesQueryDto) {
return this.danakServicesService.getServicesListForUser(queryDto);
}
@AuthGuards()
@PermissionsDec(PermissionEnum.SERVICES)
@ApiOperation({ summary: "toggle status of danak service => admin route" })
@@ -124,6 +132,14 @@ export class DanakServicesController {
return this.danakServicesService.getDanakServiceReviews(queryDto);
}
@ApiOperation({ summary: "update danak service review status ==> admin route" })
@AuthGuards()
@PermissionsDec(PermissionEnum.SERVICES)
@Patch("reviews/:id/:status")
updateDanakServiceReviewStatus(@Param() updateParamDto: UpdateReviewStatusDto) {
return this.danakServicesService.updateDanakServiceReviewStatus(updateParamDto);
}
// @AuthGuards()
//
// @ApiOperation({ summary: "get all user purchased danak services" })
@@ -10,7 +10,8 @@ import { CategoryListSearchQueryDto, CategorySearchQueryDto } from "../DTO/categ
import { CreateCategoryDto } from "../DTO/create-category.dto";
import { CreateServiceDto } from "../DTO/create-service.dto";
import { DanakServiceReviewQueryDto } from "../DTO/danak-service-review-query.dto";
import { DanakServicesSearchQueryDto } from "../DTO/danak-services-search-query.dto";
import { DanakServicesQueryDto, DanakServicesSearchQueryDto } from "../DTO/danak-services-search-query.dto";
import { UpdateReviewStatusDto } from "../DTO/update-review-status.dto";
import { DanakServiceCategory } from "../entities/danak-service-category.entity";
import { ReviewStatus } from "../enums/review-status.enum";
import { DanakServicesCategoryRepository } from "../repositories/danak-services-category.repository";
@@ -96,7 +97,7 @@ export class DanakServicesService {
}
/******************************************** */
async getCategoryServices(categoryId: string) {
async getCategoryServices(categoryId?: string) {
const category = await this.danakServicesCategoryRepository.findOne({
where: { id: categoryId, isActive: true, danakServices: { isActive: true } },
relations: {
@@ -164,6 +165,11 @@ export class DanakServicesService {
async getServicesList(queryDto: DanakServicesSearchQueryDto) {
return this.danakServicesRepository.getServicesForAdmin(queryDto);
}
/******************************************** */
async getServicesListForUser(queryDto: DanakServicesQueryDto) {
return this.danakServicesRepository.getServicesForUser(queryDto);
}
/******************************************** */
@@ -322,6 +328,14 @@ export class DanakServicesService {
/******************************************** */
async updateDanakServiceReviewStatus(updateParamDto: UpdateReviewStatusDto) {
if (updateParamDto.status === ReviewStatus.APPROVED) {
return await this.approveReview(updateParamDto.id);
} else {
return await this.rejectReview(updateParamDto.id);
}
}
async approveReview(reviewId: string) {
const review = await this.danakServiceReviewRepository.findOneBy({ id: reviewId });
if (!review) throw new BadRequestException(ServiceMessage.REVIEW_NOT_EXIST);
@@ -3,7 +3,7 @@ import { InjectRepository } from "@nestjs/typeorm";
import { Brackets, Repository } from "typeorm";
import { PaginationUtils } from "../../utils/providers/pagination.utils";
import { DanakServicesSearchQueryDto } from "../DTO/danak-services-search-query.dto";
import { DanakServicesQueryDto, DanakServicesSearchQueryDto } from "../DTO/danak-services-search-query.dto";
import { DanakService } from "../entities/danak-service.entity";
@Injectable()
@@ -19,7 +19,7 @@ export class DanakServicesRepository extends Repository<DanakService> {
async findServiceById(id: string): Promise<DanakService | null> {
return this.findOneBy({ id });
}
//+********************
async getServicesForAdmin(queryDto: DanakServicesSearchQueryDto) {
const { limit, skip } = PaginationUtils(queryDto);
@@ -54,6 +54,31 @@ export class DanakServicesRepository extends Repository<DanakService> {
}
const [services, count] = await queryBuilder.getManyAndCount();
return {
services,
count,
};
}
//+********************
async getServicesForUser(queryDto: DanakServicesQueryDto) {
const { limit, skip } = PaginationUtils(queryDto);
const queryBuilder = this.createQueryBuilder("service");
queryBuilder
.innerJoin("service.subscriptionPlans", "subscriptionPlans", "subscriptionPlans.isActive = :isActive", { isActive: true })
.leftJoinAndSelect("service.category", "category")
.where("service.isActive = :isActive", { isActive: true })
.andWhere("service.isDanakSuggest = :isDanakSuggest", { isDanakSuggest: true })
.orderBy("service.createdAt", "DESC")
.skip(skip)
.take(limit);
if (queryDto.categoryId) {
queryBuilder.andWhere("service.categoryId = :categoryId", { categoryId: queryDto.categoryId });
}
const [services, count] = await queryBuilder.getManyAndCount();
return {
services,
count,
@@ -199,6 +199,7 @@ export class InvoicesService {
dueDate,
items: invoiceItems,
});
await queryRunner.manager.save(Invoice, invoice);
await this.notificationsService.createInvoiceCreationNotification(
user.id,
@@ -214,7 +215,6 @@ export class InvoicesService {
queryRunner,
);
//
await queryRunner.manager.save(Invoice, invoice);
return invoice;
}
+5 -8
View File
@@ -3,6 +3,7 @@ import { Inject, Injectable, InternalServerErrorException, Logger } from "@nestj
import { AxiosError } from "axios";
import { catchError, firstValueFrom } from "rxjs";
import { SmsMessage } from "../../../common/enums/message.enum";
import { ISmsConfigs } from "../../../configs/sms.config";
import { SMS_CONFIG } from "../constants";
import { ISmsGetLineResponse, ISmsVerifyBody, ISmsVerifyResponse } from "../interfaces/ISms";
@@ -46,6 +47,7 @@ export class SmsService {
return data;
} catch (error) {
this.logger.error("error in sending sms", error);
throw new InternalServerErrorException(SmsMessage.SEND_SMS_ERROR);
}
}
//************************************************* */
@@ -81,7 +83,7 @@ export class SmsService {
return data;
} catch (error) {
this.logger.error("error in sending sms", error);
throw new InternalServerErrorException("error in sending sms");
throw new InternalServerErrorException(SmsMessage.SEND_SMS_ERROR);
}
}
//************************************************* */
@@ -109,7 +111,6 @@ export class SmsService {
return data;
} catch (error) {
this.logger.error("error in sending sms", error);
// throw new InternalServerErrorException("error in sending sms");
}
}
//************************************************* */
@@ -135,6 +136,8 @@ export class SmsService {
})
.pipe(
catchError((err: AxiosError) => {
console.error(err);
this.logger.error("error in sending invoice created sms", err);
throw new InternalServerErrorException("error in sending invoice created sms");
}),
@@ -143,7 +146,6 @@ export class SmsService {
return data;
} catch (error) {
this.logger.error("error in sending sms", error);
throw new InternalServerErrorException("error in sending sms");
}
}
//************************************************* */
@@ -174,7 +176,6 @@ export class SmsService {
return data;
} catch (error) {
this.logger.error("error in sending sms", error);
throw new InternalServerErrorException("error in sending sms");
}
}
//************************************************* */
@@ -206,7 +207,6 @@ export class SmsService {
return data;
} catch (error) {
this.logger.error("error in sending sms", error);
throw new InternalServerErrorException("error in sending sms");
}
}
//************************************************* */
@@ -239,7 +239,6 @@ export class SmsService {
return data;
} catch (error) {
this.logger.error("error in sending sms", error);
throw new InternalServerErrorException("error in sending sms");
}
}
@@ -272,7 +271,6 @@ export class SmsService {
return data;
} catch (error) {
this.logger.error("error in sending sms", error);
throw new InternalServerErrorException("error in sending sms");
}
}
//************************************************* */
@@ -303,7 +301,6 @@ export class SmsService {
return data;
} catch (error) {
this.logger.error("error in sending sms", error);
throw new InternalServerErrorException("error in sending sms");
}
}