chore: update referral logic

This commit is contained in:
mahyargdz
2025-04-15 15:50:31 +03:30
parent bd4d9dbf0d
commit fb8f16deb4
19 changed files with 234 additions and 262 deletions
@@ -3,13 +3,11 @@ import { randomBytes } from "node:crypto";
import { BadRequestException, Injectable } from "@nestjs/common";
// eslint-disable-next-line import/no-named-as-default
import Decimal from "decimal.js";
import { DataSource, QueryRunner } from "typeorm";
import { QueryRunner } from "typeorm";
import { ReferralMessage, UserMessage } from "../../../common/enums/message.enum";
import { User } from "../../users/entities/user.entity";
import { WalletsService } from "../../wallets/providers/wallets.service";
import { UseReferralCodeDto } from "../DTO/use-referral-code.dto";
import { ReferralRewardStatus } from "../enums/referral-reward-status.enum";
import { ReferralStatus } from "../enums/referral-status.enum";
import { ReferralCodesRepository } from "../repositories/referral-codes.repository";
import { ReferralRewardsRepository } from "../repositories/referral-rewards.repository";
@@ -20,8 +18,6 @@ export class ReferralsService {
private readonly referralsRepository: ReferralsRepository,
private readonly referralCodesRepository: ReferralCodesRepository,
private readonly referralRewardsRepository: ReferralRewardsRepository,
private readonly walletsService: WalletsService,
private readonly dataSource: DataSource,
) {}
async generateReferralCode(userId: string, queryRunner: QueryRunner) {
@@ -54,75 +50,76 @@ export class ReferralsService {
}
//*********************************** */
async useReferralCode(dto: UseReferralCodeDto) {
const queryRunner = this.dataSource.createQueryRunner();
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);
try {
await queryRunner.connect();
await queryRunner.startTransaction();
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 referredUser = await queryRunner.manager.findOne(User, { where: { id: dto.userId } });
if (!referredUser) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
const existingReferral = await queryRunner.manager.findOne(this.referralsRepository.target, {
where: { referredUser: { id: referredUser.id } },
});
if (existingReferral) throw new BadRequestException(ReferralMessage.USER_ALREADY_REFERRED);
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 referral = queryRunner.manager.create(this.referralsRepository.target, {
referrer: { id: referralCode.user.id },
referredUser: { id: referredUser.id },
referralCode: { id: referralCode.id },
});
// Check if user has already been referred
const existingReferral = await queryRunner.manager.findOne(this.referralsRepository.target, {
where: { referredUser: { id: referredUser.id } },
});
if (existingReferral) throw new BadRequestException(ReferralMessage.USER_ALREADY_REFERRED);
await queryRunner.manager.save(referral);
// Create referral record
const referral = queryRunner.manager.create(this.referralsRepository.target, {
referrer: { id: referralCode.user.id },
referredUser: { id: referredUser.id },
referralCode: { id: referralCode.id },
status: ReferralStatus.PENDING,
});
referralCode.usedCount += 1;
await queryRunner.manager.save(referralCode);
await queryRunner.manager.save(referral);
// const reward = queryRunner.manager.create(this.referralRewardsRepository.target, {
// user: { id: referralCode.user.id },
// referral: { id: referral.id },
// });
// Increment usedCount
referralCode.usedCount += 1;
await queryRunner.manager.save(referralCode);
// await queryRunner.manager.save(reward);
// Create pending reward
const reward = queryRunner.manager.create(this.referralRewardsRepository.target, {
user: { id: referralCode.user.id },
referral: { id: referral.id },
amount: 100, // Set your reward amount here
status: ReferralRewardStatus.PENDING,
});
await queryRunner.manager.save(reward);
// Charge the referred user's wallet
const chargeAmount = new Decimal(100);
await this.walletsService.createReferralRewardTransaction(referredUser.id, chargeAmount, queryRunner);
// Update referral status to COMPLETED
referral.status = ReferralStatus.COMPLETED;
await queryRunner.manager.save(referral);
// Update reward status to PAID
reward.status = ReferralRewardStatus.PAID;
reward.paidAt = new Date();
await queryRunner.manager.save(reward);
await queryRunner.commitTransaction();
return { referral, reward };
} catch (error) {
await queryRunner.rollbackTransaction();
throw error;
} finally {
await queryRunner.release();
}
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");
}