354 lines
16 KiB
JavaScript
354 lines
16 KiB
JavaScript
"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
|