package thyyxxk.webserver.service.inpatient.xmlr;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
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.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
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.dao.his.inpatient.xmlr.XiangMuLuRuDao;
import thyyxxk.webserver.dao.his.medicalinsurance.SiSettleApplyDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.datamodify.GetDropdownBox;
import thyyxxk.webserver.entity.datamodify.ZyDetailCharge;
import thyyxxk.webserver.entity.inpatient.FeeSelect;
import thyyxxk.webserver.entity.inpatient.ZyActpatient;
import thyyxxk.webserver.entity.login.UserInfo;
import thyyxxk.webserver.entity.medicalinsurance.inpatient.ZyPatientInfo;
import thyyxxk.webserver.entity.projectEntry.DrugReturnForm;
import thyyxxk.webserver.entity.xmlr.dto.XmlrQueryFee;
import thyyxxk.webserver.entity.xmlr.vo.FeeResult;
import thyyxxk.webserver.enums.authorize.RuleId;
import thyyxxk.webserver.service.PublicServer;
import thyyxxk.webserver.service.hutoolcache.UserCache;
import thyyxxk.webserver.service.hutoolcache.ZyBillItemCache;
import thyyxxk.webserver.service.medicalinsurance.SiZyService;
import thyyxxk.webserver.service.zhuyuanyisheng.emr.EmrServer;
import thyyxxk.webserver.utils.*;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * <p>
 * 描述： 项目录入
 * </p>
 *
 * @author xc
 * @date 2021-08-02 10:37
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class XiangMuLuRuService {
    private final XiangMuLuRuDao dao;
    private final PublicServer publicServer;
    private final SiZyService siZyService;
    private final SiSettleApplyDao siSettleApplyDao;
    private final UserCache userCache;
    private final ZyBillItemCache zyBillItemCache;
    private final EmrServer emrServer;

    private XiangMuLuRuService getThis() {
        return SpringUtil.getBean(this.getClass());
    }

    @Data
    public static class FeiYongTotal {
        private Long total;
        private Long chargeFee;
    }

    @Data
    public static class PatientResult {
        private Long total;
        private Long chargeFeeTotal;
        private List<ZyDetailCharge> data;
    }

    public ResultVo<ZyActpatient> getPatientInfo(String patNo, Integer times) {
        String tableName;
        QueryWrapper<?> qw = new QueryWrapper<>();
        qw.eq("inpatient_no", patNo);
        if (times == null) {
            tableName = "zy_actpatient";
        } else {
            tableName = "zy_inactpatient";
            qw.eq("admiss_times", times);
        }
        ZyActpatient patientInfo = dao.getPatientInfo(qw, tableName);
        if (patientInfo == null) {
            return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
        }
        String emrByCode = emrServer.findEmrByCode(patientInfo.getInpatientNo(), patientInfo.getAdmissTimes(), "ruyuanjiluzhuanyong");
        patientInfo.setAge(DateUtil.calculateAge(patientInfo.getBirthDate(), patientInfo.getAdmissDate()));
        patientInfo.setEmrDiagStr(EmrJsonUtils.businessCodeValueStr(emrByCode, "入院诊断"));
        return ResultVoUtil.success(patientInfo);
    }

    public ResultVo<FeeResult> getFee(XmlrQueryFee params) {
        QueryWrapper<?> qw = getQueryWrapper(params);
        FeeResult feeResult = new FeeResult();
        feeResult.setData(dao.getFee(qw));

        BigDecimal total = BigDecimal.ZERO;

        for (FeeResult.Detail item : feeResult.getData()) {
            total = total.add(item.getChargeFee());
        }
        feeResult.setFeeTotal(total.toPlainString());
        return ResultVoUtil.success(feeResult);
    }


    public QueryWrapper<?> getQueryWrapper(XmlrQueryFee params) {
        QueryWrapper<?> qw = new QueryWrapper<>();
        String usCode = TokenUtil.getInstance().getTokenUserId();

        Integer ledgerSn = publicServer.getLedgerSn(params.getInpatientNo(), params.getAdmissTimes());
        params.setLedgerSn(ledgerSn);
        params.setInfantFlag("0");
        // 如果是婴儿的话那么就需要截取 字符串了 在通过婴儿标识来判断
        if (params.getInpatientNo().contains("$")) {
            params.setInpatientNo(params.getInpatientNo().split("\\$")[0]);
            params.setInfantFlag("1");
        }

        qw.eq("inpatient_no", params.getInpatientNo())
                .eq("admiss_times", params.getAdmissTimes())
                .eq("ledger_sn", params.getLedgerSn())
                .eq("infant_flag", params.getInfantFlag())
                .ne("isnull(trans_flag_yb, 0)", 2);


        if (StrUtil.isNotBlank(params.getStartTime())) {
            qw.ge("charge_date", params.getStartTime())
                    .le("charge_date", params.getEndTime());
        }

        if (StrUtil.isNotBlank(params.getChargeCode())) {
            qw.eq("rtrim(charge_code_mx) + '_' + isnull(nullif(rtrim(a.serial), ''), '00')", params.getChargeCode());
        }

        // 如果有明确的医嘱号了，就不能在查询指定类型的医嘱了
        if (StrUtil.isNotBlank(params.getOrderNo())) {
            params.setFeeSources(2);
            params.setChargeType(0);
            params.setChargeCode(null);
            qw.eq("order_no", params.getOrderNo());
        }

        if (params.getChargeType() == 1) {
            qw.eq("isnull(nullif(rtrim(a.serial), ''), '00')", "00");
        } else if (params.getChargeType() == 2) {
            qw.ne("isnull(nullif(rtrim(a.serial), ''), '00')", "00");
        }

        if (StrUtil.isNotBlank(params.getExecDept())) {
            qw.eq("exec_unit", params.getExecDept());
        }

        if (params.getRefundSymbol() == 0) {
            qw.isNull("ori_detail_sn")
                    .ge("charge_fee", 0);
        }
        if (params.getRefundSymbol() == 1) {
            qw.and(q -> {
                q.gt("ori_detail_sn", 0)
                        .or()
                        .lt("charge_fee", 0);
            });
        }
        if (params.getRefundSymbol() == 2) {
            qw.eq("ori_detail_sn", -1);
        }

        Integer order = params.getFeeSources();

        if (order != 2 && order != 1) {
            qw.eq("order_no", order);
        }

        if (order == 1) {
            qw.gt("len(order_no)", new BigDecimal(2));
        }


        qw.orderBy(true, params.getOrderBy(), "charge_date");
        return qw;
    }

    /**
     * 获取患者费用
     * 费用 类型  1 - 医嘱  2 - 项目费用  3 - 医技 4 - 全部  5 -药品费用
     *
     * @param param 查询条件
     * @return 返回患者费用
     */
    public PatientResult getHuanZheFeiYong(ZyDetailCharge param) {
        PatientResult patientResult = new PatientResult();
        Integer ledgerSn = publicServer.getLedgerSn(param.getInpatientNo(), param.getAdmissTimes());
        param.setLedgerSn(ledgerSn);
        param.setInfantFlag("0");
        // 如果是婴儿的话那么就需要截取 字符串了 在通过婴儿标识来判断
        if (param.getInpatientNo().contains("$")) {
            param.setInpatientNo(param.getInpatientNo().split("\\$")[0]);
            param.setInfantFlag("1");
        }
        if (param.getTuiFeiFlag() == null) {
            param.setTuiFeiFlag(2);
        }
        QueryWrapper<?> qw = setQueryWrapperItem(param);

        if (param.getFeiYongLeiXingCode() == 0) {
            // 查询项目
            qw.eq("isnull(nullif(rtrim(serial), ''), '00')", "00");
            if (param.getTotal() == 0) {
                FeiYongTotal feiYongTotal = dao.huanZheFeiYongToatalV2(qw);
                patientResult.setTotal(feiYongTotal.getTotal());
                patientResult.setChargeFeeTotal(feiYongTotal.getChargeFee());
            }
            patientResult.setData(dao.huanZheXiangMuFeiYongV2(qw, param.getCurrentPage(), param.getPageSize(), param.getRiQiPaiXu()));
        } else {
            // 查询药品
            qw.ne("isnull(nullif(rtrim(serial), ''), '00')", "00");
            if (param.getTotal() == 0) {
                FeiYongTotal feiYongTotal = dao.huanZheFeiYongToatalV2(qw);
                patientResult.setTotal(feiYongTotal.getTotal());
                patientResult.setChargeFeeTotal(feiYongTotal.getChargeFee());
            }
            patientResult.setData(dao.huanZheYaoPinFeiYongV2(qw, param.getCurrentPage(), param.getPageSize(), param.getRiQiPaiXu()));
        }
        if (ListUtil.isBlank(patientResult.getData())) {
            patientResult.setData(new ArrayList<>());
            return patientResult;
        }
        return patientResult;
    }

    private QueryWrapper<?> setQueryWrapperItem(ZyDetailCharge v) {
        QueryWrapper<?> qw = new QueryWrapper<>();
        qw.eq("inpatient_no", v.getInpatientNo())
                .eq("admiss_times", v.getAdmissTimes())
                .eq("ledger_sn", v.getLedgerSn())
                .eq("infant_flag", v.getInfantFlag())
                .ne("isnull(trans_flag_yb, 0)", 2)
                .ne("order_no", new BigDecimal(6));
        if (StringUtil.notBlank(v.getChargeCode())) {
            qw.eq("charge_code_mx", v.getChargeCode());
        }
        if (StringUtil.notBlank(v.getStartTime())) {
            qw.ge("charge_date", v.getStartTime())
                    .le("charge_date", v.getEndTime());
        }
        // 因为这里是护士也要看的所以护士可以看患者所以科室的费用
        if (StringUtil.notBlank(v.getDept())) {
            qw.in("exec_unit", v.getDept());
        }
        int order = Integer.parseInt(v.getOrderNo().stripTrailingZeros().toPlainString());
        if (order != 2 && order != 1) {
            qw.eq("order_no", order);
        }
        if (order == 1) {
            qw.gt("len(order_no)", new BigDecimal(2));
        }
        if (v.getTuiFeiFlag() == 0) {
            qw.isNull("ori_detail_sn")
                    .ge("charge_fee", 0);
        }
        if (v.getTuiFeiFlag() == 1) {
            qw.and(q -> {
                q.gt("ori_detail_sn", 0)
                        .or()
                        .lt("charge_fee", 0);
            });
        }
        if (v.getTuiFeiFlag() == 2) {
            qw.eq("ori_detail_sn", -1);
        }
        if (v.getActOrderNo() != null) {
            qw.eq("order_no", v.getActOrderNo());
        }
        return qw;
    }


    /**
     * 搜索项目信息
     *
     * @param pyCode 拼音码
     * @return 返回项目信息
     */
    public ResultVo<List<FeeSelect>> getChargeCode(String pyCode) {
        return ResultVoUtil.success(dao.getChargeCode(StringUtil.isContainChinese(pyCode)));
    }


    /**
     * 退费
     *
     * @param xiangMu
     * @param tuiFeiList
     * @param updateItemTags
     * @param maxDetailSn
     * @param item
     * @return
     */
    private static int setRefund(List<ZyDetailCharge> xiangMu, List<ZyDetailCharge> tuiFeiList, List<Integer> updateItemTags, int maxDetailSn, ZyDetailCharge item) {
        // 取负数的费用
        item.setChargeFee(item.getChargeFee().negate());
        item.setChargeAmount(item.getChargeAmount().negate());
        // 执行人
        item.setOpIdCode(TokenUtil.getInstance().getTokenUserId());
        item.setOriDetailSn(item.getDetailSn());
        item.setOldGenTime(DateUtil.formatDatetime(item.getGenTime(), DateUtil.DEFAULT_PATTERN));
        // 设置 流水号
        item.setDetailSn(maxDetailSn += 1);
        // 向退费 list 里面添加
        tuiFeiList.add(item);
        xiangMu.add(item);
        updateItemTags.add(item.getOriDetailSn());
        return maxDetailSn;
    }


    @Data
    public static class SearchMb {
        private String searchName;
        private long total = 0;
        private long currentPage;
        private long pageSize;
    }


    /**
     * 获取模板
     *
     * @return 返回模板
     */
    public ResultVo<IPage<ZyDetailCharge>> getMuBan(SearchMb params) {
        IPage<ZyDetailCharge> page = new Page<>(params.getCurrentPage(), params.getPageSize(), params.getTotal() == 0);
        QueryWrapper<?> qw = new QueryWrapper<>();
        UserInfo userInfo = userCache.getUserInfoByToken();
        qw.ne("isnull(pattern_name,'')", "''");
        if (publicServer.noNeedRule()) {
            qw.eq("op_dept", userInfo.getDeptCode());
        }
        if (StrUtil.isNotBlank(params.getSearchName())) {
            qw.and(
                    queryWrapper -> {
                        queryWrapper.like("pattern_name", params.getSearchName())
                                .or()
                                .like("py_code", params.getSearchName().toUpperCase())
                                .or()
                                .like("d_code", params.getSearchName().toUpperCase())

                        ;
                    }
            );
        }
        dao.getMuBan(page, qw);
        return ResultVoUtil.success(page);
    }

    /**
     * 获取模板的具体信息
     *
     * @param patternName 模板名称
     * @param opIdCode    存模板的人
     * @return 返回具体的模板
     */
    public ResultVo<List<ZyDetailCharge>> getMuBanXinXi(String patternName, String opIdCode) {
        return ResultVoUtil.success(dao.getMuBanXinXi(patternName, opIdCode));
    }

    /**
     * 获取科室
     *
     * @return 返回科室信息
     */
    public ResultVo<List<GetDropdownBox>> getDept() {
        return ResultVoUtil.success(dao.getDept());
    }

    /**
     * 获取病区
     *
     * @return 返回科室信息
     */
    public ResultVo<List<GetDropdownBox>> getWard() {
        return ResultVoUtil.success(dao.getWard());
    }

    /**
     * 通过拼音码 来搜索项目
     *
     * @param pyCode               拼音码
     * @param xiangMuHuoYaoPinFlag 判断是查询项目还是药品 0 - 项目 1- 药品
     * @return 返回项目
     */
    public ResultVo<List<ZyDetailCharge>> queryXiangMu(String pyCode, Integer xiangMuHuoYaoPinFlag) {
        if (xiangMuHuoYaoPinFlag == 0) {
            return ResultVoUtil.success(dao.queryXiangMu("%" + pyCode.toUpperCase() + "%"));
        }
        return ResultVoUtil.success(dao.queryYaoPin("%" + pyCode.toUpperCase() + "%"));
    }

    /**
     * 这个项目录入
     *
     * @param param 参数
     * @return 返回提示语句
     */
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> xiangMuFeiYongShangChuan(ZyDetailCharge param) {
        if (param.getList().size() > 50) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "一次性项目录入大于50条");
        }
        StringBuilder errorStr = new StringBuilder();
        if (StringUtil.isBlank(param.getInpatientNo()) || param.getAdmissTimes() == null) {
            errorStr.append("住院号和住院次数为空<br />");
        }
        if (param.getList().isEmpty()) {
            errorStr.append("没有要录入的项目 <br />");
        }
        if (StringUtil.isBlank(param.getWard())) {
            errorStr.append("病区为空 <br />");
        } else if (param.getWard().startsWith("8")) {
            errorStr.append("申请科室为病区请刷新页面<br />");
        }
        if (StringUtil.isBlank(param.getDept())) {
            errorStr.append("申请科室为空 <br />");
        }
        if (StringUtil.isBlank(param.getZySerialNo())) {
            errorStr.append("住院流水号为空 <br />");
        }
        if (dao.getHuanZheSFZaiYuan(param.getInpatientNo(), param.getAdmissTimes()) == 0) {
            errorStr.append("没有患者的在院信息 <br />");
        }
        if (publicServer.needRule(RuleId.财务.getId())) {
            param.setOrderNo(new BigDecimal(6));
        }

        if (errorStr.length() > 0) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_HTML_ERROR, errorStr.toString());
        }

        // 收费项目的编码
        List<String> shiFouTingYongXiangMu = new ArrayList<>();

        param.getList().forEach(item -> {
            shiFouTingYongXiangMu.add(item.getChargeCodeMx());
        });

        List<String> yiTingYong = dao.chaXunFeiYongShiFouTingYong(shiFouTingYongXiangMu);
        if (ListUtil.notBlank(yiTingYong)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "费用录入错误，包含已停用的项目 【" + JSON.toJSONString(yiTingYong) + "】");
        }
        // 婴儿 要特殊处理
        // 如果带有这个 $ 说明是婴儿
        int infantFlag = PublicServer.getInfantFlag(param.getInpatientNo());
        param.setInpatientNo(PublicServer.getInpatientNo(param.getInpatientNo()));
        // 获取最大流水号
        Integer maxDetailSn = publicServer.getMaxDetailSn(param.getInpatientNo(), param.getAdmissTimes());
        // 获取项目的 总费用
        BigDecimal sum = new BigDecimal(0);
        // 录入人的id
        param.setOpIdCode(TokenUtil.getInstance().getTokenUserId());
        List<ZyDetailCharge> yaoPingShenQingDan = new ArrayList<>();

        Integer settlementFlag = dao.getHuanZheSFJieSuan(param.getInpatientNo(), param.getAdmissTimes());
        if (settlementFlag == null || settlementFlag != 0) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "该患者已经结算了");
        }
        Date now = new Date();
        // 药品
        for (ZyDetailCharge zyDetailCharge : param.getList()) {
            if (zyDetailCharge.getSerial().equals("00")) {
                zyDetailCharge.setChargeCode(zyDetailCharge.getChargeCodeMx());
            } else {
                ZyBillItemCache.ZyBillItem zyBillItem = zyBillItemCache.get(zyDetailCharge.getBillItemCode());
                if (zyBillItem != null) {
                    zyDetailCharge.setChargeCode(zyBillItem.getChargeCode());
                }
            }
            if (param.getChargeDate() != null) {
                zyDetailCharge.setChargeDate(param.getChargeDate());
            }
            if (zyDetailCharge.getChargeDate() == null) {
                zyDetailCharge.setChargeDate(now);
            }
            if (zyDetailCharge.getChargeAmount() == null || zyDetailCharge.getAmount() == null) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "数量或金额不能为空。");
            }
            // 判断患者的费用是否存在负数
            if (zyDetailCharge.getChargeAmount().signum() == -1 || zyDetailCharge.getAmount().signum() == -1) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "不能录入负数");
            }
            if (zyDetailCharge.getChargeAmount().compareTo(new BigDecimal(0)) == 0 || zyDetailCharge.getAmount().compareTo(new BigDecimal(0)) == 0) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "录入费用为 0");
            }
            if (StringUtil.isBlank(zyDetailCharge.getChargeCodeMx())) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "项目编码空值。");
            }
            if (StringUtil.isBlank(zyDetailCharge.getDeptCode())) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "执行科室为空。");
            }
            if (zyDetailCharge.getChargeCodeMx() == null) {
                zyDetailCharge.setChargeCodeMx(zyDetailCharge.getChargeCode());
            }
            // 0 - 住院费用  6 - 门急诊 3 - 医技
            if (param.getOrderNo() != null) {
                zyDetailCharge.setOrderNo(param.getOrderNo());
            } else {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医嘱号为空");
            }
            sum = sum.add(zyDetailCharge.getChargeAmount().multiply(zyDetailCharge.getAmount()));
            // 这里不会保存单价 只会总价
            zyDetailCharge.setChargeAmount(zyDetailCharge.getChargeAmount().multiply(zyDetailCharge.getAmount()));
            zyDetailCharge.setDetailSn(maxDetailSn += 1);
            if (!"00".equals(zyDetailCharge.getSerial())) {
                ZyDetailCharge shenQing = new ZyDetailCharge();
                BeanUtils.copyProperties(zyDetailCharge, shenQing);
                shenQing.setChargeFee(zyDetailCharge.getChargeAmount());
                shenQing.setChargeAmount((zyDetailCharge.getAmount()));
                shenQing.setGroupNo("73");
                yaoPingShenQingDan.add(shenQing);
            }
            if (zyDetailCharge.getSelfFlag() == null) {
                zyDetailCharge.setSelfFlag("0");
            }

        }
        Integer ledgerSn = publicServer.getLedgerSn(param.getInpatientNo(), param.getAdmissTimes());
        // 在此处 插入费用
        dao.chaRuFeiYong(param, param.getList(),
                infantFlag,
                ledgerSn,
                DateUtil.formatDatetime(param.getChargeDate(),
                        DateUtil.DEFAULT_PATTERN),
                param.getReceiptNo());
        if (ListUtil.notBlank(yaoPingShenQingDan)) {
            dao.shenQingYaoPing(param, yaoPingShenQingDan, infantFlag, ledgerSn, TokenUtil.getInstance().getTokenUserId());
        }
        log.info("项目录入费用上传 ==》 操作人：{},数据：{}", param.getOpIdCode(), JSON.toJSONString(param));
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "费用上传成功。");
    }

    /**
     * 上传以及修改项目录入模板
     *
     * @param zyDetailCharge 模板的一些数据
     * @return 返回成功提示
     */
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> shangChuanMuBan(ZyDetailCharge zyDetailCharge) {
        UserInfo userInfoByToken = userCache.getUserInfoByToken();
        if (dao.chaKanMuBanMingChengSFcunZi(zyDetailCharge.getName(), userInfoByToken.getCode()) > 0) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "模板名称重复，๐·°(৹˃̵﹏˂̵৹)°·๐");
        }
        zyDetailCharge.setDeptCode(userInfoByToken.getDeptCode());
        zyDetailCharge.setOpIdCode(userInfoByToken.getCode());
        for (ZyDetailCharge detailCharge : zyDetailCharge.getList()) {
            if (StringUtil.notBlank(zyDetailCharge.getBillItemCode())) {
                if ("001".equals(detailCharge.getBillItemCode()) || "002".equals(detailCharge.getBillItemCode())) {
                    detailCharge.setSerial("01");
                    detailCharge.setGroupNo("73");
                } else if ("028".equals(zyDetailCharge.getBillItemCode())) {
                    zyDetailCharge.setSerial("01");
                    zyDetailCharge.setChargeCode("BILL28");
                } else {
                    //  Serial 00 项目标志 01 药品标志
                    detailCharge.setSerial("00");
                }
            }
        }
        // 在创建新的模板之前 需要先删除 原来的
        dao.delMuBan(zyDetailCharge.getName(), zyDetailCharge.getOpIdCode());
        dao.baoCunMuBan(zyDetailCharge);
        log.info("保存项目录入模板 ==》 操作人 ：{}，数据：{}", zyDetailCharge.getOpIdCode(), JSON.toJSONString(zyDetailCharge));
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "保存模板成功。ㄟ(≧◇≦)ㄏ");
    }

    /**
     * 医嘱退费匹配
     * 第一次匹配使用 收费日期，数量，项目编码，医嘱号，账页号 来进行匹配
     * 第二次匹配使用，数量，项目编码，账页号，执行科室来进行匹配的
     *
     * @param inpatientNo 住院号
     * @param admissTimes 住院次数
     * @return 返回是否匹配成功
     */
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> yiZhuTuiFeiPiPei(String inpatientNo, Integer admissTimes, String deptCode) {
        if (StringUtil.isBlank(inpatientNo) || admissTimes == null || StringUtil.isBlank(deptCode)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "患者信息不全。");
        }
        int infantFlag = PublicServer.getInfantFlag(inpatientNo);
        inpatientNo = PublicServer.getInpatientNo(inpatientNo);
        Integer ledgerSn = publicServer.getLedgerSn(inpatientNo, admissTimes);

        // 没有必要限制科室了
        List<String> keShiLeiBiao = new ArrayList<>();

        // 获取正的医嘱费用
        List<ZyDetailCharge> getYiZhuFeiYongZhenShu = dao.getYiZhuFeiYong(inpatientNo, admissTimes, ledgerSn, ">", infantFlag, keShiLeiBiao);
        // 获取负的医嘱费用
        List<ZyDetailCharge> getYiZhuFeiYongFuShu = dao.getYiZhuFeiYong(inpatientNo, admissTimes, ledgerSn, "<", infantFlag, keShiLeiBiao);
        // 获取负数的退费数据 主要是用来判断 这一条正的是否退费了。
        List<ZyDetailCharge> tuiFeiList = dao.tuiFeiList(inpatientNo, admissTimes, infantFlag);
        if (!tuiFeiList.isEmpty()) {
            Map<Integer, Integer> map = new HashMap<>();
            for (ZyDetailCharge zyDetailCharge : tuiFeiList) {
                map.put(zyDetailCharge.getOriDetailSn(), zyDetailCharge.getDetailSn());
            }
            getYiZhuFeiYongZhenShu.forEach(item -> {
                if (map.containsKey(item.getDetailSn())) {
                    item.setTuiFeiFlag(1);
                }
            });
        }
        // 需要保存需要匹配的一些流水数据
        List<ZyDetailCharge> piPei = new ArrayList<>();
        // 此处是需要二次匹配的 list
        List<ZyDetailCharge> erCiPiPei = new ArrayList<>();
        // 用map 来保存正数的信息，但是有可能匹配的条件中map 的 key会一致 所以在这里使用 java8 的新特性 stream 流来进行分组 这样就不会因为key 一样导致数据被覆盖了
        // 第一次 匹配 根据 医嘱号 收费时间 项目编码 数量 账页号
        Map<String, List<ZyDetailCharge>> zhenShuMap = getYiZhuFeiYongZhenShu.stream().collect(Collectors.groupingBy(item -> item.getOrderNo() + DateUtil.formatDatetime(item.getChargeDate()) + item.getChargeCodeMx() + item.getChargeAmount() + item.getChargeFee() + item.getLedgerSn()));
        // 用负数拼接的 key 去查找
        for (ZyDetailCharge fuShu : getYiZhuFeiYongFuShu) {
            String key = fuShu.getOrderNo() + DateUtil.formatDatetime(fuShu.getChargeDate()) + fuShu.getChargeCodeMx() + fuShu.getChargeAmount().negate() + fuShu.getChargeFee().negate() + fuShu.getLedgerSn();
            if (zhenShuMap.containsKey(key)) {
                for (ZyDetailCharge zyDetailCharge : zhenShuMap.get(key)) {
                    if (zyDetailCharge.getTuiFeiFlag() == null && zyDetailCharge.getOriDetailSn() == null) {
                        fuShu.setOriDetailSn(zyDetailCharge.getDetailSn());
                        zyDetailCharge.setTuiFeiFlag(1);
                        piPei.add(fuShu);
//                        log.info("第一次匹配==》流水:{}，匹配流水：{}，", fuShu.getDetailSn(), fuShu.getOriDetailSn());
                        break;
                    }
                }
            } else {
                // 这个是需要进行二次匹配的
                erCiPiPei.add(fuShu);
            }
        }
        // 下面是二次匹配
        if (!erCiPiPei.isEmpty()) {
            // 二次匹配 条件为 执行科室 项目编码 数量 账页号
            Map<String, List<ZyDetailCharge>> erCiPiPeiZhenShu = getYiZhuFeiYongZhenShu.stream().collect(Collectors.groupingBy(item -> item.getExecUnit() + item.getChargeCodeMx() + item.getChargeAmount() + item.getChargeFee() + item.getLedgerSn()));
            // 开始二次匹配
            for (ZyDetailCharge zyDetailCharge : erCiPiPei) {
                String key = zyDetailCharge.getExecUnit() + zyDetailCharge.getChargeCodeMx() + zyDetailCharge.getChargeAmount().negate() + zyDetailCharge.getChargeFee().negate() + zyDetailCharge.getLedgerSn();
                if (erCiPiPeiZhenShu.containsKey(key)) {
                    for (ZyDetailCharge detailCharge : erCiPiPeiZhenShu.get(key)) {
                        if (detailCharge.getTuiFeiFlag() == null && detailCharge.getOriDetailSn() == null) {
                            zyDetailCharge.setOriDetailSn(detailCharge.getDetailSn());
                            detailCharge.setTuiFeiFlag(1);
                            piPei.add(zyDetailCharge);
//                            log.info("第二次匹配==》流水:{}，匹配流水：{}", zyDetailCharge.getDetailSn(), zyDetailCharge.getOriDetailSn());
                            break;
                        }
                    }
                }
            }
        }
        // 开始匹配
        if (!piPei.isEmpty()) {
            // 100 条的更新  ListUtils.partition 用来拆分 list size 是拆分的条数
            List<List<ZyDetailCharge>> fenDuan = ListUtils.partition(piPei, 100);
            for (List<ZyDetailCharge> list : fenDuan) {
                dao.yiZhuTuiFeiPiPei(inpatientNo, admissTimes, list, infantFlag);
            }
            publicServer.genXingYuanLiuShuiBiaoZhi(inpatientNo, admissTimes, ledgerSn);
//            log.info("医嘱退费匹配 ==》 操作人：{}，住院号：{}，住院次数：{}", TokenUtil.getInstance().getTokenUserId(), inpatientNo, admissTimes);
            return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, String.format("匹配成功共：{%d}条，匹配成功：{%s}条", getYiZhuFeiYongFuShu.size(), piPei.size()));
        }
        publicServer.genXingYuanLiuShuiBiaoZhi(inpatientNo, admissTimes, ledgerSn);
        return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST, String.format("该患者有【%d】条,未能匹配 ", getYiZhuFeiYongFuShu.size()));
    }

    /**
     * 此处删除模板 这个模板是录入住院费用的 模板
     *
     * @param patterName 模板名称
     * @param opIdCode   创建模板人的姓名
     * @return 返回提示
     */
    public ResultVo<String> shanChuMuBan(String patterName, String opIdCode) {
//        log.info("删除项目模板 ==》操作人：{}，模板名称：{}", TokenUtil.getInstance().getTokenUserId(), patterName);
        dao.delMuBan(patterName, opIdCode);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "删除成功，o(^▽^)o");
    }

    /**
     * 生成拼音和五笔码
     *
     * @param inputStr 中文
     * @return 返回编码
     */
    public ResultVo<ZyDetailCharge> getPyCode(String inputStr) {
        ZyDetailCharge zyDetailCharge = new ZyDetailCharge();
        zyDetailCharge.setPyCode(PingYinUtils.pyShouZiMuDaXie(inputStr));
        zyDetailCharge.setWbCode(PingYinUtils.getWBCode(inputStr));
        return ResultVoUtil.success(zyDetailCharge);
    }

    /**
     * 根据对应的病区来获取科室
     *
     * @param ward 科室编码
     * @return 返回对应的
     */
    public ResultVo<List<GetDropdownBox>> getBingQuDuiYingKeShi(String ward) {
        return ResultVoUtil.success(dao.getBingQuDuiYingKeShi(ward));
    }

    public ResultVo<ZyActpatient> weiGuiFeiYongFenXi(String inpatientNo, String execUnit) {
        ZyActpatient patient = publicServer.huoQuHuanZheXinXi(inpatientNo);
        List<String> keShi = publicServer.huoQuBingFangDeKeShi(execUnit);
        publicServer.genXingYuanLiuShuiBiaoZhi(patient.getInpatientNo(), patient.getAdmissTimes(), patient.getLedgerSn());
        // 药品 分大包装和小包装 可能大包装 匹配了 小包装没有 匹配 所以这里编码同步 一下
        List<String> yaoPingBianMaTongBu = dao.weiGuiYaoPinInt(patient.getInpatientNo(), patient.getAdmissTimes(), patient.getLedgerSn(), patient.getInfantFlag());

        // 这里退药 医嘱 有可能会没有携带 执行科室
        List<ZyDetailCharge> huoQuYaoPingZhongKeShiWeiKongDe = dao.huoQuYaoPingZhongKeShiWeiKongDe(inpatientNo, patient.getAdmissTimes(), patient.getLedgerSn());
        if (!huoQuYaoPingZhongKeShiWeiKongDe.isEmpty()) {
            dao.yiZhuTuiFeiGenXingZhiXingKeShi(inpatientNo, patient.getAdmissTimes(), patient.getLedgerSn(), huoQuYaoPingZhongKeShiWeiKongDe);
        }
        if (!yaoPingBianMaTongBu.isEmpty()) {
            dao.genXinYaoPingPiPeiXinXi(yaoPingBianMaTongBu);
        }
        patient.setWeiPiPei(new ArrayList<>());
        patient.setWeiXieDaiYuanLiuShui(new ArrayList<>());

        if ("al".equals(patient.getResponceType())) {
            patient.getWeiPiPei().addAll(dao.gongShangWeiPiPei(patient.getInpatientNo(), patient.getAdmissTimes(), patient.getLedgerSn(), patient.getInfantFlag()));
        } else {
            patient.getWeiPiPei().addAll(dao.weiGuiYaoPin(patient.getInpatientNo(), patient.getAdmissTimes(), patient.getLedgerSn(), patient.getInfantFlag()));
            patient.getWeiPiPei().addAll(dao.weiGuiXiangMu(patient.getInpatientNo(), patient.getAdmissTimes(), patient.getLedgerSn(), patient.getInfantFlag()));
        }
        patient.getWeiXieDaiYuanLiuShui().addAll(dao.weiXieDaiYuanLiuShuiXiangMu(patient.getInpatientNo(), patient.getAdmissTimes(), patient.getLedgerSn(), patient.getInfantFlag(), keShi, patient.getChuYuanYiZhu()));
        patient.getWeiXieDaiYuanLiuShui().addAll(dao.weiXieDaiYuanLiuShuiYaoPing(patient.getInpatientNo(), patient.getAdmissTimes(), patient.getLedgerSn(), patient.getInfantFlag(), keShi, patient.getChuYuanYiZhu()));

        return ResultVoUtil.success(patient);
    }

    public ResultVo<List<ZyDetailCharge>> huoQuZhenShuKePiPei(String inpatientNo, Integer admissTimes, Integer ledgerSn, String chargeCodeMx, String execUnit, String orderNo, String startTime, String endTime, String riQiPaiXu) {
        execUnit = StringUtil.isBlank(execUnit) ? null : execUnit;
        List<ZyDetailCharge> zhenShuFeiYong = dao.weiGuiZhenShuPiPei(publicServer.getInpatientNo(inpatientNo), admissTimes, ledgerSn, PublicServer.getInfantFlag(inpatientNo), chargeCodeMx, execUnit, orderNo, startTime, endTime, riQiPaiXu);

        if (ListUtil.isBlank(zhenShuFeiYong)) {
            zhenShuFeiYong.addAll(dao.weiGuiZhenShuPiPei(publicServer.getInpatientNo(inpatientNo), admissTimes, ledgerSn, PublicServer.getInfantFlag(inpatientNo), chargeCodeMx, null, orderNo, startTime, endTime, riQiPaiXu));
        }
        if (ListUtil.isBlank(zhenShuFeiYong)) {
            return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST, "没有查询到该负数费用的对应正数。", dao.genJuBianMaChaZhaoZhenShuFeiYong(publicServer.getInpatientNo(inpatientNo), admissTimes, ledgerSn, PublicServer.getInfantFlag(inpatientNo), chargeCodeMx, startTime, endTime, riQiPaiXu));
        }
        List<ZyDetailCharge> yuEr = dao.tuiFeiYuEr1(publicServer.getInpatientNo(inpatientNo), admissTimes, ledgerSn, chargeCodeMx, execUnit);
        Map<String, ZyDetailCharge> yuErPiPei = new HashMap<>();
        for (ZyDetailCharge item : yuEr) {
            String key = item.getInpatientNo() + item.getAdmissTimes() + item.getDetailSn() + item.getChargeCodeMx();
            yuErPiPei.put(key, item);
        }
        for (int i = 0, len = zhenShuFeiYong.size(); i < len; i++) {
            ZyDetailCharge zy = zhenShuFeiYong.get(i);
            String key = zy.getInpatientNo() + zy.getAdmissTimes() + zy.getDetailSn() + zy.getChargeCodeMx();
            if (yuErPiPei.containsKey(key)) {
                if (BigUtils.dengYu(yuErPiPei.get(key).getYiTuiFei(), 0)) {
                    zhenShuFeiYong.remove(i);
                    len--;
                    i--;
                } else {
                    // 这里是 set 退费的余额
                    zy.setYiTuiFei(yuErPiPei.get(key).getYiTuiFei());
                }
            }
        }
        return ResultVoUtil.success(zhenShuFeiYong);
    }

    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> caiFenPiPei(ZyDetailCharge zyDetailCharge) {
        String inpatientNo = PublicServer.getInpatientNo(zyDetailCharge.getInpatientNo());
        Integer infantFlag = PublicServer.getInfantFlag(zyDetailCharge.getInpatientNo());
        if (ListUtil.isBlank(zyDetailCharge.getList())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请选择数据。");
        }
        int[] detailSnList = new int[zyDetailCharge.getList().size()];
        for (int i = 0; i < zyDetailCharge.getList().size(); i++) {
            detailSnList[i] = zyDetailCharge.getList().get(i).getDetailSn();
        }
        ZyDetailCharge zy = dao.piPeiXinXiFuShu(inpatientNo, zyDetailCharge.getAdmissTimes(), zyDetailCharge.getLedgerSn(), infantFlag, zyDetailCharge.getDetailSn());
        if (zy == null) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "未找到负数费用信息，可能已经被删除了，请刷新页面重试。");
        } else if (zy.getOriDetailSn() != null || "2".equals(zy.getTransFlagYb())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "该负数费用已被正负相抵。");
        }

        List<ZyDetailCharge> zhenShuShuJu = dao.piPeiXinXi(inpatientNo, zyDetailCharge.getAdmissTimes(), zyDetailCharge.getLedgerSn(), infantFlag, detailSnList);
        if (zhenShuShuJu.size() != 1) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "每次只能匹配一条。");
        }

        Map<Integer, ZyDetailCharge> tuiFeiYuErPiPei = dao.tuiFeiYuEr2(inpatientNo, zyDetailCharge.getAdmissTimes(), zyDetailCharge.getLedgerSn(), infantFlag, detailSnList)
                .stream()
                .collect(Collectors.toMap(ZyDetailCharge::getOriDetailSn, a -> a, (k1, k2) -> k1));

        BigDecimal chargeFeeSum = new BigDecimal(0);
        BigDecimal chargeAmountSum = new BigDecimal(0);

        for (ZyDetailCharge detailCharge : zhenShuShuJu) {
            if ("2".equals(detailCharge.getTransFlagYb())) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("流水号为：{%d}，已被正负抵消。", detailCharge.getDetailSn()));
            }
            if (tuiFeiYuErPiPei.containsKey(detailCharge.getDetailSn())) {
                detailCharge.setChargeFee(detailCharge.getChargeFee().add(tuiFeiYuErPiPei.get(detailCharge.getDetailSn()).getChargeFee()));
            }
            chargeFeeSum = chargeFeeSum.add(detailCharge.getChargeFee());
            chargeAmountSum = chargeAmountSum.add(detailCharge.getChargeAmount());
        }
        if (!zy.getYbSelfFlag().equals(zhenShuShuJu.get(0).getYbSelfFlag())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "无法匹配这条医嘱，费用一条是自费，一条是医保，无法匹配。");
        }
        if (BigUtils.bigDaYu(chargeFeeSum, zy.getChargeFee().negate()) || BigUtils.dengYu(chargeFeeSum, zy.getChargeFee().negate())) {
            dao.zhiYouYiGeJiuGenXingFuShuLiuShui(zyDetailCharge.getInpatientNo(), zyDetailCharge.getAdmissTimes(), zyDetailCharge.getLedgerSn(), zyDetailCharge.getDetailSn(), zhenShuShuJu.get(0).getDetailSn());
            publicServer.genXingYuanLiuShuiBiaoZhi(inpatientNo, zyDetailCharge.getAdmissTimes(), zyDetailCharge.getLedgerSn());
            return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "费用匹配成功。");
        }
        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("负数费用：{%.2f}，匹配费用：{%.2f} \n 负数数量：{%.2f}，匹配数量：{%.2f}", zy.getChargeFee().negate(), chargeFeeSum, zy.getChargeAmount().negate(), chargeAmountSum));
    }

    public void exportExcel(HttpServletResponse response, ZyDetailCharge param) {
        param.setPageSize(param.getTotal());
        param.setCurrentPage(1);
        List<ZyDetailCharge> list = getHuanZheFeiYong(param).getData();
        String[] title = {"流水号", "医嘱号", "录入日期", "项目编码", "项目名称", "药品名称", "执行时间", "执行科室", "申请科室", "金额", "数量", "状态", "录入人", "账单码"};
        String[][] content = new String[list.size()][];
        for (int i = 0; i < list.size(); i++) {
            content[i] = new String[title.length];
            ZyDetailCharge pojo = list.get(i);
            content[i][0] = String.valueOf(pojo.getDetailSn());
            content[i][1] = String.valueOf(pojo.getOrderNo());
            content[i][2] = DateUtil.formatDatetime(pojo.getChargeDate());
            content[i][3] = pojo.getChargeCodeMx();
            content[i][4] = pojo.getChargeName();
            content[i][5] = pojo.getDrugname();
            content[i][6] = DateUtil.formatDatetime(pojo.getGenTime());
            content[i][7] = pojo.getExecDept();
            content[i][8] = pojo.getDeptCode();
            content[i][9] = pojo.getChargeFee().toString();
            content[i][10] = pojo.getChargeAmount().toString();
            content[i][11] = "1".equals(pojo.getChargeStatus()) ? "录入" : "2".equals(pojo.getChargeStatus()) ? "上账" : "结算";
            content[i][12] = pojo.getOpName();
            content[i][13] = pojo.getBillItemName();
        }
        ExcelUtil.exportExcel(response, title, content);
    }

    public ResultVo<String> xiuGaiZiFeiBiaoZhi(ZyDetailCharge param) {
        QueryWrapper<?> qw = new QueryWrapper<>();
        qw.eq("inpatient_no", param.getInpatientNo());
        qw.eq("admiss_times", param.getAdmissTimes());
        qw.eq("ledger_sn", param.getLedgerSn());
        List<Integer> detailList = new ArrayList<>();
        for (ZyDetailCharge item : param.getList()) {
            detailList.add(item.getDetailSn());
        }
        qw.in("detail_sn", detailList);
        // 把费用标志改成 0
        dao.xiuGaiZiFeiZhiYiBaoBiaoZhi(qw);
        ZyPatientInfo p = EntityCopy.Copy(param, ZyPatientInfo.class);
        p.setDetailSns(detailList);
        siZyService.revokeUploadFees(p);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }

    public ResultVo<String> rejectNotGeneratedMedicationList(String patNo, Integer times) {
        log.info("拒绝生成的药单 ==> 住院号：{}，住院次数：{}，操作人：{}", patNo, times, TokenUtil.getInstance().getTokenUserId());
        Date disdate;
        disdate = siSettleApplyDao.selectActOrderDisDate("yz_act_order", patNo, times);
        if (null == disdate) {
            disdate = siSettleApplyDao.selectActOrderDisDate("yz_inact_order", patNo, times);
        }
        if (null == disdate) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "患者没有出院医嘱，无法执行该操作！");
        }
        dao.rejectNotGeneratedMedicationList(patNo, times);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }

    public ResultVo<List<DrugReturnForm>> getNoMedicineReturnOrderGenerated(String startDate, String endDate, String groupNo) {
        UserInfo userInfo = userCache.getUserInfoByToken();
        return ResultVoUtil.success(
                groupingValues(
                        dao.selectNoMedicineReturnOrderGenerated(
                                startDate,
                                endDate,
                                userInfo.getDeptCode(),
                                groupNo),
                        null));
    }

    public List<DrugReturnForm> groupingValues(List<DrugReturnForm> list, Consumer<DrugReturnForm> consumer) {
        if (ListUtil.isBlank(list)) {
            return list;
        }
        Map<String, DrugReturnForm> map = new HashMap<>(list.size());
        list.forEach(item -> {
            if (consumer != null) {
                consumer.accept(item);
            }
            if (map.containsKey(item.getChargeCode())) {
                DrugReturnForm temp = map.get(item.getChargeCode());
                temp.setAmount(temp.getAmount().add(item.getAmount()));
                temp.setRetprice(temp.getRetprice().add(item.getRetprice().multiply(item.getAmount().abs())));
            } else {
                map.put(item.getChargeCode(), item);
            }
        });
        return new ArrayList<>(map.values());
    }

    /**
     * 生成药单
     *
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @param groupNo   药房
     * @return 返回提示
     */
    public ResultVo<JSONObject> generateMedicationList(String startDate, String endDate, String groupNo, Integer refundReason) {
        UserInfo us = userCache.getUserInfoByToken();
        Integer pageNo = publicServer.getTheDrugListNo();
        getThis().generateMedicationListFunc(startDate, endDate, groupNo, pageNo, us.getDeptCode(), refundReason);
        return getAPrescriptionByPageNo(pageNo);
    }

    /**
     * 生成药品单
     *
     * @param startDate 开始时间
     * @param endDate   结束
     * @param groupNo   药房
     * @param pageNo    药单号
     * @param dept      科室
     */
    @Transactional(rollbackFor = Exception.class)
    public void generateMedicationListFunc(String startDate, String endDate, String groupNo, Integer pageNo, String dept, Integer refundReason) {
        int count = dao.generateMedicationList(startDate, endDate, dept, groupNo, pageNo);
        if (count == 0) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "取数为空无法生成药单。");
        }
        dao.drugReturnForm(pageNo, dept, TokenUtil.getInstance().getTokenUserId(), groupNo, refundReason);
    }

    /**
     * 获取指定的药单号
     *
     * @param startDate 时间
     * @param endDate   时间
     * @return 药单
     */
    public ResultVo<List<DrugReturnForm>> getPrescription(String startDate, String endDate) {
        UserInfo us = userCache.getUserInfoByToken();
        return ResultVoUtil.success(dao.getPrescription(startDate, endDate, us.getDeptCode()));
    }

    /**
     * 根据药单号获取明细
     *
     * @param pageNo
     * @return
     */
    public ResultVo<JSONObject> getAPrescriptionByPageNo(Integer pageNo) {
        JSONObject js = new JSONObject();
        // 总金额
        AtomicReference<BigDecimal> totalFee = new AtomicReference<>(new BigDecimal("0"));
        // 计算数据
        List<DrugReturnForm> list = groupingValues(dao.getAPrescriptionByPageNo(pageNo), (item) -> {
            BigDecimal amount = item.getAmount().abs();
            totalFee.set(totalFee.get().add(amount.multiply(item.getRetprice())));
        });

        js.put("totalFee", totalFee.get().negate());
        js.put("refundReason", dao.selectRefundReasonByPageNo(pageNo));
        js.put("data", list);
        js.put("pageNo", pageNo);
        return ResultVoUtil.success(js);
    }

}

