refactor: the discount servicer

This commit is contained in:
mahyargdz
2025-04-22 15:02:26 +03:30
parent 3e87de6eae
commit 5883890e7f
5 changed files with 49 additions and 60 deletions
@@ -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);
}
}
@@ -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();
}
}
/**
@@ -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<Discount> {
@@ -61,50 +62,19 @@ export class DiscountRepository extends Repository<Discount> {
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();
}
}
@@ -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,
@@ -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);