feat(medications): 优化药物删除功能,添加事务处理和批量操作
- 在药物删除时使用事务确保数据一致性 - 删除药物时同时软删除所有相关用药记录 - 优化删除操作性能,使用批量更新替代循环删除 - 扩展删除范围,从删除未服用记录改为删除当天所有记录 - 添加完善的错误处理和日志记录
This commit is contained in:
@@ -4,14 +4,15 @@ import {
|
|||||||
ForbiddenException,
|
ForbiddenException,
|
||||||
Logger,
|
Logger,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { InjectModel } from '@nestjs/sequelize';
|
import { InjectModel, InjectConnection } from '@nestjs/sequelize';
|
||||||
import { Medication } from './models/medication.model';
|
import { Medication } from './models/medication.model';
|
||||||
import { MedicationRecord } from './models/medication-record.model';
|
import { MedicationRecord } from './models/medication-record.model';
|
||||||
import { CreateMedicationDto } from './dto/create-medication.dto';
|
import { CreateMedicationDto } from './dto/create-medication.dto';
|
||||||
import { UpdateMedicationDto } from './dto/update-medication.dto';
|
import { UpdateMedicationDto } from './dto/update-medication.dto';
|
||||||
import { MedicationStatusEnum } from './enums/medication-status.enum';
|
import { MedicationStatusEnum } from './enums/medication-status.enum';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import { Op } from 'sequelize';
|
import { Op, Transaction } from 'sequelize';
|
||||||
|
import { Sequelize } from 'sequelize-typescript';
|
||||||
import * as dayjs from 'dayjs';
|
import * as dayjs from 'dayjs';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -26,6 +27,8 @@ export class MedicationsService {
|
|||||||
private readonly medicationModel: typeof Medication,
|
private readonly medicationModel: typeof Medication,
|
||||||
@InjectModel(MedicationRecord)
|
@InjectModel(MedicationRecord)
|
||||||
private readonly recordModel: typeof MedicationRecord,
|
private readonly recordModel: typeof MedicationRecord,
|
||||||
|
@InjectConnection()
|
||||||
|
private readonly sequelize: Sequelize,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -181,12 +184,25 @@ export class MedicationsService {
|
|||||||
* 删除药物(软删除)
|
* 删除药物(软删除)
|
||||||
*/
|
*/
|
||||||
async remove(id: string, userId: string): Promise<void> {
|
async remove(id: string, userId: string): Promise<void> {
|
||||||
|
const transaction = await this.sequelize.transaction();
|
||||||
|
|
||||||
|
try {
|
||||||
const medication = await this.findOne(id, userId);
|
const medication = await this.findOne(id, userId);
|
||||||
|
|
||||||
|
// 软删除药物
|
||||||
medication.deleted = true;
|
medication.deleted = true;
|
||||||
await medication.save();
|
await medication.save({ transaction });
|
||||||
|
|
||||||
this.logger.log(`成功删除药物 ${id}`);
|
// 软删除所有相关的用药记录
|
||||||
|
await this.deleteAllMedicationRecords(medication, transaction);
|
||||||
|
|
||||||
|
await transaction.commit();
|
||||||
|
this.logger.log(`成功删除药物 ${id} 及其所有记录`);
|
||||||
|
} catch (error) {
|
||||||
|
await transaction.rollback();
|
||||||
|
this.logger.error(`删除药物失败: ${error instanceof Error ? error.message : '未知错误'}`);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -307,52 +323,62 @@ export class MedicationsService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 删除当天未服用的药物记录
|
* 删除当天的药物记录
|
||||||
* 当药物被停用时,删除当天生成的但还未服用的记录
|
* 当药物被停用时,删除当天生成的所有记录
|
||||||
*/
|
*/
|
||||||
private async deleteTodayUntakenRecords(medication: Medication): Promise<void> {
|
private async deleteTodayUntakenRecords(medication: Medication, transaction?: Transaction): Promise<void> {
|
||||||
// 使用当前时间作为基准,查询当前时间及未来的未服用记录
|
// 获取当天的开始和结束时间
|
||||||
const now = new Date();
|
const today = dayjs().format('YYYY-MM-DD');
|
||||||
|
const todayStart = dayjs(today).startOf('day').toDate();
|
||||||
|
const todayEnd = dayjs(today).endOf('day').toDate();
|
||||||
|
|
||||||
this.logger.log(
|
this.logger.log(
|
||||||
`开始删除药物 ${medication.id} 从现在起(${dayjs(now).format('YYYY-MM-DD HH:mm')})的未服用记录`,
|
`开始删除药物 ${medication.id} 在 ${today} 的所有记录`,
|
||||||
);
|
);
|
||||||
|
|
||||||
// 查询从现在开始的所有未服用记录(状态为 UPCOMING)
|
// 使用批量更新而不是循环删除,提高性能
|
||||||
const recordsToDelete = await this.recordModel.findAll({
|
const [affectedCount] = await this.recordModel.update(
|
||||||
|
{ deleted: true },
|
||||||
|
{
|
||||||
where: {
|
where: {
|
||||||
medicationId: medication.id,
|
medicationId: medication.id,
|
||||||
userId: medication.userId,
|
userId: medication.userId,
|
||||||
status: MedicationStatusEnum.UPCOMING,
|
|
||||||
scheduledTime: {
|
scheduledTime: {
|
||||||
[Op.gte]: now, // 大于等于当前时间
|
[Op.between]: [todayStart, todayEnd], // 当天的所有记录
|
||||||
},
|
},
|
||||||
deleted: false,
|
deleted: false,
|
||||||
},
|
},
|
||||||
});
|
transaction,
|
||||||
|
}
|
||||||
this.logger.log(
|
|
||||||
`找到 ${recordsToDelete.length} 条需要删除的 ${medication.id} 记录`,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (recordsToDelete.length === 0) {
|
|
||||||
this.logger.log(`没有找到 ${medication.id} 需要删除的记录`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 软删除记录
|
|
||||||
for (const record of recordsToDelete) {
|
|
||||||
const scheduledTime = dayjs(record.scheduledTime).format('YYYY-MM-DD HH:mm');
|
|
||||||
record.deleted = true;
|
|
||||||
await record.save();
|
|
||||||
|
|
||||||
this.logger.log(
|
this.logger.log(
|
||||||
`软删除记录 ${record.id},计划时间:${scheduledTime}`,
|
`成功批量软删除了 ${affectedCount} 条 ${medication.id} 的当天记录`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除药物的所有相关记录
|
||||||
|
* 当药物被删除时,软删除所有相关的服药记录
|
||||||
|
*/
|
||||||
|
private async deleteAllMedicationRecords(medication: Medication, transaction?: Transaction): Promise<void> {
|
||||||
|
this.logger.log(`开始删除药物 ${medication.id} 的所有相关记录`);
|
||||||
|
|
||||||
|
// 使用批量更新而不是循环删除,提高性能
|
||||||
|
const [affectedCount] = await this.recordModel.update(
|
||||||
|
{ deleted: true },
|
||||||
|
{
|
||||||
|
where: {
|
||||||
|
medicationId: medication.id,
|
||||||
|
userId: medication.userId,
|
||||||
|
deleted: false,
|
||||||
|
},
|
||||||
|
transaction,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
this.logger.log(
|
this.logger.log(
|
||||||
`成功删除了 ${recordsToDelete.length} 条 ${medication.id} 的未服用记录`,
|
`成功批量软删除了 ${affectedCount} 条 ${medication.id} 的记录`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user