250 lines
9.6 KiB
TypeScript
Executable File
250 lines
9.6 KiB
TypeScript
Executable File
import { Injectable } from "@nestjs/common";
|
|
import { InjectRepository } from "@nestjs/typeorm";
|
|
import { Brackets, IsNull, Not, Repository } from "typeorm";
|
|
|
|
import { SubscriptionStatus } from "../../subscriptions/enums/subscription-status.enum";
|
|
import { PaginationUtils } from "../../utils/providers/pagination.utils";
|
|
import { DanakServicesGlobalSearchDto, DanakServicesQueryDto, DanakServicesSearchQueryDto } from "../DTO/danak-services-search-query.dto";
|
|
import { DanakService } from "../entities/danak-service.entity";
|
|
import { ReviewStatus } from "../enums/review-status.enum";
|
|
|
|
@Injectable()
|
|
export class DanakServicesRepository extends Repository<DanakService> {
|
|
constructor(@InjectRepository(DanakService) danakServicesRepository: Repository<DanakService>) {
|
|
super(danakServicesRepository.target, danakServicesRepository.manager, danakServicesRepository.queryRunner);
|
|
}
|
|
|
|
async findOneByName(name: string, id?: string): Promise<DanakService | null> {
|
|
return this.findOneBy({ name, deletedAt: IsNull(), ...(id && { id: Not(id) }) });
|
|
}
|
|
|
|
async findServiceById(id: string): Promise<DanakService | null> {
|
|
return this.findOneBy({ id, deletedAt: IsNull() });
|
|
}
|
|
//+********************
|
|
async getServicesForAdmin(queryDto: DanakServicesSearchQueryDto) {
|
|
const { limit, skip } = PaginationUtils(queryDto);
|
|
|
|
const queryBuilder = this.createQueryBuilder("service")
|
|
.leftJoinAndSelect("service.category", "category")
|
|
.loadRelationCountAndMap("service.subscriptionCount", "service.subscriptionPlans")
|
|
.orderBy("service.createdAt", "DESC")
|
|
.where("service.deletedAt IS NULL")
|
|
.skip(skip)
|
|
.take(limit);
|
|
|
|
if (queryDto.isActive) {
|
|
queryBuilder.andWhere("service.isActive = :isActive", { isActive: queryDto.isActive === 1 });
|
|
}
|
|
|
|
if (queryDto.isDanakSuggest) {
|
|
queryBuilder.andWhere("service.isDanakSuggest = :isDanakSuggest", { isDanakSuggest: queryDto.isDanakSuggest === 1 });
|
|
}
|
|
|
|
if (queryDto.categoryId) {
|
|
queryBuilder.andWhere("service.categoryId = :categoryId", { categoryId: queryDto.categoryId });
|
|
}
|
|
|
|
if (queryDto.q) {
|
|
queryBuilder.andWhere(
|
|
new Brackets((qb) => {
|
|
qb.where("service.name LIKE :q", { q: `%${queryDto.q}%` })
|
|
.orWhere("service.description LIKE :q", { q: `%${queryDto.q}%` })
|
|
.orWhere("service.softwareLanguage LIKE :q", { q: `%${queryDto.q}%` })
|
|
.orWhere("service.author LIKE :q", { q: `%${queryDto.q}%` });
|
|
}),
|
|
);
|
|
}
|
|
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.deletedAt IS NULL")
|
|
// .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,
|
|
};
|
|
}
|
|
//+********************
|
|
async getDanakServiceById(serviceId: 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.id = :serviceId", { serviceId })
|
|
.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 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) {
|
|
const users = await this.createQueryBuilder("service")
|
|
.innerJoin("service.subscriptionPlans", "subscriptionPlans")
|
|
.innerJoin("subscriptionPlans.userSubscriptions", "userSubscriptions")
|
|
.innerJoin("user", "user", "userSubscriptions.userId = user.id")
|
|
.select([
|
|
"DISTINCT user.id AS id",
|
|
"user.firstName AS firstName",
|
|
"user.lastName AS lastName",
|
|
"user.email AS email",
|
|
"user.profilePic AS profilePic",
|
|
])
|
|
.where("service.id = :serviceId", { serviceId })
|
|
.andWhere("userSubscriptions.status = :status", { status: SubscriptionStatus.ACTIVE })
|
|
.andWhere("userSubscriptions.endDate > NOW()")
|
|
.getRawMany();
|
|
|
|
return users;
|
|
}
|
|
|
|
async getDanakSuggestServices() {
|
|
return this.find({
|
|
where: { isDanakSuggest: true, isActive: true, deletedAt: IsNull(), category: { isActive: true, deletedAt: IsNull() } },
|
|
relations: { category: true },
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
title: true,
|
|
description: true,
|
|
slug: true,
|
|
coverUrl: true,
|
|
userCount: true,
|
|
createDate: true,
|
|
icon: true,
|
|
createdAt: true,
|
|
isActive: true,
|
|
isDanakSuggest: true,
|
|
metaDescription: true,
|
|
category: {
|
|
id: true,
|
|
title: true,
|
|
},
|
|
},
|
|
order: { createdAt: "DESC" },
|
|
withDeleted: false,
|
|
});
|
|
}
|
|
|
|
async searchServices(queryDto: DanakServicesGlobalSearchDto) {
|
|
const servicesQuery = this.createQueryBuilder("service")
|
|
.leftJoin("service.category", "category")
|
|
.leftJoin("service.subscriptionPlans", "subscriptionPlans")
|
|
.select(["service.id", "service.name", "service.description", "service.icon", "category.id", "category.title"])
|
|
.where("service.isActive = :isActive", { isActive: true })
|
|
.andWhere("service.deletedAt IS NULL")
|
|
.andWhere("category.isActive = :categoryActive", { categoryActive: true })
|
|
.andWhere("category.deletedAt IS NULL")
|
|
.andWhere("subscriptionPlans.isActive = :planActive", { planActive: true });
|
|
|
|
if (queryDto.q) {
|
|
servicesQuery.andWhere("service.name ILIKE :searchQuery", { searchQuery: `%${queryDto.q}%` });
|
|
}
|
|
|
|
return servicesQuery.getMany();
|
|
}
|
|
}
|