package thyyxxk.webserver.service.zhuyuanyisheng;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import thyyxxk.webserver.config.exception.BizException;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.constants.Capacity;
import thyyxxk.webserver.constants.Message;
import thyyxxk.webserver.constants.sidicts.ChargeStatus;
import thyyxxk.webserver.dao.his.zhuyuanyisheng.YiZhuLuRuDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.RoleCode;
import thyyxxk.webserver.entity.datamodify.GetDropdownBox;
import thyyxxk.webserver.entity.datamodify.YzActOrder;
import thyyxxk.webserver.entity.login.UserInfo;
import thyyxxk.webserver.entity.zhuyuanyisheng.DoctorSOrderFee;
import thyyxxk.webserver.entity.zhuyuanyisheng.ZyOrderZk;
import thyyxxk.webserver.entity.zhuyuanyisheng.yizhuluru.*;
import thyyxxk.webserver.service.PublicServer;
import thyyxxk.webserver.service.redislike.RedisLikeService;
import thyyxxk.webserver.utils.*;
import thyyxxk.webserver.websocket.WebSocketServer;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 描述： 医嘱录入
 * </p>
 *
 * @author xc
 * @date 2022-01-04 16:59
 */
@Service
@Slf4j
public class YiZhuLuRuServer {


    private final YiZhuLuRuDao dao;
    private final PublicServer publicServer;
    private final RedisLikeService redisLikeService;

    /**
     * 转科的医嘱编码
     */
    private final String ZK_CODE = "06286";
    private final String ONCE = "ONCE";

    private final String ITEM = "00";
    private final String SMALL_PACKAGE = "01";
    private final String BIG_PACKAGE = "99";


    public YiZhuLuRuServer(YiZhuLuRuDao dao, PublicServer publicServer, RedisLikeService redisLikeService) {
        this.dao = dao;
        this.publicServer = publicServer;
        this.redisLikeService = redisLikeService;
    }


    /**
     * 获取医嘱的名称 这里为什么不用 医嘱的code和医嘱号呢，是因为药品编码和项目编码有些一样而医嘱号，又每次只能查询一个
     *
     * @param inpatientNo 住院号
     * @param admissTimes 住院次数
     * @param orderName   前端搜索的医嘱名称
     * @return 返回医嘱名称去重了
     */
    public ResultVo<List<GetDropdownBox>> huoQuYiZhuMingCheng(String inpatientNo, Integer admissTimes, String orderName) {
        return ResultVoUtil.success(dao.huoQuYiZhuMingZi(inpatientNo, admissTimes, StringUtil.isContainChinese(orderName)));
    }

    /**
     * 获取患者个人的频率
     *
     * @param patNo 住院号
     * @param times 住院次数
     * @return 返回自己的医嘱频率
     */
    public ResultVo<List<GetDropdownBox>> huoQuGeRenPinLv(String patNo, Integer times) {
        return ResultVoUtil.success(dao.huoQuGeRenPinLv(patNo, times));
    }

    /**
     * 获取医嘱的数据
     * 可以根据，医嘱时间区间，执行频率，医嘱名
     *
     * @param param 查询条件
     * @return 返回分页数据，同时做了树状图，这样会有一个问题，那就是开了套餐的数据查询不出来
     */
    public ResultVo<IPage<YzActOrder>> huoQuYiZhuShuJu(YiZhuFeiYongChaXunTiaoJian param) {
        QueryWrapper<?> qw = new QueryWrapper<>();
        qw.eq("inpatient_no", param.getPatNo()).eq("admiss_times", param.getTimes());
        if (StringUtil.notBlank(param.getOrderName())) {
            qw.eq("order_name", param.getOrderName());
        }
        if (StringUtil.notBlank(param.getStartTime())) {
            qw.ge("order_time", param.getStartTime()).le("order_time", param.getEndTime());
        }
        if (StringUtil.notBlank(param.getActOrderNo())) {
            qw.eq("act_order_no", param.getActOrderNo());
        }

        if (StringUtil.notBlank(param.getFrequCode())) {
            qw.eq("frequ_code", param.getFrequCode());
        }
        List<Integer> zhaungTai = Arrays.asList(1, 2, 5);

        if (zhaungTai.contains(param.getZhuangTai())) {
            qw.eq("status_flag", param.getZhuangTai());
        } else if (param.getZhuangTai() == 3) {
            qw.in("status_flag", 3, 4);
        } else if (param.getZhuangTai() == 6) {
            qw.ne("frequ_code", ONCE).isNull("end_time").eq("doctor_flag", "1").ne("status_flag", "5");
        } else if (param.getZhuangTai() == 7) {
            qw.eq("doctor_flag", "1").ge("status_flag", "2").ge("start_time", DateUtil.formatDatetime(DateUtil.addDateMinut(new Date(), -24)));
        } else if (param.getZhuangTai() == 8) {
            qw.eq("frequ_code", ONCE);
        } else if (param.getZhuangTai() == 9) {
            qw.ne("frequ_code", ONCE);
        }
        IPage<YzActOrder> page = new Page<>();
        if (param.getTotal() == 0) {
            page.setTotal(dao.huoQuYiZhuShuJuTotal(qw));
        } else {
            page.setTotal(param.getTotal());
        }

        List<YzActOrder> yiZhuList = dao.huoQuYiZhuShuJu(param.getCurrentPage(), param.getPageSize(), qw);
        // 还有那些没有被匹配的子级医嘱
        Map<BigDecimal, YzActOrder> wuFuJiYiZhu = yiZhuList.stream().collect(Collectors.toMap(YzActOrder::getActOrderNo, a -> a, (k1, k2) -> k1));

        if (ListUtil.isBlank(yiZhuList)) {
            return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
        }
        // 做成树状图
        Map<BigDecimal, YzActOrder> map = new HashMap<>();
        List<YzActOrder> tree = new ArrayList<>();
        for (YzActOrder item : yiZhuList) {
            if (item.getParentNo() == null) {
                tree.add(item);
                wuFuJiYiZhu.remove(item.getActOrderNo());
            }
            map.put(item.getActOrderNo(), item);
            EntityStringTrim.beanAttributeValueTrim(item);
            if ("00".equals(item.getSerial())) {
                item.setGroupNoName("医技科室");
                item.setSerialName("项目");
            } else {
                if ("01".equals(item.getSerial())) {
                    item.setSerialName("小包装");
                } else if ("99".equals(item.getSerial())) {
                    item.setSerialName("大包装");
                }
            }
        }
        for (YzActOrder item : yiZhuList) {
            YzActOrder actOrder = map.get(item.getParentNo());
            if (actOrder != null) {
                wuFuJiYiZhu.remove(item.getActOrderNo());
                if (actOrder.getChildren() == null) {
                    actOrder.setChildren(new ArrayList<>());
                    actOrder.setOrderGroup("┌");
                }
                item.setIsChildren(true);
                item.setOrderGroup("丨");
                actOrder.getChildren().add(item);
            }
        }
        if (!wuFuJiYiZhu.isEmpty()) {
            tree.addAll(wuFuJiYiZhu.values());
        }
        // 删除前后空格
        EntityStringTrim.beanAttributeValueTrimList(tree);
        page.setRecords(tree);
        for (YzActOrder zy : tree) {
            if (ListUtil.notBlank(zy.getChildren())) {
                zy.getChildren().get(zy.getChildren().size() - 1).setOrderGroup("└");
            }
        }
        return ResultVoUtil.success(page);
    }

    /**
     * 获取搜索的项目信息，如药品和项目
     *
     * @param code 拼音首字母，中文，编码来进行搜索
     * @return 返回项目信息
     */
    public ResultVo<List<YiZhuMingChen>> huoQuXiangMu(String code) {
        code = StringUtil.isContainChinese(code);
        List<YiZhuMingChen> list = dao.yiZhuYaoPing(code, publicServer.getGroupNo());
        list.addAll(dao.yiZhuXiangMu(code));
        EntityStringTrim.beanAttributeValueTrimList(list);
        return ResultVoUtil.success(list);
    }

    /**
     * 获取某一个费用的详细信息
     *
     * @param code   编码
     * @param serial 00-项目 01-小包装的药品 99-大包装
     * @return 返回该费用的一些详细信息，以及一些提示信息。
     */
    public ResultVo<Map<String, Object>> huoQuFeiYongXinXi(String code, String serial, String deptCode) {
        Map<String, Object> map = new HashMap<>();
        // 一些提示
        List<String> prompt = new ArrayList<>();
        // 加载项目信息
        if (ITEM.equals(serial.trim())) {
            List<XinZhenYzActOrder> xiangMu = dao.huoQuXiangMu(code);
            for (XinZhenYzActOrder item : xiangMu) {
                if (item.getDelFlag() == 1) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("该医嘱下的【%s】，已经被停用了，请联系物价科。", item.getOrderName()));
                } else if (StringUtil.isBlank(item.getNationalCode())) {
                    prompt.add(String.format("该医嘱下面的【%s】，没有医保编码，请注意。", item.getOrderName()));
                } else {
                    prompt.add(String.format("该医嘱下【%s】，医保码为：【%s】。", item.getOrderName(), item.getNationalCode()));
                }

            }
            if (ListUtil.isBlank(xiangMu)) {
                Integer paiChiYiZhu = dao.shiFouPaiChiYiZhu(code);
                switch (paiChiYiZhu) {
                    case 1:
                        prompt.add("全排斥医嘱");
                        break;
                    case 2:
                        prompt.add("单组排斥医嘱");
                        break;
                    case 3:
                        prompt.add("多组斥医嘱");
                        break;
                    default:
                        break;
                }
            }
        } else {
            YaoPinXinXi yp = dao.huoQuYaoPin(code.trim() + serial.trim(), publicServer.getGroupNo());
            if (StringUtil.notBlank(deptCode)) {
                if (dao.restrictedUseInTheDepartment(code.trim(), deptCode) > 0) {
                    return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST, "该药品禁止在患者所在的科室使用。");
                }
            }
            if (yp == null) {
                return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST, "该医嘱下的药品，可能已经被停用了，请联系药剂科。");
            }
            if (yp.getVisibleFlagZy() == 1) {
                return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST, "该药品禁止住院使用。");
            }
            Integer yiShenDengJi = dao.huoQuYiShenDengJi(TokenUtil.getTokenUserId());
            int yiShen = yiShenDengJi == null ? 0 : yiShenDengJi;
            if (yp.getYpLevel() > yiShen) {
                return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST, "您没有开此药品的权限。");
            }

            List<YaoPingJiLiang> yaoPingJiLiang = new ArrayList<>();
            if (StringUtil.notBlank(yp.getWeighUnit())) {
                yaoPingJiLiang.add(new YaoPingJiLiang(yp.getWeighUnit(), yp.getWeighUnitName(), yp.getWeight()));
            }
            if (StringUtil.notBlank(yp.getVolUnit())) {
                yaoPingJiLiang.add(new YaoPingJiLiang(yp.getVolUnit(), yp.getVolUnitName(), yp.getVolum()));
            }
            if (StringUtil.notBlank(yp.getPackUnit())) {
                yaoPingJiLiang.add(new YaoPingJiLiang(yp.getPackUnit(), yp.getPackUnitName(), yp.getPackSize()));
            }

            if (yp.getKjywFlag() == 1) {
                prompt.add("抗菌药物，需填写抗菌药物医嘱附注");
            }
            if (yp.getSelfFlagYb() == 1) {
                prompt.add("该药品医保自费药品，如符合条件请填写记账，不是请填写自费");
            }
            if (StringUtil.isBlank(yp.getNationalCode())) {
                prompt.add("该药品医保没有匹配医保码");
            } else {
                prompt.add(String.format("药品医保码为：【%s】", yp.getNationalCode()));
            }
            if (yp.getStockAmount() != null && BigUtils.bigXiaoYu(yp.getStockAmount(), 10)) {
                prompt.add(String.format("该药品剩余数量为:【%s】", yp.getStockAmount().stripTrailingZeros().toPlainString()));
            }
            if (yp.getPsFlag() == 1) {
                prompt.add("此药品为皮试药品");
                map.put("piShi", dao.piShiGeiYaoFangShi());
            }
            map.put("yaoPingJiLiang", yaoPingJiLiang);
            map.put("data", yp);
        }
        map.put("prompt", prompt);

        return ResultVoUtil.success(map);
    }

    /**
     * 获取频率
     *
     * @param code 五笔，拼音，中文，编码
     * @return 返回对应的数据
     */
    public ResultVo<List<GetDropdownBox>> huoQuZhuYuanPinLv(String code) {
        return ResultVoUtil.success(dao.huoQuZhuYuanPinLv(StringUtil.isContainChinese(code)));
    }

    /**
     * 获取给药方式
     *
     * @param code 五笔，拼音，中文，编码
     * @return 返回对应的数据
     */
    public ResultVo<List<GetDropdownBox>> huoQuGeiYaoFangShi(String code) {
        return ResultVoUtil.success(dao.huoQuGeiYaoFangShi(StringUtil.isContainChinese(code)));
    }

    /**
     * 获取执行科室
     *
     * @param code 五笔，拼音，中文，编码
     * @return 返回对应的数据
     */
    public ResultVo<List<GetDropdownBox>> huoQuZhiXinKeShi(String code) {
        return ResultVoUtil.success(dao.huoQuZhiXinKeShi(StringUtil.isContainChinese(code)));
    }

    public ResultVo<Map<String, Object>> singleDataCheck(XinZhenYiZhu param) {
        //  获取医生开药品的权限
        Integer 医生级别 = dao.huoQuYiShenDengJi(TokenUtil.getTokenUserId());
        Set<String> yaoPingCode = new HashSet<>();
        Set<String> xiangMuCode = new HashSet<>();

        for (XinZhenYzActOrder item : param.getList()) {
            if (ITEM.equals(item.getSerial().trim())) {
                xiangMuCode.add(item.getOrderCode().trim());
            } else {
                yaoPingCode.add(item.getOrderCode().trim() + item.getSerial().trim());
            }
        }
        XinZhenYiZhu huanZheXinXi = dao.huoQuHuanZheXinXi(param.getInpatientNo(), param.getAdmissTimes());
        Map<String, Object> errorMessage = checkData(param.getList().get(0), getDrugInformation(yaoPingCode, huanZheXinXi == null ? null : huanZheXinXi.getSmallDept()), getProjectInformation(xiangMuCode), huanZheXinXi, 医生级别);
        errorMessage.put("data", param.getList().get(0));
        return ResultVoUtil.success(errorMessage);
    }


    /**
     * 保存医嘱
     *
     * @param param 医嘱数据
     * @return 返回错误提示或者别的
     */
    public ResultVo<Map<String, Object>> saveTheDoctorSOrder(XinZhenYiZhu param) {
        log.info("上传数据:{}", JSON.toJSONStringWithDateFormat(param, DateUtil.DEFAULT_PATTERN));
        //  获取医生开药品的权限
        Integer 医生级别 = dao.huoQuYiShenDengJi(TokenUtil.getTokenUserId());
        // 药品的 code
        Set<String> yaoPingCode = new HashSet<>();
        // 项目的 code
        Set<String> xiangMuCode = new HashSet<>();
        // id 做 map
        Map<String, XinZhenYzActOrder> doctorSOrderMap = new HashMap<>(param.getList().size());

        for (XinZhenYzActOrder item : param.getList()) {
            if (ITEM.equals(item.getSerial().trim())) {
                xiangMuCode.add(item.getOrderCode().trim());
            } else {
                yaoPingCode.add(item.getOrderCode().trim() + item.getSerial().trim());
            }
            doctorSOrderMap.put(item.getId(), item);
        }
        // 医嘱 map {医嘱号: { 具体数据 }}
        // 获取患者信息
        XinZhenYiZhu huanZheXinXi = dao.huoQuHuanZheXinXi(param.getInpatientNo(), param.getAdmissTimes());
        if (huanZheXinXi == null) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "没有查询到患者的在院信息。");
        }
        // 设置婴儿标志
        huanZheXinXi.setInfantFlag(publicServer.getInfantFlag(huanZheXinXi.getInpatientNo()));

        boolean isThereAnyErrorMessage = false;
        Map<String, Object> map = new HashMap<>();
        String sid = WebSocketServer.getSid();
        Map<String, XinZhenYzActOrder> drug = getDrugInformation(yaoPingCode, huanZheXinXi.getSmallDept());
        Map<String, List<XinZhenYzActOrder>> project = getProjectInformation(xiangMuCode);
        for (XinZhenYzActOrder item : param.getList()) {
            Map<String, Object> 错误信息 = checkData(item, drug, project, huanZheXinXi, 医生级别);
            if (!错误信息.isEmpty()) {
                if (!isThereAnyErrorMessage && 错误信息.containsKey("error")) {
                    isThereAnyErrorMessage = true;
                }
                map.put(item.getId(), 错误信息);
            }
            错误信息.put("data", item);
            WebSocketServer.sendMessage(sid, SocketMsg.socketVo(Message.UPDATED_ORDER, map));
        }

        if (isThereAnyErrorMessage) {
            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "请修改错误的医嘱");
        }
        /* 在这里上传医嘱,一点错误信息都没了的话 */
        // 这个是 抗菌药物的信息
        List<YzActRecordKss> kssList = new ArrayList<>();
        // 这个是 转科医嘱的
        ZyOrderZk transferData = null;
        for (XinZhenYzActOrder item : param.getList()) {
            // 生成医嘱号
            item.setActOrderNo(BigDecimal.valueOf(publicServer.getActOrderNo()));

            if (item.getParentNo() != null && doctorSOrderMap.containsKey(item.getParentNo().stripTrailingZeros().toPlainString())) {
                item.setParentNo(doctorSOrderMap.get(item.getParentNo().stripTrailingZeros().toPlainString()).getActOrderNo());
            }

            if (item.getKjywFlag() != null && item.getKjywFlag() == 1) {
                YzActRecordKss kss = new YzActRecordKss();
                kss.setActOrderNo(item.getActOrderNo());
                kss.setChargeCode(item.getOrderCode());
                kss.setYyfs(item.getYyfs());
                kss.setSsqk(item.getSsqk());
                kss.setYysj(item.getYysj());
                kssList.add(kss);
            }
            if (ZK_CODE.equals(item.getOrderCode())) {
                transferData = new ZyOrderZk();
                transferData.setActOrderNo(item.getActOrderNo().stripTrailingZeros().toPlainString()).setNewDept(item.getZkDeptCode()).setNewWard(item.getZkWardCode());
            }

        }
        // 执行人
        String inputCode = TokenUtil.getTokenUserId();
        // 判断患者是否结算了
        publicServer.huanZheJieSuan(param.getInpatientNo(), param.getAdmissTimes());
        if (ListUtil.notBlank(kssList)) {
            dao.shanChuYuanKuangJunYaoWu(kssList);
            dao.chaRuKuangJunYaoWuXinXi(huanZheXinXi.getInpatientNo(), huanZheXinXi.getAdmissTimes(), inputCode, kssList);
        }
        if (transferData != null) {
            transferData.setOldWard(huanZheXinXi.getDeptCode()).setOldDept(huanZheXinXi.getSmallDept());
            dao.insertDoctorSOrder(transferData);
        }
        String groupNo = publicServer.getGroupNo();
        sendAMessageToTheNurse(param, inputCode, huanZheXinXi, groupNo);
        dao.chaRuYiZhu(huanZheXinXi.getInpatientNo(), huanZheXinXi.getAdmissTimes(), inputCode, huanZheXinXi.getInfantFlag(), huanZheXinXi.getDeptCode(), huanZheXinXi.getDeptCode(), huanZheXinXi.getReferPhysician(), param.getList());
        return ResultVoUtil.success(map);
    }

    public ResultVo<String> doesTheTemplateExist(String name) {
        if (dao.duplicateTemplateName(name, TokenUtil.getTokenUserId()) == 0) {
            return ResultVoUtil.success();
        }
        return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST, "模板名称重复");
    }

    public ResultVo<String> saveTemplate(YzOrderPattern param) {
        // 如果名字重复了，那么就修改原来的模板
        YzOrderPattern yzOrderPattern = dao.yuanLaiDeMuBanBianMa(param.getPatternName(), TokenUtil.getTokenUserId());
        UserInfo userInfo = redisLikeService.getUserInfoByCode(TokenUtil.getTokenUserId());
        List<Integer> role = userInfo.getRoles();
        if ("1".equals(param.getInputType()) && publicServer.noNeedRule(role, 38)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "您没有权限创建科室模板。");
        } else if ("2".equals(param.getInputType()) && publicServer.noNeedRule(role, 38, 11)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "您没有权限创建科室模板。");
        }
        if (null == yzOrderPattern) {
            yzOrderPattern = new YzOrderPattern();
        }
        String patternCode = yzOrderPattern.getPatternCode();

        // 有原来的模板名称而且 还要是自己创建的才能删除,否则就只能创建新的模板了
        if (StringUtil.notBlank(patternCode) && userInfo.getCode().equals(yzOrderPattern.getInputId())) {
            // 更新的时候先删除模板 原来的模板
            dao.shanChuLaoMuBan(patternCode);
            param.setPatternCode(patternCode);
        } else {
            // 设置新的模板号
            param.setPatternCode(publicServer.getPatternCode());
        }

        String py = PingYinUtils.pyShouZiMuDaXie(param.getPatternName());
        String wb = PingYinUtils.getWBCode(param.getPatternName());

        param.setPyCode(py.length() > 9 ? py.substring(0, 9) : py);
        param.setDCode(wb.length() > 9 ? wb.substring(0, 9) : wb);
        param.setInputId(TokenUtil.getTokenUserId());
        param.setDeptCode(userInfo.getDeptCode());

        dao.chaRuMuBan(param);

        Map<String, XinZhenYzActOrder> map = param.getList().stream().collect(
                Collectors.toMap(XinZhenYzActOrder::getId, a -> a, (k1, k2) -> k1)
        );

        for (XinZhenYzActOrder item : param.getList()) {
            // 设置模板号
            item.setActOrderNo(BigDecimal.valueOf(publicServer.getPatternOrderCode()));
            if (item.getParentNo() != null && map.containsKey(item.getParentNo().stripTrailingZeros().toPlainString())) {
                item.setParentNo(map.get(item.getParentNo().stripTrailingZeros().toPlainString()).getActOrderNo());
            }
        }

        dao.chaRuMuBanShuJu(param.getList(), param.getPatternCode());
        return ResultVoUtil.success();
    }


    private void 计算药品金额(XinZhenYzActOrder item, XinZhenYzActOrder feiYongXinXi, List<String> 错误信息) {
        if (feiYongXinXi == null) {
            return;
        }
        if (StringUtil.notBlank(feiYongXinXi.getDrugWeightUnit()) && item.getDoseUnit().trim().equals(feiYongXinXi.getDrugWeightUnit().trim())) {
            if (BigUtils.bigXiaoYu(item.getDose(), feiYongXinXi.getDrugWeight())) {
                item.setDrugQuan(BigDecimal.valueOf(1));
                item.setDrugOcc(BigDecimal.valueOf(1));
            } else {
                item.setDrugQuan(DecimalUtil.divide(item.getDose(), feiYongXinXi.getDrugWeight()));
                item.setDrugOcc(DecimalUtil.divide(item.getDose(), feiYongXinXi.getDrugWeight(), 2));
            }
        } else if (StringUtil.notBlank(feiYongXinXi.getDrugVolUnit()) && item.getDoseUnit().trim().equals(feiYongXinXi.getDrugVolUnit())) {
            if (BigUtils.bigXiaoYu(item.getDose(), feiYongXinXi.getDrugVolume())) {
                item.setDrugQuan(BigDecimal.valueOf(1));
                item.setDrugOcc(BigDecimal.valueOf(1));
            } else {
                item.setDrugQuan(DecimalUtil.divide(item.getDose(), feiYongXinXi.getDrugVolume()));
                item.setDrugOcc(DecimalUtil.divide(item.getDose(), feiYongXinXi.getDrugVolume(), 2));
            }
        } else if (StringUtil.notBlank(feiYongXinXi.getPackUnit()) && item.getDoseUnit().trim().equals(feiYongXinXi.getPackUnit())) {
            if (new BigDecimal(item.getDose().intValue()).compareTo(item.getDose()) != 0) {
                错误信息.add("已经是最小单位了请不要带小数点");
            }
            item.setDrugQuan(DecimalUtil.divide(item.getDose(), feiYongXinXi.getPackSize()));
            item.setDrugOcc(DecimalUtil.divide(item.getDose(), feiYongXinXi.getPackSize(), 2));
        }

    }

    private Map<String, Object> checkData(XinZhenYzActOrder item,
                                          Map<String, XinZhenYzActOrder> drug,
                                          Map<String, List<XinZhenYzActOrder>> project,
                                          XinZhenYiZhu huanZheXinXi,
                                          Integer 医生级别) {
        Boolean 严格校验 = huanZheXinXi != null;
        List<String> 错误信息 = new ArrayList<>();
        List<String> 警告信息 = new ArrayList<>();

        if (ITEM.equals(item.getSerial())) {
            List<XinZhenYzActOrder> 项目明细 = project.get(item.getOrderCode());
            // 如果这个项目下面没有费用明细，那么这就是一条口头医,口头医嘱每次只能开一个
            if (ListUtil.isBlank(项目明细)) {
                item.setDrugQuan(BigDecimal.valueOf(1));
                item.setDrugOcc(BigDecimal.valueOf(1));
            } else {
                for (XinZhenYzActOrder 明细 : 项目明细) {
                    if (明细.getDelFlag() == 1) {
                        错误信息.add(String.format("项目：【%s】，已经被物价停用了", 明细.getOrderName()));
                    }
                    if (StringUtil.isBlank(明细.getNationalCode())) {
                        警告信息.add(String.format("项目：【%s】，没有匹配医保码", 明细.getOrderName()));
                    }
                }

            }
        } else {
            XinZhenYzActOrder feiYongXinXi = drug.get(item.getOrderCode().trim() + item.getSerial().trim());
            if (feiYongXinXi != null) {
                if (feiYongXinXi.getDelFlag() == 1) {
                    错误信息.add("药品已经被停用了，请联系药剂科");
                }
                if (feiYongXinXi.getYpLevel() > 医生级别) {
                    错误信息.add("您没有开此药品的权限");
                }
                if (StringUtil.isBlank(feiYongXinXi.getNationalCode())) {
                    警告信息.add("该药品没有医保编码");
                }
                if (feiYongXinXi.getStockAmount() != null && BigUtils.bigXiaoYu(feiYongXinXi.getStockAmount(), 10)) {
                    警告信息.add(String.format("该药品剩余数量为:【%s】", feiYongXinXi.getStockAmount().stripTrailingZeros().toPlainString()));
                }
                if (严格校验) {
                    if (feiYongXinXi.getDeptRestrictions() > 0) {
                        错误信息.add("该药品禁止在患者所在的科室使用。");
                    }
                    if (feiYongXinXi.getVisibleFlagZy() == 1) {
                        错误信息.add("该药品禁止住院患者使用。");
                    }
                    item.setKjywFlag(feiYongXinXi.getKjywFlag());
                    if (feiYongXinXi.getKjywFlag() == 1) {
                        if (item.getYyfs() == null) {
                            错误信息.add("请填写抗菌药物医嘱附注信息录入");
                        } else if (item.getYyfs() == 1 || item.getYyfs() == 2) {
                            if (item.getSsqk() == null || item.getYyfs() == null) {
                                错误信息.add("当用药方式为 1 或 2 时，手术切口和用药时间不能为空");
                            }
                        }
                    }
                }
                // 计算费用金额
                计算药品金额(item, feiYongXinXi, 错误信息);
            }
        }

        if (StringUtil.isBlank(item.getOrderCode())) {
            错误信息.add("项目编码不能为空");
        }
        if (StringUtil.isBlank(item.getOrderName())) {
            错误信息.add("项目名称不能为空");
        }
        if (StringUtil.isBlank(item.getExecUnit())) {
            错误信息.add("执行科室不能为空");
        } else if (item.getExecUnit().startsWith("8")) {
            错误信息.add("执行科室不能选择为病区");
        }

        if (ZK_CODE.equals(item.getOrderCode())) {
            if (StringUtil.isBlank(item.getZkWardCode())) {
                错误信息.add("转科病房不能为空");
            }
            if (StringUtil.isBlank(item.getZkDeptCode())) {
                错误信息.add("转科科室不能为空");
            }
        }

        if (StringUtil.isBlank(item.getFrequCode())) {
            错误信息.add("频次不能为空");
        }

        // 药品的校验
        if (!ITEM.equals(item.getSerial().trim())) {
            if (StringUtil.isBlank(item.getDrugSpecification())) {
                错误信息.add("药品规格不能为空");
            }
            if (StringUtil.isBlank(item.getSupplyCode())) {
                错误信息.add("给药方式不能为空");
            }
            if (item.getDose() == null || BigUtils.dengYu(item.getDose(), 0)) {
                错误信息.add("一次计量不能为空");
            }
            if (StringUtil.isBlank(item.getDoseUnit())) {
                错误信息.add("计量单位不能为空");
            }
            if (StringUtil.isBlank(item.getSerial())) {
                错误信息.add("包装大小不能为空");
            }
        }

        if (严格校验) {
            // 获取患者的入院时间
            if (item.getOrderTime() == null) {
                错误信息.add("医嘱时间不能为空");
            } else if (item.getStartTime() == null) {
                错误信息.add("开始时间不能为空");
            } else if (huanZheXinXi.getAdmissDate() == null) {
                错误信息.add("没有查询到患者的入院时间");
            } else if (DateUtil.shiJianDaXiao(item.getStartTime(), huanZheXinXi.getAdmissDate(), "<")) {
                错误信息.add("开始时间不能在患者入院之前,患者入院时间" + DateUtil.formatDatetime(huanZheXinXi.getAdmissDate()));
            } else if (DateUtil.shiJianDaXiao(item.getStartTime(), item.getOrderTime(), "<")) {
                错误信息.add("开始时间不能在开医嘱之前");
            }

            if (item.getEndTime() != null) {
                if (ONCE.equals(item.getFrequCode().trim())) {
                    item.setEndTime(null);
                } else {
                    if (DateUtil.shiJianDaXiao(item.getEndTime(), item.getStartTime(), "<")) {
                        错误信息.add("结束时间不能在开始时间之前");
                    }
                }
            }
        }

        Map<String, Object> map = new HashMap<>(Capacity.TWO);
        if (ListUtil.notBlank(错误信息)) {
            map.put("error", 错误信息);
        }
        if (ListUtil.notBlank(警告信息)) {
            map.put("warning", 警告信息);
        }
        return map;
    }


    /***
     * 获取项目信息
     * @param xiangMuCode 项目编码
     * @return 返回数据
     */
    private Map<String, List<XinZhenYzActOrder>> getProjectInformation(Set<String> xiangMuCode) {
        if (!xiangMuCode.isEmpty()) {
            return dao.huoQuXiangMuXinXi(xiangMuCode).stream().collect(Collectors.groupingBy(item -> item.getOrderCode().trim()));
        }
        return new HashMap<>(0);
    }

    /**
     * 获取药品信息
     *
     * @param yaoPingCode 药品编码
     * @return 返回数据
     */
    private Map<String, XinZhenYzActOrder> getDrugInformation(Set<String> yaoPingCode, String dept) {
        if (!yaoPingCode.isEmpty()) {
            return dao.huoQuYaoPinXinXi(yaoPingCode, publicServer.getGroupNo(), dept).stream().collect(Collectors.toMap(item -> item.getOrderCode().trim() + item.getSerial().trim(), a -> a, (k1, k2) -> k1));
        }
        return new HashMap<>(0);
    }


    private void sendAMessageToTheNurse(XinZhenYiZhu param, String inputCode, XinZhenYiZhu huanZheXinXi, String groupNo) {
        List<String> content = new ArrayList<>();
        for (XinZhenYzActOrder item : param.getList()) {
            if (StringUtil.isBlank(item.getDrugFlag())) {
                item.setDrugFlag("o");
            }
            if ("00".equals(item.getSerial().trim())) {
                item.setGroupNo("00");
            } else if ("01".equals(item.getSerial().trim()) || "99".equals(item.getSerial().trim())) {
                item.setGroupNo(groupNo);
            }
            if (item.getEndTime() != null) {
                item.setModifier(inputCode);
            }
            content.add(String.format("医嘱名：<span style='color:#409eff'>【%s】</span><br>" + "医嘱时间：<span style='color:#409eff'>【%tF %<tT】</span><br>" + "患者姓名：<span style='color:#409eff'>【%s】</span><br>" + "床位：<span style='color:#409eff'>【%s】</span><br>" + "频次：<span style='color:#409eff'>【%s】</span>", item.getOrderName(), item.getOrderTime(), huanZheXinXi.getName(), huanZheXinXi.getBedNo(), item.getFrequCode()));
        }
        publicServer.faSongXiaoXi(huanZheXinXi, content, "新增医嘱", inputCode);
    }

    /**
     * 错误信息提示，如果只有一个 list 那就不需要提示是多少行了
     *
     * @param message  消息
     * @param listSize 当前传入数据的大小
     * @param index    当前的数据的下标
     * @return 返回提示信息
     */
    private String getCuoWuXinXi(String message, int listSize, int index) {
        if (listSize == 1) {
            return message + "<br>";
        } else {
            return String.format("第【%d】行，%s <br>", index, message);
        }
    }

    /**
     * 获取模板的名字
     *
     * @param code 编码
     * @return 返回模板名称 list
     */
    public ResultVo<IPage<YzOrderPattern>> huoQuYiZhuMuBan(String code, String deptCode, Integer muBanLeiXing, long currentPage, long total) {
        IPage<YzOrderPattern> page = new Page<>();
        if (total == 0) {
            page.setTotal(dao.huoQuMuBanTotal(StringUtil.isContainChinese(code), TokenUtil.getTokenUserId(), deptCode, muBanLeiXing));
        }
        page.setRecords(dao.huoQuMuBan(StringUtil.isContainChinese(code), TokenUtil.getTokenUserId(), deptCode, muBanLeiXing, currentPage));
        return ResultVoUtil.success(page);
    }


    private String getActOrderNo() {
        Random random = new Random();
        String a = String.valueOf(random.nextInt(5) + 1);
        String b = String.valueOf(random.nextInt(99999));
        return a + b;
    }

    /**
     * 获取模板数据
     *
     * @param code 模板的编码
     * @return 返回数据
     */
    public ResultVo<List<YzActOrder>> huoQuMuBanShuJu(String code) {
        List<YzActOrder> muBanShuJu = dao.huoQuMuBanShuJu(code);
        Map<BigDecimal, YzActOrder> map = new HashMap<>(muBanShuJu.size());
        List<YzActOrder> tree = new ArrayList<>();
        for (YzActOrder item : muBanShuJu) {
            item.setId(getActOrderNo());
            if (item.getParentNo() == null) {
                tree.add(item);
            }
            map.put(item.getActOrderNo(), item);
        }
        for (YzActOrder item : muBanShuJu) {
            YzActOrder yzActOrder = map.get(item.getParentNo());
            if (yzActOrder != null) {
                item.setParentNo(new BigDecimal(yzActOrder.getId()));
                item.setIsChildren(true);
                if (yzActOrder.getChildren() == null) {
                    yzActOrder.setChildren(new ArrayList<>());
                }
                yzActOrder.getChildren().add(item);
                // 没有副医嘱的就返回到最上层
            } else if (!tree.contains(item)) {
                item.setParentNo(null);
                tree.add(item);
            }
        }
        return ResultVoUtil.success(tree);
    }


    /**
     * 删除医嘱模板
     *
     * @param patternCode 模板的编码
     * @return 提示
     */
    public ResultVo<String> deleteADoctorSOrderTemplate(String patternCode) {
        if (StringUtil.isBlank(patternCode)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "模板编号为空。");
        }
        YzOrderPattern yzOrderPattern = dao.huoQuMuBanXinXi(patternCode);
        EntityStringTrim.beanAttributeValueTrim(yzOrderPattern);
        if (yzOrderPattern == null) {
            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "没有查询到对应的模板信息。");
        }
        String userId = TokenUtil.getTokenUserId();
        List<Integer> role = publicServer.getRoleCode().getData();
        if (publicServer.needRule(role, RoleCode.PHYSICIAN_S_ORDER_TEMPLATEEDIT)) {
            return startDeletingTemplates(patternCode);
        }
        if (userId.equals(yzOrderPattern.getInputId())) {
            return startDeletingTemplates(patternCode);
        }
        //   主任可以删除本科室的任意模板
        if (publicServer.needRule(role, RoleCode.DIRECTOR) && dao.userDeptCode(userId).equals(yzOrderPattern.getDeptCode())) {
            return startDeletingTemplates(patternCode);
        }
        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "您没有权限删除这个模板。");
    }

    /**
     * 删除父模板以及下面的子模板 数据
     *
     * @param patternCode 模板编码
     */
    private ResultVo<String> startDeletingTemplates(String patternCode) {
        dao.shanChuMuBan(patternCode);
        log.info("删除医嘱模板==> 操作人:{},模板编码:{}", TokenUtil.getTokenUserId(), patternCode);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "删除成功。");
    }

    /**
     * 收藏医嘱模板或者取消收藏
     * 如果以及收藏了就删除,没有就收藏
     *
     * @param patternCode 模板号
     * @return 提示
     */
    public ResultVo<String> collectDoctorSOrderTemplate(String patternCode) {
        String userId = TokenUtil.getTokenUserId();
        String saveTheDoctorSOrderNumber = dao.whetherToSaveTheDoctorSOrderTemplate(patternCode, userId);
        if (StringUtil.notBlank(saveTheDoctorSOrderNumber)) {
            dao.shanChuMuBan(saveTheDoctorSOrderNumber);
            return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "已取消删除。");
        } else {
            YzOrderPattern yzOrderPattern = dao.huoQuMuBanXinXi(patternCode);
            EntityStringTrim.beanAttributeValueTrim(yzOrderPattern);
            dao.chaRuShouCang(publicServer.getPatternCode(), yzOrderPattern.getPatternName() + "(收藏)", yzOrderPattern.getPyCode(), yzOrderPattern.getDCode(), dao.userDeptCode(userId), userId, yzOrderPattern.getPatternCode());
            return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "收藏成功。");
        }
    }


    /**
     * 删除或修改模板
     *
     * @param patternCode 模板点吗
     * @param patternName 模板名称
     * @param sortNo      排序号
     * @param flag        标志 1-修改 2- 删除 3-收藏和取消收藏
     * @return 返回给前端提示
     */
    public ResultVo<String> muBanCaoZuo(String patternCode, String patternName, String deptCode, Integer sortNo, Integer flag) {
        if (StringUtil.isBlank(patternCode)) {
            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "模板编码为空。");
        }
        YzOrderPattern yzOrderPattern = dao.huoQuMuBanXinXi(patternCode);
        if (yzOrderPattern == null) {
            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "没有查询到对应的模板信息。");
        }
        EntityStringTrim.beanAttributeValueTrim(yzOrderPattern);
        String inputId = TokenUtil.getTokenUserId();
        List<Integer> role = publicServer.getRoleCode().getData();
        // 管理员 和 医务部的无视 规则
        if (!role.contains(1) && !role.contains(38) && flag != 3) {
            // 只有模板在不等于 自己的时候触发
            if (!inputId.equals(yzOrderPattern.getInputId())) {
                if ("2".equals(yzOrderPattern.getInputType()) && !role.contains(11)) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "该模板为科室模板您没有权限修改或删除，请联系科主任进行修改。");
                } else if ("1".equals(yzOrderPattern.getInputType())) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "该模板为全院模板，无法删除或修改。");
                }
            }
        }
        if (flag == 1) {
            if (StringUtil.isBlank(patternName)) {
                return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "模板名称不能为空。");
            }
            if (patternName.trim().equals(yzOrderPattern.getPatternName().trim()) && sortNo.equals(yzOrderPattern.getSortNo())) {
                return ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, "数据没有变化，请勿点击。");
            }
            dao.genXingMuBan(patternName.trim(), PingYinUtils.pyShouZiMuDaXie(patternName), PingYinUtils.getWBCode(patternName), yzOrderPattern.getPatternCode(), sortNo);
            return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "修改成功。");
        } else if (flag == 2) {
            // 删除父模板以及下面的子模板 数据
            dao.shanChuMuBan(yzOrderPattern.getPatternCode());
            return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "删除成功。");
        } else if (flag == 3) {
            // 收藏模板
            String collectCode = dao.chongFuShouCang(inputId, patternCode);
            if (collectCode == null) {
                dao.chaRuShouCang(publicServer.getPatternCode(), yzOrderPattern.getPatternName() + "(收藏)", yzOrderPattern.getPyCode(), yzOrderPattern.getDCode(), deptCode, inputId, yzOrderPattern.getPatternCode());
                return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "收藏成功。");
            } else {
                dao.shanChuMuBan(yzOrderPattern.getPatternCode());
                return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "已取消收藏。");
            }
        }
        return ResultVoUtil.success();
    }

    /**
     * 医嘱操作
     *
     * @param actOrderNo 医嘱号
     * @param flag       标志 1-设为紧急 2-撤销 3-停止
     * @return 返回提示
     */
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> yiZhuChaoZuo(BigDecimal actOrderNo, Integer flag, String content) {
        YzActOrder yz = dao.chaXunYiZhuXinXin(actOrderNo);
        if (yz == null) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有查询到该医嘱可能已经被撤销了");
        }
        switch (flag) {
            case 1:
                return sheZhiJinJi(yz);
            case 2:
                return ceXiaoYiZhu(yz, content);
            case 3:
                return tingZhiShiJian(yz, content);
            default:
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "你想干什么？");
        }

    }

    public ResultVo<String> sheZhiJinJi(YzActOrder yz) {
        String emergencyFlag = null;
        if (yz.getEmergencyFlag() == null || !"1".equals(yz.getEmergencyFlag().trim())) {
            emergencyFlag = "1";
        }
        dao.sheZhiJinJi(yz.getActOrderNo(), emergencyFlag);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION);
    }

    private ResultVo<String> ceXiaoYiZhu(YzActOrder param, String content) {
        if (StringUtil.isBlank(content)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请填写撤销原因。");
        }
        YzActOrder yz = dao.chaXunYiZhuXinXin(param.getActOrderNo());
        if (yz == null) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有找到对应医嘱的信息。");
        }
        String userCode = TokenUtil.getTokenUserId();
        if (publicServer.noNeedRule(38)) {
            if (!yz.getPhysician().trim().equals(userCode)) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "不是本人开的医嘱无权撤销。");
            }
            if (DateUtil.shiJianDaXiao(new Date(), DateUtil.addDateMinut(yz.getStartTime(), 24), ">")) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "已经超过24个小时了，无法撤销。");
            }
        }
        if (!"2".equals(yz.getStatusFlag().trim())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "该医嘱无法被撤销。");
        }
        // 获取该医嘱下面的项目有没有被执行了，如果被执行了的话就不能撤销了。
        publicServer.huoQuGaiYiZhuXiaXiangMu(yz.getActOrderNo());
        // 插入撤销的原因
        dao.chaRuCheXiaoYuanYin(yz.getActOrderNo(), yz.getInpatientNo(), yz.getAdmissTimes(), content, yz.getOrderCode());
        //  删除费用 删除药品的药单 删除医嘱表 删除医技
        dao.cheXiaoYiZhu(yz.getActOrderNo());
        // 把原来的医嘱插入到 yz_erase_order 这个表
        dao.chaRuShanChuBiao(yz.getActOrderNo());
        // 更新原来的状态
        dao.genXingShanChuBiaoZhi(userCode, yz.getActOrderNo());
        log.info("删除医嘱==》数据：{}，操作人：{}", JSON.toJSONString(yz), userCode);
        publicServer.faSongXiaoXi(dao.huoQuHuanZheXinXi(yz.getInpatientNo(), yz.getAdmissTimes()), Stream.of(String.format("医嘱名：【%s】，<br>" + "医嘱号：【%s】，<br>" + "撤销原因【%s】", yz.getOrderName(), yz.getActOrderNo().toString(), content)).collect(Collectors.toList()), "撤销医嘱", TokenUtil.getTokenUserId());
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "医嘱撤销成功。");
    }

    private ResultVo<String> tingZhiShiJian(YzActOrder yz, String content) {
        String userCode = TokenUtil.getTokenUserId();
        if (StringUtil.isBlank(content)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请选择停止时间。");
        }
        String LOGICAL_ERROR = tingZhiYiZhuJiaoYan(yz, content);
        if (LOGICAL_ERROR != null) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, LOGICAL_ERROR);
        }
        dao.sheZhiTingZhiShiJian(userCode, yz.getActOrderNo(), content);
        log.info("停止医嘱==》医嘱号：{}，停止时间：{}，操作人：{}", yz.getActOrderNo(), content, userCode);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION);
    }

    private String tingZhiYiZhuJiaoYan(YzActOrder yz, String content) {
        if (!DateUtil.dateStrIsValid(content, DateUtil.DEFAULT_PATTERN)) {
            return "请输入正确的时间格式。";
        }
        if (yz.getEndTime() != null) {
            return "该医嘱已经被停止了，无法修改。";
        }
        if (DateUtil.shiJianDaXiao(content, DateUtil.formatDatetime(yz.getStartTime()), "<=")) {
            return "停止时间不能在开始时间前面。";
        }
        if (ONCE.equals(yz.getFrequCode().trim())) {
            return "临时医嘱，无法设置停止时间。";
        }
        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> piLiangXiuGaiTingZhiShiJian(YiZhuTingZhiShiJian param) {
        if (ListUtil.isBlank(param.getActOrderNoList())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请先选择数据");
        }
        if (param.getActOrderNoList().size() > 20) {
            return ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, "批量操作每次不得大于20条");
        }
        List<YzActOrder> yiZhuXinXi = dao.yiZhuXinXiJiHe(param.getActOrderNoList());
        if (yiZhuXinXi == null) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有查询到对应的医嘱信息，您选择的数据可以已经被全部停止或撤销。");
        }
        StringBuilder cuoWuXinXi = new StringBuilder();
        for (YzActOrder yzActOrder : yiZhuXinXi) {
            String jiaoYan = tingZhiYiZhuJiaoYan(yzActOrder, param.getEndTime());
            if (jiaoYan != null) {
                cuoWuXinXi.append("医嘱号：").append(yzActOrder.getActOrderNo()).append("<br>").append("医嘱名:").append(yzActOrder.getOrderName()).append("<br>").append(jiaoYan).append("<br><br>");
            }
        }
        if (cuoWuXinXi.length() > 0) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_HTML_ERROR, cuoWuXinXi.toString());
        }
        dao.piLiangSheZhiTingZhiShiJian(param.getActOrderNoList(), TokenUtil.getTokenUserId(), param.getEndTime());
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION);
    }

    public ResultVo<Map<String, Object>> expensesForGettingADoctorSOrder(String patNo, Integer times) {
        List<DoctorSOrderFee> feeDate = dao.expensesForGettingADoctorSOrder(patNo, times);
        // 这些编码的医嘱都是有问题的
        List<String> problem = Arrays.asList("5", "6", "7", "9");

        Map<String, String> problemDoctorSOrder = new HashMap<>();
        Map<String, FeeSum> totalCost = new HashMap<>();

        Map<String, List<DoctorSOrderFee>> map = new HashMap<>(feeDate.size());
        for (DoctorSOrderFee fee : feeDate) {
            // 如果这个没有就代表没有产生费用
            if (fee.getOrderNoStr() == null) {
                continue;
            }
            String chargeStatusName = ChargeStatus.getValue(fee.getChargeStatus());

            String amount = fee.getChargeAmount().abs().stripTrailingZeros().toPlainString();
            String money = fee.getChargeFee().stripTrailingZeros().toPlainString();

            // 计算费用总和
            if (totalCost.containsKey(fee.getOrderNoStr())) {
                FeeSum sum = totalCost.get(fee.getOrderNoStr());
                sum.setSum(DecimalUtil.add(money, sum.getSum()));
                sum.setAmount(DecimalUtil.add(amount, sum.getAmount()));
                totalCost.replace(fee.getOrderNoStr(), sum);
            } else {
                FeeSum sum = new FeeSum();
                sum.setAmount(amount);
                sum.setSum(money);
                totalCost.put(fee.getOrderNoStr(), sum);
            }

            if (problem.contains(fee.getChargeStatus())) {

                problemDoctorSOrder.put(fee.getOrderNoStr(), chargeStatusName);
            }

            fee.setChargeStatusName(chargeStatusName);

            if (map.containsKey(fee.getOrderNoStr())) {
                map.get(fee.getOrderNoStr()).add(fee);
            } else {
                List<DoctorSOrderFee> list = new ArrayList<>();
                list.add(fee);
                map.put(fee.getOrderNoStr(), list);
            }
        }

        Map<String, Object> feeData = new HashMap<>(3);
        feeData.put("data", map);
        feeData.put("problem", problemDoctorSOrder);
        feeData.put("totalCost", totalCost);

        return ResultVoUtil.success(feeData);
    }

}
