123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483 |
- package thyyxxk.webserver.service.zhuyuanyisheng.yizhuverify;
- import cn.hutool.core.convert.Convert;
- import cn.hutool.core.util.StrUtil;
- import cn.hutool.extra.spring.SpringUtil;
- import lombok.Getter;
- import lombok.extern.slf4j.Slf4j;
- import org.jetbrains.annotations.NotNull;
- import thyyxxk.webserver.config.envionment.YzConfig;
- import thyyxxk.webserver.constants.Capacity;
- import thyyxxk.webserver.dao.his.zhuyuanyisheng.YiZhuLuRuDao;
- import thyyxxk.webserver.entity.login.UserInfo;
- import thyyxxk.webserver.entity.yzcheck.ChargeLimitations;
- import thyyxxk.webserver.entity.zhuyuanyisheng.yizhuluru.XinZhenYiZhu;
- import thyyxxk.webserver.entity.zhuyuanyisheng.yizhuluru.XinZhenYzActOrder;
- import thyyxxk.webserver.entity.zhuyuanyisheng.yizhuluru.YzZdOrderItemConfirm;
- import thyyxxk.webserver.service.hutoolcache.ExtraCache;
- import thyyxxk.webserver.utils.*;
- import java.util.*;
- import java.util.function.Consumer;
- @Slf4j
- public class YiZhuCheckData {
- private final YiZhuLuRuDao dao;
- private final ExtraCache extraCache = SpringUtil.getBean(ExtraCache.class);
- private final YzConfig yzConfig = SpringUtil.getBean(YzConfig.class);
- /**
- * 医嘱数组
- */
- private List<XinZhenYzActOrder> list;
- /**
- * 药品
- */
- private final CacheOnce<XinZhenYzActOrder> drug = new CacheOnce<>();
- /**
- * 医生等级
- */
- private final CacheOnce<Integer> authorizedDoctorLevel = new CacheOnce<>();
- /**
- * 项目
- */
- private final CacheOnce<List<XinZhenYzActOrder>> project = new CacheOnce<>();
- /**
- * 医嘱
- */
- private final CacheOnce<XinZhenYzActOrder> yzItem = new CacheOnce<>();
- /**
- * 医保限制
- */
- private final CacheOnce<ChargeLimitations> yiBaoLimitation = new CacheOnce<>();
- /**
- * 患者信息
- */
- private XinZhenYiZhu patientInformation;
- private Boolean strictVerification = false;
- /**
- * 错误信息
- */
- List<String> errorMessage = new ArrayList<>();
- /**
- * 警告信息
- */
- List<String> warningMessage = new ArrayList<>();
- Map<String, Object> returnMap = new HashMap<>();
- private UserInfo userInfo;
- @Getter
- private Boolean passTheAudit = true;
- private final List<String> groupList = Arrays.asList("71", "73");
- private boolean checkForRestrictedMedication = false;
- /**
- * 全排斥医嘱
- */
- @Getter
- private Repel repel = null;
- private final String ONCE = "ONCE";
- public YiZhuCheckData(YiZhuLuRuDao dao) {
- this.dao = dao;
- }
- public YiZhuCheckData init(List<XinZhenYzActOrder> list, XinZhenYiZhu patientInformation) {
- userInfo = dao.selectedUserInfoByCode(TokenUtil.getInstance().getTokenUserId());
- this.list = list;
- this.patientInformation = patientInformation;
- strictVerification = patientInformation != null;
- return this;
- }
- public YiZhuCheckData init(XinZhenYzActOrder orderData, XinZhenYiZhu patientInformation) {
- List<XinZhenYzActOrder> temp = Collections.singletonList(orderData);
- init(temp, patientInformation);
- return this;
- }
- public void judgeExclusion() {
- repel = new Repel();
- }
- public Map<String, Object> startCheck(Consumer<XinZhenYzActOrder> action) {
- for (XinZhenYzActOrder item : list) {
- clearErrorMessage();
- if (strictVerification) {
- strictVerificationFunc(item);
- }
- publicCheck(item);
- String ITEM = "00";
- if (item.getSerial().equals(ITEM)) {
- itemCheck(item);
- } else {
- drugCheck(item);
- }
- if (action != null) {
- action.accept(item);
- }
- setReturnMap(item.getActOrderNo().stripTrailingZeros().toPlainString());
- }
- return getReturnMap();
- }
- /**
- * 公共校验
- *
- * @param item 医嘱
- */
- private void publicCheck(XinZhenYzActOrder item) {
- if (StringUtil.isBlank(item.getOrderCode())) {
- errorMessage.add("项目编码不能为空");
- }
- if (StringUtil.isBlank(item.getOrderName())) {
- errorMessage.add("项目名称不能为空");
- }
- if (StringUtil.isBlank(item.getExecUnit())) {
- errorMessage.add("执行科室不能为空");
- } else if (item.getExecUnit().startsWith("8")) {
- errorMessage.add("执行科室不能选择为病区");
- }
- if (StringUtil.isBlank(item.getFrequCode())) {
- errorMessage.add("频次不能为空");
- } else if (dao.getTheFrequency(item.getFrequCode()) == 0) {
- errorMessage.add("该执行频率已被停用,请更改,不然会导致无法执行。");
- }
- }
- private void itemCheck(XinZhenYzActOrder item) {
- List<XinZhenYzActOrder> projectDetails = project.get(item.getOrderCode(), dao::itemDataOne);
- XinZhenYzActOrder yzItemInio = yzItem.get(item.getOrderCode(), dao::yzItem);
- if (yzItemInio != null) {
- if (yzItemInio.getDelFlag() == 1) {
- errorMessage.add("该医嘱已被停用,请联系物价。");
- }
- }
- List<String> ZK_CODE_LIST = new ArrayList<>();
- Map<String, YzZdOrderItemConfirm> specialMedicalAdvice = new HashMap<>();
- List<YzZdOrderItemConfirm> value = extraCache.getYzZdOrderItemConfirm();
- if (value != null) {
- for (YzZdOrderItemConfirm yzCode : value) {
- if (yzCode.getItemName().equals("转科")) {
- ZK_CODE_LIST.add(yzCode.getOrderCode());
- }
- specialMedicalAdvice.put(yzCode.getOrderCode(), yzCode);
- }
- }
- if (strictVerification && specialMedicalAdvice.containsKey(item.getOrderCode())) {
- YzZdOrderItemConfirm confirm = specialMedicalAdvice.get(item.getOrderCode());
- if (confirm.getCount() > 0 && dao.selectCountByOrderCode(patientInformation.getInpatientNo(), patientInformation.getAdmissTimes(), item.getOrderCode()) > confirm.getCount()) {
- errorMessage.add("该医嘱只能开一条,请先作废上一条医嘱");
- }
- }
- if (ZK_CODE_LIST.contains(item.getOrderCode())) {
- if (StringUtil.isBlank(item.getZkWardCode())) {
- errorMessage.add("转科病房不能为空");
- }
- if (StringUtil.isBlank(item.getZkDeptCode())) {
- errorMessage.add("转科科室不能为空");
- }
- }
- // 如果这个项目下面没有费用明细,那么这就是一条口头医嘱,或者特殊医嘱
- if (ListUtil.notBlank(projectDetails)) {
- for (XinZhenYzActOrder detailed : projectDetails) {
- if (detailed.getDelFlag() == 1) {
- errorMessage.add(String.format("项目:【%s】,已经被物价停用了", detailed.getOrderName()));
- }
- if (StringUtil.isBlank(detailed.getNationalCode())) {
- warningMessage.add(String.format("项目:【%s】,没有匹配医保码", detailed.getOrderName()));
- }
- }
- }
- // 是否是排斥医嘱
- if (repel != null) {
- Integer paiChiYiZhu = dao.shiFouPaiChiYiZhu(item.getOrderCode());
- if (paiChiYiZhu != null && paiChiYiZhu.equals(1)) {
- repel.setCount(repel.getCount() + 1);
- repel.setOrderNo(item.getActOrderNo());
- repel.setDate(item.getStartTime());
- }
- if (yzConfig.getExceedingDischargeDays() != -1) {
- List<String> strings = extraCache.getYzZdOrderItemMap().get("出院");
- if (strings.contains(item.getOrderCode())) {
- Date admissDate = cn.hutool.core.date.DateUtil.beginOfDay(patientInformation.getAdmissDate());
- Date orderTime = cn.hutool.core.date.DateUtil.beginOfDay(item.getOrderTime());
- long betweenDay = cn.hutool.core.date.DateUtil.betweenDay(orderTime, admissDate, false);
- if (betweenDay <= yzConfig.getExceedingDischargeDays()) {
- if (item.getSuperiorDoctor() == null || !item.getSuperiorDoctor().equals(patientInformation.getDeptDirector())) {
- errorMessage.add("患者的住院天数小于等于4请科主任授权,开出院医嘱。");
- }
- }
- }
- }
- }
- item.setDrugOcc(item.getDrugQuan());
- }
- private void drugCheck(XinZhenYzActOrder item) {
- if (StringUtil.isBlank(item.getGroupNo())) {
- errorMessage.add("没有药房请重新开。");
- return;
- }
- if (!groupList.contains(item.getGroupNo())) {
- errorMessage.add("药房错误,请重新选择药房。");
- }
- String key = item.getOrderCode().trim() + item.getSerial().trim() + item.getGroupNo().trim();
- XinZhenYzActOrder detailsOfDrugs = getDrugData(key, item.getSupplyCode());
- if (BigUtils.bigXiaoYu(item.getDose(), 0)) {
- errorMessage.add(String.format("医嘱:【%s】,计量不能开负数", item.getOrderName()));
- }
- if (StringUtil.isBlank(item.getDrugSpecification())) {
- errorMessage.add("药品规格不能为空");
- }
- if (StringUtil.isBlank(item.getSupplyCode())) {
- errorMessage.add("给药方式不能为空");
- } else if (detailsOfDrugs.getSupplyCode() == null || "1".equals(detailsOfDrugs.getSupplyCode())) {
- errorMessage.add("给药方式已被停用。");
- }
- if (item.getDose() == null || BigUtils.dengYu(item.getDose(), 0)) {
- errorMessage.add("一次计量不能为空");
- }
- if (StringUtil.isBlank(item.getDoseUnit())) {
- errorMessage.add("计量单位不能为空");
- }
- if (StringUtil.isBlank(item.getSerial())) {
- errorMessage.add("包装大小不能为空");
- }
- if (detailsOfDrugs == null) {
- errorMessage.add("没有找到对应的药品,请联系药房。");
- return;
- }
- if (StringUtil.isBlank(item.getMiniUnit())) {
- if (item.getSerial().equals("01")) {
- item.setMiniUnit(detailsOfDrugs.getMiniUnit());
- } else {
- item.setMiniUnit(detailsOfDrugs.getPackUnit());
- }
- }
- if (detailsOfDrugs.getDelFlag() == 1) {
- errorMessage.add("药品已经被停用了,请联系药剂科");
- }
- if (detailsOfDrugs.getYpLevel() > userInfo.getDoctorLevel()) {
- Integer superiorPhysicianRank = authorizedDoctorLevel.get(item.getSuperiorDoctor(), (code) -> {
- Integer yiShenDengJi = dao.huoQuYiShenDengJi(code);
- return yiShenDengJi == null ? 0 : yiShenDengJi;
- });
- if (detailsOfDrugs.getYpLevel() > superiorPhysicianRank) {
- errorMessage.add("您没有开此药品的权限");
- }
- }
- if (StringUtil.isBlank(detailsOfDrugs.getNationalCode())) {
- warningMessage.add("该药品没有医保编码");
- }
- if (BigUtils.bigXiaoYu(detailsOfDrugs.getStockAmount(), 10)) {
- warningMessage.add(String.format("该药品剩余数量为:【%s】", detailsOfDrugs.getStockAmount().stripTrailingZeros().toPlainString()));
- }
- if (BigUtils.bigDaYu(item.getDrugQuan(), detailsOfDrugs.getStockAmount())) {
- errorMessage.add("药品领量大于药品的库存,当前库存量" + detailsOfDrugs.getStockAmount().stripTrailingZeros().toPlainString());
- }
- // 严格校验
- if (strictVerification) {
- if (detailsOfDrugs.getDeptRestrictions() > 0) {
- errorMessage.add("该药品禁止在患者所在的科室使用。");
- }
- if (detailsOfDrugs.getVisibleFlagZy() == 1) {
- errorMessage.add("该药品禁止住院患者使用。");
- }
- item.setKjywFlag(detailsOfDrugs.getKjywFlag());
- if (detailsOfDrugs.getKjywFlag() == 1) {
- if (item.getYyfs() == null) {
- errorMessage.add("请填写抗菌药物医嘱附注信息录入");
- } else if (item.getYyfs() == 1 || item.getYyfs() == 2) {
- if (item.getSsqk() == null) {
- errorMessage.add("当用药方式为 1 或 2 时,手术切口和用药时间不能为空");
- }
- }
- }
- // 校验医保限制用药(item);
- }
- String 出院带药 = "007";
- if (item.getSupplyCode() != null && 出院带药.equals(item.getSupplyCode())) {
- if (!ONCE.equals(item.getFrequCode())) {
- errorMessage.add("出院带药不能是长期医嘱。");
- }
- item.setDrugOcc(item.getDrugQuan());
- } else {
- // 计算普通药品的领量 durg_quan durg_occ
- calculateDrugAmount(item, detailsOfDrugs);
- if (item.getDrugOcc() == null) {
- errorMessage.add("医嘱领量错误,请重新选择【剂量单位】,或这可能药房剂量维护错误。");
- }
- }
- }
- void 校验医保限制用药(XinZhenYzActOrder item) {
- if (!checkForRestrictedMedication) return;
- // 自费不管
- if ("1".equals(item.getYbSelfFlag())) return;
- ChargeLimitations chargeLimitations = yiBaoLimitation.get(item.getOrderCode(), dao::hasCharge);
- if (chargeLimitations == null) {
- return;
- }
- List<ChargeLimitations> data = dao.getChargeDay(patientInformation.getInpatientNo(),
- patientInformation.getAdmissTimes(),
- patientInformation.getLedgerSn(),
- item.getOrderCode());
- // 已经使用
- int usedAlready = ListUtil.isBlank(data) ? 0 : data.size();
- //可以使用天数
- int canBeUsed = chargeLimitations.getLimitDay() - usedAlready;
- Date latestNumberOfDays = DateUtil.addNaturalDays(item.getStartTime(), canBeUsed);
- int compare = DateUtil.compare(item.getEndTime(), latestNumberOfDays);
- if (item.getEndTime() == null) {
- errorMessage.add(StrUtil.format(
- "医保限制:【{}】天,请设置停止时间,不得超过【{}】",
- chargeLimitations.getLimitDay(), DateUtil.formatDate(latestNumberOfDays, DateUtil.DEFAULT_PATTERN)));
- } else if (compare > 0) {
- errorMessage.add(StrUtil.format(
- "医保限制:【{}】天,请设置停止时间,不得超过【{}】",
- chargeLimitations.getLimitDay(), DateUtil.formatDate(latestNumberOfDays, DateUtil.DEFAULT_PATTERN)));
- }
- }
- private void strictVerificationFunc(@NotNull XinZhenYzActOrder item) {
- if (item.getParentNo() != null && item.getActOrderNo() != null) {
- if (BigUtils.bigXiaoYu(item.getActOrderNo(), item.getParentNo())) {
- errorMessage.add("子医嘱的医嘱号,小于父医嘱号,无法成组。【原因如果子医嘱的医嘱号小于父医嘱,会导致打印乱码】");
- }
- }
- // 获取患者的入院时间
- if (item.getOrderTime() == null) {
- errorMessage.add("医嘱时间不能为空");
- } else if (item.getStartTime() == null) {
- errorMessage.add("开始时间不能为空");
- } else if (patientInformation.getAdmissDate() == null) {
- errorMessage.add("没有查询到患者的入院时间");
- } else if (DateUtil.shiJianDaXiao(item.getStartTime(), patientInformation.getAdmissDate(), "<")) {
- errorMessage.add("开始时间不能在患者入院之前,患者入院时间" + DateUtil.formatDatetime(patientInformation.getAdmissDate()));
- } else if (DateUtil.shiJianDaXiao(item.getStartTime(), item.getOrderTime(), "<") && !userInfo.getDeptCode().equals("1160000")) {
- errorMessage.add("开始时间不能在开医嘱之前");
- }
- if (item.getEndTime() != null) {
- if (ONCE.equals(item.getFrequCode().trim())) {
- item.setEndTime(null);
- } else {
- if (DateUtil.shiJianDaXiao(item.getEndTime(), item.getStartTime(), "<")) {
- errorMessage.add("结束时间不能在开始时间之前");
- } else {
- item.setModifier(TokenUtil.getInstance().getTokenUserId());
- }
- }
- } else {
- item.setModifier(null);
- }
- }
- public XinZhenYzActOrder getDrugData(String code) {
- return drug.get(code, (temp) -> dao.drugDataOne(temp, patientInformation != null ? patientInformation.getZkWard() : "", null));
- }
- public XinZhenYzActOrder getDrugData(String code, String supplyCode) {
- return drug.get(code, (temp) -> dao.drugDataOne(temp, patientInformation != null ? patientInformation.getZkWard() : "", supplyCode));
- }
- public static void calculateDrugAmount(XinZhenYzActOrder item, XinZhenYzActOrder feiYongXinXi) {
- if (feiYongXinXi == null) {
- return;
- }
- item.setDrugWeight(feiYongXinXi.getDrugWeight());
- item.setDrugWeightUnit(feiYongXinXi.getDrugWeightUnit());
- item.setDrugVolume(feiYongXinXi.getDrugVolume());
- item.setDrugVolUnit(feiYongXinXi.getDrugWeightUnit());
- String doseUnit = StringUtil.isBlank(item.getDoseUnit()) ? "" : item.getDoseUnit().trim();
- if (StringUtil.notBlank(feiYongXinXi.getDrugWeightUnit()) && doseUnit.equals(feiYongXinXi.getDrugWeightUnit().trim())) {
- item.setDrugOcc(DecimalUtil.divide(item.getDose(), feiYongXinXi.getDrugWeight(), 2));
- } else if (StringUtil.notBlank(feiYongXinXi.getDrugVolUnit()) && doseUnit.equals(feiYongXinXi.getDrugVolUnit().trim())) {
- item.setDrugOcc(DecimalUtil.divide(item.getDose(), feiYongXinXi.getDrugVolume(), 2));
- } else if (StringUtil.notBlank(feiYongXinXi.getPackUnit()) && doseUnit.equals(feiYongXinXi.getPackUnit().trim())) {
- item.setDrugOcc(DecimalUtil.divide(item.getDose(), feiYongXinXi.getPackSize(), 2));
- }
- }
- private void clearErrorMessage() {
- errorMessage.clear();
- warningMessage.clear();
- }
- private void setReturnMap(String orderNo) {
- Map<String, Object> map = new HashMap<>(Capacity.TWO);
- if (ListUtil.notBlank(errorMessage)) {
- List<String> list = new ArrayList<>(errorMessage);
- map.put("error", list);
- passTheAudit = false;
- }
- if (ListUtil.notBlank(warningMessage)) {
- List<String> list = new ArrayList<>(warningMessage);
- map.put("warning", list);
- }
- if (!map.isEmpty()) {
- returnMap.put(orderNo, map);
- }
- }
- private Map<String, Object> getReturnMap() {
- return returnMap;
- }
- public Boolean getFailed() {
- return !passTheAudit;
- }
- public Boolean multipleExclusions() {
- if (repel == null) {
- return false;
- }
- return repel.getCount() > 1;
- }
- public YiZhuCheckData checkForRestrictedMedication() {
- checkForRestrictedMedication = true;
- return this;
- }
- }
|