"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.CodiSpeiService = void 0; const common_1 = require("@nestjs/common"); const typeorm_1 = require("@nestjs/typeorm"); const typeorm_2 = require("typeorm"); const virtual_account_entity_1 = require("./entities/virtual-account.entity"); const codi_transaction_entity_1 = require("./entities/codi-transaction.entity"); const spei_transaction_entity_1 = require("./entities/spei-transaction.entity"); let CodiSpeiService = class CodiSpeiService { constructor(virtualAccountRepo, codiRepo, speiRepo, dataSource) { this.virtualAccountRepo = virtualAccountRepo; this.codiRepo = codiRepo; this.speiRepo = speiRepo; this.dataSource = dataSource; } async getVirtualAccount(tenantId) { return this.virtualAccountRepo.findOne({ where: { tenantId, status: virtual_account_entity_1.VirtualAccountStatus.ACTIVE }, }); } async createVirtualAccount(tenantId, beneficiaryName, provider = 'stp') { const existing = await this.getVirtualAccount(tenantId); if (existing) { return existing; } const mockClabe = `646180${Math.floor(Math.random() * 1000000000000).toString().padStart(12, '0')}`; const account = this.virtualAccountRepo.create({ tenantId, provider, clabe: mockClabe, beneficiaryName, status: virtual_account_entity_1.VirtualAccountStatus.ACTIVE, }); return this.virtualAccountRepo.save(account); } async generateQr(tenantId, dto) { const result = await this.dataSource.query(`SELECT generate_codi_reference($1) as reference`, [tenantId]); const reference = result[0].reference; const expiresAt = new Date(); expiresAt.setMinutes(expiresAt.getMinutes() + 5); const qrData = JSON.stringify({ type: 'codi', amount: dto.amount, reference, merchant: tenantId, expires: expiresAt.toISOString(), }); const transaction = this.codiRepo.create({ tenantId, saleId: dto.saleId, qrData, amount: dto.amount, reference, description: dto.description || `Cobro ${reference}`, status: codi_transaction_entity_1.CodiTransactionStatus.PENDING, expiresAt, }); return this.codiRepo.save(transaction); } async getCodiStatus(id) { const transaction = await this.codiRepo.findOne({ where: { id } }); if (!transaction) { throw new common_1.NotFoundException('Transaccion CoDi no encontrada'); } if (transaction.status === codi_transaction_entity_1.CodiTransactionStatus.PENDING && new Date() > transaction.expiresAt) { transaction.status = codi_transaction_entity_1.CodiTransactionStatus.EXPIRED; await this.codiRepo.save(transaction); } return transaction; } async confirmCodi(id, providerData) { const transaction = await this.getCodiStatus(id); if (transaction.status !== codi_transaction_entity_1.CodiTransactionStatus.PENDING) { throw new common_1.BadRequestException(`Transaccion no esta pendiente: ${transaction.status}`); } transaction.status = codi_transaction_entity_1.CodiTransactionStatus.CONFIRMED; transaction.confirmedAt = new Date(); transaction.providerResponse = providerData; return this.codiRepo.save(transaction); } async getCodiTransactions(tenantId, limit = 50) { return this.codiRepo.find({ where: { tenantId }, order: { createdAt: 'DESC' }, take: limit, }); } async getSpeiTransactions(tenantId, limit = 50) { return this.speiRepo.find({ where: { tenantId }, order: { receivedAt: 'DESC' }, take: limit, }); } async receiveSpei(tenantId, data) { const account = await this.getVirtualAccount(tenantId); const transaction = this.speiRepo.create({ tenantId, virtualAccountId: account?.id, amount: data.amount, senderClabe: data.senderClabe, senderName: data.senderName, senderRfc: data.senderRfc, senderBank: data.senderBank, reference: data.reference, trackingKey: data.trackingKey, status: spei_transaction_entity_1.SpeiTransactionStatus.RECEIVED, receivedAt: new Date(), providerData: data.providerData, }); return this.speiRepo.save(transaction); } async reconcileSpei(id, saleId) { const transaction = await this.speiRepo.findOne({ where: { id } }); if (!transaction) { throw new common_1.NotFoundException('Transaccion SPEI no encontrada'); } transaction.saleId = saleId; transaction.status = spei_transaction_entity_1.SpeiTransactionStatus.RECONCILED; transaction.reconciledAt = new Date(); return this.speiRepo.save(transaction); } async getSummary(tenantId, date) { const targetDate = date || new Date(); const dateStr = targetDate.toISOString().split('T')[0]; const result = await this.dataSource.query(`SELECT * FROM get_codi_spei_summary($1, $2::date)`, [tenantId, dateStr]); return result[0] || { codi_count: 0, codi_total: 0, spei_count: 0, spei_total: 0, }; } async handleCodiWebhook(payload) { const { reference, status, transactionId } = payload; const transaction = await this.codiRepo.findOne({ where: { reference }, }); if (!transaction) { throw new common_1.NotFoundException('Transaccion no encontrada'); } if (status === 'confirmed') { await this.confirmCodi(transaction.id, { providerTransactionId: transactionId, ...payload, }); } } async handleSpeiWebhook(clabe, payload) { const account = await this.virtualAccountRepo.findOne({ where: { clabe }, }); if (!account) { throw new common_1.NotFoundException('Cuenta virtual no encontrada'); } await this.receiveSpei(account.tenantId, { amount: payload.amount, senderClabe: payload.senderClabe, senderName: payload.senderName, senderRfc: payload.senderRfc, senderBank: payload.senderBank, reference: payload.reference, trackingKey: payload.trackingKey, providerData: payload, }); } }; exports.CodiSpeiService = CodiSpeiService; exports.CodiSpeiService = CodiSpeiService = __decorate([ (0, common_1.Injectable)(), __param(0, (0, typeorm_1.InjectRepository)(virtual_account_entity_1.VirtualAccount)), __param(1, (0, typeorm_1.InjectRepository)(codi_transaction_entity_1.CodiTransaction)), __param(2, (0, typeorm_1.InjectRepository)(spei_transaction_entity_1.SpeiTransaction)), __metadata("design:paramtypes", [typeorm_2.Repository, typeorm_2.Repository, typeorm_2.Repository, typeorm_2.DataSource]) ], CodiSpeiService); //# sourceMappingURL=codi-spei.service.js.map