package com.zfire.mall.manager.logic.engin.deposit;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zfire.mall.manager.bean.ExcelData;
import com.zfire.mall.manager.bean.PoySaleCountBean;
import com.zfire.mall.manager.bean.ReceivableOrderBean;
import com.zfire.mall.manager.bean.admin.AdminUserCom;
import com.zfire.mall.manager.bean.engin.deposit.DepositManageBean;
import com.zfire.mall.manager.bean.engin.deposit.DepositManageRecordBean;
import com.zfire.mall.manager.bean.engin.deposit.DepositMangeItemBean;
import com.zfire.mall.manager.bean.engin.deposit.EnginOrderInfo;
import com.zfire.mall.manager.bean.engin.v2.order.HomeEnginOrderVO;
import com.zfire.mall.manager.bean.retail.ProductPriceBean;
import com.zfire.mall.manager.bean.wallet.CustomerWalletAmountBean;
import com.zfire.mall.manager.bean.wallet.CustomerWalletBean;
import com.zfire.mall.manager.commonmapper.engin.deposit.DepositMangeReserveMapper;
import com.zfire.mall.manager.constant.Constant;
import com.zfire.mall.manager.datasource.engin.entity.AgencyBills;
import com.zfire.mall.manager.datasource.engin.logic.AgencyBillsLogic;
import com.zfire.mall.manager.enums.*;
import com.zfire.mall.manager.exception.RemoteServiceException;
import com.zfire.mall.manager.logic.common.CommonLogic;
import com.zfire.mall.manager.logic.engin.deposit.bacth.ExamineHomeLogic;
import com.zfire.mall.manager.logic.engin.order.EnginSysLogic;
import com.zfire.mall.manager.logic.retail.RetailOrderLogic;
import com.zfire.mall.manager.logic.wallet.WalletLogic;
import com.zfire.mall.manager.plus.entity.*;
import com.zfire.mall.manager.plus.service.*;
import com.zfire.mall.manager.utils.CommonUtils;
import com.zfire.mall.manager.utils.CompressDownUtil;
import com.zfire.mall.manager.utils.oss.OSSUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ResourceUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DepositManageLogic {

    @Value("${file.url}")
    private String DOWN_FILE_URL;

    private static final String DOWN_PATH = "classpath:template/temp/";

    private final String FILE_SUFFIX = ".zip";

    @Resource
    DepositMangeReserveMapper depositMangeReserveMapper;
    @Resource
    CommonLogic commonLogic;
    @Resource
    DepositManageService depositManageService;
    @Resource
    DepositManageItemService depositManageItemService;
    @Resource
    DepositManageDataService depositManageDataService;
    @Resource
    DepositManageRecordService depositManageRecordService;
    @Resource
    DepositManageCheckRecordService depositManageCheckRecordService;
    @Resource
    WalletLogic walletLogic;
    @Resource
    RedisLockRegistry redisLockRegistry;
    @Autowired
    OSSUtil ossUtil;
    @Resource
    EnginSysLogic enginSysLogic;
    @Resource
    ExamineHomeLogic examineHomeLogic;
    @Resource
    AgencyBillsLogic agencyBillsLogic;
    @Resource
    RetailOrderLogic retailOrderLogic;
    @Resource
    DepositManageItemCollectService depositManageItemCollectService;
    @Resource
    EnginOrderItemService enginOrderItemService;

    public IPage<DepositManageBean> listPage(Integer settlementStatus,Integer mailFactoryStatus, String customerKeyword,
                                             String enginOrderNo, String enginOrderType, String refEnginRecordNo,
                                             String refProjectName, String refTradeCategory, String refUseUnit,
                                             String startSubmitTime, String endSubmitTime, String startConfirmTime,
                                             String endConfirmTime, String createName, String confirmName, Boolean isRefundDeposit,
                                             List<String> examineStatus, String serviceId, String materialNumber,
                                             String materialOldNumber, String materialName, String specification,
                                             String factoryNo, String specialNo, String geLiInerNote, String refFactoryNo,
                                             String refRegionWork, String startInstallTime, String endInstallTime,
                                             String startAcceptTime, String endAcceptTime, String refBuyUnitName,
                                             String refPromiseProvide, String specialItemNo, String startFactoryNo,
                                             String endFactoryNo, String startSpecialNo, String endSpecialNo,
                                             String startBillNo, String endBillNo, String startMailFactoryDate,
                                             String endMailFactoryDate, String mailFactoryYear,
                                             String startConfirmDate, String endConfirmDate, String startSettlementNo,
                                             String endSettlementNo, String startSettlementDate, String endSettlementDate,
                                             String startInFactoryDate, String endInFactoryDate, String inFactoryType,
                                             String startOrderDate, String endOrderDate, List<String> dataStates,
                                             Integer pageNum, Integer pageSize) {
        AdminUserCom adminUser = commonLogic.getAdminUser(true);
        String customerId = adminUser.getIsCustomer() ? adminUser.getCustomerId() : "";

        Long startFactoryNoL = null;
        Long endFactoryNoL = null;
        Long startSpecialNoL = null;
        Long endSpecialNoL = null;
        String preFactoryNo = "";
        String preSpecialNo = "";
        Long startBillNoL = null;
        Long endBillNoL = null;
        String preBillNo = "";
        //厂编号-开始转换成long类型
        if(!StringUtils.isBlank(startFactoryNo)
        		&& !StringUtils.isBlank(startFactoryNo.substring(startFactoryNo.replaceFirst("\\d+\\D*$", "").length())) ){
        	preFactoryNo = startFactoryNo.substring(0, startFactoryNo.replaceFirst("\\d+\\D*$", "").length());
        	startFactoryNoL = Long.parseLong(startFactoryNo.substring(startFactoryNo.replaceFirst("\\d+\\D*$", "").length()));
        }
        //厂编号-结束转换成long类型
        if(!StringUtils.isBlank(endFactoryNo)
        		&& !StringUtils.isBlank(endFactoryNo.substring(endFactoryNo.replaceFirst("\\d+\\D*$", "").length())) ){
        	endFactoryNoL = Long.parseLong(endFactoryNo.substring(endFactoryNo.replaceFirst("\\d+\\D*$", "").length()));
        }
        //特价编号-开始转换成long类型
        if(!StringUtils.isBlank(startSpecialNo)
        		&& !StringUtils.isBlank(startSpecialNo.substring(startSpecialNo.replaceFirst("\\d+\\D*$", "").length())) ){
//        	preSpecialNo = startSpecialNo.substring(0, startSpecialNo.replaceFirst("\\d+\\D*$", "").length());
//        	startSpecialNoL = Long.parseLong(startSpecialNo.substring(startSpecialNo.replaceFirst("\\d+\\D*$", "").length()));
        	String[] cs = startSpecialNo.split("-");
        	if( cs.length == 3) {
        		preSpecialNo = cs[0]+"-"+cs[1];
        		startSpecialNoL = Long.parseLong(cs[2]);
        	}
        }
        //特价编号-结束转换成long类型
        if(!StringUtils.isBlank(endSpecialNo)
        		&& !StringUtils.isBlank(endSpecialNo.substring(endSpecialNo.replaceFirst("\\d+\\D*$", "").length())) ){
//        	endSpecialNoL = Long.parseLong(endSpecialNo.substring(endSpecialNo.replaceFirst("\\d+\\D*$", "").length()));
        	String[] cs = endSpecialNo.split("-");
        	if( cs.length == 3) {
        		endSpecialNoL = Long.parseLong(cs[2]);
        	}
        }
        String regex="[^0-9]";
    	Pattern p = Pattern. compile(regex);
        //交单编号-开始转换成long类型
        if(!StringUtils.isBlank(startBillNo)) {
        	String str =p.matcher(startBillNo).replaceAll("").trim();
        	if(!StringUtils.isBlank(str) && startBillNo.indexOf(str) > -1) {
        		preBillNo = startBillNo.substring(0, startBillNo.indexOf(str)) ;
        		startBillNoL = Long.parseLong(str);
        	}
        }
        //交单编号-结束转换成long类型
        if(!StringUtils.isBlank(endBillNo)) {
        	String str =p.matcher(endBillNo).replaceAll("").trim();
        	if(!StringUtils.isBlank(str) && endBillNo.indexOf(str) > -1) {
        		endBillNoL = Long.parseLong(str);
        	}
        }
        IPage<DepositManageBean> depositManageBeanIPage = depositMangeReserveMapper.listPage(new Page<>(pageNum, pageSize),
                settlementStatus,mailFactoryStatus, customerKeyword, enginOrderNo, enginOrderType, refEnginRecordNo,
                refProjectName, refTradeCategory, refUseUnit, startSubmitTime, endSubmitTime, startConfirmTime, endConfirmTime,
                createName, confirmName, isRefundDeposit, examineStatus, serviceId, adminUser.getAdminCompanyIds(),
                adminUser.getServiceIds(), customerId, materialNumber, materialOldNumber, materialName, specification,
                factoryNo, specialNo, geLiInerNote, refFactoryNo, refRegionWork, startInstallTime, endInstallTime,
                startAcceptTime, endAcceptTime, refBuyUnitName, refPromiseProvide, specialItemNo, preFactoryNo,
                startFactoryNoL, endFactoryNoL, preSpecialNo, startSpecialNoL, endSpecialNoL, preBillNo, startBillNoL,
                endBillNoL, startMailFactoryDate, endMailFactoryDate, mailFactoryYear, startConfirmDate, endConfirmDate,
                startSettlementNo, endSettlementNo, startSettlementDate, endSettlementDate, startInFactoryDate, endInFactoryDate,
                inFactoryType, startOrderDate, endOrderDate, dataStates);

        if (CollectionUtil.isEmpty(depositManageBeanIPage.getRecords())) {
            return depositManageBeanIPage;
        }

        Set<String> recordNos = depositManageBeanIPage.getRecords().stream()
                .map(DepositManage::getRefEnginRecordNo)
                .collect(Collectors.toSet());

        // 获取订单上的发货数量
        List<EnginOrderItem> orderItems = depositMangeReserveMapper.queryOrderHasSendQty(recordNos);
        Map<String, EnginOrderItem> orderItemMap = orderItems.stream()
                .collect(Collectors.toMap(v -> v.getRefEnginRecordNo() + "|" + v.getMaterialId() + "|" + v.getCustomerWalletId() + "|" + v.getPrice() , Function.identity()));

        for (DepositManageBean record : depositManageBeanIPage.getRecords()) {
            EnginOrderItem orderItem = orderItemMap.get(record.getRefEnginRecordNo() + "|" + record.getMaterialId() + "|" + record.getCustomerWalletId() + "|" + record.getItemPrice());
            if (Objects.nonNull(orderItem)) {
                record.setOrderHasSendQty(orderItem.getQty());
            }
        }

        return depositManageBeanIPage;
    }

    public DepositManageBean detail(String id) {
        AdminUserCom adminUser = commonLogic.getAdminUser(true);
        String customerId = adminUser.getIsCustomer() ? adminUser.getCustomerId() : "";
        DepositManageBean detail = depositMangeReserveMapper.detail(id, adminUser.getAdminCompanyIds(), adminUser.getServiceIds(), customerId);
        if (StringUtils.isNotBlank(customerId)) {
            detail.setOrderGeLiInnerNote(null);
        }
        List<DepositManageItemCollect> collectList = depositManageItemCollectService.lambdaQuery()
                .eq(DepositManageItemCollect::getParentId, detail.getDepositManageId())
                .list();
        List<DepositManageData> dataList = depositManageDataService.lambdaQuery()
                .eq(DepositManageData::getParentId, detail.getDepositManageId())
                .list();
        List<DepositManageCheckRecord> checkRecords = depositManageCheckRecordService.lambdaQuery()
                .eq(DepositManageCheckRecord::getDepositManageId, detail.getDepositManageId())
                .list();
        detail.setCollectList(collectList);
        detail.setDataList(dataList);
        detail.setCheckRecordItems(checkRecords);

        List<AgencyBills> sysAgencyBills = enginSysLogic.queryBills(new ArrayList<String>() {{ this.add(detail.getRefEnginRecordNo()); }});
        if (CollectionUtil.isNotEmpty(sysAgencyBills)) {
            AgencyBills agencyBill = sysAgencyBills.get(0);
            if (Objects.isNull(detail.getInstallDate()) && Objects.nonNull(agencyBill.getInstallDate())) {
                detail.setInstallDate(agencyBill.getInstallDate());
            }
        }

        List<EnginOrderItem> orderItems = depositMangeReserveMapper.queryOrderHasSendQty(new ArrayList<String>() {{ this.add(detail.getRefEnginRecordNo()); }});
        Map<String, EnginOrderItem> orderItemMap = orderItems.stream()
                .collect(Collectors.toMap(v -> v.getRefEnginRecordNo() + "|" + v.getMaterialId() + "|" + v.getCustomerWalletId() + "|" + v.getPrice() , Function.identity()));

        for (DepositMangeItemBean record : detail.getItems()) {
            EnginOrderItem orderItem = orderItemMap.get(record.getRefEnginRecordNo() + "|" + record.getMaterialId() + "|" + record.getCustomerWalletId() + "|" + record.getPrice());
            if (Objects.nonNull(orderItem)) {
                record.setOrderHasSendQty(orderItem.getQty());
            }
        }

//        List<DepositMangeItemBean> itemBeans = detail.getItems().stream()
//                .sorted(Comparator.comparing(DepositMangeItemBean::getSalesQty).reversed())
//                .collect(Collectors.toList());
        // 以销售数量不为0的机型靠上显示，为0的靠下显示
        List<DepositMangeItemBean> itemBeans1 = detail.getItems().stream().filter(v -> v.getSalesQty() > 0).collect(Collectors.toList());
        List<DepositMangeItemBean> itemBeans0 = detail.getItems().stream().filter(v -> v.getSalesQty() == 0).collect(Collectors.toList());
        itemBeans1.addAll(itemBeans0);
        detail.setItems(itemBeans1);

        return detail;
    }

    /**
     * 申请退押
     * @param depositManageBean
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public DepositManage applyRefundDeposit(DepositManageBean depositManageBean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        DepositManage depositManage = depositManageService.lambdaQuery()
                .eq(DepositManage::getDepositManageId, depositManageBean.getDepositManageId())
//                .eq(DepositManage::getExamineStatus, ExamineStatusEnum.SAVE.toString())
                .eq(adminUser.getIsCustomer(), DepositManage::getCustomerId, adminUser.getCustomerId())
                .in(CollectionUtil.isNotEmpty(adminUser.getAdminCompanyIds()), DepositManage::getAdminCompanyId, adminUser.getAdminCompanyIds())
                .one();

        if (Objects.isNull(depositManage) || depositManage.getExamineStatus().equals(ExamineStatusEnum.WAIT.toString())) {
            throw new RemoteServiceException("当前单据状态：\"" + ExamineStatusEnum.getMsg(depositManage.getExamineStatus()) + "\"，处理失败");
        }

        if (Objects.isNull(depositManageBean.getInstallDate())) {
            throw new RemoteServiceException("安装日期不能为空，申请失败");
        }

        if (adminUser.getIsCustomer() && depositManage.getQty() == 0) {
            throw new RemoteServiceException(depositManage.getRefEnginRecordNo() + " 押金管理记录的总数量为0，申请失败");
        }

        depositManage.setExamineStatus(ExamineStatusEnum.WAIT.toString())
//                .setRemark(depositManageBean.getRemark())
                .setInstallDate(depositManageBean.getInstallDate())
                .setApplyNote(depositManageBean.getApplyNote())
                .setUpdateBy(CommonUtils.getUsername())
                .setUpdateName(CommonUtils.getNickName())
                .setSubmitBy(CommonUtils.getUsername())
                .setSubmitName(CommonUtils.getNickName())
                .setSubmitTime(DateUtil.date())
                .setConfirmResult(null);
        depositManage.updateById();
        depositManageService.lambdaUpdate()
                .set(DepositManage::getConfirmResult, null)
                .eq(DepositManage::getDepositManageId, depositManage.getDepositManageId())
                .update();

        List<DepositManageItem> depositManageItems = depositManageItemService.lambdaQuery()
                .eq(DepositManageItem::getParentId, depositManage.getDepositManageId())
                .list();

        List<String> oldNumbers = depositManageItems.stream()
                .map(DepositManageItem::getMaterialOldNumber)
                .collect(Collectors.toList());

        // 获取产品收差价格列表
        IPage<ProductPriceBean> productPricePage = retailOrderLogic.queryProductList(null, depositManage.getSaleTypeId(),
                null, null, null, null, null, depositManage.getCustomerId(),
                oldNumbers, OrderTypeEnum.DIFF.getKey(), 1, -1);

        List<ProductPriceBean> priceBeans = productPricePage.getRecords();
        Map<String, ProductPriceBean> priceBeanMap = priceBeans.stream()
                .collect(Collectors.toMap(v -> v.getSaleId() + "|" + v.getMaterialOldNumber(), Function.identity()));

        Map<String, DepositMangeItemBean> mangeItemBeanMap = depositManageBean.getItems().stream()
                .collect(Collectors.toMap(DepositMangeItemBean::getId, Function.identity()));

        for (DepositManageItem depositManageItem : depositManageItems) {
            DepositMangeItemBean depositMangeItemBean = mangeItemBeanMap.get(depositManageItem.getId());
            if (Objects.nonNull(depositMangeItemBean)) {
                Integer contractQty = Optional.ofNullable(depositMangeItemBean.getContractQty()).orElse(0);
                BigDecimal contractPrice = Optional.ofNullable(depositMangeItemBean.getContractPrice()).orElse(BigDecimal.ZERO);
                depositManageItem.setContractQty(contractQty)
                        .setContractPrice(contractPrice)
                        .setContractAmount(contractPrice.multiply(BigDecimal.valueOf(contractQty)));
                if (depositManageItem.getContractAmount().compareTo(BigDecimal.ZERO) < 0) {
                    throw new RemoteServiceException(depositManageItem.getMaterialOldNumber() + depositManageItem.getMaterialName() + "产品合同金额不能少于0");
                }
            } else {
                depositMangeItemBean = new DepositMangeItemBean();
                depositMangeItemBean.setDataQty(depositManageItem.getDataQty());
            }

            ProductPriceBean priceBean = priceBeanMap.get(depositManage.getSaleTypeId() + "|" + depositManageItem.getMaterialOldNumber());
            if (Objects.isNull(priceBean)) {
//                throw new RemoteServiceException(depositManageItem.getMaterialOldNumber() + depositManageItem.getSpecification() + "：没有找到关联收差政策价格产品");
                priceBean = new ProductPriceBean();
            }
            // 收差单价
            BigDecimal diffPrice = Optional.ofNullable(priceBean.getBatchPrice()).orElse(BigDecimal.ZERO).subtract(depositManageItem.getPrice());
            BigDecimal zero = new BigDecimal("0");

            if (diffPrice.compareTo(zero) < 0) {
                diffPrice = zero;
            }

            int diffQty = depositManageItem.getQty() - depositMangeItemBean.getDataQty();

            if (diffQty < 0) {
                diffQty = 0;
            }

            BigDecimal diffAmount = diffPrice.multiply(BigDecimal.valueOf(diffQty));

            depositManageItem.setDiffPolicyPrice(priceBean.getBatchPrice())
                    .setDiffPrice(diffPrice)
                    .setDiffAmount(diffAmount)
                    .setDataQty(depositMangeItemBean.getDataQty())
                    .setDepositMaterialId(StringUtils.isNotBlank(depositMangeItemBean.getDepositMaterialId()) ? depositMangeItemBean.getDepositMaterialId() : depositManageItem.getDepositMaterialId())
                    .setDepositMaterialName(StringUtils.isNotBlank(depositMangeItemBean.getDepositMaterialName()) ? depositMangeItemBean.getDepositMaterialName() : depositManageItem.getDepositMaterialName())
                    .setDepositMaterialNumber(StringUtils.isNotBlank(depositMangeItemBean.getDepositMaterialNumber()) ? depositMangeItemBean.getDepositMaterialNumber() : depositManageItem.getDepositMaterialNumber())
                    .setDepositMaterialOldNumber(StringUtils.isNotBlank(depositMangeItemBean.getDepositMaterialOldNumber()) ? depositMangeItemBean.getDepositMaterialOldNumber() : depositManageItem.getDepositMaterialOldNumber())
                    .setDepositSpecification(StringUtils.isNotBlank(depositMangeItemBean.getDepositSpecification()) ? depositMangeItemBean.getDepositSpecification() : depositManageItem.getDepositSpecification());
        }

        this.computeOrderSalesQtyData(depositManageItems);

        depositManageItemService.saveOrUpdateBatch(depositManageItems);

        List<DepositManageData> dataList = depositManageBean.getDataList();
        for (DepositManageData depositMangeData : dataList) {
            depositMangeData.setParentId(depositManage.getDepositManageId());
        }
        depositManageDataService.remove(new LambdaUpdateWrapper<DepositManageData>()
                .eq(DepositManageData::getDataPosition, DepositDataPositionEnum.ORIG.getKey())
                .eq(DepositManageData::getParentId, depositManage.getDepositManageId()));

        depositManageDataService.saveBatch(dataList);
        return depositManage;
    }

    /**
     * 计算销售数量和销售金额
     * @param depositManageItems
     */
    public void computeOrderSalesQtyData(List<DepositManageItem> depositManageItems) {
        List<HomeEnginOrderVO> orderItems = depositMangeReserveMapper.queryOrderItem(depositManageItems.get(0).getRefEnginRecordNo());
        Map<String, HomeEnginOrderVO> orderVOMap = orderItems.stream()
                .collect(Collectors.toMap(v -> v.getMaterialId() + "|" + v.getRealMaterialId() + "|" + v.getPrice().setScale(6), Function.identity()));
        for (DepositManageItem item : depositManageItems) {
            HomeEnginOrderVO vo = orderVOMap.get(item.getMaterialId() + "|" + item.getRealMaterialId() + "|" + item.getPrice().setScale(6));
            if (Objects.nonNull(vo))
                item.setSalesQty(vo.getItemSalesQty())
                        .setSalesAmount(vo.getItemSalesAmount());
        }
    }

    public void computeOrderSalesQtyData(String refEnginRecordNo, String materialId, String realMaterialId, BigDecimal price) {
        List<DepositManageItem> depositManageItem = depositManageItemService.lambdaQuery()
                .eq(DepositManageItem::getRefEnginRecordNo, refEnginRecordNo)
                .eq(DepositManageItem::getMaterialId, materialId)
                .eq(DepositManageItem::getRealMaterialId, realMaterialId)
                .eq(DepositManageItem::getPrice, price)
                .list();
        this.computeOrderSalesQtyData(depositManageItem);
        depositManageItemService.saveOrUpdateBatch(depositManageItem);
    }

    @Transactional(rollbackFor = Exception.class)
    public DepositManage examine(DepositManageBean depositManageBean) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        DepositManage depositManage = depositManageService.lambdaQuery()
                .eq(DepositManage::getDepositManageId, depositManageBean.getDepositManageId())
                .eq(DepositManage::getExamineStatus, ExamineStatusEnum.WAIT.getKey())
                .eq(adminUser.getIsCustomer(), DepositManage::getCustomerId, adminUser.getCustomerId())
                .in(CollectionUtil.isNotEmpty(adminUser.getAdminCompanyIds()), DepositManage::getAdminCompanyId, adminUser.getAdminCompanyIds())
                .one();
        if (adminUser.getIsCustomer()) {
            throw new RemoteServiceException("经销商没有权限");
        }
        if (Objects.isNull(depositManage)) {
            throw new RemoteServiceException("单据内容已发生变化，处理失败");
        }

        if (Objects.isNull(depositManageBean.getIsRefundDeposit())) {
            throw new RemoteServiceException("是否退押不能为空");
        }

        List<DepositManageItem> depositManageItems = depositManageItemService.lambdaQuery()
                .eq(DepositManageItem::getParentId, depositManage.getDepositManageId())
                .list();

        List<DepositManageItemCollect> depositManageItemCollects = depositManageItemCollectService.lambdaQuery()
                .eq(DepositManageItemCollect::getParentId, depositManage.getDepositManageId())
                .list();

        List<String> oldNumbers = depositManageItems.stream()
                .map(DepositManageItem::getMaterialOldNumber)
                .collect(Collectors.toList());

        // 获取产品收差价格列表
        IPage<ProductPriceBean> productPricePage = retailOrderLogic.queryProductList(null, depositManage.getSaleTypeId(),
                null, null, null, null, null, depositManage.getCustomerId(),
                oldNumbers, OrderTypeEnum.DIFF.getKey(), 1, -1);

        List<ProductPriceBean> priceBeans = productPricePage.getRecords();
        Map<String, ProductPriceBean> priceBeanMap = priceBeans.stream()
                .collect(Collectors.toMap(v -> v.getSaleId() + "|" + v.getMaterialOldNumber(), Function.identity()));

        // 有源
        List<DepositMangeItemBean> sourceList = depositManageBean.getItems().stream().filter(DepositManageItem::getIsSource).collect(Collectors.toList());
        // 无源
        List<DepositMangeItemBean> notSourceList = depositManageBean.getItems().stream().filter(v -> !v.getIsSource()).collect(Collectors.toList());

        Map<String, DepositMangeItemBean> beanMap = sourceList.stream()
                .collect(Collectors.toMap(v -> v.getMaterialId() + "|" + v.getRealMaterialId() + "|" + v.getPrice().setScale(6), Function.identity()));
        List<ReceivableOrderItem> receivableOrderItemList = new ArrayList<>();

        BigDecimal totalDiffAmount = new BigDecimal("0");
        for (DepositManageItem depositManageItem : depositManageItems) {
            DepositMangeItemBean itemBean = beanMap.get(depositManageItem.getMaterialId() + "|" + depositManageItem.getRealMaterialId() + "|" + depositManageItem.getPrice().setScale(6));
            if (Objects.isNull(itemBean)) {
                continue;
            }

            // 查找产品收差价格Map
            ProductPriceBean priceBean = priceBeanMap.get(depositManage.getSaleTypeId() + "|" + depositManageItem.getMaterialOldNumber());
            if (Objects.isNull(priceBean)) {
//                throw new RemoteServiceException(depositManageItem.getMaterialOldNumber() + depositManageItem.getSpecification() + "：没有找到关联收差政策价格产品");
                priceBean = new ProductPriceBean();
            }
            // 收差单价
            BigDecimal diffPrice = Optional.ofNullable(priceBean.getBatchPrice()).orElse(BigDecimal.ZERO).subtract(depositManageItem.getPrice());
            BigDecimal zero = new BigDecimal("0");

            if (diffPrice.compareTo(zero) < 0) {
                diffPrice = zero;
            }

            int diffQty = depositManageItem.getQty() - itemBean.getDataQty();

            if (diffQty < 0) {
                diffQty = 0;
            }

            BigDecimal diffAmount = diffPrice.multiply(BigDecimal.valueOf(diffQty));

            depositManageItem.setDiffPolicyPrice(priceBean.getBatchPrice())
                    .setDiffPrice(diffPrice)
                    .setDiffAmount(diffAmount)
                    .setDataQty(itemBean.getDataQty())
                    .setContractQty(itemBean.getContractQty())
                    .setContractPrice(itemBean.getContractPrice())
                    .setContractAmount(itemBean.getContractAmount())
                    .setDepositMaterialId(StringUtils.isNotBlank(itemBean.getDepositMaterialId()) ? itemBean.getDepositMaterialId() : depositManageItem.getDepositMaterialId())
                    .setDepositMaterialName(StringUtils.isNotBlank(itemBean.getDepositMaterialName()) ? itemBean.getDepositMaterialName() : depositManageItem.getDepositMaterialName())
                    .setDepositMaterialNumber(StringUtils.isNotBlank(itemBean.getDepositMaterialNumber()) ? itemBean.getDepositMaterialNumber() : depositManageItem.getDepositMaterialNumber())
                    .setDepositMaterialOldNumber(StringUtils.isNotBlank(itemBean.getDepositMaterialOldNumber()) ? itemBean.getDepositMaterialOldNumber() : depositManageItem.getDepositMaterialOldNumber())
                    .setDepositSpecification(StringUtils.isNotBlank(itemBean.getDepositSpecification()) ? itemBean.getDepositSpecification() : depositManageItem.getDepositSpecification());

            // 单据收差总计
            totalDiffAmount = totalDiffAmount.add(depositManageItem.getDiffAmount());

            // 收差金额不能为空并且大于0
            if (Objects.nonNull(depositManageItem.getDiffAmount()) && depositManageItem.getDiffAmount().compareTo(BigDecimal.valueOf(0)) > 0) {
                ReceivableOrderItem receivableOrderItem = new ReceivableOrderItem();
                receivableOrderItem.setCustomerId(depositManage.getCustomerId())
                        .setCustomerNumber(depositManage.getCustomerNumber())
                        .setCustomerName(depositManage.getCustomerName())
                        .setProjectCode("FYXM01_SYS")
                        .setCustomerWalletId(depositManageItem.getCustomerWalletId())
                        .setCustomerWalletName(depositManageItem.getCustomerWalletName())
                        .setWalletId(depositManageItem.getCustomerWalletNumber())
                        .setTotalAmount(depositManageItem.getDiffAmount());

                receivableOrderItemList.add(receivableOrderItem);
            }
        }

        String confirmBy = CommonUtils.getUsername();
        String confirmName = CommonUtils.getNickName();
        DateTime confirmTime = DateUtil.date();
        depositManage.setDepositDiffAmount(totalDiffAmount)
                .setRefFactoryNo(depositManageBean.getRefFactoryNo())
                .setSendFactoryDate(depositManageBean.getSendFactoryDate())
                .setInstallDate(depositManageBean.getInstallDate())
                .setGeLiInerNote(depositManageBean.getGeLiInerNote())
                .setGeLiInnerDataNote(depositManageBean.getGeLiInnerDataNote())
                .setRealUseUnit(depositManageBean.getRealUseUnit())
                .setRealInstallAddress(depositManageBean.getRealInstallAddress())
                .setRefBuyUnitName(depositManageBean.getRefBuyUnitName())
                .setRemark(depositManageBean.getRemark())
                .setUpdateBy(confirmBy)
                .setUpdateName(confirmName)
                .setCheckBy(confirmName)
                .setCheckDate(confirmTime)
                .setCheckNote(depositManageBean.getCheckNote())
                .setIsRefundDeposit(depositManageBean.isExamineResult() ? depositManageBean.getIsRefundDeposit() : false)
                .setConfirmBy(confirmBy)
                .setConfirmName(confirmName)
                .setConfirmTime(confirmTime)
                .setExamineStatus(depositManageBean.isExamineResult() ? ExamineStatusEnum.OK.toString() : ExamineStatusEnum.SAVE.toString())
                .setConfirmResult(depositManageBean.isExamineResult());
        // 更新主表
        depositManage.updateById();

        // 更新明细
        if (CollectionUtil.isNotEmpty(notSourceList) && depositManageBean.isExamineResult()) {
            for (DepositMangeItemBean bean : notSourceList) {
                DepositManageItem item = new DepositManageItem();
                BeanUtils.copyProperties(bean, item);
                depositManageItems.add(item);
            }
        }
        depositManageItemService.saveOrUpdateBatch(depositManageItems);

        // 审核通过并且是退押
        if (depositManageBean.isExamineResult()) {
            // 收差处理
            if (CollectionUtil.isNotEmpty(receivableOrderItemList)) {
                ReceivableOrderBean receivableOrderBean = new ReceivableOrderBean();
                receivableOrderBean.setUserName(depositManage.getCustomerName());
                receivableOrderBean.setItems(receivableOrderItemList);
                receivableOrderBean.setSource("工程价差");
                receivableOrderBean.setBillType("其他应收单");
                walletLogic.syncOtherRece(receivableOrderBean);
            }

            // 退押处理
            if (depositManageBean.getIsRefundDeposit()) {
                List<CustomerWalletAmountBean> walletAmountBeans = new ArrayList<>();
                for (DepositManageItemCollect depositManageItemCollect : depositManageItemCollects) {
                    if (depositManageItemCollect.getDepositAmount().compareTo(BigDecimal.ZERO) > 0) {
                        String billNo = depositManage.getRefEnginRecordNo() + "|" + depositManage.getRefEnginRecordNo();
                        walletAmountBeans.add(new CustomerWalletAmountBean(depositManageItemCollect.getCustomerWalletId(),
                                depositManageItemCollect.getDepositAmount(), "", "家用工程订单退押金" ,
                                depositManage.getCreateTime(), billNo, 4, WalletDirectionEnum.ADD.getKey()));
                        depositManageItemCollect.setRefundDepositAmount(depositManageItemCollect.getDepositAmount())
                                .setDepositAmount(BigDecimal.ZERO);
                    }
                }
                depositManageItemCollectService.saveOrUpdateBatch(depositManageItemCollects);

                walletLogic.doWalletAmount(walletAmountBeans);
            }
        } else {
            depositManageBean.setIsRefundDeposit(false);
        }

        new DepositManageCheckRecord()
                .setDepositManageId(depositManage.getDepositManageId())
                .setApplyNote(depositManage.getApplyNote())
                .setSubmitBy(depositManage.getSubmitBy())
                .setSubmitName(depositManage.getSubmitName())
                .setSubmitTime(depositManage.getSubmitTime())
                .setCheckNote(depositManageBean.getCheckNote())
                .setCheckBy(confirmBy)
                .setCheckName(confirmName)
                .setCheckDate(confirmTime)
                .setIsRefundDeposit(depositManageBean.getIsRefundDeposit())
                .insert();
        return depositManage;
    }


    public void secondRefund(DepositManageBean depositManageBean) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        DepositManage depositManage = depositManageService.lambdaQuery()
                .eq(DepositManage::getDepositManageId, depositManageBean.getDepositManageId())
                .eq(DepositManage::getExamineStatus, ExamineStatusEnum.OK.toString())
                .eq(DepositManage::getTakeDeposit, false)
                .eq(adminUser.getIsCustomer(), DepositManage::getCustomerId, adminUser.getCustomerId())
                .in(CollectionUtil.isNotEmpty(adminUser.getAdminCompanyIds()), DepositManage::getAdminCompanyId, adminUser.getAdminCompanyIds())
                .one();
        if (adminUser.getIsCustomer()) {
            throw new RemoteServiceException("经销商没有权限");
        }
        if (Objects.isNull(depositManage)) {
            throw new RemoteServiceException("当前押金单审批状态不是”审核通过“，不允许二次退押");
        }
        if (depositManage.getIsRefundDeposit()) {
            throw new RemoteServiceException("当前押金单退押金状态为”是“，不允许二次退押");
        }
        List<DepositManageItem> depositManageItems = depositManageItemService.lambdaQuery()
                .eq(DepositManageItem::getParentId, depositManage.getDepositManageId())
                .list();

        List<DepositManageItemCollect> depositManageItemCollects = depositManageItemCollectService.lambdaQuery()
                .eq(DepositManageItemCollect::getParentId, depositManage.getDepositManageId())
                .list();
        // 退押处理
        List<CustomerWalletAmountBean> walletAmountBeans = new ArrayList<>();
        for (DepositManageItemCollect depositManageItemCollect : depositManageItemCollects) {
            if (depositManageItemCollect.getDepositAmount().compareTo(BigDecimal.ZERO) > 0) {
                String billNo = depositManage.getRefEnginRecordNo() + "|" + depositManage.getRefEnginRecordNo();
                walletAmountBeans.add(new CustomerWalletAmountBean(depositManageItemCollect.getCustomerWalletId(),
                        depositManageItemCollect.getDepositAmount(), "", "家用工程订单退押金", depositManage.getCreateTime(),
                        billNo, 4, WalletDirectionEnum.ADD.getKey()));
                depositManageItemCollect.setRefundDepositAmount(depositManageItemCollect.getDepositAmount())
                        .setDepositAmount(BigDecimal.ZERO);

            }
        }
        depositManageItemCollectService.saveOrUpdateBatch(depositManageItemCollects);

        walletLogic.doWalletAmount(walletAmountBeans);

        depositManage.setIsRefundDeposit(true).updateById();

        String confirmBy = CommonUtils.getUsername();
        String confirmName = CommonUtils.getNickName();
        DateTime confirmTime = DateUtil.date();

        new DepositManageCheckRecord()
                .setDepositManageId(depositManage.getDepositManageId())
                .setApplyNote(depositManage.getApplyNote())
                .setSubmitBy(depositManage.getSubmitBy())
                .setSubmitName(depositManage.getSubmitName())
                .setSubmitTime(depositManage.getSubmitTime())
                .setCheckNote("二次退押；" + depositManageBean.getCheckNote())
                .setCheckBy(confirmBy)
                .setCheckName(confirmName)
                .setCheckDate(confirmTime)
                .setIsRefundDeposit(true)
                .insert();
    }


    @Transactional(rollbackFor = Exception.class)
    public void edit(DepositManageBean depositManageBean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        DepositManage depositManage = depositManageService.lambdaQuery()
                .eq(DepositManage::getDepositManageId, depositManageBean.getDepositManageId())
//                .eq(DepositManage::getExamineStatus, ExamineStatusEnum.WAIT.toString())
                .eq(adminUser.getIsCustomer(), DepositManage::getCustomerId, adminUser.getCustomerId())
                .in(CollectionUtil.isNotEmpty(adminUser.getAdminCompanyIds()), DepositManage::getAdminCompanyId, adminUser.getAdminCompanyIds())
                .one();

        if (Objects.nonNull(depositManage)) {
            if (depositManage.getExamineStatus().equals(ExamineStatusEnum.OK.toString()) && !adminUser.getIsCustomer()) {
                depositManage.setRealUseUnit(depositManageBean.getRealUseUnit())
                        .setRealInstallAddress(depositManageBean.getRealInstallAddress())
                        .setRefBuyUnitName(depositManageBean.getRefBuyUnitName())
                        .setGeLiInerNote(depositManageBean.getGeLiInerNote())
                        .setGeLiInnerDataNote(depositManageBean.getGeLiInnerDataNote())
                        .setExamineAfterRemark(depositManageBean.getExamineAfterRemark())
                        .setRemark(depositManageBean.getRemark())
                        .setUpdateBy(CommonUtils.getNickName())
                        .setUpdateName(CommonUtils.getUsername())
                        .setUpdateTime(DateUtil.date());
                depositManage.updateById();
                // 更新明细
                List<DepositManageItem> depositManageItems = depositManageItemService.lambdaQuery()
                        .eq(DepositManageItem::getParentId, depositManage.getDepositManageId())
                        .list();

                Map<String, DepositMangeItemBean> beanMap = depositManageBean.getItems().stream()
                        .filter(v -> StringUtils.isNotBlank(v.getMaterialId()) && StringUtils.isNotBlank(v.getRealMaterialId()) && Objects.nonNull(v.getPrice()))
                        .collect(Collectors.toMap(v -> v.getMaterialId() + v.getPrice().setScale(6) + v.getRealMaterialId(), Function.identity(), (key1, key2) -> key2));

                Map<String, DepositMangeItemBean> emptyBeanMap = depositManageBean.getItems().stream()
                        .filter(v -> StringUtils.isNotBlank(v.getId()) && (StringUtils.isBlank(v.getMaterialId()) || StringUtils.isBlank(v.getRealMaterialId()) || Objects.isNull(v.getPrice())))
                        .collect(Collectors.toMap(DepositManageItem::getId, Function.identity()));

                for (DepositManageItem depositManageItem : depositManageItems) {
                    DepositMangeItemBean itemBean = beanMap.get( depositManageItem.getMaterialId() + depositManageItem.getPrice().setScale(6) + depositManageItem.getRealMaterialId());
                    if (Objects.isNull(itemBean)) {
                        itemBean = emptyBeanMap.get(depositManageItem.getId());
                        if (Objects.isNull(itemBean)) {
                            continue;
                        }
                    }
                    depositManageItem.setDataQty(itemBean.getDataQty())
                            .setDiffAmount(itemBean.getDiffAmount())
                            .setDepositMaterialId(StringUtils.isNotBlank(itemBean.getDepositMaterialId()) ? itemBean.getDepositMaterialId() : depositManageItem.getDepositMaterialId())
                            .setDepositMaterialName(StringUtils.isNotBlank(itemBean.getDepositMaterialName()) ? itemBean.getDepositMaterialName() : depositManageItem.getDepositMaterialName())
                            .setDepositMaterialNumber(StringUtils.isNotBlank(itemBean.getDepositMaterialNumber()) ? itemBean.getDepositMaterialNumber() : depositManageItem.getDepositMaterialNumber())
                            .setDepositMaterialOldNumber(StringUtils.isNotBlank(itemBean.getDepositMaterialOldNumber()) ? itemBean.getDepositMaterialOldNumber() : depositManageItem.getDepositMaterialOldNumber())
                            .setDepositSpecification(StringUtils.isNotBlank(itemBean.getDepositSpecification()) ? itemBean.getDepositSpecification() : depositManageItem.getDepositSpecification());
                }
                depositManageItemService.saveOrUpdateBatch(depositManageItems);
            } else if(depositManage.getExamineStatus().equals(ExamineStatusEnum.WAIT.toString())
                    || depositManage.getExamineStatus().equals(ExamineStatusEnum.SAVE.toString()) ) {
                if (Objects.isNull(depositManageBean.getIsRefundDeposit())) {
                    throw new RemoteServiceException("是否退押不能为空");
                }

                // 更新主表
                depositManageService.update(depositManage, new LambdaUpdateWrapper<DepositManage>()
                        .set(!adminUser.getIsCustomer(), DepositManage::getRefFactoryNo, depositManageBean.getRefFactoryNo())
                        .set(!adminUser.getIsCustomer(), DepositManage::getSendFactoryDate, depositManageBean.getSendFactoryDate())
                        .set(DepositManage::getInstallDate, depositManageBean.getInstallDate())
                        .set(DepositManage::getApplyNote, depositManageBean.getApplyNote())
                        .set(DepositManage::getCheckBy, depositManageBean.getCheckBy())
                        .set(DepositManage::getCheckDate, depositManageBean.getCheckDate())
                        .set(DepositManage::getCheckNote, depositManageBean.getCheckNote())
                        .set(!adminUser.getIsCustomer(), DepositManage::getIsRefundDeposit, depositManageBean.getIsRefundDeposit())
                        .set(!adminUser.getIsCustomer(), DepositManage::getRealUseUnit, depositManageBean.getRealUseUnit())
                        .set(!adminUser.getIsCustomer(), DepositManage::getRealInstallAddress, depositManageBean.getRealInstallAddress())
                        .set(!adminUser.getIsCustomer(), DepositManage::getRefBuyUnitName, depositManageBean.getRefBuyUnitName())
                        .set(!adminUser.getIsCustomer(), DepositManage::getGeLiInerNote, depositManageBean.getGeLiInerNote())
                        .set(!adminUser.getIsCustomer(), DepositManage::getGeLiInnerDataNote, depositManageBean.getGeLiInnerDataNote())
                        .set(!adminUser.getIsCustomer(), DepositManage::getIsRefundDeposit, depositManageBean.getIsRefundDeposit())
                        .set(DepositManage::getRemark, depositManageBean.getRemark())
                        .set(DepositManage::getUpdateBy, CommonUtils.getUsername())
                        .set(DepositManage::getUpdateName, CommonUtils.getNickName())
                        .eq(DepositManage::getDepositManageId, depositManage.getDepositManageId()));
                // 更新明细
                List<DepositManageItem> depositManageItems = depositManageItemService.lambdaQuery()
                        .eq(DepositManageItem::getParentId, depositManage.getDepositManageId())
                        .list();

                Map<String, DepositMangeItemBean> beanMap = depositManageBean.getItems().stream()
                        .filter(v -> StringUtils.isNotBlank(v.getMaterialId()) && StringUtils.isNotBlank(v.getRealMaterialId()) && Objects.nonNull(v.getPrice()))
                        .collect(Collectors.toMap(v -> v.getMaterialId() + v.getPrice().setScale(6) + v.getRealMaterialId(), Function.identity(), (key1, key2) -> key2));

                Map<String, DepositMangeItemBean> emptyBeanMap = depositManageBean.getItems().stream()
                        .filter(v -> StringUtils.isNotBlank(v.getId()) && (StringUtils.isBlank(v.getMaterialId()) || StringUtils.isBlank(v.getRealMaterialId()) || Objects.isNull(v.getPrice())))
                        .collect(Collectors.toMap(DepositManageItem::getId, Function.identity()));

                for (DepositManageItem depositManageItem : depositManageItems) {
                    DepositMangeItemBean itemBean = beanMap.get( depositManageItem.getMaterialId() + depositManageItem.getPrice().setScale(6) + depositManageItem.getRealMaterialId());
                    if (Objects.isNull(itemBean)) {
                        itemBean = emptyBeanMap.get(depositManageItem.getId());
                        if (Objects.isNull(itemBean)) {
                            continue;
                        }
                    }
                    depositManageItem.setDataQty(itemBean.getDataQty())
                            .setDiffAmount(itemBean.getDiffAmount())
                            .setDepositMaterialId(StringUtils.isNotBlank(itemBean.getDepositMaterialId()) ? itemBean.getDepositMaterialId() : depositManageItem.getDepositMaterialId())
                            .setDepositMaterialName(StringUtils.isNotBlank(itemBean.getDepositMaterialName()) ? itemBean.getDepositMaterialName() : depositManageItem.getDepositMaterialName())
                            .setDepositMaterialNumber(StringUtils.isNotBlank(itemBean.getDepositMaterialNumber()) ? itemBean.getDepositMaterialNumber() : depositManageItem.getDepositMaterialNumber())
                            .setDepositMaterialOldNumber(StringUtils.isNotBlank(itemBean.getDepositMaterialOldNumber()) ? itemBean.getDepositMaterialOldNumber() : depositManageItem.getDepositMaterialOldNumber())
                            .setDepositSpecification(StringUtils.isNotBlank(itemBean.getDepositSpecification()) ? itemBean.getDepositSpecification() : depositManageItem.getDepositSpecification());
                }
                depositManageItemService.saveOrUpdateBatch(depositManageItems);
            }
        }
    }

    /**
     * 导入押金管理
     * @param inputStream
     * @param request
     */
    @Transactional(rollbackFor = Exception.class)
    public void importDepositInfo(InputStream inputStream, HttpServletRequest request) {
        //读取excel数据
        ExcelReader reader = ExcelUtil.getReader(inputStream);
        reader.addHeaderAlias("工程登录编号", "refEnginRecordNo");
        reader.addHeaderAlias("厂产品编码", "materialOldNumber");
        reader.addHeaderAlias("特价项目编号", "specialItemNo");
        reader.addHeaderAlias("厂编号", "factoryNo");
        reader.addHeaderAlias("特价编号", "specialNo");
        reader.addHeaderAlias("交单编号", "billNo");
        reader.addHeaderAlias("单价", "price");
        reader.addHeaderAlias("钱包序号", "customerWalletId");
        reader.addHeaderAlias("合同数量", "contractQty");
        reader.addHeaderAlias("合同价格", "contractPrice");
        reader.addHeaderAlias("合同金额", "contractAmount");
        reader.addHeaderAlias("寄厂日期", "mailFactoryDate");
        reader.addHeaderAlias("寄厂年度", "mailFactoryYear");
        reader.addHeaderAlias("确认日期", "confirmDate");
        reader.addHeaderAlias("结算编号", "settlementNo");
        reader.addHeaderAlias("结算日期", "settlementDate");
        reader.addHeaderAlias("入厂日期", "inFactoryDate");
        reader.addHeaderAlias("入厂类型", "inFactoryType");

        List<DepositManageItem> depositManageItems = reader.readAll(DepositManageItem.class);

        if (CollectionUtil.isEmpty(depositManageItems)) {
            throw new RemoteServiceException("导入数据不能空");
        }

        for (int i = 0; i < depositManageItems.size(); i++) {
            DepositManageItem depositManageItem = depositManageItems.get(i);
            if (StringUtils.isBlank(depositManageItem.getRefEnginRecordNo())) {
                throw new RemoteServiceException("第" + (i+1) + "行未发现工程登录编号");
            }
            if (StringUtils.isBlank(depositManageItem.getMaterialOldNumber())) {
                throw new RemoteServiceException("第" + (i+1) + "行未发现厂产品编码");
            }
            String factoryNoNumber;
            if (StringUtils.isNotBlank(depositManageItem.getFactoryNo())) {
                factoryNoNumber = StrUtil.removePrefixIgnoreCase(depositManageItem.getFactoryNo(), "ZJ").trim();
                if (!factoryNoNumber.matches("^[0-9]*$")) {
                    throw new RemoteServiceException("第" + (i+1) + "行厂编号不是以ZJ开头格式错误");
                }
                depositManageItem.setFactoryNoNumber(Long.parseLong(factoryNoNumber));
            }
            String specialNoNumber;
            if (StringUtils.isNotBlank(depositManageItem.getSpecialNo())) {
                String[] SpecialNos = depositManageItem.getSpecialNo().split("-");
                specialNoNumber = SpecialNos[2];
                if (!specialNoNumber.matches("^[0-9]*$")) {
                    throw new RemoteServiceException("第" + (i+1) + "行特价编号不是以??-??-开头格式错误");
            }
            depositManageItem.setSpecialNoNumber(Long.parseLong(specialNoNumber));
        }
        String billNoNumber;
        if (StringUtils.isNotBlank(depositManageItem.getBillNo())) {
            billNoNumber = StrUtil.removePrefixIgnoreCase(depositManageItem.getBillNo(), "G").trim();
            if (!billNoNumber.matches("^[0-9]*$")) {
                throw new RemoteServiceException("第" + (i+1) + "行交单编号不是以G开头格式错误");
            }
                depositManageItem.setBillNoNumber(Long.parseLong(billNoNumber));
            }
        }

        // 归类引用单号
        Set<String> RecordNoSet = depositManageItems.stream()
                .map(DepositManageItem::getRefEnginRecordNo)
                .collect(Collectors.toSet());

        for (String recordNo : RecordNoSet) {
            // 过滤所属引用单号明细
            Map<String, DepositManageItem> itemMap = depositManageItems.stream()
                    .filter(v -> v.getRefEnginRecordNo().equals(recordNo))
                    .collect(Collectors.toMap(v -> v.getMaterialOldNumber() + "|" + v.getPrice().setScale(6) + "|" + v.getCustomerWalletId(), Function.identity(), (key1, key2) -> key2));
            List<DepositManageItem> depositManageItemList = depositManageItemService.lambdaQuery()
                    .eq(DepositManageItem::getRefEnginRecordNo, recordNo)
                    .list();
            for (DepositManageItem depositManageItem : depositManageItemList) {
                DepositManageItem manageItem = itemMap.get(depositManageItem.getMaterialOldNumber() + "|" + depositManageItem.getPrice().setScale(6) + "|" + depositManageItem.getCustomerWalletId());
                if (Objects.isNull(manageItem)) {
                    continue;
                }

                depositManageItem.setSpecialItemNo(StringUtils.isNotBlank(manageItem.getSpecialItemNo()) ? manageItem.getSpecialItemNo() : null)
                        .setSpecialItemNoNumber(Objects.nonNull(manageItem.getSpecialItemNoNumber()) ? manageItem.getSpecialItemNoNumber() : null)
                        .setFactoryNo(StringUtils.isNotBlank(manageItem.getFactoryNo()) ? manageItem.getFactoryNo() : null)
                        .setFactoryNoNumber(Objects.nonNull(manageItem.getFactoryNoNumber()) ? manageItem.getFactoryNoNumber() : null)
                        .setSpecialNo(StringUtils.isNotBlank(manageItem.getSpecialNo()) ? manageItem.getSpecialNo() : null)
                        .setSpecialNoNumber(Objects.nonNull(manageItem.getSpecialNoNumber()) ? manageItem.getSpecialNoNumber() : null)
                        .setBillNo(StringUtils.isNotBlank(manageItem.getBillNo()) ? manageItem.getBillNo() : null)
                        .setBillNoNumber(Objects.nonNull(manageItem.getBillNoNumber()) ? manageItem.getBillNoNumber() : null)
                        .setMailFactoryDate(Objects.nonNull(manageItem.getMailFactoryDate()) ? manageItem.getMailFactoryDate() : null)
                        .setMailFactoryYear(StringUtils.isNotBlank(manageItem.getMailFactoryYear()) ? manageItem.getMailFactoryYear() : null)
                        .setConfirmDate(Objects.nonNull(manageItem.getConfirmDate()) ? manageItem.getConfirmDate() : null)
                        .setSettlementNo(Objects.nonNull(manageItem.getSettlementNo()) ? manageItem.getSettlementNo() : null)
                        .setSettlementDate(Objects.nonNull(manageItem.getSettlementNo()) ? manageItem.getSettlementDate() : null)
                        .setInFactoryDate(Objects.nonNull(manageItem.getInFactoryDate()) ? manageItem.getInFactoryDate() : null)
                        .setInFactoryType(StringUtils.isNotBlank(manageItem.getInFactoryType()) ? manageItem.getInFactoryType() : null);

                if (Objects.nonNull(manageItem.getContractQty())) {
                    depositManageItem.setContractQty(manageItem.getContractQty());
                }

                if (Objects.nonNull(manageItem.getContractPrice())) {
                    depositManageItem.setContractPrice(manageItem.getContractPrice());
                }

                if (Objects.nonNull(manageItem.getContractAmount())) {
                    depositManageItem.setContractAmount(manageItem.getContractAmount());
                }

            }
            // 批量更新
            depositManageItemService.saveOrUpdateBatch(depositManageItemList);
        }
    }

    public List<EnginOrderInfo> queryEnginOrderInfo(String refEnginRecordNo) {
        return depositMangeReserveMapper.queryEnginOrderInfo(refEnginRecordNo);
    }

    public void addDepositAmount(String recordNo, List<DepositManageRecordBean> depositManageRecords) throws InterruptedException {
        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_DEPOSIT_MANAGE + recordNo);
        try {
            if (!obtain.tryLock(10, TimeUnit.SECONDS)) {
                throw new RemoteServiceException("押金冻结中，请稍后再试");
            }
            if(StringUtils.isEmpty(recordNo)){
                return;
            }

            DepositManage depositManage = depositManageService.lambdaQuery()
                    .eq(DepositManage::getRefEnginRecordNo, recordNo)
                    .one();

            if (Objects.isNull(depositManage)) {
                throw new RemoteServiceException(recordNo + "没有工程单号押金管理记录");
            }

            // 查询汇总明细记录
            List<DepositManageItem> manageItems = depositManageItemService.lambdaQuery()
                    .eq(DepositManageItem::getRefEnginRecordNo, recordNo)
                    .eq(DepositManageItem::getIsSource, 1)
                    .list();
            Map<String, DepositManageItem> manageItemMap = manageItems.stream()
                    .collect(Collectors.toMap(v -> v.getMaterialId() + "|" + v.getRealMaterialId() + "|" + v.getPrice().setScale(6), Function.identity()));

            // 查询押金明细记录
            List<DepositManageItemCollect> manageItemCollects = depositManageItemCollectService.lambdaQuery()
                    .eq(DepositManageItemCollect::getRefEnginRecordNo, recordNo)
                    .list();
            Map<String, DepositManageItemCollect> manageItemCollectMap = manageItemCollects.stream()
                    .collect(Collectors.toMap(v -> v.getMaterialId() + "|" + v.getCustomerWalletId() + "|" + v.getPrice().setScale(6), Function.identity()));

            // 查询钱包名称
            List<CustomerWalletBean> customerWalletBeans = walletLogic.queryWalletByCustomerId(depositManage.getCustomerId(), null);
            Map<String, CustomerWalletBean> walletMap = customerWalletBeans.stream()
                    .collect(Collectors.toMap(CustomerWalletBean::getCustomerWalletId, v -> v));

            BigDecimal totalDepositAmount = depositManage.getDepositAmount();
            List<CustomerWalletAmountBean> walletAmountBeans = new ArrayList<>();
            Map<String, Object> enumMap = EnumUtil.getNameFieldMap(OrderTypeEnum.class, "value");

            // 处理工程订单押金
            if (this.determineDepositMangeStatus(depositManage)) {
                this.orderDirectDepositAmount(walletAmountBeans, depositManageRecords, WalletDirectionEnum.ADD.getKey());
            }

            // 遍历传入明细
            for (DepositManageRecordBean depositManageRecord : depositManageRecords) {
                checkRequireColumn(depositManageRecord);
                if (Objects.isNull(depositManageRecord.getCreateTime()))
                    depositManageRecord.setCreateTime(DateUtil.date());
                DepositManageItem depositManageItem = manageItemMap.get(depositManageRecord.getMaterialId() + "|" + depositManageRecord.getRealMaterialId() + "|" + depositManageRecord.getPrice().setScale(6));
                if (Objects.isNull(depositManageItem)) {
                    throw new RemoteServiceException(depositManageRecord.getMaterialId() + " " + depositManageRecord.getRealMaterialId() + " " + depositManageRecord.getMaterialName() + "在汇总明细里未记录");
                }
                DepositManageItemCollect depositManageItemCollect = manageItemCollectMap.get(depositManageRecord.getMaterialId() + "|" + depositManageRecord.getCustomerWalletId() + "|" + depositManageRecord.getPrice().setScale(6));
                if (Objects.isNull(depositManageItemCollect)) {
                    throw new RemoteServiceException(depositManageRecord.getMaterialId() + " " + depositManageRecord.getMaterialName() + " " + depositManageRecord.getPrice().setScale(6) + "在押金明细里未记录");
                }
                // 现金钱包
//                CustomerWalletBean amountCustomerWallet = walletMap.get(depositManageRecord.getCustomerWalletId());

                BigDecimal subDepositAmount = depositManageRecord.getDepositAmount();
//                if (amountCustomerWallet.getAmount().compareTo(subDepositAmount) < 0) {
//                    throw new RemoteServiceException(depositManageRecord.getCustomerWalletName() +
//                            "钱包余额不足, " + depositManageRecord.getMaterialName() + "的押金：" + subDepositAmount + "元扣减失败");
//                }
                String orderNo = depositManageRecord.getOrderNo();

                if (depositManageRecord.getOrderType().equals(OrderTypeEnum.HOME.getKey())) {
                    orderNo = depositManageRecord.getOrderNo() + "|" + depositManageRecord.getRefEnginRecordNo();
                }

                if (this.determineDepositMangeStatus(depositManage)) {
                    // 现金钱包扣减
                    walletAmountBeans.add(new CustomerWalletAmountBean(depositManageRecord.getCustomerWalletId(), subDepositAmount,
                            depositManageRecord.getRemark() + ">发货号：" + depositManageRecord.getConsumNo()
                            , enumMap.get(depositManageRecord.getOrderType()) + "工程订单押金"
                            , depositManageRecord.getCreateTime(), orderNo, 4, WalletDirectionEnum.SUB.getKey()));
                }

                // 加上历史发货数量
                depositManageItem.setHasSendQty(depositManageItem.getHasSendQty() + depositManageRecord.getQty());
                depositManageItemCollect.setHasSendQty(depositManageItemCollect.getHasSendQty() + depositManageRecord.getQty());
                // 加上历史押金金额
                depositManageItem.setDepositAmount(depositManageItem.getDepositAmount().add(subDepositAmount));
                depositManageItemCollect.setDepositAmount(depositManageItemCollect.getDepositAmount().add(subDepositAmount));

                totalDepositAmount = totalDepositAmount.add(subDepositAmount);

                // 注入押金管理单号
                depositManageRecord.setId(null)
                        .setParentId(depositManage.getDepositManageId())
                        .setIsExec(true)
                        .setDirection(-1);
                if (depositManage.getExamineStatus().equals(ExamineStatusEnum.OK.toString())) {
                    depositManageRecord.setIsExec(false);
                }
            }
            if (CollectionUtil.isNotEmpty(walletAmountBeans))
                walletLogic.doWalletAmount(walletAmountBeans);

            //TODO 押金管理已审核通过后依然会扣押金问题
            if (this.determineDepositMangeStatus(depositManage)) {

                // 更新主表押金总额
                depositManage.setDepositAmount(totalDepositAmount)
                        .updateById();

                // 更新明细记录
                depositManageItemService.saveOrUpdateBatch(manageItemMap.values());
                depositManageItemCollectService.saveOrUpdateBatch(manageItemCollectMap.values());
            }
            // 记录押金流水
            depositManageRecordService.saveBatch(depositManageRecords.stream()
                    .map(bean -> (DepositManageRecord)bean)
                    .collect(Collectors.toList()));
        } finally {
            obtain.unlock();
        }
    }

    public void reduceDepositAmount(String recordNo, List<DepositManageRecordBean> depositManageRecords) throws InterruptedException {
        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_DEPOSIT_MANAGE + recordNo);
        try {
            if (!obtain.tryLock(10, TimeUnit.SECONDS)) {
                throw new RemoteServiceException("押金冻结中，请稍后再试");
            }
            if(StringUtils.isEmpty(recordNo)){
                return;
            }

            DepositManage depositManage = depositManageService.lambdaQuery()
                    .eq(DepositManage::getRefEnginRecordNo, recordNo)
                    .one();

            if (Objects.isNull(depositManage)) {
                throw new RemoteServiceException(recordNo + "没有工程单号押金管理记录");
            }

            // 查询汇总明细记录
            List<DepositManageItem> manageItems = depositManageItemService.lambdaQuery()
                    .eq(DepositManageItem::getRefEnginRecordNo, recordNo)
                    .eq(DepositManageItem::getIsSource, 1)
                    .list();

            Map<String, DepositManageItem> manageItemMap = manageItems.stream()
                    .collect(Collectors.toMap(v -> v.getMaterialId() + "|" + v.getRealMaterialId() + "|" + v.getPrice().setScale(6), Function.identity()));

            // 查询押金明细记录
            List<DepositManageItemCollect> manageItemCollects = depositManageItemCollectService.lambdaQuery()
                    .eq(DepositManageItemCollect::getRefEnginRecordNo, recordNo)
                    .list();
            Map<String, DepositManageItemCollect> manageItemCollectMap = manageItemCollects.stream()
                    .collect(Collectors.toMap(v -> v.getMaterialId() + "|" + v.getCustomerWalletId() + "|" + v.getPrice().setScale(6), Function.identity()));

            // 查询钱包名称
            List<CustomerWalletBean> customerWalletBeans = walletLogic.queryWalletByCustomerId(depositManage.getCustomerId(), null);
            Map<String, CustomerWalletBean> walletMap = customerWalletBeans.stream()
                    .collect(Collectors.toMap(CustomerWalletBean::getCustomerWalletId, v -> v));

            BigDecimal totalDepositAmount = depositManage.getDepositAmount();
            Map<String, Object> enumMap = EnumUtil.getNameFieldMap(OrderTypeEnum.class, "value");
            List<CustomerWalletAmountBean> walletAmountBeans = new ArrayList<>();

            // 遍历传入明细
            for (DepositManageRecord depositManageRecord : depositManageRecords) {
                checkRequireColumn(depositManageRecord);
                if (Objects.isNull(depositManageRecord.getCreateTime()))
                    depositManageRecord.setCreateTime(DateUtil.date());
                DepositManageItem depositManageItem = manageItemMap.get(depositManageRecord.getMaterialId() + "|" + depositManageRecord.getRealMaterialId() + "|" + depositManageRecord.getPrice().setScale(6));
                if (Objects.isNull(depositManageItem)) {
                    throw new RemoteServiceException(depositManageRecord.getMaterialName() + "在汇总明细里未记录");
                }
                DepositManageItemCollect depositManageItemCollect = manageItemCollectMap.get(depositManageRecord.getMaterialId() + "|" + depositManageRecord.getCustomerWalletId() + "|" + depositManageRecord.getPrice().setScale(6));
                if (Objects.isNull(depositManageItemCollect)) {
                    throw new RemoteServiceException(depositManageRecord.getMaterialName() + "在押金明细里未记录");
                }

                // 现金钱包
//                CustomerWalletBean amountCustomerWallet = walletMap.get(depositManageRecord.getCustomerWalletId());

                BigDecimal subDepositAmount = depositManageRecord.getDepositAmount();
                String orderNo = depositManageRecord.getOrderNo();

                if (depositManageRecord.getOrderType().equals(OrderTypeEnum.HOME.getKey())) {
                    orderNo = depositManageRecord.getOrderNo() + "|" + depositManageRecord.getRefEnginRecordNo();
                }

                // 现金钱包充值
                if (depositManage.getCreateTime() == null)
                    depositManage.setCreateTime(new Date());
                walletAmountBeans.add(new CustomerWalletAmountBean(depositManageRecord.getCustomerWalletId(), subDepositAmount,
                        depositManageRecord.getRemark() + ">发货号：" + depositManageRecord.getConsumNo()
                        , enumMap.get(depositManageRecord.getOrderType()) + "工程订单押金"
                        , depositManageRecord.getCreateTime(), orderNo,4, WalletDirectionEnum.ADD.getKey()));

                // 扣除历史发货数量
                depositManageItem.setHasSendQty(depositManageItem.getHasSendQty() - depositManageRecord.getQty());
                depositManageItemCollect.setHasSendQty(depositManageItemCollect.getHasSendQty() - depositManageRecord.getQty());
                // 扣除历史押金金额
                depositManageItem.setDepositAmount(depositManageItem.getDepositAmount().subtract(subDepositAmount));
                depositManageItemCollect.setDepositAmount(depositManageItemCollect.getDepositAmount().subtract(subDepositAmount));
                // 扣除资料数量 少于0等0
                depositManageItem.setDataQty(Math.max(depositManageItem.getDataQty() - depositManageRecord.getQty(), 0));
                totalDepositAmount = totalDepositAmount.subtract(subDepositAmount);

                // 注入押金管理单号
                depositManageRecord.setId(null)
                        .setParentId(depositManage.getDepositManageId())
                        .setIsExec(true)
                        .setDirection(1);
                if (depositManage.getExamineStatus().equals(ExamineStatusEnum.OK.toString())) {
                    depositManageRecord.setIsExec(false);
                }
            }

            //TODO 押金管理已审核通过后依然会退押金问题
            if (this.determineDepositMangeStatus(depositManage)) {
                // 处理工程订单押金
                this.orderDirectDepositAmount(walletAmountBeans, depositManageRecords, WalletDirectionEnum.SUB.getKey());

                walletLogic.doWalletAmount(walletAmountBeans);
                // 更新主表押金总额
                depositManage.setDepositAmount(totalDepositAmount)
                        .updateById();

                // 更新明细记录
                depositManageItemService.saveOrUpdateBatch(manageItemMap.values());
                depositManageItemCollectService.saveOrUpdateBatch(manageItemCollectMap.values());
            }
            // 记录押金流水
            depositManageRecordService.saveBatch(depositManageRecords.stream()
                    .map(bean -> (DepositManageRecord)bean)
                    .collect(Collectors.toList()));
        }finally {
            obtain.unlock();
        }
    }

    private void orderDirectDepositAmount(List<CustomerWalletAmountBean> walletAmountBeans, List<DepositManageRecordBean> depositManageRecords, String key) {
        for (DepositManageRecordBean depositManageRecord : depositManageRecords) {
            EnginOrderItem orderItem = depositManageRecord.getOrderItem();

            // 直调未完结才执行订单押金逻辑
            if (Objects.nonNull(orderItem) && !orderItem.getDirectTransferStatus()) {
                if (Objects.isNull(depositManageRecord.getCreateTime()))
                    depositManageRecord.setCreateTime(DateUtil.date());
                BigDecimal subDepositAmount = depositManageRecord.getDepositAmount();
                walletAmountBeans.add(new CustomerWalletAmountBean(orderItem.getCustomerWalletId(), subDepositAmount
                        , ""
                        , "家用工程订单押金退款-直调"
                        , depositManageRecord.getCreateTime(), orderItem.getEnginOrderNo() + "|" + orderItem.getRefEnginRecordNo()
                        , 4, key));

                // 减去订单押金金额
                if (key.equals(WalletDirectionEnum.ADD.getKey())) {
                    orderItem.setDirectDepositAmount(orderItem.getDirectDepositAmount().subtract(subDepositAmount));
                } else {
                    orderItem.setDirectDepositAmount(orderItem.getDirectDepositAmount().add(subDepositAmount));
                }
                if (orderItem.getDirectDepositAmount().compareTo(BigDecimal.ZERO) < 0) {
                    throw new RemoteServiceException(orderItem.getMaterialNumber() + " " + orderItem.getMaterialName() + "：工程押金直调总押金金额异常");
                }
                enginOrderItemService.lambdaUpdate()
                        .set(EnginOrderItem::getDirectDepositAmount, orderItem.getDirectDepositAmount())
                        .eq(EnginOrderItem::getId, orderItem.getId())
                        .update();
            }
        }
    }

    private void checkRequireColumn(DepositManageRecord depositManageRecord) {
        if (StringUtils.isBlank(depositManageRecord.getRefEnginRecordNo())) {
            throw new RemoteServiceException("工程登录单号不能为空");
        }
        if (StringUtils.isBlank(depositManageRecord.getOrderNo())) {
            throw new RemoteServiceException("订单号不能为空");
        }
        if (StringUtils.isBlank(depositManageRecord.getCustomerWalletId())) {
            throw new RemoteServiceException("钱包不能为空");
        }
        if (Objects.isNull(depositManageRecord.getOrderDate())) {
            throw new RemoteServiceException("订单日期不能为空");
        }
        if (StringUtils.isBlank(depositManageRecord.getOrderType())) {
            throw new RemoteServiceException("订单类型不能为空");
        }
        if (StringUtils.isBlank(depositManageRecord.getSaleTypeId())
                || StringUtils.isBlank(depositManageRecord.getSaleTypeCode())
                || StringUtils.isBlank(depositManageRecord.getSaleTypeName())) {
            throw new RemoteServiceException("销售类型信息不能为空");
        }
        if (StringUtils.isBlank(depositManageRecord.getMaterialId())
                || StringUtils.isBlank(depositManageRecord.getMaterialName())
                || StringUtils.isBlank(depositManageRecord.getMaterialNumber())
                || StringUtils.isEmpty(depositManageRecord.getMaterialOldNumber())
                || StringUtils.isEmpty(depositManageRecord.getSpecification())
                || StringUtils.isEmpty(depositManageRecord.getUnit())) {
            throw new RemoteServiceException("金蝶物料信息不能为空");
        }
        if (Objects.isNull(depositManageRecord.getPrice())) {
            throw new RemoteServiceException("单价不能为空");
        }
        if (Objects.isNull(depositManageRecord.getQty())) {
            throw new RemoteServiceException("数量不能为空");
        }
        if (Objects.isNull(depositManageRecord.getDepositRate())) {
            throw new RemoteServiceException("押金比例不能为空");
        }
        if (Objects.isNull(depositManageRecord.getSingleDepositAmount())) {
            throw new RemoteServiceException("单个商品的押金金额不能为空");
        }
        if (Objects.isNull(depositManageRecord.getDepositAmount())) {
            throw new RemoteServiceException("押金金额不能为空");
        }
    }


    public void createZipFile(String parentId,String zipPath) throws Exception {
        List<DepositManageData> dataList =  depositManageDataService.lambdaQuery()
                .eq(DepositManageData::getParentId,parentId) .list();
        List<Map> list = new ArrayList<>();
        for(DepositManageData data: dataList){
            String filePath = CommonUtils.download(DOWN_FILE_URL + data.getFileUrl(),data.getFileName(), ResourceUtils.getFile(DOWN_PATH).getPath() );
            Map map = new HashMap<>();
            map.put("path",filePath);
            list.add(map);
        }
        CommonUtils.zipFile(list, zipPath);
    }

    public void downZipFile(String parentId, String dataPosition,HttpServletResponse response) throws IOException {
        DepositManage dm = depositManageService.getById(parentId);

        List<DepositManageData> dataList = depositManageDataService.lambdaQuery()
                .eq(StringUtils.isNotBlank(dataPosition), DepositManageData::getDataPosition, dataPosition)
                .eq(DepositManageData::getParentId, parentId).list();
        List<Map<String, String>> list = new ArrayList<>();
        for (DepositManageData data : dataList) {
            String filePath = data.getFileUrl();
            Map<String, String> map = new HashMap<>();
            map.put("path", filePath);
            map.put("fileName", data.getFileName());
            list.add(map);
        }
        String downloadName = dm.getRefEnginRecordNo() + dm.getCustomerName() + dm.getRefUseUnit() + FILE_SUFFIX;
        //String downloadName = dm.getRefEnginRecordNo() + dm.getCustomerName() + FILE_SUFFIX;
        CompressDownUtil.setDownloadResponse(response, downloadName);
        CompressDownUtil.compressZipByName(list, response.getOutputStream(),ossUtil,commonLogic);
    }

    public DepositManageBean nextWaitOrder(DepositManageBean depositManageBean) {
//        if (!depositManageBean.isExamineResult()) {
//            return null;
//        }

        AdminUserCom adminUser = commonLogic.getAdminUser(true);

        List<DepositManage> depositManages = depositManageService.lambdaQuery()
                .in(DepositManage::getServiceId, adminUser.getServiceIds())
                .eq(DepositManage::getExamineStatus, ExamineStatusEnum.WAIT.toString())
//                .le(DepositManage::getCreateTime, depositManageBean.getCreateTime())
                .orderByDesc(DepositManage::getDepositManageId)
                .list();
        if (CollectionUtil.isEmpty(depositManages)) {
            return null;
        }

        return this.detail(depositManages.get(0).getDepositManageId());
    }

    public void syncEnginData(DepositManage depositManage) {
        List<AgencyBills> sysAgencyBills = enginSysLogic.queryBills(new ArrayList<String>() {{ this.add(depositManage.getRefEnginRecordNo()); }});
        if (CollectionUtil.isNotEmpty(sysAgencyBills)) {
            AgencyBills agencyBill = sysAgencyBills.get(0);
            depositManage.setRefPromiseProvide(Optional.ofNullable(agencyBill.getPromiseProvide()).orElse(0) == 0 ? "未保证" : "已保证")
                    .setRefPromiseAcceptStatus(agencyBill.getPromiseAcceptStatus())
                    .setRefPromisePriceRemark(agencyBill.getPromisePriceRemark())
                    .setRefFollowAcceptRemark(agencyBill.getFollowAcceptRemark())
                    .setRefFjShenPiRemark(agencyBill.getFjShenPiRemark())
                    .setRefDatumProvide(Optional.ofNullable(agencyBill.getDatumProvide()).orElse(0) == 0 ? "未提供" : "已提供")
                    .setRefDatumProvideDate(Objects.nonNull(agencyBill.getDatumProvideDate()) ? DateUtil.date(agencyBill.getDatumProvideDate().getTime()) : null)
                    .setRefDatumAcceptStatus(agencyBill.getDatumAcceptStatus())
                    .setRefIsBigAmounts(Optional.ofNullable(agencyBill.getIsBigAmount()).orElse(0) == 0 ? "否" : "是")
                    .setRefContractResult(agencyBill.getContractResult())
                    .setRefContractIdea(agencyBill.getContractIdea())
                    .setRefToRetailResult(agencyBill.getToRetailResult())
                    .setRefToRetailIdea(agencyBill.getToRetailIdea())
                    .setRefDataDelayResult(agencyBill.getDataDelayResult())
                    .setRefDataDelayIdea(agencyBill.getDataDelayIdea())
                    .setRefOtherAnnexResult(agencyBill.getOtherAnnexResult())
                    .setRefOtherAnnexIdea(agencyBill.getOtherAnnexIdea())
                    .setRefDatumAcceptDate(agencyBill.getDatumAcceptDate());

            depositManage.updateById();
        }

//        List<DepositManage> depositManageList = depositManageService.lambdaQuery()
//                .eq(DepositManage::getEnginOrderType, OrderTypeEnum.HOME.getKey())
//                .in(DepositManage::getExamineStatus, ExamineStatusEnum.SAVE.toString(), ExamineStatusEnum.WAIT.toString())
//                .isNull(DepositManage::getRefDatumAcceptDate)
//                .list();
//
//        if (CollectionUtil.isEmpty(depositManageList)) {
//            // 没有需要查询的工程登录单号
//            return;
//        }
//
//        Set<String> stringList = depositManageList.stream()
//                .map(DepositManage::getRefEnginRecordNo)
//                .collect(Collectors.toSet());
//        List<AgencyBills> enginSysAgencyBills = enginSysLogic.queryBills(stringList);
//
//        if (CollectionUtil.isEmpty(enginSysAgencyBills)) {
//            // 查询的没有需要更新的审核资料日期
//            return;
//        }
//
//        try {
//            Map<String, DepositManage> manageMap = depositManageList.stream()
//                    .collect(Collectors.toMap(DepositManage::getRefEnginRecordNo, Function.identity()));
//
//            List<DepositManage> updDepositManageList = new ArrayList<>();
//            for (AgencyBills agencyBill : enginSysAgencyBills) {
//                DepositManage depositManage = manageMap.get(agencyBill.getRecordNo());
//                if (Objects.isNull(depositManage)) {
//                    continue;
//                }
//                DepositManage newDepositManage = new DepositManage();
//                newDepositManage.setDepositManageId(depositManage.getDepositManageId())
//                        .setRefPromiseProvide(Optional.ofNullable(agencyBill.getPromiseProvide()).orElse(0) == 0 ? "未保证" : "已保证")
//                        .setRefPromiseAcceptStatus(agencyBill.getPromiseAcceptStatus())
//                        .setRefPromisePriceRemark(agencyBill.getPromisePriceRemark())
//                        .setRefFollowAcceptRemark(agencyBill.getFollowAcceptRemark())
//                        .setRefFjShenPiRemark(agencyBill.getFjShenPiRemark())
//                        .setRefDatumProvide(Optional.ofNullable(agencyBill.getDatumProvide()).orElse(0) == 0 ? "未提供" : "已提供")
//                        .setRefDatumProvideDate(Objects.nonNull(agencyBill.getDatumProvideDate()) ? DateUtil.date(agencyBill.getDatumProvideDate().getTime()) : null)
//                        .setRefDatumAcceptStatus(agencyBill.getDatumAcceptStatus())
//                        .setRefIsBigAmounts(Optional.ofNullable(agencyBill.getIsBigAmount()).orElse(0) == 0 ? "否" : "是")
//                        .setRefContractResult(agencyBill.getContractResult())
//                        .setRefContractIdea(agencyBill.getContractIdea())
//                        .setRefToRetailResult(agencyBill.getToRetailResult())
//                        .setRefToRetailIdea(agencyBill.getToRetailIdea())
//                        .setRefDataDelayResult(agencyBill.getDataDelayResult())
//                        .setRefDataDelayIdea(agencyBill.getDataDelayIdea())
//                        .setRefOtherAnnexResult(agencyBill.getOtherAnnexResult())
//                        .setRefOtherAnnexIdea(agencyBill.getOtherAnnexIdea())
//                        .setRefDatumAcceptDate(agencyBill.getDatumAcceptDate());
//                updDepositManageList.add(newDepositManage);
//            }
//
//            if (CollectionUtil.isNotEmpty(updDepositManageList)) {
//                depositManageService.updateBatchById(updDepositManageList);
//            }
//
//        } catch (Exception e) {
//            throw new RemoteServiceException("转换工程机数据时失败" + e.getMessage());
//        }
    }

    public String bachConditionExamineHome(List<String> ids) throws InterruptedException {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        List<DepositManage> depositManages = depositManageService.lambdaQuery()
                .eq(DepositManage::getEnginOrderType, OrderTypeEnum.HOME.getKey())
                .in(DepositManage::getExamineStatus, ExamineStatusEnum.SAVE.toString(), ExamineStatusEnum.WAIT.toString())
                .in(DepositManage::getDepositManageId, ids.stream().distinct().collect(Collectors.toList()))
//                .isNotNull(DepositManage::getRefDatumAcceptDate)
                .list();
        if (adminUser.getIsCustomer()) {
            throw new RemoteServiceException("经销商没有权限");
        }
        String confirmBy = CommonUtils.getUsername();
        String confirmName = CommonUtils.getNickName();
        DateTime confirmTime = DateUtil.date();

        if (CollectionUtil.isEmpty(depositManages)) {
            throw new RemoteServiceException("未发现可审核押金单据");
        }

        StringBuilder sb = new StringBuilder();
        int count = 0;
        for (DepositManage depositManage : depositManages) {
            if (depositManage.getExamineStatus().equals(ExamineStatusEnum.SAVE.toString())) {
                this.syncEnginData(depositManage);
            }
            Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.DEPOSIT_MANAGE + depositManage.getRefEnginRecordNo());
            try {
                if (!obtain.tryLock(5, TimeUnit.SECONDS)) {
                    String msg = "已审核" + count + "张单据，" + sb.deleteCharAt(sb.length()-1) + "；" +
                            "处理到工程登录编号：\"" + depositManage.getRefEnginRecordNo() + "\"时超时！";
                    if (count == 0) {
                        msg = "处理到工程登录编号：\"" + depositManage.getRefEnginRecordNo() + "\"时超时！";
                    }
                    throw new RemoteServiceException(msg);
                }
                examineHomeLogic.handleSingleDeposit(depositManageItemService, walletLogic, depositManage, confirmBy,
                        confirmName, confirmTime);
                sb.append(depositManage.getRefEnginRecordNo()).append("，");
                // 回传工程机系统数据
                agencyBillsLogic.depositConfirmUpdateAgencyBills(depositManage);
                count++;
            } catch(Exception e) {
                log.error("【工程审批退押处理】失败", e);
                throw e;
            } finally {
                obtain.unlock();
            }
        }

        return "已审核" + count + "张单据，" + sb.deleteCharAt(sb.length()-1) + "。";
    }

    public ExcelData exportHome(List<DepositManageBean> depositManageBeanList) {
        List<List<Object>> rows = new ArrayList<>();

        AdminUserCom adminUser = commonLogic.getAdminUser();
        String[] titles = new String[] {
                "工程登录编码", "经销商名称", "使用单位", "规格型号", "厂产品编码", "订单数量", "单价", "金额", "实装规格型号", "实装厂产品编码", "实装物料编号",
                "合同数量", "合同价格", "合同金额", "安装时间", "联系人", "固定电话", "移动电话", "安装地址", "受理日期", "资料审核日期", "项目类别",
                "购买单位", "保证函", "审批通过后备注", "物料编码", "产品名称", "押金数量", "发货数量", "资料数量", "收差金额",
                "经销商编码", "是否退押", "押金总额", "验收人", "验收说明", "申请日期", "押金金额", "项目类型", "项目说明", "状态", "区域"
        };

        if (!adminUser.getIsCustomer()) {
            titles = new String[] {
                    "工程登录编码", "特价项目编号", "厂编号", "特价编号", "交单编号", "经销商名称", "使用单位", "规格型号", "厂产品编码",
                    "订单数量", "单价", "金额", "实装规格型号", "实装厂产品编码", "实装物料编号", "合同数量", "合同价格", "合同金额", "安装时间", "联系人", "固定电话", "移动电话", "安装地址",
                    "受理日期", "寄厂日期", "寄厂年度", "确认日期", "结算编号", "结算日期", "入厂日期", "入厂类型", "资料审核日期", "格力内部备注", "项目类别",
                    "购买单位", "保证函", "审批通过后备注", "物料编码", "产品名称", "押金数量", "发货数量", "资料数量", "收差金额",
                    "经销商编码", "是否退押", "押金总额", "验收人", "验收说明", "申请日期", "押金金额", "项目类型", "项目说明", "状态", "区域", "钱包序号"
            };
        }

        Map<String, Object> enumMap = EnumUtil.getNameFieldMap(ExamineStatusEnum.class, "msg");
        for (DepositManageBean depositManageBean : depositManageBeanList) {
            List<Object> row = new ArrayList<>();
            row.add(depositManageBean.getRefEnginRecordNo());
            if (!adminUser.getIsCustomer()) {
                row.add(depositManageBean.getSpecialItemNo());
                row.add(depositManageBean.getFactoryNo());
                row.add(depositManageBean.getSpecialNo());
                row.add(depositManageBean.getBillNo());
            }
            row.add(depositManageBean.getCustomerName());
            row.add(depositManageBean.getRefUseUnit());
            row.add(depositManageBean.getSpecification());
            row.add(depositManageBean.getMaterialOldNumber());
            row.add(depositManageBean.getItemQty());
            row.add(depositManageBean.getItemPrice());
            row.add(depositManageBean.getItemPrice().multiply(BigDecimal.valueOf(depositManageBean.getItemQty())));
            row.add(depositManageBean.getRealSpecification());
            row.add(depositManageBean.getRealMaterialOldNumber());
            row.add(depositManageBean.getRealMaterialNumber());
            row.add(depositManageBean.getItemContractQty());
            row.add(depositManageBean.getItemContractPrice());
            row.add(depositManageBean.getItemContractAmount());
            row.add(DateUtil.formatDate(depositManageBean.getInstallDate()));
            row.add(depositManageBean.getRefLinkman());
            row.add(depositManageBean.getRefTel());
            row.add(depositManageBean.getRefPhone());
            row.add(depositManageBean.getRefInstallAddress());
            row.add(DateUtil.formatDateTime(depositManageBean.getCheckDate()));
            if (!adminUser.getIsCustomer()) {
                row.add(depositManageBean.getMailFactoryDate());
                row.add(depositManageBean.getMailFactoryYear());
                row.add(depositManageBean.getConfirmDate());
                row.add(depositManageBean.getSettlementNo());
                row.add(depositManageBean.getSettlementDate());
                row.add(depositManageBean.getInFactoryDate());
                row.add(depositManageBean.getInFactoryType());
            }
            row.add(DateUtil.formatDateTime(depositManageBean.getRefDatumAcceptDate()));
            if (!adminUser.getIsCustomer()) {
                row.add(depositManageBean.getGeLiInerNote());
            }
            row.add(depositManageBean.getRefProjectCategory());
            row.add(depositManageBean.getRefBuyUnitName());
            row.add(depositManageBean.getRefPromiseProvide());
            row.add(depositManageBean.getExamineAfterRemark());
            row.add(depositManageBean.getMaterialNumber());
            row.add(depositManageBean.getMaterialName());
            row.add(depositManageBean.getHasSendQty());
            row.add(depositManageBean.getOrderHasSendQty());
            row.add(depositManageBean.getItemDataQty());
            row.add(depositManageBean.getItemDiffAmount());
            row.add(depositManageBean.getCustomerNumber());
            row.add(depositManageBean.getIsRefundDeposit() ? "是" : "否");
            row.add(depositManageBean.getDepositAmount());
            row.add(depositManageBean.getCheckBy());
            row.add(depositManageBean.getCheckNote());
            row.add(DateUtil.formatDateTime(depositManageBean.getSubmitTime()));
            row.add(depositManageBean.getItemDepositAmount());
            row.add(depositManageBean.getRefProjectType());
            row.add(depositManageBean.getRefProjectNote());
            row.add(enumMap.get(depositManageBean.getExamineStatus()));
            row.add(depositManageBean.getRefRegionWork());
            row.add(depositManageBean.getCustomerWalletId());

            rows.add(row);
        }
        ExcelData excelData = new ExcelData();
        excelData.setTitles(Arrays.asList(titles));
        excelData.setRows(rows);
        return excelData;
    }

    public ExcelData exportTrade(List<DepositManageBean> depositManageBeanList) {
        List<List<Object>> rows = new ArrayList<>();

        AdminUserCom adminUser = commonLogic.getAdminUser();
        String[] titles = new String[] {
                "厂编号", "特价编号", "工程信息编码", "经销商名称", "项目名称", "行业类别", "使用单位", "规格型号", "厂产品编码", "数量", "单价",
                "金额", "安装时间", "联系人", "固定电话", "移动电话", "安装地址", "物料编码", "产品名称", "发货数量", "收差金额",
                "经销商编码", "是否退押", "押金总额", "验收人", "验收说明", "申请日期", "验收日期", "押金金额", "审批通过后备注", "项目类型",
                "项目说明", "状态"
        };

        if (!adminUser.getIsCustomer()) {
            titles = new String[] {
                    "厂编号", "特价编号", "工程信息编码", "经销商名称", "项目名称", "行业类别", "使用单位", "规格型号", "厂产品编码", "数量", "单价",
                    "金额", "安装时间", "联系人", "固定电话", "移动电话", "安装地址", "物料编码", "产品名称", "发货数量", "收差金额",
                    "经销商编码", "是否退押", "押金总额", "验收人", "验收说明", "申请日期", "验收日期", "押金金额", "审批通过后备注", "项目类型",
                    "项目说明", "状态", "格力内部备注"
            };
        }


        Map<String, Object> enumMap = EnumUtil.getNameFieldMap(ExamineStatusEnum.class, "msg");
        for (DepositManageBean depositManageBean : depositManageBeanList) {
            List<Object> row = new ArrayList<>();
            row.add("");
            row.add("");
            row.add(depositManageBean.getRefEnginRecordNo());
            row.add(depositManageBean.getCustomerName());
            row.add(depositManageBean.getRefProjectName());
            row.add(depositManageBean.getRefTradeCategory());
            row.add(depositManageBean.getRefUseUnit());
            row.add(depositManageBean.getSpecification());
            row.add(depositManageBean.getMaterialOldNumber());
            row.add(depositManageBean.getQty());
            row.add(depositManageBean.getItemPrice());
            row.add(depositManageBean.getItemPrice().multiply(BigDecimal.valueOf(depositManageBean.getItemQty())));
            row.add(DateUtil.formatDate(depositManageBean.getInstallDate()));
            row.add(depositManageBean.getRefLinkman());
            row.add(depositManageBean.getRefTel());
            row.add(depositManageBean.getRefPhone());
            row.add(depositManageBean.getRefInstallAddress());
            row.add(depositManageBean.getMaterialNumber());
            row.add(depositManageBean.getMaterialName());
            row.add(depositManageBean.getHasSendQty());
//            row.add(depositManageBean.getItemDataQty());
            row.add(depositManageBean.getItemDiffAmount());
            row.add(depositManageBean.getCustomerNumber());
            row.add(depositManageBean.getIsRefundDeposit() ? "是" : "否");
            row.add(depositManageBean.getDepositAmount());
            row.add(depositManageBean.getCheckBy());
            row.add(depositManageBean.getCheckNote());
            row.add(DateUtil.formatDateTime(depositManageBean.getSubmitTime()));
            row.add(DateUtil.formatDateTime(depositManageBean.getCheckDate()));
            row.add(depositManageBean.getDepositAmount());
            row.add(depositManageBean.getExamineAfterRemark());
            row.add(depositManageBean.getRefProjectType());
            row.add(depositManageBean.getRefProjectNote());
            row.add(enumMap.get(depositManageBean.getExamineStatus()));
            if (!adminUser.getIsCustomer()) {
                row.add(depositManageBean.getGeLiInerNote());
            }

            rows.add(row);

        }
        ExcelData excelData = new ExcelData();
        excelData.setTitles(Arrays.asList(titles));
        excelData.setRows(rows);
        return excelData;
    }

    public void depositConfirmUpdateAgencyBills(DepositManage depositManage, DepositManageBean depositManageBean) {
        if (depositManageBean.isExamineResult() &&
                depositManage.getExamineStatus().equals(ExamineStatusEnum.OK.toString())) {
            agencyBillsLogic.depositConfirmUpdateAgencyBills(depositManage);
        }
    }

    public DepositMangeItemBean onlineComputeDiff(DepositMangeItemBean depositManageItem) {
        if (Objects.isNull(depositManageItem.getDataQty())) {
            return depositManageItem;
        }
        if (StringUtils.isBlank(depositManageItem.getSaleTypeId())) {
            throw new RemoteServiceException("销售类型错误，无法计算");
        }

        List<String> oldNumbers = new ArrayList<String>(){{ this.add(depositManageItem.getMaterialOldNumber()); }};

        // 获取产品收差价格列表
        IPage<ProductPriceBean> productPricePage = retailOrderLogic.queryProductList(null, depositManageItem.getSaleTypeId(),
                null, null, null, null, null, null,
                oldNumbers, OrderTypeEnum.DIFF.getKey(), 1, -1);

        List<ProductPriceBean> priceBeans = productPricePage.getRecords();

        Map<String, ProductPriceBean> priceBeanMap = priceBeans.stream()
                .collect(Collectors.toMap(v -> v.getSaleId() + "|" + v.getMaterialOldNumber(), Function.identity()));

        ProductPriceBean priceBean = priceBeanMap.get(depositManageItem.getSaleTypeId() + "|" + depositManageItem.getMaterialOldNumber());
        if (Objects.isNull(priceBean)) {
            depositManageItem.setDiffPolicyPrice(BigDecimal.ZERO)
                    .setDiffPrice(BigDecimal.ZERO)
                    .setDiffAmount(BigDecimal.ZERO);
        }
        // 收差单价
        BigDecimal diffPrice;
        try {
            diffPrice = priceBean.getBatchPrice().subtract(depositManageItem.getPrice());

            if (diffPrice.compareTo(BigDecimal.ZERO) < 0) {
                diffPrice = BigDecimal.ZERO;
            }

            int diffQty = depositManageItem.getQty() - depositManageItem.getDataQty();

            if (diffQty < 0) {
                diffQty = 0;
            }

            BigDecimal diffAmount = diffPrice.multiply(BigDecimal.valueOf(diffQty));

            depositManageItem.setDiffPolicyPrice(priceBean.getBatchPrice())
                    .setDiffPrice(diffPrice)
                    .setDiffAmount(diffAmount);
        } catch (Exception e) {
            log.error("在线计算收差价格异常", e);
            depositManageItem.setDiffPolicyPrice(BigDecimal.ZERO)
                    .setDiffPrice(BigDecimal.ZERO)
                    .setDiffAmount(BigDecimal.ZERO);
            return depositManageItem;
        }
        return depositManageItem;
    }

    public PoySaleCountBean countList(String customerKeyword, String enginOrderNo, String enginOrderType,
                                      String refEnginRecordNo, String refProjectName, String refTradeCategory,
                                      String refUseUnit, String startSubmitTime, String endSubmitTime,
                                      String startConfirmTime, String endConfirmTime, String createName,
                                      String confirmName, Boolean isRefundDeposit, List<String> examineStatus,
                                      String serviceId, String materialNumber, String materialOldNumber,
                                      String materialName, String specification, String factoryNo, String specialNo,
                                      String geLiInerNote, String refFactoryNo, String refRegionWork, String startInstallTime,
                                      String endInstallTime, String startAcceptTime, String endAcceptTime, String refBuyUnitName,
                                      String refPromiseProvide, String specialItemNo, String startFactoryNo, String endFactoryNo,
                                      String startSpecialNo, String endSpecialNo, String startBillNo, String endBillNo,
                                      String startMailFactoryDate, String endMailFactoryDate, String mailFactoryYear,
                                      String startConfirmDate, String endConfirmDate, String startSettlementNo,
                                      String endSettlementNo, String startSettlementDate, String endSettlementDate,
                                      String startInFactoryDate, String endInFactoryDate, String inFactoryType,
                                      Integer settlementStatus, Integer mailFactoryStatus, String startOrderDate,
                                      String endOrderDate, List<String> dataStates) {
        AdminUserCom adminUser = commonLogic.getAdminUser(true);
        String customerId = adminUser.getIsCustomer() ? adminUser.getCustomerId() : "";

        Long startFactoryNoL = null;
        Long endFactoryNoL = null;
        Long startSpecialNoL = null;
        Long endSpecialNoL = null;
        String preFactoryNo = "";
        String preSpecialNo = "";
        Long startBillNoL = null;
        Long endBillNoL = null;
        String preBillNo = "";
        //厂编号-开始转换成long类型
        if(!StringUtils.isBlank(startFactoryNo)
                && !StringUtils.isBlank(startFactoryNo.substring(startFactoryNo.replaceFirst("\\d+\\D*$", "").length())) ){
            preFactoryNo = startFactoryNo.substring(0, startFactoryNo.replaceFirst("\\d+\\D*$", "").length());
            startFactoryNoL = Long.parseLong(startFactoryNo.substring(startFactoryNo.replaceFirst("\\d+\\D*$", "").length()));
        }
        //厂编号-结束转换成long类型
        if(!StringUtils.isBlank(endFactoryNo)
                && !StringUtils.isBlank(endFactoryNo.substring(endFactoryNo.replaceFirst("\\d+\\D*$", "").length())) ){
            endFactoryNoL = Long.parseLong(endFactoryNo.substring(endFactoryNo.replaceFirst("\\d+\\D*$", "").length()));
        }
        //特价编号-开始转换成long类型
        if(!StringUtils.isBlank(startSpecialNo)
                && !StringUtils.isBlank(startSpecialNo.substring(startSpecialNo.replaceFirst("\\d+\\D*$", "").length())) ){
//        	preSpecialNo = startSpecialNo.substring(0, startSpecialNo.replaceFirst("\\d+\\D*$", "").length());
//        	startSpecialNoL = Long.parseLong(startSpecialNo.substring(startSpecialNo.replaceFirst("\\d+\\D*$", "").length()));
            String[] cs = startSpecialNo.split("-");
            if( cs.length == 3) {
                preSpecialNo = cs[0]+"-"+cs[1];
                startSpecialNoL = Long.parseLong(cs[2]);
            }
        }
        //特价编号-结束转换成long类型
        if(!StringUtils.isBlank(endSpecialNo)
                && !StringUtils.isBlank(endSpecialNo.substring(endSpecialNo.replaceFirst("\\d+\\D*$", "").length())) ){
//        	endSpecialNoL = Long.parseLong(endSpecialNo.substring(endSpecialNo.replaceFirst("\\d+\\D*$", "").length()));
            String[] cs = endSpecialNo.split("-");
            if( cs.length == 3) {
                endSpecialNoL = Long.parseLong(cs[2]);
            }
        }
        String regex="[^0-9]";
        Pattern p = Pattern. compile(regex);
        //交单编号-开始转换成long类型
        if(!StringUtils.isBlank(startBillNo)) {
            String str =p.matcher(startBillNo).replaceAll("").trim();
            if(!StringUtils.isBlank(str) && startBillNo.indexOf(str) > -1) {
                preBillNo = startBillNo.substring(0, startBillNo.indexOf(str)) ;
                startBillNoL = Long.parseLong(str);
            }
        }
        //交单编号-结束转换成long类型
        if(!StringUtils.isBlank(endBillNo)) {
            String str =p.matcher(endBillNo).replaceAll("").trim();
            if(!StringUtils.isBlank(str) && endBillNo.indexOf(str) > -1) {
                endBillNoL = Long.parseLong(str);
            }
        }
        return depositMangeReserveMapper.countList(
                customerKeyword, enginOrderNo, enginOrderType, refEnginRecordNo, refProjectName, refTradeCategory, refUseUnit,
                startSubmitTime, endSubmitTime, startConfirmTime, endConfirmTime, createName, confirmName, isRefundDeposit,
                examineStatus, serviceId, adminUser.getAdminCompanyIds(), adminUser.getServiceIds(), customerId,
                materialNumber, materialOldNumber, materialName, specification, factoryNo, specialNo, geLiInerNote,
                refFactoryNo, refRegionWork, startInstallTime, endInstallTime, startAcceptTime, endAcceptTime,
                refBuyUnitName, refPromiseProvide, specialItemNo, preFactoryNo, startFactoryNoL, endFactoryNoL, preSpecialNo,
                startSpecialNoL, endSpecialNoL, preBillNo, startBillNoL, endBillNoL, startMailFactoryDate, endMailFactoryDate,
                mailFactoryYear, startConfirmDate, endConfirmDate, startSettlementNo,
                endSettlementNo, startSettlementDate, endSettlementDate, startInFactoryDate, endInFactoryDate, inFactoryType,
                settlementStatus, mailFactoryStatus, startOrderDate, endOrderDate, dataStates);
    }

    /**
     * 补充资料
     * @param depositManageBean
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public DepositManage amendData(DepositManageBean depositManageBean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        DepositManage depositManage = depositManageService.lambdaQuery()
                .eq(DepositManage::getDepositManageId, depositManageBean.getDepositManageId())
                .in(DepositManage::getExamineStatus, ExamineStatusEnum.OK.getKey())
                .in(DepositManage::getDataState, DepositDataStateEnum.NORMAL.getKey(), DepositDataStateEnum.AMEND.getKey())
                .eq(adminUser.getIsCustomer(), DepositManage::getCustomerId, adminUser.getCustomerId())
                .in(CollectionUtil.isNotEmpty(adminUser.getAdminCompanyIds()), DepositManage::getAdminCompanyId, adminUser.getAdminCompanyIds())
                .one();

        if (Objects.isNull(depositManage)) {
            throw new RemoteServiceException("单据处理失败");
        }

        depositManageService.lambdaUpdate()
                .set(DepositManage::getAmendRemark, depositManageBean.getAmendRemark())
                .set(DepositManage::getDataState, DepositDataStateEnum.WAIT_REVIEW.getKey())
                .set(DepositManage::getAmendBy, CommonUtils.getUsername())
                .set(DepositManage::getAmendName, CommonUtils.getNickName())
                .set(DepositManage::getAmendTime, DateUtil.date())
                .eq(DepositManage::getDepositManageId, depositManage.getDepositManageId())
                .update();

        List<DepositManageData> dataList = depositManageBean.getDataList();
        for (DepositManageData depositMangeData : dataList) {
            depositMangeData.setParentId(depositManage.getDepositManageId());
        }

        depositManageDataService.remove(new LambdaUpdateWrapper<DepositManageData>()
                .eq(DepositManageData::getDataPosition, DepositDataPositionEnum.AMEND.getKey())
                .eq(DepositManageData::getParentId, depositManage.getDepositManageId()));

        depositManageDataService.saveBatch(dataList);
        return depositManage;
    }

    /**
     * 复核资料
     * @param depositManageBean
     * @return
     */
    public void reviewData(DepositManageBean depositManageBean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        DepositManage depositManage = depositManageService.lambdaQuery()
                .eq(DepositManage::getDepositManageId, depositManageBean.getDepositManageId())
                .in(DepositManage::getExamineStatus, ExamineStatusEnum.OK.getKey())
                .eq(DepositManage::getDataState, DepositDataStateEnum.WAIT_REVIEW.getKey())
                .eq(adminUser.getIsCustomer(), DepositManage::getCustomerId, adminUser.getCustomerId())
                .in(CollectionUtil.isNotEmpty(adminUser.getAdminCompanyIds()), DepositManage::getAdminCompanyId, adminUser.getAdminCompanyIds())
                .one();

        if (adminUser.getIsCustomer()) {
            throw new RemoteServiceException("经销商没有权限");
        }
        if (Objects.isNull(depositManage)) {
            throw new RemoteServiceException("当前单据状态不是“补充资料”，处理失败");
        }

        DateTime curDate = DateUtil.date();
        LambdaUpdateChainWrapper<DepositManage> wrapper;
        // 复核通过
        if (depositManageBean.isExamineResult()) {
            wrapper = depositManageService.lambdaUpdate().set(DepositManage::getDataState, DepositDataStateEnum.REVIEW.getKey());
        } else {
            wrapper = depositManageService.lambdaUpdate().set(DepositManage::getDataState, DepositDataStateEnum.AMEND.getKey());
        }
        wrapper.set(DepositManage::getReviewRemark, depositManageBean.getReviewRemark())
                .set(DepositManage::getReviewBy, CommonUtils.getUsername())
                .set(DepositManage::getReviewName, CommonUtils.getNickName())
                .set(DepositManage::getReviewTime, curDate)
                .eq(DepositManage::getDepositManageId, depositManage.getDepositManageId())
                .update();

        new DepositManageCheckRecord()
                .setDepositManageId(depositManage.getDepositManageId())
                .setApplyNote(depositManage.getAmendRemark())
                .setSubmitBy(depositManage.getAmendBy())
                .setSubmitName(depositManage.getAmendName())
                .setSubmitTime(depositManage.getAmendTime())
                .setCheckNote(depositManageBean.getReviewRemark())
                .setCheckBy(CommonUtils.getUsername())
                .setCheckName(CommonUtils.getNickName())
                .setCheckDate(curDate)
                .setIsRefundDeposit(depositManageBean.getIsRefundDeposit())
                .insert();
    }


    private boolean determineDepositMangeStatus(DepositManage depositManage) {
        return (depositManage.getExamineStatus().equals(ExamineStatusEnum.SAVE.toString())
                || depositManage.getExamineStatus().equals(ExamineStatusEnum.WAIT.toString()));
    }

    public void updateEnginInfo() {
//        Integer totalCount = depositManageService.lambdaQuery()
//                .eq(DepositManage::getEnginOrderType, OrderTypeEnum.HOME.getKey())
//                .count();
//
//        int pages = totalCount % 500 == 0 ? totalCount / 500 : totalCount / 500 + 1;
//
//        List<DepositManage> depositManagesNew = new ArrayList<>();
//
//        for (int i = 0; i < pages; i++) {
//            List<DepositManage> depositManages = depositManageService.lambdaQuery()
//                    .eq(DepositManage::getEnginOrderType, OrderTypeEnum.HOME.getKey())
//                    .page(new Page<>(i+1, 500,false))
//                    .getRecords();
//            List<AgencyBills> sysAgencyBills = enginSysLogic.queryBills(depositManages.stream()
//                    .map(DepositManage::getRefEnginRecordNo).collect(Collectors.toList()));
//
//            Map<String, DepositManage> manageMap = depositManages.stream()
//                    .collect(Collectors.toMap(DepositManage::getRefEnginRecordNo, Function.identity()));
//
//            if (CollectionUtil.isNotEmpty(sysAgencyBills)) {
//                for (AgencyBills bill : sysAgencyBills) {
//                    DepositManage depositManage = manageMap.get(bill.getRecordNo());
//                    if (Objects.isNull(depositManage)) {
//                        continue;
//                    }
//                    depositManagesNew.add(new DepositManage()
//                            .setDepositManageId(depositManage.getDepositManageId())
//                            .setRefContractIdea(bill.getContractIdea())
//                            .setRefToRetailIdea(bill.getToRetailIdea())
//                            .setRefDataDelayIdea(bill.getDataDelayIdea())
//                            .setRefOtherAnnexIdea(bill.getOtherAnnexIdea()));
//                }
//
//            }
//        }
//        if (CollectionUtil.isNotEmpty(depositManagesNew))
//            depositManageService.saveOrUpdateBatch(depositManagesNew);

        depositMangeReserveMapper.batchSpanUpdateInfo();
    }
}
