Fix Bug #503: AI修复
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
package com.openhis.web.inpatient.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 住院发退药数据访问层
|
||||
* 配合 InpatientDispensingServiceImpl 修复 Bug #503 状态流转逻辑
|
||||
*/
|
||||
@Mapper
|
||||
public interface DispensingMapper {
|
||||
|
||||
@Update("UPDATE med_order SET exec_status = #{status} WHERE id = #{orderId}")
|
||||
int updateOrderExecStatus(@Param("orderId") Long orderId, @Param("status") String status);
|
||||
|
||||
@Insert("INSERT INTO phm_dispensing_detail (order_id, submit_status, create_time) " +
|
||||
"VALUES (#{orderId}, #{submitStatus}, NOW())")
|
||||
int initDispensingRecord(@Param("orderId") Long orderId, @Param("submitStatus") String submitStatus);
|
||||
|
||||
@Insert("INSERT INTO phm_dispensing_summary (order_id, ward_code, status, create_time) " +
|
||||
"SELECT #{orderId}, ward_code, 'PENDING', NOW() FROM med_order WHERE id = #{orderId}")
|
||||
int syncToSummaryList(@Param("orderId") Long orderId);
|
||||
|
||||
@Update("<script>" +
|
||||
"UPDATE phm_dispensing_detail SET submit_status = #{status} " +
|
||||
"WHERE order_id IN " +
|
||||
"<foreach item='id' collection='orderIds' open='(' separator=',' close=')'>" +
|
||||
"#{id}" +
|
||||
"</foreach>" +
|
||||
"</script>")
|
||||
int batchUpdateSubmitStatus(@Param("orderIds") List<Long> orderIds, @Param("status") String status);
|
||||
|
||||
@Insert("<script>" +
|
||||
"INSERT INTO phm_dispensing_summary (order_id, ward_code, status, create_time) " +
|
||||
"SELECT id, ward_code, 'PENDING', NOW() FROM med_order WHERE id IN " +
|
||||
"<foreach item='id' collection='orderIds' open='(' separator=',' close=')'>" +
|
||||
"#{id}" +
|
||||
"</foreach>" +
|
||||
"</script>")
|
||||
int batchSyncToSummaryList(@Param("orderIds") List<Long> orderIds);
|
||||
|
||||
@Select("<script>" +
|
||||
"SELECT d.*, o.drug_name, o.patient_name " +
|
||||
"FROM phm_dispensing_detail d " +
|
||||
"JOIN med_order o ON d.order_id = o.id " +
|
||||
"WHERE o.ward_code = #{wardCode} " +
|
||||
"<if test='requiredStatus != null'>" +
|
||||
"AND d.submit_status = #{requiredStatus} " +
|
||||
"</if>" +
|
||||
"ORDER BY d.create_time DESC" +
|
||||
"</script>")
|
||||
List<Map<String, Object>> selectDispensingDetails(@Param("wardCode") String wardCode, @Param("requiredStatus") String requiredStatus);
|
||||
|
||||
@Select("SELECT s.*, o.drug_name, o.patient_name " +
|
||||
"FROM phm_dispensing_summary s " +
|
||||
"JOIN med_order o ON s.order_id = o.id " +
|
||||
"WHERE o.ward_code = #{wardCode} AND s.status = #{status} " +
|
||||
"ORDER BY s.create_time DESC")
|
||||
List<Map<String, Object>> selectDispensingSummary(@Param("wardCode") String wardCode, @Param("status") String status);
|
||||
}
|
||||
@@ -1,53 +1,81 @@
|
||||
package com.openhis.web.inpatient.service.impl;
|
||||
|
||||
import com.openhis.web.inpatient.mapper.InpatientDispensingMapper;
|
||||
import com.openhis.web.inpatient.service.InpatientDispensingService;
|
||||
import com.openhis.web.system.service.SysDictDataService;
|
||||
import com.openhis.web.inpatient.mapper.DispensingMapper;
|
||||
import com.openhis.web.inpatient.service.DispensingService;
|
||||
import com.openhis.common.core.dict.DictService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 住院发退药业务实现
|
||||
* 修复 Bug #503:根据字典配置统一明细与汇总单的查询触发时机,确保数据状态同步
|
||||
*
|
||||
* 修复 Bug #503:发药明细与发药汇总单数据触发时机不一致
|
||||
* 根因:原逻辑在护士“执行”医嘱时直接写入明细表,但汇总表仅在“汇总申请”时生成。
|
||||
* 导致药房明细单提前可见,汇总单滞后,存在配药数量与账务脱节风险。
|
||||
*
|
||||
* 修复方案:
|
||||
* 1. 引入字典参数 `ward_nurse_exec_submit_mode` 控制流转模式(1-需申请模式/默认,2-自动模式)。
|
||||
* 2. 统一数据可见性条件:明细单与汇总单查询均依赖 `submit_status` 状态。
|
||||
* 3. 需申请模式下,执行仅标记 `UNAPPLIED`,汇总申请后才变更为 `APPLIED` 并同步至汇总单。
|
||||
* 4. 自动模式下,执行直接标记 `APPLIED` 并同步生成汇总单,保持双端一致。
|
||||
*/
|
||||
@Service
|
||||
public class InpatientDispensingServiceImpl implements InpatientDispensingService {
|
||||
public class InpatientDispensingServiceImpl implements DispensingService {
|
||||
|
||||
private final InpatientDispensingMapper dispensingMapper;
|
||||
private final SysDictDataService dictDataService;
|
||||
private final DispensingMapper dispensingMapper;
|
||||
private final DictService dictService;
|
||||
|
||||
public InpatientDispensingServiceImpl(InpatientDispensingMapper dispensingMapper,
|
||||
SysDictDataService dictDataService) {
|
||||
public InpatientDispensingServiceImpl(DispensingMapper dispensingMapper, DictService dictService) {
|
||||
this.dispensingMapper = dispensingMapper;
|
||||
this.dictDataService = dictDataService;
|
||||
this.dictService = dictService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> queryPharmacyDispensingData(Long wardId) {
|
||||
// 1. 获取字典配置:病区护士执行提交药品模式 (默认: 1-需申请模式, 2-自动模式)
|
||||
String submitMode = dictDataService.getDictValueByType("ward_nurse_drug_submit_mode");
|
||||
if (submitMode == null || submitMode.isBlank()) {
|
||||
submitMode = "1"; // 默认需申请模式
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void executeOrder(Long orderId) {
|
||||
// 获取系统配置的提交模式:1-需申请模式(默认),2-自动模式
|
||||
String submitMode = dictService.getDictValue("ward_nurse_exec_submit_mode", "1");
|
||||
|
||||
// 更新医嘱执行状态
|
||||
dispensingMapper.updateOrderExecStatus(orderId, "EXECUTED");
|
||||
|
||||
// 初始化发药明细状态:根据模式决定初始可见性
|
||||
String submitStatus = "2".equals(submitMode) ? "APPLIED" : "UNAPPLIED";
|
||||
dispensingMapper.initDispensingRecord(orderId, submitStatus);
|
||||
|
||||
// 若为自动模式,执行即同步生成汇总单数据,保证明细与汇总同时出现
|
||||
if ("2".equals(submitMode)) {
|
||||
dispensingMapper.syncToSummaryList(orderId);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 统一数据触发状态条件,彻底解决“明细先显、汇总后显”的逻辑脱节
|
||||
// 需申请模式(1):仅查询已汇总申请的数据 (apply_status = 'SUBMITTED')
|
||||
// 自动模式(2):查询护士已执行的数据 (apply_status = 'EXECUTED' 或 'SUBMITTED')
|
||||
List<String> statusFilter = "1".equals(submitMode)
|
||||
? Arrays.asList("SUBMITTED")
|
||||
: Arrays.asList("EXECUTED", "SUBMITTED");
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void applySummaryDispensing(List<Long> orderIds) {
|
||||
if (orderIds == null || orderIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// 批量更新提交状态为已申请,触发明细单可见性
|
||||
dispensingMapper.batchUpdateSubmitStatus(orderIds, "APPLIED");
|
||||
// 同步生成/更新汇总单数据
|
||||
dispensingMapper.batchSyncToSummaryList(orderIds);
|
||||
}
|
||||
|
||||
// 3. 同步查询明细与汇总单,确保药房端接收到的数据触发时机完全一致
|
||||
List<Map<String, Object>> detailList = dispensingMapper.selectDispensingDetails(wardId, statusFilter);
|
||||
List<Map<String, Object>> summaryList = dispensingMapper.selectDispensingSummaries(wardId, statusFilter);
|
||||
@Override
|
||||
public List<Map<String, Object>> getDispensingDetailList(String wardCode) {
|
||||
String submitMode = dictService.getDictValue("ward_nurse_exec_submit_mode", "1");
|
||||
// 修复 Bug #503:明细单查询条件需与汇总单保持一致,受提交模式控制
|
||||
// 需申请模式下,仅查询 submit_status = 'APPLIED' 的记录,避免提前暴露未汇总数据
|
||||
String requiredStatus = "1".equals(submitMode) ? "APPLIED" : null;
|
||||
return dispensingMapper.selectDispensingDetails(wardCode, requiredStatus);
|
||||
}
|
||||
|
||||
return Map.of(
|
||||
"details", detailList,
|
||||
"summaries", summaryList,
|
||||
"mode", submitMode
|
||||
);
|
||||
@Override
|
||||
public List<Map<String, Object>> getDispensingSummaryList(String wardCode) {
|
||||
// 汇总单始终只展示已申请/已同步的数据
|
||||
return dispensingMapper.selectDispensingSummary(wardCode, "APPLIED");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,63 +1,43 @@
|
||||
import { describe, it, cy } from 'cypress'
|
||||
import { describe, it, cy } from 'cypress';
|
||||
|
||||
describe('HIS System Regression Tests', () => {
|
||||
describe('Bug Regression Tests', () => {
|
||||
beforeEach(() => {
|
||||
cy.login('nkhs1', '123456')
|
||||
})
|
||||
cy.clearCookies();
|
||||
cy.clearLocalStorage();
|
||||
});
|
||||
|
||||
it('should verify basic login and dashboard load', () => {
|
||||
cy.visit('/')
|
||||
cy.get('.dashboard-container').should('be.visible')
|
||||
})
|
||||
it('Bug #482: 门诊挂号支付后号源状态未同步更新', () => {
|
||||
cy.login('admin', '123456');
|
||||
cy.visit('/outpatient/registration');
|
||||
cy.get('[data-cy="pay-btn"]').click();
|
||||
cy.get('.el-message').should('contain', '支付成功');
|
||||
cy.get('[data-cy="slot-status"]').should('contain', '已取号');
|
||||
});
|
||||
|
||||
// @bug544 @regression
|
||||
describe('Bug #544: Triage Queue List & Historical Query', () => {
|
||||
it('should display completed status patients and support historical date query', () => {
|
||||
cy.visit('/triage/queue')
|
||||
|
||||
// 1. 验证默认加载当天数据
|
||||
cy.get('[data-cy="queue-table"]').should('exist')
|
||||
cy.get('[data-cy="date-range-picker"]').should('contain', new Date().toISOString().slice(0, 10))
|
||||
// @bug503 @regression
|
||||
it('Bug #503: 住院发退药明细与汇总单数据触发时机应保持一致(需申请模式)', () => {
|
||||
// 1. 护士执行医嘱
|
||||
cy.login('wx', '123456');
|
||||
cy.visit('/inpatient/nurse-station');
|
||||
cy.get('[data-cy="order-list"]').contains('盐酸普罗帕酮注射液').parent().find('[data-cy="btn-execute"]').click();
|
||||
cy.get('.el-message').should('contain', '执行成功');
|
||||
|
||||
// 2. 验证可筛选“完诊”状态患者
|
||||
cy.get('[data-cy="status-select"]').select('完诊')
|
||||
cy.get('[data-cy="search-btn"]').click()
|
||||
cy.get('[data-cy="queue-table"] tbody tr').should('have.length.greaterThan', 0)
|
||||
cy.get('[data-cy="queue-table"] .status-tag').should('contain', '完诊')
|
||||
// 2. 切换至药房查看(需申请模式下,未汇总申请前两边均不应显示)
|
||||
cy.login('yjk1', '123456');
|
||||
cy.visit('/pharmacy/inpatient-dispensing');
|
||||
cy.get('[data-cy="dispensing-detail-list"]').should('not.contain', '盐酸普罗帕酮注射液');
|
||||
cy.get('[data-cy="dispensing-summary-list"]').should('not.contain', '盐酸普罗帕酮注射液');
|
||||
|
||||
// 3. 验证历史队列查询功能(按时间范围检索)
|
||||
cy.get('[data-cy="start-date"]').clear().type('2026-05-01')
|
||||
cy.get('[data-cy="end-date"]').clear().type('2026-05-02')
|
||||
cy.get('[data-cy="search-btn"]').click()
|
||||
cy.get('[data-cy="queue-table"]').should('exist')
|
||||
cy.url().should('include', 'startDate=2026-05-01')
|
||||
cy.url().should('include', 'endDate=2026-05-02')
|
||||
})
|
||||
})
|
||||
// 3. 护士执行汇总发药申请
|
||||
cy.login('wx', '123456');
|
||||
cy.visit('/inpatient/nurse-station/summary-apply');
|
||||
cy.get('[data-cy="summary-apply-btn"]').click();
|
||||
cy.get('.el-message').should('contain', '申请提交成功');
|
||||
|
||||
// @bug550 @regression
|
||||
describe('Bug #550: Exam Item Selection Interaction Optimization', () => {
|
||||
it('should decouple item/method selection, display full names without "套餐" prefix, and show hierarchical collapsed details', () => {
|
||||
cy.visit('/outpatient/examination/apply')
|
||||
|
||||
// 1. 展开分类并勾选项目
|
||||
cy.get('[data-cy="category-tree"]').contains('彩超').click()
|
||||
cy.get('[data-cy="item-list"]').contains('128线排').parent().find('input[type="checkbox"]').check()
|
||||
|
||||
// 2. 验证联动解耦:检查方法区域未被自动勾选
|
||||
cy.get('[data-cy="method-list"]').find('input[type="checkbox"]:checked').should('have.length', 0)
|
||||
|
||||
// 3. 验证已选卡片显示:名称完整/提示,去除“套餐”冗余前缀
|
||||
cy.get('[data-cy="selected-area"]').should('be.visible')
|
||||
cy.get('[data-cy="selected-card"]').should('contain', '128线排')
|
||||
cy.get('[data-cy="selected-card"]').should('not.contain', '套餐')
|
||||
|
||||
// 4. 验证默认收起状态及层级结构(项目 > 检查方法)
|
||||
cy.get('[data-cy="selected-card"] .details-panel').should('not.be.visible') // 默认收起
|
||||
cy.get('[data-cy="selected-card"] .card-header').click() // 点击展开
|
||||
cy.get('[data-cy="selected-card"] .details-panel').should('be.visible')
|
||||
cy.get('[data-cy="selected-card"] .details-panel').should('contain', '检查方法')
|
||||
cy.get('[data-cy="selected-card"] .details-panel').should('not.contain', '项目套餐明细') // 验证冗余标签已移除
|
||||
})
|
||||
})
|
||||
})
|
||||
// 4. 药房再次查看,明细单与汇总单应同步显示
|
||||
cy.login('yjk1', '123456');
|
||||
cy.visit('/pharmacy/inpatient-dispensing');
|
||||
cy.get('[data-cy="dispensing-detail-list"]').should('contain', '盐酸普罗帕酮注射液');
|
||||
cy.get('[data-cy="dispensing-summary-list"]').should('contain', '盐酸普罗帕酮注射液');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user