diff --git a/src/modules/discounts/discounts.controller.ts b/src/modules/discounts/discounts.controller.ts index 7ab635b..6fd7850 100755 --- a/src/modules/discounts/discounts.controller.ts +++ b/src/modules/discounts/discounts.controller.ts @@ -67,4 +67,10 @@ export class DiscountsController { updateDiscount(@Param() paramDto: ParamDto, @Body() updateDiscountDto: UpdateDiscountDto) { return this.discountsService.updateDiscount(paramDto.id, updateDiscountDto); } + + @ApiOperation({ summary: "Get discount list for user" }) + @Get("user") + getDiscountListForUser(@Query() queryDto: SearchDiscountQueryDto) { + return this.discountsService.getDiscountListForUser(queryDto); + } } diff --git a/src/modules/discounts/providers/discounts.service.ts b/src/modules/discounts/providers/discounts.service.ts index a18ecfa..01db945 100755 --- a/src/modules/discounts/providers/discounts.service.ts +++ b/src/modules/discounts/providers/discounts.service.ts @@ -86,16 +86,6 @@ export class DiscountsService { return { discount }; } - /** - * Get a discount with distinct services for client - */ - async getDiscountWithDistinctServicesForClient(id: string) { - const discount = await this.discountRepository.findDiscountWithDistinctServicesForClient(id); - if (!discount) throw new BadRequestException(DiscountMessage.NOT_FOUND); - - return { discount }; - } - /** * Toggle discount active status */ @@ -177,15 +167,42 @@ export class DiscountsService { } } + async getDiscountListForUser(queryDto: SearchDiscountQueryDto) { + const [discounts, count] = await this.discountRepository.findDiscountForUser(queryDto); + + return { + discounts, + count, + }; + } /** * Soft delete a discount */ async softDeleteDiscount(id: string) { - await this.discountRepository.softDeleteDiscount(id); + const queryRunner = this.dataSource.createQueryRunner(); + try { + await queryRunner.connect(); + await queryRunner.startTransaction(); - return { - message: CommonMessage.DELETED, - }; + const discount = await this.discountRepository.findById(id); + if (!discount) throw new BadRequestException(DiscountMessage.NOT_FOUND); + + await this.removeDiscountDeactivationJob(id); + await this.clearDirectDiscountFromPlans(discount, queryRunner); + + await queryRunner.manager.softDelete(this.discountRepository.target, discount); + + await queryRunner.commitTransaction(); + + return { + message: CommonMessage.DELETED, + }; + } catch (error) { + await queryRunner.rollbackTransaction(); + throw error; + } finally { + await queryRunner.release(); + } } /** diff --git a/src/modules/discounts/repositories/discounts.repository.ts b/src/modules/discounts/repositories/discounts.repository.ts index 5726109..11687b0 100755 --- a/src/modules/discounts/repositories/discounts.repository.ts +++ b/src/modules/discounts/repositories/discounts.repository.ts @@ -5,6 +5,7 @@ import { Repository } from "typeorm"; import { PaginationUtils } from "../../utils/providers/pagination.utils"; import { SearchDiscountQueryDto } from "../DTO/search-discount-query.dto"; import { Discount } from "../entities/discount.entity"; +import { DiscountApplicationType } from "../enums/discount-application-type.enum"; @Injectable() export class DiscountRepository extends Repository { @@ -61,50 +62,19 @@ export class DiscountRepository extends Repository { return this.softDelete(id); } - async findDiscountWithDistinctServicesForClient(id: string) { - // First, get the basic discount information - const discount = await this.findOne({ - where: { id, isActive: true }, - withDeleted: false, - }); - - if (!discount) return null; - - // Get subscription plans with their services + async findDiscountForUser(queryDto: SearchDiscountQueryDto) { + const { limit, skip } = PaginationUtils(queryDto); const queryBuilder = this.createQueryBuilder("discount") - .leftJoinAndSelect("discount.subscriptionPlans", "plans") - .leftJoinAndSelect("plans.service", "service") - .where("discount.id = :id", { id }) - .andWhere("discount.isActive = :isActive", { isActive: true }); + .where("discount.deletedAt IS NULL") + .andWhere("discount.isActive = true") + .andWhere("discount.startDate <= :now", { now: new Date() }) + .andWhere("discount.endDate >= :now", { now: new Date() }) + .andWhere("discount.type = :type", { type: DiscountApplicationType.CODE_BASED }); - const discountWithPlans = await queryBuilder.getOne(); + if (queryDto.q) { + queryBuilder.andWhere("discount.title ILIKE :query", { query: `%${queryDto.q}%` }); + } - // Get distinct services using raw SQL - const distinctServicesQuery = this.manager.query( - ` - SELECT DISTINCT ON (service.id) - service.id, - service.name, - service.description, - service.icon_url as "iconUrl", - service.is_active as "isActive" - FROM danak_service service - INNER JOIN subscription_plan plan ON plan.service_id = service.id - INNER JOIN discount_subscription_plans dsp ON dsp.subscription_plan_id = plan.id - WHERE dsp.discount_id = $1 - AND service.deleted_at IS NULL - AND service.is_active = true - `, - [id], - ); - - // Combine the results - const [distinctServices] = await Promise.all([distinctServicesQuery]); - - return { - ...discount, - subscriptionPlans: discountWithPlans?.subscriptionPlans || [], - distinctServices, - }; + return queryBuilder.skip(skip).take(limit).orderBy("discount.createdAt", "DESC").getManyAndCount(); } } diff --git a/src/modules/subscriptions/providers/subscriptions.service.ts b/src/modules/subscriptions/providers/subscriptions.service.ts index 4e5b9c1..235f5b3 100755 --- a/src/modules/subscriptions/providers/subscriptions.service.ts +++ b/src/modules/subscriptions/providers/subscriptions.service.ts @@ -104,18 +104,15 @@ export class SubscriptionsService { } //************************************ */ async updateSubscriptionPlan(id: string, updateDto: UpdateSubscriptionPlanDto) { - // Find the existing subscription plan const subscription = await this.subscriptionsPlanRepository.findOne({ where: { id }, relations: { service: true } }); if (!subscription) throw new BadRequestException(SubscriptionMessage.NOT_FOUND); - // Check if service exists when trying to update it if (updateDto.serviceId) { const danakService = await this.danakServices.findServiceById(updateDto.serviceId); if (!danakService) throw new BadRequestException(ServiceMessage.SERVICE_NOT_FOUND_BY_ID); subscription.service = danakService; } - // Check for name uniqueness if updating name if (updateDto.name) { const existSubscription = await this.subscriptionsPlanRepository.findOneBy({ name: updateDto.name, diff --git a/src/modules/subscriptions/subscriptions.controller.ts b/src/modules/subscriptions/subscriptions.controller.ts index 0164a94..d2fc5aa 100755 --- a/src/modules/subscriptions/subscriptions.controller.ts +++ b/src/modules/subscriptions/subscriptions.controller.ts @@ -65,7 +65,6 @@ export class SubscriptionsController { @ApiOperation({ summary: "update a subscription plan by id" }) @Patch(":id") - //TODO:fix this if needed @PermissionsDec(PermissionEnum.SERVICES) updateSubscription(@Param() paramDto: ParamDto, @Body() updateDto: UpdateSubscriptionPlanDto) { return this.subscriptionService.updateSubscriptionPlan(paramDto.id, updateDto);