package com.hzs.scm.ic.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzs.common.core.constant.CacheConstants;
import com.hzs.common.core.constant.ScmFieldConstants;
import com.hzs.common.core.constant.SystemFieldConstants;
import com.hzs.common.core.constant.msg.ScmMsgConstants;
import com.hzs.common.core.enums.EScmOrderType;
import com.hzs.common.core.enums.EYesNo;
import com.hzs.common.core.service.RedisService;
import com.hzs.common.core.utils.ComputeUtil;
import com.hzs.common.core.utils.DateUtils;
import com.hzs.common.core.utils.StringUtils;
import com.hzs.common.core.utils.reflect.ReflectUtils;
import com.hzs.common.domain.sale.ext.SaOrderExt;
import com.hzs.common.domain.sale.ext.SaOrderItemsExt;
import com.hzs.common.domain.scm.ic.IcOnHandNum;
import com.hzs.common.domain.scm.ic.IcOnHandNumB;
import com.hzs.common.domain.scm.ic.IcOnHandSpecs;
import com.hzs.common.domain.scm.ic.ext.IcOnHandNumExt;
import com.hzs.common.domain.scm.pub.ScmItemSpecs;
import com.hzs.common.domain.scm.sale.ext.IcSaleoutBExt;
import com.hzs.common.domain.scm.sale.ext.IcSaleoutHExt;
import com.hzs.common.domain.scm.warn.ext.IcWarnConfigExt;
import com.hzs.scm.ic.mapper.IcOnHandNumMapper;
import com.hzs.scm.ic.param.OnHandNumParam;
import com.hzs.scm.ic.service.IIcAvailableNumService;
import com.hzs.scm.ic.service.IIcOnHandNumBService;
import com.hzs.scm.ic.service.IIcOnHandNumService;
import com.hzs.scm.ic.service.IIcOnHandSpecsService;
import com.hzs.scm.warn.service.IIcWarnConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 现存量 服务实现类
 * </p>
 *
 * @author hzs
 * @since 2023-11-21
 */
@Service
public class IcOnHandNumServiceImpl extends ServiceImpl<IcOnHandNumMapper, IcOnHandNum> implements IIcOnHandNumService {

    @Autowired
    private IIcOnHandNumBService icOnHandNumbService;

    @Autowired
    private IIcOnHandSpecsService icOnHandSpecsService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private IIcAvailableNumService availableNumService;

    @Autowired
    private IIcWarnConfigService warnConfigService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized void mergeIcOnHandNumByGeneralIn(Object generalHvo, List<?> generalBvoList, Integer orderType, Long pkMember) {
        try {
            // 获得对应条数的主键
            // 更新现存量表 一个批次一条数据 使用merge进行更新
            List<IcOnHandNumB> saveOnHandNumbList = new ArrayList<>();
            List<IcOnHandSpecs> saveOnHandSpecsList = new ArrayList<>();
            List<IcOnHandNumExt> icOnHandNumList = new ArrayList<>();
            for (Object generalBvo : generalBvoList) {
                // 根据仓库 产品id 规格 批次号查询是否已经存在，存在的话对数量进行修改
                // 现存量规格表
                List<ScmItemSpecs> scmItemSpecsList = ReflectUtils.invokeGetter(generalBvo, ScmFieldConstants.SCM_ITEM_SPECS_LIST);
                // 现存量表
                Integer pkProductBas = ReflectUtils.invokeGetter(generalBvo, ScmFieldConstants.PK_PRODUCT_BAS);
                if(pkProductBas == null){
                    throw new RuntimeException("产品没有绑定产品基本信息，不能进行出入库操作");
                }
                IcOnHandNumExt icOnHandNum = new IcOnHandNumExt();
                icOnHandNum.setPkCorp(ReflectUtils.invokeGetter(generalHvo, ScmFieldConstants.PK_CORP));
                icOnHandNum.setPkCubasdoc(ReflectUtils.invokeGetter(generalHvo, ScmFieldConstants.PK_CUBASDOC));
                icOnHandNum.setPkProductBas(pkProductBas);
                icOnHandNum.setPkProduct(ReflectUtils.invokeGetter(generalBvo, ScmFieldConstants.PK_PRODUCT));
                icOnHandNum.setPkUnit(ReflectUtils.invokeGetter(generalBvo, ScmFieldConstants.PK_UNIT));
                icOnHandNum.setPkStorehouse(ReflectUtils.invokeGetter(generalBvo, ScmFieldConstants.PK_STOREHOUSE));
                icOnHandNum.setNonhandnum(ReflectUtils.invokeGetter(generalBvo, ScmFieldConstants.N_NUM));
                icOnHandNum.setPkBatchCode(ReflectUtils.invokeGetter(generalBvo, ScmFieldConstants.PK_BATCH_CODE));
                icOnHandNum.setProductDate(ReflectUtils.invokeGetter(generalBvo, ScmFieldConstants.PRODUCT_DATE));
                icOnHandNum.setExpireDate(ReflectUtils.invokeGetter(generalBvo, ScmFieldConstants.EXPIRE_DATE));
                Integer pkCubasdoc = ReflectUtils.invokeGetter(generalBvo, ScmFieldConstants.PK_CUBASDOC);
                if(pkCubasdoc != null){
                    icOnHandNum.setPkCubasdoc(pkCubasdoc);
                }
                icOnHandNum.setPkCountry(ReflectUtils.invokeGetter(generalHvo, SystemFieldConstants.PK_COUNTRY_VALUE));
                icOnHandNum.setPkCreator(pkMember);
                // 查询现存量表，是否存在现存量
                List<IcOnHandNumExt> oldOnHandNumList = baseMapper.queryOnHandNumByCondition(icOnHandNum);
                List<IcOnHandNumB> onhandNumBiList = new ArrayList<>();
                List<IcOnHandSpecs> icOnHandSpecsList = packageIcOnHandItemList(generalHvo, orderType, pkMember, onhandNumBiList, generalBvo, scmItemSpecsList, icOnHandNum);
                // 用于更新可用量
                icOnHandNum.setScmItemSpecsList(scmItemSpecsList);
                updateOrInsertOnHandNum(oldOnHandNumList, icOnHandNum);
                for (IcOnHandSpecs icOnHandSpecs : icOnHandSpecsList) {
                    icOnHandSpecs.setPkOnhandnum(icOnHandNum.getPkId());
                }
                saveOnHandSpecsList.addAll(icOnHandSpecsList);
                for(IcOnHandNumB onHandNumB : onhandNumBiList){
                    onHandNumB.setPkOnhandnum(icOnHandNum.getPkId());
                }
                saveOnHandNumbList.addAll(onhandNumBiList);
                // 现存量流水
                icOnHandNumList.add(icOnHandNum);
            }
            // 撤单退单时更新可用量，销售订单，销售退货时不更新可用量，可用量撤单时更新
            if (EScmOrderType.SALE_OUT.getValue() != orderType && icOnHandNumList.size() > 0) {
                // 更新可用量
                availableNumService.mergeIcAvailableNumByIcOnHandNum(icOnHandNumList, pkMember);
            }
            if (saveOnHandNumbList.size() > 0) {
                // 保存
                icOnHandNumbService.insertIcOnHandNumbByList(saveOnHandNumbList);
            }
            if (saveOnHandSpecsList.size() > 0) {
                // 更新保存
                icOnHandSpecsService.mergeIcOnHandSpecsByList(saveOnHandSpecsList);
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void mergeIcOnHandNumByGeneralOut(Object generalHvo, List<?> generalBvoList, Integer orderType, Long pkMember) {
        // 根据明细表查询出产品、仓库内所有的批次信息，按照倒叙排列
        // 需要按照先进先出进行扣减，当前批次不够扣减下一个批次
        // 加锁
        List<IcOnHandNumB> icOnHandNumbList = new ArrayList<>();
        for (Object generalBvo : generalBvoList) {
            // 根据仓库 产品id 规格 批次号查询是否已经存在，存在的话对数量进行修改
            // 现存量规格表
            // 现存量表
            IcOnHandNum icOnHandNum = IcOnHandNum.builder()
                    .pkProduct(ReflectUtils.invokeGetter(generalBvo, ScmFieldConstants.PK_PRODUCT))
                    .pkStorehouse(ReflectUtils.invokeGetter(generalBvo, ScmFieldConstants.PK_STOREHOUSE))
                    .pkBatchCode(ReflectUtils.invokeGetter(generalBvo, ScmFieldConstants.PK_BATCH_CODE))
                    .build();
            icOnHandNum.setPkCountry(ReflectUtils.invokeGetter(generalHvo, SystemFieldConstants.PK_COUNTRY_VALUE));
            // 查询现存量表，是否存在现存量
            String handKey = getStringKey(ReflectUtils.invokeGetter(generalBvo, ScmFieldConstants.SCM_ITEM_SPECS_LIST));
            List<IcOnHandNum> oldOnHandNumList = baseMapper.queryIcOnHandNumByCondition(icOnHandNum, handKey);
            // 待扣减库存
            BigDecimal nNum = ReflectUtils.invokeGetter(generalBvo, ScmFieldConstants.N_NUM);
            List<IcOnHandNum> deductOnHandNumList = new ArrayList<>();
            Date date = DateUtils.currentDateTime();
            for (IcOnHandNum onHandNum : oldOnHandNumList) {
                onHandNum.setPkModified(pkMember);
                onHandNum.setModifiedTime(date);
                if(ComputeUtil.compareValue(onHandNum.getNonhandnum(), nNum)){
                    onHandNum.setNonhandnum(nNum.negate());
                    deductOnHandNumList.add(onHandNum);
                    nNum = BigDecimal.ZERO;
                    break;
                }else {
                    nNum = ComputeUtil.computeSubtract(nNum, onHandNum.getNonhandnum());
                    onHandNum.setNonhandnum(onHandNum.getNonhandnum().negate());
                    deductOnHandNumList.add(onHandNum);
                }
            }
            if(ComputeUtil.compareValue(nNum)){
                throw new RuntimeException(ScmMsgConstants.IC_ON_HAND_NUM_NOT_EMPTY);
            }
            // 一行行更新，防止不同行用同一个批次
            updateOrInsertOnHandNum(deductOnHandNumList);
            for (IcOnHandNum icOnHand : deductOnHandNumList) {
                packageIcOnHandBiList(generalHvo, orderType, pkMember, icOnHandNumbList, generalBvo, icOnHand);
            }
            // 非销售出库单出库时需要更新可用量
            if (EScmOrderType.SALE_OUT.getValue() != orderType && deductOnHandNumList.size() > 0) {
                List<IcOnHandNumExt> onHandNumList = new ArrayList<>();
                for (IcOnHandNum onHandNum : deductOnHandNumList) {
                    IcOnHandNumExt icOnHandNumExt = BeanUtil.copyProperties(onHandNum, IcOnHandNumExt.class);
                    icOnHandNumExt.setScmItemSpecsList(BeanUtil.copyToList(onHandNum.getScmItemSpecsList(), ScmItemSpecs.class));
                    onHandNumList.add(icOnHandNumExt);
                }
                // 更新可用量
                availableNumService.mergeIcAvailableNumByIcOnHandNum(onHandNumList, pkMember);
            }
        }
        if (icOnHandNumbList.size() > 0) {
            // 保存
            icOnHandNumbService.insertIcOnHandNumbByList(icOnHandNumbList);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void backIcOnHandNumByGeneralOut(Object generalHvo, List<?> generalBvoList, Integer orderType, Long pkMember) {
        // 根据明细表查询出产品、仓库内所有的批次信息，按照倒叙排列
        // 需要按照先进先出进行扣减，当前批次不够扣减下一个批次
        // 加锁
        List<IcOnHandNumB> icOnHandNumbList = new ArrayList<>();
        for (Object generalBvo : generalBvoList) {
            // 现存量流水
            IcOnHandNumB icOnHandNumB = IcOnHandNumB.builder()
                    .orderType(orderType)
                    .pkGeneralH(ReflectUtils.invokeGetter(generalHvo, SystemFieldConstants.PK_ID_VALUE))
                    .pkGeneralB(ReflectUtils.invokeGetter(generalBvo, SystemFieldConstants.PK_ID_VALUE))
                    .build();
            icOnHandNumbList.add(icOnHandNumB);
        }
        // 根据参数查询库存流水，验证数量
        List<IcOnHandNumB> onHandNumbList = icOnHandNumbService.queryOnHandNumByHandNumbList(icOnHandNumbList);
        Map<String, IcOnHandNumB> handNumbMap = new HashMap<>();
        for (IcOnHandNumB icOnHandNumB : onHandNumbList) {
            String key = icOnHandNumB.getOrderType() + "_" + icOnHandNumB.getPkGeneralH() + "_" + icOnHandNumB.getPkGeneralB();
            if(handNumbMap.containsKey(key)) {
                IcOnHandNumB onHandNumB = handNumbMap.get(key);
                onHandNumB.setNnum(ComputeUtil.computeAdd(onHandNumB.getNnum(), icOnHandNumB.getNnum()));
            }else {
                handNumbMap.put(key, icOnHandNumB);
            }
        }
        // 验证数量
        for (Object generalBvo : generalBvoList) {
            String key = orderType + "_" + ReflectUtils.invokeGetter(generalHvo, SystemFieldConstants.PK_ID_VALUE) + "_"
                    + ReflectUtils.invokeGetter(generalBvo, SystemFieldConstants.PK_ID_VALUE);
            if(!handNumbMap.containsKey(key)){
                throw new RuntimeException(ScmMsgConstants.IC_ON_HAND_NUM_B_NOT_EXIST);
            }
            IcOnHandNumB icOnHandNumB = handNumbMap.get(key);
            // 扣减的数量要跟出库单数量一致，否则有问题不能操作
            if(!ComputeUtil.compareEqual(ComputeUtil.computeAdd(icOnHandNumB.getNnum(),
                    ReflectUtils.invokeGetter(generalBvo, ScmFieldConstants.N_NUM)), BigDecimal.ZERO)){
                throw new RuntimeException(ScmMsgConstants.IC_ON_HAND_NUM_B_NOT_EXIST);
            }
        }
        // 封装流水明细表
        List<IcOnHandNumB> insertHandNumbList= new ArrayList<>();
        for (IcOnHandNumB icOnHandNumB : onHandNumbList) {
            // 现存量流水
            IcOnHandNumB onHandNumB = BeanUtil.copyProperties(icOnHandNumB, IcOnHandNumB.class);
            onHandNumB.setNnum(icOnHandNumB.getNnum().negate());
            onHandNumB.setPkCountry(ReflectUtils.invokeGetter(generalHvo, SystemFieldConstants.PK_COUNTRY_VALUE));
            onHandNumB.setPkCreator(pkMember);
            insertHandNumbList.add(onHandNumB);
        }
        baseMapper.mergeUpdateBackOnHandNumByNum(insertHandNumbList, pkMember);
        if (insertHandNumbList.size() > 0) {
            // 保存
            icOnHandNumbService.insertIcOnHandNumbByList(insertHandNumbList);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void mergeIcOnHandNumByGeneralOut(IcSaleoutHExt icSaleOutExt, Integer orderType, Long pkMember) {
        // 根据明细表查询出产品、仓库内所有的批次信息，按照倒叙排列
        // 需要按照先进先出进行扣减，当前批次不够扣减下一个批次
        // 加锁
        List<IcOnHandNumB> icOnHandNumbList = new ArrayList<>();
        List<IcSaleoutBExt> saleoutbExtList = new ArrayList<>();
        for (IcSaleoutBExt saleOutB : icSaleOutExt.getSaleoutbExtList()) {
            // 根据仓库 产品id 规格 批次号查询是否已经存在，存在的话对数量进行修改
            // 现存量规格表
//            List<ScmItemSpecs> scmItemSpecsList = saleOutB.getScmItemSpecsList();
            // 现存量表
            IcOnHandNum icOnHandNum = IcOnHandNum.builder()
                    .pkProduct(saleOutB.getPkProduct())
                    .pkStorehouse(saleOutB.getPkStorehouse())
                    .build();
            icOnHandNum.setPkCountry(saleOutB.getPkCountry());
            // 查询现存量表，是否存在现存量
            String handKey = getStringKey(saleOutB.getScmItemSpecsList());
            List<IcOnHandNum> oldOnHandNumList = baseMapper.queryIcOnHandNumByCondition(icOnHandNum, handKey);
            // 待扣减库存
            BigDecimal nNum = saleOutB.getNnum();
            List<IcOnHandNum> deductOnHandNumList = new ArrayList<>();
            Date date = DateUtils.currentDateTime();
            for (IcOnHandNum onHandNum : oldOnHandNumList) {
                onHandNum.setPkModified(pkMember);
                onHandNum.setModifiedTime(date);
                if(ComputeUtil.compareValue(onHandNum.getNonhandnum(), nNum)){
                    saleOutB.setPkBatchCode(onHandNum.getPkBatchCode());
                    saleoutbExtList.add(saleOutB);
                    onHandNum.setNonhandnum(nNum.negate());
                    deductOnHandNumList.add(onHandNum);
                    nNum = BigDecimal.ZERO;
                    break;
                }else {
                    IcSaleoutBExt copySaleoutB = BeanUtil.copyProperties(saleOutB, IcSaleoutBExt.class);
                    // 获取id
                    copySaleoutB.setPkBatchCode(onHandNum.getPkBatchCode());
                    copySaleoutB.setNnum(onHandNum.getNonhandnum());
                    saleoutbExtList.add(copySaleoutB);
                    nNum = ComputeUtil.computeSubtract(nNum, onHandNum.getNonhandnum());
                    onHandNum.setNonhandnum(onHandNum.getNonhandnum().negate());
                    deductOnHandNumList.add(onHandNum);
                    saleOutB.setNnum(nNum);
                }
            }
            if(ComputeUtil.compareValue(nNum)){
                throw new RuntimeException(ScmMsgConstants.IC_ON_HAND_NUM_NOT_EMPTY);
            }
            // 一行行更新，防止不同行用同一个批次
            updateOrInsertOnHandNum(deductOnHandNumList);
            for (IcOnHandNum icOnHand : deductOnHandNumList) {
                packageIcOnHandBiList(icSaleOutExt, orderType, pkMember, icOnHandNumbList, saleOutB, icOnHand);
            }
        }
        icSaleOutExt.setSaleoutbExtList(saleoutbExtList);
        if (icOnHandNumbList.size() > 0) {
            // 保存
            icOnHandNumbService.insertIcOnHandNumbByList(icOnHandNumbList);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean mergeIcOnHandNumByStoreOut(SaOrderExt saOrderExt, Integer orderType, Long pkMember) {
        // 根据明细表查询出产品、仓库内所有的批次信息，按照倒叙排列
        // 需要按照先进先出进行扣减，当前批次不够扣减下一个批次
        // 加锁
        List<IcOnHandNumB> icOnHandNumbList = new ArrayList<>();
        for (SaOrderItemsExt saOrderItemsExt : saOrderExt.getOrderItemsExtList()) {
            // 根据仓库 产品id 规格 批次号查询是否已经存在，存在的话对数量进行修改
            // 现存量表
            IcOnHandNum icOnHandNum = IcOnHandNum.builder()
                    .pkProduct(saOrderItemsExt.getPkProduct())
                    .pkStorehouse(saOrderExt.getPkStorehouse())
                    .build();
            icOnHandNum.setPkCountry(saOrderItemsExt.getPkCountry());
            // 查询现存量表，是否存在现存量
            List<IcOnHandNum> oldOnHandNumList = baseMapper.queryIcOnHandNumByCondition(icOnHandNum, saOrderItemsExt.getSpecsNameId());
            // 待扣减库存
            BigDecimal nNum = BigDecimal.valueOf(saOrderItemsExt.getQuantity());
            List<IcOnHandNum> deductOnHandNumList = new ArrayList<>();
            Date date = DateUtils.currentDateTime();
            for (IcOnHandNum onHandNum : oldOnHandNumList) {
                onHandNum.setPkModified(pkMember);
                onHandNum.setModifiedTime(date);
                if(ComputeUtil.compareValue(onHandNum.getNonhandnum(), nNum)){
                    onHandNum.setNonhandnum(nNum.negate());
                    deductOnHandNumList.add(onHandNum);
                    nNum = BigDecimal.ZERO;
                    break;
                }else {
                    nNum = ComputeUtil.computeSubtract(nNum, onHandNum.getNonhandnum());
                    onHandNum.setNonhandnum(onHandNum.getNonhandnum().negate());
                    deductOnHandNumList.add(onHandNum);
                }
            }
            if(ComputeUtil.compareValue(nNum)){
                return Boolean.FALSE;
            }
            // 一行行更新，防止不同行用同一个批次
            updateOrInsertOnHandNum(deductOnHandNumList);
            for (IcOnHandNum icOnHand : deductOnHandNumList) {
                packageIcOnHandBiList(saOrderExt, orderType, pkMember, icOnHandNumbList, saOrderItemsExt, icOnHand);
            }
        }
        if (icOnHandNumbList.size() > 0) {
            // 保存
            icOnHandNumbService.insertIcOnHandNumbByList(icOnHandNumbList);
        }
        return Boolean.TRUE;
    }

    @Override
    public List<IcOnHandNumExt> queryInventoryProductByParam(OnHandNumParam onHandNumParam) {
        List<IcOnHandNumExt> onHandNumExtList = baseMapper.queryInventoryProductByParam(onHandNumParam);
        List<IcWarnConfigExt> configExtList = warnConfigService.queryWarnConfigInventory();
        Map<String, IcWarnConfigExt> warnConfigExtMap = new HashMap<>();
        configExtList.forEach(warnConfig->
                warnConfigExtMap.put(warnConfig.getPkStoreHouse() +"_"+warnConfig.getProductCode()+"_"+ warnConfig.getSpecsName(), warnConfig));
        for (IcOnHandNumExt icOnHandNumExt : onHandNumExtList) {
            if(EYesNo.YES.getIntValue() == icOnHandNumExt.getDisplayRed()){
                icOnHandNumExt.setWarnMsg(ScmMsgConstants.IC_ON_HAND_NUM_VALID_PERIOD);
            }
            String key = icOnHandNumExt.getPkStorehouse() + "_" + icOnHandNumExt.getProductCode() + "_" + icOnHandNumExt.getSpecsName();
            if(warnConfigExtMap.containsKey(key)){
                icOnHandNumExt.setDisplayRed(EYesNo.YES.getIntValue());
                if(StringUtils.isNotEmpty(icOnHandNumExt.getWarnMsg())) {
                    icOnHandNumExt.setWarnMsg(icOnHandNumExt.getWarnMsg() + ScmMsgConstants.IC_ON_HAND_NUM_NOT_EMPTY_WARN);
                }else{
                    icOnHandNumExt.setWarnMsg(ScmMsgConstants.IC_ON_HAND_NUM_NOT_EMPTY_WARN);
                }
            }else{
                icOnHandNumExt.setDisplayRed(EYesNo.NO.getIntValue());
            }
        }
        return onHandNumExtList;
    }

    @Override
    public List<IcOnHandNumExt> queryOnHandNumByList(List<Long> idList) {
        return baseMapper.queryOnHandNumByList(idList);
    }

    private List<IcOnHandSpecs> packageIcOnHandItemList(Object generalHvo, Integer orderType, Long pkMember, List<IcOnHandNumB> icOnHandNumbList, Object generalBvo, List<ScmItemSpecs> scmItemSpecsList, IcOnHandNum icOnHandNum) {
        List<IcOnHandSpecs> icOnHandSpecsList = new ArrayList<>();
        packageIcOnHandBiList(generalHvo, orderType, pkMember, icOnHandNumbList, generalBvo, icOnHandNum);
        // 现存量规格表
        if (CollectionUtil.isNotEmpty(scmItemSpecsList)) {
            for (ScmItemSpecs scmItemSpecs : scmItemSpecsList) {
                IcOnHandSpecs icOnHandSpecs = IcOnHandSpecs.builder()
                        .pkOnhandnum(icOnHandNum.getPkId())
                        .pkSpecsType(scmItemSpecs.getPkSpecsType())
                        .pkSpecs(scmItemSpecs.getPkSpecs())
                        .specsName(scmItemSpecs.getSpecsName())
                        .build();
                icOnHandSpecs.setPkCountry(ReflectUtils.invokeGetter(generalHvo, SystemFieldConstants.PK_COUNTRY_VALUE));
                icOnHandSpecs.setPkCreator(pkMember);
                icOnHandSpecsList.add(icOnHandSpecs);
            }
        }
        return icOnHandSpecsList;
    }

    private void packageIcOnHandBiList(Object generalHvo, Integer orderType, Long pkMember, List<IcOnHandNumB> icOnHandNumbList, Object generalBvo, IcOnHandNum icOnHandNum) {
        // 现存量流水
        IcOnHandNumB icOnHandNumB = IcOnHandNumB.builder()
                .pkOnhandnum(icOnHandNum.getPkId())
                .orderType(orderType)
                .pkGeneralH(ReflectUtils.invokeGetter(generalHvo, SystemFieldConstants.PK_ID_VALUE))
                .pkGeneralB(ReflectUtils.invokeGetter(generalBvo, SystemFieldConstants.PK_ID_VALUE))
                .nnum(icOnHandNum.getNonhandnum())
                .build();
        icOnHandNumB.setPkCountry(ReflectUtils.invokeGetter(generalHvo, SystemFieldConstants.PK_COUNTRY_VALUE));
        icOnHandNumB.setPkCreator(pkMember);
        icOnHandNumbList.add(icOnHandNumB);
    }

    private List<IcOnHandNum> queryIcOnHandNumByCondition(IcOnHandNum icOnHandNum) {
        QueryWrapper<IcOnHandNum> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SystemFieldConstants.PK_COUNTRY, icOnHandNum.getPkCountry());
        queryWrapper.eq(ScmFieldConstants.PK_PRODUCT_FIELD, icOnHandNum.getPkProduct());
        queryWrapper.eq(ScmFieldConstants.PK_STOREHOUSE_FIELD, icOnHandNum.getPkStorehouse());
        if (icOnHandNum.getPkBatchCode() != null) {
            queryWrapper.eq(ScmFieldConstants.PK_BATCH_CODE_FIELD, icOnHandNum.getPkBatchCode());
        }
        return baseMapper.selectList(queryWrapper);
    }

    /*
     * @description: 更新或修改现存量表
     * @author: sui q
     * @date: 2023/11/22 15:29
     * @param: null null
     **/
    private void updateOrInsertOnHandNum(List<IcOnHandNumExt> oldOnHandNumList, IcOnHandNum icOnHandNum) {
        Map<String, IcOnHandNumExt> onHandNumMap = new HashMap<>();
        if (oldOnHandNumList != null && oldOnHandNumList.size() > 0) {
            for (IcOnHandNumExt onHandNum : oldOnHandNumList) {
                onHandNumMap.put(onHandNum.getSpecsName(), onHandNum);
            }
        }
        String handKey = getStringKey(icOnHandNum.getScmItemSpecsList());
        // 存在修改
        if (onHandNumMap.containsKey(handKey)) {
            // 加锁
            IcOnHandNum oldOnHandNum = onHandNumMap.get(handKey);
            icOnHandNum.setPkId(oldOnHandNum.getPkId());
            String key = CacheConstants.IC_ON_HAND_NUM_LOCK + icOnHandNum.getPkId();
            try {
                if (!redisService.lockKeyOnce(key)) {
                    throw new RuntimeException(ScmMsgConstants.BILL_NOT_OPERATION);
                }
                oldOnHandNum.setProductDate(icOnHandNum.getProductDate());
                oldOnHandNum.setExpireDate(icOnHandNum.getExpireDate());
                oldOnHandNum.setPkCubasdoc(icOnHandNum.getPkCubasdoc());
                oldOnHandNum.setNonhandnum(icOnHandNum.getNonhandnum());
                oldOnHandNum.setPkModified(icOnHandNum.getPkCreator());
                oldOnHandNum.setModifiedTime(DateUtils.currentDateTime());
                if (baseMapper.updateOnHandNumByNum(oldOnHandNum) <= 0) {
                    throw new RuntimeException(ScmMsgConstants.IC_ON_HAND_NUM_NOT_EMPTY);
                }
            }finally {
                redisService.unlock(key);
            }
        } else {
            save(icOnHandNum);
        }
    }
    private String getStringKey(List<ScmItemSpecs> scmItemSpecsList) {
        if(scmItemSpecsList == null || scmItemSpecsList.size() == 0){
            return "x123";
        }
        StringBuilder handKey = new StringBuilder();
        for (int i = 0; i < scmItemSpecsList.size(); i++) {
            ScmItemSpecs scmItemSpecs = scmItemSpecsList.get(i);
            handKey.append(scmItemSpecs.getPkSpecs());
            if(i < scmItemSpecsList.size() - 1){
                handKey.append(",");
            }
        }
        return handKey.toString();
    }

    /*
     * @description: 更新或修改现存量表
     * @author: sui q
     * @date: 2023/11/22 15:29
     * @param: null null
     **/
    private void updateOrInsertOnHandNum(List<IcOnHandNum> updOnHandNumList) {
        // 加锁
        List<String> keyList = new ArrayList<>();
        for (IcOnHandNum icOnHandNum : updOnHandNumList) {
            String key = CacheConstants.IC_ON_HAND_NUM_LOCK + icOnHandNum.getPkId();
            keyList.add(key);
        }
        try {
            if (!redisService.lockKeyByList(keyList)) {
                throw new RuntimeException(ScmMsgConstants.BILL_NOT_OPERATION);
            }
            if (baseMapper.mergeUpdateOnHandNumByNum(updOnHandNumList) < updOnHandNumList.size()) {
                throw new RuntimeException(ScmMsgConstants.IC_ON_HAND_NUM_NOT_EMPTY);
            }
        }finally {
            redisService.unlockByList(keyList);
        }
    }
}
