feat: 新增体重记录接口及枚举,优化AI教练选择项处理
This commit is contained in:
@@ -216,12 +216,13 @@ export class UsersService {
|
||||
|
||||
await user.save();
|
||||
|
||||
const [profile] = await this.userProfileModel.findOrCreate({
|
||||
where: { userId },
|
||||
defaults: { userId },
|
||||
});
|
||||
|
||||
// 更新或创建扩展信息
|
||||
if (dailyStepsGoal !== undefined || dailyCaloriesGoal !== undefined || pilatesPurposes !== undefined || weight !== undefined || initialWeight !== undefined || targetWeight !== undefined || height !== undefined || activityLevel !== undefined) {
|
||||
const [profile] = await this.userProfileModel.findOrCreate({
|
||||
where: { userId },
|
||||
defaults: { userId },
|
||||
});
|
||||
if (dailyStepsGoal !== undefined) { profile.dailyStepsGoal = dailyStepsGoal as any; profileChanges.dailyStepsGoal = dailyStepsGoal; }
|
||||
if (dailyCaloriesGoal !== undefined) { profile.dailyCaloriesGoal = dailyCaloriesGoal as any; profileChanges.dailyCaloriesGoal = dailyCaloriesGoal; }
|
||||
if (pilatesPurposes !== undefined) { profile.pilatesPurposes = pilatesPurposes as any; profileChanges.pilatesPurposes = pilatesPurposes; }
|
||||
@@ -278,6 +279,7 @@ export class UsersService {
|
||||
message: 'success',
|
||||
data: {
|
||||
...user.toJSON(),
|
||||
...profile.toJSON(),
|
||||
isNew: false,
|
||||
} as any,
|
||||
};
|
||||
@@ -318,7 +320,156 @@ export class UsersService {
|
||||
order: [['created_at', 'DESC']],
|
||||
limit,
|
||||
});
|
||||
return rows.map(r => ({ weight: r.weight, source: r.source, createdAt: r.createdAt }));
|
||||
return rows.map(r => ({
|
||||
id: r.id,
|
||||
weight: r.weight,
|
||||
source: r.source,
|
||||
createdAt: r.createdAt
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新体重记录
|
||||
*/
|
||||
async updateWeightRecord(userId: string, recordId: number, updateData: { weight: number; source?: WeightUpdateSource }) {
|
||||
const t = await this.sequelize.transaction();
|
||||
try {
|
||||
// 查找并验证体重记录是否存在且属于当前用户
|
||||
const weightRecord = await this.userWeightHistoryModel.findOne({
|
||||
where: { id: recordId, userId },
|
||||
transaction: t,
|
||||
});
|
||||
|
||||
if (!weightRecord) {
|
||||
throw new NotFoundException('体重记录不存在');
|
||||
}
|
||||
|
||||
const oldWeight = weightRecord.weight;
|
||||
const oldSource = weightRecord.source;
|
||||
|
||||
// 更新体重记录
|
||||
await weightRecord.update({
|
||||
weight: updateData.weight,
|
||||
source: updateData.source || weightRecord.source,
|
||||
}, { transaction: t });
|
||||
|
||||
// 如果这是最新的体重记录,同时更新用户档案中的体重
|
||||
const latestRecord = await this.userWeightHistoryModel.findOne({
|
||||
where: { userId },
|
||||
order: [['created_at', 'DESC']],
|
||||
transaction: t,
|
||||
});
|
||||
|
||||
if (latestRecord && latestRecord.id === recordId) {
|
||||
const profile = await this.userProfileModel.findOne({
|
||||
where: { userId },
|
||||
transaction: t,
|
||||
});
|
||||
if (profile) {
|
||||
profile.weight = updateData.weight;
|
||||
await profile.save({ transaction: t });
|
||||
}
|
||||
}
|
||||
|
||||
await t.commit();
|
||||
|
||||
// 记录活动日志
|
||||
await this.activityLogsService.record({
|
||||
userId,
|
||||
entityType: ActivityEntityType.USER_PROFILE,
|
||||
action: ActivityActionType.UPDATE,
|
||||
entityId: recordId.toString(),
|
||||
changes: {
|
||||
weight: { from: oldWeight, to: updateData.weight },
|
||||
...(updateData.source && updateData.source !== oldSource ? { source: { from: oldSource, to: updateData.source } } : {}),
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
code: ResponseCode.SUCCESS,
|
||||
message: 'success',
|
||||
data: {
|
||||
id: weightRecord.id,
|
||||
userId: weightRecord.userId,
|
||||
weight: weightRecord.weight,
|
||||
source: weightRecord.source,
|
||||
createdAt: weightRecord.createdAt,
|
||||
updatedAt: weightRecord.updatedAt,
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
await t.rollback();
|
||||
this.logger.error(`更新体重记录失败: ${error instanceof Error ? error.message : String(error)}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除体重记录
|
||||
*/
|
||||
async deleteWeightRecord(userId: string, recordId: number): Promise<boolean> {
|
||||
const t = await this.sequelize.transaction();
|
||||
try {
|
||||
// 查找并验证体重记录是否存在且属于当前用户
|
||||
const weightRecord = await this.userWeightHistoryModel.findOne({
|
||||
where: { id: recordId, userId },
|
||||
transaction: t,
|
||||
});
|
||||
|
||||
if (!weightRecord) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const recordData = {
|
||||
id: weightRecord.id,
|
||||
weight: weightRecord.weight,
|
||||
source: weightRecord.source,
|
||||
createdAt: weightRecord.createdAt,
|
||||
};
|
||||
|
||||
// 删除体重记录
|
||||
await weightRecord.destroy({ transaction: t });
|
||||
|
||||
// 如果删除的是最新记录,需要更新用户档案中的体重为倒数第二新的记录
|
||||
const latestRecord = await this.userWeightHistoryModel.findOne({
|
||||
where: { userId },
|
||||
order: [['created_at', 'DESC']],
|
||||
transaction: t,
|
||||
});
|
||||
|
||||
const profile = await this.userProfileModel.findOne({
|
||||
where: { userId },
|
||||
transaction: t,
|
||||
});
|
||||
|
||||
if (profile) {
|
||||
if (latestRecord) {
|
||||
// 有其他体重记录,更新为最新的体重
|
||||
profile.weight = latestRecord.weight;
|
||||
} else {
|
||||
// 没有其他体重记录,清空体重字段
|
||||
profile.weight = null;
|
||||
}
|
||||
await profile.save({ transaction: t });
|
||||
}
|
||||
|
||||
await t.commit();
|
||||
|
||||
// 记录活动日志
|
||||
await this.activityLogsService.record({
|
||||
userId,
|
||||
entityType: ActivityEntityType.USER_PROFILE,
|
||||
action: ActivityActionType.DELETE,
|
||||
entityId: recordId.toString(),
|
||||
changes: recordData,
|
||||
});
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
await t.rollback();
|
||||
this.logger.error(`删除体重记录失败: ${error instanceof Error ? error.message : String(error)}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user