update: add new route to get service with slug
This commit is contained in:
@@ -198,9 +198,9 @@ export const enum ServiceMessage {
|
|||||||
SHOW_IN_SLIDER_BOOLEAN = "وضعیت نمایش در اسلایدر سرویس باید یک بولین باشد",
|
SHOW_IN_SLIDER_BOOLEAN = "وضعیت نمایش در اسلایدر سرویس باید یک بولین باشد",
|
||||||
COVER_URL_REQUIRED = "آدرس عکس کاور سرویس مورد نیاز است",
|
COVER_URL_REQUIRED = "آدرس عکس کاور سرویس مورد نیاز است",
|
||||||
COVER_URL_SHOULD_BE_URL = "آدرس عکس کاور سرویس باید یک آدرس یو آر ال باشد",
|
COVER_URL_SHOULD_BE_URL = "آدرس عکس کاور سرویس باید یک آدرس یو آر ال باشد",
|
||||||
SLUG_REQUIRED = "شناسه منحصر به فرد سرویس مورد نیاز است",
|
SLUG_REQUIRED = "اسلاگ سرویس مورد نیاز است",
|
||||||
SLUG_STRING = "شناسه منحصر به فرد سرویس باید یک رشته باشد",
|
SLUG_STRING = "اسلاگ سرویس باید یک رشته باشد",
|
||||||
SLUG_LENGTH = "شناسه منحصر به فرد سرویس باید بین ۳ تا ۱۵۰ کاراکتر باشد",
|
SLUG_LENGTH = "اسلاگ سرویس باید بین ۳ تا ۱۵۰ کاراکتر باشد",
|
||||||
SERVICE_ALREADY_EXISTS_WITH_THIS_SLUG = "سرویسی با این اسلاگ قبلا ثبت شده است",
|
SERVICE_ALREADY_EXISTS_WITH_THIS_SLUG = "سرویسی با این اسلاگ قبلا ثبت شده است",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { ApiProperty } from "@nestjs/swagger";
|
||||||
|
import { IsNotEmpty, IsString, Length } from "class-validator";
|
||||||
|
|
||||||
|
import { ServiceMessage } from "../../../common/enums/message.enum";
|
||||||
|
export class GetServiceBySlugParamDto {
|
||||||
|
@IsNotEmpty({ message: ServiceMessage.SLUG_REQUIRED })
|
||||||
|
@IsString({ message: ServiceMessage.SLUG_STRING })
|
||||||
|
@Length(3, 150, { message: ServiceMessage.SLUG_LENGTH })
|
||||||
|
@ApiProperty({ description: "slug of the service", example: "service-slug" })
|
||||||
|
slug: string;
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import { CreateDanakServiceCategoryDto } from "./DTO/create-category.dto";
|
|||||||
import { CreateServiceDto } from "./DTO/create-service.dto";
|
import { CreateServiceDto } from "./DTO/create-service.dto";
|
||||||
import { DanakServiceReviewQueryDto } from "./DTO/danak-service-review-query.dto";
|
import { DanakServiceReviewQueryDto } from "./DTO/danak-service-review-query.dto";
|
||||||
import { DanakServicesGlobalSearchDto, DanakServicesQueryDto, DanakServicesSearchQueryDto } from "./DTO/danak-services-search-query.dto";
|
import { DanakServicesGlobalSearchDto, DanakServicesQueryDto, DanakServicesSearchQueryDto } from "./DTO/danak-services-search-query.dto";
|
||||||
|
import { GetServiceBySlugParamDto } from "./DTO/get-service-by-slug-param.dto";
|
||||||
import { UpdateDanakServiceCategoryDto } from "./DTO/update-category.dto";
|
import { UpdateDanakServiceCategoryDto } from "./DTO/update-category.dto";
|
||||||
import { UpdateReviewStatusDto } from "./DTO/update-review-status.dto";
|
import { UpdateReviewStatusDto } from "./DTO/update-review-status.dto";
|
||||||
import { UpdateServiceDto } from "./DTO/update-service.dto";
|
import { UpdateServiceDto } from "./DTO/update-service.dto";
|
||||||
@@ -156,12 +157,24 @@ export class DanakServicesController {
|
|||||||
return this.danakServicesService.getDanakServiceByIdWithSubs(paramDto.id, isAdmin, userId);
|
return this.danakServicesService.getDanakServiceByIdWithSubs(paramDto.id, isAdmin, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiOperation({ summary: "get danakService by slug" })
|
||||||
|
@Get("slug/:slug")
|
||||||
|
getServiceBySlug(@Param() paramDto: GetServiceBySlugParamDto, @UserDec("isAdmin") isAdmin: boolean, @UserDec("id") userId: string) {
|
||||||
|
return this.danakServicesService.getServiceBySlugWithSubs(paramDto.slug, isAdmin, userId);
|
||||||
|
}
|
||||||
|
|
||||||
@ApiOperation({ summary: "get danakService by id public" })
|
@ApiOperation({ summary: "get danakService by id public" })
|
||||||
@Get(":id/public")
|
@Get(":id/public")
|
||||||
getDanakServiceByIdPublic(@Param() paramDto: ParamDto) {
|
getDanakServiceByIdPublic(@Param() paramDto: ParamDto) {
|
||||||
return this.danakServicesService.getDanakServiceByIdPublic(paramDto.id);
|
return this.danakServicesService.getDanakServiceByIdPublic(paramDto.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiOperation({ summary: "get danakService by slug public" })
|
||||||
|
@Get("slug/:slug/public")
|
||||||
|
getServiceBySlugPublic(@Param() paramDto: GetServiceBySlugParamDto) {
|
||||||
|
return this.danakServicesService.getServiceBySlugPublic(paramDto.slug);
|
||||||
|
}
|
||||||
|
|
||||||
@ApiOperation({ summary: "update danak service" })
|
@ApiOperation({ summary: "update danak service" })
|
||||||
@AuthGuards()
|
@AuthGuards()
|
||||||
@PermissionsDec(PermissionEnum.SERVICES)
|
@PermissionsDec(PermissionEnum.SERVICES)
|
||||||
|
|||||||
@@ -441,6 +441,21 @@ export class DanakServicesService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
/******************************************** */
|
/******************************************** */
|
||||||
|
async getServiceBySlugWithSubs(slug: string, isAdmin: boolean, userId: string) {
|
||||||
|
const danakService = await this.danakServicesRepository.getServiceBySlug(slug, isAdmin);
|
||||||
|
|
||||||
|
if (!danakService) throw new BadRequestException(ServiceMessage.SERVICE_NOT_FOUND_BY_ID);
|
||||||
|
|
||||||
|
const averageRating = await this.danakServiceReviewRepository.getAverageRating(danakService.id);
|
||||||
|
|
||||||
|
const hasSubscription = await this.checkUserPurchasedService(userId, danakService.id);
|
||||||
|
return {
|
||||||
|
danakService,
|
||||||
|
averageRating,
|
||||||
|
purchased: !!hasSubscription,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/******************************************** */
|
||||||
|
|
||||||
async getDanakServiceByIdPublic(serviceId: string) {
|
async getDanakServiceByIdPublic(serviceId: string) {
|
||||||
const danakService = await this.danakServicesRepository.getDanakServiceById(serviceId, false);
|
const danakService = await this.danakServicesRepository.getDanakServiceById(serviceId, false);
|
||||||
@@ -450,6 +465,14 @@ export class DanakServicesService {
|
|||||||
return { danakService, averageRating };
|
return { danakService, averageRating };
|
||||||
}
|
}
|
||||||
/******************************************** */
|
/******************************************** */
|
||||||
|
async getServiceBySlugPublic(slug: string) {
|
||||||
|
const danakService = await this.danakServicesRepository.getServiceBySlug(slug, false);
|
||||||
|
if (!danakService) throw new BadRequestException(ServiceMessage.SERVICE_NOT_FOUND_BY_ID);
|
||||||
|
const averageRating = await this.danakServiceReviewRepository.getAverageRating(danakService.id);
|
||||||
|
|
||||||
|
return { danakService, averageRating };
|
||||||
|
}
|
||||||
|
/******************************************** */
|
||||||
|
|
||||||
async getServiceUsers(serviceId: string) {
|
async getServiceUsers(serviceId: string) {
|
||||||
await this.findServiceById(serviceId);
|
await this.findServiceById(serviceId);
|
||||||
|
|||||||
@@ -135,6 +135,52 @@ export class DanakServicesRepository extends Repository<DanakService> {
|
|||||||
return serviceQueryBuilder.getOne();
|
return serviceQueryBuilder.getOne();
|
||||||
}
|
}
|
||||||
//+********************
|
//+********************
|
||||||
|
async getServiceBySlug(slug: string, isAdmin: boolean) {
|
||||||
|
const serviceQueryBuilder = this.createQueryBuilder("service")
|
||||||
|
.where("service.deletedAt IS NULL")
|
||||||
|
.leftJoin("service.category", "category")
|
||||||
|
.addSelect(["category.id", "category.title"])
|
||||||
|
.leftJoinAndSelect("service.images", "images")
|
||||||
|
.leftJoinAndSelect("service.subscriptionPlans", "subscriptionPlans")
|
||||||
|
.leftJoinAndSelect("subscriptionPlans.directDiscount", "directDiscount", "directDiscount.id IS NOT NULL")
|
||||||
|
.leftJoin("service.reviews", "reviews", "reviews.status = :reviewStatus", { reviewStatus: ReviewStatus.APPROVED })
|
||||||
|
.leftJoin("reviews.user", "user")
|
||||||
|
.addSelect([
|
||||||
|
"reviews.id",
|
||||||
|
"reviews.comment",
|
||||||
|
"reviews.rating",
|
||||||
|
"reviews.title",
|
||||||
|
"reviews.createdAt",
|
||||||
|
"reviews.status",
|
||||||
|
"user.id",
|
||||||
|
"user.firstName",
|
||||||
|
"user.lastName",
|
||||||
|
"user.profilePic",
|
||||||
|
])
|
||||||
|
// .loadRelationCountAndMap("service.reviewCount", "service.reviews")
|
||||||
|
// .addSelect(
|
||||||
|
// (subQuery) =>
|
||||||
|
// subQuery
|
||||||
|
// .select("CAST(AVG(rating) AS DECIMAL(10,2))", "averageRating")
|
||||||
|
// .from(DanakServiceReview, "r")
|
||||||
|
// .where("r.serviceId = service.id")
|
||||||
|
// .andWhere("r.status = :reviewStatus", { reviewStatus: ReviewStatus.APPROVED }),
|
||||||
|
// "averageRating",
|
||||||
|
// )
|
||||||
|
.andWhere("service.slug = :slug", { slug })
|
||||||
|
.groupBy("service.id,category.id, images.id, subscriptionPlans.id, reviews.id, user.id, directDiscount.id");
|
||||||
|
|
||||||
|
if (!isAdmin) {
|
||||||
|
serviceQueryBuilder
|
||||||
|
.andWhere("service.isActive = :isActive", { isActive: true })
|
||||||
|
.andWhere("subscriptionPlans.isActive = :planActive", { planActive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceQueryBuilder.orderBy("subscriptionPlans.price", "ASC");
|
||||||
|
|
||||||
|
return serviceQueryBuilder.getOne();
|
||||||
|
}
|
||||||
|
//+********************
|
||||||
async getUsersByService(serviceId: string) {
|
async getUsersByService(serviceId: string) {
|
||||||
const users = await this.createQueryBuilder("service")
|
const users = await this.createQueryBuilder("service")
|
||||||
.innerJoin("service.subscriptionPlans", "subscriptionPlans")
|
.innerJoin("service.subscriptionPlans", "subscriptionPlans")
|
||||||
|
|||||||
Reference in New Issue
Block a user