package com.openhis.web.adjustprice.appservice.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.core.domain.entity.SysDictData;
import com.core.common.enums.AdjustPriceEnum;
import com.core.common.utils.AssignSeqUtil;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.core.system.service.ISysDictDataService;
import com.openhis.administration.domain.ChangePriceRecord;
import com.openhis.administration.dto.ChangePriceDataDto;
import com.openhis.administration.dto.ChargeItemDefDetailPriceDto;
import com.openhis.administration.dto.HealthcareDto;
import com.openhis.administration.dto.OrgDataDto;
import com.openhis.administration.service.*;
import com.openhis.common.constant.CommonConstants;
import com.openhis.common.constant.PromptMsgConstant;
import com.openhis.common.enums.*;
import com.openhis.common.utils.EnumUtils;
import com.openhis.common.utils.HisQueryUtils;
import com.openhis.common.utils.RedisKeys;
import com.openhis.common.utils.RedisUtil;
import com.openhis.medication.service.IMedicationService;
import com.openhis.web.adjustprice.appservice.IAdjustPriceService;
import com.openhis.web.adjustprice.dto.AdjustPriceDataVo;
import com.openhis.web.adjustprice.dto.AdjustPriceManagerSearchParam;
import com.openhis.web.adjustprice.dto.ChangePricePageDto;
import com.openhis.web.adjustprice.mapper.AdjustPriceMapper;
import com.openhis.web.inventorymanage.dto.InventorySearchParam;
import com.openhis.workflow.dto.ActivityDto;
import com.openhis.workflow.dto.AdjustPriceDto;
import com.openhis.workflow.service.IActivityDefinitionService;
import com.openhis.workflow.service.IInventoryItemService;

/**
 * @ClassName AdjustPriceServiceImpl
 * @Description 调价业务实现
 * @Author raymond
 * @Date 2025/10/15 16:10
 * @Version 1.0
 **/
@Service
public class AdjustPriceServiceImpl implements IAdjustPriceService {
    @Resource
    private IInventoryItemService inventoryItemService;
    @Resource
    private IActivityDefinitionService activityDefinitionService;
    @Resource
    private IHealthcareServiceService healthcareServiceService;
    @Resource
    private IMedicationService medicationService;
    @Resource
    private AdjustPriceMapper adjustPriceMapper;
    @Resource
    private IDeviceDefinitionService deviceDefinitionService;
    @Resource
    private IOrganizationService organizationService;
    @Resource
    private IChargeItemDefinitionService chargeItemDefinitionService;
    @Resource
    private IChangePriceRecordService changePriceRecordService;
    @Resource
    private ISysDictDataService sysDictDataService;
    @Resource
    private AssignSeqUtil assignSeqUtil;
    @Resource
    private RedisUtil redisUtil;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<?> submitChangePriceData(List<AdjustPriceDataVo> dataVoList) {
        if (dataVoList.isEmpty()) {
            return R.fail(MessageUtils.createMessage(PromptMsgConstant.AdjustPrice.M00001, null));
        }
        if (dataVoList.stream()
            .anyMatch(data -> this.redisUtil.hasKey(RedisKeys.getProductsKey(data.getItemId().toString())))) {
            return R.fail(MessageUtils.createMessage(PromptMsgConstant.AdjustPrice.M00002, null));
        }
        //获取数据中的类型
        Integer categoryType = dataVoList.get(0).getCategoryType();
        // 单据号
        String busNo = assignSeqUtil.getSeqByDay(AssignSeqEnum.CHANGE_PRICE_BUZ.getPrefix());
        // 当前人
        Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
        // 根据表单提交的tab 进入不同的 execute
        if (AdjustPriceEnum.MEDICINE.getCode().equals(categoryType)
            || AdjustPriceEnum.CONSUMABLES.getCode().equals(categoryType)) {
            //如果是 药品或者是耗材 因为药品和耗材的价格取的是 charge_detail表
            this.executeChangePriceForMedication(dataVoList, busNo, practitionerId, categoryType);
        } else if (AdjustPriceEnum.DIAGNOSIS.getCode().equals(categoryType)) {
            //如果是 如果是 诊疗， 取价格主表
            this.executeChangePriceForActivity(dataVoList, busNo, practitionerId);
        } else {
            //如果是 如果是 挂号， 取价格主表
            this.executeChangePriceForHealth(dataVoList, busNo, practitionerId);
        }
        return R.ok();
    }

    @Override
    public R<?> submitExamineChangePriceData(List<AdjustPriceDataVo> dataVoList) {
        if (dataVoList.isEmpty()) {
            return R.fail(MessageUtils.createMessage(PromptMsgConstant.AdjustPrice.M00001, null));
        }
        if (dataVoList.stream()
            .anyMatch(data -> this.redisUtil.hasKey(RedisKeys.getProductsKey(data.getItemId().toString())))) {
            return R.fail(MessageUtils.createMessage(PromptMsgConstant.AdjustPrice.M00002, null));
        }
        //获取数据中的类型
        Integer categoryType = dataVoList.get(0).getCategoryType();
        // 单据号
        String busNo = assignSeqUtil.getSeqByDay(AssignSeqEnum.CHANGE_PRICE_BUZ.getPrefix());
        // 当前人
        Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
        // 根据表单提交的tab 进入不同的 execute
        if (AdjustPriceEnum.MEDICINE.getCode().equals(categoryType)
            || AdjustPriceEnum.CONSUMABLES.getCode().equals(categoryType)) {
            this.executeChangePriceForMedicationExamine(dataVoList, busNo, practitionerId, categoryType);
        } else if (AdjustPriceEnum.DIAGNOSIS.getCode().equals(categoryType)) {
            this.executeChangePriceForActivityExamine(dataVoList, busNo, practitionerId);
        } else {
            this.executeChangePriceForHealthExamine(dataVoList, busNo, practitionerId);
        }
        return R.ok();
    }

    @Override
    public R<?> searchKeyWordDataListByMed(String searchKey) {
        //如果 searchKey == null 默认返回10条，反则 查询所有
        return R.ok(this.medicationService.searchMedListByKeyWord(searchKey));
    }

    @Override
    public R<?> searchKeyWordDataListByDevice(String searchKey) {
        //如果 searchKey == null 默认返回10条，反则 查询所有
        return R.ok(this.deviceDefinitionService.searchDeviceListByKeyWord(searchKey));
    }

    @Override
    public R<?> searchKeyWordDataListByActivity(String searchKey) {
        //如果 searchKey == null 默认返回10条，反则 查询所有
        return R.ok(this.activityDefinitionService.searchActivityListByKeyWord(searchKey));
    }

    @Override
    public R<?> searchChangePriceSubmitDataToPage(AdjustPriceManagerSearchParam adjustPriceManagerSearchParam,
        Integer pageNo, Integer pageSize, String searchKey, HttpServletRequest request) {
        Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
        HashSet<String> searchFields = new HashSet<>();
        searchFields.add(CommonConstants.FieldName.BusNo);
        // 构建查询条件
        QueryWrapper<InventorySearchParam> queryWrapper =
            HisQueryUtils.buildQueryWrapper(adjustPriceManagerSearchParam, searchKey, searchFields, request);
        // 查询入库单据分页列表
        Page<ChangePricePageDto> changePricePageDtoPage = this.adjustPriceMapper.searchChangePriceDataToPage(
            new Page<>(pageNo, pageSize), queryWrapper, SupplyType.REQUEST_MEDICATION_CHANGE_PRICE.getValue(),
            SupplyType.REQUEST_DEVICE_CHANGE_PRICE.getValue(), SupplyType.REQUEST_ACTIVITY_CHANGE_PRICE.getValue(),
            SupplyType.REQUEST_HEALTH_CHANGE_PRICE.getValue(), practitionerId);
        changePricePageDtoPage.getRecords().forEach(e -> {
            e.setStatusEnum_enumText(EnumUtils.getInfoByValue(SupplyStatus.class, e.getStatusEnum()));
            e.setCategoryEnum_enumText(EnumUtils.getInfoByValue(SupplyType.class, e.getItemCategoryEnum()));
        });
        return R.ok(changePricePageDtoPage);
    }

    @Override
    public R<?> searchChangePriceDataByMed(String busNo) {
        // 根据 单据号 查询 药品详情
        List<ChangePriceDataDto> dataList = this.changePriceRecordService.searchMedChangePriceByBusNo(busNo,
            SupplyType.REQUEST_MEDICATION_CHANGE_PRICE.getValue(), null);
        // 获取 药品的单位
        for (ChangePriceDataDto changePriceDataDto : dataList) {
            SysDictData sysDictData =
                sysDictDataService.selectDictInfo(CommonConstants.FieldName.UnitCode, changePriceDataDto.getUnitCode());
            changePriceDataDto.setLabel(sysDictData.getDictLabel());
        }
        return R.ok(dataList);
    }

    @Override
    public R<?> searchChangePriceDataByDevice(String busNo) {
        //根据 单据号 耗材调价单详情
        return R.ok(this.changePriceRecordService.searchDeviceChangePriceByBusNo(busNo,
            SupplyType.REQUEST_DEVICE_CHANGE_PRICE.getValue(), null));
    }

    @Override
    public R<?> searchChangePriceDataByActivity(String busNo) {
        //根据 单据号 查询 诊疗调价单详情
        return R.ok(this.changePriceRecordService.searchActivityChangePriceByBusNo(busNo,
            SupplyType.REQUEST_ACTIVITY_CHANGE_PRICE.getValue(), null));
    }

    @Override
    public R<?> searchChangePriceDataByHealth(String busNo) {
        //根据 单据号 挂号调价单详情
        return R.ok(this.changePriceRecordService.searchHealthChangePriceByBusNo(busNo,
            SupplyType.REQUEST_HEALTH_CHANGE_PRICE.getValue(), null));
    }

    @Override
    public R<?> cancelChangePriceData(String busNo) {
        //根据 单据号查询出 当前所有请求调价的数据集
        List<ChangePriceRecord> changePriceRecordList =
            this.changePriceRecordService.searchChangePriceDataForBusNo(busNo);
        //循环数据集合，将状态修改为 无效状态
        for (ChangePriceRecord data : changePriceRecordList) {
            ChangePriceRecord changePriceRecord = this.changePriceRecordService.getById(data.getId());
            changePriceRecord.setStatusEnum(SupplyStatus.EXPIRED_INVALIDATED.getValue());
            this.changePriceRecordService.updateById(changePriceRecord);
        }
        return R.ok();
    }

    @Override
    public R<?> searchAllOrgData() {
        //查询所有科室
        List<OrgDataDto> orgDataList = this.organizationService.searchOrgDataByHealth();
        return R.ok(orgDataList);
    }

    @Override
    public R<?> searchHealthData(Long orgId) {
        //根据科室ID 查询所有号源
        return R.ok(this.healthcareServiceService.searchAllHeathData(orgId,PublicationStatus.ACTIVE.getValue()));
    }

    @Override
    public R<?> updateExamineByApproval(String busNo) {
        //根据调价单编号 查询 分组后的 数据
        List<ChangePriceRecord> changePriceRecordList =
            this.changePriceRecordService.searchChangePriceDataGroupByBusNo(busNo);
        if (!changePriceRecordList.isEmpty()) {
            // 循环将数据进行填充
            for (ChangePriceRecord data : changePriceRecordList) {
                //提交 审批时，查看是否有正在审核中的 货品数据 。根据 货品ID 从redis中查询
                if (this.redisUtil.hasKey(RedisKeys.getProductsKey(data.getItemId().toString()))) {
                    return R.fail(MessageUtils.createMessage(PromptMsgConstant.AdjustPrice.M00002, null));
                }
                //如果不存在，向redis中插入 药品信息 = 给当前 货品上锁 。审批通过或驳回后 释放
                this.redisUtil.set(RedisKeys.getProductsKey(data.getItemId().toString()), data.getItemId());
            }
            //根据 busNo 修改调价单状态
            this.changePriceRecordService.submitApproval(busNo);
        }
        return R.ok();
    }

    @Override
    public R<?> checkMedApprovalExist(Long itemId) {
        //添加 货品调价时，先查询 当前货品是否在 审核中，如果在，不允许改价。
        return this.changePriceRecordService.searchMedChangePriceByItemId(itemId,
            SupplyType.REQUEST_MEDICATION_CHANGE_PRICE.getValue(), SupplyStatus.APPROVAL.getValue()).isEmpty() ? R.ok()
                : R.fail(MessageUtils.createMessage(PromptMsgConstant.AdjustPrice.M00002, null));
    }

    @Override
    public R<?> checkDeviceApprovalExist(Long itemId) {
        //添加 货品调价时，先查询 当前货品是否在 审核中，如果在，不允许改价。
        return this.changePriceRecordService.searchDeviceChangePriceByItemId(itemId,
            SupplyType.REQUEST_DEVICE_CHANGE_PRICE.getValue(), SupplyStatus.APPROVAL.getValue()).isEmpty() ? R.ok()
                : R.fail(MessageUtils.createMessage(PromptMsgConstant.AdjustPrice.M00002, null));
    }

    @Override
    public R<?> checkActivityApprovalExist(Long itemId) {
        //添加 货品调价时，先查询 当前货品是否在 审核中，如果在，不允许改价。
        return this.changePriceRecordService.searchActivityChangePriceByItemId(itemId,
            SupplyType.REQUEST_ACTIVITY_CHANGE_PRICE.getValue(), SupplyStatus.APPROVAL.getValue()).isEmpty() ? R.ok()
                : R.fail(MessageUtils.createMessage(PromptMsgConstant.AdjustPrice.M00002, null));
    }

    @Override
    public R<?> checkHealthApprovalExist(Long itemId) {
        //添加 货品调价时，先查询 当前货品是否在 审核中，如果在，不允许改价。
        return this.changePriceRecordService.searchHealthChangePriceByItemId(itemId,
            SupplyType.REQUEST_HEALTH_CHANGE_PRICE.getValue(), SupplyStatus.APPROVAL.getValue()).isEmpty() ? R.ok()
                : R.fail(MessageUtils.createMessage(PromptMsgConstant.AdjustPrice.M00002, null));
    }

    public boolean executeChangePriceForMedication(List<AdjustPriceDataVo> dataVoList, String busNo,
        Long practitionerId, Integer categoryType) {
        // 有库存的药品或耗材集合
        List<AdjustPriceDataVo> resultList = new LinkedList<>();
        // 从map中将表单集合取出
        Map<Long, AdjustPriceDataVo> dataVoMap = this.executeMap(dataVoList);
        //根据表单中的id数组 加载库存集合
        List<AdjustPriceDto> inventoryItemList =
            this.inventoryItemService.searchResultDataList(this.executeItemIds(dataVoList));
        for (AdjustPriceDto data : inventoryItemList) {
            AdjustPriceDataVo dataVo = new AdjustPriceDataVo();
            dataVo.setTotalQuantity(data.getTotalCount());
            dataVo.setItemTable(data.getItemTable());
            dataVo.setItemId(data.getItemId());
            dataVo.setNewBuyingPrice(dataVoMap.get(data.getItemId()).getNewBuyingPrice());
            dataVo.setNewRetailPrice(dataVoMap.get(data.getItemId()).getNewRetailPrice());
            dataVo.setReason(dataVoMap.get(data.getItemId()).getReason());
            dataVo.setUnitCode(dataVoMap.get(data.getItemId()).getUnitCode());
            dataVo.setLotNumber(data.getLotNumber());
            dataVo.setLocationId(data.getLocationId());
            resultList.add(dataVo);
        }
        //填充 ChangePriceRecord 对象，返回list进行批量添加
        List<ChangePriceRecord> changePriceRecords =
            this.executeChangePriceData(busNo, practitionerId, resultList, SupplyStatus.PENDING_APPROVAL.getValue(),
                AdjustPriceEnum.MEDICINE.getCode().equals(categoryType)
                    ? SupplyType.REQUEST_MEDICATION_CHANGE_PRICE.getValue()
                    : SupplyType.REQUEST_DEVICE_CHANGE_PRICE.getValue());
        return this.changePriceRecordService.saveOrUpdateBatch(changePriceRecords);
    }

    public boolean executeChangePriceForMedicationExamine(List<AdjustPriceDataVo> dataVoList, String busNo,
        Long practitionerId, Integer categoryType) {
        // 有库存的药品或耗材集合
        List<AdjustPriceDataVo> resultList = new LinkedList<>();
        Map<Long, AdjustPriceDataVo> dataVoMap = this.executeMap(dataVoList);
        List<AdjustPriceDto> inventoryItemList =
            this.inventoryItemService.searchResultDataList(this.executeItemIds(dataVoList));
        for (AdjustPriceDto data : inventoryItemList) {
            AdjustPriceDataVo dataVo = new AdjustPriceDataVo();
            dataVo.setTotalQuantity(data.getTotalCount());
            dataVo.setItemTable(data.getItemTable());
            dataVo.setItemId(data.getItemId());
            dataVo.setNewBuyingPrice(dataVoMap.get(data.getItemId()).getNewBuyingPrice());
            dataVo.setNewRetailPrice(dataVoMap.get(data.getItemId()).getNewRetailPrice());
            dataVo.setReason(dataVoMap.get(data.getItemId()).getReason());
            dataVo.setUnitCode(dataVoMap.get(data.getItemId()).getUnitCode());
            dataVo.setLotNumber(data.getLotNumber());
            dataVo.setLocationId(data.getLocationId());
            resultList.add(dataVo);
            this.redisUtil.set(RedisKeys.getProductsKey(data.getItemId().toString()), data.getItemId());
        }
        //填充 ChangePriceRecord 对象，返回list进行批量添加
        List<ChangePriceRecord> changePriceRecords =
            this.executeChangePriceData(busNo, practitionerId, resultList, SupplyStatus.APPROVAL.getValue(),
                AdjustPriceEnum.MEDICINE.getCode().equals(categoryType)
                    ? SupplyType.REQUEST_MEDICATION_CHANGE_PRICE.getValue()
                    : SupplyType.REQUEST_DEVICE_CHANGE_PRICE.getValue());
        return this.changePriceRecordService.saveOrUpdateBatch(changePriceRecords);
    }

    public boolean executeChangePriceForActivity(List<AdjustPriceDataVo> dataVoList, String busNo,
        Long practitionerId) {
        List<ActivityDto> dataDtoList =
            this.activityDefinitionService.searchActivityDefinitionByIds(this.executeItemIds(dataVoList));
        Map<Long, AdjustPriceDataVo> dataVoMap = this.executeMap(dataVoList);
        List<AdjustPriceDataVo> resultList = new LinkedList<>();
        for (ActivityDto data : dataDtoList) {
            AdjustPriceDataVo dataVo = new AdjustPriceDataVo();
            dataVo.setItemTable(CommonConstants.TableName.WOR_ACTIVITY_DEFINITION);
            dataVo.setName(data.getName());
            dataVo.setItemId(data.getItemId());
            dataVo.setNewBuyingPrice(dataVoMap.get(data.getItemId()).getNewBuyingPrice());
            dataVo.setNewRetailPrice(dataVoMap.get(data.getItemId()).getNewRetailPrice());
            dataVo.setReason(dataVoMap.get(data.getItemId()).getReason());
            dataVo.setLotNumber(dataVoMap.get(data.getItemId()).getLotNumber());
            resultList.add(dataVo);
        }
        //填充 ChangePriceRecord 对象，返回list进行批量添加
        List<ChangePriceRecord> changePriceRecords = this.executeChangePriceData(busNo, practitionerId, resultList,
            SupplyStatus.PENDING_APPROVAL.getValue(), SupplyType.REQUEST_ACTIVITY_CHANGE_PRICE.getValue());
        return this.changePriceRecordService.saveOrUpdateBatch(changePriceRecords);
    }

    /**
     * Desc: 处理申请 诊疗改价业务申请
     * 
     * @param dataVoList
     * @Author raymond
     * @Date 11:19 2025/10/18
     * @return boolean
     **/
    public boolean executeChangePriceForActivityExamine(List<AdjustPriceDataVo> dataVoList, String busNo,
        Long practitionerId) {
        List<ActivityDto> dataDtoList =
            this.activityDefinitionService.searchActivityDefinitionByIds(this.executeItemIds(dataVoList));
        Map<Long, AdjustPriceDataVo> dataVoMap = this.executeMap(dataVoList);
        List<AdjustPriceDataVo> resultList = new LinkedList<>();
        for (ActivityDto data : dataDtoList) {
            AdjustPriceDataVo dataVo = new AdjustPriceDataVo();
            dataVo.setItemTable(CommonConstants.TableName.WOR_ACTIVITY_DEFINITION);
            dataVo.setName(data.getName());
            dataVo.setItemId(data.getItemId());
            dataVo.setNewBuyingPrice(dataVoMap.get(data.getItemId()).getNewBuyingPrice());
            dataVo.setNewRetailPrice(dataVoMap.get(data.getItemId()).getNewRetailPrice());
            dataVo.setReason(dataVoMap.get(data.getItemId()).getReason());
            dataVo.setLotNumber(dataVoMap.get(data.getItemId()).getLotNumber());
            resultList.add(dataVo);
            this.redisUtil.set(RedisKeys.getProductsKey(data.getItemId().toString()), data.getItemId());
        }
        //填充 ChangePriceRecord 对象，返回list进行批量添加
        List<ChangePriceRecord> changePriceRecords = this.executeChangePriceData(busNo, practitionerId, resultList,
            SupplyStatus.APPROVAL.getValue(), SupplyType.REQUEST_ACTIVITY_CHANGE_PRICE.getValue());
        return this.changePriceRecordService.saveOrUpdateBatch(changePriceRecords);
    }

    /**
     * Desc: 处理申请 挂号改价业务
     *
     * @param dataVoList
     * @Author raymond
     * @Date 11:20 2025/10/18
     * @return boolean
     **/
    public boolean executeChangePriceForHealth(List<AdjustPriceDataVo> dataVoList, String busNo, Long practitionerId) {
        List<HealthcareDto> dataDtoList =
            this.healthcareServiceService.searchHealthByIds(this.executeItemIds(dataVoList));
        List<AdjustPriceDataVo> resultList = new LinkedList<>();
        Map<Long, AdjustPriceDataVo> dataVoMap = this.executeMap(dataVoList);
        for (HealthcareDto data : dataDtoList) {
            AdjustPriceDataVo dataVo = new AdjustPriceDataVo();
            dataVo.setItemTable(CommonConstants.TableName.ADM_HEALTHCARE_SERVICE);
            dataVo.setItemId(data.getItemId());
            dataVo.setName(data.getName());
            dataVo.setNewBuyingPrice(dataVoMap.get(data.getItemId()).getNewBuyingPrice());
            dataVo.setNewRetailPrice(dataVoMap.get(data.getItemId()).getNewRetailPrice());
            dataVo.setReason(dataVoMap.get(data.getItemId()).getReason());
            dataVo.setLotNumber(dataVoMap.get(data.getItemId()).getLotNumber());
            resultList.add(dataVo);
        }
        //填充 ChangePriceRecord 对象，返回list进行批量添加 supply_request表共享了 审核状态和 category 枚举
        List<ChangePriceRecord> changePriceRecords = this.executeChangePriceData(busNo, practitionerId, resultList,
            SupplyStatus.PENDING_APPROVAL.getValue(), SupplyType.REQUEST_HEALTH_CHANGE_PRICE.getValue());
        return this.changePriceRecordService.saveOrUpdateBatch(changePriceRecords);
    }

    /**
     * Desc: 处理申请 挂号改价业务
     *
     * @param dataVoList
     * @Author raymond
     * @Date 11:20 2025/10/18
     * @return boolean
     **/
    public boolean executeChangePriceForHealthExamine(List<AdjustPriceDataVo> dataVoList, String busNo,
        Long practitionerId) {
        List<HealthcareDto> dataDtoList =
            this.healthcareServiceService.searchHealthByIds(this.executeItemIds(dataVoList));
        List<AdjustPriceDataVo> resultList = new LinkedList<>();
        Map<Long, AdjustPriceDataVo> dataVoMap = this.executeMap(dataVoList);
        for (HealthcareDto data : dataDtoList) {
            AdjustPriceDataVo dataVo = new AdjustPriceDataVo();
            dataVo.setItemTable(CommonConstants.TableName.ADM_HEALTHCARE_SERVICE);
            dataVo.setItemId(data.getItemId());
            dataVo.setName(data.getName());
            dataVo.setNewBuyingPrice(dataVoMap.get(data.getItemId()).getNewBuyingPrice());
            dataVo.setNewRetailPrice(dataVoMap.get(data.getItemId()).getNewRetailPrice());
            dataVo.setReason(dataVoMap.get(data.getItemId()).getReason());
            dataVo.setLotNumber(dataVoMap.get(data.getItemId()).getLotNumber());
            resultList.add(dataVo);
            this.redisUtil.set(RedisKeys.getProductsKey(data.getItemId().toString()), data.getItemId());
        }
        //填充 ChangePriceRecord 对象，返回list进行批量添加 supply_request表共享了 审核状态和 category 枚举
        List<ChangePriceRecord> changePriceRecords = this.executeChangePriceData(busNo, practitionerId, resultList,
            SupplyStatus.APPROVAL.getValue(), SupplyType.REQUEST_HEALTH_CHANGE_PRICE.getValue());
        return this.changePriceRecordService.saveOrUpdateBatch(changePriceRecords);
    }

    /**
     * Desc: 封装对象数据
     *
     * @param busNo
     * @param curUserId
     * @param itemList
     * @Author raymond
     * @Date 09:35 2025/10/18
     * @return java.util.List<com.openhis.workflow.domain.ChangePriceRecord>
     **/
    public List<ChangePriceRecord> executeChangePriceData(String busNo, Long curUserId,
        List<AdjustPriceDataVo> itemList, Integer statusEnum, Integer categoryEnum) {
        List<ChangePriceRecord> srList = new LinkedList<>();
        for (AdjustPriceDataVo dataVo : itemList) {
            ChangePriceRecord cpr = new ChangePriceRecord();
            //如果是 药品调价
            if (SupplyType.REQUEST_MEDICATION_CHANGE_PRICE.getValue().equals(categoryEnum)) {
                // 获取当前进货价
                ChargeItemDefDetailPriceDto buyingPriceDto = this.chargeItemDefinitionService
                    .getMedPriceByParam(ConditionCode.LOT_NUMBER_COST.getCode(), dataVo.getItemId());
                // 获取当前零售价
                ChargeItemDefDetailPriceDto retailPriceDto = this.chargeItemDefinitionService
                    .getMedPriceByParam(ConditionCode.LOT_NUMBER_PRICE.getCode(), dataVo.getItemId());
                if (buyingPriceDto != null || retailPriceDto != null) {
                    // 库存 以最小单位存储，以货品最小单位进行计算
                    BigDecimal partPercent =
                        dataVo.getTotalQuantity().divide(buyingPriceDto.getPartPercent(), 6, RoundingMode.HALF_UP);
                    //进货价盈负差
                    BigDecimal buyingDiffPrice =
                        dataVo.getNewBuyingPrice().subtract(buyingPriceDto.getPrice()).multiply(partPercent);
                    // 零售价盈负差
                    BigDecimal retailDiffPrice =
                        dataVo.getNewRetailPrice().subtract(retailPriceDto.getPrice()).multiply(partPercent);
                    //填充 change_price_record表数据
                    cpr.setNewBuyingPrice(dataVo.getNewBuyingPrice()).setNewRetailPrice(dataVo.getNewRetailPrice())
                        .setItemQuantity(dataVo.getTotalQuantity()).setItemId(dataVo.getItemId())
                        .setItemTable(dataVo.getItemTable()).setReason(dataVo.getReason()).setBusNo(busNo)
                        .setApplicantId(curUserId).setStatusEnum(statusEnum).setItemCategoryEnum(categoryEnum)
                        .setLotNumber(dataVo.getLotNumber()).setUnitCode(dataVo.getUnitCode())
                        .setOriginBuyingPrice(buyingPriceDto.getPrice()).setOriginRetailPrice(retailPriceDto.getPrice())
                        .setDifferenceBuyingPrice(buyingDiffPrice).setDifferenceRetailPrice(retailDiffPrice)
                        .setApplicantTime(SupplyStatus.APPROVAL.getValue().equals(statusEnum) ? new Date() : null);
                    srList.add(cpr);
                } //如果是 耗材调价
            } else if (SupplyType.REQUEST_DEVICE_CHANGE_PRICE.getValue().equals(categoryEnum)) {
                // 获取当前进货价
                ChargeItemDefDetailPriceDto buyingPriceDto = this.chargeItemDefinitionService
                    .getDevicePriceByParam(ConditionCode.LOT_NUMBER_COST.getCode(), dataVo.getItemId());
                // 获取当前零售价
                ChargeItemDefDetailPriceDto retailPriceDto = this.chargeItemDefinitionService
                    .getDevicePriceByParam(ConditionCode.LOT_NUMBER_PRICE.getCode(), dataVo.getItemId());
                if (buyingPriceDto != null || retailPriceDto != null) {
                    // 库存 以最小单位存储，以货品最小单位进行计算
                    BigDecimal partPercent =
                        dataVo.getTotalQuantity().divide(buyingPriceDto.getPartPercent(), 6, RoundingMode.HALF_UP);
                    //进货价盈负差
                    BigDecimal buyingDiffPrice =
                        dataVo.getNewBuyingPrice().subtract(buyingPriceDto.getPrice()).multiply(partPercent);
                    // 零售价盈负差
                    BigDecimal retailDiffPrice =
                        dataVo.getNewRetailPrice().subtract(retailPriceDto.getPrice()).multiply(partPercent);
                    //填充 change_price_record表数据
                    cpr.setNewBuyingPrice(dataVo.getNewBuyingPrice()).setNewRetailPrice(dataVo.getNewRetailPrice())
                        .setItemQuantity(dataVo.getTotalQuantity()).setItemId(dataVo.getItemId()).setLocationId(dataVo.getLocationId())
                        .setItemTable(dataVo.getItemTable()).setReason(dataVo.getReason()).setBusNo(busNo)
                        .setApplicantId(curUserId).setStatusEnum(statusEnum).setItemCategoryEnum(categoryEnum)
                        .setLotNumber(dataVo.getLotNumber()).setUnitCode(dataVo.getUnitCode())
                        .setOriginBuyingPrice(buyingPriceDto.getPrice()).setOriginRetailPrice(retailPriceDto.getPrice())
                        .setDifferenceBuyingPrice(buyingDiffPrice).setDifferenceRetailPrice(retailDiffPrice)
                        .setApplicantTime(SupplyStatus.APPROVAL.getValue().equals(statusEnum) ? new Date() : null);
                    srList.add(cpr);
                }
            } else {//如果是 诊疗或者挂号调价，诊疗和耗材 没有库存
                ChargeItemDefDetailPriceDto retailPriceDto = this.chargeItemDefinitionService
                    .getProductPrice(PublicationStatus.ACTIVE.getValue(), dataVo.getItemId());
                if (retailPriceDto != null) {
                    //新价格 - 原价格
                    BigDecimal retailDiffPrice = dataVo.getNewRetailPrice().subtract(retailPriceDto.getPrice());
                    //填充 change_price_record表数据
                    cpr.setNewBuyingPrice(dataVo.getNewBuyingPrice()).setNewRetailPrice(dataVo.getNewRetailPrice())
                        .setItemQuantity(dataVo.getTotalQuantity()).setItemId(dataVo.getItemId())
                        .setItemTable(dataVo.getItemTable()).setReason(dataVo.getReason()).setBusNo(busNo)
                        .setApplicantId(curUserId).setStatusEnum(statusEnum).setItemCategoryEnum(categoryEnum)
                        .setLotNumber(dataVo.getLotNumber()).setUnitCode(dataVo.getUnitCode())
                        .setOriginRetailPrice(retailPriceDto.getPrice()).setDifferenceRetailPrice(retailDiffPrice)
                        .setApplicantTime(SupplyStatus.APPROVAL.getValue().equals(statusEnum) ? new Date() : null);
                    srList.add(cpr);
                }
            }
        }
        return srList;
    }

    /**
     * Desc: 封装获取药品和耗材的id数组
     *
     * @param dataVoList
     * @Author raymond
     * @Date 08:03 2025/10/18
     * @return java.util.List<java.lang.Long>
     **/
    public List<Long> executeItemIds(List<AdjustPriceDataVo> dataVoList) {
        List<Long> itemIds = new LinkedList<>();
        for (AdjustPriceDataVo data : dataVoList) {
            itemIds.add(data.getItemId());
        }
        return itemIds;
    }
    /**
     * Desc: 存储表单数据
     * @param dataVoList
     * @Author raymond
     * @Date 10:28 2025/11/5
     * @return java.util.Map<java.lang.Long,com.openhis.web.adjustprice.dto.AdjustPriceDataVo>
     **/
    public Map<Long, AdjustPriceDataVo> executeMap(List<AdjustPriceDataVo> dataVoList) {
        Map<Long, AdjustPriceDataVo> map = new ConcurrentHashMap<>();
        for (AdjustPriceDataVo data : dataVoList) {
            map.put(data.getItemId(), data);
        }
        return map;
    }
}
