126 lines
4.5 KiB
TypeScript
Executable File
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");
|
|
}
|
|
}
|