返回 AiToEarn
finance.service.ts
根目录 / project / aitoearn-electron / server / src / modules / finance / finance.service.ts
1 /*
2 * @Author: nevin
3 * @Date: 2025-02-15 20:59:55
4 * @LastEditTime: 2025-04-27 14:05:49
5 * @LastEditors: nevin
6 * @Description:
7 */
8 import { Injectable } from '@nestjs/common';
9 import { InjectModel } from '@nestjs/mongoose';
10 import { Model, RootFilterQuery } from 'mongoose';
11 import { paginateModel } from 'src/common/paginate/create-pagination';
12 import { UserWalletAccount } from 'src/db/schema/userWalletAccount.shema';
13 import {
14 UserWalletRecord,
15 UserWalletRecordStatus,
16 UserWalletRecordType,
17 } from 'src/db/schema/userWalletRecord.shema';
18 import { ErrHttpBack } from 'src/filters/http-exception.back-code';
19 import { AppHttpException } from 'src/filters/http-exception.filter';
20 import { RedisService } from 'src/lib/redis/redis.service';
21 import { AlicloudSmsService } from 'src/lib/sms/alicloud-sms.service';
22 import { getRandomString } from 'src/util';
23 import {
24 GetUserWalletRecordListByAdminDto,
25 GetUserWalletRecordListDto,
26 } from './dto/userWalletRecord.dto';
27 import { UserWallet } from 'src/db/schema/userWallet.shema';
28 import { ObjectId } from 'mongodb';
29 @Injectable()
30 export class FinanceService {
31 constructor(
32 private readonly redisService: RedisService,
33 private readonly alicloudSmsService: AlicloudSmsService,
34 @InjectModel(UserWallet.name)
35 private readonly userWalletModel: Model<UserWallet>,
36 @InjectModel(UserWalletAccount.name)
37 private readonly userWalletAccountModel: Model<UserWalletAccount>,
38 @InjectModel(UserWalletRecord.name)
39 private readonly userWalletRecordModel: Model<UserWalletRecord>,
40 ) {}
41
42 // ------- 用户的钱包账户 START ---------
43 /**
44 * 获取用户钱包账户
45 * @param userId
46 * @returns
47 */
48 async getUserWalletByUserId(userId: ObjectId): Promise<UserWallet> {
49 const account = await this.userWalletModel.findOne({ userId });
50 if (account) return account;
51
52 return await this.userWalletModel.create({
53 userId,
54 });
55 }
56
57 /**
58 * 更新用户钱包账户的余额
59 * @param userWallet
60 * @param balance
61 * @returns
62 */
63 async updateUserWalletBalance(
64 userId: ObjectId,
65 balance: number,
66 ): Promise<boolean> {
67 const userWallet = await this.getUserWalletByUserId(userId);
68 const res = await this.userWalletModel.updateOne(
69 { userId: userWallet.userId },
70 {
71 $inc: {
72 balance,
73 },
74 },
75 );
76
77 return res.modifiedCount > 0;
78 }
79
80 // ------- 用户的钱包账户 END ---------
81
82 // --------- userWalletAccount STR ---------
83 /**
84 * 发送手机号验证码-创建用户钱包账户
85 * @param phone
86 */
87 async postCreateUserWalletAccountCode(phone: string) {
88 const cacheKey = `CreateUserWalletAccount:${phone}`;
89 let code = await this.redisService.get(cacheKey);
90 if (code) throw new AppHttpException(ErrHttpBack.err_user_code_had);
91
92 code = getRandomString(6, true);
93 const res = await this.alicloudSmsService.sendLoginSms(phone, code);
94
95 if (process.env.NODE_ENV === 'production') {
96 if (!res) throw new AppHttpException(ErrHttpBack.err_user_code_send_fail);
97 }
98
99 this.redisService.setKey(cacheKey, code, 60 * 5);
100 return process.env.NODE_ENV === 'production' ? res : code;
101 }
102
103 /**
104 * 创建用户钱包账户
105 * @param user
106 * @param data
107 * @returns
108 */
109 async createUserWalletAccount(
110 userId: string,
111 data: Partial<UserWalletAccount>,
112 ) {
113 return await this.userWalletAccountModel.create({
114 ...data,
115 isDef: false,
116 userId,
117 });
118 }
119
120 // 根据ID获取用户钱包账户
121 async getUserWalletAccountById(id: string) {
122 return await this.userWalletAccountModel.findOne({ _id: id });
123 }
124 // 获取用户钱包账户列表
125 async getUserWalletAccountList(userId: string) {
126 return await this.userWalletAccountModel.find({ userId });
127 }
128
129 // 删除用户钱包账户
130 async deleteUserWalletAccount(userId: string, id: string): Promise<boolean> {
131 const res = await this.userWalletAccountModel.deleteOne({
132 userId,
133 _id: id,
134 });
135 return res.deletedCount > 0;
136 }
137 // --------- userWalletAccount END ---------
138
139 // --------- userWalletRecord STR ---------
140 // 创建用户钱包记录
141 async createUserWalletRecord(
142 userId: string,
143 account: UserWalletAccount,
144 data: {
145 dataId?: string; // 关联数据的ID
146 type: UserWalletRecordType;
147 balance: number;
148 status: UserWalletRecordStatus;
149 des?: string;
150 },
151 ) {
152 return await this.userWalletRecordModel.create({
153 ...data,
154 userId,
155 account: account.id,
156 });
157 }
158
159 // 分页获取记录列表
160 async getUserWalletRecordList(
161 userId: string,
162 query: GetUserWalletRecordListDto,
163 ) {
164 const { page, pageSize, type, time } = query;
165 const filter: RootFilterQuery<UserWalletRecord> = {
166 userId,
167 ...(type && { type }),
168 ...(time && {
169 createTime: {
170 $gte: new Date(time[0]),
171 $lte: new Date(time[1]),
172 },
173 }),
174 };
175
176 return paginateModel(
177 this.userWalletRecordModel,
178 { page, pageSize },
179 filter,
180 'account',
181 { _id: -1 },
182 );
183 }
184
185 /**
186 * 获取列表
187 * @param query
188 * @returns
189 */
190 async getWalletRecordList(query: GetUserWalletRecordListByAdminDto) {
191 const { page, pageSize, type, userId, status, time } = query;
192 const filter: RootFilterQuery<UserWalletRecord> = {
193 ...(type && { type }),
194 ...(userId && { userId }),
195 ...(status !== undefined && { status }),
196 ...(time && {
197 payTime: {
198 $gte: new Date(time[0]),
199 $lte: new Date(time[1]),
200 },
201 }),
202 };
203
204 return paginateModel(
205 this.userWalletRecordModel,
206 { page, pageSize },
207 filter,
208 'account',
209 { _id: -1 },
210 );
211 }
212
213 /**
214 * 提交发布奖励
215 * @param id
216 * @param data
217 * @returns
218 */
219 async submitUserWalletRecord(
220 id: string,
221 data: {
222 imgUrl?: string; // 反馈截图
223 des?: string;
224 },
225 ): Promise<boolean> {
226 const { balance, userId } = await this.userWalletRecordModel.findOne({
227 _id: id,
228 });
229
230 const res = await this.userWalletRecordModel.updateOne(
231 { _id: id },
232 {
233 ...data,
234 status: UserWalletRecordStatus.SUCCESS,
235 payTime: new Date(),
236 },
237 );
238
239 // 减少余额
240 this.updateUserWalletBalance(new ObjectId(userId), -balance);
241
242 return res.modifiedCount > 0;
243 }
244
245 /**
246 * 拒绝发布奖励
247 * @param id
248 * @param data
249 * @returns
250 */
251 async rejectUserWalletRecord(
252 id: string,
253 data: {
254 imgUrl?: string; // 反馈截图
255 des?: string;
256 },
257 ): Promise<boolean> {
258 const res = await this.userWalletRecordModel.updateOne(
259 { _id: id },
260 {
261 ...data,
262 status: UserWalletRecordStatus.FAIL,
263 },
264 );
265
266 return res.modifiedCount > 0;
267 }
268
269 // --------- userWalletRecord END ---------
270
271 // 获取提现中的钱数总和
272 async getDoingWalletRecordCount(userId: string) {
273 const result = await this.userWalletRecordModel.aggregate([
274 {
275 $match: {
276 userId,
277 status: UserWalletRecordStatus.WAIT,
278 },
279 },
280 {
281 $group: {
282 _id: null,
283 totalBalance: { $sum: '$balance' },
284 },
285 },
286 ]);
287
288 return result.length > 0 ? result[0].totalBalance : 0;
289 }
290 }
291
291 lines TYPESCRIPT