m
This commit is contained in:
+354
@@ -0,0 +1,354 @@
|
||||
"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.SignInService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const typeorm_1 = require("@nestjs/typeorm");
|
||||
const typeorm_2 = require("typeorm");
|
||||
const user_sign_in_model_1 = require("../../../model/user_sign_in.model");
|
||||
const user_sign_in_calendar_model_1 = require("../../../model/user_sign_in_calendar.model");
|
||||
const user_sign_in_task_model_1 = require("../../../model/user_sign_in_task.model");
|
||||
const user_sign_in_task_reward_model_1 = require("../../../model/user_sign_in_task_reward.model");
|
||||
const user_financial_product_model_1 = require("../../../model/user_financial_product.model");
|
||||
const api_1 = require("../../common/api");
|
||||
const signin_vo_1 = require("../vo/signin.vo");
|
||||
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 financial_product_model_1 = require("../../../model/financial_product.model");
|
||||
let SignInService = class SignInService {
|
||||
userSignInModel;
|
||||
userSignInCalendarModel;
|
||||
userSignInTaskModel;
|
||||
userSignInTaskRewardModel;
|
||||
userFinancialProductModel;
|
||||
dataSource;
|
||||
constructor(userSignInModel, userSignInCalendarModel, userSignInTaskModel, userSignInTaskRewardModel, userFinancialProductModel, dataSource) {
|
||||
this.userSignInModel = userSignInModel;
|
||||
this.userSignInCalendarModel = userSignInCalendarModel;
|
||||
this.userSignInTaskModel = userSignInTaskModel;
|
||||
this.userSignInTaskRewardModel = userSignInTaskRewardModel;
|
||||
this.userFinancialProductModel = userFinancialProductModel;
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
async getSignInInfo(userId) {
|
||||
const signInStats = await this.userSignInModel.findOne({
|
||||
where: { userId },
|
||||
});
|
||||
const nowYYYMMDD = help_1.Help.formatDate(Date.now(), 'YYYY-MM-DD');
|
||||
return api_1.Api.success({
|
||||
...signInStats,
|
||||
signToDay: nowYYYMMDD == signInStats?.lastSignInDate,
|
||||
});
|
||||
}
|
||||
async getSignInCalendar(userId, year, month) {
|
||||
const firstDay = `${year}-${String(month).padStart(2, '0')}-01`;
|
||||
const lastDay = new Date(year, month, 0).toISOString().split('T')[0];
|
||||
const signInRecords = await this.userSignInCalendarModel.find({
|
||||
where: {
|
||||
userId,
|
||||
signInDate: (0, typeorm_2.Between)(firstDay, lastDay),
|
||||
},
|
||||
order: { signInDate: 'ASC' },
|
||||
});
|
||||
return api_1.Api.pagination(signInRecords, signInRecords.length);
|
||||
}
|
||||
async getProgress() {
|
||||
const userId = (0, user_id_context_1.getUserIdContext)();
|
||||
const userSignIn = await this.userSignInModel.findOneByOrFail({
|
||||
userId,
|
||||
});
|
||||
const existFirst = userSignIn.firstSignInDate != null;
|
||||
const nowDate = new Date();
|
||||
const nowYYYMMDD = help_1.Help.formatDate(nowDate, 'YYYY-MM-DD');
|
||||
const startDate = new Date();
|
||||
startDate.setDate(startDate.getDate() - (existFirst ? 3 : 0));
|
||||
let startYYYMMDD = help_1.Help.formatDate(startDate, 'YYYY-MM-DD');
|
||||
const firstSignDate = userSignIn.firstSignInDate || nowYYYMMDD;
|
||||
if (firstSignDate > startYYYMMDD) {
|
||||
startYYYMMDD = firstSignDate;
|
||||
}
|
||||
const signInCalendars = await this.userSignInCalendarModel.find({
|
||||
where: {
|
||||
userId,
|
||||
signInDate: (0, typeorm_2.Between)(startYYYMMDD, nowYYYMMDD),
|
||||
},
|
||||
});
|
||||
const signedDates = new Map();
|
||||
signInCalendars.forEach((it) => {
|
||||
signedDates.set(it.signInDate, it);
|
||||
});
|
||||
const dates = [];
|
||||
const current = new Date(startYYYMMDD);
|
||||
const endDate = new Date(startYYYMMDD);
|
||||
endDate.setDate(endDate.getDate() + 6);
|
||||
while (current <= endDate) {
|
||||
const dateStr = help_1.Help.formatDate(current, 'YYYY-MM-DD');
|
||||
dates.push(dateStr);
|
||||
current.setDate(current.getDate() + 1);
|
||||
}
|
||||
return api_1.Api.pagination(dates.map((date) => {
|
||||
const vo = new signin_vo_1.SignInProgressDayVo();
|
||||
vo.date = date;
|
||||
vo.isFutureDay = date > nowYYYMMDD;
|
||||
vo.signedIn = signedDates.has(date);
|
||||
vo.isMakeUp = signedDates.get(date)?.isMakeUp || user_sign_in_calendar_model_1.SignInType.Normal;
|
||||
vo.isDay = date == nowYYYMMDD;
|
||||
vo.consecutiveDay = help_1.Help.diffDays(date, firstSignDate) + 1;
|
||||
return vo;
|
||||
}), 0);
|
||||
}
|
||||
async getTaskList(userId) {
|
||||
const tasks = await this.userSignInTaskModel.find({
|
||||
order: { requiredDays: 'ASC' },
|
||||
});
|
||||
if (tasks.length === 0) {
|
||||
return api_1.Api.success([]);
|
||||
}
|
||||
const taskIds = tasks.map((t) => t.id);
|
||||
const rewards = await this.userSignInTaskRewardModel.find({
|
||||
where: {
|
||||
userId,
|
||||
userSignInTaskId: (0, typeorm_2.In)(taskIds),
|
||||
},
|
||||
});
|
||||
const rewardMap = new Map();
|
||||
for (const reward of rewards) {
|
||||
rewardMap.set(reward.userSignInTaskId, reward);
|
||||
}
|
||||
const taskList = tasks.map((task) => {
|
||||
const reward = rewardMap.get(task.id);
|
||||
if (reward) {
|
||||
const status = reward.claimStatus === user_sign_in_task_reward_model_1.ClaimStatus.Claimed
|
||||
? signin_vo_1.TaskStatus.Completed
|
||||
: signin_vo_1.TaskStatus.Pending;
|
||||
return {
|
||||
id: task.id,
|
||||
title: task.title,
|
||||
subtitle: task.subtitle,
|
||||
requiredDays: task.requiredDays,
|
||||
icon: task.icon,
|
||||
status,
|
||||
rewardId: reward.id,
|
||||
};
|
||||
}
|
||||
return {
|
||||
id: task.id,
|
||||
title: task.title,
|
||||
subtitle: task.subtitle,
|
||||
requiredDays: task.requiredDays,
|
||||
icon: task.icon,
|
||||
status: signin_vo_1.TaskStatus.InProgress,
|
||||
rewardId: undefined,
|
||||
};
|
||||
});
|
||||
return api_1.Api.pagination(taskList, taskList.length);
|
||||
}
|
||||
async todaySignIn(userId) {
|
||||
const nowYYYMMDD = help_1.Help.formatDate(Date.now(), 'YYYY-MM-DD');
|
||||
const signInStats = await this.userSignInModel.findOneOrFail({
|
||||
where: { userId },
|
||||
});
|
||||
if (signInStats && signInStats.lastSignInDate === nowYYYMMDD) {
|
||||
return api_1.Api.error('今日已签到');
|
||||
}
|
||||
const yesterday = help_1.Help.formatDate(new Date(Date.now() - 86400000), 'YYYY-MM-DD');
|
||||
let consecutiveDays = 1;
|
||||
if (signInStats && signInStats.lastSignInDate === yesterday) {
|
||||
consecutiveDays = signInStats.consecutiveDays + 1;
|
||||
}
|
||||
else {
|
||||
consecutiveDays = 1;
|
||||
}
|
||||
await data_source_context_1.DataSourceContext.startTransaction(async (tx) => {
|
||||
const signInRepo = tx.getRepository(user_sign_in_model_1.UserSignInModel);
|
||||
const calendarRepo = tx.getRepository(user_sign_in_calendar_model_1.UserSignInCalendarModel);
|
||||
const taskRepo = tx.getRepository(user_sign_in_task_model_1.UserSignInTaskModel);
|
||||
const rewardRepo = tx.getRepository(user_sign_in_task_reward_model_1.UserSignInTaskRewardModel);
|
||||
await signInRepo.update({ userId }, {
|
||||
lastSignInDate: nowYYYMMDD,
|
||||
consecutiveDays,
|
||||
});
|
||||
const calendarRecord = calendarRepo.create({
|
||||
userId,
|
||||
signInDate: nowYYYMMDD,
|
||||
isMakeUp: user_sign_in_calendar_model_1.SignInType.Normal,
|
||||
});
|
||||
await calendarRepo.save(calendarRecord);
|
||||
const tasks = await taskRepo.find({
|
||||
order: { requiredDays: 'ASC' },
|
||||
});
|
||||
for (const task of tasks) {
|
||||
if (consecutiveDays >= task.requiredDays) {
|
||||
const existingReward = await rewardRepo.findOne({
|
||||
where: {
|
||||
userId,
|
||||
userSignInTaskId: task.id,
|
||||
},
|
||||
});
|
||||
if (!existingReward) {
|
||||
const reward = rewardRepo.create({
|
||||
userId,
|
||||
userSignInTaskId: task.id,
|
||||
title: task.title,
|
||||
subtitle: task.subtitle,
|
||||
requiredDays: task.requiredDays,
|
||||
icon: task.icon,
|
||||
financialProductId: task.financialProductId,
|
||||
claimStatus: user_sign_in_task_reward_model_1.ClaimStatus.Pending,
|
||||
});
|
||||
await rewardRepo.save(reward);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return api_1.Api.successMsg('签到成功');
|
||||
}
|
||||
async makeUpSignIn(userId, date) {
|
||||
const nowYYYMMDD = help_1.Help.formatDate(Date.now(), 'YYYY-MM-DD');
|
||||
if (date >= nowYYYMMDD) {
|
||||
return api_1.Api.error('只能补签今天之前的日期');
|
||||
}
|
||||
const signInStats = await this.userSignInModel.findOneOrFail({
|
||||
where: { userId },
|
||||
});
|
||||
const existingRecord = await this.userSignInCalendarModel.findOne({
|
||||
where: { userId, signInDate: date },
|
||||
});
|
||||
if (existingRecord) {
|
||||
return api_1.Api.error('该日期已签到,无需补签');
|
||||
}
|
||||
const makeUpCount = signInStats.makeUpCount;
|
||||
if (makeUpCount <= 0) {
|
||||
return api_1.Api.error('补签次数已用完');
|
||||
}
|
||||
if (!signInStats.lastSignInDate) {
|
||||
return api_1.Api.error('请先完成首次签到');
|
||||
}
|
||||
await data_source_context_1.DataSourceContext.startTransaction(async (tx) => {
|
||||
const calendarRepo = tx.getRepository(user_sign_in_calendar_model_1.UserSignInCalendarModel);
|
||||
const signInRepo = tx.getRepository(user_sign_in_model_1.UserSignInModel);
|
||||
const taskRepo = tx.getRepository(user_sign_in_task_model_1.UserSignInTaskModel);
|
||||
const rewardRepo = tx.getRepository(user_sign_in_task_reward_model_1.UserSignInTaskRewardModel);
|
||||
const calendarRecord = calendarRepo.create({
|
||||
userId,
|
||||
signInDate: date,
|
||||
isMakeUp: user_sign_in_calendar_model_1.SignInType.MakeUp,
|
||||
});
|
||||
await calendarRepo.save(calendarRecord);
|
||||
const newConsecutiveDays = await this.calcConsecutiveDays(tx, userId, signInStats.lastSignInDate, signInStats.consecutiveDays);
|
||||
await signInRepo.update({ userId }, {
|
||||
consecutiveDays: newConsecutiveDays,
|
||||
makeUpCount: () => `makeUpCount - 1`,
|
||||
usedMakeUpCount: () => `usedMakeUpCount + 1`,
|
||||
});
|
||||
const tasks = await taskRepo.find({
|
||||
order: { requiredDays: 'ASC' },
|
||||
});
|
||||
for (const task of tasks) {
|
||||
if (newConsecutiveDays >= task.requiredDays) {
|
||||
const existingReward = await rewardRepo.findOne({
|
||||
where: {
|
||||
userId,
|
||||
userSignInTaskId: task.id,
|
||||
},
|
||||
});
|
||||
if (!existingReward) {
|
||||
const reward = rewardRepo.create({
|
||||
userId,
|
||||
userSignInTaskId: task.id,
|
||||
title: task.title,
|
||||
subtitle: task.subtitle,
|
||||
requiredDays: task.requiredDays,
|
||||
icon: task.icon,
|
||||
financialProductId: task.financialProductId,
|
||||
claimStatus: user_sign_in_task_reward_model_1.ClaimStatus.Pending,
|
||||
});
|
||||
await rewardRepo.save(reward);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return api_1.Api.successMsg('补签成功');
|
||||
}
|
||||
async calcConsecutiveDays(tx, userId, endDate, expectedDays) {
|
||||
const startDate = help_1.Help.formatDate(new Date(endDate).getTime() - expectedDays * 86400000, 'YYYY-MM-DD');
|
||||
const calendarRepo = tx.getRepository(user_sign_in_calendar_model_1.UserSignInCalendarModel);
|
||||
const count = await calendarRepo.count({
|
||||
where: {
|
||||
userId,
|
||||
signInDate: (0, typeorm_2.Between)(startDate, endDate),
|
||||
},
|
||||
});
|
||||
return count === expectedDays + 1 ? expectedDays + 1 : expectedDays;
|
||||
}
|
||||
async claimReward(userId, rewardId) {
|
||||
await data_source_context_1.DataSourceContext.startTransaction(async (tx) => {
|
||||
const rewardRepo = tx.getRepository(user_sign_in_task_reward_model_1.UserSignInTaskRewardModel);
|
||||
const financialProductRepo = tx.getRepository(financial_product_model_1.FinancialProductModel);
|
||||
const financialRepo = tx.getRepository(user_financial_product_model_1.UserFinancialProductModel);
|
||||
const reward = await rewardRepo.findOne({
|
||||
where: { id: rewardId, userId },
|
||||
});
|
||||
if (!reward) {
|
||||
throw new Error('奖励记录不存在');
|
||||
}
|
||||
if (reward.claimStatus === user_sign_in_task_reward_model_1.ClaimStatus.Claimed) {
|
||||
throw new Error('该奖励已领取');
|
||||
}
|
||||
const financialProduct = await financialProductRepo.findOneBy({
|
||||
id: reward.financialProductId,
|
||||
});
|
||||
if (!financialProduct) {
|
||||
throw new Error('理财产品不存在');
|
||||
}
|
||||
const now = Date.now();
|
||||
const periodDays = financialProduct.period;
|
||||
const expireTime = Math.floor((now + periodDays * 86400000) / 1000);
|
||||
const userFinancialProduct = financialRepo.create({
|
||||
userId,
|
||||
financialProductId: reward.financialProductId,
|
||||
name: reward.title,
|
||||
period: periodDays,
|
||||
principal: financialProduct.principal,
|
||||
yieldRate: financialProduct.yieldRate,
|
||||
source: user_financial_product_model_1.HoldingSource.Gift,
|
||||
status: user_financial_product_model_1.HoldingStatus.Earning,
|
||||
expireTime,
|
||||
});
|
||||
await financialRepo.save(userFinancialProduct);
|
||||
await rewardRepo.update({ id: rewardId }, {
|
||||
userFinancialProductId: userFinancialProduct.id,
|
||||
claimStatus: user_sign_in_task_reward_model_1.ClaimStatus.Claimed,
|
||||
});
|
||||
});
|
||||
return api_1.Api.successMsg('领取成功');
|
||||
}
|
||||
};
|
||||
exports.SignInService = SignInService;
|
||||
exports.SignInService = SignInService = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__param(0, (0, typeorm_1.InjectRepository)(user_sign_in_model_1.UserSignInModel)),
|
||||
__param(1, (0, typeorm_1.InjectRepository)(user_sign_in_calendar_model_1.UserSignInCalendarModel)),
|
||||
__param(2, (0, typeorm_1.InjectRepository)(user_sign_in_task_model_1.UserSignInTaskModel)),
|
||||
__param(3, (0, typeorm_1.InjectRepository)(user_sign_in_task_reward_model_1.UserSignInTaskRewardModel)),
|
||||
__param(4, (0, typeorm_1.InjectRepository)(user_financial_product_model_1.UserFinancialProductModel)),
|
||||
__metadata("design:paramtypes", [typeorm_2.Repository,
|
||||
typeorm_2.Repository,
|
||||
typeorm_2.Repository,
|
||||
typeorm_2.Repository,
|
||||
typeorm_2.Repository,
|
||||
typeorm_2.DataSource])
|
||||
], SignInService);
|
||||
//# sourceMappingURL=signin.service.js.map
|
||||
Reference in New Issue
Block a user