"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