michangarrito/apps/backend/dist/modules/referrals/referrals.service.js
rckrdmrd 97f407c661 [MIGRATION-V2] feat: Migrar michangarrito a estructura v2
- Prefijo v2: MCH
- TRACEABILITY-MASTER.yml creado
- Listo para integracion como submodulo

Workspace: v2.0.0 | SIMCO: v4.0.0
2026-01-10 11:28:54 -06:00

208 lines
8.6 KiB
JavaScript

"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ReferralsService = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("@nestjs/typeorm");
const typeorm_2 = require("typeorm");
const referral_code_entity_1 = require("./entities/referral-code.entity");
const referral_entity_1 = require("./entities/referral.entity");
const referral_reward_entity_1 = require("./entities/referral-reward.entity");
let ReferralsService = class ReferralsService {
constructor(codeRepo, referralRepo, rewardRepo, dataSource) {
this.codeRepo = codeRepo;
this.referralRepo = referralRepo;
this.rewardRepo = rewardRepo;
this.dataSource = dataSource;
}
async getMyCode(tenantId) {
let code = await this.codeRepo.findOne({ where: { tenantId } });
if (!code) {
code = await this.generateCode(tenantId);
}
return code;
}
async generateCode(tenantId) {
const existing = await this.codeRepo.findOne({ where: { tenantId } });
if (existing) {
return existing;
}
const result = await this.dataSource.query(`SELECT generate_referral_code('MCH') as code`);
const newCode = result[0].code;
const referralCode = this.codeRepo.create({
tenantId,
code: newCode,
active: true,
});
return this.codeRepo.save(referralCode);
}
async validateCode(code) {
const referralCode = await this.codeRepo.findOne({
where: { code: code.toUpperCase(), active: true },
});
if (!referralCode) {
throw new common_1.NotFoundException('Codigo de referido no valido o inactivo');
}
return referralCode;
}
async applyCode(referredTenantId, code) {
const referralCode = await this.validateCode(code);
if (referralCode.tenantId === referredTenantId) {
throw new common_1.BadRequestException('No puedes usar tu propio codigo de referido');
}
const existingReferral = await this.referralRepo.findOne({
where: { referredTenantId },
});
if (existingReferral) {
throw new common_1.ConflictException('Ya tienes un codigo de referido aplicado');
}
const expiresAt = new Date();
expiresAt.setDate(expiresAt.getDate() + 30);
const referral = this.referralRepo.create({
referrerTenantId: referralCode.tenantId,
referredTenantId,
codeUsed: referralCode.code,
status: referral_entity_1.ReferralStatus.PENDING,
expiresAt,
});
await this.referralRepo.save(referral);
referralCode.usesCount += 1;
await this.codeRepo.save(referralCode);
return referral;
}
async getReferralByReferred(referredTenantId) {
return this.referralRepo.findOne({ where: { referredTenantId } });
}
async getMyReferrals(tenantId) {
return this.referralRepo.find({
where: { referrerTenantId: tenantId },
order: { createdAt: 'DESC' },
});
}
async convertReferral(referredTenantId) {
const referral = await this.referralRepo.findOne({
where: { referredTenantId, status: referral_entity_1.ReferralStatus.PENDING },
});
if (!referral) {
throw new common_1.NotFoundException('No se encontro referido pendiente');
}
if (referral.expiresAt && new Date() > referral.expiresAt) {
referral.status = referral_entity_1.ReferralStatus.EXPIRED;
await this.referralRepo.save(referral);
throw new common_1.BadRequestException('El periodo de conversion ha expirado');
}
referral.status = referral_entity_1.ReferralStatus.CONVERTED;
referral.convertedAt = new Date();
await this.referralRepo.save(referral);
const expiresAt = new Date();
expiresAt.setFullYear(expiresAt.getFullYear() + 1);
const reward = this.rewardRepo.create({
tenantId: referral.referrerTenantId,
referralId: referral.id,
type: referral_reward_entity_1.RewardType.FREE_MONTH,
monthsEarned: 1,
monthsUsed: 0,
expiresAt,
status: referral_reward_entity_1.RewardStatus.AVAILABLE,
});
await this.rewardRepo.save(reward);
referral.status = referral_entity_1.ReferralStatus.REWARDED;
referral.referrerRewardApplied = true;
referral.rewardAppliedAt = new Date();
await this.referralRepo.save(referral);
return referral;
}
async getMyRewards(tenantId) {
return this.rewardRepo.find({
where: { tenantId },
order: { createdAt: 'DESC' },
});
}
async getAvailableMonths(tenantId) {
const rewards = await this.rewardRepo.find({
where: { tenantId, status: referral_reward_entity_1.RewardStatus.AVAILABLE, type: referral_reward_entity_1.RewardType.FREE_MONTH },
});
return rewards.reduce((sum, r) => sum + (r.monthsEarned - r.monthsUsed), 0);
}
async useReferralMonth(tenantId) {
const reward = await this.rewardRepo.findOne({
where: { tenantId, status: referral_reward_entity_1.RewardStatus.AVAILABLE, type: referral_reward_entity_1.RewardType.FREE_MONTH },
order: { createdAt: 'ASC' },
});
if (!reward || reward.monthsEarned <= reward.monthsUsed) {
return false;
}
reward.monthsUsed += 1;
if (reward.monthsUsed >= reward.monthsEarned) {
reward.status = referral_reward_entity_1.RewardStatus.USED;
}
await this.rewardRepo.save(reward);
return true;
}
async getStats(tenantId) {
const result = await this.dataSource.query(`SELECT * FROM get_referral_stats($1)`, [tenantId]);
const stats = result[0] || {
total_invited: 0,
total_converted: 0,
total_pending: 0,
total_expired: 0,
months_earned: 0,
months_available: 0,
};
const code = await this.getMyCode(tenantId);
return {
code: code.code,
totalInvited: stats.total_invited,
totalConverted: stats.total_converted,
totalPending: stats.total_pending,
totalExpired: stats.total_expired,
monthsEarned: stats.months_earned,
monthsAvailable: stats.months_available,
};
}
async getReferredDiscount(tenantId) {
const referral = await this.referralRepo.findOne({
where: {
referredTenantId: tenantId,
referredDiscountApplied: false,
status: referral_entity_1.ReferralStatus.PENDING,
},
});
if (!referral) {
return 0;
}
return 50;
}
async markDiscountApplied(tenantId) {
const referral = await this.referralRepo.findOne({
where: { referredTenantId: tenantId },
});
if (referral) {
referral.referredDiscountApplied = true;
await this.referralRepo.save(referral);
}
}
};
exports.ReferralsService = ReferralsService;
exports.ReferralsService = ReferralsService = __decorate([
(0, common_1.Injectable)(),
__param(0, (0, typeorm_1.InjectRepository)(referral_code_entity_1.ReferralCode)),
__param(1, (0, typeorm_1.InjectRepository)(referral_entity_1.Referral)),
__param(2, (0, typeorm_1.InjectRepository)(referral_reward_entity_1.ReferralReward)),
__metadata("design:paramtypes", [typeorm_2.Repository,
typeorm_2.Repository,
typeorm_2.Repository,
typeorm_2.DataSource])
], ReferralsService);
//# sourceMappingURL=referrals.service.js.map