bug 349 350 351 354 356 357

This commit is contained in:
Ranyunqiao
2026-04-13 12:10:22 +08:00
parent 13e83e0c82
commit 49eed7c784
10 changed files with 227 additions and 63 deletions

View File

@@ -134,7 +134,7 @@ public class DoctorScheduleAppServiceImpl implements IDoctorScheduleAppService {
if (poolSaved) {
// 创建号源槽
List<ScheduleSlot> slots = createScheduleSlots(pool.getId().intValue(), newSchedule.getLimitNumber(),
List<ScheduleSlot> slots = createScheduleSlots(pool.getId(), newSchedule.getLimitNumber(),
newSchedule.getStartTime(), newSchedule.getEndTime());
boolean slotsSaved = scheduleSlotService.saveBatch(slots);
@@ -224,7 +224,7 @@ public class DoctorScheduleAppServiceImpl implements IDoctorScheduleAppService {
if (poolSaved) {
// 创建号源槽
List<ScheduleSlot> slots = createScheduleSlots(pool.getId().intValue(), newSchedule.getLimitNumber(),
List<ScheduleSlot> slots = createScheduleSlots(pool.getId(), newSchedule.getLimitNumber(),
newSchedule.getStartTime(), newSchedule.getEndTime());
boolean slotsSaved = scheduleSlotService.saveBatch(slots);
@@ -384,7 +384,7 @@ public class DoctorScheduleAppServiceImpl implements IDoctorScheduleAppService {
/**
* 创建号源槽
*/
private List<ScheduleSlot> createScheduleSlots(Integer poolId, Integer limitNumber, LocalTime startTime,
private List<ScheduleSlot> createScheduleSlots(Long poolId, Integer limitNumber, LocalTime startTime,
LocalTime endTime) {
List<ScheduleSlot> slots = new ArrayList<>();
@@ -514,7 +514,7 @@ public class DoctorScheduleAppServiceImpl implements IDoctorScheduleAppService {
.in("pool_id", poolIds));
if (ObjectUtil.isNotEmpty(slots)) {
List<Integer> slotIds = slots.stream().map(ScheduleSlot::getId)
List<Long> slotIds = slots.stream().map(ScheduleSlot::getId)
.collect(java.util.stream.Collectors.toList());
// 3. 逻辑删除所有号源槽
scheduleSlotService.removeByIds(slotIds);

View File

@@ -581,8 +581,33 @@ public class ConsultationAppServiceImpl implements IConsultationAppService {
.collect(Collectors.groupingBy(Practitioner::getOrgId));
// 构建树形结构
// 过滤条件:科室分类只要包含"门诊(编码1)"或"住院(编码2)"其一,即可显示
List<DepartmentTreeDto> treeList = new ArrayList<>();
for (Organization dept : deptList) {
// 过滤科室:只显示包含门诊(1)或住院(2)分类的科室
String classEnum = dept.getClassEnum();
boolean needShow = false;
if (classEnum != null && !classEnum.isEmpty()) {
// 拆分分类编码,检查是否包含 1 或 2
String[] codes = classEnum.split(",");
for (String code : codes) {
code = code.trim();
if ("1".equals(code) || "2".equals(code)) {
needShow = true;
break;
}
}
} else {
// 如果没有分类,默认显示
needShow = true;
}
if (!needShow) {
// 既不包含门诊也不包含住院,跳过
continue;
}
DepartmentTreeDto treeDto = new DepartmentTreeDto();
treeDto.setId(dept.getId());
treeDto.setLabel(dept.getName());
@@ -599,11 +624,10 @@ public class ConsultationAppServiceImpl implements IConsultationAppService {
})
.collect(Collectors.toList());
treeDto.setChildren(children);
} else {
treeDto.setChildren(new ArrayList<>());
// 只添加有医生的科室
treeList.add(treeDto);
}
treeList.add(treeDto);
// 没有医生的科室不添加到列表中
}
@@ -1340,9 +1364,13 @@ public class ConsultationAppServiceImpl implements IConsultationAppService {
throw new IllegalArgumentException("会诊申请不存在");
}
// 只有已提交状态才能确认
if (request.getConsultationStatus() != ConsultationStatusEnum.SUBMITTED.getCode()) {
throw new IllegalArgumentException("只有已提交状态的会诊申请才能确认");
// 会诊必须处于已提交或已确认状态才能确认
// - 已提交(10):还没有医生确认
// - 已确认(20):已有部分医生确认,允许其他医生继续确认(每个医生独立确认,类似已读)
// - 已签名(30)或已完成(40):不能再确认
if (request.getConsultationStatus() != null &&
request.getConsultationStatus() >= ConsultationStatusEnum.SIGNED.getCode()) {
throw new IllegalArgumentException("会诊已签名或完成,无法再确认");
}
// 2. 获取当前登录医生信息
@@ -1360,26 +1388,20 @@ public class ConsultationAppServiceImpl implements IConsultationAppService {
throw new IllegalArgumentException("您不在被邀请的医生列表中");
}
log.info("会诊确认检查currentPhysicianId={}, invitedId={}, invitedStatus={}, CONFIRMED.code={}",
currentPhysicianId, invited.getId(), invited.getInvitedStatus(), ConsultationStatusEnum.CONFIRMED.getCode());
if (invited.getInvitedStatus() != null && invited.getInvitedStatus() >= ConsultationStatusEnum.CONFIRMED.getCode()) {
throw new IllegalArgumentException("您已经确认过了,无需重复确认");
}
// 4. 更新邀请记录(存储会诊意见)
// 格式:科室-会诊确认参加医师:意见内容
// 兼容:若前端未填写“会诊确认参加医师”,则回退为当前医生姓名
String confirmingPhysicianText =
StringUtils.hasText(dto.getConfirmingPhysician()) ? dto.getConfirmingPhysician().trim() : currentPhysicianName;
String formattedOpinion = String.format("%s-%s%s",
currentDeptName,
confirmingPhysicianText,
dto.getConsultationOpinion());
// 直接存储用户输入的原始意见内容,不添加医师姓名前缀
invited.setInvitedStatus(ConsultationStatusEnum.CONFIRMED.getCode()); // 已确认
invited.setConfirmOpinion(formattedOpinion);
invited.setConfirmOpinion(dto.getConsultationOpinion()); // 直接存储原始意见,不添加前缀
invited.setConfirmTime(new Date());
consultationInvitedMapper.updateById(invited);
log.info("医生 {} 确认会诊,意见:{}", currentPhysicianName, formattedOpinion);
log.info("医生 {} 确认会诊", currentPhysicianName);
// 5. 更新会诊申请的确认计数
Integer confirmedCount = (request.getConfirmedCount() == null ? 0 : request.getConfirmedCount()) + 1;

View File

@@ -599,27 +599,40 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
}
}
// 药品前端adviceType=1
// 药品前端adviceType=1=西药, 2=中成药 → 都属于药品后端分类
List<AdviceSaveDto> medicineList = adviceSaveList.stream()
.filter(e -> ItemType.MEDICINE.getValue().equals(e.getAdviceType())
|| e.getAdviceType() == 1).collect(Collectors.toList());
.filter(e -> ItemType.MEDICINE.getValue().equals(e.getAdviceType())
|| e.getAdviceType() == 1
|| e.getAdviceType() == 2) // 前端中成药类型值为2 → 也属于药品分类
.collect(Collectors.toList());
// 耗材前端adviceType=4后端ItemType.DEVICE=2
List<AdviceSaveDto> deviceList = adviceSaveList.stream()
.filter(e -> ItemType.DEVICE.getValue().equals(e.getAdviceType())
.filter(e -> ItemType.DEVICE.getValue().equals(e.getAdviceType())
|| e.getAdviceType() == 4) // 前端耗材类型值为4
.collect(Collectors.toList());
// 诊疗活动前端adviceType=3诊疗、adviceType=5会诊、adviceType=6手术
// 诊疗活动前端adviceType=3诊疗、adviceType=5会诊、adviceType=6手术、adviceType=23检查 → 都属于诊疗后端分类
List<AdviceSaveDto> activityList = adviceSaveList.stream()
.filter(e -> ItemType.ACTIVITY.getValue().equals(e.getAdviceType())
.filter(e -> ItemType.ACTIVITY.getValue().equals(e.getAdviceType())
|| e.getAdviceType() == 3 // 前端诊疗类型值为3
|| e.getAdviceType() == 5 // 前端会诊类型值为5
|| ItemType.SURGERY.getValue().equals(e.getAdviceType())) // 🔧 BugFix#318: 手术类型值为6
|| e.getAdviceType() == 6 // 前端手术类型值为6
|| e.getAdviceType() == 23 // 前端检查类型值为23
|| ItemType.SURGERY.getValue().equals(e.getAdviceType())) // 后端手术类型值为6
.collect(Collectors.toList());
// 🔍 Debug日志: 记录分类结果
log.info("BugFix#219: 医嘱分类完成 - 药品:{}, 耗材:{}, 诊疗:{}",
// 🔍 Debug日志日志: 记录分类结果
log.info("BugFix#219: 医嘱分类完成 - 药品:{}, 耗材:{}, 诊疗:{}",
medicineList.size(), deviceList.size(), activityList.size());
// 🔍 Debug日志: 打印所有医嘱的adviceType
for (AdviceSaveDto dto : adviceSaveList) {
log.info("BugFix#219: 医嘱详情 - adviceType:{}, requestId:{}, adviceName:{}, dbOpType:{}",
dto.getAdviceType(), dto.getRequestId(),
dto.getContentJson() != null && dto.getContentJson().contains("adviceName")
? dto.getContentJson().substring(0, Math.min(100, dto.getContentJson().length()))
: "N/A",
dto.getDbOpType());
}
// 统计各类删除操作
long medDeleteCount = medicineList.stream().filter(e -> DbOpType.DELETE.getCode().equals(e.getDbOpType())).count();
@@ -679,19 +692,114 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
// 签发时,把草稿状态的账单更新为待收费
if (AdviceOpType.SIGN_ADVICE.getCode().equals(adviceOpType) && !adviceSaveList.isEmpty()) {
// 签发的医嘱id集合
// 签发的医嘱id集合 - 收集所有需要签发的医嘱ID
List<Long> requestIds = adviceSaveList.stream()
.filter(e -> !DbOpType.DELETE.getCode().equals(e.getDbOpType()) && e.getRequestId() != null)
.collect(Collectors.toList()).stream().map(AdviceSaveDto::getRequestId)
.collect(Collectors.toList());
// 🔧 BugFix: 批量更新药品请求状态为已签发(ACTIVE=2)
if (!requestIds.isEmpty() && !medicineList.isEmpty()) {
List<Long> medicineIds = medicineList.stream()
.filter(e -> !DbOpType.DELETE.getCode().equals(e.getDbOpType()) && e.getRequestId() != null)
.map(AdviceSaveDto::getRequestId)
.collect(Collectors.toList());
if (!medicineIds.isEmpty()) {
log.info("BugFix: 准备批量更新药品医嘱状态medicineIds={}", medicineIds);
UpdateWrapper<MedicationRequest> updateWrapper = new UpdateWrapper<>();
updateWrapper.in("id", medicineIds);
updateWrapper.set("status_enum", RequestStatus.ACTIVE.getValue());
boolean updateResult = iMedicationRequestService.update(null, updateWrapper);
log.info("BugFix: 批量更新药品医嘱状态为已签发count={}, result={}", medicineIds.size(), updateResult);
// 🔧 BugFix: 如果批量更新失败,尝试逐个更新
if (!updateResult) {
log.warn("BugFix: 批量更新药品医嘱状态失败,尝试逐个更新");
for (Long medicineId : medicineIds) {
try {
MedicationRequest updateReq = new MedicationRequest();
updateReq.setId(medicineId);
updateReq.setStatusEnum(RequestStatus.ACTIVE.getValue());
boolean singleResult = iMedicationRequestService.updateById(updateReq);
log.info("BugFix: 逐个更新药品医嘱状态id={}, result={}", medicineId, singleResult);
} catch (Exception e) {
log.error("BugFix: 逐个更新药品医嘱状态失败id={}", medicineId, e);
}
}
}
}
}
// 🔧 BugFix: 批量更新耗材请求状态为已签发(ACTIVE=2)
if (!requestIds.isEmpty() && !deviceList.isEmpty()) {
List<Long> deviceIds = deviceList.stream()
.filter(e -> !DbOpType.DELETE.getCode().equals(e.getDbOpType()) && e.getRequestId() != null)
.map(AdviceSaveDto::getRequestId)
.collect(Collectors.toList());
if (!deviceIds.isEmpty()) {
log.info("BugFix: 准备批量更新耗材医嘱状态deviceIds={}", deviceIds);
UpdateWrapper<DeviceRequest> updateWrapper = new UpdateWrapper<>();
updateWrapper.in("id", deviceIds);
updateWrapper.set("status_enum", RequestStatus.ACTIVE.getValue());
boolean updateResult = iDeviceRequestService.update(null, updateWrapper);
log.info("BugFix: 批量更新耗材医嘱状态为已签发count={}, result={}", deviceIds.size(), updateResult);
// 🔧 BugFix: 如果批量更新失败,尝试逐个更新
if (!updateResult) {
log.warn("BugFix: 批量更新耗材医嘱状态失败,尝试逐个更新");
for (Long deviceId : deviceIds) {
try {
DeviceRequest updateReq = new DeviceRequest();
updateReq.setId(deviceId);
updateReq.setStatusEnum(RequestStatus.ACTIVE.getValue());
boolean singleResult = iDeviceRequestService.updateById(updateReq);
log.info("BugFix: 逐个更新耗材医嘱状态id={}, result={}", deviceId, singleResult);
} catch (Exception e) {
log.error("BugFix: 逐个更新耗材医嘱状态失败id={}", deviceId, e);
}
}
}
}
}
// 🔧 BugFix: 批量更新诊疗请求状态为已签发(ACTIVE=2)
if (!requestIds.isEmpty() && !activityList.isEmpty()) {
List<Long> activityIds = activityList.stream()
.filter(e -> !DbOpType.DELETE.getCode().equals(e.getDbOpType()) && e.getRequestId() != null)
.map(AdviceSaveDto::getRequestId)
.collect(Collectors.toList());
if (!activityIds.isEmpty()) {
log.info("BugFix: 准备批量更新诊疗医嘱状态activityIds={}", activityIds);
UpdateWrapper<ServiceRequest> updateWrapper = new UpdateWrapper<>();
updateWrapper.in("id", activityIds);
updateWrapper.set("status_enum", RequestStatus.ACTIVE.getValue());
boolean updateResult = iServiceRequestService.update(null, updateWrapper);
log.info("BugFix: 批量更新诊疗医嘱状态为已签发count={}, result={}", activityIds.size(), updateResult);
// 🔧 BugFix: 如果批量更新失败,尝试逐个更新
if (!updateResult) {
log.warn("BugFix: 批量更新诊疗医嘱状态失败,尝试逐个更新");
for (Long activityId : activityIds) {
try {
ServiceRequest updateReq = new ServiceRequest();
updateReq.setId(activityId);
updateReq.setStatusEnum(RequestStatus.ACTIVE.getValue());
boolean singleResult = iServiceRequestService.updateById(updateReq);
log.info("BugFix: 逐个更新诊疗医嘱状态id={}, result={}", activityId, singleResult);
} catch (Exception e) {
log.error("BugFix: 逐个更新诊疗医嘱状态失败id={}", activityId, e);
}
}
}
}
}
// 就诊id
Long encounterId = adviceSaveList.get(0).getEncounterId();
// 使用安全的更新方法,避免并发冲突
// 使用安全的更新方法,避免并发冲突 - 更新费用项状态
iChargeItemService.updateChargeStatusByConditionSafe(
encounterId,
ChargeItemStatus.DRAFT.getValue(),
ChargeItemStatus.PLANNED.getValue(),
encounterId,
ChargeItemStatus.DRAFT.getValue(),
ChargeItemStatus.PLANNED.getValue(),
requestIds);
}
@@ -734,11 +842,14 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
// 声明费用项
ChargeItem chargeItem;
// 新增 + 修改
// 🔧 BugFix: 如果 requestId 不为空说明是已存在的医嘱,需要更新,即使 dbOpType 不匹配也应该包含进来
List<AdviceSaveDto> insertOrUpdateList = medicineList.stream()
.filter(e -> (DbOpType.INSERT.getCode().equals(e.getDbOpType())
|| DbOpType.UPDATE.getCode().equals(e.getDbOpType())))
|| DbOpType.UPDATE.getCode().equals(e.getDbOpType())
|| e.getRequestId() != null))
.collect(Collectors.toList());
// 删除
// 🔧 BugFix: 如果 dbOpType 不匹配但 requestId 存在,仍然允许删除(增加健壮性)
List<AdviceSaveDto> deleteList = medicineList.stream()
.filter(e -> DbOpType.DELETE.getCode().equals(e.getDbOpType())).collect(Collectors.toList());
// 校验删除的医嘱是否已经收费
@@ -1151,9 +1262,11 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
// 声明费用项
ChargeItem chargeItem;
// 新增 + 修改
// 🔧 BugFix: 如果 requestId 不为空说明是已存在的医嘱,需要更新,即使 dbOpType 不匹配也应该包含进来
List<AdviceSaveDto> insertOrUpdateList = deviceList.stream()
.filter(e -> (DbOpType.INSERT.getCode().equals(e.getDbOpType())
|| DbOpType.UPDATE.getCode().equals(e.getDbOpType())))
|| DbOpType.UPDATE.getCode().equals(e.getDbOpType())
|| e.getRequestId() != null))
.collect(Collectors.toList());
// 删除
List<AdviceSaveDto> deleteList = deviceList.stream()
@@ -1439,9 +1552,11 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
// 声明费用项
ChargeItem chargeItem;
// 新增 + 修改
// 🔧 BugFix: 如果 requestId 不为空说明是已存在的医嘱,需要更新,即使 dbOpType 不匹配也应该包含进来
List<AdviceSaveDto> insertOrUpdateList = activityList.stream()
.filter(e -> (DbOpType.INSERT.getCode().equals(e.getDbOpType())
|| DbOpType.UPDATE.getCode().equals(e.getDbOpType())))
|| DbOpType.UPDATE.getCode().equals(e.getDbOpType())
|| e.getRequestId() != null))
.collect(Collectors.toList());
// 删除
List<AdviceSaveDto> deleteList = activityList.stream()