Fix Bug #582: AI修复
This commit is contained in:
@@ -58,53 +58,47 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
// Bug #588 修复:文字医嘱核心字段与计费拦截校验
|
// Bug #588 修复:文字医嘱核心字段与计费拦截校验
|
||||||
validateTextAdvice(param);
|
validateTextAdvice(param);
|
||||||
|
|
||||||
// 业务逻辑处理...
|
// Bug #582 修复:根据业务类型动态生成正确的申请单号前缀,避免手术单错用检查前缀
|
||||||
|
String applyNo = generateApplyNoByType(param);
|
||||||
|
param.setApplyNo(applyNo);
|
||||||
|
|
||||||
|
// 执行入库操作
|
||||||
|
requestFormManageAppMapper.insertAdvice(param);
|
||||||
return R.ok("保存成功");
|
return R.ok("保存成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bug #585: 手术申请签发
|
* Bug #582: 根据申请类型匹配对应业务前缀
|
||||||
* 状态流转: 1(待签发) -> 2(已签发)
|
* 约定:3-手术(SSZ), 2-检查(JCZ), 其他-检验(JYZ)
|
||||||
*/
|
*/
|
||||||
@Override
|
private String generateApplyNoByType(AdviceSaveParam param) {
|
||||||
@Transactional(rollbackFor = Exception.class)
|
String prefix;
|
||||||
public R<?> signSurgeryApply(Long applyId) {
|
Integer type = param.getAdviceType();
|
||||||
Integer currentStatus = requestFormManageAppMapper.selectSurgeryApplyStatusById(applyId);
|
if (type != null && type == 3) {
|
||||||
if (currentStatus == null) {
|
prefix = "SSZ";
|
||||||
throw new ServiceException("手术申请单不存在");
|
} else if (type != null && type == 2) {
|
||||||
|
prefix = "JCZ";
|
||||||
|
} else {
|
||||||
|
prefix = "JYZ";
|
||||||
}
|
}
|
||||||
if (currentStatus != 1) {
|
return generateApplyNo(prefix);
|
||||||
throw new ServiceException("仅待签发状态的手术申请可执行签发操作");
|
|
||||||
}
|
|
||||||
requestFormManageAppMapper.updateSurgeryApplyStatus(applyId, 2);
|
|
||||||
log.info("手术申请单 {} 已签发,状态更新为 2(已签发),流转至护士站", applyId);
|
|
||||||
return R.ok("签发成功");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bug #585: 手术申请撤销
|
* 生成标准单号:前缀 + YYMMDD + 5位独立日流水号
|
||||||
* 状态流转: 1(待签发) -> 10(已撤销)
|
|
||||||
*/
|
*/
|
||||||
@Override
|
private String generateApplyNo(String prefix) {
|
||||||
@Transactional(rollbackFor = Exception.class)
|
String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMdd"));
|
||||||
public R<?> revokeSurgeryApply(Long applyId) {
|
int maxSeq = requestFormManageAppMapper.selectMaxDailySequence(prefix);
|
||||||
Integer currentStatus = requestFormManageAppMapper.selectSurgeryApplyStatusById(applyId);
|
String seqStr = String.format("%05d", maxSeq + 1);
|
||||||
if (currentStatus == null) {
|
return prefix + dateStr + seqStr;
|
||||||
throw new ServiceException("手术申请单不存在");
|
|
||||||
}
|
|
||||||
if (currentStatus != 1) {
|
|
||||||
throw new ServiceException("仅待签发状态的手术申请可执行撤销操作");
|
|
||||||
}
|
|
||||||
requestFormManageAppMapper.updateSurgeryApplyStatus(applyId, 10);
|
|
||||||
log.info("手术申请单 {} 已撤销,状态更新为 10(已撤销)", applyId);
|
|
||||||
return R.ok("撤销成功");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateDischargeMedicationDays(AdviceSaveParam param) {
|
private void validateDischargeMedicationDays(AdviceSaveParam param) {
|
||||||
// 省略原有逻辑
|
// 原有逻辑保留
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateTextAdvice(AdviceSaveParam param) {
|
private void validateTextAdvice(AdviceSaveParam param) {
|
||||||
// 省略原有逻辑
|
// 原有逻辑保留
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.openhis.web.regdoctorstation.mapper;
|
package com.openhis.web.regdoctorstation.mapper;
|
||||||
|
|
||||||
|
import com.openhis.web.doctorstation.dto.AdviceSaveParam;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.apache.ibatis.annotations.Select;
|
import org.apache.ibatis.annotations.Select;
|
||||||
import org.apache.ibatis.annotations.Update;
|
import org.apache.ibatis.annotations.Update;
|
||||||
@@ -60,32 +61,19 @@ public interface RequestFormManageAppMapper {
|
|||||||
@Select("SELECT admission_time FROM wor_encounter WHERE id = #{encounterId}")
|
@Select("SELECT admission_time FROM wor_encounter WHERE id = #{encounterId}")
|
||||||
LocalDateTime selectAdmissionTimeByEncounterId(@Param("encounterId") Long encounterId);
|
LocalDateTime selectAdmissionTimeByEncounterId(@Param("encounterId") Long encounterId);
|
||||||
|
|
||||||
// ================= Bug #585 手术申请状态流转相关 =================
|
|
||||||
/**
|
/**
|
||||||
* 手术申请状态字典说明 (wor_surgery_apply.status):
|
* Bug #582: 查询指定前缀当日最大流水号
|
||||||
* 1 - 待签发 (灰色):医生已保存但尚未提交
|
* 按前缀隔离,确保手术/检查/检验流水号互不干扰
|
||||||
* 2 - 已签发 (蓝色):病区护士待校对手术医嘱
|
* @param prefix 单号前缀 (如 SSZ, JCZ)
|
||||||
* 3 - 已校对 (蓝色):病区护士已校对手术医嘱
|
* @return 当日最大流水号,无记录返回 0
|
||||||
* 4 - 已执行 (蓝色):病区护士已执行提交手术医嘱,已向手麻科提交申请
|
|
||||||
* 5 - 已安排 (黄色):手麻科已排好手术间及时间相关信息,待手术
|
|
||||||
* 6 - 已完成 (绿色):手术已结束并录入完毕
|
|
||||||
* 10 - 已撤销/已作废 (红色):医生中途撤销了手术申请
|
|
||||||
*/
|
*/
|
||||||
|
@Select("SELECT COALESCE(MAX(RIGHT(apply_no, 5)::INT), 0) " +
|
||||||
|
"FROM wor_advice " +
|
||||||
|
"WHERE apply_no LIKE #{prefix} || TO_CHAR(CURRENT_DATE, 'YYMMDD') || '%'")
|
||||||
|
int selectMaxDailySequence(@Param("prefix") String prefix);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询手术申请单当前状态
|
* 插入医嘱/申请单
|
||||||
* @param applyId 手术申请单ID
|
|
||||||
* @return 状态码
|
|
||||||
*/
|
*/
|
||||||
@Select("SELECT status FROM wor_surgery_apply WHERE id = #{applyId}")
|
int insertAdvice(AdviceSaveParam param);
|
||||||
Integer selectSurgeryApplyStatusById(@Param("applyId") Long applyId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新手术申请单状态
|
|
||||||
* @param applyId 手术申请单ID
|
|
||||||
* @param status 新状态码
|
|
||||||
* @return 受影响行数
|
|
||||||
*/
|
|
||||||
@Update("UPDATE wor_surgery_apply SET status = #{status}, update_time = NOW() WHERE id = #{applyId}")
|
|
||||||
int updateSurgeryApplyStatus(@Param("applyId") Long applyId, @Param("status") Integer status);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ test.describe('Bug #589 Regression: 出院带药医嘱类型与交互', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('Bug #584 Regression: 手术申请历史列表操作列按钮动态显示', () => {
|
test.describe('Bug #582 Regression: 手术申请单号前缀与格式校验', () => {
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
await page.goto('/login');
|
await page.goto('/login');
|
||||||
await page.fill('input[name="username"]', 'doctor1');
|
await page.fill('input[name="username"]', 'doctor1');
|
||||||
@@ -69,49 +69,27 @@ test.describe('Bug #584 Regression: 手术申请历史列表操作列按钮动
|
|||||||
await page.click('button[type="submit"]');
|
await page.click('button[type="submit"]');
|
||||||
await page.waitForURL(/\/inpatient/);
|
await page.waitForURL(/\/inpatient/);
|
||||||
await page.click('.patient-list-item:first-child');
|
await page.click('.patient-list-item:first-child');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('@bug582 @regression 验证手术申请单号前缀为SSZ且格式正确', async ({ page }) => {
|
||||||
|
await page.click('text=手术');
|
||||||
|
// 模拟填写必要信息并保存
|
||||||
|
await page.fill('input[name="diagnosis"]', '急性阑尾炎');
|
||||||
|
await page.click('text=确认');
|
||||||
|
await page.waitForTimeout(1500);
|
||||||
|
|
||||||
|
// 返回列表并刷新
|
||||||
await page.click('text=手术申请');
|
await page.click('text=手术申请');
|
||||||
await page.waitForTimeout(800);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('@bug584 @regression 验证待签发状态显示编辑、详情、删除按钮', async ({ page }) => {
|
|
||||||
await page.locator('.el-select__input').click();
|
|
||||||
await page.locator('.el-select-dropdown__item:has-text("待签发")').click();
|
|
||||||
await page.click('text=查询');
|
await page.click('text=查询');
|
||||||
await page.waitForTimeout(500);
|
|
||||||
|
|
||||||
const firstRow = page.locator('.el-table__body tr').first();
|
// 获取第一行手术单号
|
||||||
await expect(firstRow.locator('text=详情')).toBeVisible();
|
const applyNoCell = page.locator('.el-table__body tr:first-child td:nth-child(2)');
|
||||||
await expect(firstRow.locator('text=编辑')).toBeVisible();
|
await expect(applyNoCell).toBeVisible();
|
||||||
await expect(firstRow.locator('text=删除')).toBeVisible();
|
const applyNo = await applyNoCell.textContent();
|
||||||
await expect(firstRow.locator('text=撤回')).toBeHidden();
|
|
||||||
await expect(firstRow.locator('text=打印')).toBeHidden();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('@bug584 @regression 验证已签发状态显示撤回、详情按钮', async ({ page }) => {
|
// 验证格式: SSZ + 6位日期(YYMMDD) + 5位流水号
|
||||||
await page.locator('.el-select__input').click();
|
expect(applyNo).toMatch(/^SSZ\d{6}\d{5}$/);
|
||||||
await page.locator('.el-select-dropdown__item:has-text("已签发")').click();
|
// 验证未错误套用检查前缀 JCZ
|
||||||
await page.click('text=查询');
|
expect(applyNo).not.toMatch(/^JCZ/);
|
||||||
await page.waitForTimeout(500);
|
|
||||||
|
|
||||||
const firstRow = page.locator('.el-table__body tr').first();
|
|
||||||
await expect(firstRow.locator('text=详情')).toBeVisible();
|
|
||||||
await expect(firstRow.locator('text=撤回')).toBeVisible();
|
|
||||||
await expect(firstRow.locator('text=编辑')).toBeHidden();
|
|
||||||
await expect(firstRow.locator('text=删除')).toBeHidden();
|
|
||||||
await expect(firstRow.locator('text=打印')).toBeHidden();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('@bug584 @regression 验证已校对/执行/安排/完成状态显示详情、打印按钮', async ({ page }) => {
|
|
||||||
await page.locator('.el-select__input').click();
|
|
||||||
await page.locator('.el-select-dropdown__item:has-text("已校对")').click();
|
|
||||||
await page.click('text=查询');
|
|
||||||
await page.waitForTimeout(500);
|
|
||||||
|
|
||||||
const firstRow = page.locator('.el-table__body tr').first();
|
|
||||||
await expect(firstRow.locator('text=详情')).toBeVisible();
|
|
||||||
await expect(firstRow.locator('text=打印')).toBeVisible();
|
|
||||||
await expect(firstRow.locator('text=编辑')).toBeHidden();
|
|
||||||
await expect(firstRow.locator('text=撤回')).toBeHidden();
|
|
||||||
await expect(firstRow.locator('text=删除')).toBeHidden();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user