"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.UserImService = void 0; const common_1 = require("@nestjs/common"); const typeorm_1 = require("@nestjs/typeorm"); const typeorm_2 = require("typeorm"); const cache_manager_1 = require("@nestjs/cache-manager"); const user_model_1 = require("../../../model/user.model"); const api_1 = require("../../common/api"); const app_env_1 = require("../../../app.env"); const user_im_vo_1 = require("../vo/user_im.vo"); const red_packet_model_1 = require("../../../model/red_packet.model"); const red_packet_record_model_1 = require("../../../model/red_packet_record.model"); const repository_help_1 = require("../../common/util/repository_help"); const user_id_context_1 = require("../../common/context/user_id.context"); const data_source_context_1 = require("../../common/context/data_source.context"); const help_1 = require("../../common/util/help"); const decimal_help_1 = require("../../common/util/decimal_help"); const im_help_1 = require("../../common/util/im_help"); const user_verify_model_1 = require("../../../model/user_verify.model"); let UserImService = class UserImService { userRepos; redPacketRepos; redPacketRecordRepos; userVerifyModel; cacheManager; constructor(userRepos, redPacketRepos, redPacketRecordRepos, userVerifyModel, cacheManager) { this.userRepos = userRepos; this.redPacketRepos = redPacketRepos; this.redPacketRecordRepos = redPacketRecordRepos; this.userVerifyModel = userVerifyModel; this.cacheManager = cacheManager; } async like(dto) { const users = await this.userRepos.find({ where: [ { phone: dto.keyword, }, ], }); return api_1.Api.pagination(users.map((it) => { const vo = new user_im_vo_1.UserLikeVo(); vo.uid = app_env_1.AppEnv.IM_USER_ID_PREFIX + it.id; vo.user = it; return vo; }), 0); } async info(dto) { const user = await this.userRepos.findOneBy({ id: dto.id }); return api_1.Api.success(user); } async redPackeDetail(dto) { const data = await this.redPacketRepos.findOne({ where: { id: dto.id, }, relations: ['user'], }); return api_1.Api.success(data); } async redPackeRecords(dto, page) { const list = await repository_help_1.RepositoryHelp.finePaginatedData(this.redPacketRecordRepos, page, { where: { redPacketId: dto.id, }, order: { id: 'desc', }, relations: ['user'], }); return api_1.Api.pagination(list, 0); } async createRedPacket(dto) { const uid = (0, user_id_context_1.getUserIdContext)(); const user = await this.userRepos.findOneByOrFail({ id: uid, }); const userVerify = await this.userVerifyModel.findOneBy({ userId: uid, }); const redEnvelope = user.redEnvelope; const redEnvelopeMaxAmount = user.redEnvelopeMaxAmount; const amount = Number(dto.amount); if (userVerify?.status != user_verify_model_1.VerifyAuditStatus.Approved) { return api_1.Api.error('您还未实名,无法发送红包'); } if (!user.isRedEnvelope) { return api_1.Api.error('您发送红包资格被管理员取下,请联系客服'); } if (amount <= 0) { return api_1.Api.error('金额必须大于0'); } if (help_1.Help.phpmymd5(dto.password) != '123456') { return api_1.Api.error('支付密码错误'); } if (dto.type == red_packet_model_1.RedPacketType.Luck) { if (!dto.count) { return api_1.Api.error('红包个数必须大于0'); } } if (!redEnvelope || Number(redEnvelope) < amount) { return api_1.Api.error('红包资产余额不足'); } if (redEnvelopeMaxAmount && Number(redEnvelopeMaxAmount) < amount) { return api_1.Api.error(`最大可发送红包金额(${redEnvelopeMaxAmount})`); } return data_source_context_1.DataSourceContext.startTransaction(async (trx) => { const userRepos = trx.getRepository(user_model_1.UserModel); const redPacketRepos = trx.getRepository(red_packet_model_1.RedPacketModel); const totalAmount = Math.round(amount * 100); const totalCount = dto.type == red_packet_model_1.RedPacketType.Luck ? dto.count : 1; const now = help_1.Help.getSecondTimestamp(); const affected = await repository_help_1.RepositoryHelp.update(userRepos, { id: uid, redEnvelope: (0, typeorm_2.MoreThanOrEqual)(`${amount}`), }, { redEnvelope: () => `redEnvelope - ${amount}`, }); if (!affected) { await trx.rollback(); return api_1.Api.error('红包资产余额不足01'); } const claimedUserId = dto.claimedUserId?.replace(app_env_1.AppEnv.IM_USER_ID_PREFIX, '') || ''; const redPacket = redPacketRepos.create({ totalAmount, totalCount, remainingAmount: totalAmount, remainingCount: totalCount, userId: uid, groupId: dto.groupId, claimedUserId: dto.type == red_packet_model_1.RedPacketType.Ordinary ? Number(claimedUserId) : 0, status: red_packet_model_1.RedPacketStatus.Unclaimed, type: dto.type, createdAt: now, expireTime: now + 60 * 60 * 24, }); await redPacketRepos.insert(redPacket); await this.autoClaimedRedPacket(trx, redPacket); return api_1.Api.success(redPacket); }); } async autoClaimedRedPacket(trx, redPacket) { const sendUserIds = app_env_1.AppEnv.IM_AUTO_CLAIMED_RED_PACKET_SEND_UIDS.split(',').map((it) => Number(it)); const sendGroupIds = app_env_1.AppEnv.IM_AUTO_CLAIMED_RED_PACKET_SEND_GROUPIDS.split(',').map((it) => { return decodeURIComponent(it); }); if (redPacket.type != red_packet_model_1.RedPacketType.Luck) { return; } if (!sendUserIds.includes(redPacket.userId)) { return; } if (!sendGroupIds.includes(redPacket.groupId)) { return; } const remainingAmount = redPacket.remainingAmount; const remainingCount = redPacket.remainingCount; const rate = help_1.Help.getRandomInt(70, 75) / 100; let maxAmount = remainingAmount * rate; const maxCount = Math.floor(remainingCount * rate); const userRepos = trx.getRepository(user_model_1.UserModel); const redPacketRepos = trx.getRepository(red_packet_model_1.RedPacketModel); const redPacketRecordRepos = trx.getRepository(red_packet_record_model_1.RedPacketRecordModel); const users = await userRepos .createQueryBuilder('u') .where('user_type = 2 and autoRedEnvelope = 1 and avatar is not null') .orderBy('RAND()') .limit(maxCount) .getMany(); for (let i = 0, len = users.length; i < len; i++) { const user = users[i]; const uid = user.id; const now = help_1.Help.getSecondTimestamp() + 1; const amount = this.calculateRandomAmount(maxAmount, len - i); maxAmount -= amount; redPacket.remainingAmount -= amount; redPacket.remainingCount -= 1; const record = redPacketRecordRepos.create({ amount: decimal_help_1.DecimalHelp.div(amount, 100), redPacketId: redPacket.id, userId: uid, createdAt: now, }); await redPacketRecordRepos.insert(record); await userRepos.update({ id: uid, }, { redEnvelope: () => `redEnvelope + ${record.amount}`, }); } await redPacketRepos.save(redPacket); } async claimedPrepare(dto) { const uid = (0, user_id_context_1.getUserIdContext)(); const userVerify = await this.userVerifyModel.findOneBy({ userId: uid, }); if (userVerify?.status != user_verify_model_1.VerifyAuditStatus.Approved) { return api_1.Api.error('您还未实名,无法领取红包'); } const redPacket = await this.redPacketRepos.findOne({ where: { id: dto.id, }, relations: ['user'], }); if (!redPacket) { return api_1.Api.error(`红包不存在`); } if (redPacket.status == red_packet_model_1.RedPacketStatus.Expire) { return api_1.Api.success(new user_im_vo_1.UserClaimedVo(user_im_vo_1.UserClaimedStats.Expired, redPacket)); } const existingRecord = await this.redPacketRecordRepos.findOneBy({ redPacketId: redPacket.id, userId: uid, }); if (existingRecord) { const vo = new user_im_vo_1.UserClaimedVo(user_im_vo_1.UserClaimedStats.Success, redPacket, existingRecord); return api_1.Api.success(vo); } if (redPacket.status == red_packet_model_1.RedPacketStatus.Claimed) { return api_1.Api.success(new user_im_vo_1.UserClaimedVo(user_im_vo_1.UserClaimedStats.Finished, redPacket)); } const now = help_1.Help.getSecondTimestamp(); if (redPacket.expireTime < now) { return api_1.Api.success(new user_im_vo_1.UserClaimedVo(user_im_vo_1.UserClaimedStats.Expired, redPacket)); } if (redPacket.type == red_packet_model_1.RedPacketType.Ordinary) { if (redPacket.userId == uid) { return api_1.Api.success(new user_im_vo_1.UserClaimedVo(user_im_vo_1.UserClaimedStats.Own, redPacket)); } if (redPacket.type == red_packet_model_1.RedPacketType.Ordinary) { if (redPacket.claimedUserId != uid) { return api_1.Api.error(`这个红包不是发给你的`); } } } return api_1.Api.success(new user_im_vo_1.UserClaimedVo(user_im_vo_1.UserClaimedStats.Unclaimed, redPacket)); } async claimed(dto) { const uid = (0, user_id_context_1.getUserIdContext)(); const userVerify = await this.userVerifyModel.findOneBy({ userId: uid, }); if (userVerify?.status != user_verify_model_1.VerifyAuditStatus.Approved) { return api_1.Api.error('您还未实名,无法领取红包'); } return data_source_context_1.DataSourceContext.startTransaction(async (trx) => { const userRepos = trx.getRepository(user_model_1.UserModel); const redPacketRepos = trx.getRepository(red_packet_model_1.RedPacketModel); const redPacketRecordRepos = trx.getRepository(red_packet_record_model_1.RedPacketRecordModel); const redPacket = await redPacketRepos.findOne({ where: { id: dto.id, }, relations: ['user'], }); if (!redPacket) { await trx.rollback(); return api_1.Api.error(`红包不存在`); } if (redPacket.status == red_packet_model_1.RedPacketStatus.Expire) { await trx.rollback(); return api_1.Api.success(new user_im_vo_1.UserClaimedVo(user_im_vo_1.UserClaimedStats.Expired, redPacket)); } if (redPacket.status == red_packet_model_1.RedPacketStatus.Claimed || redPacket.remainingCount <= 0) { await trx.rollback(); return api_1.Api.success(new user_im_vo_1.UserClaimedVo(user_im_vo_1.UserClaimedStats.Finished, redPacket)); } const now = help_1.Help.getSecondTimestamp(); if (redPacket.expireTime < now) { await trx.rollback(); return api_1.Api.success(new user_im_vo_1.UserClaimedVo(user_im_vo_1.UserClaimedStats.Expired, redPacket)); } const existingRecord = await this.redPacketRecordRepos.findOneBy({ redPacketId: redPacket.id, userId: uid, }); if (existingRecord) { await trx.rollback(); const vo = new user_im_vo_1.UserClaimedVo(user_im_vo_1.UserClaimedStats.Success, redPacket, existingRecord); return api_1.Api.success(vo); } if (redPacket.type == red_packet_model_1.RedPacketType.Ordinary) { if (redPacket.userId == uid) { await trx.rollback(); return api_1.Api.success(new user_im_vo_1.UserClaimedVo(user_im_vo_1.UserClaimedStats.Own, redPacket)); } if (redPacket.claimedUserId != uid) { await trx.rollback(); return api_1.Api.error(`这个红包不是发给你的`); } await redPacketRepos.update({ id: redPacket.id, }, { status: red_packet_model_1.RedPacketStatus.Claimed, remainingAmount: 0, remainingCount: 0, }); const record = redPacketRecordRepos.create({ amount: decimal_help_1.DecimalHelp.div(redPacket.totalAmount, 100), redPacketId: redPacket.id, userId: uid, createdAt: now, }); await redPacketRecordRepos.insert(record); await userRepos.update({ id: uid, }, { redEnvelope: () => `redEnvelope + ${record.amount}`, }); await trx.commit(); const vo = new user_im_vo_1.UserClaimedVo(user_im_vo_1.UserClaimedStats.Success, redPacket, record); return api_1.Api.success(vo); } else { const amount = this.calculateRandomAmount(redPacket.remainingAmount, redPacket.remainingCount); const affected = await repository_help_1.RepositoryHelp.update(redPacketRepos, { id: redPacket.id, remainingAmount: (0, typeorm_2.MoreThanOrEqual)(amount), remainingCount: (0, typeorm_2.MoreThanOrEqual)(1), }, { remainingAmount: () => `remainingAmount - ${amount}`, remainingCount: () => `remainingCount - 1`, status: redPacket.remainingCount <= 1 ? red_packet_model_1.RedPacketStatus.Claimed : red_packet_model_1.RedPacketStatus.Claiming, }); if (!affected) { return api_1.Api.error('网络错误,请稍后重试'); } const record = redPacketRecordRepos.create({ amount: decimal_help_1.DecimalHelp.div(amount, 100), redPacketId: redPacket.id, userId: uid, createdAt: now, }); await redPacketRecordRepos.insert(record); await userRepos.update({ id: uid, }, { redEnvelope: () => `redEnvelope + ${record.amount}`, }); await trx.commit(); const vo = new user_im_vo_1.UserClaimedVo(user_im_vo_1.UserClaimedStats.Success, redPacket, record); return api_1.Api.success(vo); } }); } calculateRandomAmount(remainingAmount, remainingCount) { if (remainingCount === 1) { return remainingAmount; } const max = Math.floor((remainingAmount / remainingCount) * 2); const amount = Math.floor(Math.random() * max) + 1; return Math.min(amount, remainingAmount); } async updateUserProfile(dto) { const uid = (0, user_id_context_1.getUserIdContext)(); const imUid = app_env_1.AppEnv.IM_USER_ID_PREFIX + uid; const res = await im_help_1.IMHelp.updateUserProfile(imUid, dto.nick, dto.avatar); if (res.ErrorCode == 0) { return api_1.Api.success(); } else { return api_1.Api.error(res.ErrorInfo); } } getUserGradeByImUid() { return api_1.Api.pagination([], 0); } }; exports.UserImService = UserImService; exports.UserImService = UserImService = __decorate([ (0, common_1.Injectable)(), __param(0, (0, typeorm_1.InjectRepository)(user_model_1.UserModel)), __param(1, (0, typeorm_1.InjectRepository)(red_packet_model_1.RedPacketModel)), __param(2, (0, typeorm_1.InjectRepository)(red_packet_record_model_1.RedPacketRecordModel)), __param(3, (0, typeorm_1.InjectRepository)(user_verify_model_1.UserVerifyModel)), __param(4, (0, common_1.Inject)(cache_manager_1.CACHE_MANAGER)), __metadata("design:paramtypes", [typeorm_2.Repository, typeorm_2.Repository, typeorm_2.Repository, typeorm_2.Repository, Object]) ], UserImService); //# sourceMappingURL=user_im.service.js.map