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

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

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

import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.exception.ServiceException;
import com.core.common.utils.AgeCalculatorUtil;
import com.core.common.utils.DateUtils;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.openhis.administration.domain.*;
import com.openhis.administration.service.IChargeItemService;
import com.openhis.administration.service.IDeviceDefinitionService;
import com.openhis.administration.service.IOrganizationService;
import com.openhis.administration.service.ITraceNoManageService;
import com.openhis.common.constant.CommonConstants;
import com.openhis.common.constant.PromptMsgConstant;
import com.openhis.common.enums.*;
import com.openhis.common.enums.ybenums.YbInvChgType;
import com.openhis.common.utils.EnumUtils;
import com.openhis.common.utils.HisQueryUtils;
import com.openhis.web.inventorymanage.appservice.impl.ReceiptApprovalAppServiceImpl;
import com.openhis.web.inventorymanage.dto.SupplyItemDetailDto;
import com.openhis.web.pharmacymanage.appservice.IMedicalDeviceDispenseAppService;
import com.openhis.web.pharmacymanage.dto.*;
import com.openhis.web.pharmacymanage.mapper.MedicalDeviceDispenseMapper;
import com.openhis.web.pharmacymanage.mapper.ReturnMedicineMapper;
import com.openhis.workflow.domain.DeviceDispense;
import com.openhis.workflow.domain.InventoryItem;
import com.openhis.workflow.service.IDeviceDispenseService;
import com.openhis.workflow.service.IInventoryItemService;

;

/**
 * 材料发送 应用实现类
 *
 * @author yuxj
 * @date 2025/8/21
 */
@Service
public class MedicalDeviceDispenseAppServiceImpl implements IMedicalDeviceDispenseAppService {

    @Resource
    private IOrganizationService organizationService;

    @Resource
    private IDeviceDispenseService deviceDispenseService;

    @Resource
    private IInventoryItemService inventoryItemService;

    @Resource
    private MedicalDeviceDispenseMapper medicalDeviceDispenseMapper;

    @Resource
    private ReturnMedicineMapper returnMedicineMapper;

    @Resource
    private ITraceNoManageService traceNoManageService;

    @Resource
    private WesternMedicineDispenseAppServiceImpl westernMedicineDispenseAppService;

    @Resource
    private IChargeItemService chargeItemService;

    @Resource
    private IDeviceDefinitionService deviceDefinitionService;

    @Resource
    private ReceiptApprovalAppServiceImpl receiptApprovalAppService;

    /**
     * 获取页面初始化信息
     *
     * @return 初始化信息
     */
    @Override
    public R<?> init() {

        DispenseInitDto initDto = new DispenseInitDto();

        // 获取科室下拉选列表
        List<Organization> organizationList =
            organizationService.getList(OrganizationType.DEPARTMENT.getValue(), OrganizationClass.CLINIC.getValue());
        List<DispenseInitDto.DepartmentOption> organizationOptions = organizationList.stream()
            .map(organization -> new DispenseInitDto.DepartmentOption(organization.getId(), organization.getName()))
            .collect(Collectors.toList());

        // 获取配药人下拉选列表
        List<Practitioner> preparerDoctorList =
            medicalDeviceDispenseMapper.getPreparerDoctorList(PractitionerRoles.PHARMACIST.getCode());
        List<DispenseInitDto.PreparerDoctorOption> preparerDoctorOptions = preparerDoctorList.stream()
            .map(practitioner -> new DispenseInitDto.PreparerDoctorOption(practitioner.getId(), practitioner.getName()))
            .collect(Collectors.toList());

        // 未发药原因下拉选列表
        List<DispenseInitDto.NotPerformedReasonOption> notPerformedReasonOptions =
            Stream.of(NotPerformedReasonEnum.values())
                .map(notPerformedReason -> new DispenseInitDto.NotPerformedReasonOption(notPerformedReason.getValue(),
                    notPerformedReason.getInfo()))
                .collect(Collectors.toList());

        // 发药状态
        List<DispenseInitDto.DispenseStatusOption> dispenseStatusOptions = new ArrayList<>();
        dispenseStatusOptions.add(new DispenseInitDto.DispenseStatusOption(DispenseStatus.IN_PROGRESS.getValue(),
            DispenseStatus.IN_PROGRESS.getInfo()));
        dispenseStatusOptions.add(new DispenseInitDto.DispenseStatusOption(DispenseStatus.COMPLETED.getValue(),
            DispenseStatus.COMPLETED.getInfo()));

        initDto.setDepartmentOptions(organizationOptions).setNotPerformedReasonOptions(notPerformedReasonOptions)
            .setDispenseStatusOptions(dispenseStatusOptions).setPreparerDoctorOptions(preparerDoctorOptions);
        return R.ok(initDto);
    }

    /**
     * 分页查询病人列表
     *
     * @param encounterInfoSearchParam 查询条件
     * @param searchKey 模糊查询关键字
     * @param pageNo 当前页码
     * @param pageSize 查询条数
     * @param request 请求数据
     * @return 病人列表
     */
    @Override
    public R<?> getEncounterInfoListPage(EncounterInfoSearchParam encounterInfoSearchParam, String searchKey,
        Integer pageNo, Integer pageSize, HttpServletRequest request) {
        // 发药状态初始化
        Integer statusEnum = encounterInfoSearchParam.getStatusEnum();
        encounterInfoSearchParam.setStatusEnum(null);
        // 构建查询条件
        QueryWrapper<EncounterInfoSearchParam> queryWrapper =
            HisQueryUtils.buildQueryWrapper(encounterInfoSearchParam, searchKey,
                new HashSet<>(Arrays.asList(CommonConstants.FieldName.PatientName, CommonConstants.FieldName.IdCard,
                    CommonConstants.FieldName.PatientPyStr, CommonConstants.FieldName.PatientWbStr)),
                request);
        // 查询就诊病人列表
        Page<EncounterInfoDto> encounterInfoPage =
            medicalDeviceDispenseMapper.selectEncounterInfoListPage(new Page<>(pageNo, pageSize), queryWrapper,
                statusEnum, DispenseStatus.IN_PROGRESS.getValue(), DispenseStatus.COMPLETED.getValue(),
                DispenseStatus.PREPARATION.getValue(), DispenseStatus.PREPARED.getValue());
        encounterInfoPage.getRecords().forEach(encounterInfo -> {
            // 性别
            encounterInfo.setGenderEnum_enumText(
                EnumUtils.getInfoByValue(AdministrativeGender.class, encounterInfo.getGenderEnum()));
            // 发药状态
            encounterInfo
                .setStatusEnum_enumText(EnumUtils.getInfoByValue(DispenseStatus.class, encounterInfo.getStatusEnum()));
            if (encounterInfo.getBirthDate() != null) {
                // 计算年龄
                encounterInfo.setAge(AgeCalculatorUtil.getAge(encounterInfo.getBirthDate()));
            }
        });
        return R.ok(encounterInfoPage);
    }

    /**
     * 发耗材单查询
     *
     * @param itemDispenseOrderDto 查询信息
     * @param pageNo 当前页码
     * @param pageSize 查询条数
     * @return 发耗材单
     */
    @Override
    public R<?> getDeviceDispenseOrderList(ItemDispenseOrderDto itemDispenseOrderDto, Integer pageNo,
        Integer pageSize) {
        // 发药状态初始化
        Integer dispenseStatus = itemDispenseOrderDto.getStatusEnum();
        itemDispenseOrderDto.setStatusEnum(null);
        // 构建查询条件
        QueryWrapper<ItemDispenseOrderDto> queryWrapper =
            HisQueryUtils.buildQueryWrapper(itemDispenseOrderDto, null, null, null);
        // 处方单信息查询
        Page<ItemDispenseOrderDto> deviceDispenseOrderPage =
            medicalDeviceDispenseMapper.selectDeviceDispenseOrderPage(new Page<>(pageNo, pageSize), queryWrapper,
                DispenseStatus.IN_PROGRESS.getValue(), DispenseStatus.COMPLETED.getValue(),
                DispenseStatus.PREPARATION.getValue(), DispenseStatus.PREPARED.getValue(), dispenseStatus);
        deviceDispenseOrderPage.getRecords().forEach(deviceDispenseOrder -> {
            // 发药状态
            deviceDispenseOrder.setStatusEnum_enumText(
                EnumUtils.getInfoByValue(DispenseStatus.class, deviceDispenseOrder.getStatusEnum()));
            // 设置所在表名
            deviceDispenseOrder.setItemTable(CommonConstants.TableName.ADM_DEVICE_DEFINITION);
        });
        return R.ok(deviceDispenseOrderPage);
    }

    /**
     * 核对发耗材
     *
     * @param dispenseDeviceList 发耗材信息
     * @return 处理结果
     */
    @Override
    public R<?> deviceDispense(List<DispenseItemDto> dispenseDeviceList) {
        // 配药人检查
        if (dispenseDeviceList.get(0).getPreparerId() == null
            || dispenseDeviceList.get(0).getPreparerId().equals(SecurityUtils.getLoginUser().getPractitionerId())) {
            return R.fail("请选择调配药师");
        }
        List<InventoryItem> inventoryItemList = new ArrayList<>();
        // 获取发药单id列表
        List<Long> devDispenseIdList =
            dispenseDeviceList.stream().map(DispenseItemDto::getDispenseId).collect(Collectors.toList());
        // 获取库存信息
        List<UnDispenseInventoryDto> inventoryList = returnMedicineMapper.selectInventoryInfoList(devDispenseIdList, null,
            CommonConstants.TableName.MED_MEDICATION_DEFINITION, CommonConstants.TableName.ADM_DEVICE_DEFINITION);
        // 按每个药品分组
        Map<Long, List<UnDispenseInventoryDto>> groupedByItemId =
            inventoryList.stream().collect(Collectors.groupingBy(UnDispenseInventoryDto::getItemId));
        // 遍历每个分组校验库存状态
        for (Map.Entry<Long, List<UnDispenseInventoryDto>> entry : groupedByItemId.entrySet()) {
            List<UnDispenseInventoryDto> groupItems = entry.getValue();
            if (groupItems.stream().map(UnDispenseInventoryDto::getInventoryStatusEnum)
                .allMatch(x -> x.equals(PublicationStatus.RETIRED.getValue()))) {
                // 库存停供校验
                return R.fail(groupItems.get(0).getItemName() + "库存已停供");
            }
        }
        if (!inventoryList.isEmpty()) {
            for (UnDispenseInventoryDto unDispenseInventoryDto : inventoryList) {
                if (PublicationStatus.ACTIVE.getValue().equals(unDispenseInventoryDto.getInventoryStatusEnum())) {
                    InventoryItem inventoryItem = new InventoryItem();
                    // 库存数量判定
                    if (unDispenseInventoryDto.getDispenseUnit().equals(unDispenseInventoryDto.getInventoryUnitCode())) {
                        // 当前库存数量(拆零单位)=当前库存数量(拆零单位)-请求数量
                        BigDecimal quantity = unDispenseInventoryDto.getInventoryQuantity().subtract(unDispenseInventoryDto.getQuantity());
                        // 库存数量判定
                        if (quantity.compareTo(BigDecimal.ZERO) < 0) {
                            // 库存数量不足
                            return R.fail(unDispenseInventoryDto.getItemName() + "当前库存数量不足");
                        } else {
                            inventoryItem.setId(unDispenseInventoryDto.getInventoryId()).setQuantity(quantity);
                        }
                    } else {
                        // 当前库存数量(拆零单位)=当前库存数量(拆零单位)-拆零数量（拆零比×请求数量）
                        BigDecimal quantity = unDispenseInventoryDto.getInventoryQuantity()
                            .subtract(unDispenseInventoryDto.getPartPercent().multiply(unDispenseInventoryDto.getQuantity()));
                        // 库存数量判定
                        if (quantity.compareTo(BigDecimal.ZERO) < 0) {
                            // 库存数量不足
                            return R.fail(unDispenseInventoryDto.getItemName() + "当前库存数量不足");
                        } else {
                            inventoryItem.setId(unDispenseInventoryDto.getInventoryId()).setQuantity(quantity);
                        }
                    }
                    inventoryItemList.add(inventoryItem);
                }
            }
        }
        // 材料发放信息查询
        List<DeviceDispense> dispenseList = deviceDispenseService
            .list(new LambdaQueryWrapper<DeviceDispense>().in(DeviceDispense::getId, devDispenseIdList));
        // 追溯码列表
        List<TraceNoManage> tracesNoManageList = new ArrayList<>();
        TraceNoManage traceNoManage;
        List<SupplyItemDetailDto> supplyItemDetailList = new ArrayList<>();
        if (dispenseList != null) {
            if (dispenseList.stream().map(DeviceDispense::getStatusEnum)
                .anyMatch(x -> !x.equals(DispenseStatus.PREPARATION.getValue()))) {
                throw new ServiceException("耗材发放失败，请检查发耗材单状态");
            } else {
                for (DeviceDispense deviceDispense : dispenseList) {
                    // 材料发放状态
                    deviceDispense.setStatusEnum(DispenseStatus.COMPLETED.getValue());
                    // 发药数量
                    deviceDispense.setDispenseQuantity(deviceDispense.getQuantity());
                    // 发药时间
                    deviceDispense.setDispenseTime(DateUtils.getNowDate());
                    // 发药人
                    deviceDispense.setPerformerId(SecurityUtils.getLoginUser().getPractitionerId());
                    // 配药时间
                    deviceDispense.setPrepareTime(DateUtils.getNowDate());
                    // 配药人
                    deviceDispense.setPreparerId(dispenseDeviceList.get(0).getPreparerId());
                    // 设置库存变更参数
                    supplyItemDetailList.add(new SupplyItemDetailDto().setItemId(deviceDispense.getDeviceDefId())
                        .setLotNumber(deviceDispense.getLotNumber())
                        .setItemTable(CommonConstants.TableName.ADM_DEVICE_DEFINITION));
                    if (deviceDispense.getTraceNo() == null) {
                        // 根据数量设置追溯码
                        deviceDispense.setTraceNo(String.join(CommonConstants.Common.COMMA, Collections
                            .nCopies(deviceDispense.getQuantity().intValue(), CommonConstants.Common.DEV_TRACE_NO)));
                    } else {
                        // 使用逗号分割追溯码并转换为List
                        String[] traceNoList = deviceDispense.getTraceNo().split(CommonConstants.Common.COMMA);
                        for (String item : traceNoList) {
                            traceNoManage = new TraceNoManage();
                            // 追溯码处理
                            traceNoManage.setItemTable(CommonConstants.TableName.ADM_DEVICE_DEFINITION)
                                // 项目id
                                .setItemId(deviceDispense.getDeviceDefId())
                                // 仓库类型
                                .setLocationTypeEnum(LocationForm.WAREHOUSE.getValue())
                                // 仓库
                                .setLocationId(deviceDispense.getLocationId())
                                // 产品批号
                                .setLotNumber(deviceDispense.getLotNumber())
                                // 追溯码
                                .setTraceNo(item)
                                // 追溯码状态
                                .setStatusEnum(TraceNoStatus.OUT.getValue())
                                // 追溯码单位
                                .setUnitCode(deviceDispense.getUnitCode())
                                // 操作类型
                                .setOperationType(SupplyType.DISPENSE_MEDICATION.getValue());
                            tracesNoManageList.add(traceNoManage);
                        }
                    }
                }
                // 药品发放更新
                deviceDispenseService.updateBatchById(dispenseList);
            }
        } else {
            return R.fail(MessageUtils.createMessage(PromptMsgConstant.Common.M00007, null));
        }
        // 库存更新
        inventoryItemService.updateBatchById(inventoryItemList);
        // 追溯码管理表数据追加
        traceNoManageService.saveBatch(tracesNoManageList);
        // 返回信息
        String returnMsg = null;
        List<String> uploadFailedNoList;
        // 调用医保商品销售接口
        String ybSwitch = SecurityUtils.getLoginUser().getOptionJson().getString(CommonConstants.Option.YB_SWITCH);
        // 医保开关
        if (Whether.YES.getCode().equals(ybSwitch)) {
            // 设置进销存参数
            List<DeviceDefinition> deviceDefinitions = deviceDefinitionService.listByIds(
                supplyItemDetailList.stream().map(SupplyItemDetailDto::getItemId).collect(Collectors.toList()));
            // 用itemId分组
            Map<Long, DeviceDefinition> deviceMap =
                deviceDefinitions.stream().collect(Collectors.toMap(DeviceDefinition::getId, Function.identity()));
            // 设置库存变更参数
            for (SupplyItemDetailDto dto : supplyItemDetailList) {
                if (CommonConstants.TableName.ADM_DEVICE_DEFINITION.equals(dto.getItemTable())) {
                    DeviceDefinition dev = deviceMap.get(dto.getItemId());
                    if (dev != null) {
                        dto.setItemBusNo(dev.getBusNo()).setPartPercent(dev.getPartPercent()).setRxFlag(dev.getRxFlag())
                            .setYbNo(dev.getYbNo());
                    }
                }
            }
            uploadFailedNoList = westernMedicineDispenseAppService.ybMedicineIntegrated(null, devDispenseIdList);
            uploadFailedNoList = receiptApprovalAppService.ybInventoryIntegrated(supplyItemDetailList,
                YbInvChgType.OTHER_OUT, DateUtils.getNowDate());
            if (uploadFailedNoList != null) {
                returnMsg = "3505商品销售上传错误，错误项目编码" + uploadFailedNoList;
            } else {
                returnMsg = "3505商品销售上传成功";
            }
        }
        return R.ok(returnMsg, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, null));
    }

    /**
     * 发放耗材
     *
     * @param chargeItemIds 耗材收费单ids
     * @return 处理结果
     */
    @Override
    public R<?> dispenseMedicalConsumables(List<Long> chargeItemIds) {
        // 查看所属医院
        String fixmedinsCode =
            SecurityUtils.getLoginUser().getOptionJson().getString(CommonConstants.Option.FIXMEDINS_CODE);
        if (!HospitalCodeEnum.CCU.getCode().equals(fixmedinsCode)) {
            return R.ok();
        }
        List<ChargeItem> chargeItemList = chargeItemService.listByIds(chargeItemIds);
        if (chargeItemList == null || chargeItemList.isEmpty()) {
            return R.fail(MessageUtils.createMessage(PromptMsgConstant.Common.M00007, null));
        }

        List<InventoryItem> inventoryItemList = new ArrayList<>();
        // 获取发申请id列表
        List<Long> devRequestIdList =
            chargeItemList.stream().map(ChargeItem::getServiceId).collect(Collectors.toList());
        // 获取耗材发放id列表
        List<Long> devDispenseIdList = deviceDispenseService
            .list(new LambdaQueryWrapper<DeviceDispense>().in(DeviceDispense::getDeviceReqId, devRequestIdList))
            .stream().map(DeviceDispense::getId).collect(Collectors.toList());
        // 获取库存信息
        List<UnDispenseInventoryDto> inventoryList = returnMedicineMapper.selectInventoryInfoList(devDispenseIdList, null,
            CommonConstants.TableName.MED_MEDICATION_DEFINITION, CommonConstants.TableName.ADM_DEVICE_DEFINITION);
        // 按每个耗材分组
        Map<Long, List<UnDispenseInventoryDto>> groupedByItemId =
            inventoryList.stream().collect(Collectors.groupingBy(UnDispenseInventoryDto::getItemId));
        // 遍历每个分组校验库存状态
        for (Map.Entry<Long, List<UnDispenseInventoryDto>> entry : groupedByItemId.entrySet()) {
            List<UnDispenseInventoryDto> groupItems = entry.getValue();
            if (groupItems.stream().map(UnDispenseInventoryDto::getInventoryStatusEnum)
                .allMatch(x -> x.equals(PublicationStatus.RETIRED.getValue()))) {
                // 库存停供校验
                return R.fail(groupItems.get(0).getItemName() + "库存已停供");
            }
        }
        if (!inventoryList.isEmpty()) {
            for (UnDispenseInventoryDto unDispenseInventoryDto : inventoryList) {
                if (PublicationStatus.ACTIVE.getValue().equals(unDispenseInventoryDto.getInventoryStatusEnum())) {
                    InventoryItem inventoryItem = new InventoryItem();
                    // 库存数量判定
                    if (unDispenseInventoryDto.getDispenseUnit().equals(unDispenseInventoryDto.getInventoryUnitCode())) {
                        // 当前库存数量(拆零单位)=当前库存数量(拆零单位)-请求数量
                        BigDecimal quantity = unDispenseInventoryDto.getInventoryQuantity().subtract(unDispenseInventoryDto.getQuantity());
                        // 库存数量判定
                        if (quantity.compareTo(BigDecimal.ZERO) < 0) {
                            // 库存数量不足
                            return R.fail(unDispenseInventoryDto.getItemName() + "当前库存数量不足");
                        } else {
                            inventoryItem.setId(unDispenseInventoryDto.getInventoryId()).setQuantity(quantity);
                        }
                    } else {
                        // 当前库存数量(拆零单位)=当前库存数量(拆零单位)-拆零数量（拆零比×请求数量）
                        BigDecimal quantity = unDispenseInventoryDto.getInventoryQuantity()
                            .subtract(unDispenseInventoryDto.getPartPercent().multiply(unDispenseInventoryDto.getQuantity()));
                        // 库存数量判定
                        if (quantity.compareTo(BigDecimal.ZERO) < 0) {
                            // 库存数量不足
                            return R.fail(unDispenseInventoryDto.getItemName() + "当前库存数量不足");
                        } else {
                            inventoryItem.setId(unDispenseInventoryDto.getInventoryId()).setQuantity(quantity);
                        }
                    }
                    inventoryItemList.add(inventoryItem);
                }
            }
        }
        // 发耗材信息查询
        List<DeviceDispense> dispenseList = deviceDispenseService
            .list(new LambdaQueryWrapper<DeviceDispense>().in(DeviceDispense::getId, devDispenseIdList));
        List<SupplyItemDetailDto> supplyItemDetailList = new ArrayList<>();
        if (dispenseList != null) {
            if (dispenseList.stream().map(DeviceDispense::getStatusEnum)
                .anyMatch(x -> x.equals(DispenseStatus.COMPLETED.getValue()))) {
                throw new ServiceException("耗材已发放，请勿重复操作");
            } else {
                for (DeviceDispense deviceDispense : dispenseList) {
                    // 耗材发放状态
                    deviceDispense.setStatusEnum(DispenseStatus.COMPLETED.getValue());
                    // 发药数量
                    deviceDispense.setDispenseQuantity(deviceDispense.getQuantity());
                    // 发药时间
                    deviceDispense.setDispenseTime(DateUtils.getNowDate());
                    // 发药人（长大写死发耗材人）
                    deviceDispense.setPerformerId(CommonConstants.CCU.DisDeviceDoctor);
                    // 根据数量设置追溯码
                    deviceDispense.setTraceNo(String.join(CommonConstants.Common.COMMA, Collections
                        .nCopies(deviceDispense.getQuantity().intValue(), CommonConstants.Common.DEV_TRACE_NO)));
                    // 设置库存变更参数
                    supplyItemDetailList.add(new SupplyItemDetailDto().setItemId(deviceDispense.getDeviceDefId())
                        .setLotNumber(deviceDispense.getLotNumber())
                        .setItemTable(CommonConstants.TableName.ADM_DEVICE_DEFINITION));
                }
                // 药品发放更新
                deviceDispenseService.updateBatchById(dispenseList);
            }
        } else {
            return R.fail(MessageUtils.createMessage(PromptMsgConstant.Common.M00007, null));
        }
        // 库存更新
        inventoryItemService.updateBatchById(inventoryItemList);
        // 返回信息
        String returnMsg = null;
        // 调用医保商品销售接口
        String ybSwitch = SecurityUtils.getLoginUser().getOptionJson().getString(CommonConstants.Option.YB_SWITCH);
        List<String> uploadFailedNoList = new ArrayList<>();
        // 医保开关
        if (Whether.YES.getCode().equals(ybSwitch)) {
            // 设置进销存参数
            List<DeviceDefinition> deviceDefinitions = deviceDefinitionService.listByIds(
                supplyItemDetailList.stream().map(SupplyItemDetailDto::getItemId).collect(Collectors.toList()));
            // 用itemId分组
            Map<Long, DeviceDefinition> deviceMap =
                deviceDefinitions.stream().collect(Collectors.toMap(DeviceDefinition::getId, Function.identity()));
            // 设置库存变更参数
            for (SupplyItemDetailDto dto : supplyItemDetailList) {
                if (CommonConstants.TableName.ADM_DEVICE_DEFINITION.equals(dto.getItemTable())) {
                    DeviceDefinition dev = deviceMap.get(dto.getItemId());
                    if (dev != null) {
                        dto.setItemBusNo(dev.getBusNo()).setPartPercent(dev.getPartPercent()).setRxFlag(dev.getRxFlag())
                            .setYbNo(dev.getYbNo());
                    }
                }
            }
            uploadFailedNoList = westernMedicineDispenseAppService.ybMedicineIntegrated(null, devDispenseIdList);
            uploadFailedNoList = receiptApprovalAppService.ybInventoryIntegrated(supplyItemDetailList,
                YbInvChgType.OTHER_OUT, DateUtils.getNowDate());
            if (uploadFailedNoList != null) {
                returnMsg = "3505商品销售上传错误，错误项目编码" + uploadFailedNoList;
            } else {
                returnMsg = "3505商品销售上传成功";
            }
        }
        return R.ok(returnMsg, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, null));
    }

    /**
     * 作废
     *
     * @param dispenseDeviceList 作废信息
     * @return 处理结果
     */
    @Override
    public R<?> deviceCancel(List<DispenseItemDto> dispenseDeviceList) {
        // 获取发材料单id列表
        List<Long> devDispenseIdList =
            dispenseDeviceList.stream().map(DispenseItemDto::getDispenseId).collect(Collectors.toList());
        // 材料发放信息查询
        List<DeviceDispense> dispenseList = deviceDispenseService
            .list(new LambdaQueryWrapper<DeviceDispense>().in(DeviceDispense::getId, devDispenseIdList));
        if (dispenseList != null) {
            for (DeviceDispense medicationDispense : dispenseList) {
                // 材料发放状态
                medicationDispense.setStatusEnum(DispenseStatus.DECLINED.getValue());
                // 未发药原因
                medicationDispense.setNotPerformedReasonEnum(dispenseDeviceList.get(0).getNotPerformedReasonEnum());
            }
            // 药品发放更新
            deviceDispenseService.updateBatchById(dispenseList);
        } else {
            return R.fail(MessageUtils.createMessage(PromptMsgConstant.Common.M00007, null));
        }
        return R.ok(MessageUtils.createMessage(PromptMsgConstant.Common.M00004, null));
    }

}
