update: the danak services module and add new route to fetch the danak service
This commit is contained in:
Executable → Regular
+142
-130
@@ -1,182 +1,194 @@
|
||||
// import { randomBytes } from "node:crypto";
|
||||
|
||||
// import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common";
|
||||
// import { In } from "typeorm";
|
||||
// // eslint-disable-next-line import/no-named-as-default
|
||||
// import Decimal from "decimal.js";
|
||||
|
||||
// import { CommonMessage, DiscountMessage, SubscriptionMessage, UserMessage } from "../../../common/enums/message.enum";
|
||||
// import { SubscriptionsPlanRepository } from "../../subscriptions/repositories/subscriptions.repository";
|
||||
// import { UserRepository } from "../../users/repositories/users.repository";
|
||||
// import { PaginationUtils } from "../../utils/providers/pagination.utils";
|
||||
// import { User } from "../../users/entities/user.entity";
|
||||
// import { CreateDiscountDto } from "../DTO/create-discount.dto";
|
||||
// import { SearchDiscountsDto } from "../DTO/discount-search-query.dto";
|
||||
// import { DiscountRepository } from "../repositories/discount.repository";
|
||||
// import { UpdateDiscountDto } from "../DTO/update-discount.dto";
|
||||
// import { Discount } from "../entities/discount.entity";
|
||||
// import { DiscountType } from "../enums/discount-type.enum";
|
||||
// import { DiscountServicesRepository } from "../repositories/discount-services.repository";
|
||||
// import { DiscountRepository } from "../repositories/discounts.repository";
|
||||
// import { UsageDiscountRepository } from "../repositories/usage-discounts.repository";
|
||||
|
||||
// @Injectable()
|
||||
// export class DiscountService {
|
||||
// export class DiscountsService {
|
||||
// constructor(
|
||||
// private readonly discountRepository: DiscountRepository,
|
||||
// private readonly subscriptionPlanRepository: SubscriptionsPlanRepository,
|
||||
// private readonly userRepository: UserRepository,
|
||||
// private readonly discountServicesRepository: DiscountServicesRepository,
|
||||
// private readonly usageDiscountRepository: UsageDiscountRepository,
|
||||
// ) {}
|
||||
|
||||
// /******************************************** */
|
||||
|
||||
// async create(createDiscountDto: CreateDiscountDto) {
|
||||
// const { subscriptionPlanIds, ...discountData } = createDiscountDto;
|
||||
// const existingDiscount = await this.discountRepository.findByCode(createDiscountDto.title);
|
||||
// if (existingDiscount) {
|
||||
// throw new BadRequestException(DISCOUNT_ERROR_MESSAGES.ALREADY_EXISTS);
|
||||
// }
|
||||
|
||||
// const code = await this.generateUniqueCouponCode();
|
||||
// // Create the discount without product relations
|
||||
// const { targetProducts, ...discountData } = createDiscountDto;
|
||||
|
||||
// const discount = this.discountRepository.create({
|
||||
// const discount = await this.discountRepository.create({
|
||||
// ...discountData,
|
||||
// code,
|
||||
// startDate: new Date(createDiscountDto.startDate),
|
||||
// endDate: new Date(createDiscountDto.endDate),
|
||||
// status: createDiscountDto.status || DiscountStatus.ACTIVE,
|
||||
// isActive: createDiscountDto.isActive !== undefined ? createDiscountDto.isActive : true,
|
||||
// });
|
||||
|
||||
// if (createDiscountDto.subscriptionPlanIds && createDiscountDto.subscriptionPlanIds.length) {
|
||||
// const subscriptionPlans = await this.subscriptionPlanRepository.find({
|
||||
// where: { id: In(createDiscountDto.subscriptionPlanIds) },
|
||||
// });
|
||||
|
||||
// if (subscriptionPlans.length !== createDiscountDto.subscriptionPlanIds.length) {
|
||||
// throw new NotFoundException(SubscriptionMessage.NOT_FOUND);
|
||||
// }
|
||||
|
||||
// discount.subscriptionPlans = subscriptionPlans;
|
||||
// // Add product relations if provided
|
||||
// if (targetProducts && targetProducts.length > 0) {
|
||||
// await this.discountServicesRepository.createMany(discount.id, targetProducts);
|
||||
// }
|
||||
|
||||
// if (createDiscountDto.userIds) {
|
||||
// const users = await this.userRepository.find({ where: { id: In(createDiscountDto.userIds) } });
|
||||
|
||||
// if (users.length !== createDiscountDto.userIds.length) {
|
||||
// throw new NotFoundException(UserMessage.USER_NOT_FOUND);
|
||||
// }
|
||||
|
||||
// discount.users = users;
|
||||
// // Fetch the complete discount with relations
|
||||
// const fullDiscount = await this.discountRepository.findById(discount.id);
|
||||
// if (!fullDiscount) {
|
||||
// throw new NotFoundException(DISCOUNT_ERROR_MESSAGES.NOT_FOUND);
|
||||
// }
|
||||
|
||||
// await this.discountRepository.save(discount);
|
||||
|
||||
// return {
|
||||
// message: CommonMessage.CREATED,
|
||||
// discount,
|
||||
// };
|
||||
// return fullDiscount;
|
||||
// }
|
||||
|
||||
// /******************************************** */
|
||||
// async findAll(options?: any): Promise<[Discount[], number]> {
|
||||
// return this.discountRepository.findAll(options);
|
||||
// }
|
||||
|
||||
// async findByCode(code: string) {
|
||||
// const discount = await this.discountRepository.findOne({
|
||||
// where: { code, isActive: true },
|
||||
// relations: ["subscriptionPlans"],
|
||||
// });
|
||||
// async findById(id: string): Promise<Discount> {
|
||||
// const discount = await this.discountRepository.findById(id);
|
||||
// if (!discount) {
|
||||
// throw new NotFoundException(DiscountMessage.NOT_FOUND);
|
||||
// throw new NotFoundException(DISCOUNT_ERROR_MESSAGES.NOT_FOUND);
|
||||
// }
|
||||
// return { discount };
|
||||
// return discount;
|
||||
// }
|
||||
|
||||
// /******************************************** */
|
||||
// async update(id: string, updateDiscountDto: UpdateDiscountDto): Promise<Discount> {
|
||||
// // Validate discount exists
|
||||
// await this.findById(id);
|
||||
|
||||
// async findDiscountsByUser(queryDto: SearchDiscountsDto, userId: string) {
|
||||
// const user = await this.userRepository.findOneBy({
|
||||
// id: userId,
|
||||
// });
|
||||
// if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
|
||||
// // Handle product relations separately
|
||||
// const { targetProducts, startDate: startDateStr, endDate: endDateStr, ...otherFields } = updateDiscountDto;
|
||||
|
||||
// const { limit, skip } = PaginationUtils(queryDto);
|
||||
// // Initialize update data with other fields
|
||||
// const updateData: Partial<Discount> = { ...otherFields };
|
||||
|
||||
// const queryBuilder = this.discountRepository.createQueryBuilder("discount");
|
||||
|
||||
// queryBuilder
|
||||
// .leftJoin("discount.users", "user")
|
||||
// .where("user.id = :userId", { userId: user.id })
|
||||
// .leftJoinAndSelect("discount.subscriptionPlans", "subscriptionPlans")
|
||||
// .leftJoin("subscriptionPlans.service", "service")
|
||||
// .addSelect(["service.id", "service.name", "service.title", "service.link", "service.icon", "service.description"]);
|
||||
|
||||
// if (queryDto.q) {
|
||||
// queryBuilder.andWhere("discount.code ILIKE :q", { q: `%${queryDto.q}%` });
|
||||
// // Add date fields if they exist
|
||||
// if (startDateStr) {
|
||||
// updateData.startDate = new Date(startDateStr);
|
||||
// }
|
||||
|
||||
// queryBuilder.orderBy("discount.createdAt", "DESC").skip(skip).take(limit);
|
||||
|
||||
// const [discounts, count] = await queryBuilder.getManyAndCount();
|
||||
|
||||
// return {
|
||||
// discounts,
|
||||
// count,
|
||||
// paginate: true,
|
||||
// };
|
||||
// }
|
||||
|
||||
// /******************************************** */
|
||||
|
||||
// async findAll(queryDto: SearchDiscountsDto) {
|
||||
// const { limit, skip } = PaginationUtils(queryDto);
|
||||
|
||||
// const queryBuilder = this.discountRepository.createQueryBuilder("discount");
|
||||
|
||||
// queryBuilder
|
||||
// .leftJoinAndSelect("discount.subscriptionPlans", "subscriptionPlans")
|
||||
// .leftJoin("subscriptionPlans.service", "service")
|
||||
// .addSelect(["service.id", "service.name", "service.title", "service.link", "service.icon", "service.description"])
|
||||
// .leftJoinAndSelect("discount.users", "users");
|
||||
|
||||
// if (queryDto.q) {
|
||||
// queryBuilder.andWhere("discount.code ILIKE :q", { q: `%${queryDto.q}%` });
|
||||
// if (endDateStr) {
|
||||
// updateData.endDate = new Date(endDateStr);
|
||||
// }
|
||||
|
||||
// queryBuilder.orderBy("discount.createdAt", "DESC").skip(skip).take(limit);
|
||||
// // Update the discount entity
|
||||
// const updatedDiscount = await this.discountRepository.update(id, updateData);
|
||||
// if (!updatedDiscount) {
|
||||
// throw new NotFoundException(DISCOUNT_ERROR_MESSAGES.NOT_FOUND);
|
||||
// }
|
||||
|
||||
// const [discounts, count] = await queryBuilder.getManyAndCount();
|
||||
// // Handle product relations if provided
|
||||
// if (targetProducts !== undefined) {
|
||||
// // Remove existing relations
|
||||
// await this.discountServicesRepository.deleteByDiscountId(id);
|
||||
|
||||
// return {
|
||||
// discounts,
|
||||
// count,
|
||||
// paginate: true,
|
||||
// };
|
||||
// // Add new relations if not empty
|
||||
// if (targetProducts.length > 0) {
|
||||
// await this.discountServicesRepository.createMany(id, targetProducts);
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Return the updated discount with relations
|
||||
// return this.findById(id);
|
||||
// }
|
||||
|
||||
// /******************************************** */
|
||||
|
||||
// async findOne(id: string) {
|
||||
// const discount = await this.discountRepository.findOne({
|
||||
// where: { id },
|
||||
// relations: ["subscriptionPlans"],
|
||||
// });
|
||||
// if (!discount) throw new BadRequestException(DiscountMessage.NOT_FOUND);
|
||||
// return { discount };
|
||||
// async delete(id: string): Promise<void> {
|
||||
// const discount = await this.findById(id);
|
||||
// await this.discountRepository.delete(discount.id);
|
||||
// }
|
||||
|
||||
// /******************************************** */
|
||||
// async toggleActive(id: string, isActive: boolean): Promise<Discount> {
|
||||
// await this.findById(id);
|
||||
// const updatedDiscount = await this.discountRepository.update(id, { isActive });
|
||||
// if (!updatedDiscount) {
|
||||
// throw new NotFoundException(DISCOUNT_ERROR_MESSAGES.NOT_FOUND);
|
||||
// }
|
||||
// return updatedDiscount;
|
||||
// }
|
||||
|
||||
// async validateDiscount(code: string, user: User, productId?: string): Promise<Discount> {
|
||||
// const discount = await this.discountRepository.findValidByCode(code);
|
||||
|
||||
// async toggleActive(id: string) {
|
||||
// const discount = await this.discountRepository.findOne({ where: { id } });
|
||||
// if (!discount) {
|
||||
// throw new BadRequestException(DiscountMessage.NOT_FOUND);
|
||||
// throw new BadRequestException(DISCOUNT_ERROR_MESSAGES.INVALID);
|
||||
// }
|
||||
|
||||
// discount.isActive = !discount.isActive;
|
||||
// // Check if user has already used this discount
|
||||
// const usageCount = await this.usageDiscountRepository.countByUserAndDiscount(user.id, discount.id);
|
||||
// if (usageCount > 0) {
|
||||
// throw new BadRequestException(DISCOUNT_ERROR_MESSAGES.ALREADY_USED);
|
||||
// }
|
||||
|
||||
// const updatedDiscount = await this.discountRepository.save(discount);
|
||||
// // Check if product is valid for this discount
|
||||
// if (productId && discount.discountServices && discount.discountServices.length > 0) {
|
||||
// const hasProduct = await this.discountServicesRepository.hasProductForDiscount(discount.id, productId);
|
||||
// if (!hasProduct) {
|
||||
// throw new BadRequestException(DISCOUNT_ERROR_MESSAGES.INVALID_PRODUCT);
|
||||
// }
|
||||
// }
|
||||
|
||||
// return {
|
||||
// message: CommonMessage.UPDATE_SUCCESS,
|
||||
// updatedDiscount,
|
||||
// };
|
||||
// return discount;
|
||||
// }
|
||||
|
||||
// /******************************************** */
|
||||
// async applyDiscount(amount: number, discountId: string, productId?: string): Promise<number> {
|
||||
// const discount = await this.findById(discountId);
|
||||
|
||||
// async generateUniqueCouponCode(): Promise<string> {
|
||||
// const code = this.generateCouponCode();
|
||||
// const exists = await this.discountRepository.findOne({ where: { code } });
|
||||
// if (exists) return this.generateUniqueCouponCode();
|
||||
// return code;
|
||||
// if (!discount.isValid) {
|
||||
// throw new BadRequestException(DISCOUNT_ERROR_MESSAGES.INVALID);
|
||||
// }
|
||||
|
||||
// // Check if product is valid for this discount
|
||||
// if (productId && discount.discountServices && discount.discountServices.length > 0) {
|
||||
// const hasProduct = await this.discountServicesRepository.hasProductForDiscount(discount.id, productId);
|
||||
// if (!hasProduct) {
|
||||
// throw new BadRequestException(DISCOUNT_ERROR_MESSAGES.INVALID_PRODUCT);
|
||||
// }
|
||||
// }
|
||||
|
||||
// let discountAmount = 0;
|
||||
|
||||
// if (discount.type === DiscountType.PERCENTAGE) {
|
||||
// discountAmount = (amount * discount.value) / 100;
|
||||
// } else if (discount.type === DiscountType.FIXED_AMOUNT) {
|
||||
// discountAmount = discount.value;
|
||||
// }
|
||||
|
||||
// // Ensure discount doesn't exceed the original amount
|
||||
// if (discountAmount > amount) {
|
||||
// discountAmount = amount;
|
||||
// }
|
||||
|
||||
// return discountAmount;
|
||||
// }
|
||||
|
||||
// /******************************************** */
|
||||
// async recordDiscountUsage(userId: string, discountId: string, appliedAmount: number): Promise<void> {
|
||||
// const discount = await this.findById(discountId);
|
||||
|
||||
// private generateCouponCode(length = 8) {
|
||||
// return randomBytes(length).toString("hex").slice(0, length).toUpperCase();
|
||||
// // Increment usage count
|
||||
// await this.discountRepository.update(discount.id, {
|
||||
// usedCount: discount.usedCount + 1,
|
||||
// });
|
||||
|
||||
// // Record usage
|
||||
// await this.usageDiscountRepository.create({
|
||||
// user: { id: userId } as User,
|
||||
// discount: { id: discountId } as Discount,
|
||||
// appliedAmount: new Decimal(appliedAmount),
|
||||
// usedAt: new Date(),
|
||||
// });
|
||||
// }
|
||||
|
||||
// async getProductsForDiscount(discountId: string): Promise<string[]> {
|
||||
// const discountServices = await this.discountServicesRepository.findByDiscountId(discountId);
|
||||
// return discountServices.map((service) => service.danakService.id);
|
||||
// }
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user