refactor: the discount servicer
This commit is contained in:
@@ -67,4 +67,10 @@ export class DiscountsController {
|
|||||||
updateDiscount(@Param() paramDto: ParamDto, @Body() updateDiscountDto: UpdateDiscountDto) {
|
updateDiscount(@Param() paramDto: ParamDto, @Body() updateDiscountDto: UpdateDiscountDto) {
|
||||||
return this.discountsService.updateDiscount(paramDto.id, 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 };
|
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
|
* 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
|
* Soft delete a discount
|
||||||
*/
|
*/
|
||||||
async softDeleteDiscount(id: string) {
|
async softDeleteDiscount(id: string) {
|
||||||
await this.discountRepository.softDeleteDiscount(id);
|
const queryRunner = this.dataSource.createQueryRunner();
|
||||||
|
try {
|
||||||
|
await queryRunner.connect();
|
||||||
|
await queryRunner.startTransaction();
|
||||||
|
|
||||||
|
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 {
|
return {
|
||||||
message: CommonMessage.DELETED,
|
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 { PaginationUtils } from "../../utils/providers/pagination.utils";
|
||||||
import { SearchDiscountQueryDto } from "../DTO/search-discount-query.dto";
|
import { SearchDiscountQueryDto } from "../DTO/search-discount-query.dto";
|
||||||
import { Discount } from "../entities/discount.entity";
|
import { Discount } from "../entities/discount.entity";
|
||||||
|
import { DiscountApplicationType } from "../enums/discount-application-type.enum";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DiscountRepository extends Repository<Discount> {
|
export class DiscountRepository extends Repository<Discount> {
|
||||||
@@ -61,50 +62,19 @@ export class DiscountRepository extends Repository<Discount> {
|
|||||||
return this.softDelete(id);
|
return this.softDelete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async findDiscountWithDistinctServicesForClient(id: string) {
|
async findDiscountForUser(queryDto: SearchDiscountQueryDto) {
|
||||||
// First, get the basic discount information
|
const { limit, skip } = PaginationUtils(queryDto);
|
||||||
const discount = await this.findOne({
|
|
||||||
where: { id, isActive: true },
|
|
||||||
withDeleted: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!discount) return null;
|
|
||||||
|
|
||||||
// Get subscription plans with their services
|
|
||||||
const queryBuilder = this.createQueryBuilder("discount")
|
const queryBuilder = this.createQueryBuilder("discount")
|
||||||
.leftJoinAndSelect("discount.subscriptionPlans", "plans")
|
.where("discount.deletedAt IS NULL")
|
||||||
.leftJoinAndSelect("plans.service", "service")
|
.andWhere("discount.isActive = true")
|
||||||
.where("discount.id = :id", { id })
|
.andWhere("discount.startDate <= :now", { now: new Date() })
|
||||||
.andWhere("discount.isActive = :isActive", { isActive: true });
|
.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
|
return queryBuilder.skip(skip).take(limit).orderBy("discount.createdAt", "DESC").getManyAndCount();
|
||||||
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,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,18 +104,15 @@ export class SubscriptionsService {
|
|||||||
}
|
}
|
||||||
//************************************ */
|
//************************************ */
|
||||||
async updateSubscriptionPlan(id: string, updateDto: UpdateSubscriptionPlanDto) {
|
async updateSubscriptionPlan(id: string, updateDto: UpdateSubscriptionPlanDto) {
|
||||||
// Find the existing subscription plan
|
|
||||||
const subscription = await this.subscriptionsPlanRepository.findOne({ where: { id }, relations: { service: true } });
|
const subscription = await this.subscriptionsPlanRepository.findOne({ where: { id }, relations: { service: true } });
|
||||||
if (!subscription) throw new BadRequestException(SubscriptionMessage.NOT_FOUND);
|
if (!subscription) throw new BadRequestException(SubscriptionMessage.NOT_FOUND);
|
||||||
|
|
||||||
// Check if service exists when trying to update it
|
|
||||||
if (updateDto.serviceId) {
|
if (updateDto.serviceId) {
|
||||||
const danakService = await this.danakServices.findServiceById(updateDto.serviceId);
|
const danakService = await this.danakServices.findServiceById(updateDto.serviceId);
|
||||||
if (!danakService) throw new BadRequestException(ServiceMessage.SERVICE_NOT_FOUND_BY_ID);
|
if (!danakService) throw new BadRequestException(ServiceMessage.SERVICE_NOT_FOUND_BY_ID);
|
||||||
subscription.service = danakService;
|
subscription.service = danakService;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for name uniqueness if updating name
|
|
||||||
if (updateDto.name) {
|
if (updateDto.name) {
|
||||||
const existSubscription = await this.subscriptionsPlanRepository.findOneBy({
|
const existSubscription = await this.subscriptionsPlanRepository.findOneBy({
|
||||||
name: updateDto.name,
|
name: updateDto.name,
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ export class SubscriptionsController {
|
|||||||
|
|
||||||
@ApiOperation({ summary: "update a subscription plan by id" })
|
@ApiOperation({ summary: "update a subscription plan by id" })
|
||||||
@Patch(":id")
|
@Patch(":id")
|
||||||
//TODO:fix this if needed
|
|
||||||
@PermissionsDec(PermissionEnum.SERVICES)
|
@PermissionsDec(PermissionEnum.SERVICES)
|
||||||
updateSubscription(@Param() paramDto: ParamDto, @Body() updateDto: UpdateSubscriptionPlanDto) {
|
updateSubscription(@Param() paramDto: ParamDto, @Body() updateDto: UpdateSubscriptionPlanDto) {
|
||||||
return this.subscriptionService.updateSubscriptionPlan(paramDto.id, updateDto);
|
return this.subscriptionService.updateSubscriptionPlan(paramDto.id, updateDto);
|
||||||
|
|||||||
Reference in New Issue
Block a user