feat: 合并 upstream/v1.3 新增功能模块(安全合并策略)

新增功能模块:
- 药房管理:住院退药、处方审核功能
- 报表管理:门诊管理报表、药房结算报表、医嘱统计报表
- 支付管理:三方对账功能
- 新增枚举类:电子处方类型、频次类型、病历状态等10个
- 新增实体类:处方审核记录、第三方支付请求、中医结算目录
- 工具类增强:年龄计算、Excel工具

合并策略:仅合并低风险新增文件,保留现有业务功能
上游版本:v1.3 (2025-03-06发版)
合并分支:merge-upstream-v1.3-0310

🤖 Auto-generated by Claude Code
This commit is contained in:
2026-03-10 18:16:23 +08:00
parent 39b608dfd0
commit fe07cee58c
116 changed files with 5406 additions and 330 deletions

View File

@@ -0,0 +1,59 @@
/*
* Copyright ©2023 CJB-CNIT Team. All rights reserved
*/
package com.openhis.web.pharmacymanage.appservice;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import com.core.common.core.domain.R;
import com.openhis.web.pharmacymanage.dto.EncounterInfoDto;
import com.openhis.web.pharmacymanage.dto.ReturnMedicineDto;
/**
* TODO:概括描述当前类的主要用途和注意事项
*
* @author zwh
* @date 2025-12-29
*/
public interface IInHospitalReturnMedicineAppService {
/**
* 页面初始化
*
* @return 初始化信息
*/
R<?> init();
/**
* 查询退药患者分页列表
*
* @param encounterInfoDto 查询条件
* @param searchKey 模糊查询关键字
* @param pageNo 当前页码
* @param pageSize 查询条数
* @param request 请求数据
* @return 退药患者分页列表
*/
R<?> getReturnMedicinePatientPage(EncounterInfoDto encounterInfoDto, String searchKey, Integer pageNo,
Integer pageSize, HttpServletRequest request);
/**
* 查询退药信息
*
* @param encounterId 就诊ID
* @param refundStatus 退药id
* @param itemTable 项目类型
* @return 退药信息
*/
R<?> getReturnMedicineInfo(Long encounterId, Integer refundStatus, String itemTable);
/**
* 退药处理
*
* @param medicineReturnList 退药清单
* @return 处理结果
*/
R<?> medicineReturn(List<ReturnMedicineDto> medicineReturnList);
}

View File

@@ -0,0 +1,62 @@
package com.openhis.web.pharmacymanage.appservice;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.core.common.core.domain.R;
import com.openhis.administration.dto.PrescriptionReviewRecordDto;
/**
* 处方审方 应用实现接口
*
* @author swb
* @date 2026/01/29
*/
public interface IPrescriptionReviewAppService {
/**
* 审方
*
* @param recordDto 处方审方记录dto
* @return 是否成功
*/
R<?> review(PrescriptionReviewRecordDto recordDto);
/**
* 查询处方审方记录
*
* @param prescriptionNoList 处方号集合
* @param reviewStatus 审核状态
* @return 处方审方记录
*/
List<PrescriptionReviewRecordDto> getPrescriptionReviewRecords(List<String> prescriptionNoList,
Integer reviewStatus);
/**
* 查询处方审核信息
*
* @param practitionerId 参与者id
* @param reviewStatus 审核状态
* @param patientName 患者姓名
* @param pageNo 当前页
* @param pageSize 每页多少条
* @param request 请求
* @return 处方审核信息
*/
R<?> getPrescriptionReviewPageInfo(Long practitionerId, Integer reviewStatus, String patientName, Integer pageNo,
Integer pageSize, HttpServletRequest request);
/**
* 导出处方审核信息
*
* @param practitionerId 参与者id
* @param reviewStatus 审核状态
* @param patientName 患者姓名
* @param request 请求
* @param response 响应
*/
void makeFile(Long practitionerId, Integer reviewStatus, String patientName, HttpServletRequest request,
HttpServletResponse response);
}

View File

@@ -0,0 +1,686 @@
/*
* Copyright ©2023 CJB-CNIT Team. All rights reserved
*/
package com.openhis.web.pharmacymanage.appservice.impl;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.exception.ServiceException;
import com.core.common.utils.AgeCalculatorUtil;
import com.core.common.utils.DateUtils;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.openhis.administration.domain.*;
import com.openhis.administration.service.*;
import com.openhis.common.constant.CommonConstants;
import com.openhis.common.constant.PromptMsgConstant;
import com.openhis.common.enums.*;
import com.openhis.common.enums.ybenums.YbInvChgType;
import com.openhis.common.enums.ybenums.YbMdtrtCertType;
import com.openhis.common.enums.ybenums.YbRxFlag;
import com.openhis.common.utils.EnumUtils;
import com.openhis.common.utils.HisQueryUtils;
import com.openhis.financial.domain.Contract;
import com.openhis.financial.domain.PaymentReconciliation;
import com.openhis.financial.service.IContractService;
import com.openhis.financial.service.IPaymentReconciliationService;
import com.openhis.medication.domain.MedicationDefinition;
import com.openhis.medication.domain.MedicationDispense;
import com.openhis.medication.domain.MedicationRequest;
import com.openhis.medication.service.IMedicationDefinitionService;
import com.openhis.medication.service.IMedicationDispenseService;
import com.openhis.medication.service.IMedicationRequestService;
import com.openhis.web.inventorymanage.appservice.impl.ReceiptApprovalAppServiceImpl;
import com.openhis.web.inventorymanage.dto.SupplyItemDetailDto;
import com.openhis.web.pharmacymanage.appservice.IInHospitalReturnMedicineAppService;
import com.openhis.web.pharmacymanage.dto.*;
import com.openhis.web.pharmacymanage.mapper.InHospitalReturnMedicineAppMapper;
import com.openhis.web.pharmacymanage.mapper.ReturnMedicineMapper;
import com.openhis.workflow.domain.DeviceDispense;
import com.openhis.workflow.domain.InventoryItem;
import com.openhis.workflow.service.IDeviceDispenseService;
import com.openhis.workflow.service.IDeviceRequestService;
import com.openhis.workflow.service.IInventoryItemService;
import com.openhis.yb.domain.ClinicSettle;
import com.openhis.yb.dto.Medical3506Param;
import com.openhis.yb.dto.MedicalInventory3511Param;
import com.openhis.yb.service.IClinicSettleService;
import com.openhis.yb.service.YbManager;
/**
* TODO:概括描述当前类的主要用途和注意事项
*
* @author zwh
* @date 2025-12-29
*/
@Service
public class InHospitalReturnMedicineAppServiceImpl implements IInHospitalReturnMedicineAppService {
@Resource
private ITraceNoManageService traceNoManageService;
@Resource
private IOrganizationService iOrganizationService;
@Resource
private IInventoryItemService iInventoryItemService;
@Resource
private InHospitalReturnMedicineAppMapper inHospitalReturnMedicineAppMapper;
@Resource
private ReturnMedicineMapper returnMedicineMapper;
@Resource
private IMedicationRequestService medicationRequestService;
@Resource
private IMedicationDispenseService medicationDispenseService;
@Resource
private IDeviceDispenseService deviceDispenseService;
@Resource
private IDeviceRequestService deviceRequestService;
@Resource
private YbManager ybService;
@Resource
private IChargeItemService iChargeItemService;
@Resource
private IPaymentReconciliationService iPaymentReconciliationService;
@Resource
private IContractService iContractService;
@Resource
private IClinicSettleService clinicSettleService;
@Resource
private IEncounterDiagnosisService encounterDiagnosisService;
@Resource
private IAccountService accountService;
@Resource
private IDeviceDefinitionService deviceDefinitionService;
@Resource
private IMedicationDefinitionService medicationDefinitionService;
@Resource
private ReceiptApprovalAppServiceImpl receiptApprovalAppService;
/**
* 获取页面初始化信息
*
* @return 初始化信息
*/
@Override
public R<?> init() {
ReturnMedicineInitDto initDto = new ReturnMedicineInitDto();
// 获取科室下拉选列表
List<Organization> organizationList =
iOrganizationService.getList(OrganizationType.DEPARTMENT.getValue(), String.valueOf(OrganizationClass.CLINIC.getValue()));
List<ReturnMedicineInitDto.DepartmentOption> organizationOptions = organizationList.stream().map(
organization -> new ReturnMedicineInitDto.DepartmentOption(organization.getId(), organization.getName()))
.collect(Collectors.toList());
// 发药状态
List<ReturnMedicineInitDto.RefundStatusOption> refundStatusOptions = new ArrayList<>();
refundStatusOptions.add(new ReturnMedicineInitDto.RefundStatusOption(DispenseStatus.PENDING_REFUND.getValue(),
DispenseStatus.PENDING_REFUND.getInfo()));
refundStatusOptions.add(new ReturnMedicineInitDto.RefundStatusOption(DispenseStatus.REFUNDED.getValue(),
DispenseStatus.REFUNDED.getInfo()));
initDto.setDepartmentOptions(organizationOptions).setRefundStatusOptions(refundStatusOptions);
return R.ok(initDto);
}
/**
* 查询退药患者分页列表
*
* @param encounterInfoDto 查询条件
* @param searchKey 模糊查询关键字
* @param pageNo 当前页码
* @param pageSize 查询条数
* @param request 请求数据
* @return 退药患者分页列表
*/
@Override
public R<?> getReturnMedicinePatientPage(EncounterInfoDto encounterInfoDto, String searchKey, Integer pageNo,
Integer pageSize, HttpServletRequest request) {
Integer refundEnum = encounterInfoDto.getRefundEnum();
encounterInfoDto.setRefundEnum(null);
// 构建查询条件
QueryWrapper<EncounterInfoDto> queryWrapper = HisQueryUtils.buildQueryWrapper(encounterInfoDto, searchKey,
new HashSet<>(Arrays.asList(CommonConstants.FieldName.PatientName, CommonConstants.FieldName.IdCard,
CommonConstants.FieldName.PatientPyStr, CommonConstants.FieldName.PatientWbStr)),
request);
// 查询退药患者分页列表
Page<EncounterInfoDto> encounterInfoPage = inHospitalReturnMedicineAppMapper.selectEncounterInfoListPage(
new Page<>(pageNo, pageSize), queryWrapper, refundEnum, DispenseStatus.PENDING_REFUND.getValue(),
DispenseStatus.REFUNDED.getValue(), EncounterClass.IMP.getValue(),
CommonConstants.TableName.MED_MEDICATION_DEFINITION, CommonConstants.TableName.ADM_DEVICE_DEFINITION);
encounterInfoPage.getRecords().forEach(encounterInfo -> {
// 性别
encounterInfo.setGenderEnum_enumText(
EnumUtils.getInfoByValue(AdministrativeGender.class, encounterInfo.getGenderEnum()));
// 年龄
encounterInfo.setAge(AgeCalculatorUtil.getAge(encounterInfo.getBirthDate()));
// 退药状态
encounterInfo
.setRefundEnum_enumText(EnumUtils.getInfoByValue(DispenseStatus.class, encounterInfo.getRefundEnum()));
});
return R.ok(encounterInfoPage);
}
/**
* 查询退药信息
*
* @param encounterId 就诊ID
* @param refundStatus 退药id
* @param itemTable 项目类型
* @return 退药信息
*/
@Override
public R<?> getReturnMedicineInfo(Long encounterId, Integer refundStatus, String itemTable) {
// 获取退药信息
List<ReturnMedicineInfoDto> returnMedicineInfoList = inHospitalReturnMedicineAppMapper.selectReturnMedicineInfo(
encounterId, CommonConstants.TableName.WOR_DEVICE_REQUEST, CommonConstants.TableName.MED_MEDICATION_REQUEST,
CommonConstants.TableName.MED_MEDICATION_DEFINITION, CommonConstants.TableName.ADM_DEVICE_DEFINITION,
itemTable, refundStatus, DispenseStatus.PENDING_REFUND.getValue(), DispenseStatus.REFUNDED.getValue());
returnMedicineInfoList.forEach(returnMedicineInfoDto -> {
// 退药状态
returnMedicineInfoDto.setRefundEnum_enumText(
EnumUtils.getInfoByValue(DispenseStatus.class, returnMedicineInfoDto.getRefundEnum()));
// 退药请求状态
returnMedicineInfoDto.setReqStatus_enumText(
EnumUtils.getInfoByValue(RequestStatus.class, returnMedicineInfoDto.getReqStatus()));
});
return R.ok(returnMedicineInfoList);
}
/**
* 退药处理
*
* @param medicineReturnList 退药清单
* @return 处理结果
*/
@Override
public R<?> medicineReturn(List<ReturnMedicineDto> medicineReturnList) {
if (medicineReturnList == null || medicineReturnList.isEmpty()) {
return R.ok();
}
// 分别处理退药与退耗材的请求
List<ReturnMedicineDto> returnMedicineList = new ArrayList<>();
List<ReturnMedicineDto> returnDeviceList = new ArrayList<>();
// 追溯码列表
List<TraceNoManage> traceNoManageList = new ArrayList<>();
TraceNoManage traceNoManage;
medicineReturnList.forEach(item -> {
switch (item.getTableName()) {
case CommonConstants.TableName.MED_MEDICATION_REQUEST -> returnMedicineList
.add(new ReturnMedicineDto().setDispenseId(item.getDispenseId()).setRequestId(item.getRequestId()));
case CommonConstants.TableName.WOR_DEVICE_REQUEST -> returnDeviceList
.add(new ReturnMedicineDto().setDispenseId(item.getDispenseId()).setRequestId(item.getRequestId()));
}
});
// 进销存参数
List<SupplyItemDetailDto> supplyItemDetailList = new ArrayList<>();
// 处理退药
// 获取药品退药id列表
List<Long> medReturnIdList = new ArrayList<>();
if (!returnMedicineList.isEmpty()) {
// 获取药品退药id列表
medReturnIdList =
returnMedicineList.stream().map(ReturnMedicineDto::getDispenseId).collect(Collectors.toList());
// 获取药品退药请求id列表
List<Long> medRequestIdList =
returnMedicineList.stream().map(ReturnMedicineDto::getRequestId).collect(Collectors.toList());
if (medReturnIdList.isEmpty()) {
throw new ServiceException("请选择要退的药品");
}
if (medRequestIdList.isEmpty()) {
throw new ServiceException("请选择要退的药品");
}
// 药品退药信息查询
List<MedicationDispense> refundMedList = medicationDispenseService.listByIds(medReturnIdList);
// 药品退药请求查询
List<MedicationRequest> refundMedRequestList = medicationRequestService.listByIds(medRequestIdList);
if (refundMedList == null || refundMedList.isEmpty()) {
throw new ServiceException("请选择要退的药品");
}
// 重复退药校验
if (refundMedList.stream().map(MedicationDispense::getStatusEnum)
.anyMatch(x -> x.equals(DispenseStatus.REFUNDED.getValue()))) {
throw new ServiceException("药品已退药,请勿重复退药");
}
// 更新退药单
for (MedicationDispense medicationDispense : refundMedList) {
// 退药状态
medicationDispense.setStatusEnum(DispenseStatus.REFUNDED.getValue());
// 退药数量
medicationDispense.setDispenseQuantity(medicationDispense.getQuantity());
// 状态变更时间
medicationDispense.setStatusChangedTime(DateUtils.getNowDate());
// 退药时间
medicationDispense.setDispenseTime(DateUtils.getNowDate());
// 退药人
medicationDispense.setPractitionerId(SecurityUtils.getLoginUser().getPractitionerId());
// 设置库存变更参数
SupplyItemDetailDto supplyItemDetailDto = new SupplyItemDetailDto();
for (MedicationRequest medicationRequest : refundMedRequestList) {
// 根据退药id查询退药请求id用于医保关联
if (medicationDispense.getMedReqId().equals(medicationRequest.getId())) {
supplyItemDetailDto.setRequestId(medicationRequest.getRefundMedicineId());
}
}
supplyItemDetailDto.setItemTable(CommonConstants.TableName.MED_MEDICATION_DEFINITION)
.setItemId(medicationDispense.getMedicationId()).setLotNumber(medicationDispense.getLotNumber());
supplyItemDetailList.add(supplyItemDetailDto);
// 追溯码表相关处理
if (medicationDispense.getTraceNo() != null) {
// 使用逗号分割追溯码并转换为List
String[] traceNoList = medicationDispense.getTraceNo().split(CommonConstants.Common.COMMA);
for (String item : traceNoList) {
traceNoManage = new TraceNoManage();
// 追溯码处理
traceNoManage.setItemTable(CommonConstants.TableName.MED_MEDICATION_DEFINITION)
// 项目id
.setItemId(medicationDispense.getMedicationId())
// 仓库类型
.setLocationTypeEnum(null)
// 仓库
.setLocationId(medicationDispense.getLocationId())
// 仓位
.setLocationStoreId(null)
// 产品批号
.setLotNumber(medicationDispense.getLotNumber())
// 追溯码
.setTraceNo(item)
// 追溯码状态
.setStatusEnum(TraceNoStatus.IN.getValue())
// 追溯码单位
.setUnitCode(medicationDispense.getUnitCode())
// 操作类型
.setOperationType(SupplyType.RETURN_MEDICATION.getValue());
traceNoManageList.add(traceNoManage);
}
}
}
// 退药更新
medicationDispenseService.updateBatchById(refundMedList);
}
// 处理退耗材
// 获取退耗材id列表
List<Long> devReturnIdList = new ArrayList<>();
if (!returnDeviceList.isEmpty()) {
// 获取退耗材id列表
devReturnIdList =
returnDeviceList.stream().map(ReturnMedicineDto::getDispenseId).collect(Collectors.toList());
// 获取退耗材请求id列表
List<Long> devRequestIdList = returnDeviceList.stream().map(ReturnMedicineDto::getRequestId).toList();
if (devReturnIdList.isEmpty()) {
throw new ServiceException("请选择要退的耗材");
}
if (devRequestIdList.isEmpty()) {
throw new ServiceException("请选择要退的耗材");
}
// 退耗材信息查询
List<DeviceDispense> refundDevList = deviceDispenseService.listByIds(devReturnIdList);
if (refundDevList == null || refundDevList.isEmpty()) {
throw new ServiceException("请选择要退的耗材");
}
// 重复退耗材校验
if (refundDevList.stream().map(DeviceDispense::getStatusEnum)
.anyMatch(x -> x.equals(DispenseStatus.REFUNDED.getValue()))) {
throw new ServiceException("耗材已退,请勿重复操作");
}
// 更新退耗材单状态
for (DeviceDispense deviceDispense : refundDevList) {
// 退药时间
deviceDispense.setDispenseTime(DateUtils.getNowDate());
// 退药数量
deviceDispense.setDispenseQuantity(deviceDispense.getQuantity());
// 退药状态
deviceDispense.setStatusEnum(DispenseStatus.REFUNDED.getValue());
// 设置库存变更参数
supplyItemDetailList
.add(new SupplyItemDetailDto().setItemTable(CommonConstants.TableName.ADM_DEVICE_DEFINITION)
.setItemId(deviceDispense.getDeviceDefId()).setLotNumber(deviceDispense.getLotNumber()));
// // 使用逗号分割追溯码并转换为List
// String[] traceNoList = deviceDispense.getTraceNo().split(CommonConstants.Common.COMMA);
// for (String item : traceNoList) {
// traceNoManage = new TraceNoManage();
// // 追溯码处理
// traceNoManage.setItemTable(CommonConstants.TableName.ADM_DEVICE_DEFINITION)
// // 项目id
// .setItemId(deviceDispense.getDeviceDefId())
// // 仓库类型
// .setLocationTypeEnum(LocationForm.PHARMACY.getValue())
// // 仓库
// .setLocationId(deviceDispense.getLocationId())
// // 产品批号
// .setLotNumber(deviceDispense.getLotNumber())
// // 追溯码
// .setTraceNo(item)
// // 追溯码状态
// .setStatusEnum(TraceNoStatus.IN.getValue())
// // 追溯码单位
// .setUnitCode(deviceDispense.getUnitCode())
// // 操作类型
// .setOperationType(SupplyType.RETURN_MEDICATION.getValue());
// traceNoManageList.add(traceNoManage);
// }
}
deviceDispenseService.updateBatchById(refundDevList);
}
// 追溯码管理表数据追加
traceNoManageService.saveBatch(traceNoManageList);
// 处理退库存
// 获取库存信息
List<UnDispenseInventoryDto> unDispenseInventoryList =
returnMedicineMapper.selectInventoryInfoList(devReturnIdList, medReturnIdList,
CommonConstants.TableName.MED_MEDICATION_DEFINITION, CommonConstants.TableName.ADM_DEVICE_DEFINITION);
// 库存待更新列表
List<InventoryItem> inventoryItemList = new ArrayList<>();
// 根据批号,发放项目,发放药房进行分组处理
Map<String, List<UnDispenseInventoryDto>> unDispenseInventoryMap =
unDispenseInventoryList.stream().collect(Collectors.groupingBy(x -> x.getItemId()
+ CommonConstants.Common.DASH + x.getLotNumber() + CommonConstants.Common.DASH + x.getLocationId()));
if (!unDispenseInventoryMap.isEmpty()) {
for (Map.Entry<String, List<UnDispenseInventoryDto>> entry : unDispenseInventoryMap.entrySet()) {
List<UnDispenseInventoryDto> inventoryList = entry.getValue();
if (!inventoryList.isEmpty()) {
// 最小单位数量
BigDecimal minQuantity = BigDecimal.ZERO;
for (UnDispenseInventoryDto unDispenseInventoryDto : inventoryList) {
BigDecimal quantity = unDispenseInventoryDto.getQuantity();
if (!unDispenseInventoryDto.getDispenseUnit()
.equals(unDispenseInventoryDto.getInventoryUnitCode())) {
// 转换为小单位进行累加
quantity =
unDispenseInventoryDto.getQuantity().multiply(unDispenseInventoryDto.getPartPercent());
}
minQuantity = minQuantity.add(quantity);
}
// 理论上不出bug的情况下以项目id批号仓库进行分组处理库存一定唯一所以get(0)
// 设置待更新的库存信息
inventoryItemList.add(new InventoryItem().setId(inventoryList.get(0).getInventoryId())
.setQuantity(inventoryList.get(0).getInventoryQuantity().add(minQuantity)));
}
}
// 库存更新
iInventoryItemService.updateBatchById(inventoryItemList);
} else {
throw new ServiceException("请检查库存信息");
}
// 处理退药医保
// 返回信息
String returnMsg = null;
List<String> uploadFailedNoList;
// 调用医保商品销售退货接口
String ybSwitch = SecurityUtils.getLoginUser().getOptionJson().getString(CommonConstants.Option.YB_SWITCH); // 医保开关
if (Whether.YES.getCode().equals(ybSwitch)) {
List<DeviceDefinition> deviceDefinitions = new ArrayList<>();
List<MedicationDefinition> medicationDefinitions = new ArrayList<>();
if (!returnMedicineList.isEmpty()) {
// 设置进销存参数
medicationDefinitions = medicationDefinitionService.listByIds(supplyItemDetailList.stream()
.filter(x -> x.getItemTable().equals(CommonConstants.TableName.MED_MEDICATION_DEFINITION))
.map(SupplyItemDetailDto::getItemId).collect(Collectors.toList()));
}
if (!returnDeviceList.isEmpty()) {
deviceDefinitions = deviceDefinitionService.listByIds(supplyItemDetailList.stream()
.filter(x -> x.getItemTable().equals(CommonConstants.TableName.ADM_DEVICE_DEFINITION))
.map(SupplyItemDetailDto::getItemId).collect(Collectors.toList()));
}
// 创建映射表,添加空集合保护
Map<Long, MedicationDefinition> medicationMap =
medicationDefinitions != null ? medicationDefinitions.stream().filter(Objects::nonNull)
.collect(Collectors.toMap(MedicationDefinition::getId, Function.identity())) : new HashMap<>();
Map<Long, DeviceDefinition> deviceMap =
deviceDefinitions != null ? deviceDefinitions.stream().filter(Objects::nonNull)
.collect(Collectors.toMap(DeviceDefinition::getId, Function.identity())) : new HashMap<>();
// 设置库存变更参数,添加完整判空
for (SupplyItemDetailDto supplyItemDetailDto : supplyItemDetailList) {
if (supplyItemDetailDto == null)
continue;
if (CommonConstants.TableName.MED_MEDICATION_DEFINITION.equals(supplyItemDetailDto.getItemTable())) {
if (supplyItemDetailDto.getItemId() != null) {
MedicationDefinition med = medicationMap.get(supplyItemDetailDto.getItemId());
if (med != null) {
supplyItemDetailDto.setItemBusNo(med.getBusNo()).setPartPercent(med.getPartPercent())
.setRxFlag(med.getRxFlag()).setYbNo(med.getYbNo());
}
}
} else if (CommonConstants.TableName.ADM_DEVICE_DEFINITION.equals(supplyItemDetailDto.getItemTable())) {
if (supplyItemDetailDto.getItemId() != null) {
DeviceDefinition dev = deviceMap.get(supplyItemDetailDto.getItemId());
if (dev != null) {
supplyItemDetailDto.setItemBusNo(dev.getBusNo()).setPartPercent(dev.getPartPercent())
.setRxFlag(dev.getRxFlag()).setYbNo(dev.getYbNo());
}
}
}
}
uploadFailedNoList = this.ybReturnIntegrated(medReturnIdList, null);
uploadFailedNoList = receiptApprovalAppService.ybInventoryIntegrated(supplyItemDetailList,
YbInvChgType.OTHER_OUT, DateUtils.getNowDate(), true);
if (uploadFailedNoList != null) {
returnMsg = "3506商品销售退货上传错误错误项目编码" + uploadFailedNoList;
} else {
returnMsg = "3506商品销售退货上传成功";
}
}
// 返回退药成功信息
return R.ok(returnMsg, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[] {"退药"}));
}
/**
* 医保退药相关进销存接口
*
* @param dispenseMedIdList 退药id列表
* @param dispenseDevIdList 退耗材id列表
* @return 上传失败的编号集合
*/
public List<String> ybReturnIntegrated(List<Long> dispenseMedIdList, List<Long> dispenseDevIdList) {
List<String> uploadFailedNoList = new ArrayList<>();
R<?> result;
if (!dispenseMedIdList.isEmpty() || !dispenseDevIdList.isEmpty()) {
// 查询退药项目相关信息
List<DispenseInventoryDto> dispenseInventoryList = returnMedicineMapper.selectReturnItemDetail(
dispenseDevIdList, dispenseMedIdList, CommonConstants.TableName.MED_MEDICATION_DEFINITION,
CommonConstants.TableName.ADM_DEVICE_DEFINITION);
for (DispenseInventoryDto dispenseInventoryDto : dispenseInventoryList) {
if (dispenseInventoryDto.getYbNo() == null) {
continue;
}
Pair<Medical3506Param, Contract> medical3506Pair = getMedical3506Param(dispenseInventoryDto);
// 如果自费则自动取省医保
Contract contract = medical3506Pair.getRight();
if (contract != null) {
if (CommonConstants.BusinessName.DEFAULT_CONTRACT_NO
.equals(medical3506Pair.getRight().getBusNo())) {
contract = null;
}
}
result = ybService.cancelMerchandise(medical3506Pair.getLeft(), contract);
if (result.getCode() != 200) {
uploadFailedNoList.add(dispenseInventoryDto.getDispenseNo());
}
}
}
return uploadFailedNoList;
}
private Pair<Medical3506Param, Contract> getMedical3506Param(DispenseInventoryDto dispenseInventoryDto) {
Medical3506Param medical3506Param = new Medical3506Param();
ChargeItem chargeItem = null;
if (CommonConstants.TableName.MED_MEDICATION_DEFINITION.equals(dispenseInventoryDto.getItemTable())) {
// 查询费用结算信息
chargeItem = iChargeItemService.getOne(new LambdaQueryWrapper<ChargeItem>()
.eq(ChargeItem::getServiceTable, CommonConstants.TableName.MED_MEDICATION_REQUEST)
.eq(ChargeItem::getServiceId, dispenseInventoryDto.getRefundId())
.eq(ChargeItem::getTenantId, SecurityUtils.getLoginUser().getTenantId()));
} else if (CommonConstants.TableName.ADM_DEVICE_DEFINITION.equals(dispenseInventoryDto.getItemTable())) {
chargeItem = iChargeItemService.getOne(new LambdaQueryWrapper<ChargeItem>()
.eq(ChargeItem::getServiceTable, CommonConstants.TableName.WOR_DEVICE_REQUEST)
.eq(ChargeItem::getServiceId, dispenseInventoryDto.getRefundId())
.eq(ChargeItem::getTenantId, SecurityUtils.getLoginUser().getTenantId()));
}
if (chargeItem == null) {
throw new ServiceException("未查询到收费项");
}
// 查询就诊诊断信息
EncounterDiagnosis encounterDiagnosis = encounterDiagnosisService.getById(chargeItem.getEncounterDiagnosisId());
if (encounterDiagnosis == null) {
throw new ServiceException("未查找到就诊诊断信息");
}
// 查询付款信息
PaymentReconciliation paymentReconciliation =
iPaymentReconciliationService.getOne(new LambdaQueryWrapper<PaymentReconciliation>()
.eq(PaymentReconciliation::getEncounterId, chargeItem.getEncounterId())
.like(PaymentReconciliation::getChargeItemIds, chargeItem.getId())
.eq(PaymentReconciliation::getStatusEnum, PaymentStatus.SUCCESS.getValue())
.eq(PaymentReconciliation::getPatientId, chargeItem.getPatientId())
.eq(PaymentReconciliation::getPaymentEnum, PaymentType.PAY.getValue()));
if (paymentReconciliation == null) {
throw new ServiceException("未查询到收费");
}
// 查询账户信息
Account account = accountService
.getOne(new LambdaQueryWrapper<Account>().eq(Account::getEncounterId, chargeItem.getEncounterId())
.eq(Account::getEncounterFlag, Whether.YES.getValue()));
if (account == null) {
throw new ServiceException("未查询到账户");
}
// 查询合同实体
Contract contract =
iContractService.getOne(new LambdaQueryWrapper<Contract>().eq(Contract::getBusNo, account.getContractNo()));
if (contract == null) {
throw new ServiceException("未查询到合同信息");
}
YbMdtrtCertType mdtrtCertType;
if (AccountType.PERSONAL_CASH_ACCOUNT.getCode().equals(account.getTypeCode())) {
mdtrtCertType = YbMdtrtCertType.MDTRT_CERT_TYPE02;
} else {
mdtrtCertType = YbMdtrtCertType.getByValue(account.getTypeCode());// 2025/05/28 该值存01/02/03
}
if (mdtrtCertType == null) {
throw new ServiceException("未查询到电子凭证");
}
// 查询就诊id
if (contract.getCategoryEnum().equals(Category.SELF.getValue())
|| contract.getCategoryEnum().equals(Category.PUBLIC.getValue())) {
medical3506Param.setMdtrtSn(dispenseInventoryDto.getEncounterNo());
} else {
ClinicSettle clinicSettle = clinicSettleService.getOne(new LambdaQueryWrapper<ClinicSettle>()
.in(ClinicSettle::getSetlId, List.of(paymentReconciliation.getYbSettleIds()))
.eq(ClinicSettle::getMedType, encounterDiagnosis.getMedTypeCode()).last(" LIMIT 1"));
if (clinicSettle != null) {
medical3506Param.setMdtrtSn(clinicSettle.getMdtrtId());
} else {
medical3506Param.setMdtrtSn(dispenseInventoryDto.getEncounterNo());
}
}
// // 查询发票信息
// Invoice invoice = iInvoiceService.getById(paymentReconciliation.getInvoiceId());
// if (invoice == null) {
// throw new ServiceException("未查询到发票信息");
// }
// 转换为JSON
JSONArray medicalTraceNo = new JSONArray();
// 获取追溯码信息
if (dispenseInventoryDto.getTraceNo() != null) {
List<String> traceNoList =
Arrays.stream(dispenseInventoryDto.getTraceNo().split(CommonConstants.Common.COMMA)).map(String::trim)
.filter(s -> !s.isEmpty()).toList();
for (String traceNo : traceNoList) {
Map<String, String> traceNoMap = new HashMap<>();
traceNoMap.put("drug_trac_codg", traceNo);
medicalTraceNo.add(traceNoMap);
}
}
medical3506Param.setMedListCodg(dispenseInventoryDto.getYbNo())
.setFixmedinsBchno(dispenseInventoryDto.getRefundId().toString())
.setFixmedinsHilistId(dispenseInventoryDto.getItemNo())
.setFixmedinsHilistName(CommonConstants.TableName.MED_MEDICATION_DEFINITION)
.setPsnCertType(mdtrtCertType.getValue()).setManuLotnum(dispenseInventoryDto.getLotNumber())
.setManuDate(dispenseInventoryDto.getProductionDate())
.setSelRetnCnt(new BigDecimal(dispenseInventoryDto.getDispenseQuantity().toString()))
.setSelRetnTime(dispenseInventoryDto.getDispenseTime()).setExpyEnd(dispenseInventoryDto.getExpirationDate())
.setDrugtracinfo(medicalTraceNo).setCertno(dispenseInventoryDto.getIdCard());
// 查看所属医院
String fixmedinsCode =
SecurityUtils.getLoginUser().getOptionJson().getString(CommonConstants.Option.FIXMEDINS_CODE);
if (dispenseInventoryDto.getPreparerName() == null && HospitalCodeEnum.CCU.getCode().equals(fixmedinsCode)) {
medical3506Param.setSelRetnOpterName(CommonConstants.CCU.DisDeviceDoctorName);
} else {
medical3506Param.setSelRetnOpterName(dispenseInventoryDto.getPreparerName());
}
if (dispenseInventoryDto.getInventoryUnitCode().equals(dispenseInventoryDto.getDispenseUnitCode())) {
medical3506Param.setTrdnFlag(Whether.YES.getCode());
} else {
medical3506Param.setTrdnFlag(Whether.NO.getCode());
}
if (YbRxFlag.IMPORTANT_HERBAL_SLICES.getCode() == dispenseInventoryDto.getRxFlag()) {
medical3506Param.setRxFlag(YbRxFlag.IMPORTANT_HERBAL_SLICES.getName());
} else if (YbRxFlag.WESTERN_AND_CHINESE_PATENT_MEDICINE.getCode() == dispenseInventoryDto.getRxFlag()) {
medical3506Param.setRxFlag(YbRxFlag.WESTERN_AND_CHINESE_PATENT_MEDICINE.getName());
} else if (YbRxFlag.SELF_PREPARED_MEDICATION.getCode() == dispenseInventoryDto.getRxFlag()) {
medical3506Param.setRxFlag(YbRxFlag.WESTERN_AND_CHINESE_PATENT_MEDICINE.getName());
}
if (CommonConstants.TableName.MED_MEDICATION_DEFINITION.equals(dispenseInventoryDto.getItemTable())) {
medical3506Param.setFixmedinsHilistName(CommonConstants.TableName.MED_MEDICATION_DEFINITION);
} else if (CommonConstants.TableName.ADM_DEVICE_DEFINITION.equals(dispenseInventoryDto.getItemTable())) {
medical3506Param.setFixmedinsHilistName(CommonConstants.TableName.ADM_DEVICE_DEFINITION);
}
return Pair.of(medical3506Param, contract);
}
private MedicalInventory3511Param getMedical3511Param(DispenseInventoryDto dispenseInventoryDto) {
MedicalInventory3511Param medicalInventory3511Param = new MedicalInventory3511Param();
String fixmedinsCode =
SecurityUtils.getLoginUser().getOptionJson().getString(CommonConstants.Option.FIXMEDINS_CODE);
// TODO
medicalInventory3511Param.setFixmedinsCode(fixmedinsCode).setMedinsListCodg(dispenseInventoryDto.getYbNo())
.setFixmedinsBchno(dispenseInventoryDto.getLotNumber()).setBegndate(dispenseInventoryDto.getDispenseTime())
.setEnddate(dispenseInventoryDto.getDispenseTime());
return medicalInventory3511Param;
}
}

View File

@@ -0,0 +1,266 @@
package com.openhis.web.pharmacymanage.appservice.impl;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.core.common.core.domain.R;
import com.core.common.utils.AgeCalculatorUtil;
import com.core.common.utils.NewExcelUtil;
import com.core.common.utils.SecurityUtils;
import com.core.common.utils.StringUtils;
import com.core.common.utils.bean.BeanUtils;
import com.openhis.administration.domain.PrescriptionReviewRecord;
import com.openhis.administration.dto.PrescriptionReviewRecordDto;
import com.openhis.administration.service.IPrescriptionReviewRecordService;
import com.openhis.common.enums.AdministrativeGender;
import com.openhis.common.enums.EncounterClass;
import com.openhis.common.enums.ReviewReasonEnum;
import com.openhis.common.enums.ReviewReasonableStatus;
import com.openhis.common.utils.EnumUtils;
import com.openhis.common.utils.HisQueryUtils;
import com.openhis.common.utils.PageUtils;
import com.openhis.web.doctorstation.dto.PrescriptionInfoBaseDto;
import com.openhis.web.doctorstation.dto.PrescriptionInfoDetailDto;
import com.openhis.web.doctorstation.mapper.DoctorStationMainAppMapper;
import com.openhis.web.pharmacymanage.appservice.IPrescriptionReviewAppService;
import lombok.extern.slf4j.Slf4j;
/**
* 处方审方 应用实现类
*
* @author swb
* @date 2026/1/30
*/
@Slf4j
@Service
public class PrescriptionReviewAppServiceImpl implements IPrescriptionReviewAppService {
@Autowired
IPrescriptionReviewRecordService prescriptionReviewRecordService;
@Autowired
DoctorStationMainAppMapper doctorStationMainAppMapper;
/**
* 审方
*
* @param recordDto 处方审方记录dto
* @return 是否成功
*/
@Override
public R<?> review(PrescriptionReviewRecordDto recordDto) {
if (recordDto.getEncounterId() == null) {
return R.fail("就诊id不能为空");
}
if (recordDto.getPrescriptionNo() == null) {
return R.fail("处方号不能为空");
}
if (recordDto.getReasonableFlag() == null) {
return R.fail("是否合理标识不能为空");
}
List<PrescriptionInfoDetailDto> prescriptionDetailInfo = doctorStationMainAppMapper
.getPrescriptionDetailInfo(recordDto.getPrescriptionNo(), recordDto.getEncounterId());
List<Long> requestIds = prescriptionDetailInfo.stream().map(PrescriptionInfoDetailDto::getRequestId).toList();
recordDto.setMedRequestIds(StringUtils.join(requestIds, ","));
recordDto.setPractitioner(SecurityUtils.getLoginUser().getPractitionerId());
boolean review = prescriptionReviewRecordService.review(recordDto);
if (!review) {
return R.fail("审方失败");
}
return R.ok("审方成功");
}
/**
* 获取处方审方记录列表
*
* @param prescriptionNoList 处方号集合
* @param reviewStatus 审方状态
* @return 处方审方记录列表
*/
@Override
public List<PrescriptionReviewRecordDto> getPrescriptionReviewRecords(List<String> prescriptionNoList,
Integer reviewStatus) {
List<PrescriptionReviewRecord> prescriptionReviewRecords =
prescriptionReviewRecordService.getPrescriptionReviewRecords(prescriptionNoList, null, null, reviewStatus);
return prescriptionReviewRecords.stream().map(e -> {
PrescriptionReviewRecordDto prescriptionReviewRecordDto = new PrescriptionReviewRecordDto();
prescriptionReviewRecordDto.setPractitioner(e.getPractitionerId());
BeanUtils.copyProperties(e, prescriptionReviewRecordDto);
return prescriptionReviewRecordDto;
}).toList();
}
/**
* 获取处方审方记录分页列表
*
* @param doctorId 医生id
* @param reviewStatus 审方状态
* @param patientName 患者姓名
* @param request 请求
* @return 处方审方记录分页列表
*/
public List<PrescriptionInfoBaseDto> getPrescriptionReviewInfo(Long doctorId, Integer reviewStatus,
String patientName, HttpServletRequest request) {
QueryWrapper<PrescriptionInfoBaseDto> queryWrapper =
HisQueryUtils.buildQueryWrapper(new PrescriptionInfoBaseDto().setPractitionerId(doctorId), patientName,
new HashSet<>(List.of("patient_name")), request);
List<PrescriptionInfoBaseDto> prescriptionInfos =
doctorStationMainAppMapper.getPrescriptionInfos(queryWrapper, EncounterClass.AMB.getValue());
// 处方列表为空时直接返回空集合
if (prescriptionInfos == null || prescriptionInfos.isEmpty()) {
return List.of();
}
// 处方号列表
List<String> prescriptionNoList =
prescriptionInfos.stream().map(PrescriptionInfoBaseDto::getPrescriptionNo).toList();
// 本次就诊的处方信息
List<PrescriptionInfoDetailDto> prescriptionDetailInfo =
doctorStationMainAppMapper.getPrescriptionDetailInfoByPrescriptionNo(prescriptionNoList);
for (PrescriptionInfoBaseDto infoBaseDto : prescriptionInfos) {
// 性别
infoBaseDto.setGenderEnum_enumText(
EnumUtils.getInfoByValue(AdministrativeGender.class, infoBaseDto.getGenderEnum()));
// 计算年龄
infoBaseDto
.setAge(infoBaseDto.getBirthDate() != null ? AgeCalculatorUtil.getAge(infoBaseDto.getBirthDate()) : "");
// 处方单详情
List<PrescriptionInfoDetailDto> prescriptionInfoDetailList = prescriptionDetailInfo.stream()
.filter(e -> infoBaseDto.getPrescriptionNo().equals(e.getPrescriptionNo()))
.collect(Collectors.toList());
infoBaseDto.setPrescriptionInfoDetailList(prescriptionInfoDetailList);
}
if (!prescriptionInfos.isEmpty()) {
List<PrescriptionReviewRecordDto> prescriptionReviewRecords =
getPrescriptionReviewRecords(prescriptionNoList, reviewStatus);
if (reviewStatus != null) {
// 处方审方记录
if (prescriptionReviewRecords != null && !prescriptionReviewRecords.isEmpty()) {
List<String> prescriptionNos =
prescriptionReviewRecords.stream().map(PrescriptionReviewRecordDto::getPrescriptionNo).toList();
// 根据是否合理筛选
prescriptionInfos = prescriptionInfos.stream()
.filter(e -> prescriptionNos.contains(e.getPrescriptionNo())).toList();
}
}
// 根据处方号分组
Map<String, List<PrescriptionReviewRecordDto>> prescriptionMap;
if (prescriptionReviewRecords != null && !prescriptionReviewRecords.isEmpty()) {
prescriptionMap = prescriptionReviewRecords.stream()
.collect(Collectors.groupingBy(PrescriptionReviewRecordDto::getPrescriptionNo));
} else {
prescriptionMap = null;
}
prescriptionInfos.forEach(record -> {
if (prescriptionMap != null && prescriptionMap.containsKey(record.getPrescriptionNo())) {
PrescriptionReviewRecordDto prescription = prescriptionMap.get(record.getPrescriptionNo()).get(0);
// 审方ID
record.setPrescriberReviewId(prescription.getId());
// 审方人
record.setReviewer(prescription.getPractitioner());
// 是否合理
record.setIsReasonable(prescription.getReasonableFlag());
// 存在问题
record.setReasonEnum(prescription.getReasonEnum());
record.setReasonEnum_enumText(ReviewReasonEnum.getByValue(prescription.getReasonEnum()));
// 其他问题
record.setReason(prescription.getReasonText());
} else {
// 是否合理:设置为待点评
record.setIsReasonable(ReviewReasonableStatus.TO_BE_COMMENTED.getValue());
// 审方人
// record.setReviewer(SecurityUtils.getLoginUser().getPractitionerId());
}
List<PrescriptionInfoDetailDto> detailList = record.getPrescriptionInfoDetailList();
if (detailList != null && !detailList.isEmpty()) {
// 基药数量
int baseDrugQuantity = detailList.stream().filter(e -> e.getBasicFlag() == 1).toList().size();
// 抗菌药数量
int antibioticQuantity =
detailList.stream().filter(e -> e.getAntibioticFlag() == 1).toList().size();
// 注射剂数量
int injectionQuantity = detailList.stream().filter(e -> e.getInjectFlag() == 1).toList().size();
// 是否包含抗菌药
boolean antibioticFlag = antibioticQuantity > 0;
// 是否包含注射剂
boolean injectFlag = injectionQuantity > 0;
// 药品品种数量
int drugVarietyQuantity = detailList.stream()
.collect(Collectors.groupingBy(PrescriptionInfoDetailDto::getAdviceName)).size();
// 处方总金额
BigDecimal totalAmount = detailList.stream().map(PrescriptionInfoDetailDto::getTotalPrice)
.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
// 是否包含注射药品
record.setIsIncludeInjections(injectFlag);
// 是否包含抗生素
record.setIsContainAntibiotics(antibioticFlag);
// 基药数量
record.setBaseDrugQuantity(baseDrugQuantity);
// 抗菌药数量
record.setAntibioticQuantity(antibioticQuantity);
// 注射剂数量
record.setInjectionQuantity(injectionQuantity);
// 药品品种数量
record.setDrugVarietyQuantity(drugVarietyQuantity);
// 处方总金额
record.setTotalAmount(totalAmount);
}
});
}
return prescriptionInfos;
}
/**
* 查询处方审核信息(分页)
*
* @param doctorId 医生id
* @param reviewStatus 审核状态
* @param patientName 患者姓名
* @param pageNo 当前页
* @param pageSize 每页多少条
* @param request 请求
* @return 处方审核信息
*/
@Override
public R<?> getPrescriptionReviewPageInfo(Long doctorId, Integer reviewStatus, String patientName, Integer pageNo,
Integer pageSize, HttpServletRequest request) {
List<PrescriptionInfoBaseDto> prescriptionInfos =
getPrescriptionReviewInfo(doctorId, reviewStatus, patientName, request);
prescriptionInfos.sort(Comparator.comparing(PrescriptionInfoBaseDto::getRequestTime).reversed());
return R.ok(PageUtils.buildPage(prescriptionInfos, pageNo, pageSize));
}
/**
* 导出处方审核信息
*
* @param doctorId 医生id
* @param reviewStatus 审核状态
* @param patientName 患者姓名
* @param request 请求
* @param response 响应
*/
@Override
public void makeFile(Long doctorId, Integer reviewStatus, String patientName, HttpServletRequest request,
HttpServletResponse response) {
List<PrescriptionInfoBaseDto> prescriptionInfos =
getPrescriptionReviewInfo(doctorId, reviewStatus, patientName, request);
if (prescriptionInfos != null && !prescriptionInfos.isEmpty()) {
try {
NewExcelUtil<PrescriptionInfoBaseDto> excelUtil = new NewExcelUtil<>(PrescriptionInfoBaseDto.class);
excelUtil.exportExcel(response, prescriptionInfos, "处方审核信息");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright ©2023 CJB-CNIT Team. All rights reserved
*/
package com.openhis.web.pharmacymanage.controller;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.*;
import com.core.common.core.domain.R;
import com.openhis.web.pharmacymanage.appservice.IInHospitalReturnMedicineAppService;
import com.openhis.web.pharmacymanage.dto.EncounterInfoDto;
import com.openhis.web.pharmacymanage.dto.ReturnMedicineDto;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
* TODO:概括描述当前类的主要用途和注意事项
*
* @author zwh
* @date 2025-12-29
*/
@RestController
@RequestMapping("/pharmacy-manage/inHospital-return-medicine")
@Slf4j
@AllArgsConstructor
public class InHospitalReturnMedicineController {
@Resource
public IInHospitalReturnMedicineAppService inHospitalReturnMedicineAppService;
/**
* 获取页面初始化信息
*
* @return 初始化信息
*/
@GetMapping(value = "/init")
public R<?> returnMedicineInit() {
return inHospitalReturnMedicineAppService.init();
}
/**
* 查询退药患者分页列表
*
* @param encounterInfoDto 查询条件
* @param searchKey 模糊查询关键字
* @param pageNo 当前页码
* @param pageSize 查询条数
* @param request 请求数据
* @return 退药患者分页列表
*/
@GetMapping(value = "/return-patient-page")
public R<?> getReturnMedicinePatientPage(EncounterInfoDto encounterInfoDto,
@RequestParam(value = "searchKey", defaultValue = "") String searchKey,
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest request) {
return inHospitalReturnMedicineAppService.getReturnMedicinePatientPage(encounterInfoDto, searchKey, pageNo,
pageSize, request);
}
/**
* 查询退药信息
*
* @param encounterId 就诊ID
* @param refundStatus 退药id
* @param itemTable 项目类型
* @return 退药信息
*/
@GetMapping("/medicine-return-list")
public R<?> getReturnMedicineInfo(@RequestParam Long encounterId, @RequestParam Integer refundStatus,
String itemTable) {
return inHospitalReturnMedicineAppService.getReturnMedicineInfo(encounterId, refundStatus, itemTable);
}
/**
* 退药处理
*
* @param medicineReturnList 退药清单
* @return 处理结果
*/
@PutMapping("/medicine-return")
public R<?> medicineReturn(@RequestBody List<ReturnMedicineDto> medicineReturnList) {
return inHospitalReturnMedicineAppService.medicineReturn(medicineReturnList);
}
}

View File

@@ -0,0 +1,80 @@
package com.openhis.web.pharmacymanage.controller;
/**
* 处方审方Controller
*
* @author swb
* @date 2026/1/30
*/
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.core.common.core.domain.R;
import com.openhis.administration.dto.PrescriptionReviewRecordDto;
import com.openhis.web.pharmacymanage.appservice.IPrescriptionReviewAppService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
* 处方审方Controller
*/
@RestController
@RequestMapping("/pharmacy-manage/prescription-review")
@Slf4j
@AllArgsConstructor
public class PrescriptionReviewController {
@Autowired
private IPrescriptionReviewAppService prescriptionReviewAppService;
/**
* 审方
*
* @param recordDto 审方记录dto
* @return 是否成功
*/
@PostMapping("/review")
public R<?> review(@RequestBody PrescriptionReviewRecordDto recordDto) {
return prescriptionReviewAppService.review(recordDto);
}
/**
* 查询处方审核信息
*
* @param practitionerId 参与者id
* @param reviewStatus 审核状态
* @param patientName 患者姓名
* @param pageNo 当前页
* @param pageSize 每页多少条
* @param request 请求
* @return 处方审核信息
*/
@GetMapping(value = "/info")
public R<?> getPrescriptionReviewInfo(@RequestParam(required = false) Long practitionerId,
@RequestParam(required = false) Integer reviewStatus, @RequestParam(required = false) String patientName,
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest request) {
return prescriptionReviewAppService.getPrescriptionReviewPageInfo(practitionerId, reviewStatus, patientName,
pageNo, pageSize, request);
}
/**
* 处方点评导出
*
* @param practitionerId 参与者id
* @param reviewStatus 审核状态
* @param patientName 患者姓名
* @param request 请求
* @param response 响应
*/
@GetMapping(value = "/export")
public void makeFile(@RequestParam(required = false) Long practitionerId,
@RequestParam(required = false) Integer reviewStatus, @RequestParam(required = false) String patientName,
HttpServletRequest request, HttpServletResponse response) {
prescriptionReviewAppService.makeFile(practitionerId, reviewStatus, patientName, request, response);
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright ©2023 CJB-CNIT Team. All rights reserved
*/
package com.openhis.web.pharmacymanage.dto;
import java.util.Date;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 农大门诊配/发药 参数类
*
*/
@Data
@Accessors(chain = true)
public class JlauDispenseParam {
/**
* 配/发药信息
*/
private List<DispenseItemDto> dispenseMedicineList;
/**
* UI选择的发药时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date dispenseTime;
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright ©2023 CJB-CNIT Team. All rights reserved
*/
package com.openhis.web.pharmacymanage.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.openhis.web.pharmacymanage.dto.EncounterInfoDto;
import com.openhis.web.pharmacymanage.dto.ReturnMedicineInfoDto;
/**
* TODO:概括描述当前类的主要用途和注意事项
*
* @author zwh
* @date 2025-12-29
*/
@Repository
public interface InHospitalReturnMedicineAppMapper {
/**
* 查询退药患者分页列表
*
* @param page 分页
* @param queryWrapper 查询条件
* @param refundStatus 退药状态
* @param pendingRefund 退药状态:待退药
* @param refunded 退药状态:已退药
* @param imp 患者类型:住院
* @param medMedicationDefinition 药品表
* @param admDeviceDefinition 耗材表
* @return 退药患者分页列表
*/
Page<EncounterInfoDto> selectEncounterInfoListPage(@Param("page") Page<EncounterInfoDto> page,
@Param(Constants.WRAPPER) QueryWrapper<EncounterInfoDto> queryWrapper,
@Param("refundStatus") Integer refundStatus, @Param("pendingRefund") Integer pendingRefund,
@Param("refunded") Integer refunded, @Param("imp") Integer imp,
@Param("medMedicationDefinition") String medMedicationDefinition,
@Param("admDeviceDefinition") String admDeviceDefinition);
/**
* 申请退药清单查询
*
* @param encounterId 就诊ID
* @param medMedicationRequest 药品请求表
* @param worDeviceRequest 耗材请求表
* @param medMedicationDefinition 药品表
* @param admDeviceDefinition 耗材表
* @param itemTable 项目所在表
* @param refundStatus 退药状态
* @param pendingRefund 退药状态:待退药
* @param refunded 退药状态:已退药
* @return 申请退药清单
*/
List<ReturnMedicineInfoDto> selectReturnMedicineInfo(@Param("encounterId") Long encounterId,
@Param("worDeviceRequest") String worDeviceRequest, @Param("medMedicationRequest") String medMedicationRequest,
@Param("medMedicationDefinition") String medMedicationDefinition,
@Param("admDeviceDefinition") String admDeviceDefinition, @Param("itemTable") String itemTable,
@Param("refundStatus") Integer refundStatus, @Param("pendingRefund") Integer pendingRefund,
@Param("refunded") Integer refunded);
}