Files
dsc-api/src/modules/referrals/providers/referrals.service.ts
T
2025-04-22 12:28:11 +03:30

126 lines
4.5 KiB
TypeScript
Executable File

import { randomBytes } from "node:crypto";
import { BadRequestException, Injectable } from "@nestjs/common";
import Decimal from "decimal.js";
import { QueryRunner } from "typeorm";
import { ReferralMessage, UserMessage } from "../../../common/enums/message.enum";
import { User } from "../../users/entities/user.entity";
import { UseReferralCodeDto } from "../DTO/use-referral-code.dto";
import { ReferralStatus } from "../enums/referral-status.enum";
import { ReferralCodesRepository } from "../repositories/referral-codes.repository";
import { ReferralRewardsRepository } from "../repositories/referral-rewards.repository";
import { ReferralsRepository } from "../repositories/referrals.repository";
@Injectable()
export class ReferralsService {
private MAX_ATTEMPTS = 10;
constructor(
private readonly referralsRepository: ReferralsRepository,
private readonly referralCodesRepository: ReferralCodesRepository,
private readonly referralRewardsRepository: ReferralRewardsRepository,
) {}
async generateReferralCode(userId: string, queryRunner: QueryRunner) {
const existReferralCode = await queryRunner.manager.findOneBy(this.referralCodesRepository.target, { user: { id: userId } });
if (existReferralCode) throw new BadRequestException(ReferralMessage.CODE_EXIST_FOR_USER);
let attempts = 0;
let code: string;
let existCode;
do {
if (attempts >= this.MAX_ATTEMPTS) {
throw new BadRequestException(ReferralMessage.CODE_GENERATION_FAILED);
}
code = this.generateRandomCode();
existCode = await queryRunner.manager.findOneBy(this.referralCodesRepository.target, { code });
attempts++;
} while (existCode);
const referralCode = queryRunner.manager.create(this.referralCodesRepository.target, {
code,
user: { id: userId },
});
await queryRunner.manager.save(referralCode);
return code;
}
//*********************************** */
async useReferralCode(dto: UseReferralCodeDto, queryRunner: QueryRunner) {
const referredUser = await queryRunner.manager.findOne(User, { where: { id: dto.userId } });
if (!referredUser) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
const referralCode = await queryRunner.manager.findOne(this.referralCodesRepository.target, {
where: { code: dto.referralCode, isActive: true },
relations: { user: true },
});
if (!referralCode || !referralCode.user) throw new BadRequestException(ReferralMessage.INVALID_OR_INACTIVE_REFERRAL_CODE);
const existingReferral = await queryRunner.manager.findOne(this.referralsRepository.target, {
where: { referredUser: { id: referredUser.id } },
});
if (existingReferral) throw new BadRequestException(ReferralMessage.USER_ALREADY_REFERRED);
const referral = queryRunner.manager.create(this.referralsRepository.target, {
referrer: { id: referralCode.user.id },
referredUser: { id: referredUser.id },
referralCode: { id: referralCode.id },
});
await queryRunner.manager.save(referral);
referralCode.usedCount += 1;
await queryRunner.manager.save(referralCode);
// const reward = queryRunner.manager.create(this.referralRewardsRepository.target, {
// user: { id: referralCode.user.id },
// referral: { id: referral.id },
// });
// await queryRunner.manager.save(reward);
return referral;
}
//*********************************** */
async getPendingReferral(userId: string, queryRunner: QueryRunner) {
return queryRunner.manager.findOne(this.referralsRepository.target, {
where: {
referredUser: { id: userId },
status: ReferralStatus.PENDING,
},
relations: { referrer: true },
});
}
//*********************************** */
async createReferral(userId: string, queryRunner: QueryRunner) {
const referral = queryRunner.manager.create(this.referralsRepository.target, {
referrer: { id: userId },
referredUser: { id: userId },
});
await queryRunner.manager.save(referral);
}
//*********************************** */
async createReferralReward(userId: string, referralId: string, amount: Decimal, queryRunner: QueryRunner) {
const reward = queryRunner.manager.create(this.referralRewardsRepository.target, {
user: { id: userId },
referral: { id: referralId },
amount,
});
await queryRunner.manager.save(reward);
return reward;
}
//*********************************** */
private generateRandomCode(): string {
return randomBytes(6).toString("hex");
}
}